diff options
Diffstat (limited to 'docs/examples')
266 files changed, 3878 insertions, 1764 deletions
diff --git a/docs/examples/Cython Magics.ipynb b/docs/examples/Cython Magics.ipynb index 0a8c8f56f..9bbf934c8 100644 --- a/docs/examples/Cython Magics.ipynb +++ b/docs/examples/Cython Magics.ipynb @@ -356,7 +356,7 @@ "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](http://docs.cython.org/src/tutorial/clibraries.html) for more details on the use of these flags."
+ "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."
]
}
],
diff --git a/docs/examples/README.rst b/docs/examples/README.rst index 02c21a5fe..f998f4f33 100644 --- a/docs/examples/README.rst +++ b/docs/examples/README.rst @@ -1,3 +1,5 @@ -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`.
+: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`. diff --git a/docs/examples/not_in_docs/great_circle/p1.py b/docs/examples/not_in_docs/great_circle/p1.py index c0694a235..e60b9723f 100644 --- a/docs/examples/not_in_docs/great_circle/p1.py +++ b/docs/examples/not_in_docs/great_circle/p1.py @@ -1,7 +1,7 @@ import math def great_circle(lon1, lat1, lon2, lat2): - radius = 3956 # miles + radius = 3956 # miles x = math.pi/180.0 a = (90.0 - lat1)*x diff --git a/docs/examples/quickstart/build/hello.pyx b/docs/examples/quickstart/build/hello.pyx index 47fc8d1cf..da1b827ac 100644 --- a/docs/examples/quickstart/build/hello.pyx +++ b/docs/examples/quickstart/build/hello.pyx @@ -1,2 +1,2 @@ -def say_hello_to(name):
- print("Hello %s!" % name)
+def say_hello_to(name): + print("Hello %s!" % name) diff --git a/docs/examples/quickstart/build/setup.py b/docs/examples/quickstart/build/setup.py index 4fb8c8154..fe959a106 100644 --- a/docs/examples/quickstart/build/setup.py +++ b/docs/examples/quickstart/build/setup.py @@ -1,5 +1,8 @@ -from distutils.core import setup
-from Cython.Build import cythonize
-
-setup(name='Hello world app',
- ext_modules=cythonize("hello.pyx"))
+from setuptools import setup +from Cython.Build import cythonize + +setup( + name='Hello world app', + ext_modules=cythonize("hello.pyx"), + zip_safe=False, +) diff --git a/docs/examples/quickstart/cythonize/cdef_keyword.py b/docs/examples/quickstart/cythonize/cdef_keyword.py new file mode 100644 index 000000000..6c0ee3e68 --- /dev/null +++ b/docs/examples/quickstart/cythonize/cdef_keyword.py @@ -0,0 +1,4 @@ +@cython.cfunc +@cython.exceptval(-2, check=True) +def f(x: cython.double) -> cython.double: + return x ** 2 - x diff --git a/docs/examples/quickstart/cythonize/cdef_keyword.pyx b/docs/examples/quickstart/cythonize/cdef_keyword.pyx index 16503ee89..bc7d893fa 100644 --- a/docs/examples/quickstart/cythonize/cdef_keyword.pyx +++ b/docs/examples/quickstart/cythonize/cdef_keyword.pyx @@ -1,2 +1,4 @@ -cdef double f(double x) except? -2:
- return x ** 2 - x
+ + +cdef double f(double x) except? -2: + return x ** 2 - x diff --git a/docs/examples/quickstart/cythonize/integrate.py b/docs/examples/quickstart/cythonize/integrate.py index 8d420b923..80d6d13a7 100644 --- a/docs/examples/quickstart/cythonize/integrate.py +++ b/docs/examples/quickstart/cythonize/integrate.py @@ -1,10 +1,10 @@ -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
+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 diff --git a/docs/examples/quickstart/cythonize/integrate_cy.py b/docs/examples/quickstart/cythonize/integrate_cy.py new file mode 100644 index 000000000..592ce8db7 --- /dev/null +++ b/docs/examples/quickstart/cythonize/integrate_cy.py @@ -0,0 +1,13 @@ +def 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 diff --git a/docs/examples/quickstart/cythonize/integrate_cy.pyx b/docs/examples/quickstart/cythonize/integrate_cy.pyx index 0bb0cd548..0e20a6c33 100644 --- a/docs/examples/quickstart/cythonize/integrate_cy.pyx +++ b/docs/examples/quickstart/cythonize/integrate_cy.pyx @@ -1,12 +1,13 @@ -def f(double x):
- return x ** 2 - x
-
-
-def integrate_f(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 += f(a + i * dx)
- return s * dx
+def 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 diff --git a/docs/examples/tutorial/array/clone.py b/docs/examples/tutorial/array/clone.py new file mode 100644 index 000000000..6736c2f67 --- /dev/null +++ b/docs/examples/tutorial/array/clone.py @@ -0,0 +1,8 @@ +from 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) diff --git a/docs/examples/tutorial/array/clone.pyx b/docs/examples/tutorial/array/clone.pyx index e2bac0e4a..2eb803499 100644 --- a/docs/examples/tutorial/array/clone.pyx +++ b/docs/examples/tutorial/array/clone.pyx @@ -1,8 +1,8 @@ -from 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)
+from 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) diff --git a/docs/examples/tutorial/array/overhead.py b/docs/examples/tutorial/array/overhead.py new file mode 100644 index 000000000..f60c019ce --- /dev/null +++ b/docs/examples/tutorial/array/overhead.py @@ -0,0 +1,17 @@ +from 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 diff --git a/docs/examples/tutorial/array/overhead.pyx b/docs/examples/tutorial/array/overhead.pyx index e385bff3f..a113e8dc9 100644 --- a/docs/examples/tutorial/array/overhead.pyx +++ b/docs/examples/tutorial/array/overhead.pyx @@ -1,15 +1,17 @@ -from 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
+from 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 diff --git a/docs/examples/tutorial/array/resize.py b/docs/examples/tutorial/array/resize.py new file mode 100644 index 000000000..c2e50472f --- /dev/null +++ b/docs/examples/tutorial/array/resize.py @@ -0,0 +1,10 @@ +from 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)) diff --git a/docs/examples/tutorial/array/resize.pyx b/docs/examples/tutorial/array/resize.pyx index a11fbde7b..7b92958b4 100644 --- a/docs/examples/tutorial/array/resize.pyx +++ b/docs/examples/tutorial/array/resize.pyx @@ -1,10 +1,10 @@ -from 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))
+from 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)) diff --git a/docs/examples/tutorial/array/safe_usage.py b/docs/examples/tutorial/array/safe_usage.py new file mode 100644 index 000000000..8b9ffd42c --- /dev/null +++ b/docs/examples/tutorial/array/safe_usage.py @@ -0,0 +1,6 @@ +from 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]) diff --git a/docs/examples/tutorial/array/safe_usage.pyx b/docs/examples/tutorial/array/safe_usage.pyx index 61d6b39eb..15107ae92 100644 --- a/docs/examples/tutorial/array/safe_usage.pyx +++ b/docs/examples/tutorial/array/safe_usage.pyx @@ -1,6 +1,6 @@ -from cpython cimport array
-import array
-cdef array.array a = array.array('i', [1, 2, 3])
-cdef int[:] ca = a
-
-print(ca[0])
+from cpython cimport array +import array +cdef array.array a = array.array('i', [1, 2, 3]) +cdef int[:] ca = a + +print(ca[0]) diff --git a/docs/examples/tutorial/array/unsafe_usage.py b/docs/examples/tutorial/array/unsafe_usage.py new file mode 100644 index 000000000..99b2b1690 --- /dev/null +++ b/docs/examples/tutorial/array/unsafe_usage.py @@ -0,0 +1,11 @@ +from 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)) diff --git a/docs/examples/tutorial/array/unsafe_usage.pyx b/docs/examples/tutorial/array/unsafe_usage.pyx index 2aefeb102..d1f498c68 100644 --- a/docs/examples/tutorial/array/unsafe_usage.pyx +++ b/docs/examples/tutorial/array/unsafe_usage.pyx @@ -1,11 +1,11 @@ -from 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))
+from 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)) diff --git a/docs/examples/tutorial/cdef_classes/integrate.py b/docs/examples/tutorial/cdef_classes/integrate.py new file mode 100644 index 000000000..cd02554e5 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/integrate.py @@ -0,0 +1,17 @@ +from 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)) diff --git a/docs/examples/tutorial/cdef_classes/integrate.pyx b/docs/examples/tutorial/cdef_classes/integrate.pyx index a3bbcbfec..ad4c8540b 100644 --- a/docs/examples/tutorial/cdef_classes/integrate.pyx +++ b/docs/examples/tutorial/cdef_classes/integrate.pyx @@ -1,14 +1,17 @@ -from 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))
+from 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)) diff --git a/docs/examples/tutorial/cdef_classes/math_function.py b/docs/examples/tutorial/cdef_classes/math_function.py index 21281cc9b..1a6ee896c 100644 --- a/docs/examples/tutorial/cdef_classes/math_function.py +++ b/docs/examples/tutorial/cdef_classes/math_function.py @@ -1,7 +1,7 @@ -class MathFunction(object):
- def __init__(self, name, operator):
- self.name = name
- self.operator = operator
-
- def __call__(self, *operands):
- return self.operator(*operands)
+class MathFunction(object): + def __init__(self, name, operator): + self.name = name + self.operator = operator + + def __call__(self, *operands): + return self.operator(*operands) diff --git a/docs/examples/tutorial/cdef_classes/math_function_2.py b/docs/examples/tutorial/cdef_classes/math_function_2.py new file mode 100644 index 000000000..ba5917639 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/math_function_2.py @@ -0,0 +1,5 @@ +@cython.cclass +class Function: + @cython.ccall + def evaluate(self, x: float) -> float: + return 0 diff --git a/docs/examples/tutorial/cdef_classes/math_function_2.pyx b/docs/examples/tutorial/cdef_classes/math_function_2.pyx index 1793ef689..a4bdb7aa2 100644 --- a/docs/examples/tutorial/cdef_classes/math_function_2.pyx +++ b/docs/examples/tutorial/cdef_classes/math_function_2.pyx @@ -1,3 +1,5 @@ -cdef class Function:
- cpdef double evaluate(self, double x) except *:
- return 0
+ +cdef class Function: + + cpdef double evaluate(self, double x) except *: + return 0 diff --git a/docs/examples/tutorial/cdef_classes/nonecheck.py b/docs/examples/tutorial/cdef_classes/nonecheck.py new file mode 100644 index 000000000..dccb97435 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/nonecheck.py @@ -0,0 +1,20 @@ +# 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! diff --git a/docs/examples/tutorial/cdef_classes/nonecheck.pyx b/docs/examples/tutorial/cdef_classes/nonecheck.pyx index b9e12c8d5..92c8fa42b 100644 --- a/docs/examples/tutorial/cdef_classes/nonecheck.pyx +++ b/docs/examples/tutorial/cdef_classes/nonecheck.pyx @@ -1,19 +1,20 @@ -# 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!
+# 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! diff --git a/docs/examples/tutorial/cdef_classes/sin_of_square.py b/docs/examples/tutorial/cdef_classes/sin_of_square.py new file mode 100644 index 000000000..1904ea934 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/sin_of_square.py @@ -0,0 +1,13 @@ +from 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) diff --git a/docs/examples/tutorial/cdef_classes/sin_of_square.pyx b/docs/examples/tutorial/cdef_classes/sin_of_square.pyx index 7aab96056..67af294b5 100644 --- a/docs/examples/tutorial/cdef_classes/sin_of_square.pyx +++ b/docs/examples/tutorial/cdef_classes/sin_of_square.pyx @@ -1,9 +1,13 @@ -from 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)
+from 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) diff --git a/docs/examples/tutorial/cdef_classes/wave_function.py b/docs/examples/tutorial/cdef_classes/wave_function.py new file mode 100644 index 000000000..7ff59a762 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/wave_function.py @@ -0,0 +1,22 @@ +from 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 diff --git a/docs/examples/tutorial/cdef_classes/wave_function.pyx b/docs/examples/tutorial/cdef_classes/wave_function.pyx index aa35d954e..34b144667 100644 --- a/docs/examples/tutorial/cdef_classes/wave_function.pyx +++ b/docs/examples/tutorial/cdef_classes/wave_function.pyx @@ -1,21 +1,22 @@ -from 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
+from 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 diff --git a/docs/examples/tutorial/clibraries/cqueue.pxd b/docs/examples/tutorial/clibraries/cqueue.pxd index 13a07d317..a657ae331 100644 --- a/docs/examples/tutorial/clibraries/cqueue.pxd +++ b/docs/examples/tutorial/clibraries/cqueue.pxd @@ -1,5 +1,3 @@ -# cqueue.pxd
-
cdef extern from "c-algorithms/src/queue.h":
ctypedef struct Queue:
pass
diff --git a/docs/examples/tutorial/clibraries/queue.py b/docs/examples/tutorial/clibraries/queue.py new file mode 100644 index 000000000..e99b9b32c --- /dev/null +++ b/docs/examples/tutorial/clibraries/queue.py @@ -0,0 +1,8 @@ +from cython.cimports import cqueue + +@cython.cclass +class Queue: + _c_queue: cython.pointer(cqueue.Queue) + + def __cinit__(self): + self._c_queue = cqueue.queue_new() diff --git a/docs/examples/tutorial/clibraries/queue.pyx b/docs/examples/tutorial/clibraries/queue.pyx index 5363ee4f5..654c07b8d 100644 --- a/docs/examples/tutorial/clibraries/queue.pyx +++ b/docs/examples/tutorial/clibraries/queue.pyx @@ -1,9 +1,8 @@ -# queue.pyx
-
-cimport cqueue
-
-cdef class Queue:
- cdef cqueue.Queue* _c_queue
-
- def __cinit__(self):
- self._c_queue = cqueue.queue_new()
+cimport cqueue + + +cdef class Queue: + cdef cqueue.Queue* _c_queue + + def __cinit__(self): + self._c_queue = cqueue.queue_new() diff --git a/docs/examples/tutorial/clibraries/queue2.py b/docs/examples/tutorial/clibraries/queue2.py new file mode 100644 index 000000000..de6d58a99 --- /dev/null +++ b/docs/examples/tutorial/clibraries/queue2.py @@ -0,0 +1,10 @@ +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() diff --git a/docs/examples/tutorial/clibraries/queue2.pyx b/docs/examples/tutorial/clibraries/queue2.pyx index 9278fbf4b..5dca04c22 100644 --- a/docs/examples/tutorial/clibraries/queue2.pyx +++ b/docs/examples/tutorial/clibraries/queue2.pyx @@ -1,11 +1,10 @@ -# queue.pyx
-
-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()
+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() diff --git a/docs/examples/tutorial/clibraries/queue3.py b/docs/examples/tutorial/clibraries/queue3.py new file mode 100644 index 000000000..79f341254 --- /dev/null +++ b/docs/examples/tutorial/clibraries/queue3.py @@ -0,0 +1,68 @@ +from 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) diff --git a/docs/examples/tutorial/clibraries/queue3.pyx b/docs/examples/tutorial/clibraries/queue3.pyx index cc84cf172..c15c48e15 100644 --- a/docs/examples/tutorial/clibraries/queue3.pyx +++ b/docs/examples/tutorial/clibraries/queue3.pyx @@ -1,7 +1,7 @@ -# queue.pyx - cimport cqueue + + cdef class Queue: """A queue class for C integer values. @@ -22,6 +22,7 @@ cdef class Queue: 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, <void*> <Py_ssize_t> value): @@ -33,15 +34,19 @@ cdef class Queue: # 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 = <Py_ssize_t> cqueue.queue_peek_head(self._c_queue) @@ -52,6 +57,8 @@ cdef class 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") diff --git a/docs/examples/tutorial/clibraries/test_queue.py b/docs/examples/tutorial/clibraries/test_queue.py index 5390a82c1..41b267395 100644 --- a/docs/examples/tutorial/clibraries/test_queue.py +++ b/docs/examples/tutorial/clibraries/test_queue.py @@ -1,36 +1,36 @@ -from __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())
+from __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()) diff --git a/docs/examples/tutorial/cython_tutorial/primes.py b/docs/examples/tutorial/cython_tutorial/primes.py new file mode 100644 index 000000000..645d9479d --- /dev/null +++ b/docs/examples/tutorial/cython_tutorial/primes.py @@ -0,0 +1,27 @@ +def 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 diff --git a/docs/examples/tutorial/cython_tutorial/primes.pyx b/docs/examples/tutorial/cython_tutorial/primes.pyx index 96ecdb59a..7707e30dc 100644 --- a/docs/examples/tutorial/cython_tutorial/primes.pyx +++ b/docs/examples/tutorial/cython_tutorial/primes.pyx @@ -1,9 +1,13 @@ def primes(int nb_primes): cdef int n, i, len_p - cdef int p[1000] + 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: @@ -18,6 +22,6 @@ def primes(int nb_primes): len_p += 1 n += 1 - # Let's return the result in a python list: - result_as_list = [prime for prime in p[:len_p]] + # Let's copy the result into a Python list: + result_as_list = [prime for prime in p[:len_p]] return result_as_list diff --git a/docs/examples/tutorial/cython_tutorial/primes_cpp.py b/docs/examples/tutorial/cython_tutorial/primes_cpp.py new file mode 100644 index 000000000..468d00c46 --- /dev/null +++ b/docs/examples/tutorial/cython_tutorial/primes_cpp.py @@ -0,0 +1,22 @@ +# 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. diff --git a/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx b/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx index 57bfe9cc2..afef8bd13 100644 --- a/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx +++ b/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx @@ -1,21 +1,22 @@ -# 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
-
- # Vectors are automatically converted to Python
- # lists when converted to Python objects.
- return p
+# 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. diff --git a/docs/examples/tutorial/cython_tutorial/primes_python.py b/docs/examples/tutorial/cython_tutorial/primes_python.py index f6559d519..845af5bbf 100644 --- a/docs/examples/tutorial/cython_tutorial/primes_python.py +++ b/docs/examples/tutorial/cython_tutorial/primes_python.py @@ -1,4 +1,4 @@ -def primes_python(nb_primes): +def primes(nb_primes): p = [] n = 2 while len(p) < nb_primes: diff --git a/docs/examples/tutorial/cython_tutorial/setup.py b/docs/examples/tutorial/cython_tutorial/setup.py deleted file mode 100644 index 302a08e5f..000000000 --- a/docs/examples/tutorial/cython_tutorial/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -from distutils.core import setup -from Cython.Build import cythonize - -setup( - ext_modules=cythonize("fib.pyx"), -) diff --git a/docs/examples/tutorial/embedding/embedded.pyx b/docs/examples/tutorial/embedding/embedded.pyx new file mode 100644 index 000000000..2ed823945 --- /dev/null +++ b/docs/examples/tutorial/embedding/embedded.pyx @@ -0,0 +1,12 @@ +# 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 diff --git a/docs/examples/tutorial/embedding/embedded_main.c b/docs/examples/tutorial/embedding/embedded_main.c new file mode 100644 index 000000000..e14901a5e --- /dev/null +++ b/docs/examples/tutorial/embedding/embedded_main.c @@ -0,0 +1,69 @@ +/* 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 diff --git a/docs/examples/tutorial/external/atoi.py b/docs/examples/tutorial/external/atoi.py new file mode 100644 index 000000000..250b26a5c --- /dev/null +++ b/docs/examples/tutorial/external/atoi.py @@ -0,0 +1,6 @@ +from 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! diff --git a/docs/examples/tutorial/external/atoi.pyx b/docs/examples/tutorial/external/atoi.pyx index 48643bbf2..ef1219854 100644 --- a/docs/examples/tutorial/external/atoi.pyx +++ b/docs/examples/tutorial/external/atoi.pyx @@ -1,5 +1,6 @@ -from 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!
+from 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! diff --git a/docs/examples/tutorial/external/cpdef_sin.pyx b/docs/examples/tutorial/external/cpdef_sin.pyx index 47e09f433..eee2326a4 100644 --- a/docs/examples/tutorial/external/cpdef_sin.pyx +++ b/docs/examples/tutorial/external/cpdef_sin.pyx @@ -1,7 +1,7 @@ -"""
->>> sin(0)
-0.0
-"""
-
-cdef extern from "math.h":
- cpdef double sin(double x)
+""" +>>> sin(0) +0.0 +""" + +cdef extern from "math.h": + cpdef double sin(double x) diff --git a/docs/examples/tutorial/external/keyword_args.pyx b/docs/examples/tutorial/external/keyword_args.pyx index 327e4e08b..7c2a786cc 100644 --- a/docs/examples/tutorial/external/keyword_args.pyx +++ b/docs/examples/tutorial/external/keyword_args.pyx @@ -1,2 +1,2 @@ -cdef extern from "string.h":
- char* strstr(const char *haystack, const char *needle)
+cdef extern from "string.h": + char* strstr(const char *haystack, const char *needle) diff --git a/docs/examples/tutorial/external/keyword_args_call.py b/docs/examples/tutorial/external/keyword_args_call.py new file mode 100644 index 000000000..b3b3f5049 --- /dev/null +++ b/docs/examples/tutorial/external/keyword_args_call.py @@ -0,0 +1,7 @@ +from cython.cimports.strstr import strstr + +def main(): + data: cython.p_char = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" + + pos = strstr(needle='akd', haystack=data) + print(pos is not cython.NULL) diff --git a/docs/examples/tutorial/external/keyword_args_call.pyx b/docs/examples/tutorial/external/keyword_args_call.pyx index 4be5f755d..de2b6f2b2 100644 --- a/docs/examples/tutorial/external/keyword_args_call.pyx +++ b/docs/examples/tutorial/external/keyword_args_call.pyx @@ -1,7 +1,7 @@ -cdef 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)
+cdef 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) diff --git a/docs/examples/tutorial/external/libc_sin.py b/docs/examples/tutorial/external/libc_sin.py new file mode 100644 index 000000000..f4223253d --- /dev/null +++ b/docs/examples/tutorial/external/libc_sin.py @@ -0,0 +1,5 @@ +from cython.cimports.libc.math import sin + +@cython.cfunc +def f(x: cython.double) -> cython.double: + return sin(x * x) diff --git a/docs/examples/tutorial/external/libc_sin.pyx b/docs/examples/tutorial/external/libc_sin.pyx index 25a4430e3..2de8444d6 100644 --- a/docs/examples/tutorial/external/libc_sin.pyx +++ b/docs/examples/tutorial/external/libc_sin.pyx @@ -1,4 +1,5 @@ -from libc.math cimport sin
-
-cdef double f(double x):
- return sin(x * x)
+from libc.math cimport sin + + +cdef double f(double x): + return sin(x * x) diff --git a/docs/examples/tutorial/external/py_version_hex.py b/docs/examples/tutorial/external/py_version_hex.py new file mode 100644 index 000000000..3b19d0d02 --- /dev/null +++ b/docs/examples/tutorial/external/py_version_hex.py @@ -0,0 +1,4 @@ +from cython.cimports.cpython.version import PY_VERSION_HEX + +# Python version >= 3.2 final ? +print(PY_VERSION_HEX >= 0x030200F0) diff --git a/docs/examples/tutorial/external/py_version_hex.pyx b/docs/examples/tutorial/external/py_version_hex.pyx index d732b00e7..e33f207c1 100644 --- a/docs/examples/tutorial/external/py_version_hex.pyx +++ b/docs/examples/tutorial/external/py_version_hex.pyx @@ -1,4 +1,4 @@ -from cpython.version cimport PY_VERSION_HEX
-
-# Python version >= 3.2 final ?
-print(PY_VERSION_HEX >= 0x030200F0)
+from cpython.version cimport PY_VERSION_HEX + +# Python version >= 3.2 final ? +print(PY_VERSION_HEX >= 0x030200F0) diff --git a/docs/examples/tutorial/external/setup.py b/docs/examples/tutorial/external/setup.py index 653214c84..289bc9534 100644 --- a/docs/examples/tutorial/external/setup.py +++ b/docs/examples/tutorial/external/setup.py @@ -1,13 +1,12 @@ -from distutils.core import setup
-from distutils.extension import Extension
-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))
+from 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)) diff --git a/docs/examples/tutorial/external/strstr.pxd b/docs/examples/tutorial/external/strstr.pxd new file mode 100644 index 000000000..7c2a786cc --- /dev/null +++ b/docs/examples/tutorial/external/strstr.pxd @@ -0,0 +1,2 @@ +cdef extern from "string.h": + char* strstr(const char *haystack, const char *needle) diff --git a/docs/examples/tutorial/memory_allocation/malloc.py b/docs/examples/tutorial/memory_allocation/malloc.py new file mode 100644 index 000000000..fb7e82236 --- /dev/null +++ b/docs/examples/tutorial/memory_allocation/malloc.py @@ -0,0 +1,24 @@ +import 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) diff --git a/docs/examples/tutorial/memory_allocation/malloc.pyx b/docs/examples/tutorial/memory_allocation/malloc.pyx index e01a378e3..6aa583aab 100644 --- a/docs/examples/tutorial/memory_allocation/malloc.pyx +++ b/docs/examples/tutorial/memory_allocation/malloc.pyx @@ -1,23 +1,24 @@ -import 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 = <double *> 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)
+import 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 = <double *> 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) diff --git a/docs/examples/tutorial/memory_allocation/some_memory.py b/docs/examples/tutorial/memory_allocation/some_memory.py new file mode 100644 index 000000000..31ad63a6e --- /dev/null +++ b/docs/examples/tutorial/memory_allocation/some_memory.py @@ -0,0 +1,27 @@ +from 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 + # re-use 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 diff --git a/docs/examples/tutorial/memory_allocation/some_memory.pyx b/docs/examples/tutorial/memory_allocation/some_memory.pyx index 2e639ac4d..e6bb63b77 100644 --- a/docs/examples/tutorial/memory_allocation/some_memory.pyx +++ b/docs/examples/tutorial/memory_allocation/some_memory.pyx @@ -1,25 +1,27 @@ -from 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 = <double*> 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
- # re-use the original data location.
- mem = <double*> 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
+from 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 = <double*> 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 + # re-use the original data location. + mem = <double*> 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 diff --git a/docs/examples/tutorial/numpy/convolve2.pyx b/docs/examples/tutorial/numpy/convolve2.pyx index be7512fe1..b77b92f53 100644 --- a/docs/examples/tutorial/numpy/convolve2.pyx +++ b/docs/examples/tutorial/numpy/convolve2.pyx @@ -1,4 +1,4 @@ -# tag: numpy_old +# tag: numpy # You can ignore the previous line. # It's for internal testing of the cython documentation. @@ -9,6 +9,12 @@ import numpy as np # currently part of the Cython distribution). cimport numpy as np +# 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" +np.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. diff --git a/docs/examples/tutorial/numpy/convolve_py.py b/docs/examples/tutorial/numpy/convolve_py.py index c3cbc5f86..39b276a04 100644 --- a/docs/examples/tutorial/numpy/convolve_py.py +++ b/docs/examples/tutorial/numpy/convolve_py.py @@ -1,43 +1,43 @@ -import 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
+import 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 diff --git a/docs/examples/tutorial/parallelization/manual_work.py b/docs/examples/tutorial/parallelization/manual_work.py new file mode 100644 index 000000000..d6b0167d9 --- /dev/null +++ b/docs/examples/tutorial/parallelization/manual_work.py @@ -0,0 +1,24 @@ +# 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() diff --git a/docs/examples/tutorial/parallelization/manual_work.pyx b/docs/examples/tutorial/parallelization/manual_work.pyx new file mode 100644 index 000000000..886015839 --- /dev/null +++ b/docs/examples/tutorial/parallelization/manual_work.pyx @@ -0,0 +1,25 @@ +# 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() + diff --git a/docs/examples/tutorial/parallelization/median.py b/docs/examples/tutorial/parallelization/median.py new file mode 100644 index 000000000..535a2b136 --- /dev/null +++ b/docs/examples/tutorial/parallelization/median.py @@ -0,0 +1,35 @@ +# 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) diff --git a/docs/examples/tutorial/parallelization/median.pyx b/docs/examples/tutorial/parallelization/median.pyx new file mode 100644 index 000000000..242cb6091 --- /dev/null +++ b/docs/examples/tutorial/parallelization/median.pyx @@ -0,0 +1,34 @@ +# 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) + diff --git a/docs/examples/tutorial/parallelization/norm.py b/docs/examples/tutorial/parallelization/norm.py new file mode 100644 index 000000000..1d8c2758a --- /dev/null +++ b/docs/examples/tutorial/parallelization/norm.py @@ -0,0 +1,12 @@ +from 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) diff --git a/docs/examples/tutorial/parallelization/norm.pyx b/docs/examples/tutorial/parallelization/norm.pyx new file mode 100644 index 000000000..5a702f975 --- /dev/null +++ b/docs/examples/tutorial/parallelization/norm.pyx @@ -0,0 +1,12 @@ +from 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) diff --git a/docs/examples/tutorial/parallelization/normalize.py b/docs/examples/tutorial/parallelization/normalize.py new file mode 100644 index 000000000..0519be4d4 --- /dev/null +++ b/docs/examples/tutorial/parallelization/normalize.py @@ -0,0 +1,16 @@ +from 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 diff --git a/docs/examples/tutorial/parallelization/normalize.pyx b/docs/examples/tutorial/parallelization/normalize.pyx new file mode 100644 index 000000000..e167ad7ad --- /dev/null +++ b/docs/examples/tutorial/parallelization/normalize.pyx @@ -0,0 +1,17 @@ +from 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 + diff --git a/docs/examples/tutorial/parallelization/parallel_sin.py b/docs/examples/tutorial/parallelization/parallel_sin.py new file mode 100644 index 000000000..be6cbc030 --- /dev/null +++ b/docs/examples/tutorial/parallelization/parallel_sin.py @@ -0,0 +1,16 @@ +from 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) diff --git a/docs/examples/tutorial/parallelization/parallel_sin.pyx b/docs/examples/tutorial/parallelization/parallel_sin.pyx new file mode 100644 index 000000000..c3091541e --- /dev/null +++ b/docs/examples/tutorial/parallelization/parallel_sin.pyx @@ -0,0 +1,16 @@ +from 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) diff --git a/docs/examples/tutorial/parallelization/setup.py b/docs/examples/tutorial/parallelization/setup.py new file mode 100644 index 000000000..eb343e5da --- /dev/null +++ b/docs/examples/tutorial/parallelization/setup.py @@ -0,0 +1,29 @@ +from 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), +) diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi.py b/docs/examples/tutorial/profiling_tutorial/calc_pi.py index bc265e560..3775eb816 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi.py +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi.py @@ -1,10 +1,8 @@ -# calc_pi.py
-
-def 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
+def 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 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py new file mode 100644 index 000000000..b05eeedb5 --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py @@ -0,0 +1,12 @@ +# 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 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx index dab8d238d..485bbabf8 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx @@ -1,13 +1,11 @@ -# cython: profile=True
-
-# calc_pi.pyx
-
-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
+# 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 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py new file mode 100644 index 000000000..df3dfa3a1 --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py @@ -0,0 +1,15 @@ +# 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 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx index 0f0bdb18a..742991b1a 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx @@ -1,13 +1,14 @@ -# cython: profile=True
-
-# calc_pi.pyx
-
-cdef inline double recip_square(int i):
- 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
+# 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 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py new file mode 100644 index 000000000..b457cd99d --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py @@ -0,0 +1,17 @@ +# 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 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx index ab3f9ea9f..415ac4a22 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx @@ -1,16 +1,17 @@ -# cython: profile=True
-
-# calc_pi.pyx
-
-cimport cython
-
-@cython.profile(False)
-cdef inline double recip_square(int i):
- 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
+# 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 diff --git a/docs/examples/tutorial/profiling_tutorial/often_called.py b/docs/examples/tutorial/profiling_tutorial/often_called.py new file mode 100644 index 000000000..15197cb97 --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/often_called.py @@ -0,0 +1,5 @@ +import cython + +@cython.profile(False) +def my_often_called_function(): + pass diff --git a/docs/examples/tutorial/profiling_tutorial/often_called.pyx b/docs/examples/tutorial/profiling_tutorial/often_called.pyx index 77c689c9c..3699dce4f 100644 --- a/docs/examples/tutorial/profiling_tutorial/often_called.pyx +++ b/docs/examples/tutorial/profiling_tutorial/often_called.pyx @@ -1,5 +1,5 @@ -cimport cython
-
-@cython.profile(False)
-def my_often_called_function():
- pass
+cimport cython + +@cython.profile(False) +def my_often_called_function(): + pass diff --git a/docs/examples/tutorial/profiling_tutorial/profile.py b/docs/examples/tutorial/profiling_tutorial/profile.py index 1c12bf971..c0b76472a 100644 --- a/docs/examples/tutorial/profiling_tutorial/profile.py +++ b/docs/examples/tutorial/profiling_tutorial/profile.py @@ -1,10 +1,8 @@ -# profile.py
-
-import 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()
+import 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() diff --git a/docs/examples/tutorial/profiling_tutorial/profile_2.py b/docs/examples/tutorial/profiling_tutorial/profile_2.py index 38fb50104..ca5ca514b 100644 --- a/docs/examples/tutorial/profiling_tutorial/profile_2.py +++ b/docs/examples/tutorial/profiling_tutorial/profile_2.py @@ -1,13 +1,11 @@ -# profile.py
-
-import 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()
+import 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() diff --git a/docs/examples/tutorial/pure/A.py b/docs/examples/tutorial/pure/A.py index 1e0cea950..98d5530c8 100644 --- a/docs/examples/tutorial/pure/A.py +++ b/docs/examples/tutorial/pure/A.py @@ -1,14 +1,14 @@ -def 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))
+def 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)) diff --git a/docs/examples/tutorial/pure/A_equivalent.pyx b/docs/examples/tutorial/pure/A_equivalent.pyx index 1b256a010..ab9e0081c 100644 --- a/docs/examples/tutorial/pure/A_equivalent.pyx +++ b/docs/examples/tutorial/pure/A_equivalent.pyx @@ -1,15 +1,15 @@ -cpdef 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))
+cpdef 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)) diff --git a/docs/examples/tutorial/pure/annotations.py b/docs/examples/tutorial/pure/annotations.py index 2b8487c0b..09682c352 100644 --- a/docs/examples/tutorial/pure/annotations.py +++ b/docs/examples/tutorial/pure/annotations.py @@ -1,5 +1,5 @@ -import cython
-
-def func(foo: dict, bar: cython.int) -> tuple:
- foo["hello world"] = 3 + bar
- return foo, 5
+import cython + +def func(foo: dict, bar: cython.int) -> tuple: + foo["hello world"] = 3 + bar + return foo, 5 diff --git a/docs/examples/tutorial/pure/c_arrays.py b/docs/examples/tutorial/pure/c_arrays.py index 33067da68..f221b7ae8 100644 --- a/docs/examples/tutorial/pure/c_arrays.py +++ b/docs/examples/tutorial/pure/c_arrays.py @@ -1,15 +1,15 @@ -import 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
+import 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 diff --git a/docs/examples/tutorial/pure/cclass.py b/docs/examples/tutorial/pure/cclass.py index 61c65183d..7f9cb1a04 100644 --- a/docs/examples/tutorial/pure/cclass.py +++ b/docs/examples/tutorial/pure/cclass.py @@ -1,16 +1,16 @@ -import 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
+import 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 diff --git a/docs/examples/tutorial/pure/compiled_switch.py b/docs/examples/tutorial/pure/compiled_switch.py index 47d62a3e6..a35cac2c6 100644 --- a/docs/examples/tutorial/pure/compiled_switch.py +++ b/docs/examples/tutorial/pure/compiled_switch.py @@ -1,6 +1,6 @@ -import cython
-
-if cython.compiled:
- print("Yep, I'm compiled.")
-else:
- print("Just a lowly interpreted script.")
+import cython + +if cython.compiled: + print("Yep, I'm compiled.") +else: + print("Just a lowly interpreted script.") diff --git a/docs/examples/tutorial/pure/cython_declare.py b/docs/examples/tutorial/pure/cython_declare.py index cf6d58bba..50a4ab8aa 100644 --- a/docs/examples/tutorial/pure/cython_declare.py +++ b/docs/examples/tutorial/pure/cython_declare.py @@ -1,4 +1,4 @@ -import cython
-
-x = cython.declare(cython.int) # cdef int x
-y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721
+import cython + +x = cython.declare(cython.int) # cdef int x +y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721 diff --git a/docs/examples/tutorial/pure/cython_declare2.py b/docs/examples/tutorial/pure/cython_declare2.py index 35fae7d7b..ee491d62b 100644 --- a/docs/examples/tutorial/pure/cython_declare2.py +++ b/docs/examples/tutorial/pure/cython_declare2.py @@ -1,3 +1,3 @@ -import cython
-
-cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y
+import cython + +cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y diff --git a/docs/examples/tutorial/pure/disabled_annotations.py b/docs/examples/tutorial/pure/disabled_annotations.py new file mode 100644 index 000000000..c92b4cf8e --- /dev/null +++ b/docs/examples/tutorial/pure/disabled_annotations.py @@ -0,0 +1,33 @@ +import 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 diff --git a/docs/examples/tutorial/pure/dostuff.py b/docs/examples/tutorial/pure/dostuff.py index 748c31b10..7a88533c5 100644 --- a/docs/examples/tutorial/pure/dostuff.py +++ b/docs/examples/tutorial/pure/dostuff.py @@ -1,5 +1,5 @@ -def dostuff(n):
- t = 0
- for i in range(n):
- t += i
- return t
+def dostuff(n): + t = 0 + for i in range(n): + t += i + return t diff --git a/docs/examples/tutorial/pure/exceptval.py b/docs/examples/tutorial/pure/exceptval.py index 8bf564040..3d991f7c1 100644 --- a/docs/examples/tutorial/pure/exceptval.py +++ b/docs/examples/tutorial/pure/exceptval.py @@ -1,7 +1,7 @@ -import cython
-
-@cython.exceptval(-1)
-def func(x: cython.int) -> cython.int:
- if x < 0:
- raise ValueError("need integer >= 0")
- return x + 1
+import cython + +@cython.exceptval(-1) +def func(x: cython.int) -> cython.int: + if x < 0: + raise ValueError("need integer >= 0") + return x + 1 diff --git a/docs/examples/tutorial/pure/locals.py b/docs/examples/tutorial/pure/locals.py index 8eda7114a..b273a9ebe 100644 --- a/docs/examples/tutorial/pure/locals.py +++ b/docs/examples/tutorial/pure/locals.py @@ -1,6 +1,6 @@ -import cython
-
-@cython.locals(a=cython.long, b=cython.long, n=cython.longlong)
-def foo(a, b, x, y):
- n = a * b
- # ...
+import cython + +@cython.locals(a=cython.long, b=cython.long, n=cython.longlong) +def foo(a, b, x, y): + n = a * b + # ... diff --git a/docs/examples/tutorial/pure/mymodule.py b/docs/examples/tutorial/pure/mymodule.py index 62d4c76ac..83f5cdc28 100644 --- a/docs/examples/tutorial/pure/mymodule.py +++ b/docs/examples/tutorial/pure/mymodule.py @@ -1,10 +1,10 @@ -# 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))
+# 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)) diff --git a/docs/examples/tutorial/pure/pep_526.py b/docs/examples/tutorial/pure/pep_526.py index 163d97859..ecb3bfcdf 100644 --- a/docs/examples/tutorial/pure/pep_526.py +++ b/docs/examples/tutorial/pure/pep_526.py @@ -1,22 +1,22 @@ -import 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
+import 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 diff --git a/docs/examples/tutorial/pure/py_cimport.py b/docs/examples/tutorial/pure/py_cimport.py new file mode 100644 index 000000000..233ddde7e --- /dev/null +++ b/docs/examples/tutorial/pure/py_cimport.py @@ -0,0 +1,5 @@ + +from cython.cimports.libc import math + +def use_libc_math(): + return math.ceil(5.5) diff --git a/docs/examples/tutorial/string/api_func.pyx b/docs/examples/tutorial/string/api_func.pyx index ec6b27751..c9e05f9e3 100644 --- a/docs/examples/tutorial/string/api_func.pyx +++ b/docs/examples/tutorial/string/api_func.pyx @@ -1,5 +1,5 @@ -from to_unicode cimport _text
-
-def api_func(s):
- text_input = _text(s)
- # ...
+from to_unicode cimport _text + +def api_func(s): + text_input = _text(s) + # ... diff --git a/docs/examples/tutorial/string/arg_memview.pyx b/docs/examples/tutorial/string/arg_memview.pyx index 63a18f943..e2b6d75be 100644 --- a/docs/examples/tutorial/string/arg_memview.pyx +++ b/docs/examples/tutorial/string/arg_memview.pyx @@ -1,5 +1,5 @@ -def process_byte_data(unsigned char[:] data):
- length = data.shape[0]
- first_byte = data[0]
- slice_view = data[1:-1]
- # ...
+def process_byte_data(unsigned char[:] data): + length = data.shape[0] + first_byte = data[0] + slice_view = data[1:-1] + # ... diff --git a/docs/examples/tutorial/string/auto_conversion_1.pyx b/docs/examples/tutorial/string/auto_conversion_1.pyx index 929c03d68..ee2b116e4 100644 --- a/docs/examples/tutorial/string/auto_conversion_1.pyx +++ b/docs/examples/tutorial/string/auto_conversion_1.pyx @@ -1,9 +1,9 @@ -# 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 = <bytes>c_string
+# 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 = <bytes>c_string diff --git a/docs/examples/tutorial/string/auto_conversion_2.pyx b/docs/examples/tutorial/string/auto_conversion_2.pyx index 84436661d..9f7a5ad04 100644 --- a/docs/examples/tutorial/string/auto_conversion_2.pyx +++ b/docs/examples/tutorial/string/auto_conversion_2.pyx @@ -1,12 +1,12 @@ -# 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 = <bytes>c_string
-
-# explicit conversion to Python unicode:
-py_bytes_object = <unicode>c_string
+# 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 = <bytes>c_string + +# explicit conversion to Python unicode: +py_bytes_object = <unicode>c_string diff --git a/docs/examples/tutorial/string/auto_conversion_3.pyx b/docs/examples/tutorial/string/auto_conversion_3.pyx index 509d7e324..b9a1b7517 100644 --- a/docs/examples/tutorial/string/auto_conversion_3.pyx +++ b/docs/examples/tutorial/string/auto_conversion_3.pyx @@ -1,6 +1,6 @@ -# cython: c_string_type=unicode, c_string_encoding=ascii
-
-def func():
- ustring = u'abc'
- cdef char* s = ustring
- return s[0] # returns u'a'
+# cython: c_string_type=unicode, c_string_encoding=ascii + +def func(): + ustring = u'abc' + cdef char* s = ustring + return s[0] # returns u'a' diff --git a/docs/examples/tutorial/string/c_func.pyx b/docs/examples/tutorial/string/c_func.pyx index a456b815b..4763f2671 100644 --- a/docs/examples/tutorial/string/c_func.pyx +++ b/docs/examples/tutorial/string/c_func.pyx @@ -1,22 +1,23 @@ -from libc.stdlib cimport malloc
-from libc.string cimport strcpy, strlen
-
-cdef char* hello_world = 'hello world'
-cdef Py_ssize_t n = strlen(hello_world)
-
-
-cdef char* c_call_returning_a_c_string():
- cdef char* c_string = <char *> malloc((n + 1) * sizeof(char))
- if not c_string:
- raise MemoryError()
- 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] = <char *> malloc((n + 1) * sizeof(char))
- if not c_string_ptr[0]:
- raise MemoryError()
-
- strcpy(c_string_ptr[0], hello_world)
- length[0] = n
+from libc.stdlib cimport malloc +from libc.string cimport strcpy, strlen + +cdef char* hello_world = 'hello world' +cdef Py_ssize_t n = strlen(hello_world) + + +cdef char* c_call_returning_a_c_string(): + cdef char* c_string = <char *> 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] = <char *> malloc((n + 1) * sizeof(char)) + if not c_string_ptr[0]: + return # malloc failed + + strcpy(c_string_ptr[0], hello_world) + length[0] = n diff --git a/docs/examples/tutorial/string/const.pyx b/docs/examples/tutorial/string/const.pyx index e066c77ac..0b89b9e41 100644 --- a/docs/examples/tutorial/string/const.pyx +++ b/docs/examples/tutorial/string/const.pyx @@ -1,4 +1,4 @@ -cdef 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)
+cdef 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) diff --git a/docs/examples/tutorial/string/cpp_string.pyx b/docs/examples/tutorial/string/cpp_string.pyx index b6c9e44f9..313e72a67 100644 --- a/docs/examples/tutorial/string/cpp_string.pyx +++ b/docs/examples/tutorial/string/cpp_string.pyx @@ -1,12 +1,12 @@ -# 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
-
+# 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 + diff --git a/docs/examples/tutorial/string/decode.pyx b/docs/examples/tutorial/string/decode.pyx index c3e2faf68..79fc41835 100644 --- a/docs/examples/tutorial/string/decode.pyx +++ b/docs/examples/tutorial/string/decode.pyx @@ -1,9 +1,9 @@ -from 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')
+from 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') diff --git a/docs/examples/tutorial/string/decode_cpp_string.pyx b/docs/examples/tutorial/string/decode_cpp_string.pyx index 8f1d01af8..52861c209 100644 --- a/docs/examples/tutorial/string/decode_cpp_string.pyx +++ b/docs/examples/tutorial/string/decode_cpp_string.pyx @@ -1,10 +1,10 @@ -# 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
+# 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 diff --git a/docs/examples/tutorial/string/for_bytes.pyx b/docs/examples/tutorial/string/for_bytes.pyx index 69e9202ae..d4d3e1f81 100644 --- a/docs/examples/tutorial/string/for_bytes.pyx +++ b/docs/examples/tutorial/string/for_bytes.pyx @@ -1,6 +1,6 @@ -cdef 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")
+cdef 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") diff --git a/docs/examples/tutorial/string/for_char.pyx b/docs/examples/tutorial/string/for_char.pyx index adc16bcd8..81abae97c 100644 --- a/docs/examples/tutorial/string/for_char.pyx +++ b/docs/examples/tutorial/string/for_char.pyx @@ -1,6 +1,6 @@ -cdef 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")
+cdef 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") diff --git a/docs/examples/tutorial/string/for_unicode.pyx b/docs/examples/tutorial/string/for_unicode.pyx index aabd562e4..0f8ab0c7d 100644 --- a/docs/examples/tutorial/string/for_unicode.pyx +++ b/docs/examples/tutorial/string/for_unicode.pyx @@ -1,6 +1,6 @@ -cdef unicode ustring = u'Hello world'
-
-# NOTE: no typing required for 'uchar' !
-for uchar in ustring:
- if uchar == u'A':
- print("Found the letter A")
+cdef unicode ustring = u'Hello world' + +# NOTE: no typing required for 'uchar' ! +for uchar in ustring: + if uchar == u'A': + print("Found the letter A") diff --git a/docs/examples/tutorial/string/if_char_in.pyx b/docs/examples/tutorial/string/if_char_in.pyx index 73521b2de..e33e18d59 100644 --- a/docs/examples/tutorial/string/if_char_in.pyx +++ b/docs/examples/tutorial/string/if_char_in.pyx @@ -1,5 +1,5 @@ -cpdef 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")
+cpdef 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") diff --git a/docs/examples/tutorial/string/naive_decode.pyx b/docs/examples/tutorial/string/naive_decode.pyx index 186d2affa..b3c44d9af 100644 --- a/docs/examples/tutorial/string/naive_decode.pyx +++ b/docs/examples/tutorial/string/naive_decode.pyx @@ -1,4 +1,4 @@ -from 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')
+from 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') diff --git a/docs/examples/tutorial/string/return_memview.pyx b/docs/examples/tutorial/string/return_memview.pyx index f6233436a..be9b597a4 100644 --- a/docs/examples/tutorial/string/return_memview.pyx +++ b/docs/examples/tutorial/string/return_memview.pyx @@ -1,9 +1,9 @@ -def 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])
+def 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]) diff --git a/docs/examples/tutorial/string/slicing_c_string.pyx b/docs/examples/tutorial/string/slicing_c_string.pyx index 2e937430e..f8d272e32 100644 --- a/docs/examples/tutorial/string/slicing_c_string.pyx +++ b/docs/examples/tutorial/string/slicing_c_string.pyx @@ -1,15 +1,15 @@ -from 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)
+from 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) diff --git a/docs/examples/tutorial/string/to_char.pyx b/docs/examples/tutorial/string/to_char.pyx index 5e4a16161..7912ea485 100644 --- a/docs/examples/tutorial/string/to_char.pyx +++ b/docs/examples/tutorial/string/to_char.pyx @@ -1,8 +1,8 @@ -# 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 = (<unicode>s).encode('utf8')
- return s
+# 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 = (<unicode>s).encode('utf8') + return s diff --git a/docs/examples/tutorial/string/to_unicode.pyx b/docs/examples/tutorial/string/to_unicode.pyx index 8ab8f2662..188a8776e 100644 --- a/docs/examples/tutorial/string/to_unicode.pyx +++ b/docs/examples/tutorial/string/to_unicode.pyx @@ -1,22 +1,22 @@ -# 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 <unicode>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 (<bytes>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 <unicode> 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.")
+# 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 <unicode>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 (<bytes>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 <unicode> 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.") diff --git a/docs/examples/tutorial/string/try_finally.pyx b/docs/examples/tutorial/string/try_finally.pyx index aea786f5b..4cf943e56 100644 --- a/docs/examples/tutorial/string/try_finally.pyx +++ b/docs/examples/tutorial/string/try_finally.pyx @@ -1,9 +1,9 @@ -from 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)
+from 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) diff --git a/docs/examples/tutorial/string/utf_eight.pyx b/docs/examples/tutorial/string/utf_eight.pyx index 7113947f4..654c51ae8 100644 --- a/docs/examples/tutorial/string/utf_eight.pyx +++ b/docs/examples/tutorial/string/utf_eight.pyx @@ -1,15 +1,15 @@ -from 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:
+from 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)
\ No newline at end of file diff --git a/docs/examples/userguide/buffer/matrix.py b/docs/examples/userguide/buffer/matrix.py new file mode 100644 index 000000000..0e431163d --- /dev/null +++ b/docs/examples/userguide/buffer/matrix.py @@ -0,0 +1,15 @@ +# 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) diff --git a/docs/examples/userguide/buffer/matrix.pyx b/docs/examples/userguide/buffer/matrix.pyx index abdb2d3c7..f2547f6c3 100644 --- a/docs/examples/userguide/buffer/matrix.pyx +++ b/docs/examples/userguide/buffer/matrix.pyx @@ -1,16 +1,15 @@ -# distutils: language = c++
-
-# matrix.pyx
-
-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)
+# 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) diff --git a/docs/examples/userguide/buffer/matrix_with_buffer.py b/docs/examples/userguide/buffer/matrix_with_buffer.py new file mode 100644 index 000000000..34ccc6591 --- /dev/null +++ b/docs/examples/userguide/buffer/matrix_with_buffer.py @@ -0,0 +1,48 @@ +# 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 diff --git a/docs/examples/userguide/buffer/matrix_with_buffer.pyx b/docs/examples/userguide/buffer/matrix_with_buffer.pyx index 985991cbe..fc2c160f3 100644 --- a/docs/examples/userguide/buffer/matrix_with_buffer.pyx +++ b/docs/examples/userguide/buffer/matrix_with_buffer.pyx @@ -1,45 +1,48 @@ -# 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 shape[2]
- cdef Py_ssize_t strides[2]
- 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] = <Py_ssize_t>( <char *>&(self.v[1])
- - <char *>&(self.v[0]))
- self.strides[0] = self.ncols * self.strides[1]
-
- buffer.buf = <char *>&(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
+# 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] = <Py_ssize_t>( <char *>&(self.v[1]) + - <char *>&(self.v[0])) + + + + self.strides[0] = self.ncols * self.strides[1] + + buffer.buf = <char *>&(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 diff --git a/docs/examples/userguide/buffer/view_count.py b/docs/examples/userguide/buffer/view_count.py new file mode 100644 index 000000000..6a0554abc --- /dev/null +++ b/docs/examples/userguide/buffer/view_count.py @@ -0,0 +1,30 @@ +# 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 diff --git a/docs/examples/userguide/buffer/view_count.pyx b/docs/examples/userguide/buffer/view_count.pyx index ee8d5085d..8c4b1d524 100644 --- a/docs/examples/userguide/buffer/view_count.pyx +++ b/docs/examples/userguide/buffer/view_count.pyx @@ -1,29 +1,30 @@ -# 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
\ No newline at end of file +# 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 diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle.py b/docs/examples/userguide/early_binding_for_speed/rectangle.py new file mode 100644 index 000000000..cd534d051 --- /dev/null +++ b/docs/examples/userguide/early_binding_for_speed/rectangle.py @@ -0,0 +1,22 @@ +@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() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle.pyx b/docs/examples/userguide/early_binding_for_speed/rectangle.pyx index ffc5593b0..b58f6534b 100644 --- a/docs/examples/userguide/early_binding_for_speed/rectangle.pyx +++ b/docs/examples/userguide/early_binding_for_speed/rectangle.pyx @@ -1,19 +1,22 @@ -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()
+ +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() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py new file mode 100644 index 000000000..ee2a14fb8 --- /dev/null +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py @@ -0,0 +1,26 @@ +@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() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx index 5502b4568..3b64d766b 100644 --- a/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx @@ -1,22 +1,26 @@ -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):
- 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):
- rect = Rectangle(x0, y0, x1, y1)
- return rect.area()
+ +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() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py new file mode 100644 index 000000000..670f340a4 --- /dev/null +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py @@ -0,0 +1,23 @@ +@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() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx index 01df3759f..53f2a8ad2 100644 --- a/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx @@ -1,19 +1,23 @@ -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):
- 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()
+ +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() diff --git a/docs/examples/userguide/extension_types/c_property.pyx b/docs/examples/userguide/extension_types/c_property.pyx new file mode 100644 index 000000000..b759ceec1 --- /dev/null +++ b/docs/examples/userguide/extension_types/c_property.pyx @@ -0,0 +1,20 @@ +cdef 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. diff --git a/docs/examples/userguide/extension_types/cheesy.py b/docs/examples/userguide/extension_types/cheesy.py new file mode 100644 index 000000000..0995c3993 --- /dev/null +++ b/docs/examples/userguide/extension_types/cheesy.py @@ -0,0 +1,36 @@ +import 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) diff --git a/docs/examples/userguide/extension_types/cheesy.pyx b/docs/examples/userguide/extension_types/cheesy.pyx new file mode 100644 index 000000000..2859d848f --- /dev/null +++ b/docs/examples/userguide/extension_types/cheesy.pyx @@ -0,0 +1,36 @@ + + + +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) diff --git a/docs/examples/userguide/extension_types/dataclass.py b/docs/examples/userguide/extension_types/dataclass.py new file mode 100644 index 000000000..d8ed68666 --- /dev/null +++ b/docs/examples/userguide/extension_types/dataclass.py @@ -0,0 +1,21 @@ +import cython +try: + import typing + import dataclasses +except ImportError: + pass # The modules don't actually have to exists for Cython to use them as annotations + +@cython.dataclasses.dataclass +@cython.cclass +class MyDataclass: + # fields can be declared using annotations + a: cython.int = 0 + b: double = cython.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] = [] diff --git a/docs/examples/userguide/extension_types/dataclass.pyx b/docs/examples/userguide/extension_types/dataclass.pyx new file mode 100644 index 000000000..b03d5f7b1 --- /dev/null +++ b/docs/examples/userguide/extension_types/dataclass.pyx @@ -0,0 +1,21 @@ +cimport cython +try: + import typing + import dataclasses +except ImportError: + pass # The modules don't actually have to exists for Cython to use them as annotations + + +@cython.dataclasses.dataclass +cdef class MyDataclass: + # fields can be declared using annotations + a: cython.int = 0 + b: double = cython.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] = [] diff --git a/docs/examples/userguide/extension_types/dict_animal.py b/docs/examples/userguide/extension_types/dict_animal.py new file mode 100644 index 000000000..a36dd3f89 --- /dev/null +++ b/docs/examples/userguide/extension_types/dict_animal.py @@ -0,0 +1,12 @@ +@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 diff --git a/docs/examples/userguide/extension_types/dict_animal.pyx b/docs/examples/userguide/extension_types/dict_animal.pyx index ab66900fe..575b835e9 100644 --- a/docs/examples/userguide/extension_types/dict_animal.pyx +++ b/docs/examples/userguide/extension_types/dict_animal.pyx @@ -1,11 +1,12 @@ -cdef class Animal:
-
- cdef int number_of_legs
- cdef dict __dict__
-
- def __cinit__(self, int number_of_legs):
- self.number_of_legs = number_of_legs
-
-
-dog = Animal(4)
-dog.has_tail = True
+ +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 diff --git a/docs/examples/userguide/extension_types/extendable_animal.py b/docs/examples/userguide/extension_types/extendable_animal.py new file mode 100644 index 000000000..2eef69460 --- /dev/null +++ b/docs/examples/userguide/extension_types/extendable_animal.py @@ -0,0 +1,15 @@ +@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 diff --git a/docs/examples/userguide/extension_types/extendable_animal.pyx b/docs/examples/userguide/extension_types/extendable_animal.pyx index fe53218b5..2ec165421 100644 --- a/docs/examples/userguide/extension_types/extendable_animal.pyx +++ b/docs/examples/userguide/extension_types/extendable_animal.pyx @@ -1,14 +1,15 @@ -cdef class Animal:
-
- cdef int number_of_legs
-
- def __cinit__(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
\ No newline at end of file + +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 diff --git a/docs/examples/userguide/extension_types/my_module.pyx b/docs/examples/userguide/extension_types/my_module.pyx index 6ceb057ca..fb0701c12 100644 --- a/docs/examples/userguide/extension_types/my_module.pyx +++ b/docs/examples/userguide/extension_types/my_module.pyx @@ -1,11 +1,11 @@ -from __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.")
+from __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.") diff --git a/docs/examples/userguide/extension_types/owned_pointer.py b/docs/examples/userguide/extension_types/owned_pointer.py new file mode 100644 index 000000000..1c235a883 --- /dev/null +++ b/docs/examples/userguide/extension_types/owned_pointer.py @@ -0,0 +1,17 @@ +import 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 diff --git a/docs/examples/userguide/extension_types/owned_pointer.pyx b/docs/examples/userguide/extension_types/owned_pointer.pyx new file mode 100644 index 000000000..98b61d91c --- /dev/null +++ b/docs/examples/userguide/extension_types/owned_pointer.pyx @@ -0,0 +1,17 @@ + +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 diff --git a/docs/examples/userguide/extension_types/penguin.py b/docs/examples/userguide/extension_types/penguin.py new file mode 100644 index 000000000..6db8eba16 --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin.py @@ -0,0 +1,14 @@ +import 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__() ! diff --git a/docs/examples/userguide/extension_types/penguin.pyx b/docs/examples/userguide/extension_types/penguin.pyx new file mode 100644 index 000000000..b890c9ffd --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin.pyx @@ -0,0 +1,14 @@ + + + +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__() ! diff --git a/docs/examples/userguide/extension_types/penguin2.py b/docs/examples/userguide/extension_types/penguin2.py new file mode 100644 index 000000000..063563d16 --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin2.py @@ -0,0 +1,12 @@ +import 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! diff --git a/docs/examples/userguide/extension_types/penguin2.pyx b/docs/examples/userguide/extension_types/penguin2.pyx new file mode 100644 index 000000000..726aeef8e --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin2.pyx @@ -0,0 +1,12 @@ +cimport 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! diff --git a/docs/examples/userguide/extension_types/pets.py b/docs/examples/userguide/extension_types/pets.py new file mode 100644 index 000000000..fc6497cb0 --- /dev/null +++ b/docs/examples/userguide/extension_types/pets.py @@ -0,0 +1,22 @@ +import 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() diff --git a/docs/examples/userguide/extension_types/pets.pyx b/docs/examples/userguide/extension_types/pets.pyx new file mode 100644 index 000000000..bb06e059d --- /dev/null +++ b/docs/examples/userguide/extension_types/pets.pyx @@ -0,0 +1,22 @@ + + +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() diff --git a/docs/examples/userguide/extension_types/python_access.py b/docs/examples/userguide/extension_types/python_access.py new file mode 100644 index 000000000..27478f50c --- /dev/null +++ b/docs/examples/userguide/extension_types/python_access.py @@ -0,0 +1,7 @@ +import 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') diff --git a/docs/examples/userguide/extension_types/python_access.pyx b/docs/examples/userguide/extension_types/python_access.pyx index 13e19091e..db11de63c 100644 --- a/docs/examples/userguide/extension_types/python_access.pyx +++ b/docs/examples/userguide/extension_types/python_access.pyx @@ -1,3 +1,7 @@ -cdef class Shrubbery:
- cdef public int width, height
- cdef readonly float depth
+ + + +cdef class Shrubbery: + cdef public int width, height + + cdef readonly float depth diff --git a/docs/examples/userguide/extension_types/shrubbery.py b/docs/examples/userguide/extension_types/shrubbery.py new file mode 100644 index 000000000..0e624a1d2 --- /dev/null +++ b/docs/examples/userguide/extension_types/shrubbery.py @@ -0,0 +1,12 @@ +@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.") diff --git a/docs/examples/userguide/extension_types/shrubbery.pyx b/docs/examples/userguide/extension_types/shrubbery.pyx index 9d2a5481a..8c4e58776 100644 --- a/docs/examples/userguide/extension_types/shrubbery.pyx +++ b/docs/examples/userguide/extension_types/shrubbery.pyx @@ -1,12 +1,12 @@ -from __future__ import print_function
-
-cdef class Shrubbery:
- cdef int width, 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.")
+from __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.") diff --git a/docs/examples/userguide/extension_types/shrubbery_2.py b/docs/examples/userguide/extension_types/shrubbery_2.py new file mode 100644 index 000000000..d6b722500 --- /dev/null +++ b/docs/examples/userguide/extension_types/shrubbery_2.py @@ -0,0 +1,10 @@ +import 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 diff --git a/docs/examples/userguide/extension_types/shrubbery_2.pyx b/docs/examples/userguide/extension_types/shrubbery_2.pyx index e0d8c45b5..4a7782735 100644 --- a/docs/examples/userguide/extension_types/shrubbery_2.pyx +++ b/docs/examples/userguide/extension_types/shrubbery_2.pyx @@ -1,8 +1,10 @@ -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
+ +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 diff --git a/docs/examples/userguide/extension_types/widen_shrubbery.py b/docs/examples/userguide/extension_types/widen_shrubbery.py new file mode 100644 index 000000000..f69f4dc96 --- /dev/null +++ b/docs/examples/userguide/extension_types/widen_shrubbery.py @@ -0,0 +1,6 @@ +import cython +from cython.cimports.my_module import Shrubbery + +@cython.cfunc +def widen_shrubbery(sh: Shrubbery, extra_width): + sh.width = sh.width + extra_width diff --git a/docs/examples/userguide/extension_types/widen_shrubbery.pyx b/docs/examples/userguide/extension_types/widen_shrubbery.pyx index aff3bd116..c6f58f00c 100644 --- a/docs/examples/userguide/extension_types/widen_shrubbery.pyx +++ b/docs/examples/userguide/extension_types/widen_shrubbery.pyx @@ -1,4 +1,6 @@ -from my_module cimport Shrubbery
-
-cdef widen_shrubbery(Shrubbery sh, extra_width):
- sh.width = sh.width + extra_width
+ +from my_module cimport Shrubbery + + +cdef widen_shrubbery(Shrubbery sh, extra_width): + sh.width = sh.width + extra_width diff --git a/docs/examples/userguide/extension_types/wrapper_class.py b/docs/examples/userguide/extension_types/wrapper_class.py new file mode 100644 index 000000000..b625ffebd --- /dev/null +++ b/docs/examples/userguide/extension_types/wrapper_class.py @@ -0,0 +1,65 @@ +import 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) diff --git a/docs/examples/userguide/extension_types/wrapper_class.pyx b/docs/examples/userguide/extension_types/wrapper_class.pyx new file mode 100644 index 000000000..e2a0c3ff2 --- /dev/null +++ b/docs/examples/userguide/extension_types/wrapper_class.pyx @@ -0,0 +1,65 @@ + +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 = <my_c_struct *>malloc(sizeof(my_c_struct)) + + if _ptr is NULL: + raise MemoryError + _ptr.a = 0 + _ptr.b = 0 + return WrapperClass.from_ptr(_ptr, owner=True) diff --git a/docs/examples/userguide/external_C_code/delorean.pyx b/docs/examples/userguide/external_C_code/delorean.pyx index 52c713616..9c6af9f87 100644 --- a/docs/examples/userguide/external_C_code/delorean.pyx +++ b/docs/examples/userguide/external_C_code/delorean.pyx @@ -1,9 +1,9 @@ -# delorean.pyx
-
-cdef public struct Vehicle:
- int speed
- float power
-
-cdef api void activate(Vehicle *v):
- if v.speed >= 88 and v.power >= 1.21:
- print("Time travel achieved")
\ No newline at end of file +# 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") diff --git a/docs/examples/userguide/external_C_code/marty.c b/docs/examples/userguide/external_C_code/marty.c index 8096ab19a..d7f5117f7 100644 --- a/docs/examples/userguide/external_C_code/marty.c +++ b/docs/examples/userguide/external_C_code/marty.c @@ -1,13 +1,14 @@ -# 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);
- Py_Finalize();
-}
+# 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(); +} diff --git a/docs/examples/userguide/external_C_code/platform_adaptation.pyx b/docs/examples/userguide/external_C_code/platform_adaptation.pyx new file mode 100644 index 000000000..0beece8f4 --- /dev/null +++ b/docs/examples/userguide/external_C_code/platform_adaptation.pyx @@ -0,0 +1,14 @@ +cdef extern from *: + """ + #if defined(_WIN32) || defined(MS_WINDOWS) || defined(_MSC_VER) + #include "stdlib.h" + #define myapp_sleep(m) _sleep(m) + #else + #include <unistd.h> + #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) diff --git a/docs/examples/userguide/external_C_code/struct_field_adaptation.h b/docs/examples/userguide/external_C_code/struct_field_adaptation.h new file mode 100644 index 000000000..ca55460f4 --- /dev/null +++ b/docs/examples/userguide/external_C_code/struct_field_adaptation.h @@ -0,0 +1,13 @@ +typedef 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 diff --git a/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx b/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx new file mode 100644 index 000000000..cff6bbdc2 --- /dev/null +++ b/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx @@ -0,0 +1,31 @@ +cdef 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)) diff --git a/docs/examples/userguide/external_C_code/c_code_docstring.pyx b/docs/examples/userguide/external_C_code/verbatim_c_code.pyx index 430e89c48..fb1937166 100644 --- a/docs/examples/userguide/external_C_code/c_code_docstring.pyx +++ b/docs/examples/userguide/external_C_code/verbatim_c_code.pyx @@ -1,9 +1,9 @@ -cdef 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)
+cdef 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) diff --git a/docs/examples/userguide/fusedtypes/char_or_float.py b/docs/examples/userguide/fusedtypes/char_or_float.py new file mode 100644 index 000000000..4930bf065 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/char_or_float.py @@ -0,0 +1,17 @@ +from __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)) diff --git a/docs/examples/userguide/fusedtypes/char_or_float.pyx b/docs/examples/userguide/fusedtypes/char_or_float.pyx index 6db746831..5a525431f 100644 --- a/docs/examples/userguide/fusedtypes/char_or_float.pyx +++ b/docs/examples/userguide/fusedtypes/char_or_float.pyx @@ -1,17 +1,17 @@ -from __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))
+from __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)) diff --git a/docs/examples/userguide/fusedtypes/conditional_gil.pyx b/docs/examples/userguide/fusedtypes/conditional_gil.pyx new file mode 100644 index 000000000..473132f2e --- /dev/null +++ b/docs/examples/userguide/fusedtypes/conditional_gil.pyx @@ -0,0 +1,15 @@ +cimport 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 diff --git a/docs/examples/userguide/fusedtypes/indexing.py b/docs/examples/userguide/fusedtypes/indexing.py new file mode 100644 index 000000000..054f6a742 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/indexing.py @@ -0,0 +1,25 @@ +import 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) diff --git a/docs/examples/userguide/fusedtypes/indexing.pyx b/docs/examples/userguide/fusedtypes/indexing.pyx new file mode 100644 index 000000000..16c7395f0 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/indexing.pyx @@ -0,0 +1,25 @@ +cimport 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) diff --git a/docs/examples/userguide/fusedtypes/pointer.py b/docs/examples/userguide/fusedtypes/pointer.py new file mode 100644 index 000000000..043074c79 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/pointer.py @@ -0,0 +1,13 @@ +my_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)) diff --git a/docs/examples/userguide/fusedtypes/pointer.pyx b/docs/examples/userguide/fusedtypes/pointer.pyx new file mode 100644 index 000000000..ad7758c16 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/pointer.pyx @@ -0,0 +1,13 @@ +ctypedef 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) diff --git a/docs/examples/userguide/fusedtypes/type_checking.py b/docs/examples/userguide/fusedtypes/type_checking.py new file mode 100644 index 000000000..bffe4b328 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/type_checking.py @@ -0,0 +1,28 @@ +bunch_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" diff --git a/docs/examples/userguide/fusedtypes/type_checking.pyx b/docs/examples/userguide/fusedtypes/type_checking.pyx new file mode 100644 index 000000000..7bd359739 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/type_checking.pyx @@ -0,0 +1,28 @@ +cimport 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(<int> 5, b'm') # will print "i is an int" and "s is a string" +myfunc(<long> 5, 3) # will print "i is a long" +myfunc(<short> 5, 3) # will print "i is a short" diff --git a/docs/examples/userguide/language_basics/casting_python.pxd b/docs/examples/userguide/language_basics/casting_python.pxd new file mode 100644 index 000000000..fa3d46030 --- /dev/null +++ b/docs/examples/userguide/language_basics/casting_python.pxd @@ -0,0 +1,2 @@ +cdef extern from *: + ctypedef Py_ssize_t Py_intptr_t diff --git a/docs/examples/userguide/language_basics/casting_python.py b/docs/examples/userguide/language_basics/casting_python.py new file mode 100644 index 000000000..1c02c461c --- /dev/null +++ b/docs/examples/userguide/language_basics/casting_python.py @@ -0,0 +1,22 @@ +from 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" diff --git a/docs/examples/userguide/language_basics/casting_python.pyx b/docs/examples/userguide/language_basics/casting_python.pyx index fe84acde2..4cc819ae3 100644 --- a/docs/examples/userguide/language_basics/casting_python.pyx +++ b/docs/examples/userguide/language_basics/casting_python.pyx @@ -1,19 +1,19 @@ -from cpython.ref cimport PyObject
-
-cdef extern from *:
- ctypedef Py_ssize_t Py_intptr_t
-
-python_string = "foo"
-
-cdef void* ptr = <void*>python_string
-cdef Py_intptr_t adress_in_c = <Py_intptr_t>ptr
-address_from_void = adress_in_c # address_from_void is a python int
-
-cdef PyObject* ptr2 = <PyObject*>python_string
-cdef Py_intptr_t address_in_c2 = <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(<object>ptr) # Prints "foo"
-print(<object>ptr2) # prints "foo"
+from cpython.ref cimport PyObject + +cdef extern from *: + ctypedef Py_ssize_t Py_intptr_t + +python_string = "foo" + +cdef void* ptr = <void*>python_string +cdef Py_intptr_t adress_in_c = <Py_intptr_t>ptr +address_from_void = adress_in_c # address_from_void is a python int + +cdef PyObject* ptr2 = <PyObject*>python_string +cdef Py_intptr_t address_in_c2 = <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(<object>ptr) # Prints "foo" +print(<object>ptr2) # prints "foo" diff --git a/docs/examples/userguide/language_basics/cdef_block.pyx b/docs/examples/userguide/language_basics/cdef_block.pyx index 4132aeee1..c0c303029 100644 --- a/docs/examples/userguide/language_basics/cdef_block.pyx +++ b/docs/examples/userguide/language_basics/cdef_block.pyx @@ -1,12 +1,12 @@ -from __future__ import print_function
-
-cdef:
- struct Spam:
- int tons
-
- int i
- float a
- Spam *p
-
- void f(Spam *s):
- print(s.tons, "Tons of spam")
+from __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") diff --git a/docs/examples/userguide/language_basics/compile_time.pyx b/docs/examples/userguide/language_basics/compile_time.pyx index fcaf75f29..f302dd241 100644 --- a/docs/examples/userguide/language_basics/compile_time.pyx +++ b/docs/examples/userguide/language_basics/compile_time.pyx @@ -1,9 +1,9 @@ -from __future__ import print_function
-
-DEF FavouriteFood = u"spam"
-DEF ArraySize = 42
-DEF OtherArraySize = 2 * ArraySize + 17
-
-cdef int a1[ArraySize]
-cdef int a2[OtherArraySize]
-print("I like", FavouriteFood)
\ No newline at end of file +from __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) diff --git a/docs/examples/userguide/language_basics/struct_union_enum.pyx b/docs/examples/userguide/language_basics/enum.pyx index ccbc28d42..1b5f5d614 100644 --- a/docs/examples/userguide/language_basics/struct_union_enum.pyx +++ b/docs/examples/userguide/language_basics/enum.pyx @@ -1,16 +1,11 @@ -cdef struct Grail:
- int age
- float volume
-
-cdef union Food:
- char *spam
- float *eggs
-
-cdef enum CheeseType:
- cheddar, edam,
- camembert
-
-cdef enum CheeseState:
- hard = 1
- soft = 2
- runny = 3
+cdef enum CheeseType: + cheddar, edam, + camembert + +cdef enum CheeseState: + hard = 1 + soft = 2 + runny = 3 + +print(CheeseType.cheddar) +print(CheeseState.hard) diff --git a/docs/examples/userguide/language_basics/function_pointer.pyx b/docs/examples/userguide/language_basics/function_pointer.pyx new file mode 100644 index 000000000..b345c62b4 --- /dev/null +++ b/docs/examples/userguide/language_basics/function_pointer.pyx @@ -0,0 +1,8 @@ +cdef int(*ptr_add)(int, int) + +cdef int add(int a, int b): + return a + b + +ptr_add = add + +print(ptr_add(1, 3)) diff --git a/docs/examples/userguide/language_basics/function_pointer_struct.pyx b/docs/examples/userguide/language_basics/function_pointer_struct.pyx new file mode 100644 index 000000000..5ef618961 --- /dev/null +++ b/docs/examples/userguide/language_basics/function_pointer_struct.pyx @@ -0,0 +1,9 @@ +cdef 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)) diff --git a/docs/examples/userguide/language_basics/kwargs_1.pyx b/docs/examples/userguide/language_basics/kwargs_1.pyx index e5e18c008..1117c967c 100644 --- a/docs/examples/userguide/language_basics/kwargs_1.pyx +++ b/docs/examples/userguide/language_basics/kwargs_1.pyx @@ -1,6 +1,6 @@ -def 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)
+def 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) diff --git a/docs/examples/userguide/language_basics/kwargs_2.pyx b/docs/examples/userguide/language_basics/kwargs_2.pyx index a2c639ea6..902df694c 100644 --- a/docs/examples/userguide/language_basics/kwargs_2.pyx +++ b/docs/examples/userguide/language_basics/kwargs_2.pyx @@ -1,5 +1,5 @@ -def g(a, b, *, c, d):
- ...
-
-# We cannot call g with less verbosity than this.
-foo = g(4.0, "something", c=68, d="other")
+def g(a, b, *, c, d): + ... + +# We cannot call g with less verbosity than this. +foo = g(4.0, "something", c=68, d="other") diff --git a/docs/examples/userguide/language_basics/open_file.py b/docs/examples/userguide/language_basics/open_file.py new file mode 100644 index 000000000..ad3ae0374 --- /dev/null +++ b/docs/examples/userguide/language_basics/open_file.py @@ -0,0 +1,19 @@ +from 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) diff --git a/docs/examples/userguide/language_basics/open_file.pyx b/docs/examples/userguide/language_basics/open_file.pyx index 19eac104e..ad45fc8c4 100644 --- a/docs/examples/userguide/language_basics/open_file.pyx +++ b/docs/examples/userguide/language_basics/open_file.pyx @@ -1,18 +1,18 @@ -from 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 = <double *> malloc(number * sizeof(double))
- if not my_array: # same as 'is NULL' above
- raise MemoryError()
- ...
- free(my_array)
+from 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 = <double *> malloc(number * sizeof(double)) + if not my_array: # same as 'is NULL' above + raise MemoryError() + ... + free(my_array) diff --git a/docs/examples/userguide/language_basics/optional_subclassing.py b/docs/examples/userguide/language_basics/optional_subclassing.py new file mode 100644 index 000000000..480ae100b --- /dev/null +++ b/docs/examples/userguide/language_basics/optional_subclassing.py @@ -0,0 +1,19 @@ +from __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) diff --git a/docs/examples/userguide/language_basics/optional_subclassing.pyx b/docs/examples/userguide/language_basics/optional_subclassing.pyx index f655cadf3..b2a3d4dec 100644 --- a/docs/examples/userguide/language_basics/optional_subclassing.pyx +++ b/docs/examples/userguide/language_basics/optional_subclassing.pyx @@ -1,13 +1,19 @@ -from __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)
+from __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) diff --git a/docs/examples/userguide/language_basics/override.py b/docs/examples/userguide/language_basics/override.py new file mode 100644 index 000000000..f9e0be83f --- /dev/null +++ b/docs/examples/userguide/language_basics/override.py @@ -0,0 +1,17 @@ +from __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") diff --git a/docs/examples/userguide/language_basics/override.pyx b/docs/examples/userguide/language_basics/override.pyx index 873a7ec6e..1a7ceefb7 100644 --- a/docs/examples/userguide/language_basics/override.pyx +++ b/docs/examples/userguide/language_basics/override.pyx @@ -1,13 +1,17 @@ -from __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")
+from __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") diff --git a/docs/examples/userguide/language_basics/parameter_refcount.py b/docs/examples/userguide/language_basics/parameter_refcount.py new file mode 100644 index 000000000..2b25915ba --- /dev/null +++ b/docs/examples/userguide/language_basics/parameter_refcount.py @@ -0,0 +1,23 @@ +from __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)) diff --git a/docs/examples/userguide/language_basics/parameter_refcount.pyx b/docs/examples/userguide/language_basics/parameter_refcount.pyx new file mode 100644 index 000000000..6fe3ffadd --- /dev/null +++ b/docs/examples/userguide/language_basics/parameter_refcount.pyx @@ -0,0 +1,23 @@ +from __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(<PyObject *>python_dict) diff --git a/docs/examples/userguide/language_basics/struct.py b/docs/examples/userguide/language_basics/struct.py new file mode 100644 index 000000000..32b6b252a --- /dev/null +++ b/docs/examples/userguide/language_basics/struct.py @@ -0,0 +1,7 @@ +Grail = cython.struct( + age=cython.int, + volume=cython.float) + +def main(): + grail: Grail = Grail(5, 3.0) + print(grail.age, grail.volume) diff --git a/docs/examples/userguide/language_basics/struct.pyx b/docs/examples/userguide/language_basics/struct.pyx new file mode 100644 index 000000000..3ef79172b --- /dev/null +++ b/docs/examples/userguide/language_basics/struct.pyx @@ -0,0 +1,7 @@ +cdef struct Grail: + int age + float volume + +def main(): + cdef Grail grail = Grail(5, 3.0) + print(grail.age, grail.volume) diff --git a/docs/examples/userguide/language_basics/union.py b/docs/examples/userguide/language_basics/union.py new file mode 100644 index 000000000..efcda358b --- /dev/null +++ b/docs/examples/userguide/language_basics/union.py @@ -0,0 +1,9 @@ +Food = 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]) diff --git a/docs/examples/userguide/language_basics/union.pyx b/docs/examples/userguide/language_basics/union.pyx new file mode 100644 index 000000000..e05f63fcc --- /dev/null +++ b/docs/examples/userguide/language_basics/union.pyx @@ -0,0 +1,9 @@ +cdef 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]) diff --git a/docs/examples/userguide/memoryviews/add_one.pyx b/docs/examples/userguide/memoryviews/add_one.pyx index cbe65b069..7de7a1274 100644 --- a/docs/examples/userguide/memoryviews/add_one.pyx +++ b/docs/examples/userguide/memoryviews/add_one.pyx @@ -1,12 +1,12 @@ -import 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)
+import 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) diff --git a/docs/examples/userguide/memoryviews/copy.pyx b/docs/examples/userguide/memoryviews/copy.pyx index 9f000a3b4..9eb1307bf 100644 --- a/docs/examples/userguide/memoryviews/copy.pyx +++ b/docs/examples/userguide/memoryviews/copy.pyx @@ -1,12 +1,12 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/memoryviews/custom_dtype.pyx b/docs/examples/userguide/memoryviews/custom_dtype.pyx new file mode 100644 index 000000000..d54d7bbc4 --- /dev/null +++ b/docs/examples/userguide/memoryviews/custom_dtype.pyx @@ -0,0 +1,26 @@ +import 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 diff --git a/docs/examples/userguide/memoryviews/memory_layout.pyx b/docs/examples/userguide/memoryviews/memory_layout.pyx index 5c2818dc0..8f9d8a23c 100644 --- a/docs/examples/userguide/memoryviews/memory_layout.pyx +++ b/docs/examples/userguide/memoryviews/memory_layout.pyx @@ -1,11 +1,11 @@ -from cython cimport view
-
-# 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
+from cython cimport view + +# 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 diff --git a/docs/examples/userguide/memoryviews/memory_layout_2.pyx b/docs/examples/userguide/memoryviews/memory_layout_2.pyx index 1cb039dd4..71d2cceb2 100644 --- a/docs/examples/userguide/memoryviews/memory_layout_2.pyx +++ b/docs/examples/userguide/memoryviews/memory_layout_2.pyx @@ -1,6 +1,6 @@ -from cython cimport view
-
-# VALID
-cdef int[::view.indirect, ::1, :] a
-cdef int[::view.indirect, :, ::1] b
-cdef int[::view.indirect_contiguous, ::1, :] c
+from cython cimport view + +# VALID +cdef int[::view.indirect, ::1, :] a +cdef int[::view.indirect, :, ::1] b +cdef int[::view.indirect_contiguous, ::1, :] c diff --git a/docs/examples/userguide/memoryviews/memview_to_c.pyx b/docs/examples/userguide/memoryviews/memview_to_c.pyx index c5abc19ac..ad6190cc7 100644 --- a/docs/examples/userguide/memoryviews/memview_to_c.pyx +++ b/docs/examples/userguide/memoryviews/memview_to_c.pyx @@ -1,28 +1,28 @@ -cdef 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.
+cdef 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. diff --git a/docs/examples/userguide/memoryviews/not_none.pyx b/docs/examples/userguide/memoryviews/not_none.pyx index ae3b6c936..f6c0fed8a 100644 --- a/docs/examples/userguide/memoryviews/not_none.pyx +++ b/docs/examples/userguide/memoryviews/not_none.pyx @@ -1,11 +1,11 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/memoryviews/np_flag_const.pyx b/docs/examples/userguide/memoryviews/np_flag_const.pyx index 03f0ea4a3..54eb3d338 100644 --- a/docs/examples/userguide/memoryviews/np_flag_const.pyx +++ b/docs/examples/userguide/memoryviews/np_flag_const.pyx @@ -1,7 +1,7 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/memoryviews/quickstart.pyx b/docs/examples/userguide/memoryviews/quickstart.pyx index 58335c0cf..a313859d9 100644 --- a/docs/examples/userguide/memoryviews/quickstart.pyx +++ b/docs/examples/userguide/memoryviews/quickstart.pyx @@ -6,7 +6,7 @@ narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3)) cdef int [:, :, :] narr_view = narr # Memoryview on a C array -cdef int carr[3][3][3] +cdef int[3][3][3] carr cdef int [:, :, :] carr_view = carr # Memoryview on a Cython array diff --git a/docs/examples/userguide/memoryviews/slicing.pyx b/docs/examples/userguide/memoryviews/slicing.pyx index a6134aae2..d7bd896e6 100644 --- a/docs/examples/userguide/memoryviews/slicing.pyx +++ b/docs/examples/userguide/memoryviews/slicing.pyx @@ -1,10 +1,10 @@ -import 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, ...]
+import 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, ...] diff --git a/docs/examples/userguide/memoryviews/transpose.pyx b/docs/examples/userguide/memoryviews/transpose.pyx index 7611529c2..8a53f7140 100644 --- a/docs/examples/userguide/memoryviews/transpose.pyx +++ b/docs/examples/userguide/memoryviews/transpose.pyx @@ -1,6 +1,6 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/memoryviews/view_string.pyx b/docs/examples/userguide/memoryviews/view_string.pyx index 7aace3ea5..9fdeae053 100644 --- a/docs/examples/userguide/memoryviews/view_string.pyx +++ b/docs/examples/userguide/memoryviews/view_string.pyx @@ -1,9 +1,9 @@ -cdef 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
+cdef 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 diff --git a/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx b/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx index 2fc87907d..af5ef9071 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx @@ -1,44 +1,44 @@ -# 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
+# 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 diff --git a/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx b/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx index 98a683de7..3882c289d 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx @@ -1,34 +1,34 @@ -# 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
+# 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 diff --git a/docs/examples/userguide/numpy_tutorial/compute_memview.pyx b/docs/examples/userguide/numpy_tutorial/compute_memview.pyx index d264e773a..166cd6df3 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_memview.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_memview.pyx @@ -1,34 +1,34 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/numpy_tutorial/compute_prange.pyx b/docs/examples/userguide/numpy_tutorial/compute_prange.pyx index c00d2261b..562c73070 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_prange.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_prange.pyx @@ -1,53 +1,53 @@ -# 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
+# 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 diff --git a/docs/examples/userguide/numpy_tutorial/compute_py.py b/docs/examples/userguide/numpy_tutorial/compute_py.py index 00bcf244c..4a5f90b4d 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_py.py +++ b/docs/examples/userguide/numpy_tutorial/compute_py.py @@ -1,28 +1,28 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/numpy_tutorial/compute_typed.pyx b/docs/examples/userguide/numpy_tutorial/compute_typed.pyx index 8218aa709..cccc1aa3b 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_typed.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_typed.pyx @@ -1,50 +1,50 @@ -import 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
+import 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 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc.py b/docs/examples/userguide/numpy_ufuncs/ufunc.py new file mode 100644 index 000000000..874183c84 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc.py @@ -0,0 +1,8 @@ +# 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 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc.pyx b/docs/examples/userguide/numpy_ufuncs/ufunc.pyx new file mode 100644 index 000000000..b29c071e1 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc.pyx @@ -0,0 +1,8 @@ +# 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 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py new file mode 100644 index 000000000..b3f4fb6de --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py @@ -0,0 +1,7 @@ +# 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 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx new file mode 100644 index 000000000..61127261c --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx @@ -0,0 +1,7 @@ +# tag: numpy +cimport cython + + +@cython.ufunc +cdef (int, int) add_one_add_two(int x): + return x+1, x+2 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py new file mode 100644 index 000000000..01cc3bc57 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py @@ -0,0 +1,7 @@ +# tag: numpy +import cython + +@cython.ufunc +@cython.cfunc +def generic_add_one(x: cython.numeric) -> cython.numeric: + return x+1 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx new file mode 100644 index 000000000..3baf58136 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx @@ -0,0 +1,7 @@ +# tag: numpy +cimport cython + + +@cython.ufunc +cdef cython.numeric generic_add_one(cython.numeric x): + return x+1 diff --git a/docs/examples/userguide/parallelism/breaking_loop.py b/docs/examples/userguide/parallelism/breaking_loop.py new file mode 100644 index 000000000..00d0225b5 --- /dev/null +++ b/docs/examples/userguide/parallelism/breaking_loop.py @@ -0,0 +1,15 @@ +from 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 diff --git a/docs/examples/userguide/parallelism/breaking_loop.pyx b/docs/examples/userguide/parallelism/breaking_loop.pyx index d11b179d9..e7445082d 100644 --- a/docs/examples/userguide/parallelism/breaking_loop.pyx +++ b/docs/examples/userguide/parallelism/breaking_loop.pyx @@ -1,13 +1,15 @@ -from cython.parallel import prange
-
-cdef int func(Py_ssize_t n):
- 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
+from 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 diff --git a/docs/examples/userguide/parallelism/cimport_openmp.py b/docs/examples/userguide/parallelism/cimport_openmp.py new file mode 100644 index 000000000..9288a4381 --- /dev/null +++ b/docs/examples/userguide/parallelism/cimport_openmp.py @@ -0,0 +1,11 @@ +# 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() + # ... diff --git a/docs/examples/userguide/parallelism/cimport_openmp.pyx b/docs/examples/userguide/parallelism/cimport_openmp.pyx index 235ee10bc..54d5f18db 100644 --- a/docs/examples/userguide/parallelism/cimport_openmp.pyx +++ b/docs/examples/userguide/parallelism/cimport_openmp.pyx @@ -1,13 +1,11 @@ -# tag: openmp
-# You can ignore the previous line.
-# It's for internal testing of the Cython documentation.
-
-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()
- # ...
+# 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() + # ... diff --git a/docs/examples/userguide/parallelism/memoryview_sum.py b/docs/examples/userguide/parallelism/memoryview_sum.py new file mode 100644 index 000000000..6cff5d587 --- /dev/null +++ b/docs/examples/userguide/parallelism/memoryview_sum.py @@ -0,0 +1,7 @@ +from 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] diff --git a/docs/examples/userguide/parallelism/memoryview_sum.pyx b/docs/examples/userguide/parallelism/memoryview_sum.pyx new file mode 100644 index 000000000..bdc1c9feb --- /dev/null +++ b/docs/examples/userguide/parallelism/memoryview_sum.pyx @@ -0,0 +1,7 @@ +from 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] diff --git a/docs/examples/userguide/parallelism/parallel.py b/docs/examples/userguide/parallelism/parallel.py new file mode 100644 index 000000000..0fb62d10f --- /dev/null +++ b/docs/examples/userguide/parallelism/parallel.py @@ -0,0 +1,30 @@ +from 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) diff --git a/docs/examples/userguide/parallelism/parallel.pyx b/docs/examples/userguide/parallelism/parallel.pyx new file mode 100644 index 000000000..2a952d537 --- /dev/null +++ b/docs/examples/userguide/parallelism/parallel.pyx @@ -0,0 +1,30 @@ +from 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 = <int *> 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) diff --git a/docs/examples/userguide/parallelism/setup_py.py b/docs/examples/userguide/parallelism/setup_py.py new file mode 100644 index 000000000..85a037dc5 --- /dev/null +++ b/docs/examples/userguide/parallelism/setup_py.py @@ -0,0 +1,16 @@ +from 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), +) diff --git a/docs/examples/userguide/parallelism/setup.py b/docs/examples/userguide/parallelism/setup_pyx.py index 0fb6026f7..fe6d0a64c 100644 --- a/docs/examples/userguide/parallelism/setup.py +++ b/docs/examples/userguide/parallelism/setup_pyx.py @@ -1,17 +1,16 @@ -from distutils.core import setup
-from distutils.extension import Extension
-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),
-)
+from 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), +) diff --git a/docs/examples/userguide/parallelism/simple_sum.py b/docs/examples/userguide/parallelism/simple_sum.py new file mode 100644 index 000000000..f952a8556 --- /dev/null +++ b/docs/examples/userguide/parallelism/simple_sum.py @@ -0,0 +1,10 @@ +from 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) diff --git a/docs/examples/userguide/parallelism/simple_sum.pyx b/docs/examples/userguide/parallelism/simple_sum.pyx index 83b862ea6..929a988e5 100644 --- a/docs/examples/userguide/parallelism/simple_sum.pyx +++ b/docs/examples/userguide/parallelism/simple_sum.pyx @@ -1,10 +1,10 @@ -from 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)
+from 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) diff --git a/docs/examples/userguide/sharing_declarations/landscaping.py b/docs/examples/userguide/sharing_declarations/landscaping.py new file mode 100644 index 000000000..2d2c4b5b7 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/landscaping.py @@ -0,0 +1,7 @@ +from cython.cimports.shrubbing import Shrubbery +import shrubbing + +def main(): + sh: Shrubbery + sh = shrubbing.standard_shrubbery() + print("Shrubbery size is", sh.width, 'x', sh.length) diff --git a/docs/examples/userguide/sharing_declarations/landscaping.pyx b/docs/examples/userguide/sharing_declarations/landscaping.pyx index c54e74fd0..afc999e53 100644 --- a/docs/examples/userguide/sharing_declarations/landscaping.pyx +++ b/docs/examples/userguide/sharing_declarations/landscaping.pyx @@ -1,7 +1,7 @@ -cimport shrubbing
-import shrubbing
-
-def main():
- cdef shrubbing.Shrubbery sh
- sh = shrubbing.standard_shrubbery()
- print("Shrubbery size is", sh.width, 'x', sh.length)
+cimport shrubbing +import shrubbing + +def main(): + cdef shrubbing.Shrubbery sh + sh = shrubbing.standard_shrubbery() + print("Shrubbery size is", sh.width, 'x', sh.length) diff --git a/docs/examples/userguide/sharing_declarations/lunch.py b/docs/examples/userguide/sharing_declarations/lunch.py new file mode 100644 index 000000000..df56913eb --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/lunch.py @@ -0,0 +1,5 @@ +import cython +from cython.cimports.c_lunch import eject_tomato as c_eject_tomato + +def eject_tomato(speed: cython.float): + c_eject_tomato(speed) diff --git a/docs/examples/userguide/sharing_declarations/lunch.pyx b/docs/examples/userguide/sharing_declarations/lunch.pyx index 7bb2d4756..fea5e4c87 100644 --- a/docs/examples/userguide/sharing_declarations/lunch.pyx +++ b/docs/examples/userguide/sharing_declarations/lunch.pyx @@ -1,4 +1,5 @@ -cimport c_lunch
-
-def eject_tomato(float speed):
- c_lunch.eject_tomato(speed)
+ +cimport c_lunch + +def eject_tomato(float speed): + c_lunch.eject_tomato(speed) diff --git a/docs/examples/userguide/sharing_declarations/restaurant.py b/docs/examples/userguide/sharing_declarations/restaurant.py new file mode 100644 index 000000000..b4bdb2eba --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/restaurant.py @@ -0,0 +1,12 @@ +import 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}') diff --git a/docs/examples/userguide/sharing_declarations/restaurant.pyx b/docs/examples/userguide/sharing_declarations/restaurant.pyx index 0c1dbf5c0..f556646dc 100644 --- a/docs/examples/userguide/sharing_declarations/restaurant.pyx +++ b/docs/examples/userguide/sharing_declarations/restaurant.pyx @@ -1,12 +1,12 @@ -from __future__ import print_function
-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}')
+ +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}') diff --git a/docs/examples/userguide/sharing_declarations/setup_py.py b/docs/examples/userguide/sharing_declarations/setup_py.py new file mode 100644 index 000000000..45ded0ff4 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/setup_py.py @@ -0,0 +1,4 @@ +from setuptools import setup +from Cython.Build import cythonize + +setup(ext_modules=cythonize(["landscaping.py", "shrubbing.py"])) diff --git a/docs/examples/userguide/sharing_declarations/setup.py b/docs/examples/userguide/sharing_declarations/setup_pyx.py index 64804f97d..505b53e9d 100644 --- a/docs/examples/userguide/sharing_declarations/setup.py +++ b/docs/examples/userguide/sharing_declarations/setup_pyx.py @@ -1,4 +1,4 @@ -from distutils.core import setup
-from Cython.Build import cythonize
-
-setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"]))
+from setuptools import setup +from Cython.Build import cythonize + +setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"])) diff --git a/docs/examples/userguide/sharing_declarations/shrubbing.py b/docs/examples/userguide/sharing_declarations/shrubbing.py new file mode 100644 index 000000000..27e20d631 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/shrubbing.py @@ -0,0 +1,10 @@ +import 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) diff --git a/docs/examples/userguide/sharing_declarations/shrubbing.pyx b/docs/examples/userguide/sharing_declarations/shrubbing.pyx index a8b70dae2..91235e5ec 100644 --- a/docs/examples/userguide/sharing_declarations/shrubbing.pyx +++ b/docs/examples/userguide/sharing_declarations/shrubbing.pyx @@ -1,7 +1,10 @@ -cdef class Shrubbery:
- def __cinit__(self, int w, int l):
- self.width = w
- self.length = l
-
-def standard_shrubbery():
- return Shrubbery(3, 7)
+ + + +cdef class Shrubbery: + def __init__(self, int w, int l): + self.width = w + self.length = l + +def standard_shrubbery(): + return Shrubbery(3, 7) diff --git a/docs/examples/userguide/sharing_declarations/spammery.py b/docs/examples/userguide/sharing_declarations/spammery.py new file mode 100644 index 000000000..88554be4a --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/spammery.py @@ -0,0 +1,10 @@ +import 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) diff --git a/docs/examples/userguide/sharing_declarations/spammery.pyx b/docs/examples/userguide/sharing_declarations/spammery.pyx index f65cf63d7..da11e737e 100644 --- a/docs/examples/userguide/sharing_declarations/spammery.pyx +++ b/docs/examples/userguide/sharing_declarations/spammery.pyx @@ -1,11 +1,10 @@ -from __future__ import print_function
-
-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)
+ +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) diff --git a/docs/examples/userguide/sharing_declarations/volume.pxd b/docs/examples/userguide/sharing_declarations/volume.pxd index 598efd922..a30c68e52 100644 --- a/docs/examples/userguide/sharing_declarations/volume.pxd +++ b/docs/examples/userguide/sharing_declarations/volume.pxd @@ -1 +1 @@ -cdef float cube(float)
+cdef float cube(float x) diff --git a/docs/examples/userguide/sharing_declarations/volume.py b/docs/examples/userguide/sharing_declarations/volume.py new file mode 100644 index 000000000..1f6ff9c72 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/volume.py @@ -0,0 +1,2 @@ +def cube(x): + return x * x * x diff --git a/docs/examples/userguide/sharing_declarations/volume.pyx b/docs/examples/userguide/sharing_declarations/volume.pyx index 0fbab6fb7..0476b6068 100644 --- a/docs/examples/userguide/sharing_declarations/volume.pyx +++ b/docs/examples/userguide/sharing_declarations/volume.pyx @@ -1,2 +1,2 @@ -cdef float cube(float x):
- return x * x * x
+cdef float cube(float x): + return x * x * x diff --git a/docs/examples/userguide/special_methods/total_ordering.py b/docs/examples/userguide/special_methods/total_ordering.py new file mode 100644 index 000000000..7d164d6df --- /dev/null +++ b/docs/examples/userguide/special_methods/total_ordering.py @@ -0,0 +1,13 @@ +import cython +@cython.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 diff --git a/docs/examples/userguide/special_methods/total_ordering.pyx b/docs/examples/userguide/special_methods/total_ordering.pyx new file mode 100644 index 000000000..06d2ccef7 --- /dev/null +++ b/docs/examples/userguide/special_methods/total_ordering.pyx @@ -0,0 +1,13 @@ +import cython + +@cython.total_ordering +cdef class ExtGe: + cdef int x + + def __ge__(self, other): + if not isinstance(other, ExtGe): + return NotImplemented + return self.x >= (<ExtGe>other).x + + def __eq__(self, other): + return isinstance(other, ExtGe) and self.x == (<ExtGe>other).x diff --git a/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd b/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd index 68f949122..a26e69b51 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd +++ b/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd @@ -1,7 +1,7 @@ cdef extern from "Rectangle.cpp":
pass
-# Decalre the class with cdef
+# Declare the class with cdef
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
Rectangle() except +
diff --git a/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx b/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx index 24192bf96..d074fa5ab 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx @@ -1,12 +1,12 @@ -# 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
+# 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 diff --git a/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx b/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx index 13c75426e..35d064fdd 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx @@ -1,7 +1,7 @@ -# distutils: language = c++
-
-cdef extern from "<algorithm>" namespace "std":
- T max[T](T a, T b)
-
-print(max[long](3, 4))
-print(max(1.5, 2.5)) # simple template argument deduction
+# distutils: language = c++ + +cdef extern from "<algorithm>" namespace "std": + T max[T](T a, T b) + +print(max[long](3, 4)) +print(max(1.5, 2.5)) # simple template argument deduction diff --git a/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx b/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx index ea0007e6a..cdce8910f 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx @@ -1,12 +1,12 @@ -# 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]
+# 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] diff --git a/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx b/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx index e53f39b98..c5c764468 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx @@ -1,17 +1,17 @@ -# distutils: language = c++
-
-cdef extern from "<vector>" 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<int>::iterator
+# distutils: language = c++ + +cdef extern from "<vector>" 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<int>::iterator diff --git a/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx b/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx index 30bdb7bcb..b4be72c16 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx @@ -1,19 +1,19 @@ -# 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 = <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'
+# 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 = <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' diff --git a/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx b/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx index e7c4423ef..d8eec16ef 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx @@ -8,7 +8,7 @@ from Rectangle cimport Rectangle cdef class PyRectangle: cdef Rectangle c_rect # Hold a C++ instance which we're wrapping - def __cinit__(self, int x0, int y0, int x1, int y1): + def __init__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): diff --git a/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx b/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx index 508e55dc6..ec4b34ab4 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx @@ -1,12 +1,18 @@ -# 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, int x0, int y0, int x1, int y1):
- self.c_rect = new Rectangle(x0, y0, x1, y1)
-
- def __dealloc__(self):
- del self.c_rect
+# 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 diff --git a/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx b/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx index 1bac30dec..441292ace 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx @@ -5,7 +5,7 @@ from Rectangle cimport Rectangle cdef class PyRectangle: cdef Rectangle c_rect - def __cinit__(self, int x0, int y0, int x1, int y1): + def __init__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): diff --git a/docs/examples/userguide/wrapping_CPlusPlus/setup.py b/docs/examples/userguide/wrapping_CPlusPlus/setup.py index 0c89865d6..09009d28d 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/setup.py +++ b/docs/examples/userguide/wrapping_CPlusPlus/setup.py @@ -1,4 +1,4 @@ -from distutils.core import setup +from setuptools import setup from Cython.Build import cythonize diff --git a/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx b/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx index 8e7383ca2..4ff232b82 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx @@ -1,30 +1,30 @@ -# distutils: language = c++
-
-# import dereference and increment operators
-from cython.operator cimport dereference as deref, preincrement as inc
-
-cdef extern from "<vector>" 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
+# distutils: language = c++ + +# import dereference and increment operators +from cython.operator cimport dereference as deref, preincrement as inc + +cdef extern from "<vector>" 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 diff --git a/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx b/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx index d7fdfc969..f1697e1ec 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx @@ -1,15 +1,15 @@ -# 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)
+# 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) diff --git a/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx b/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx index 592e83ad9..4cdf12fc2 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx @@ -1,17 +1,17 @@ -# 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
+# 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 |