Commit 0e289608 authored by scoder's avatar scoder Committed by GitHub

Merge branch 'master' into broken_and_redirect_links

parents 6ff0ce3c d460da83
......@@ -70,6 +70,9 @@ Bugs fixed
generated an invalid C function call to the (non-existent) base type implementation.
(Github issue #2309)
* Exception catching based on a non-literal (runtime) tuple could fail to match the
exception. (Github issue #2425)
0.28.3 (2018-05-27)
===================
......@@ -2180,9 +2183,9 @@ Features added
* GDB support. http://docs.cython.org/src/userguide/debugging.html
* A new build system with support for inline distutils directives, correct dependency tracking, and parallel compilation. http://wiki.cython.org/enhancements/distutils_preprocessing
* A new build system with support for inline distutils directives, correct dependency tracking, and parallel compilation. https://github.com/cython/cython/wiki/enhancements-distutils_preprocessing
* Support for dynamic compilation at runtime via the new cython.inline function and cython.compile decorator. http://wiki.cython.org/enhancements/inline
* Support for dynamic compilation at runtime via the new cython.inline function and cython.compile decorator. https://github.com/cython/cython/wiki/enhancements-inline
* "nogil" blocks are supported when compiling pure Python code by writing "with cython.nogil".
......
......@@ -809,8 +809,7 @@ def create_extension_list(patterns, exclude=None, ctx=None, aliases=None, quiet=
elif name:
module_name = name
if module_name == 'cython':
raise ValueError('cython is a special module, cannot be used as a module name')
Utils.raise_error_if_module_name_forbidden(module_name)
if module_name not in seen:
try:
......
......@@ -3,7 +3,7 @@
# Cython Scanner - Lexical Definitions
#
from __future__ import absolute_import
from __future__ import absolute_import, unicode_literals
raw_prefixes = "rR"
bytes_prefixes = "bB"
......
......@@ -469,6 +469,8 @@ def run_pipeline(source, options, full_module_name=None, context=None):
abs_path = os.path.abspath(source)
full_module_name = full_module_name or context.extract_module_name(source, options)
Utils.raise_error_if_module_name_forbidden(full_module_name)
if options.relative_path_in_code_position_comments:
rel_path = full_module_name.replace('.', os.sep) + source_ext
if not abs_path.endswith(rel_path):
......
......@@ -3260,10 +3260,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
return node
if node.type.is_pyobject:
if operator in ('Eq', 'Ne'):
ret_type = PyrexTypes.c_bint_type
else:
ret_type = PyrexTypes.py_object_type
ret_type = PyrexTypes.py_object_type
elif node.type is PyrexTypes.c_bint_type and operator in ('Eq', 'Ne'):
ret_type = PyrexTypes.c_bint_type
else:
......
......@@ -14,13 +14,15 @@ cdef class Method:
cdef dict kwargs
cdef readonly object __name__ # for tracing the scanner
## methods commented with '##' out are used by Parsing.py when compiled.
@cython.final
cdef class CompileTimeScope:
cdef public dict entries
cdef public CompileTimeScope outer
cdef declare(self, name, value)
cdef lookup_here(self, name)
cpdef lookup(self, name)
##cdef declare(self, name, value)
##cdef lookup_here(self, name)
##cpdef lookup(self, name)
@cython.final
cdef class PyrexScanner(Scanner):
......@@ -51,15 +53,15 @@ cdef class PyrexScanner(Scanner):
@cython.locals(current_level=cython.long, new_level=cython.long)
cpdef indentation_action(self, text)
#cpdef eof_action(self, text)
cdef next(self)
cdef peek(self)
##cdef next(self)
##cdef peek(self)
#cpdef put_back(self, sy, systring)
#cdef unread(self, token, value)
cdef bint expect(self, what, message = *) except -2
cdef expect_keyword(self, what, message = *)
cdef expected(self, what, message = *)
cdef expect_indent(self)
cdef expect_dedent(self)
cdef expect_newline(self, message=*, bint ignore_semicolon=*)
cdef int enter_async(self) except -1
cdef int exit_async(self) except -1
##cdef bint expect(self, what, message = *) except -2
##cdef expect_keyword(self, what, message = *)
##cdef expected(self, what, message = *)
##cdef expect_indent(self)
##cdef expect_dedent(self)
##cdef expect_newline(self, message=*, bint ignore_semicolon=*)
##cdef int enter_async(self) except -1
##cdef int exit_async(self) except -1
This diff is collapsed.
......@@ -153,6 +153,13 @@ cdef extern from "Python.h":
# PyErr_SetFromErrno(type);" when the system call returns an
# error.
PyObject* PyErr_SetFromErrnoWithFilenameObject(object type, object filenameObject) except NULL
# Similar to PyErr_SetFromErrno(), with the additional behavior
# that if filenameObject is not NULL, it is passed to the
# constructor of type as a third parameter.
# In the case of OSError exception, this is used to define
# the filename attribute of the exception instance.
PyObject* PyErr_SetFromErrnoWithFilename(object type, char *filename) except NULL
# Return value: Always NULL. Similar to PyErr_SetFromErrno(),
# with the additional behavior that if filename is not NULL, it is
......
cdef extern from "<forward_list>" namespace "std" nogil:
cdef cppclass forward_list[T,ALLOCATOR=*]:
ctypedef T value_type
ctypedef ALLOCATOR allocator_type
# these should really be allocator_type.size_type and
# allocator_type.difference_type to be true to the C++ definition
# but cython doesn't support deferred access on template arguments
ctypedef size_t size_type
ctypedef ptrdiff_t difference_type
cppclass iterator:
iterator()
iterator(iterator &)
T& operator*()
iterator operator++()
bint operator==(iterator)
bint operator!=(iterator)
cppclass const_iterator(iterator):
pass
forward_list() except +
forward_list(forward_list&) except +
forward_list(size_t, T&) except +
#forward_list& operator=(forward_list&)
bint operator==(forward_list&, forward_list&)
bint operator!=(forward_list&, forward_list&)
bint operator<(forward_list&, forward_list&)
bint operator>(forward_list&, forward_list&)
bint operator<=(forward_list&, forward_list&)
bint operator>=(forward_list&, forward_list&)
void assign(size_t, T&)
T& front()
iterator before_begin()
const_iterator const_before_begin "before_begin"()
iterator begin()
const_iterator const_begin "begin"()
iterator end()
const_iterator const_end "end"()
bint empty()
size_t max_size()
void clear()
iterator insert_after(iterator, T&)
void insert_after(iterator, size_t, T&)
iterator erase_after(iterator)
iterator erase_after(iterator, iterator)
void push_front(T&)
void pop_front()
void resize(size_t)
void resize(size_t, T&)
void swap(forward_list&)
void merge(forward_list&)
void merge[Compare](forward_list&, Compare)
void splice_after(iterator, forward_list&)
void splice_after(iterator, forward_list&, iterator)
void splice_after(iterator, forward_list&, iterator, iterator)
void remove(const T&)
void remove_if[Predicate](Predicate)
void reverse()
void unique()
void unique[Predicate](Predicate)
void sort()
void sort[Compare](Compare)
......@@ -28,18 +28,23 @@ cdef class Scanner:
cdef public level
@cython.final
@cython.locals(input_state=long)
cdef next_char(self)
@cython.locals(action=Action)
cpdef tuple read(self)
@cython.final
cdef tuple scan_a_token(self)
cdef tuple position(self)
##cdef tuple position(self) # used frequently by Parsing.py
@cython.final
@cython.locals(cur_pos=Py_ssize_t, cur_line=Py_ssize_t, cur_line_start=Py_ssize_t,
input_state=long, next_pos=Py_ssize_t, state=dict,
buf_start_pos=Py_ssize_t, buf_len=Py_ssize_t, buf_index=Py_ssize_t,
trace=bint, discard=Py_ssize_t, data=unicode, buffer=unicode)
cdef run_machine_inlined(self)
@cython.final
cdef begin(self, state)
@cython.final
cdef produce(self, value, text = *)
......@@ -796,15 +796,48 @@ static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err,
// so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument
// => optimise for that case
static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
Py_ssize_t i, n;
assert(PyExceptionClass_Check(exc_type));
n = PyTuple_GET_SIZE(tuple);
#if PY_MAJOR_VERSION >= 3
// the tighter subtype checking in Py3 allows faster out-of-order comparison
for (i=0; i<n; i++) {
if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
}
#endif
for (i=0; i<n; i++) {
PyObject *t = PyTuple_GET_ITEM(tuple, i);
#if PY_MAJOR_VERSION < 3
if (likely(exc_type == t)) return 1;
#endif
if (likely(PyExceptionClass_Check(t))) {
if (__Pyx_inner_PyErr_GivenExceptionMatches2(exc_type, NULL, t)) return 1;
} else {
// FIXME: Py3: PyErr_SetString(PyExc_TypeError, "catching classes that do not inherit from BaseException is not allowed");
}
}
return 0;
}
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) {
if (likely(err == exc_type)) return 1;
if (likely(PyExceptionClass_Check(err))) {
return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type);
if (likely(PyExceptionClass_Check(exc_type))) {
return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type);
} else if (likely(PyTuple_Check(exc_type))) {
return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type);
} else {
// FIXME: Py3: PyErr_SetString(PyExc_TypeError, "catching classes that do not inherit from BaseException is not allowed");
}
}
return PyErr_GivenExceptionMatches(err, exc_type);
}
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) {
// Only used internally with known exception types => pure safety check assertions.
assert(PyExceptionClass_Check(exc_type1));
assert(PyExceptionClass_Check(exc_type2));
if (likely(err == exc_type1 || err == exc_type2)) return 1;
if (likely(PyExceptionClass_Check(err))) {
return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2);
......
......@@ -713,7 +713,7 @@ static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject els
{{py: c_op = {'Eq': '==', 'Ne': '!='}[op] }}
{{py:
return_compare = (
(lambda a,b,c_op: "if ({a} {c_op} {b}) {return_true}; else {return_false};".format(
(lambda a,b,c_op, return_true=return_true, return_false=return_false: "if ({a} {c_op} {b}) {return_true}; else {return_false};".format(
a=a, b=b, c_op=c_op, return_true=return_true, return_false=return_false))
if ret_type.is_pyobject else
(lambda a,b,c_op: "return ({a} {c_op} {b});".format(a=a, b=b, c_op=c_op))
......
......@@ -487,3 +487,9 @@ def add_metaclass(metaclass):
orig_vars.pop('__weakref__', None)
return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper
def raise_error_if_module_name_forbidden(full_module_name):
#it is bad idea to call the pyx-file cython.pyx, so fail early
if full_module_name == 'cython' or full_module_name.endswith('.cython'):
raise ValueError('cython is a special module, cannot be used as a module name')
......@@ -127,7 +127,7 @@ pygments_style = 'sphinx'
todo_include_todos = True
# intersphinx for standard :keyword:s (def, for, etc.)
intersphinx_mapping = {'python': ('http://docs.python.org/3/', None)}
intersphinx_mapping = {'python': ('https://docs.python.org/3/', None)}
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
......
from libc.stdlib cimport atoi
cdef parse_charptr_to_py_int(char*s):
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!
......@@ -4,4 +4,4 @@ cdef extern from "string.h":
cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh"
cdef char* pos = strstr(needle='akd', haystack=data)
print(pos != NULL)
print(pos is not NULL)
cimport cython
@cython.profile(False)
def my_often_called_function():
pass
# mymodule.pxd
# declare a C function as "cpdef" to export it to the module
cdef extern from "math.h":
cpdef double sin(double x)
# 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))
cdef class Shrubbery:
cdef int width, height
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 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 widen_shrubbery(Shrubbery sh, extra_width):
sh.width = sh.width + extra_width
# 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
# 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();
}
from cpython.ref cimport PyObject
from libc.stdint cimport uintptr_t
python_string = "foo"
cdef void* ptr = <void*>python_string
cdef uintptr_t adress_in_c = <uintptr_t>ptr
address_from_void = adress_in_c # address_from_void is a python int
cdef PyObject* ptr2 = <PyObject*>python_string
cdef uintptr_t address_in_c2 = <uintptr_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 __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
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
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 g(a, b, *, c, d):
...
# We cannot call g with less verbosity than this.
foo = g(4.0, "something", c=68, d="other")
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)
cdef class A:
cdef foo(self)
cdef class B(A):
cdef foo(self, x=*)
cdef class C(B):
cpdef foo(self, x=*, int 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)
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")
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
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
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
# VALID
cdef int[::view.indirect, ::1, :] a
cdef int[::view.indirect, :, ::1] b
cdef int[::view.indirect_contiguous, ::1, :] c
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
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
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
array = np.arange(20, dtype=np.intc).reshape((2, 10))
cdef int[:, ::1] c_contig = array
cdef int[::1, :] f_contig = c_contig.T
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 extern from "lunch.h":
void eject_tomato(float)
cdef enum otherstuff:
sausage, eggs, lettuce
cdef struct spamdish:
int oz_of_spam
otherstuff filler
cimport shrubbing
import shrubbing
def main():
cdef shrubbing.Shrubbery sh
sh = shrubbing.standard_shrubbery()
print("Shrubbery size is", sh.width, 'x', sh.length)
cimport c_lunch
def eject_tomato(float speed):
c_lunch.eject_tomato(speed)
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}')
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"]))
cdef class Shrubbery:
cdef int width
cdef int length
cdef class Shrubbery:
def __cinit__(self, int w, int l):
self.width = w
self.length = l
def standard_shrubbery():
return Shrubbery(3, 7)
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)
cdef float cube(float x):
return x * x * x
......@@ -8,5 +8,5 @@ cdef extern from "Rectangle.h" namespace "shapes":
Rectangle(int, int, int, int) except +
int x0, y0, x1, y1
int getArea()
void getSize(int*width, int*height)
void getSize(int* width, int* height)
void move(int, int)
# 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++
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++
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++
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++
# 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++
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 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
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html web htmlhelp latex changes linkcheck
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " web to make files usable by Sphinx.web"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview over all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
clean:
-rm -rf build/*
html:
mkdir -p build/html build/doctrees
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
@echo
@echo "Build finished. The HTML pages are in build/html."
web:
mkdir -p build/web build/doctrees
$(SPHINXBUILD) -b web $(ALLSPHINXOPTS) build/web
@echo
@echo "Build finished; now you can run"
@echo " python -m sphinx.web build/web"
@echo "to start the server."
htmlhelp:
mkdir -p build/htmlhelp build/doctrees
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in build/htmlhelp."
latex:
mkdir -p build/latex build/doctrees
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
@echo
@echo "Build finished; the LaTeX files are in build/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
mkdir -p build/changes build/doctrees
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
@echo
@echo "The overview file is in build/changes."
linkcheck:
mkdir -p build/linkcheck build/doctrees
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in build/linkcheck/output.txt."
......@@ -51,7 +51,8 @@ system, for example, it might look similar to this::
(``gcc`` will need to have paths to your included header files and paths
to libraries you want to link with.)
After compilation, a ``yourmod.so`` file is written into the target directory
After compilation, a ``yourmod.so`` (:file:`yourmod.pyd` for Windows)
file is written into the target directory
and your module, ``yourmod``, is available for you to import as with any other
Python module. Note that if you are not relying on ``cythonize`` or distutils,
you will not automatically benefit from the platform specific file extension
......@@ -104,7 +105,13 @@ the necessary include files, e.g. for NumPy::
include_path = [numpy.get_include()]
Note for Numpy users. Despite this, you will still get warnings like the
.. note::
Using memoryviews or importing NumPy with ``import numpy`` does not mean that
you have to add the path to NumPy include files. You need to add this path only
if you use ``cimport numpy``.
Despite this, you will still get warnings like the
following from the compiler, because Cython is using a deprecated Numpy API::
.../include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
......@@ -462,6 +469,7 @@ C-compiling the module C files.
Also take a look at the `cython_freeze
<https://github.com/cython/cython/blob/master/bin/cython_freeze>`_ tool.
.. _pyximport:
Compiling with :mod:`pyximport`
===============================
......
......@@ -158,7 +158,7 @@ We can thus change the init function as follows:
exception instance in order to raise it may actually fail because
we are running out of memory. Luckily, CPython provides a C-API
function ``PyErr_NoMemory()`` that safely raises the right
exception for us. Since version 0.14.1, Cython automatically
exception for us. Cython automatically
substitutes this C-API call whenever you write ``raise
MemoryError`` or ``raise MemoryError()``. If you use an older
version, you have to cimport the C-API function from the standard
......
......@@ -77,7 +77,7 @@ It is shipped and installed with Cython and can be used like this::
>>> import helloworld
Hello World
Since Cython 0.11, the :ref:`Pyximport<pyximport>` module also has experimental
The :ref:`Pyximport<pyximport>` module also has experimental
compilation support for normal Python modules. This allows you to
automatically run Cython on every .pyx and .py module that Python
imports, including the standard library and installed packages.
......
......@@ -92,7 +92,7 @@ names like this::
char* strstr(const char*, const char*)
However, this prevents Cython code from calling it with keyword
arguments (supported since Cython 0.19). It is therefore preferable
arguments. It is therefore preferable
to write the declaration like this instead:
.. literalinclude:: ../../examples/tutorial/external/keyword_args.pyx
......
......@@ -23,7 +23,8 @@ the Cython version -- Cython uses ".pyx" as its file suffix.
.. literalinclude:: ../../examples/tutorial/numpy/convolve_py.py
This should be compiled to produce :file:`yourmod.so` (for Linux systems). We
This should be compiled to produce :file:`yourmod.so` (for Linux systems, on Windows
systems, it will be :file:`yourmod.pyd`). We
run a Python session to test both the Python version (imported from
``.py``-file) and the compiled Cython module.
......
......@@ -44,14 +44,9 @@ If your profiling is messed up because of the call overhead to some small
functions that you rather do not want to see in your profile - either because
you plan to inline them anyway or because you are sure that you can't make them
any faster - you can use a special decorator to disable profiling for one
function only::
cimport cython
@cython.profile(False)
def my_often_called_function():
pass
function only (regardless of whether it is globally enabled or not):
.. literalinclude:: ../../examples/tutorial/profiling_tutorial/often_called.pyx
Enabling line tracing
---------------------
......
......@@ -299,25 +299,11 @@ Calling C functions
Normally, it isn't possible to call C functions in pure Python mode as there
is no general way to support it in normal (uncompiled) Python. However, in
cases where an equivalent Python function exists, this can be achieved by
combining C function coercion with a conditional import as follows::
combining C function coercion with a conditional import as follows:
# in mymodule.pxd:
.. literalinclude:: ../../examples/tutorial/pure/mymodule.pxd
# declare a C function as "cpdef" to export it to the module
cdef extern from "math.h":
cpdef double sin(double x)
# in 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))
.. literalinclude:: ../../examples/tutorial/pure/mymodule.py
Note that the "sin" function will show up in the module namespace of "mymodule"
here (i.e. there will be a ``mymodule.sin()`` function). You can mark it as an
......@@ -334,7 +320,7 @@ to make the names match again.
Using C arrays for fixed size lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Since Cython 0.22, C arrays can automatically coerce to Python lists or tuples.
C arrays can automatically coerce to Python lists or tuples.
This can be exploited to replace fixed size Python lists in Python code by C
arrays when compiled. An example:
......
......@@ -164,7 +164,7 @@ the assignment in a try-finally construct:
To convert the byte string back into a C :c:type:`char*`, use the
opposite assignment::
cdef char* other_c_string = py_string
cdef char* other_c_string = py_string # other_c_string is a 0-terminated string.
This is a very fast operation after which ``other_c_string`` points to
the byte string buffer of the Python string itself. It is tied to the
......@@ -260,7 +260,7 @@ not modify a string they return, for example:
.. literalinclude:: ../../examples/tutorial/string/someheader.h
Since version 0.18, Cython has support for the ``const`` modifier in
Cython has support for the ``const`` modifier in
the language, so you can declare the above functions straight away as
follows:
......@@ -296,7 +296,7 @@ bytes most of which tend to be 0.
Again, no bounds checking is done if slice indices are provided, so
incorrect indices lead to data corruption and crashes. However, using
negative indices is possible since Cython 0.17 and will inject a call
negative indices is possible and will inject a call
to :c:func:`strlen()` in order to determine the string length.
Obviously, this only works for 0-terminated strings without internal
null bytes. Text encoded in UTF-8 or one of the ISO-8859 encodings is
......@@ -467,7 +467,7 @@ supports the ``__future__`` import ``unicode_literals`` that instructs
the parser to read all unprefixed :obj:`str` literals in a source file as
unicode string literals, just like Python 3.
.. _`CEP 108`: http://wiki.cython.org/enhancements/stringliterals
.. _`CEP 108`: https://github.com/cython/cython/wiki/enhancements-stringliterals
Single bytes and characters
---------------------------
......@@ -475,7 +475,7 @@ Single bytes and characters
The Python C-API uses the normal C :c:type:`char` type to represent
a byte value, but it has two special integer types for a Unicode code
point value, i.e. a single Unicode character: :c:type:`Py_UNICODE`
and :c:type:`Py_UCS4`. Since version 0.13, Cython supports the
and :c:type:`Py_UCS4`. Cython supports the
first natively, support for :c:type:`Py_UCS4` is new in Cython 0.15.
:c:type:`Py_UNICODE` is either defined as an unsigned 2-byte or
4-byte integer, or as :c:type:`wchar_t`, depending on the platform.
......
......@@ -105,21 +105,23 @@ will be very inefficient. If the attribute is private, it will not work at all
-- the code will compile, but an attribute error will be raised at run time.
The solution is to declare ``sh`` as being of type :class:`Shrubbery`, as
follows::
follows:
cdef widen_shrubbery(Shrubbery sh, extra_width):
sh.width = sh.width + extra_width
.. literalinclude:: ../../examples/userguide/extension_types/widen_shrubbery.pyx
Now the Cython compiler knows that ``sh`` has a C attribute called
:attr:`width` and will generate code to access it directly and efficiently.
The same consideration applies to local variables, for example,::
The same consideration applies to local variables, for example:
.. literalinclude:: ../../examples/userguide/extension_types/shrubbery_2.pyx
.. note::
cdef Shrubbery another_shrubbery(Shrubbery sh1):
cdef Shrubbery sh2
sh2 = Shrubbery()
sh2.width = sh1.width
sh2.height = sh1.height
return sh2
We here ``cimport`` the class :class:`Shrubbery`, and this is necessary
to declare the type at compile time. To be able to ``cimport`` an extension type,
we split the class definition into two parts, one in a definition file and
the other in the corresponding implementation file. You should read
:ref:`sharing_extension_types` to learn to do that.
Type Testing and Casting
......@@ -347,7 +349,7 @@ inherit from multiple extension types provided that the usual Python rules for
multiple inheritance are followed (i.e. the C layouts of all the base classes
must be compatible).
Since Cython 0.13.1, there is a way to prevent extension types from
There is a way to prevent extension types from
being subtyped in Python. This is done via the ``final`` directive,
usually set on an extension type using a decorator::
......@@ -419,7 +421,7 @@ compatible types.::
cdef void* ptr
def __dealloc__(self):
if self.ptr != NULL:
if self.ptr is not NULL:
free(self.ptr)
@staticmethod
......
......@@ -458,32 +458,12 @@ contains the api call which is generating the segmentation fault does not call
the :func:`import_modulename` function before the api call which crashes.
Any public C type or extension type declarations in the Cython module are also
made available when you include :file:`modulename_api.h`.::
made available when you include :file:`modulename_api.h`.:
# delorean.pyx
cdef public struct Vehicle:
int speed
float power
.. literalinclude:: ../../examples/userguide/external_C_code/delorean.pyx
cdef api void activate(Vehicle *v):
if v.speed >= 88 and v.power >= 1.21:
print("Time travel achieved")
.. sourcecode:: c
# 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();
}
.. literalinclude:: ../../examples/userguide/external_C_code/marty.c
:language: C
.. note::
......@@ -587,7 +567,7 @@ header::
If the callback may be called from another non-Python thread,
care must be taken to initialize the GIL first, through a call to
`PyEval_InitThreads() <http://docs.python.org/dev/c-api/init.html#PyEval_InitThreads>`_.
`PyEval_InitThreads() <https://docs.python.org/dev/c-api/init.html#c.PyEval_InitThreads>`_.
If you're already using :ref:`cython.parallel <parallel>` in your module, this will already have been taken care of.
The GIL may also be acquired through the ``with gil`` statement::
......
......@@ -107,21 +107,9 @@ You can declare classes with :keyword:`cdef`, making them :ref:`extension-types`
have a behavior very close to python classes, but are faster because they use a ``struct``
internally to store attributes.
Here is a simple example::
Here is a simple example:
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.")
.. literalinclude:: ../../examples/userguide/extension_types/shrubbery.pyx
You can read more about them in :ref:`extension-types`.
......@@ -179,20 +167,9 @@ Grouping multiple C declarations
--------------------------------
If you have a series of declarations that all begin with :keyword:`cdef`, you
can group them into a :keyword:`cdef` block like this::
from __future__ import print_function
can group them into a :keyword:`cdef` block like this:
cdef:
struct Spam:
int tons
int i
float a
Spam *p
void f(Spam *s):
print(s.tons, "Tons of spam")
.. literalinclude:: ../../examples/userguide/language_basics/cdef_block.pyx
.. _cpdef:
.. _cdef:
......@@ -311,35 +288,15 @@ To avoid repetition (and potential future inconsistencies), default argument val
not visible in the declaration (in ``.pxd`` files) but only in
the implementation (in ``.pyx`` files).
When in a ``.pyx`` file, the signature is the same as it is in Python itself::
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)
When in a ``.pyx`` file, the signature is the same as it is in Python itself:
.. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pyx
When in a ``.pxd`` file, the signature is different like this example: ``cdef foo(x=*)``.
This is because the program calling the function just needs to know what signatures are
possible in C, but doesn't need to know the value of the default arguments.::
cdef class A:
cdef foo(self)
cdef class B(A):
cdef foo(self, x=*)
cdef class C(B):
cpdef foo(self, x=*, int k=*)
possible in C, but doesn't need to know the value of the default arguments.:
.. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pxd
.. note::
The number of arguments may increase when subclassing,
......@@ -355,13 +312,9 @@ Keyword-only Arguments
----------------------
As in Python 3, ``def`` functions can have keyword-only arguments
listed after a ``"*"`` parameter and before a ``"**"`` parameter if any::
def f(a, b, *args, c, d = 42, e, **kwds):
...
listed after a ``"*"`` parameter and before a ``"**"`` parameter if any:
# We cannot call f with less verbosity than this.
foo = f(4, "bar", c=68, e=1.0)
.. literalinclude:: ../../examples/userguide/language_basics/kwargs_1.pyx
As shown above, the ``c``, ``d`` and ``e`` arguments can not be
passed as positional arguments and must be passed as keyword arguments.
......@@ -369,16 +322,12 @@ Furthermore, ``c`` and ``e`` are **required** keyword arguments
since they do not have a default value.
A single ``"*"`` without argument name can be used to
terminate the list of positional arguments::
def g(a, b, *, c, d):
...
terminate the list of positional arguments:
# We cannot call g with less verbosity than this.
foo = g(4.0, "something", c=68, d="other")
.. literalinclude:: ../../examples/userguide/language_basics/kwargs_2.pyx
Shown above, the signature takes exactly two positional
parameters and has two required keyword parameters
parameters and has two required keyword parameters.
Function Pointers
-----------------
......@@ -479,12 +428,9 @@ returns ``NULL``. The except clause doesn't work that way; its only purpose is
for propagating Python exceptions that have already been raised, either by a Cython
function or a C function that calls Python/C API routines. To get an exception
from a non-Python-aware function such as :func:`fopen`, you will have to check the
return value and raise it yourself, for example,::
return value and raise it yourself, for example:
cdef FILE* p
p = fopen("spam.txt", "r")
if p == NULL:
raise SpamError("Couldn't open the spam file")
.. literalinclude:: ../../examples/userguide/language_basics/open_file.pyx
.. _overriding_in_extension_types:
......@@ -492,39 +438,15 @@ Overriding in extension types
-----------------------------
``cpdef`` methods can override ``cdef`` methods::
from __future__ import print_function
``cpdef`` methods can override ``cdef`` methods:
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)
.. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pyx
When subclassing an extension type with a Python class,
``def`` methods can override ``cpdef`` methods but not ``cdef``
methods::
from __future__ import print_function
cdef class A:
cdef foo(self):
print("A")
methods:
cdef class B(A):
cpdef foo(self):
print("B")
class C(B): # NOTE: not cdef class
def foo(self):
print("C")
.. literalinclude:: ../../examples/userguide/language_basics/override.pyx
If ``C`` above would be an extension type (``cdef class``),
this would not work correctly.
......@@ -556,6 +478,8 @@ possibilities.
+----------------------------+--------------------+------------------+
| char* | str/bytes | str/bytes [#]_ |
+----------------------------+--------------------+------------------+
| C array | iterable | list [#2]_ |
+----------------------------+--------------------+------------------+
| struct, | | dict [#1]_ |
| union | | |
+----------------------------+--------------------+------------------+
......@@ -568,6 +492,10 @@ possibilities.
combinations. An example is a union of an ``int`` and a ``char*``,
in which case the pointer value may or may not be a valid pointer.
.. [#2] Other than signed/unsigned char[].
The conversion will fail if the length of C array is not known at compile time,
and when using a slice of a C array.
Caveats when using a Python string in a C context
-------------------------------------------------
......@@ -632,26 +560,9 @@ You can also cast a C pointer back to a Python object reference
with ``<object>``, or a more specific builtin or extension type
(e.g. ``<MyExtType>ptr``). This will increase the reference count of
the object by one, i.e. the cast returns an owned reference.
Here is an example::
from cpython.ref cimport PyObject
from libc.stdint cimport uintptr_t
python_string = "foo"
cdef void* ptr = <void*>python_string
cdef uintptr_t adress_in_c = <uintptr_t>ptr
address_from_void = adress_in_c # address_from_void is a python int
cdef PyObject* ptr2 = <PyObject*>python_string
cdef uintptr_t address_in_c2 = <uintptr_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"
Here is an example:
.. literalinclude:: ../../examples/userguide/language_basics/casting_python.pyx
The precedence of ``<...>`` is such that ``<type>a.b.c`` is interpreted as ``<type>(a.b.c)``.
......@@ -971,13 +882,7 @@ the source at that point as a literal. For this to work, the compile-time
expression must evaluate to a Python value of type ``int``, ``long``,
``float``, ``bytes`` or ``unicode`` (``str`` in Py3).
::
from __future__ import print_function
cdef int a1[ArraySize]
cdef int a2[OtherArraySize]
print("I like", FavouriteFood)
.. literalinclude:: ../../examples/userguide/language_basics/compile_time.pyx
Conditional Statements
----------------------
......
......@@ -71,14 +71,9 @@ This also works conveniently as function arguments:
The ``not None`` declaration for the argument automatically rejects
None values as input, which would otherwise be allowed. The reason why
None is allowed by default is that it is conveniently used for return
arguments::
arguments:
def process_buffer(int[:,:] input not None,
int[:,:] output = None):
if output is None:
output = ... # e.g. numpy.empty_like(input)
# process 'input' into 'output'
return output
.. literalinclude:: ../../examples/userguide/memoryviews/not_none.pyx
Cython will reject incompatible buffers automatically, e.g. passing a
three dimensional buffer into a function that requires a two
......@@ -102,40 +97,24 @@ dimension::
print(buf[-1,-2])
The following function loops over each dimension of a 2D array and
adds 1 to each item::
adds 1 to each item:
def add_one(int[:,:] buf):
for x in xrange(buf.shape[0]):
for y in xrange(buf.shape[1]):
buf[x,y] += 1
.. literalinclude:: ../../examples/userguide/memoryviews/add_one.pyx
Indexing and slicing can be done with or without the GIL. It basically works
like NumPy. If indices are specified for every dimension you will get an element
of the base type (e.g. `int`). Otherwise, you will get a new view. An Ellipsis
means you get consecutive slices for every unspecified dimension::
means you get consecutive slices for every unspecified dimension:
cdef int[:, :, :] my_view = exporting_object
# These are all equivalent
my_view[10]
my_view[10, :, :]
my_view[10, ...]
.. literalinclude:: ../../examples/userguide/memoryviews/slicing.pyx
Copying
-------
Memory views can be copied in place::
cdef int[:, :, :] to_view, from_view
...
Memory views can be copied in place:
# copy the elements in from_view to to_view
to_view[...] = from_view
# or
to_view[:] = from_view
# or
to_view[:, :, :] = from_view
.. literalinclude:: ../../examples/userguide/memoryviews/copy.pyx
They can also be copied with the ``copy()`` and ``copy_fortran()`` methods; see
:ref:`view_copy_c_fortran`.
......@@ -146,10 +125,9 @@ Transposing
-----------
In most cases (see below), the memoryview can be transposed in the same way that
NumPy slices can be transposed::
NumPy slices can be transposed:
cdef int[:, ::1] c_contig = ...
cdef int[::1, :] f_contig = c_contig.T
.. literalinclude:: ../../examples/userguide/memoryviews/transpose.pyx
This gives a new, transposed, view on the data.
......@@ -171,6 +149,9 @@ As for NumPy, new axes can be introduced by indexing an array with ``None`` ::
# 2D array with shape (50, 1)
myslice[:, None]
# 3D array with shape (1, 10, 1)
myslice[None, 10:-20:2, None]
One may mix new axis indexing with all other forms of indexing and slicing.
See also an example_.
......@@ -178,13 +159,14 @@ Read-only views
---------------
Since Cython 0.28, the memoryview item type can be declared as ``const`` to
support read-only buffers as input::
support read-only buffers as input:
cdef const double[:] myslice # const item type => read-only view
.. literalinclude:: ../../examples/userguide/memoryviews/np_flag_const.pyx
a = np.linspace(0, 10, num=50)
a.setflags(write=False)
myslice = a
Using a non-const memoryview with a binary Python string produces a runtime error.
You can solve this issue with a ``const`` memoryview:
.. literalinclude:: ../../examples/userguide/memoryviews/view_string.pyx
Note that this does not *require* the input buffer to be read-only::
......@@ -436,31 +418,21 @@ The flags are as follows:
* contiguous - contiguous and direct
* indirect_contiguous - the list of pointers is contiguous
and they can be used like this::
and they can be used like this:
from cython cimport view
# direct access in both dimensions, strided in the first dimension, contiguous in the last
cdef int[:, ::view.contiguous] a
.. literalinclude:: ../../examples/userguide/memoryviews/memory_layout.pyx
# contiguous list of pointers to contiguous lists of ints
cdef int[::view.indirect_contiguous, ::1] b
Only the first, last or the dimension following an indirect dimension may be
specified contiguous:
# direct or indirect in the first dimension, direct in the second dimension
# strided in both dimensions
cdef int[::view.generic, :] c
.. literalinclude:: ../../examples/userguide/memoryviews/memory_layout_2.pyx
Only the first, last or the dimension following an indirect dimension may be
specified contiguous::
::
# INVALID
cdef int[::view.contiguous, ::view.indirect, :] a
cdef int[::1, ::view.indirect, :] b
cdef int[::view.contiguous, ::view.indirect, :] d
cdef int[::1, ::view.indirect, :] e
# VALID
cdef int[::view.indirect, ::1, :] a
cdef int[::view.indirect, :, ::1] b
cdef int[::view.indirect_contiguous, ::1, :]
The difference between the `contiguous` flag and the `::1` specifier is that the
former specifies contiguity for only one dimension, whereas the latter specifies
......@@ -686,7 +658,5 @@ call functions in C files, see :ref:`using_c_libraries`.
.. _GIL: http://docs.python.org/dev/glossary.html#term-global-interpreter-lock
.. _new style buffers: https://docs.python.org/c-api/buffer.html
.. _pep 3118: https://www.python.org/dev/peps/pep-3118/
.. _NumPy: https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#memory-layout
.. _example: http://www.scipy.org/Numpy_Example_List#newaxis
.. _example: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
......@@ -147,7 +147,8 @@ Cython version -- Cython uses ".pyx" as its file suffix.
.. literalinclude:: ../../examples/userguide/numpy_tutorial/convolve_py.py
:linenos:
This should be compiled to produce :file:`convolve_cy.so` (for Linux systems). We
This should be compiled to produce :file:`convolve_cy.so` (for Linux systems,
on Windows systems, this will be a ``.pyd`` file). We
run a Python session to test both the Python version (imported from
``.py``-file) and the compiled Cython module.
......
......@@ -131,7 +131,7 @@ It currently supports OpenMP, but later on more backends might be supported.
with nogil, parallel():
local_buf = <int *> malloc(sizeof(int) * size)
if local_buf == NULL:
if local_buf is NULL:
abort()
# populate our local buffer in a sequential loop
......
Porting Cython code to PyPy
===========================
Since version 0.17, Cython has basic support for cpyext, the layer in
Cython has basic support for cpyext, the layer in
`PyPy <http://pypy.org/>`_ that emulates CPython's C-API. This is
achieved by making the generated C code adapt at C compile time, so
the generated code will compile in both CPython and PyPy unchanged.
......
......@@ -21,10 +21,14 @@ Python 3 Support
Cython creates ``.c`` files that can be built and used with both
Python 2.x and Python 3.x. In fact, compiling your module with
Cython may very well be the easiest way to port code to Python 3.
We are also working to make the compiler run in both Python 2.x and 3.x.
Cython may very well be an easy way to port code to Python 3.
Many Python 3 constructs are already supported by Cython.
Cython also supports various syntax additions that came with
Python 3.0 and later major Python releases. If they do not conflict
with existing Python 2.x syntax or semantics, they are usually just
accepted by the compiler. Everything else depends on the
compiler directive ``language_level=3``
(see :ref:`compiler directives<compiler-directives>`).
List/Set/Dict Comprehensions
----------------------------
......@@ -67,7 +71,6 @@ extra positional arguments, e.g.::
takes exactly two positional parameters and has two required keyword parameters.
Conditional expressions "x if b else y"
=========================================
......@@ -258,26 +261,13 @@ remain the same. There is a slight performance penalty in some cases when a
cdef/cpdef function without any optional is overridden with one that does have
default argument values.
For example, one can have the ``.pxd`` file::
For example, one can have the ``.pxd`` file:
cdef class A:
cdef foo(self)
cdef class B(A)
cdef foo(self, x=*)
cdef class C(B):
cpdef foo(self, x=*, int k=*)
.. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pxd
with corresponding ``.pyx`` file::
with corresponding ``.pyx`` file:
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
.. literalinclude:: ../../examples/userguide/language_basics/optional_subclassing.pyx
.. note::
......
......@@ -80,28 +80,13 @@ Here is an example. :file:`dishes.pxd` is a definition file which exports a
C data type. :file:`restaurant.pyx` is an implementation file which imports and
uses it.
:file:`dishes.pxd`::
:file:`dishes.pxd`:
cdef enum otherstuff:
sausage, eggs, lettuce
.. literalinclude:: ../../examples/userguide/sharing_declarations/dishes.pxd
cdef struct spamdish:
int oz_of_spam
otherstuff filler
:file:`restaurant.pyx`:
:file:`restaurant.pyx`::
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("%d oz spam, filler no. %d" % (d.oz_of_spam, d.filler))
.. literalinclude:: ../../examples/userguide/sharing_declarations/restaurant.pyx
It is important to understand that the :keyword:`cimport` statement can only
be used to import C data types, C functions and variables, and extension
......@@ -147,17 +132,13 @@ for an imaginary module, and :keyword:`cimport` that module. You can then
refer to the C functions by qualifying them with the name of the module.
Here's an example:
:file:`c_lunch.pxd`::
:file:`c_lunch.pxd`:
cdef extern from "lunch.h":
void eject_tomato(float)
.. literalinclude:: ../../examples/userguide/sharing_declarations/c_lunch.pxd
:file:`lunch.pyx`::
:file:`lunch.pyx`:
cimport c_lunch
def eject_tomato(float speed):
c_lunch.eject_tomato(speed)
.. literalinclude:: ../../examples/userguide/sharing_declarations/lunch.pyx
You don't need any :file:`c_lunch.pyx` file, because the only things defined
in :file:`c_lunch.pxd` are extern C entities. There won't be any actual
......@@ -173,28 +154,17 @@ C functions defined at the top level of a module can be made available via
:keyword:`cimport` by putting headers for them in the ``.pxd`` file, for
example:
:file:`volume.pxd`::
cdef float cube(float)
:file:`volume.pxd`:
:file:`volume.pyx`::
.. literalinclude:: ../../examples/userguide/sharing_declarations/volume.pxd
cdef float cube(float x):
return x * x * x
:file:`volume.pyx`:
:file:`spammery.pyx`::
.. literalinclude:: ../../examples/userguide/sharing_declarations/volume.pyx
from __future__ import print_function
:file:`spammery.pyx`:
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)
.. literalinclude:: ../../examples/userguide/sharing_declarations/spammery.pyx
.. note::
......@@ -203,6 +173,7 @@ example:
this object from Python, nor can you use it from Cython using a normal import
statement; you have to use :keyword:`cimport`.
.. _sharing_extension_types:
Sharing Extension Types
=======================
......@@ -222,38 +193,23 @@ Python methods.
Here is an example of a module which defines and exports an extension type,
and another module which uses it:
:file:`Shrubbing.pxd`::
cdef class Shrubbery:
cdef int width
cdef int length
:file:`Shrubbing.pyx`::
:file:`shrubbing.pxd`:
cdef class Shrubbery:
def __cinit__(self, int w, int l):
self.width = w
self.length = l
.. literalinclude:: ../../examples/userguide/sharing_declarations/shrubbing.pxd
def standard_shrubbery():
return Shrubbery(3, 7)
:file:`shrubbing.pyx`:
:file:`Landscaping.pyx`::
.. literalinclude:: ../../examples/userguide/sharing_declarations/shrubbing.pyx
cimport Shrubbing
import Shrubbing
:file:`landscaping.pyx`:
cdef Shrubbing.Shrubbery sh
sh = Shrubbing.standard_shrubbery()
print("Shrubbery size is %d x %d" % (sh.width, sh.length))
.. literalinclude:: ../../examples/userguide/sharing_declarations/landscaping.pyx
One would then need to compile both of these modules, e.g. using
:file:`setup.py`::
:file:`setup.py`:
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize(["Landscaping.pyx", "Shrubbing.pyx"]))
.. literalinclude:: ../../examples/userguide/sharing_declarations/setup.py
Some things to note about this example:
......
......@@ -75,8 +75,6 @@ them through :func:`cythonize`::
)
.. _pyximport:
Pyximport
===========
......@@ -107,51 +105,4 @@ on end user side as it hooks into their import system. The best way
to cater for end users is to provide pre-built binary packages in the
`wheel <https://wheel.readthedocs.io/>`_ packaging format.
Arguments
---------
The function ``pyximport.install()`` can take several arguments to
influence the compilation of Cython or Python files.
.. autofunction:: pyximport.install
Dependency Handling
--------------------
Since :mod:`pyximport` does not use `cythonize()` internally, it currently
requires a different setup for dependencies. It is possible to declare that
your module depends on multiple files, (likely ``.h`` and ``.pxd`` files).
If your Cython module is named ``foo`` and thus has the filename
:file:`foo.pyx` then you should create another file in the same directory
called :file:`foo.pyxdep`. The :file:`modname.pyxdep` file can be a list of
filenames or "globs" (like ``*.pxd`` or ``include/*.h``). Each filename or
glob must be on a separate line. Pyximport will check the file date for each
of those files before deciding whether to rebuild the module. In order to
keep track of the fact that the dependency has been handled, Pyximport updates
the modification time of your ".pyx" source file. Future versions may do
something more sophisticated like informing distutils of the dependencies
directly.
Limitations
------------
Pyximport does not give you any control over how your Cython file is
compiled. Usually the defaults are fine. You might run into problems if
you wanted to write your program in half-C, half-Cython and build them
into a single library.
Pyximport does not hide the Distutils/GCC warnings and errors generated
by the import process. Arguably this will give you better feedback if
something went wrong and why. And if nothing went wrong it will give you
the warm fuzzy feeling that pyximport really did rebuild your module as it
was supposed to.
Basic module reloading support is available with the option ``reload_support=True``.
Note that this will generate a new module filename for each build and thus
end up loading multiple shared libraries into memory over time. CPython does
not support reloading shared libraries as such.
Pyximport puts both your ``.c`` file and the platform-specific binary into
a separate build directory, usually ``$HOME/.pyxblx/``. To copy it back
into the package hierarchy (usually next to the source file) for manual
reuse, you can pass the option ``inplace=True``.
To have more information of :mod:`pyximport`, please refer to :ref:`pyximport`.
\ No newline at end of file
......@@ -185,6 +185,8 @@ method called :meth:`__next__`, not next. The Python system will automatically
supply a next method which calls your :meth:`__next__`. Do *NOT* explicitly
give your type a :meth:`next` method, or bad things could happen.
.. _special_methods_table:
Special Method Table
---------------------
......@@ -241,6 +243,8 @@ like :meth:`__eq__` or the single special method :meth:`__richcmp__`.
Depending on the application, one way or the other may be better.
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| Name | Parameters | Return type | Description |
+=======================+=======================================+=============+========================================================+
| __eq__ |self, y | object | self == y |
+-----------------------+---------------------------------------+-------------+--------------------------------------------------------+
| __ne__ |self, y | object | self != y (falls back to ``__eq__`` if not available) |
......
......@@ -252,25 +252,12 @@ themselves::
Nested class declarations
--------------------------
C++ allows nested class declaration. Class declarations can also be
nested in Cython::
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
Note that the nested class is declared with a ``cppclass`` but without a ``cdef``.
nested in Cython:
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/nested_class.pyx
Note that the nested class is declared with a ``cppclass`` but without a ``cdef``,
as it is already part of a ``cdef`` declaration section.
C++ operators not compatible with Python syntax
------------------------------------------------
......@@ -299,36 +286,9 @@ which can also be written ``&foo``.
Templates
----------
Cython uses a bracket syntax for templating. A simple example for wrapping C++ vector::
# 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
Cython uses a bracket syntax for templating. A simple example for wrapping C++ vector:
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/templates.pyx
Multiple template parameters can be defined as a list, such as ``[T, U, V]``
or ``[int, bool, char]``. Optional template parameters can be indicated
......@@ -339,55 +299,33 @@ a typedef for its template parameters it is preferable to use that name here.
Template functions are defined similarly to class templates, with
the template parameter list following the function name::
cdef extern from "<algorithm>" namespace "std":
T max[T](T a, T b)
the template parameter list following the function name:
print(max[long](3, 4))
print(max(1.5, 2.5)) # simple template argument deduction
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/function_template.pyx
Standard library
-----------------
Most of the containers of the C++ Standard Library have been declared
in pxd files located in ``/Cython/Includes/libcpp``. These containers
are: deque, list, map, pair, queue, set, stack, vector.
in pxd files located
in `/Cython/Includes/libcpp <https://github.com/cython/cython/tree/master/Cython/Includes/libcpp>`_.
These containers are: deque, list, map, pair, queue, set, stack, vector.
For example::
For example:
from libcpp.vector cimport vector
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/vector_demo.pyx
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)
The pxd files
in `/Cython/Includes/libcpp <https://github.com/cython/cython/tree/master/Cython/Includes/libcpp>`_
also work as good examples on how to declare C++ classes.
The pxd files in ``/Cython/Includes/libcpp`` also work as good examples on
how to declare C++ classes.
Since Cython 0.17, the STL containers coerce from and to the
The STL containers coerce from and to the
corresponding Python builtin types. The conversion is triggered
either by an assignment to a typed variable (including typed function
arguments) or by an explicit cast, e.g.::
from libcpp.string cimport string
from libcpp.vector cimport vector
cdef string s = py_bytes_object
print(s)
cpp_string = <string> py_unicode_object.encode('utf-8')
arguments) or by an explicit cast, e.g.:
cdef vector[int] vect = xrange(1, 10, 2)
print(vect) # [1, 3, 5, 7, 9]
cdef vector[string] cpp_strings = b'ab cd ef gh'.split()
print(cpp_strings[1]) # b'cd'
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx
The following coercions are available:
......@@ -413,16 +351,21 @@ inside of containers, e.g. a C++ vector of maps of strings.
Iteration over stl containers (or indeed any class with ``begin()`` and
``end()`` methods returning an object supporting incrementing, dereferencing,
and comparison) is supported via the ``for .. in`` syntax (including in list
comprehensions). For example, one can write::
comprehensions). For example, one can write:
cdef vector[int] v = ...
for value in v:
f(value)
return [x*x for x in v if x % 2 == 0]
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/iterate.pyx
If the loop target variable is unspecified, an assignment from type
``*container.begin()`` is used for :ref:`type inference <compiler-directives>`.
.. note::
Slicing stl containers is supported,
you can do ``for x in my_vector[:5]: ...`` but unlike pointers slices,
it will create a temporary Python object and iterate over it. Thus
making the iteration very slow. You might want to avoid slicing
C++ containers for performance reasons.
Simplified wrapping with default constructor
--------------------------------------------
......@@ -430,20 +373,9 @@ Simplified wrapping with default constructor
If your extension type instantiates a wrapped C++ class using the default
constructor (not passing any arguments), you may be able to simplify the
lifecycle handling by tying it directly to the lifetime of the Python wrapper
object. Instead of a pointer attribute, you can declare an instance::
cdef class VectorStack:
cdef vector[int] v
def push(self, x):
self.v.push_back(x)
object. Instead of a pointer attribute, you can declare an instance:
def pop(self):
if self.v.empty():
raise IndexError()
x = self.v.back()
self.v.pop_back()
return x
.. literalinclude:: ../../examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx
Cython will automatically generate code that instantiates the C++ object
instance when the Python object is created and deletes it when the Python
......@@ -598,7 +530,8 @@ possible to declare them in the :file:`setup.py` file::
Cython will generate and compile the :file:`rect.cpp` file (from
:file:`rect.pyx`), then it will compile :file:`Rectangle.cpp`
(implementation of the ``Rectangle`` class) and link both object files
together into :file:`rect.so`, which you can then import in Python using
together into :file:`rect.so` on Linux, or :file:`rect.pyd` on windows,
which you can then import in Python using
``import rect`` (if you forget to link the :file:`Rectangle.o`, you will
get missing symbols while importing the library in Python).
......
......@@ -618,7 +618,7 @@ class TestBuilder(object):
test_class = CythonUnitTestCase
else:
test_class = CythonRunTestCase
elif mode in ['compile', 'error', 'test']:
elif mode in ['compile', 'error']:
test_class = CythonCompileTestCase
else:
raise KeyError('Invalid test mode: ' + mode)
......
......@@ -85,20 +85,20 @@ def compile_cython_modules(profile=False, compile_more=False, cython_with_refnan
compiled_modules = [
"Cython.Plex.Scanners",
"Cython.Plex.Actions",
"Cython.Compiler.Pythran",
"Cython.Compiler.Lexicon",
"Cython.Compiler.Scanning",
"Cython.Compiler.Parsing",
"Cython.Compiler.Visitor",
"Cython.Compiler.FlowControl",
"Cython.Compiler.Code",
"Cython.Runtime.refnanny",
"Cython.Compiler.FusedNode",
"Cython.Tempita._tempita",
"Cython.StringIOTree",
]
if compile_more:
compiled_modules.extend([
"Cython.StringIOTree",
"Cython.Compiler.Code",
"Cython.Compiler.Lexicon",
"Cython.Compiler.Parsing",
"Cython.Compiler.Pythran",
"Cython.Build.Dependencies",
"Cython.Compiler.ParseTreeTransforms",
"Cython.Compiler.Nodes",
......
PYTHON -c "import cythonize_tests"
PYTHON -c "import cython_tests"
######## cythonize_tests.py ########
from Cython.Build.Cythonize import main as cythonize
for test_case in ["cython.pyx", "src/cython.pyx", "src2/cython.pyx"]:
try:
cythonize([test_case])
except ValueError:
pass
else:
assert False, "ValueError not raised - forbidding cythonize "+test_case+" doesn't work"
try:
cythonize(["notcython.pys"])
except ValueError:
assert False, "ValueError raised - forbidding cythonize notcython.pyx should work"
else:
pass
######## cython_tests.py ########
from Cython.Compiler.Main import main as cython
import sys
for test_case in ["cython.pyx", "src/cython.pyx", "src2/cython.pyx"]:
sys.argv=["cython", test_case] #cython.py will extract parameters from sys.argv
try:
cython(command_line=1)
except ValueError:
pass
else:
assert False, "ValueError not raised - forbidding cython "+test_case+" doesn't work"
sys.argv=["cython", "notcython.pyx"] #cython.py will extract parameters from sys.argv
try:
cython(["notcython.pys"])
except ValueError:
assert False, "ValueError raised - forbidding cythonize notcython.pyx should work"
else:
pass
######## cython.pyx ########
######## src/__init__.py ########
######## src/cython.pyx ########
######## notcython.pyx ########
######## src2/cython.pyx ########
# mode: run
# tag: cpp, werror, cpp11
from cython.operator cimport dereference as deref
from cython.operator cimport preincrement as incr
from libcpp.forward_list cimport forward_list
from libcpp cimport bool as cbool
def simple_iteration_test(L):
"""
>>> iteration_test([1,2,4,8])
8
4
2
1
>>> iteration_test([8,4,2,1])
1
2
4
8
"""
cdef forward_list[int] l
for a in L:
l.push_front(a)
for a in l:
print(a)
def iteration_test(L):
"""
>>> iteration_test([1,2,4,8])
8
4
2
1
>>> iteration_test([8,4,2,1])
1
2
4
8
"""
l = new forward_list[int]()
try:
for a in L:
l.push_front(a)
it = l.begin()
while it != l.end():
a = deref(it)
incr(it)
print(a)
finally:
del l
def test_value_type(x):
"""
>>> test_value_type(2)
2.0
>>> test_value_type(2.5)
2.5
"""
cdef forward_list[double].value_type val = x
return val
def test_value_type_complex(x):
"""
>>> test_value_type_complex(2)
(2+0j)
"""
cdef forward_list[double complex].value_type val = x
return val
# Tests GitHub issue #1788.
cdef cppclass MyForwardList[T](forward_list):
pass
cdef cppclass Ints(MyForwardList[int]):
pass
......@@ -898,4 +898,33 @@ def test_copy_buffer(np.ndarray[double, ndim=1] a):
return a
@testcase
def test_broadcast_comparison(np.ndarray[double, ndim=1] a):
"""
>>> a = np.ones(10, dtype=np.double)
>>> a0, obj0, a1, obj1 = test_broadcast_comparison(a)
>>> np.all(a0 == (a == 0)) or a0
True
>>> np.all(a1 == (a == 1)) or a1
True
>>> np.all(obj0 == (a == 0)) or obj0
True
>>> np.all(obj1 == (a == 1)) or obj1
True
>>> a = np.zeros(10, dtype=np.double)
>>> a0, obj0, a1, obj1 = test_broadcast_comparison(a)
>>> np.all(a0 == (a == 0)) or a0
True
>>> np.all(a1 == (a == 1)) or a1
True
>>> np.all(obj0 == (a == 0)) or obj0
True
>>> np.all(obj1 == (a == 1)) or obj1
True
"""
cdef object obj = a
return a == 0, obj == 0, a == 1, obj == 1
include "numpy_common.pxi"
......@@ -22,7 +22,7 @@ def test_itimer(sec, usec):
t.it_value.tv_sec = 0
t.it_value.tv_usec = 0
ret = setitimer(ITIMER_REAL, &t, NULL)
return gtime.it_interval.tv_sec, gtime.it_interval.tv_usec
return int(gtime.it_interval.tv_sec), int(gtime.it_interval.tv_usec)
def test_gettimeofday():
"""
......
# mode: test
# mode: run
def f(x, y):
x = y
......
......@@ -58,6 +58,36 @@ def single_except_expression(a, x):
i = 3
return i
exceptions = (ValueError, TypeError)
def single_except_global_tuple(x):
"""
>>> single_except_global_tuple(None)
2
>>> single_except_global_tuple(ValueError('test'))
3
>>> single_except_global_tuple(TypeError('test'))
3
>>> class TypeErrorSubtype(TypeError): pass
>>> single_except_global_tuple(TypeErrorSubtype('test'))
3
>>> single_except_global_tuple(AttributeError('test'))
Traceback (most recent call last):
AttributeError: test
"""
cdef int i
try:
i = 1
if x:
raise x
i = 2
except exceptions:
i = 3
return i
def double_except_no_raise(a,b):
"""
>>> double_except_no_raise(TypeError, ValueError)
......@@ -179,6 +209,10 @@ def normal_and_bare_except_raise(x, a):
2
>>> normal_and_bare_except_raise(ValueError('test'), TypeError)
3
>>> normal_and_bare_except_raise(TypeError('test'), (TypeError, ValueError))
2
>>> normal_and_bare_except_raise(ValueError('test'), (TypeError, ValueError))
2
>>> normal_and_bare_except_raise(None, TypeError)
1
"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment