Commit 2748f9ef authored by mathbunnyru's avatar mathbunnyru

Delete trailing spaces

parent 3d4f7a19
...@@ -71,7 +71,7 @@ def runcmd(cmd, shell=True): ...@@ -71,7 +71,7 @@ def runcmd(cmd, shell=True):
returncode = os.system(cmd) returncode = os.system(cmd)
else: else:
returncode = subprocess.call(cmd, shell=shell) returncode = subprocess.call(cmd, shell=shell)
if returncode: if returncode:
sys.exit(returncode) sys.exit(returncode)
......
...@@ -65,7 +65,7 @@ changes/contributions they have specific copyright on, they should indicate ...@@ -65,7 +65,7 @@ changes/contributions they have specific copyright on, they should indicate
their copyright in the commit message of the change, when they commit the their copyright in the commit message of the change, when they commit the
change to one of the IPython repositories. change to one of the IPython repositories.
With this in mind, the following banner should be used in any source code file With this in mind, the following banner should be used in any source code file
to indicate the copyright and license terms: to indicate the copyright and license terms:
:: ::
......
...@@ -85,7 +85,7 @@ class DeclarationWriter(TreeVisitor): ...@@ -85,7 +85,7 @@ class DeclarationWriter(TreeVisitor):
def visit_StatListNode(self, node): def visit_StatListNode(self, node):
self.visitchildren(node) self.visitchildren(node)
def visit_CDefExternNode(self, node): def visit_CDefExternNode(self, node):
if node.include_file is None: if node.include_file is None:
file = u'*' file = u'*'
...@@ -516,6 +516,6 @@ class PxdWriter(DeclarationWriter): ...@@ -516,6 +516,6 @@ class PxdWriter(DeclarationWriter):
if node.api: if node.api:
self.put(u'api ') self.put(u'api ')
self.visit(node.declarator) self.visit(node.declarator)
def visit_StatNode(self, node): def visit_StatNode(self, node):
pass pass
...@@ -13,7 +13,7 @@ class TestMemviewParsing(CythonTest): ...@@ -13,7 +13,7 @@ class TestMemviewParsing(CythonTest):
def not_parseable(self, expected_error, s): def not_parseable(self, expected_error, s):
e = self.should_fail(lambda: self.fragment(s), Errors.CompileError) e = self.should_fail(lambda: self.fragment(s), Errors.CompileError)
self.assertEqual(expected_error, e.message_only) self.assertEqual(expected_error, e.message_only)
def test_default_1dim(self): def test_default_1dim(self):
self.parse(u"cdef int[:] x") self.parse(u"cdef int[:] x")
self.parse(u"cdef short int[:] x") self.parse(u"cdef short int[:] x")
......
...@@ -12,9 +12,9 @@ python_var = 13 ...@@ -12,9 +12,9 @@ python_var = 13
def spam(a=0): def spam(a=0):
cdef: cdef:
int b, c int b, c
b = c = d = 0 b = c = d = 0
b = 1 b = 1
c = 2 c = 2
int(10) int(10)
...@@ -23,11 +23,11 @@ def spam(a=0): ...@@ -23,11 +23,11 @@ def spam(a=0):
some_c_function() some_c_function()
cpdef eggs(): cpdef eggs():
pass pass
cdef ham(): cdef ham():
pass pass
cdef class SomeClass(object): cdef class SomeClass(object):
def spam(self): def spam(self):
pass pass
......
...@@ -2517,8 +2517,8 @@ class FixGdbCommand(gdb.Command): ...@@ -2517,8 +2517,8 @@ class FixGdbCommand(gdb.Command):
def fix_gdb(self): def fix_gdb(self):
""" """
It seems that invoking either 'cy exec' and 'py-exec' work perfectly It seems that invoking either 'cy exec' and 'py-exec' work perfectly
fine, but after this gdb's python API is entirely broken. fine, but after this gdb's python API is entirely broken.
Maybe some uncleared exception value is still set? Maybe some uncleared exception value is still set?
sys.exc_clear() didn't help. A demonstration: sys.exc_clear() didn't help. A demonstration:
......
""" """
array.pxd array.pxd
Cython interface to Python's array.array module. Cython interface to Python's array.array module.
* 1D contiguous data view * 1D contiguous data view
* tools for fast array creation, maximum C-speed and handiness * tools for fast array creation, maximum C-speed and handiness
* suitable as allround light weight auto-array within Cython code too * suitable as allround light weight auto-array within Cython code too
Usage: Usage:
>>> cimport array >>> cimport array
Usage through Cython buffer interface (Py2.3+): Usage through Cython buffer interface (Py2.3+):
>>> def f(arg1, unsigned i, double dx) >>> def f(arg1, unsigned i, double dx)
... array.array[double] a = arg1 ... array.array[double] a = arg1
... a[i] += dx ... a[i] += dx
Fast C-level new_array(_zeros), resize_array, copy_array, Py_SIZE(obj), Fast C-level new_array(_zeros), resize_array, copy_array, Py_SIZE(obj),
zero_array zero_array
cdef array.array[double] k = array.copy(d) cdef array.array[double] k = array.copy(d)
cdef array.array[double] n = array.array(d, Py_SIZE(d) * 2 ) cdef array.array[double] n = array.array(d, Py_SIZE(d) * 2 )
cdef array.array[double] m = array.zeros_like(FLOAT_TEMPLATE) cdef array.array[double] m = array.zeros_like(FLOAT_TEMPLATE)
array.resize(f, 200000) array.resize(f, 200000)
Zero overhead with naked data pointer views by union: Zero overhead with naked data pointer views by union:
_f, _d, _i, _c, _u, ... _f, _d, _i, _c, _u, ...
=> Original C array speed + Python dynamic memory management => Original C array speed + Python dynamic memory management
cdef array.array a = inarray cdef array.array a = inarray
if if
a._d[2] += 0.66 # use as double array without extra casting a._d[2] += 0.66 # use as double array without extra casting
float *subview = vector._f + 10 # starting from 10th element float *subview = vector._f + 10 # starting from 10th element
unsigned char *subview_buffer = vector._B + 4 unsigned char *subview_buffer = vector._B + 4
Suitable as lightweight arrays intra Cython without speed penalty. Suitable as lightweight arrays intra Cython without speed penalty.
Replacement for C stack/malloc arrays; no trouble with refcounting, Replacement for C stack/malloc arrays; no trouble with refcounting,
mem.leaks; seamless Python compatibility, buffer() optional mem.leaks; seamless Python compatibility, buffer() optional
last changes: 2009-05-15 rk last changes: 2009-05-15 rk
: 2009-12-06 bp : 2009-12-06 bp
......
...@@ -5,7 +5,7 @@ cdef extern from "Python.h": ...@@ -5,7 +5,7 @@ cdef extern from "Python.h":
pass pass
cdef extern from "datetime.h": cdef extern from "datetime.h":
ctypedef extern class datetime.date[object PyDateTime_Date]: ctypedef extern class datetime.date[object PyDateTime_Date]:
pass pass
...@@ -23,11 +23,11 @@ cdef extern from "datetime.h": ...@@ -23,11 +23,11 @@ cdef extern from "datetime.h":
ctypedef struct PyDateTime_Date: ctypedef struct PyDateTime_Date:
pass pass
ctypedef struct PyDateTime_Time: ctypedef struct PyDateTime_Time:
char hastzinfo char hastzinfo
PyObject *tzinfo PyObject *tzinfo
ctypedef struct PyDateTime_DateTime: ctypedef struct PyDateTime_DateTime:
char hastzinfo char hastzinfo
PyObject *tzinfo PyObject *tzinfo
...@@ -36,22 +36,22 @@ cdef extern from "datetime.h": ...@@ -36,22 +36,22 @@ cdef extern from "datetime.h":
int days int days
int seconds int seconds
int microseconds int microseconds
# Define structure for C API. # Define structure for C API.
ctypedef struct PyDateTime_CAPI: ctypedef struct PyDateTime_CAPI:
# type objects # type objects
PyTypeObject *DateType PyTypeObject *DateType
PyTypeObject *DateTimeType PyTypeObject *DateTimeType
PyTypeObject *TimeType PyTypeObject *TimeType
PyTypeObject *DeltaType PyTypeObject *DeltaType
PyTypeObject *TZInfoType PyTypeObject *TZInfoType
# constructors # constructors
object (*Date_FromDate)(int, int, int, PyTypeObject*) object (*Date_FromDate)(int, int, int, PyTypeObject*)
object (*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, object, PyTypeObject*) object (*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, object, PyTypeObject*)
object (*Time_FromTime)(int, int, int, int, object, PyTypeObject*) object (*Time_FromTime)(int, int, int, int, object, PyTypeObject*)
object (*Delta_FromDelta)(int, int, int, int, PyTypeObject*) object (*Delta_FromDelta)(int, int, int, int, PyTypeObject*)
# constructors for the DB API # constructors for the DB API
object (*DateTime_FromTimestamp)(object, object, object) object (*DateTime_FromTimestamp)(object, object, object)
object (*Date_FromTimestamp)(object, object) object (*Date_FromTimestamp)(object, object)
...@@ -96,7 +96,7 @@ cdef extern from "datetime.h": ...@@ -96,7 +96,7 @@ cdef extern from "datetime.h":
# PyDateTime CAPI object. # PyDateTime CAPI object.
PyDateTime_CAPI *PyDateTimeAPI PyDateTime_CAPI *PyDateTimeAPI
void PyDateTime_IMPORT() void PyDateTime_IMPORT()
# Datetime C API initialization function. # Datetime C API initialization function.
...@@ -108,7 +108,7 @@ cdef inline void import_datetime(): ...@@ -108,7 +108,7 @@ cdef inline void import_datetime():
# Note, there are no range checks for any of the arguments. # Note, there are no range checks for any of the arguments.
cdef inline object date_new(int year, int month, int day): cdef inline object date_new(int year, int month, int day):
return PyDateTimeAPI.Date_FromDate(year, month, day, PyDateTimeAPI.DateType) return PyDateTimeAPI.Date_FromDate(year, month, day, PyDateTimeAPI.DateType)
# Create time object using DateTime CAPI factory function # Create time object using DateTime CAPI factory function
# Note, there are no range checks for any of the arguments. # Note, there are no range checks for any of the arguments.
cdef inline object time_new(int hour, int minute, int second, int microsecond, object tz): cdef inline object time_new(int hour, int minute, int second, int microsecond, object tz):
...@@ -127,7 +127,7 @@ cdef inline object timedelta_new(int days, int seconds, int useconds): ...@@ -127,7 +127,7 @@ cdef inline object timedelta_new(int days, int seconds, int useconds):
# More recognizable getters for date/time/datetime/timedelta. # More recognizable getters for date/time/datetime/timedelta.
# There are no setters because datetime.h hasn't them. # There are no setters because datetime.h hasn't them.
# This is because of immutable nature of these objects by design. # This is because of immutable nature of these objects by design.
# If you would change time/date/datetime/timedelta object you need to recreate. # If you would change time/date/datetime/timedelta object you need to recreate.
# Get tzinfo of time # Get tzinfo of time
cdef inline object time_tzinfo(object o): cdef inline object time_tzinfo(object o):
...@@ -136,7 +136,7 @@ cdef inline object time_tzinfo(object o): ...@@ -136,7 +136,7 @@ cdef inline object time_tzinfo(object o):
else: else:
return None return None
# Get tzinfo of datetime # Get tzinfo of datetime
cdef inline object datetime_tzinfo(object o): cdef inline object datetime_tzinfo(object o):
if (<PyDateTime_DateTime*>o).hastzinfo: if (<PyDateTime_DateTime*>o).hastzinfo:
return <object>(<PyDateTime_DateTime*>o).tzinfo return <object>(<PyDateTime_DateTime*>o).tzinfo
...@@ -146,7 +146,7 @@ cdef inline object datetime_tzinfo(object o): ...@@ -146,7 +146,7 @@ cdef inline object datetime_tzinfo(object o):
# Get year of date # Get year of date
cdef inline int date_year(object o): cdef inline int date_year(object o):
return PyDateTime_GET_YEAR(o) return PyDateTime_GET_YEAR(o)
# Get month of date # Get month of date
cdef inline int date_month(object o): cdef inline int date_month(object o):
return PyDateTime_GET_MONTH(o) return PyDateTime_GET_MONTH(o)
...@@ -158,7 +158,7 @@ cdef inline int date_day(object o): ...@@ -158,7 +158,7 @@ cdef inline int date_day(object o):
# Get year of datetime # Get year of datetime
cdef inline int datetime_year(object o): cdef inline int datetime_year(object o):
return PyDateTime_GET_YEAR(o) return PyDateTime_GET_YEAR(o)
# Get month of datetime # Get month of datetime
cdef inline int datetime_month(object o): cdef inline int datetime_month(object o):
return PyDateTime_GET_MONTH(o) return PyDateTime_GET_MONTH(o)
......
...@@ -14,7 +14,7 @@ cdef extern from "<iterator>" namespace "std" nogil: ...@@ -14,7 +14,7 @@ cdef extern from "<iterator>" namespace "std" nogil:
pass pass
cdef cppclass random_access_iterator_tag(bidirectional_iterator_tag): cdef cppclass random_access_iterator_tag(bidirectional_iterator_tag):
pass pass
cdef cppclass back_insert_iterator[T](iterator[output_iterator_tag,void,void,void,void]): cdef cppclass back_insert_iterator[T](iterator[output_iterator_tag,void,void,void,void]):
pass pass
cdef cppclass front_insert_iterator[T](iterator[output_iterator_tag,void,void,void,void]): cdef cppclass front_insert_iterator[T](iterator[output_iterator_tag,void,void,void,void]):
...@@ -29,4 +29,4 @@ cdef extern from "<iterator>" namespace "std" nogil: ...@@ -29,4 +29,4 @@ cdef extern from "<iterator>" namespace "std" nogil:
##insert_iterator<Container> inserter (Container& x, typename Container::iterator it) ##insert_iterator<Container> inserter (Container& x, typename Container::iterator it)
insert_iterator[CONTAINER] inserter[CONTAINER,ITERATOR](CONTAINER &, ITERATOR) insert_iterator[CONTAINER] inserter[CONTAINER,ITERATOR](CONTAINER &, ITERATOR)
...@@ -5,7 +5,7 @@ cdef extern from "<limits>" namespace "std" nogil: ...@@ -5,7 +5,7 @@ cdef extern from "<limits>" namespace "std" nogil:
round_to_nearest = 1 round_to_nearest = 1
round_toward_infinity = 2 round_toward_infinity = 2
round_toward_neg_infinity = 3 round_toward_neg_infinity = 3
enum float_denorm_style: enum float_denorm_style:
denorm_indeterminate = -1 denorm_indeterminate = -1
denorm_absent = 0 denorm_absent = 0
...@@ -37,7 +37,7 @@ cdef extern from "<limits>" namespace "std" nogil: ...@@ -37,7 +37,7 @@ cdef extern from "<limits>" namespace "std" nogil:
const int min_exponent10 const int min_exponent10
const int max_exponent const int max_exponent
const int max_exponent10 const int max_exponent10
const bint has_infinity const bint has_infinity
const bint has_quiet_NaN const bint has_quiet_NaN
const bint has_signaling_NaN const bint has_signaling_NaN
......
...@@ -16,8 +16,8 @@ cdef extern from "<memory>" namespace "std" nogil: ...@@ -16,8 +16,8 @@ cdef extern from "<memory>" namespace "std" nogil:
void construct( T *, const T &) #C++98. The C++11 version is variadic AND perfect-forwarding void construct( T *, const T &) #C++98. The C++11 version is variadic AND perfect-forwarding
void destroy(T *) #C++98 void destroy(T *) #C++98
void destroy[U](U *) #unique_ptr unit tests fail w/this void destroy[U](U *) #unique_ptr unit tests fail w/this
cdef cppclass unique_ptr[T,DELETER=*]: cdef cppclass unique_ptr[T,DELETER=*]:
unique_ptr() unique_ptr()
unique_ptr(nullptr_t) unique_ptr(nullptr_t)
......
...@@ -113,7 +113,7 @@ class Template(object): ...@@ -113,7 +113,7 @@ class Template(object):
self.default_namespace['start_braces'] = delimeters[0] self.default_namespace['start_braces'] = delimeters[0]
self.default_namespace['end_braces'] = delimeters[1] self.default_namespace['end_braces'] = delimeters[1]
self.delimeters = delimeters self.delimeters = delimeters
self._unicode = is_unicode(content) self._unicode = is_unicode(content)
if name is None and stacklevel is not None: if name is None and stacklevel is not None:
try: try:
......
...@@ -129,7 +129,7 @@ class TestJediTyper(TransformTest): ...@@ -129,7 +129,7 @@ class TestJediTyper(TransformTest):
variables = types.pop((None, (1, 0))) variables = types.pop((None, (1, 0)))
self.assertFalse(types) self.assertFalse(types)
self.assertEqual({'a': set(['list']), 'b': set(['list']), 'c': set(['list']), 'd': set(['list'])}, variables) self.assertEqual({'a': set(['list']), 'b': set(['list']), 'c': set(['list']), 'd': set(['list'])}, variables)
def test_typing_function_list(self): def test_typing_function_list(self):
code = '''\ code = '''\
def func(x): def func(x):
...@@ -149,14 +149,14 @@ class TestJediTyper(TransformTest): ...@@ -149,14 +149,14 @@ class TestJediTyper(TransformTest):
code = '''\ code = '''\
a = dict() a = dict()
b = {i: i**2 for i in range(10)} b = {i: i**2 for i in range(10)}
c = a c = a
''' '''
types = self._test(code) types = self._test(code)
self.assertIn((None, (1, 0)), types) self.assertIn((None, (1, 0)), types)
variables = types.pop((None, (1, 0))) variables = types.pop((None, (1, 0)))
self.assertFalse(types) self.assertFalse(types)
self.assertEqual({'a': set(['dict']), 'b': set(['dict']), 'c': set(['dict'])}, variables) self.assertEqual({'a': set(['dict']), 'b': set(['dict']), 'c': set(['dict'])}, variables)
def test_typing_function_dict(self): def test_typing_function_dict(self):
code = '''\ code = '''\
def func(x): def func(x):
...@@ -186,7 +186,7 @@ class TestJediTyper(TransformTest): ...@@ -186,7 +186,7 @@ class TestJediTyper(TransformTest):
variables = types.pop((None, (1, 0))) variables = types.pop((None, (1, 0)))
self.assertFalse(types) self.assertFalse(types)
self.assertEqual({'a': set(['set']), 'c': set(['set']), 'd': set(['set']), 'e': set(['set'])}, variables) self.assertEqual({'a': set(['set']), 'c': set(['set']), 'd': set(['set']), 'e': set(['set'])}, variables)
def test_typing_function_set(self): def test_typing_function_set(self):
code = '''\ code = '''\
def func(x): def func(x):
......
...@@ -29,7 +29,7 @@ typedef struct arraydescr { ...@@ -29,7 +29,7 @@ typedef struct arraydescr {
int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *); int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
char *formats; char *formats;
#endif #endif
} arraydescr; } arraydescr;
...@@ -110,7 +110,7 @@ static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) { ...@@ -110,7 +110,7 @@ static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
if (items == NULL) { if (items == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
self->data.ob_item = (char*) items; self->data.ob_item = (char*) items;
self->ob_size = n; self->ob_size = n;
self->allocated = n; self->allocated = n;
......
...@@ -24,12 +24,12 @@ ...@@ -24,12 +24,12 @@
make make
./nCr 10 5 ./nCr 10 5
./python ./python
* Build notes * Build notes
* benchmarks/chaos.py requires cython 0.24 or newer * benchmarks/chaos.py requires cython 0.24 or newer
* embed and freeze work for python2, require cython 0.24 or higher * embed and freeze work for python2, require cython 0.24 or higher
for python 3.5 for python 3.5
#!/usr/bin/python #!/usr/bin/python
# Back-Propagation Neural Networks # Back-Propagation Neural Networks
# #
# Written in Python. See http://www.python.org/ # Written in Python. See http://www.python.org/
# #
# Neil Schemenauer <nascheme@enme.ucalgary.ca> # Neil Schemenauer <nascheme@enme.ucalgary.ca>
...@@ -26,7 +26,7 @@ def makeMatrix(I, J, fill=0.0): ...@@ -26,7 +26,7 @@ def makeMatrix(I, J, fill=0.0):
return m return m
class NN(object): class NN(object):
# print 'class NN' # print 'class NN'
def __init__(self, ni, nh, no): def __init__(self, ni, nh, no):
# number of input, hidden, and output nodes # number of input, hidden, and output nodes
self.ni = ni + 1 # +1 for bias node self.ni = ni + 1 # +1 for bias node
...@@ -37,7 +37,7 @@ class NN(object): ...@@ -37,7 +37,7 @@ class NN(object):
self.ai = [1.0]*self.ni self.ai = [1.0]*self.ni
self.ah = [1.0]*self.nh self.ah = [1.0]*self.nh
self.ao = [1.0]*self.no self.ao = [1.0]*self.no
# create weights # create weights
self.wi = makeMatrix(self.ni, self.nh) self.wi = makeMatrix(self.ni, self.nh)
self.wo = makeMatrix(self.nh, self.no) self.wo = makeMatrix(self.nh, self.no)
...@@ -49,7 +49,7 @@ class NN(object): ...@@ -49,7 +49,7 @@ class NN(object):
for k in range(self.no): for k in range(self.no):
self.wo[j][k] = rand(-2.0, 2.0) self.wo[j][k] = rand(-2.0, 2.0)
# last change in weights for momentum # last change in weights for momentum
self.ci = makeMatrix(self.ni, self.nh) self.ci = makeMatrix(self.ni, self.nh)
self.co = makeMatrix(self.nh, self.no) self.co = makeMatrix(self.nh, self.no)
......
...@@ -17,7 +17,7 @@ class Dir(object): ...@@ -17,7 +17,7 @@ class Dir(object):
def __init__(self, x, y): def __init__(self, x, y):
self.x = x self.x = x
self.y = y self.y = y
DIRS = [ Dir(1, 0), DIRS = [ Dir(1, 0),
Dir(-1, 0), Dir(-1, 0),
Dir(0, 1), Dir(0, 1),
...@@ -35,7 +35,7 @@ class Done(object): ...@@ -35,7 +35,7 @@ class Done(object):
FIRST_STRATEGY = 3 FIRST_STRATEGY = 3
MAX_NEIGHBORS_STRATEGY = 4 MAX_NEIGHBORS_STRATEGY = 4
MIN_NEIGHBORS_STRATEGY = 5 MIN_NEIGHBORS_STRATEGY = 5
def __init__(self, count, empty=False): def __init__(self, count, empty=False):
self.count = count self.count = count
self.cells = None if empty else [[0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)] self.cells = None if empty else [[0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)]
...@@ -60,11 +60,11 @@ class Done(object): ...@@ -60,11 +60,11 @@ class Done(object):
return True return True
else: else:
return False return False
def remove_all(self, v): def remove_all(self, v):
for i in range(self.count): for i in range(self.count):
self.remove(i, v) self.remove(i, v)
def remove_unfixed(self, v): def remove_unfixed(self, v):
changed = False changed = False
for i in range(self.count): for i in range(self.count):
...@@ -72,7 +72,7 @@ class Done(object): ...@@ -72,7 +72,7 @@ class Done(object):
if self.remove(i, v): if self.remove(i, v):
changed = True changed = True
return changed return changed
def filter_tiles(self, tiles): def filter_tiles(self, tiles):
for v in range(8): for v in range(8):
if tiles[v] == 0: if tiles[v] == 0:
...@@ -206,14 +206,14 @@ class Hex(object): ...@@ -206,14 +206,14 @@ class Hex(object):
def contains_pos(self, pos): def contains_pos(self, pos):
return pos in self.nodes_by_pos return pos in self.nodes_by_pos
def get_by_pos(self, pos): def get_by_pos(self, pos):
return self.nodes_by_pos[pos] return self.nodes_by_pos[pos]
def get_by_id(self, id): def get_by_id(self, id):
return self.nodes_by_id[id] return self.nodes_by_id[id]
################################## ##################################
class Pos(object): class Pos(object):
def __init__(self, hex, tiles, done = None): def __init__(self, hex, tiles, done = None):
...@@ -223,7 +223,7 @@ class Pos(object): ...@@ -223,7 +223,7 @@ class Pos(object):
def clone(self): def clone(self):
return Pos(self.hex, self.tiles, self.done.clone()) return Pos(self.hex, self.tiles, self.done.clone())
################################## ##################################
@cython.locals(pos=Pos, i=cython.long, v=cython.int, @cython.locals(pos=Pos, i=cython.long, v=cython.int,
...@@ -260,7 +260,7 @@ def constraint_pass(pos, last_move=None): ...@@ -260,7 +260,7 @@ def constraint_pass(pos, last_move=None):
for cell in done.cells: for cell in done.cells:
if len(cell) == 1: if len(cell) == 1:
left[cell[0]] -= 1 left[cell[0]] -= 1
for v in range(8): for v in range(8):
# If there is none, remove the possibility from all tiles # If there is none, remove the possibility from all tiles
if (pos.tiles[v] > 0) and (left[v] == 0): if (pos.tiles[v] > 0) and (left[v] == 0):
...@@ -276,7 +276,7 @@ def constraint_pass(pos, last_move=None): ...@@ -276,7 +276,7 @@ def constraint_pass(pos, last_move=None):
if (not done.already_done(i)) and (v in cell): if (not done.already_done(i)) and (v in cell):
done.set_done(i, v) done.set_done(i, v)
changed = True changed = True
# Force empty or non-empty around filled cells # Force empty or non-empty around filled cells
filled_cells = (range(done.count) if last_move is None filled_cells = (range(done.count) if last_move is None
else [last_move]) else [last_move])
...@@ -307,7 +307,7 @@ def constraint_pass(pos, last_move=None): ...@@ -307,7 +307,7 @@ def constraint_pass(pos, last_move=None):
for u in unknown: for u in unknown:
if done.remove(u, EMPTY): if done.remove(u, EMPTY):
changed = True changed = True
return changed return changed
ASCENDING = 1 ASCENDING = 1
...@@ -402,7 +402,7 @@ def solved(pos, output, verbose=False): ...@@ -402,7 +402,7 @@ def solved(pos, output, verbose=False):
if (not all_done) or (not exact): if (not all_done) or (not exact):
return OPEN return OPEN
print_pos(pos, output) print_pos(pos, output)
return SOLVED return SOLVED
...@@ -414,7 +414,7 @@ def solve_step(prev, strategy, order, output, first=False): ...@@ -414,7 +414,7 @@ def solve_step(prev, strategy, order, output, first=False):
pass pass
else: else:
pos = prev pos = prev
moves = find_moves(pos, strategy, order) moves = find_moves(pos, strategy, order)
if len(moves) == 0: if len(moves) == 0:
return solved(pos, output) return solved(pos, output)
...@@ -481,12 +481,12 @@ def read_file(file): ...@@ -481,12 +481,12 @@ def read_file(file):
else: else:
inctile = int(tile) inctile = int(tile)
tiles[inctile] += 1 tiles[inctile] += 1
# Look for locked tiles # Look for locked tiles
if tile[0] == "+": if tile[0] == "+":
print("Adding locked tile: %d at pos %d, %d, id=%d" % print("Adding locked tile: %d at pos %d, %d, id=%d" %
(inctile, x, y, hex.get_by_pos((x, y)).id)) (inctile, x, y, hex.get_by_pos((x, y)).id))
done.set_done(hex.get_by_pos((x, y)).id, inctile) done.set_done(hex.get_by_pos((x, y)).id, inctile)
linei += 1 linei += 1
for y in range(1, size): for y in range(1, size):
ry = size - 1 + y ry = size - 1 + y
...@@ -500,7 +500,7 @@ def read_file(file): ...@@ -500,7 +500,7 @@ def read_file(file):
else: else:
inctile = int(tile) inctile = int(tile)
tiles[inctile] += 1 tiles[inctile] += 1
# Look for locked tiles # Look for locked tiles
if tile[0] == "+": if tile[0] == "+":
print("Adding locked tile: %d at pos %d, %d, id=%d" % print("Adding locked tile: %d at pos %d, %d, id=%d" %
(inctile, x, ry, hex.get_by_pos((x, ry)).id)) (inctile, x, ry, hex.get_by_pos((x, ry)).id))
...@@ -530,13 +530,13 @@ def run_level36(): ...@@ -530,13 +530,13 @@ def run_level36():
output = StringIO() output = StringIO()
solve_file(f, strategy, order, output) solve_file(f, strategy, order, output)
expected = """\ expected = """\
3 4 3 2 3 4 3 2
3 4 4 . 3 3 4 4 . 3
2 . . 3 4 3 2 . . 3 4 3
2 . 1 . 3 . 2 2 . 1 . 3 . 2
3 3 . 2 . 2 3 3 . 2 . 2
3 . 2 . 2 3 . 2 . 2
2 2 . 1 2 2 . 1
""" """
if output.getvalue() != expected: if output.getvalue() != expected:
raise AssertionError("got a wrong answer:\n%s" % output.getvalue()) raise AssertionError("got a wrong answer:\n%s" % output.getvalue())
......
...@@ -143,7 +143,7 @@ def main(n): ...@@ -143,7 +143,7 @@ def main(n):
tk = time.time() tk = time.time()
times.append(tk - t0) times.append(tk - t0)
return times return times
if __name__ == "__main__": if __name__ == "__main__":
parser = optparse.OptionParser( parser = optparse.OptionParser(
usage="%prog [options]", usage="%prog [options]",
......
...@@ -102,13 +102,13 @@ class TaskState(object): ...@@ -102,13 +102,13 @@ class TaskState(object):
self.task_waiting = False self.task_waiting = False
self.task_holding = False self.task_holding = False
return self return self
def waitingWithPacket(self): def waitingWithPacket(self):
self.packet_pending = True self.packet_pending = True
self.task_waiting = True self.task_waiting = True
self.task_holding = False self.task_holding = False
return self return self
def isPacketPending(self): def isPacketPending(self):
return self.packet_pending return self.packet_pending
...@@ -233,7 +233,7 @@ class Task(TaskState): ...@@ -233,7 +233,7 @@ class Task(TaskState):
if t is None: if t is None:
raise Exception("Bad task id %d" % id) raise Exception("Bad task id %d" % id)
return t return t
# DeviceTask # DeviceTask
...@@ -307,7 +307,7 @@ class IdleTask(Task): ...@@ -307,7 +307,7 @@ class IdleTask(Task):
else: else:
i.control = i.control//2 ^ 0xd008 i.control = i.control//2 ^ 0xd008
return self.release(I_DEVB) return self.release(I_DEVB)
# WorkTask # WorkTask
...@@ -385,7 +385,7 @@ class Richards(object): ...@@ -385,7 +385,7 @@ class Richards(object):
wkq = None; wkq = None;
DeviceTask(I_DEVA, 4000, wkq, TaskState().waiting(), DeviceTaskRec()); DeviceTask(I_DEVA, 4000, wkq, TaskState().waiting(), DeviceTaskRec());
DeviceTask(I_DEVB, 5000, wkq, TaskState().waiting(), DeviceTaskRec()); DeviceTask(I_DEVB, 5000, wkq, TaskState().waiting(), DeviceTaskRec());
schedule() schedule()
if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246: if taskWorkArea.holdCount == 9297 and taskWorkArea.qpktCount == 23246:
...@@ -431,7 +431,7 @@ else: ...@@ -431,7 +431,7 @@ else:
for it in item.__dict__.values(): for it in item.__dict__.values():
if isinstance(it, types.FunctionType): if isinstance(it, types.FunctionType):
pypyjit.enable(it.func_code) pypyjit.enable(it.func_code)
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
if len(sys.argv) >= 2: if len(sys.argv) >= 2:
......
...@@ -55,7 +55,7 @@ def main(n): ...@@ -55,7 +55,7 @@ def main(n):
tk = time() tk = time()
times.append(tk - t0) times.append(tk - t0)
return times return times
if __name__ == "__main__": if __name__ == "__main__":
parser = optparse.OptionParser( parser = optparse.OptionParser(
usage="%prog [options]", usage="%prog [options]",
......
...@@ -8,7 +8,7 @@ cdef extern from "cheesefinder.h": ...@@ -8,7 +8,7 @@ cdef extern from "cheesefinder.h":
def find(f): def find(f):
find_cheeses(callback, <void*>f) find_cheeses(callback, <void*>f)
cdef void callback(char *name, void *f): cdef void callback(char *name, void *f):
(<object>f)(name.decode('utf-8')) (<object>f)(name.decode('utf-8'))
...@@ -18,7 +18,7 @@ except: ...@@ -18,7 +18,7 @@ except:
print("Error building external library, please create libmymath.a manually.") print("Error building external library, please create libmymath.a manually.")
sys.exit(1) sys.exit(1)
# Here is how to use the library built above. # Here is how to use the library built above.
ext_modules = cythonize([ ext_modules = cythonize([
Extension("call_mymath", Extension("call_mymath",
sources=["call_mymath.pyx"], sources=["call_mymath.pyx"],
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<meta name="GENERATOR" content="Mozilla/4.51 (Macintosh; I; PPC) [Netscape]"><title>FAQ.html</title></head> <meta name="GENERATOR" content="Mozilla/4.51 (Macintosh; I; PPC) [Netscape]"><title>FAQ.html</title></head>
<body> <body>
<center> <h1> <hr width="100%">Cython FAQ <center> <h1> <hr width="100%">Cython FAQ
<hr width="100%"></h1> <hr width="100%"></h1>
</center> </center>
<h2> Contents</h2> <h2> Contents</h2>
...@@ -21,22 +21,22 @@ ...@@ -21,22 +21,22 @@
</ul> </ul>
<hr width="100%"> <h2> <a name="CallCAPI"></a>How do I call Python/C API routines?</h2> <hr width="100%"> <h2> <a name="CallCAPI"></a>How do I call Python/C API routines?</h2>
Declare them as C functions inside a <tt>cdef extern from</tt> block. Declare them as C functions inside a <tt>cdef extern from</tt> block.
Use the type name <tt>object</tt> for any parameters and return types which Use the type name <tt>object</tt> for any parameters and return types which
are Python object references. Don't use the word <tt>const</tt> anywhere. are Python object references. Don't use the word <tt>const</tt> anywhere.
Here is an example which defines and uses the <tt>PyString_FromStringAndSize</tt> routine: Here is an example which defines and uses the <tt>PyString_FromStringAndSize</tt> routine:
<blockquote><tt>cdef extern from "Python.h":</tt> <br> <blockquote><tt>cdef extern from "Python.h":</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; object PyString_FromStringAndSize(char *, int)</tt> <p><tt>cdef char buf[42]</tt> <br> <tt>&nbsp;&nbsp;&nbsp; object PyString_FromStringAndSize(char *, int)</tt> <p><tt>cdef char buf[42]</tt> <br>
<tt>my_string = PyString_FromStringAndSize(buf, 42)</tt></p> <tt>my_string = PyString_FromStringAndSize(buf, 42)</tt></p>
</blockquote> </blockquote>
<h2> <a name="NullBytes"></a>How do I convert a C string containing null <h2> <a name="NullBytes"></a>How do I convert a C string containing null
bytes to a Python string?</h2> bytes to a Python string?</h2>
Put in a declaration for the <tt>PyString_FromStringAndSize</tt> API routine Put in a declaration for the <tt>PyString_FromStringAndSize</tt> API routine
and use that<tt>.</tt> See <a href="#CallCAPI">How do I call Python/C API and use that<tt>.</tt> See <a href="#CallCAPI">How do I call Python/C API
routines?</a> <h2> <a name="NumericAccess"></a>How do I access the data inside a Numeric routines?</a> <h2> <a name="NumericAccess"></a>How do I access the data inside a Numeric
array object?</h2> array object?</h2>
Use a <tt>cdef extern from</tt> block to include the Numeric header file Use a <tt>cdef extern from</tt> block to include the Numeric header file
and declare the array object as an external extension type. The following and declare the array object as an external extension type. The following
code illustrates how to do this: code illustrates how to do this:
<blockquote><tt>cdef extern from "Numeric/arrayobject.h":</tt> <p><tt>&nbsp;&nbsp;&nbsp; struct PyArray_Descr:</tt> <br> <blockquote><tt>cdef extern from "Numeric/arrayobject.h":</tt> <p><tt>&nbsp;&nbsp;&nbsp; struct PyArray_Descr:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int type_num, elsize</tt> <br> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int type_num, elsize</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char type</tt> </p> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char type</tt> </p>
...@@ -73,5 +73,5 @@ section of the <a href="extension_types.html">"Extension ...@@ -73,5 +73,5 @@ section of the <a href="extension_types.html">"Extension
Types"</a> documentation page.<br> Types"</a> documentation page.<br>
<h2><a name="Quack"></a>Python says my extension type has no method called 'quack', but I know it does. What gives?</h2> <h2><a name="Quack"></a>Python says my extension type has no method called 'quack', but I know it does. What gives?</h2>
You may have declared the method using <span style="font-family: monospace;">cdef</span> instead of <span style="font-family: monospace;">def</span>. Only functions and methods declared with <span style="font-family: monospace;">def</span> are callable from Python code.<br> You may have declared the method using <span style="font-family: monospace;">cdef</span> instead of <span style="font-family: monospace;">def</span>. Only functions and methods declared with <span style="font-family: monospace;">def</span> are callable from Python code.<br>
--- ---
</body></html> </body></html>
\ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"><title>Extension Types</title></head> <meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"><title>Extension Types</title></head>
<body> <body>
<h1> <hr width="100%">Extension Types <h1> <hr width="100%">Extension Types
<hr width="100%"></h1> <hr width="100%"></h1>
<h2> Contents</h2> <h2> Contents</h2>
<ul> <ul>
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<li> <a href="#ExtTypeAttrs">Attributes</a></li> <li> <a href="#ExtTypeAttrs">Attributes</a></li>
<li> <a href="#NotNone">Extension types and None</a></li> <li> <a href="#NotNone">Extension types and None</a></li>
<li> <a href="special_methods.html">Special methods</a></li> <li> <a href="special_methods.html">Special methods</a></li>
<li> <a href="#Properties">Properties</a> <font style="color: rgb(0, 153, 0);" color="#ed181e">(NEW in <li> <a href="#Properties">Properties</a> <font style="color: rgb(0, 153, 0);" color="#ed181e">(NEW in
0.9)</font></li> 0.9)</font></li>
<li><a href="#SubclassingExtTypes">Subclassing</a></li> <li><a href="#SubclassingExtTypes">Subclassing</a></li>
<li> <a href="#CMethods">C Methods</a> <font style="color: rgb(0, 153, 0);" color="#ff0000">(NEW in 0.9)</font><br> <li> <a href="#CMethods">C Methods</a> <font style="color: rgb(0, 153, 0);" color="#ff0000">(NEW in 0.9)</font><br>
...@@ -31,14 +31,14 @@ ...@@ -31,14 +31,14 @@
</ul> </ul>
<h2> <a name="Introduction"></a>Introduction</h2> <h2> <a name="Introduction"></a>Introduction</h2>
As well as creating normal user-defined classes with the Python <b>class</b> As well as creating normal user-defined classes with the Python <b>class</b>
statement, Cython also lets you create new built-in Python types, known as statement, Cython also lets you create new built-in Python types, known as
<i>extension types</i>. You define an extension type using the <b>cdef class</b> statement. Here's an example: <i>extension types</i>. You define an extension type using the <b>cdef class</b> statement. Here's an example:
<blockquote><tt>cdef class Shrubbery:</tt> <p><tt>&nbsp;&nbsp;&nbsp; cdef int width, height</tt> </p> <blockquote><tt>cdef class Shrubbery:</tt> <p><tt>&nbsp;&nbsp;&nbsp; cdef int width, height</tt> </p>
<p><tt>&nbsp;&nbsp;&nbsp; def __init__(self, w, h):</tt> <br> <p><tt>&nbsp;&nbsp;&nbsp; def __init__(self, w, h):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.width = w</tt> <br> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.width = w</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.height = h</tt> </p> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.height = h</tt> </p>
<p><tt>&nbsp;&nbsp;&nbsp; def describe(self):</tt> <br> <p><tt>&nbsp;&nbsp;&nbsp; def describe(self):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print "This shrubbery is", <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print "This shrubbery is",
self.width, \</tt> <br> self.width, \</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
"by", self.height, "cubits."</tt></p> "by", self.height, "cubits."</tt></p>
...@@ -46,8 +46,8 @@ self.width, \</tt> <br> ...@@ -46,8 +46,8 @@ self.width, \</tt> <br>
As you can see, a Cython extension type definition looks a lot like a Python As you can see, a Cython extension type definition looks a lot like a Python
class definition. Within it, you use the <b>def</b> statement to define class definition. Within it, you use the <b>def</b> statement to define
methods that can be called from Python code. You can even define many of methods that can be called from Python code. You can even define many of
the special methods such as <tt>__init__</tt> as you would in Python. the special methods such as <tt>__init__</tt> as you would in Python.
<p>The main difference is that you can use the <b>cdef</b> statement to define <p>The main difference is that you can use the <b>cdef</b> statement to define
attributes. The attributes may be Python objects (either generic or of a particular attributes. The attributes may be Python objects (either generic or of a particular
extension type), or they may be of any C data type. So you can use extension extension type), or they may be of any C data type. So you can use extension
types to wrap arbitrary C data structures and provide a Python-like interface types to wrap arbitrary C data structures and provide a Python-like interface
...@@ -56,50 +56,50 @@ to them. </p> ...@@ -56,50 +56,50 @@ to them. </p>
Attributes of an extension type are stored directly in the object's C struct. Attributes of an extension type are stored directly in the object's C struct.
The set of attributes is fixed at compile time; you can't add attributes The set of attributes is fixed at compile time; you can't add attributes
to an extension type instance at run time simply by assigning to them, as to an extension type instance at run time simply by assigning to them, as
you could with a Python class instance. (You can subclass the extension type you could with a Python class instance. (You can subclass the extension type
in Python and add attributes to instances of the subclass, however.) in Python and add attributes to instances of the subclass, however.)
<p>There are two ways that attributes of an extension type can be accessed: <p>There are two ways that attributes of an extension type can be accessed:
by Python attribute lookup, or by direct access to the C struct from Cython by Python attribute lookup, or by direct access to the C struct from Cython
code. Python code is only able to access attributes of an extension type code. Python code is only able to access attributes of an extension type
by the first method, but Cython code can use either method. </p> by the first method, but Cython code can use either method. </p>
<p>By default, extension type attributes are only accessible by direct access, <p>By default, extension type attributes are only accessible by direct access,
not Python access, which means that they are not accessible from Python code. not Python access, which means that they are not accessible from Python code.
To make them accessible from Python code, you need to declare them as <tt>public</tt> or <tt>readonly</tt>. For example, </p> To make them accessible from Python code, you need to declare them as <tt>public</tt> or <tt>readonly</tt>. For example, </p>
<blockquote><tt>cdef class Shrubbery:</tt> <br> <blockquote><tt>cdef class Shrubbery:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; cdef public int width, height</tt> <br> <tt>&nbsp;&nbsp;&nbsp; cdef public int width, height</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; cdef readonly float depth</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; cdef readonly float depth</tt></blockquote>
makes the <tt>width</tt> and <tt>height</tt> attributes readable and writable makes the <tt>width</tt> and <tt>height</tt> attributes readable and writable
from Python code, and the <tt>depth</tt> attribute readable but not writable. from Python code, and the <tt>depth</tt> attribute readable but not writable.
<p>Note that you can only expose simple C types, such as ints, floats and <p>Note that you can only expose simple C types, such as ints, floats and
strings, for Python access. You can also expose Python-valued attributes, strings, for Python access. You can also expose Python-valued attributes,
although read-write exposure is only possible for generic Python attributes although read-write exposure is only possible for generic Python attributes
(of type <tt>object</tt>). If the attribute is declared to be of an extension (of type <tt>object</tt>). If the attribute is declared to be of an extension
type, it must be exposed <tt>readonly</tt>. </p> type, it must be exposed <tt>readonly</tt>. </p>
<p>Note also that the <tt>public</tt> and <tt>readonly</tt> options apply <p>Note also that the <tt>public</tt> and <tt>readonly</tt> options apply
only to <i>Python</i> access, not direct access. All the attributes of an only to <i>Python</i> access, not direct access. All the attributes of an
extension type are always readable and writable by direct access. </p> extension type are always readable and writable by direct access. </p>
<p>Howerver, for direct access to be possible, the Cython compiler must know <p>Howerver, for direct access to be possible, the Cython compiler must know
that you have an instance of that type, and not just a generic Python object. that you have an instance of that type, and not just a generic Python object.
It knows this already in the case of the "self" parameter of the methods of It knows this already in the case of the "self" parameter of the methods of
that type, but in other cases you will have to tell it by means of a declaration. that type, but in other cases you will have to tell it by means of a declaration.
For example, </p> For example, </p>
<blockquote><tt>cdef widen_shrubbery(Shrubbery sh, extra_width):</tt> <br> <blockquote><tt>cdef widen_shrubbery(Shrubbery sh, extra_width):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width</tt></blockquote>
If you attempt to access an extension type attribute through a generic If you attempt to access an extension type attribute through a generic
object reference, Cython will use a Python attribute lookup. If the attribute object reference, Cython will use a Python attribute lookup. If the attribute
is exposed for Python access (using <tt>public</tt> or <tt>readonly</tt>) is exposed for Python access (using <tt>public</tt> or <tt>readonly</tt>)
then this will work, but it will be much slower than direct access. then this will work, but it will be much slower than direct access.
<h2> <a name="NotNone"></a>Extension types and None</h2> <h2> <a name="NotNone"></a>Extension types and None</h2>
When you declare a parameter or C variable as being of an extension type, When you declare a parameter or C variable as being of an extension type,
Cython will allow it to take on the value None as well as values of its declared Cython will allow it to take on the value None as well as values of its declared
type. This is analogous to the way a C pointer can take on the value NULL, type. This is analogous to the way a C pointer can take on the value NULL,
and you need to exercise the same caution because of it. There is no problem and you need to exercise the same caution because of it. There is no problem
as long as you are performing Python operations on it, because full dynamic as long as you are performing Python operations on it, because full dynamic
type checking will be applied. However, when you access C attributes of an type checking will be applied. However, when you access C attributes of an
extension type (as in the <tt>widen_shrubbery</tt> function above), it's up extension type (as in the <tt>widen_shrubbery</tt> function above), it's up
to you to make sure the reference you're using is not None -- in the interests to you to make sure the reference you're using is not None -- in the interests
of efficiency, Cython does <i>not</i> check this. of efficiency, Cython does <i>not</i> check this.
<p>You need to be particularly careful when exposing Python functions which <p>You need to be particularly careful when exposing Python functions which
take extension types as arguments. If we wanted to make <tt>widen_shrubbery</tt> take extension types as arguments. If we wanted to make <tt>widen_shrubbery</tt>
a Python function, for example, if we simply wrote </p> a Python function, for example, if we simply wrote </p>
...@@ -107,7 +107,7 @@ a Python function, for example, if we simply wrote </p> ...@@ -107,7 +107,7 @@ a Python function, for example, if we simply wrote </p>
<tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
# <font color="#ed181e">dangerous!</font></tt></blockquote> # <font color="#ed181e">dangerous!</font></tt></blockquote>
then users of our module could crash it by passing None for the <tt>sh</tt> then users of our module could crash it by passing None for the <tt>sh</tt>
parameter. parameter.
<p>One way to fix this would be </p> <p>One way to fix this would be </p>
<blockquote><tt>def widen_shrubbery(Shrubbery sh, extra_width):</tt> <br> <blockquote><tt>def widen_shrubbery(Shrubbery sh, extra_width):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; if sh is None:</tt> <br> <tt>&nbsp;&nbsp;&nbsp; if sh is None:</tt> <br>
...@@ -115,12 +115,12 @@ parameter. ...@@ -115,12 +115,12 @@ parameter.
<tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width</tt></blockquote>
but since this is anticipated to be such a frequent requirement, Cython but since this is anticipated to be such a frequent requirement, Cython
provides a more convenient way. Parameters of a Python function declared provides a more convenient way. Parameters of a Python function declared
as an extension type can have a <b><tt>not None</tt></b> clause: as an extension type can have a <b><tt>not None</tt></b> clause:
<blockquote><tt>def widen_shrubbery(Shrubbery sh not None, extra_width):</tt> <blockquote><tt>def widen_shrubbery(Shrubbery sh not None, extra_width):</tt>
<br> <br>
<tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; sh.width = sh.width + extra_width</tt></blockquote>
Now the function will automatically check that <tt>sh</tt> is not None Now the function will automatically check that <tt>sh</tt> is not None
along with checking that it has the right type. along with checking that it has the right type.
<p>Note, however that the <tt>not None</tt> clause can <i>only</i> be used <p>Note, however that the <tt>not None</tt> clause can <i>only</i> be used
in Python functions (defined with <tt>def</tt>) and not C functions (defined in Python functions (defined with <tt>def</tt>) and not C functions (defined
with <tt>cdef</tt>). If you need to check whether a parameter to a C function with <tt>cdef</tt>). If you need to check whether a parameter to a C function
...@@ -131,19 +131,19 @@ along with checking that it has the right type. ...@@ -131,19 +131,19 @@ along with checking that it has the right type.
never to be None.</li> never to be None.</li>
</ul> </ul>
<ul> <ul>
<li> When comparing a value with None, keep in mind that, if <tt>x</tt> is a Python object, <tt>x is None</tt> and <tt>x is not None</tt> are very <li> When comparing a value with None, keep in mind that, if <tt>x</tt> is a Python object, <tt>x is None</tt> and <tt>x is not None</tt> are very
efficient because they translate directly to C pointer comparisons, whereas efficient because they translate directly to C pointer comparisons, whereas
<tt>x == None</tt> and <tt>x != None</tt>, or simply using <tt>x</tt> as a boolean value (as in <tt>if x: ...</tt>) will invoke Python operations <tt>x == None</tt> and <tt>x != None</tt>, or simply using <tt>x</tt> as a boolean value (as in <tt>if x: ...</tt>) will invoke Python operations
and therefore be much slower.</li> and therefore be much slower.</li>
</ul> </ul>
<h2> <a name="ExtTypeSpecialMethods"></a>Special methods</h2> <h2> <a name="ExtTypeSpecialMethods"></a>Special methods</h2>
Although the principles are similar, there are substantial differences Although the principles are similar, there are substantial differences
between many of the <span style="font-family: monospace;">__xxx__</span> special methods of extension types and their between many of the <span style="font-family: monospace;">__xxx__</span> special methods of extension types and their
Python counterparts. There is a <a href="special_methods.html">separate page</a> devoted to this subject, and you should read it carefully before attempting Python counterparts. There is a <a href="special_methods.html">separate page</a> devoted to this subject, and you should read it carefully before attempting
to use any special methods in your extension types. to use any special methods in your extension types.
<h2> <a name="Properties"></a>Properties</h2> <h2> <a name="Properties"></a>Properties</h2>
There is a special syntax for defining <b>properties</b> in an extension There is a special syntax for defining <b>properties</b> in an extension
class: class:
<blockquote><tt>cdef class Spam:</tt> <p><tt>&nbsp;&nbsp;&nbsp; property cheese:</tt> </p> <blockquote><tt>cdef class Spam:</tt> <p><tt>&nbsp;&nbsp;&nbsp; property cheese:</tt> </p>
<p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "A doc string can go <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "A doc string can go
here."</tt> </p> here."</tt> </p>
...@@ -166,8 +166,8 @@ here."</tt> </p> ...@@ -166,8 +166,8 @@ here."</tt> </p>
&nbsp;</p> &nbsp;</p>
</blockquote> </blockquote>
The <tt>__get__</tt>, <tt>__set__</tt> and <tt>__del__</tt> methods are The <tt>__get__</tt>, <tt>__set__</tt> and <tt>__del__</tt> methods are
all optional; if they are omitted, an exception will be raised when the corresponding all optional; if they are omitted, an exception will be raised when the corresponding
operation is attempted. operation is attempted.
<p>Here's a complete example. It defines a property which adds to a list <p>Here's a complete example. It defines a property which adds to a list
each time it is written to, returns the list when it is read, and empties each time it is written to, returns the list when it is read, and empties
the list when it is deleted. <br> the list when it is deleted. <br>
...@@ -217,16 +217,16 @@ the list when it is deleted. <br> ...@@ -217,16 +217,16 @@ the list when it is deleted. <br>
</center> </center>
<h2> <a name="SubclassingExtTypes"></a>Subclassing</h2> <h2> <a name="SubclassingExtTypes"></a>Subclassing</h2>
An extension type may inherit from a built-in type or another extension An extension type may inherit from a built-in type or another extension
type: type:
<blockquote><tt>cdef class Parrot:</tt> <br> <blockquote><tt>cdef class Parrot:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt><tt></tt> <p><tt>cdef class Norwegian(Parrot):</tt> <br> <tt>&nbsp;&nbsp;&nbsp; ...</tt><tt></tt> <p><tt>cdef class Norwegian(Parrot):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></p> <tt>&nbsp;&nbsp;&nbsp; ...</tt></p>
</blockquote> </blockquote>
<p><br> <p><br>
A complete definition of the base type must be available to Cython, so if A complete definition of the base type must be available to Cython, so if
the base type is a built-in type, it must have been previously declared as the base type is a built-in type, it must have been previously declared as
an <b>extern</b> extension type. If the base type is defined in another Cython an <b>extern</b> extension type. If the base type is defined in another Cython
module, it must either be declared as an extern extension type or imported module, it must either be declared as an extern extension type or imported
using the <b><a href="sharing.html">cimport</a></b> statement. </p> using the <b><a href="sharing.html">cimport</a></b> statement. </p>
<p>An extension type can only have one base class (no multiple inheritance). <p>An extension type can only have one base class (no multiple inheritance).
</p> </p>
...@@ -236,8 +236,8 @@ rules for multiple inheritance are followed (i.e. the C layouts of all the ...@@ -236,8 +236,8 @@ rules for multiple inheritance are followed (i.e. the C layouts of all the
base classes must be compatible).<br> base classes must be compatible).<br>
</p> </p>
<h2><a name="CMethods"></a>C methods</h2> <h2><a name="CMethods"></a>C methods</h2>
Extension types can have C methods as well as Python methods. Like C functions, Extension types can have C methods as well as Python methods. Like C functions,
C methods are declared using <tt>cdef</tt> instead of <tt>def</tt>. C methods C methods are declared using <tt>cdef</tt> instead of <tt>def</tt>. C methods
are "virtual", and may be overridden in derived extension types.<br> are "virtual", and may be overridden in derived extension types.<br>
<br> <br>
<table align="center" cellpadding="5"> <table align="center" cellpadding="5">
...@@ -285,7 +285,7 @@ C method using the usual Python technique, i.e.<br> ...@@ -285,7 +285,7 @@ C method using the usual Python technique, i.e.<br>
<h2><a name="ForwardDeclaringExtTypes"></a>Forward-declaring extension types</h2> <h2><a name="ForwardDeclaringExtTypes"></a>Forward-declaring extension types</h2>
Extension types can be forward-declared, like struct and union types. This Extension types can be forward-declared, like struct and union types. This
will be necessary if you have two extension types that need to refer to will be necessary if you have two extension types that need to refer to
each other, e.g. each other, e.g.
<blockquote><tt>cdef class Shrubbery # forward declaration</tt> <p><tt>cdef class Shrubber:</tt> <br> <blockquote><tt>cdef class Shrubbery # forward declaration</tt> <p><tt>cdef class Shrubber:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; cdef Shrubbery work_in_progress</tt> </p> <tt>&nbsp;&nbsp;&nbsp; cdef Shrubbery work_in_progress</tt> </p>
<p><tt>cdef class Shrubbery:</tt> <br> <p><tt>cdef class Shrubbery:</tt> <br>
...@@ -315,21 +315,21 @@ type <span style="font-family: monospace;">object</span> called <span style="fon ...@@ -315,21 +315,21 @@ type <span style="font-family: monospace;">object</span> called <span style="fon
<br> <br>
<h2><a name="PublicAndExtern"></a>Public and external extension types</h2> <h2><a name="PublicAndExtern"></a>Public and external extension types</h2>
Extension types can be declared <b>extern</b> or <b>public</b>. An <a href="#ExternalExtTypes"><b>extern</b> extension type declaration</a> makes Extension types can be declared <b>extern</b> or <b>public</b>. An <a href="#ExternalExtTypes"><b>extern</b> extension type declaration</a> makes
an extension type defined in external C code available to a Cython module. an extension type defined in external C code available to a Cython module.
A <a href="#PublicExtensionTypes"><b>public</b> extension type declaration</a> makes an extension type defined in a Cython module available to external C A <a href="#PublicExtensionTypes"><b>public</b> extension type declaration</a> makes an extension type defined in a Cython module available to external C
code. code.
<h3> <a name="ExternalExtTypes"></a>External extension types</h3> <h3> <a name="ExternalExtTypes"></a>External extension types</h3>
An <b>extern</b> extension type allows you to gain access to the internals An <b>extern</b> extension type allows you to gain access to the internals
of Python objects defined in the Python core or in a non-Cython extension of Python objects defined in the Python core or in a non-Cython extension
module. module.
<blockquote><b>NOTE:</b> In Cython versions before 0.8, <b>extern</b> extension <blockquote><b>NOTE:</b> In Cython versions before 0.8, <b>extern</b> extension
types were also used to reference extension types defined in another Cython types were also used to reference extension types defined in another Cython
module. While you can still do that, Cython 0.8 and later provides a better module. While you can still do that, Cython 0.8 and later provides a better
mechanism for this. See <a href="sharing.html">Sharing C Declarations Between mechanism for this. See <a href="sharing.html">Sharing C Declarations Between
Cython Modules</a>.</blockquote> Cython Modules</a>.</blockquote>
Here is an example which will let you get at the C-level members of the Here is an example which will let you get at the C-level members of the
built-in <i>complex</i> object. built-in <i>complex</i> object.
<blockquote><tt>cdef extern from "complexobject.h":</tt> <p><tt>&nbsp;&nbsp;&nbsp; struct Py_complex:</tt> <br> <blockquote><tt>cdef extern from "complexobject.h":</tt> <p><tt>&nbsp;&nbsp;&nbsp; struct Py_complex:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double real</tt> <br> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double real</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double imag</tt> </p> <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double imag</tt> </p>
...@@ -342,7 +342,7 @@ built-in <i>complex</i> object. ...@@ -342,7 +342,7 @@ built-in <i>complex</i> object.
<tt>&nbsp;&nbsp;&nbsp; print "Real:", c.cval.real</tt> <br> <tt>&nbsp;&nbsp;&nbsp; print "Real:", c.cval.real</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; print "Imag:", c.cval.imag</tt></p> <tt>&nbsp;&nbsp;&nbsp; print "Imag:", c.cval.imag</tt></p>
</blockquote> </blockquote>
Some important things to note are: Some important things to note are:
<ol> <ol>
<li> In this example, <b>ctypedef class</b> has been used. This is because, <li> In this example, <b>ctypedef class</b> has been used. This is because,
in the Python header files, the <tt>PyComplexObject</tt> struct is declared in the Python header files, the <tt>PyComplexObject</tt> struct is declared
...@@ -353,13 +353,13 @@ built-in <i>complex</i> object. ...@@ -353,13 +353,13 @@ built-in <i>complex</i> object.
<tt>} PyComplexObject;<br> <tt>} PyComplexObject;<br>
<br> <br>
</tt></div> </tt></div>
</li><li>As well as the name of the extension type, the <i>module</i> in which </li><li>As well as the name of the extension type, the <i>module</i> in which
its type object can be found is also specified. See the <a href="#ImplicitImport">implicit importing</a> section below.&nbsp; <br> its type object can be found is also specified. See the <a href="#ImplicitImport">implicit importing</a> section below.&nbsp; <br>
<br> <br>
</li> </li>
<li> When declaring an external extension type, you don't declare <li> When declaring an external extension type, you don't declare
any methods. Declaration of methods is not required in order to call them, any methods. Declaration of methods is not required in order to call them,
because the calls are Python method calls. Also, as with structs and unions, because the calls are Python method calls. Also, as with structs and unions,
if your extension class declaration is inside a <i>cdef extern from</i> block, if your extension class declaration is inside a <i>cdef extern from</i> block,
you only need to declare those C members which you wish to access.</li> you only need to declare those C members which you wish to access.</li>
</ol> </ol>
...@@ -370,26 +370,26 @@ extension types. I apologise for this, but for complicated reasons it proved ...@@ -370,26 +370,26 @@ extension types. I apologise for this, but for complicated reasons it proved
to be too difficult to continue supporting the old way of doing these while to be too difficult to continue supporting the old way of doing these while
introducing the new features that I wanted.</blockquote> introducing the new features that I wanted.</blockquote>
Cython 0.8 and later requires you to include a module name in an extern Cython 0.8 and later requires you to include a module name in an extern
extension class declaration, for example, extension class declaration, for example,
<blockquote><tt>cdef extern class MyModule.Spam:</tt> <br> <blockquote><tt>cdef extern class MyModule.Spam:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
The type object will be implicitly imported from the specified module and The type object will be implicitly imported from the specified module and
bound to the corresponding name in this module. In other words, in this bound to the corresponding name in this module. In other words, in this
example an implicit example an implicit
<ol> <ol>
<pre>from <tt>MyModule</tt> import Spam</pre> <pre>from <tt>MyModule</tt> import Spam</pre>
</ol> </ol>
statement will be executed at module load time. statement will be executed at module load time.
<p>The module name can be a dotted name to refer to a module inside a package <p>The module name can be a dotted name to refer to a module inside a package
hierarchy, for example, </p> hierarchy, for example, </p>
<blockquote><tt>cdef extern class My.Nested.Package.Spam:</tt> <br> <blockquote><tt>cdef extern class My.Nested.Package.Spam:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
You can also specify an alternative name under which to import the type You can also specify an alternative name under which to import the type
using an <b>as</b> clause, for example, using an <b>as</b> clause, for example,
<ol> <ol>
<tt>cdef extern class My.Nested.Package.Spam as Yummy:</tt> <br> <tt>cdef extern class My.Nested.Package.Spam as Yummy:</tt> <br>
<tt>&nbsp;&nbsp; ...</tt> </ol> <tt>&nbsp;&nbsp; ...</tt> </ol>
which corresponds to the implicit import statement which corresponds to the implicit import statement
<ol> <ol>
<pre>from <tt>My.Nested.Package</tt> import <tt>Spam</tt> as <tt>Yummy</tt></pre> <pre>from <tt>My.Nested.Package</tt> import <tt>Spam</tt> as <tt>Yummy</tt></pre>
</ol> </ol>
...@@ -398,7 +398,7 @@ using an <b>as</b> clause, for example, ...@@ -398,7 +398,7 @@ using an <b>as</b> clause, for example,
purposes. When used in an expression, it refers to a module-level global purposes. When used in an expression, it refers to a module-level global
variable holding the type's constructor (i.e. its type-object). However, variable holding the type's constructor (i.e. its type-object). However,
it can also be used as a C type name to declare variables, arguments and it can also be used as a C type name to declare variables, arguments and
return values of that type. return values of that type.
<p>When you declare </p> <p>When you declare </p>
<blockquote><tt>cdef extern class MyModule.Spam:</tt> <br> <blockquote><tt>cdef extern class MyModule.Spam:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
...@@ -406,35 +406,35 @@ return values of that type. ...@@ -406,35 +406,35 @@ return values of that type.
by which you can refer to the constructor, but only <tt>Spam</tt> can be by which you can refer to the constructor, but only <tt>Spam</tt> can be
used as a type name. For example, if you were to explicity <tt>import MyModule</tt>, used as a type name. For example, if you were to explicity <tt>import MyModule</tt>,
you could use<tt> MyModule.Spam()</tt> to create a Spam instance, but you you could use<tt> MyModule.Spam()</tt> to create a Spam instance, but you
wouldn't be able to use <tt>MyModule.Spam</tt> as a type name. wouldn't be able to use <tt>MyModule.Spam</tt> as a type name.
<p>When an <b>as</b> clause is used, the name specified in the <b>as</b> <p>When an <b>as</b> clause is used, the name specified in the <b>as</b>
clause also takes over both roles. So if you declare </p> clause also takes over both roles. So if you declare </p>
<blockquote><tt>cdef extern class MyModule.Spam as Yummy:</tt> <br> <blockquote><tt>cdef extern class MyModule.Spam as Yummy:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
then <tt>Yummy</tt> becomes both the type name and a name for the constructor. then <tt>Yummy</tt> becomes both the type name and a name for the constructor.
Again, there are other ways that you could get hold of the constructor, Again, there are other ways that you could get hold of the constructor,
but only <tt>Yummy</tt> is usable as a type name. but only <tt>Yummy</tt> is usable as a type name.
<h3> <a name="PublicExtensionTypes"></a>Public extension types</h3> <h3> <a name="PublicExtensionTypes"></a>Public extension types</h3>
An extension type can be declared <b>public</b>, in which case a <b>.h</b> An extension type can be declared <b>public</b>, in which case a <b>.h</b>
file is generated containing declarations for its object struct and type file is generated containing declarations for its object struct and type
object. By including the <b>.h</b> file in external C code that you write, object. By including the <b>.h</b> file in external C code that you write,
that code can access the attributes of the extension type. that code can access the attributes of the extension type.
<h3> <a name="NameSpecClause"></a>Name specification clause</h3> <h3> <a name="NameSpecClause"></a>Name specification clause</h3>
The part of the class declaration in square brackets is a special feature The part of the class declaration in square brackets is a special feature
only available for <b>extern</b> or <b>public</b> extension types. The full only available for <b>extern</b> or <b>public</b> extension types. The full
form of this clause is form of this clause is
<blockquote><tt>[object </tt><i>object_struct_name</i><tt>, type </tt><i>type_object_name</i><span style="font-family: monospace;"> ]</span></blockquote> <blockquote><tt>[object </tt><i>object_struct_name</i><tt>, type </tt><i>type_object_name</i><span style="font-family: monospace;"> ]</span></blockquote>
where <i>object_struct_name</i> is the name to assume for the type's C where <i>object_struct_name</i> is the name to assume for the type's C
struct, and <i>type_object_name</i> is the name to assume for the type's struct, and <i>type_object_name</i> is the name to assume for the type's
statically declared type object. (The object and type clauses can be written statically declared type object. (The object and type clauses can be written
in either order.) in either order.)
<p>If the extension type declaration is inside a <b>cdef extern from</b> <p>If the extension type declaration is inside a <b>cdef extern from</b>
block, the <b>object</b> clause is required, because Cython must be able to block, the <b>object</b> clause is required, because Cython must be able to
generate code that is compatible with the declarations in the header file. generate code that is compatible with the declarations in the header file.
Otherwise, for <b>extern</b> extension types, the <b>object</b> clause is Otherwise, for <b>extern</b> extension types, the <b>object</b> clause is
optional. </p> optional. </p>
<p>For <b>public</b> extension types, the <b>object</b> and <b>type</b> clauses <p>For <b>public</b> extension types, the <b>object</b> and <b>type</b> clauses
are both required, because Cython must be able to generate code that is compatible are both required, because Cython must be able to generate code that is compatible
with external C code. </p> with external C code. </p>
<p> </p> <p> </p>
<hr width="100%"> <br> <hr width="100%"> <br>
......
<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en"> <!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html><head> <html><head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"> <meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]">
<title>Cython Language Overview</title> <title>Cython Language Overview</title>
</head> </head>
<body> <body>
<h1> <hr width="100%">Overview of the Cython Language&nbsp; <hr width="100%"></h1> <h1> <hr width="100%">Overview of the Cython Language&nbsp; <hr width="100%"></h1>
This document informally describes the extensions to the Python language This document informally describes the extensions to the Python language
made by Cython. Some day there will be a reference manual covering everything made by Cython. Some day there will be a reference manual covering everything
in more detail. <br> in more detail. <br>
&nbsp; &nbsp;
<h2> Contents</h2> <h2> Contents</h2>
<ul> <ul>
<li> <a href="#Basics">Basics</a></li> <li> <a href="#Basics">Basics</a></li>
...@@ -65,90 +65,90 @@ expressions<br> ...@@ -65,90 +65,90 @@ expressions<br>
<li> <a href="#SemanticDifferences">Semantic differences between Python <li> <a href="#SemanticDifferences">Semantic differences between Python
and Cython</a></li> and Cython</a></li>
</ul> </ul>
</ul> </ul>
<h2> <hr width="100%"><a name="Basics"></a>Basics <h2> <hr width="100%"><a name="Basics"></a>Basics
<hr width="100%"></h2> <hr width="100%"></h2>
This section describes the basic features of the Cython language. The facilities This section describes the basic features of the Cython language. The facilities
covered in this section allow you to create Python-callable functions that covered in this section allow you to create Python-callable functions that
manipulate C data structures and convert between Python and C data types. manipulate C data structures and convert between Python and C data types.
Later sections will cover facilities for <a href="#InterfacingWithExternal">wrapping external C code</a>, <a href="extension_types.html">creating new Python types</a> and <a href="sharing.html">cooperation between Cython modules</a>. Later sections will cover facilities for <a href="#InterfacingWithExternal">wrapping external C code</a>, <a href="extension_types.html">creating new Python types</a> and <a href="sharing.html">cooperation between Cython modules</a>.
<h3> <a name="PyFuncsVsCFuncs"></a>Python functions vs. C functions</h3> <h3> <a name="PyFuncsVsCFuncs"></a>Python functions vs. C functions</h3>
There are two kinds of function definition in Cython: There are two kinds of function definition in Cython:
<p><b>Python functions</b> are defined using the <b>def</b> statement, as <p><b>Python functions</b> are defined using the <b>def</b> statement, as
in Python. They take Python objects as parameters and return Python objects. in Python. They take Python objects as parameters and return Python objects.
</p> </p>
<p><b>C functions</b> are defined using the new <b>cdef</b> statement. They <p><b>C functions</b> are defined using the new <b>cdef</b> statement. They
take either Python objects or C values as parameters, and can return either take either Python objects or C values as parameters, and can return either
Python objects or C values. </p> Python objects or C values. </p>
<p>Within a Cython module, Python functions and C functions can call each other <p>Within a Cython module, Python functions and C functions can call each other
freely, but only Python functions can be called from outside the module by freely, but only Python functions can be called from outside the module by
interpreted Python code. So, any functions that you want to "export" from interpreted Python code. So, any functions that you want to "export" from
your Cython module must be declared as Python functions using <span style="font-weight: bold;">def</span>. </p> your Cython module must be declared as Python functions using <span style="font-weight: bold;">def</span>. </p>
<p>Parameters of either type of function can be declared to have C data types, <p>Parameters of either type of function can be declared to have C data types,
using normal C declaration syntax. For example, </p> using normal C declaration syntax. For example, </p>
<blockquote> <pre>def spam(int i, char *s):<br>&nbsp;&nbsp;&nbsp; ...</pre> <blockquote> <pre>def spam(int i, char *s):<br>&nbsp;&nbsp;&nbsp; ...</pre>
<pre>cdef int eggs(unsigned long l, float f):<br>&nbsp;&nbsp;&nbsp; ...</pre> <pre>cdef int eggs(unsigned long l, float f):<br>&nbsp;&nbsp;&nbsp; ...</pre>
</blockquote> </blockquote>
When a parameter of a Python function is declared to have a C data type, When a parameter of a Python function is declared to have a C data type,
it is passed in as a Python object and automatically converted to a C value, it is passed in as a Python object and automatically converted to a C value,
if possible. Automatic conversion is currently only possible for numeric if possible. Automatic conversion is currently only possible for numeric
types and string types; attempting to use any other type for the parameter types and string types; attempting to use any other type for the parameter
of a Python function will result in a compile-time error. of a Python function will result in a compile-time error.
<p>C functions, on the other hand, can have parameters of any type, since <p>C functions, on the other hand, can have parameters of any type, since
they're passed in directly using a normal C function call. </p> they're passed in directly using a normal C function call. </p>
<h3> <a name="PyObjParams"></a>Python objects as parameters and return values</h3> <h3> <a name="PyObjParams"></a>Python objects as parameters and return values</h3>
If no type is specified for a parameter or return value, <i>it is assumed If no type is specified for a parameter or return value, <i>it is assumed
to be a Python object.</i> (Note that this is different from the C convention, to be a Python object.</i> (Note that this is different from the C convention,
where it would default to <tt>int</tt>.) For example, the following defines where it would default to <tt>int</tt>.) For example, the following defines
a C function that takes two Python objects as parameters and returns a Python a C function that takes two Python objects as parameters and returns a Python
object: object:
<blockquote> <pre>cdef spamobjs(x, y):<br>&nbsp;&nbsp;&nbsp; ...</pre> <blockquote> <pre>cdef spamobjs(x, y):<br>&nbsp;&nbsp;&nbsp; ...</pre>
</blockquote> </blockquote>
Reference counting for these objects is performed automatically according Reference counting for these objects is performed automatically according
to the standard Python/C API rules (i.e. borrowed references are taken as to the standard Python/C API rules (i.e. borrowed references are taken as
parameters and a new reference is returned). parameters and a new reference is returned).
<p>The name <b>object</b> can also be used to explicitly declare something <p>The name <b>object</b> can also be used to explicitly declare something
as a Python object. This can be useful if the name being declared would otherwise as a Python object. This can be useful if the name being declared would otherwise
be taken as the name of a type, for example, </p> be taken as the name of a type, for example, </p>
<blockquote> <pre>cdef ftang(object int):<br>&nbsp;&nbsp;&nbsp; ...</pre> <blockquote> <pre>cdef ftang(object int):<br>&nbsp;&nbsp;&nbsp; ...</pre>
</blockquote> </blockquote>
declares a parameter called <tt>int</tt> which is a Python object. You declares a parameter called <tt>int</tt> which is a Python object. You
can also use <b>object </b>as the explicit return type of a function, e.g. can also use <b>object </b>as the explicit return type of a function, e.g.
<blockquote> <pre>cdef object ftang(object int):<br>&nbsp;&nbsp;&nbsp; ...</pre> <blockquote> <pre>cdef object ftang(object int):<br>&nbsp;&nbsp;&nbsp; ...</pre>
</blockquote> </blockquote>
In the interests of clarity, it is probably a good idea to always be explicit In the interests of clarity, it is probably a good idea to always be explicit
about <b>object </b>parameters in C functions. about <b>object </b>parameters in C functions.
<h3> <a name="CVarAndTypeDecls"></a>C variable and type definitions</h3> <h3> <a name="CVarAndTypeDecls"></a>C variable and type definitions</h3>
The <b>cdef</b> statement is also used to declare C variables, either The <b>cdef</b> statement is also used to declare C variables, either
local or module-level: local or module-level:
<blockquote> <pre>cdef int i, j, k<br>cdef float f, g[42], *h</pre> <blockquote> <pre>cdef int i, j, k<br>cdef float f, g[42], *h</pre>
</blockquote> </blockquote>
and C struct, union or enum types: and C struct, union or enum types:
<blockquote> <pre>cdef struct Grail:<br>&nbsp;&nbsp;&nbsp; int age<br>&nbsp;&nbsp;&nbsp; float volume</pre> <blockquote> <pre>cdef struct Grail:<br>&nbsp;&nbsp;&nbsp; int age<br>&nbsp;&nbsp;&nbsp; float volume</pre>
<pre>cdef union Food:<br>&nbsp;&nbsp;&nbsp; char *spam<br>&nbsp;&nbsp;&nbsp; float *eggs</pre> <pre>cdef union Food:<br>&nbsp;&nbsp;&nbsp; char *spam<br>&nbsp;&nbsp;&nbsp; float *eggs</pre>
<pre>cdef enum CheeseType:<br>&nbsp;&nbsp;&nbsp; cheddar, edam,&nbsp;<br>&nbsp;&nbsp;&nbsp; camembert</pre> <pre>cdef enum CheeseType:<br>&nbsp;&nbsp;&nbsp; cheddar, edam,&nbsp;<br>&nbsp;&nbsp;&nbsp; camembert</pre>
...@@ -156,21 +156,21 @@ local or module-level: ...@@ -156,21 +156,21 @@ local or module-level:
</blockquote> </blockquote>
There is currently no special syntax for defining a constant, but you There is currently no special syntax for defining a constant, but you
can use an anonymous enum declaration for this purpose, for example, can use an anonymous enum declaration for this purpose, for example,
<blockquote><tt>cdef enum:</tt> <br> <blockquote><tt>cdef enum:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; tons_of_spam = 3</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; tons_of_spam = 3</tt></blockquote>
Note that the words <span style="font-family: monospace;">struct</span>, <span style="font-family: monospace;">union</span> and <span style="font-family: monospace;">enum</span> are used only when <i>defining</i> a type, not when referring to it. For example, to declare a variable pointing Note that the words <span style="font-family: monospace;">struct</span>, <span style="font-family: monospace;">union</span> and <span style="font-family: monospace;">enum</span> are used only when <i>defining</i> a type, not when referring to it. For example, to declare a variable pointing
to a Grail you would write to a Grail you would write
<blockquote> <pre>cdef Grail *gp</pre> <blockquote> <pre>cdef Grail *gp</pre>
</blockquote> </blockquote>
and <i>not</i> and <i>not</i>
<blockquote> <pre>cdef struct Grail *gp <font color="#ed181e"># WRONG</font></pre> <blockquote> <pre>cdef struct Grail *gp <font color="#ed181e"># WRONG</font></pre>
</blockquote> </blockquote>
There is also a <b>ctypedef</b> statement for giving names to types, e.g. There is also a <b>ctypedef</b> statement for giving names to types, e.g.
<blockquote> <pre>ctypedef unsigned long ULong</pre> <blockquote> <pre>ctypedef unsigned long ULong</pre>
<pre>ctypedef int *IntPtr<br></pre></blockquote> <pre>ctypedef int *IntPtr<br></pre></blockquote>
...@@ -222,9 +222,9 @@ unsigned long<br> ...@@ -222,9 +222,9 @@ unsigned long<br>
</td> </td>
</tr> </tr>
<tr> <tr>
</tr> </tr>
<tr> <tr>
<td style="vertical-align: top; width: 40%; white-space: nowrap;">float, double, long double<br> <td style="vertical-align: top; width: 40%; white-space: nowrap;">float, double, long double<br>
...@@ -289,26 +289,26 @@ understand the issue and be careful what you do.<br> ...@@ -289,26 +289,26 @@ understand the issue and be careful what you do.<br>
</blockquote> </blockquote>
<h3> <a name="ScopeRules"></a>Scope rules</h3> <h3> <a name="ScopeRules"></a>Scope rules</h3>
Cython determines whether a variable belongs to a local scope, the module Cython determines whether a variable belongs to a local scope, the module
scope, or the built-in scope <i>completely statically.</i> As with Python, scope, or the built-in scope <i>completely statically.</i> As with Python,
assigning to a variable which is not otherwise declared implicitly declares assigning to a variable which is not otherwise declared implicitly declares
it to be a Python variable residing in the scope where it is assigned. Unlike it to be a Python variable residing in the scope where it is assigned. Unlike
Python, however, a name which is referred to but not declared or assigned Python, however, a name which is referred to but not declared or assigned
is assumed to reside in the <i>builtin scope, </i>not the module scope. is assumed to reside in the <i>builtin scope, </i>not the module scope.
Names added to the module dictionary at run time will not shadow such names. Names added to the module dictionary at run time will not shadow such names.
<p>You can use a <b>global</b> statement at the module level to explicitly <p>You can use a <b>global</b> statement at the module level to explicitly
declare a name to be a module-level name when there would otherwise not be declare a name to be a module-level name when there would otherwise not be
any indication of this, for example, </p> any indication of this, for example, </p>
<blockquote><tt>global __name__</tt> <br> <blockquote><tt>global __name__</tt> <br>
<tt>print __name__</tt></blockquote> <tt>print __name__</tt></blockquote>
Without the <b>global</b> statement, the above would print the name of Without the <b>global</b> statement, the above would print the name of
the builtins module.<br> the builtins module.<br>
<br> <br>
...@@ -318,35 +318,35 @@ the builtins module.<br> ...@@ -318,35 +318,35 @@ the builtins module.<br>
to it. In particular, tricks such as the following will <i>not</i> work to it. In particular, tricks such as the following will <i>not</i> work
in Cython:<br> in Cython:<br>
<blockquote> <pre>try:<br>&nbsp; x = True<br>except NameError:<br>&nbsp; True = 1<br></pre> <blockquote> <pre>try:<br>&nbsp; x = True<br>except NameError:<br>&nbsp; True = 1<br></pre>
</blockquote> </blockquote>
because, due to the assignment, the True will always be looked up in the because, due to the assignment, the True will always be looked up in the
module-level scope. You would have to do something like this instead:<br> module-level scope. You would have to do something like this instead:<br>
<blockquote> <pre>import __builtin__<br>try:<br> True = __builtin__.True<br>except AttributeError:<br> True = 1<br></pre> <blockquote> <pre>import __builtin__<br>try:<br> True = __builtin__.True<br>except AttributeError:<br> True = 1<br></pre>
</blockquote> </blockquote>
<hr width="100%"> <hr width="100%">
<h3> <a name="StatsAndExprs"></a>Statements and expressions</h3> <h3> <a name="StatsAndExprs"></a>Statements and expressions</h3>
Control structures and expressions follow Python syntax for the most part. Control structures and expressions follow Python syntax for the most part.
When applied to Python objects, they have the same semantics as in Python When applied to Python objects, they have the same semantics as in Python
(unless otherwise noted). Most of the Python operators can also be applied (unless otherwise noted). Most of the Python operators can also be applied
to C values, with the obvious semantics. to C values, with the obvious semantics.
<p>If Python objects and C values are mixed in an expression, conversions <p>If Python objects and C values are mixed in an expression, conversions
are performed automatically between Python objects and C numeric or string are performed automatically between Python objects and C numeric or string
types. </p> types. </p>
<p>Reference counts are maintained automatically for all Python objects, and <p>Reference counts are maintained automatically for all Python objects, and
all Python operations are automatically checked for errors, with appropriate all Python operations are automatically checked for errors, with appropriate
action taken. </p> action taken. </p>
<h4> <a name="ExprSyntaxDifferences"></a>Differences between C and Cython <h4> <a name="ExprSyntaxDifferences"></a>Differences between C and Cython
expressions</h4> expressions</h4>
There There
...@@ -358,18 +358,18 @@ no direct equivalent in Python.<br> ...@@ -358,18 +358,18 @@ no direct equivalent in Python.<br>
<li>An integer literal without an <span style="font-family: monospace; font-weight: bold;">L</span> suffix is treated as a C constant, and will be truncated to whatever size your C compiler thinks appropriate. With an <span style="font-family: monospace; font-weight: bold;">L</span> suffix, it will be converted to Python long integer (even if it would be small enough to fit into a C int).<br> <li>An integer literal without an <span style="font-family: monospace; font-weight: bold;">L</span> suffix is treated as a C constant, and will be truncated to whatever size your C compiler thinks appropriate. With an <span style="font-family: monospace; font-weight: bold;">L</span> suffix, it will be converted to Python long integer (even if it would be small enough to fit into a C int).<br>
<br> <br>
</li> </li>
<li> There is no <b><tt>-&gt;</tt></b> operator in Cython. Instead of <tt>p-&gt;x</tt>, <li> There is no <b><tt>-&gt;</tt></b> operator in Cython. Instead of <tt>p-&gt;x</tt>,
use <tt>p.x</tt></li> use <tt>p.x</tt></li>
&nbsp; <li> There is no <b><tt>*</tt></b> operator in Cython. Instead of &nbsp; <li> There is no <b><tt>*</tt></b> operator in Cython. Instead of
<tt>*p</tt>, use <tt>p[0]</tt></li> <tt>*p</tt>, use <tt>p[0]</tt></li>
&nbsp; <li> There is an <b><tt>&amp;</tt></b> operator, with the same semantics &nbsp; <li> There is an <b><tt>&amp;</tt></b> operator, with the same semantics
as in C.</li> as in C.</li>
&nbsp; <li> The null C pointer is called <b><tt>NULL</tt></b>, not 0 (and &nbsp; <li> The null C pointer is called <b><tt>NULL</tt></b>, not 0 (and
<tt>NULL</tt> is a reserved word).</li> <tt>NULL</tt> is a reserved word).</li>
&nbsp; <li> Character literals are written with a <b>c</b> prefix, for &nbsp; <li> Character literals are written with a <b>c</b> prefix, for
example:</li> example:</li>
<ul> <ul>
...@@ -380,29 +380,29 @@ example:</li> ...@@ -380,29 +380,29 @@ example:</li>
<pre>cdef char *p, float *q<br>p = &lt;char*&gt;q</pre> <pre>cdef char *p, float *q<br>p = &lt;char*&gt;q</pre>
</ul> </ul>
<i><b>Warning</b>: Don't attempt to use a typecast to convert between <i><b>Warning</b>: Don't attempt to use a typecast to convert between
Python and C data types -- it won't do the right thing. Leave Cython to perform Python and C data types -- it won't do the right thing. Leave Cython to perform
the conversion automatically.</i> the conversion automatically.</i>
</ul> </ul>
<h4> <a name="ForFromLoop"></a>Integer for-loops</h4> <h4> <a name="ForFromLoop"></a>Integer for-loops</h4>
You should be aware that a for-loop such as You should be aware that a for-loop such as
<blockquote><tt>for i in range(n):</tt> <br> <blockquote><tt>for i in range(n):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
won't be very fast, even if <tt>i</tt> and <tt>n</tt> are declared as won't be very fast, even if <tt>i</tt> and <tt>n</tt> are declared as
C integers, because <tt>range</tt> is a Python function. For iterating over C integers, because <tt>range</tt> is a Python function. For iterating over
ranges of integers, Cython has another form of for-loop: ranges of integers, Cython has another form of for-loop:
<blockquote><tt>for i from 0 &lt;= i &lt; n:</tt> <br> <blockquote><tt>for i from 0 &lt;= i &lt; n:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
If the loop variable and the lower and upper bounds are all C integers, If the loop variable and the lower and upper bounds are all C integers,
this form of loop will be much faster, because Cython will translate it into this form of loop will be much faster, because Cython will translate it into
pure C code. pure C code.
<p>Some things to note about the <tt>for-from</tt> loop: </p> <p>Some things to note about the <tt>for-from</tt> loop: </p>
<ul> <ul>
<li> The target expression must be a variable name.</li> <li> The target expression must be a variable name.</li>
...@@ -412,61 +412,61 @@ the target name.</li> ...@@ -412,61 +412,61 @@ the target name.</li>
are both from the set {<tt>&lt;</tt>, <tt>&lt;=</tt>} then it is upwards; are both from the set {<tt>&lt;</tt>, <tt>&lt;=</tt>} then it is upwards;
if they are both from the set {<tt>&gt;</tt>, <tt>&gt;=</tt>} then it is if they are both from the set {<tt>&gt;</tt>, <tt>&gt;=</tt>} then it is
downwards. (Any other combination is disallowed.)</li> downwards. (Any other combination is disallowed.)</li>
</ul> </ul>
Like other Python looping statements, <tt>break</tt> and <tt>continue</tt> may be used in the body, and the loop may have an <tt>else</tt> clause. Like other Python looping statements, <tt>break</tt> and <tt>continue</tt> may be used in the body, and the loop may have an <tt>else</tt> clause.
<h2> <hr width="100%"></h2> <h2> <hr width="100%"></h2>
<h3> <a name="ExceptionValues"></a>Error return values</h3> <h3> <a name="ExceptionValues"></a>Error return values</h3>
If you don't do anything special, a function declared with <b>cdef</b> that does not return a Python object has no way of reporting Python exceptions If you don't do anything special, a function declared with <b>cdef</b> that does not return a Python object has no way of reporting Python exceptions
to its caller. If an exception is detected in such a function, a warning to its caller. If an exception is detected in such a function, a warning
message is printed and the exception is ignored. message is printed and the exception is ignored.
<p>If you want a C function that does not return a Python object to be able <p>If you want a C function that does not return a Python object to be able
to propagate exceptions to its caller, you need to declare an <b>exception to propagate exceptions to its caller, you need to declare an <b>exception
value</b> for it. Here is an example: </p> value</b> for it. Here is an example: </p>
<blockquote><tt>cdef int spam() except -1:</tt> <br> <blockquote><tt>cdef int spam() except -1:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
With this declaration, whenever an exception occurs inside <tt>spam</tt>, With this declaration, whenever an exception occurs inside <tt>spam</tt>,
it will immediately return with the value <tt>-1</tt>. Furthermore, whenever it will immediately return with the value <tt>-1</tt>. Furthermore, whenever
a call to <tt>spam</tt> returns <tt>-1</tt>, an exception will be assumed a call to <tt>spam</tt> returns <tt>-1</tt>, an exception will be assumed
to have occurred and will be propagated. to have occurred and will be propagated.
<p>When you declare an exception value for a function, you should never explicitly <p>When you declare an exception value for a function, you should never explicitly
return that value. If all possible return values are legal and you can't return that value. If all possible return values are legal and you can't
reserve one entirely for signalling errors, you can use an alternative form reserve one entirely for signalling errors, you can use an alternative form
of exception value declaration: </p> of exception value declaration: </p>
<blockquote><tt>cdef int spam() except? -1:</tt> <br> <blockquote><tt>cdef int spam() except? -1:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
The "?" indicates that the value <tt>-1</tt> only indicates a <i>possible</i> error. In this case, Cython generates a call to <tt>PyErr_Occurred</tt>if the The "?" indicates that the value <tt>-1</tt> only indicates a <i>possible</i> error. In this case, Cython generates a call to <tt>PyErr_Occurred</tt>if the
exception value is returned, to make sure it really is an error. exception value is returned, to make sure it really is an error.
<p>There is also a third form of exception value declaration: </p> <p>There is also a third form of exception value declaration: </p>
<blockquote><tt>cdef int spam() except *:</tt> <br> <blockquote><tt>cdef int spam() except *:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
This form causes Cython to generate a call to <tt>PyErr_Occurred</tt> after This form causes Cython to generate a call to <tt>PyErr_Occurred</tt> after
<i>every</i> call to spam, regardless of what value it returns. If you have <i>every</i> call to spam, regardless of what value it returns. If you have
a function returning <tt>void</tt> that needs to propagate errors, you will a function returning <tt>void</tt> that needs to propagate errors, you will
have to use this form, since there isn't any return value to test. have to use this form, since there isn't any return value to test.
<p>Some things to note: </p> <p>Some things to note: </p>
<ul> <ul>
<li> Currently, exception values can only declared for functions returning <li> Currently, exception values can only declared for functions returning
an integer, float or pointer type, and the value must be a <i>literal</i>, an integer, float or pointer type, and the value must be a <i>literal</i>,
not an expression (although it can be negative). The only possible pointer not an expression (although it can be negative). The only possible pointer
exception value is <tt>NULL</tt>. Void functions can only use the <tt>except exception value is <tt>NULL</tt>. Void functions can only use the <tt>except
*</tt> form.</li> *</tt> form.</li>
<br> <br>
&nbsp; <li> The exception value specification is part of the signature &nbsp; <li> The exception value specification is part of the signature
...@@ -477,18 +477,18 @@ is an example of a pointer-to-function declaration with an exception value:</li> ...@@ -477,18 +477,18 @@ is an example of a pointer-to-function declaration with an exception value:</li>
<ul> <ul>
<pre><tt>int (*grail)(int, char *) except -1</tt></pre> <pre><tt>int (*grail)(int, char *) except -1</tt></pre>
</ul> </ul>
<li> You don't need to (and shouldn't) declare exception values for functions <li> You don't need to (and shouldn't) declare exception values for functions
which return Python objects. Remember that a function with no declared return which return Python objects. Remember that a function with no declared return
type implicitly returns a Python object.</li> type implicitly returns a Python object.</li>
</ul> </ul>
<h4> <a name="CheckingReturnValues"></a>Checking return values of non-Cython <h4> <a name="CheckingReturnValues"></a>Checking return values of non-Cython
functions</h4> functions</h4>
It's important to understand that the <tt>except</tt> clause does <i>not</i> cause an error to be <i>raised</i> when the specified value is returned. For It's important to understand that the <tt>except</tt> clause does <i>not</i> cause an error to be <i>raised</i> when the specified value is returned. For
example, you can't write something like example, you can't write something like
<blockquote> <pre>cdef extern FILE *fopen(char *filename, char *mode) except NULL <font color="#ed181e"># WRONG!</font></pre> <blockquote> <pre>cdef extern FILE *fopen(char *filename, char *mode) except NULL <font color="#ed181e"># WRONG!</font></pre>
</blockquote> </blockquote>
...@@ -497,26 +497,26 @@ returns NULL. The except clause doesn't work that way; its only purpose ...@@ -497,26 +497,26 @@ returns NULL. The except clause doesn't work that way; its only purpose
is for <i>propagating</i> exceptions that have already been raised, either is for <i>propagating</i> exceptions that have already been raised, either
by a Cython function or a C function that calls Python/C API routines. To 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 fopen, you will get an exception from a non-Python-aware function such as fopen, you will
have to check the return value and raise it yourself, for example, have to check the return value and raise it yourself, for example,
<blockquote> <pre>cdef FILE *p<br>p = fopen("spam.txt", "r")<br>if p == NULL:<br>&nbsp;&nbsp;&nbsp; raise SpamError("Couldn't open the spam file")</pre> <blockquote> <pre>cdef FILE *p<br>p = fopen("spam.txt", "r")<br>if p == NULL:<br>&nbsp;&nbsp;&nbsp; raise SpamError("Couldn't open the spam file")</pre>
</blockquote> </blockquote>
<h4> <hr width="100%"></h4> <h4> <hr width="100%"></h4>
<h4> <a name="IncludeStatement"></a>The <tt>include</tt> statement</h4> <h4> <a name="IncludeStatement"></a>The <tt>include</tt> statement</h4>
For convenience, a large Cython module can be split up into a number of For convenience, a large Cython module can be split up into a number of
files which are put together using the <b>include</b> statement, for example files which are put together using the <b>include</b> statement, for example
<blockquote> <pre>include "spamstuff.pxi"</pre> <blockquote> <pre>include "spamstuff.pxi"</pre>
</blockquote> </blockquote>
The contents of the named file are textually included at that point. The The contents of the named file are textually included at that point. The
included file can contain any complete top-level Cython statements, including included file can contain any complete top-level Cython statements, including
other <b>include</b> statements. The <b>include</b> statement itself can other <b>include</b> statements. The <b>include</b> statement itself can
only appear at the top level of a file. only appear at the top level of a file.
<p>The <b>include</b> statement can also be used in conjunction with <a href="#PublicDecls"><b>public</b> declarations</a> to make C functions and <p>The <b>include</b> statement can also be used in conjunction with <a href="#PublicDecls"><b>public</b> declarations</a> to make C functions and
variables defined in one Cython module accessible to another. However, note variables defined in one Cython module accessible to another. However, note
that some of these uses have been superseded by the facilities described that some of these uses have been superseded by the facilities described
...@@ -524,55 +524,55 @@ in <a href="sharing.html">Sharing Declarations Between Cython Modules</a>, ...@@ -524,55 +524,55 @@ in <a href="sharing.html">Sharing Declarations Between Cython Modules</a>,
and it is expected that use of the <b>include</b> statement for this purpose and it is expected that use of the <b>include</b> statement for this purpose
will be phased out altogether in future versions. </p> will be phased out altogether in future versions. </p>
<h2> <hr width="100%"><a name="InterfacingWithExternal"></a>Interfacing with External <h2> <hr width="100%"><a name="InterfacingWithExternal"></a>Interfacing with External
C Code C Code
<hr width="100%"></h2> <hr width="100%"></h2>
One of the main uses of Cython is wrapping existing libraries of C code. One of the main uses of Cython is wrapping existing libraries of C code.
This is achieved by using <a href="#ExternDecls">external declarations</a> to declare the C functions and variables from the library that you want to This is achieved by using <a href="#ExternDecls">external declarations</a> to declare the C functions and variables from the library that you want to
use. use.
<p>You can also use <a href="#PublicDecls">public declarations</a> to make <p>You can also use <a href="#PublicDecls">public declarations</a> to make
C functions and variables defined in a Cython module available to external C functions and variables defined in a Cython module available to external
C code. The need for this is expected to be less frequent, but you might C code. The need for this is expected to be less frequent, but you might
want to do it, for example, if you are embedding Python in another application want to do it, for example, if you are embedding Python in another application
as a scripting language. Just as a Cython module can be used as a bridge to as a scripting language. Just as a Cython module can be used as a bridge to
allow Python code to call C code, it can also be used to allow C code to allow Python code to call C code, it can also be used to allow C code to
call Python code. </p> call Python code. </p>
<h3> <a name="ExternDecls"></a>External declarations</h3> <h3> <a name="ExternDecls"></a>External declarations</h3>
By default, C functions and variables declared at the module level are By default, C functions and variables declared at the module level are
local to the module (i.e. they have the C <b>static</b> storage class). They local to the module (i.e. they have the C <b>static</b> storage class). They
can also be declared <b>extern</b> to specify that they are defined elsewhere, can also be declared <b>extern</b> to specify that they are defined elsewhere,
for example: for example:
<blockquote> <pre>cdef extern int spam_counter</pre> <blockquote> <pre>cdef extern int spam_counter</pre>
<pre>cdef extern void order_spam(int tons)</pre> <pre>cdef extern void order_spam(int tons)</pre>
</blockquote> </blockquote>
<blockquote> </blockquote> <blockquote> </blockquote>
<h4> <a name="ReferencingHeaders"></a>Referencing C header files</h4> <h4> <a name="ReferencingHeaders"></a>Referencing C header files</h4>
When you use an extern definition on its own as in the examples above, When you use an extern definition on its own as in the examples above,
Cython includes a declaration for it in the generated C file. This can cause Cython includes a declaration for it in the generated C file. This can cause
problems if the declaration doesn't exactly match the declaration that will problems if the declaration doesn't exactly match the declaration that will
be seen by other C code. If you're wrapping an existing C library, for example, be seen by other C code. If you're wrapping an existing C library, for example,
it's important that the generated C code is compiled with exactly the same it's important that the generated C code is compiled with exactly the same
declarations as the rest of the library. declarations as the rest of the library.
<p>To achieve this, you can tell Cython that the declarations are to be found <p>To achieve this, you can tell Cython that the declarations are to be found
in a C header file, like this: </p> in a C header file, like this: </p>
<blockquote> <pre>cdef extern from "spam.h":</pre> <blockquote> <pre>cdef extern from "spam.h":</pre>
<pre>&nbsp;&nbsp;&nbsp; int spam_counter</pre> <pre>&nbsp;&nbsp;&nbsp; int spam_counter</pre>
<pre>&nbsp;&nbsp;&nbsp; void order_spam(int tons)</pre> <pre>&nbsp;&nbsp;&nbsp; void order_spam(int tons)</pre>
</blockquote> </blockquote>
The <b>cdef extern from</b> clause does three things: The <b>cdef extern from</b> clause does three things:
<ol> <ol>
<li> It directs Cython to place a <b>#include</b> statement for the named <li> It directs Cython to place a <b>#include</b> statement for the named
...@@ -583,14 +583,14 @@ declarations as the rest of the library. ...@@ -583,14 +583,14 @@ declarations as the rest of the library.
</li> </li>
&nbsp; <li> It treats all declarations within the block as though they &nbsp; <li> It treats all declarations within the block as though they
started with <b>cdef extern</b>.</li> started with <b>cdef extern</b>.</li>
</ol> </ol>
It's important to understand that Cython does <i>not</i> itself read the It's important to understand that Cython does <i>not</i> itself read the
C header file, so you still need to provide Cython versions of any declarations C header file, so you still need to provide Cython versions of any declarations
from it that you use. However, the Cython declarations don't always have to from it that you use. However, the Cython declarations don't always have to
exactly match the C ones, and in some cases they shouldn't or can't. In particular: exactly match the C ones, and in some cases they shouldn't or can't. In particular:
<ol> <ol>
<li> Don't use <b>const</b>. Cython doesn't know anything about const, <li> Don't use <b>const</b>. Cython doesn't know anything about const,
...@@ -601,8 +601,8 @@ although on rare occasions you might have to use a cast.<sup><a href="#Footnote ...@@ -601,8 +601,8 @@ although on rare occasions you might have to use a cast.<sup><a href="#Footnote
such as <b>__declspec()</b>.<br> such as <b>__declspec()</b>.<br>
</li> </li>
&nbsp; <li> If the header file declares a big struct and you only want &nbsp; <li> If the header file declares a big struct and you only want
to use a few members, you only need to declare the members you're interested to use a few members, you only need to declare the members you're interested
in. Leaving the rest out doesn't do any harm, because the C compiler will in. Leaving the rest out doesn't do any harm, because the C compiler will
use the full definition from the header file.<br> use the full definition from the header file.<br>
<br> <br>
In some cases, you might not need <i>any</i> of the struct's members, in In some cases, you might not need <i>any</i> of the struct's members, in
...@@ -617,14 +617,14 @@ Note that you can only do this inside a <b>cdef extern from</b> block; struct ...@@ -617,14 +617,14 @@ Note that you can only do this inside a <b>cdef extern from</b> block; struct
declarations anywhere else must be non-empty.<br> declarations anywhere else must be non-empty.<br>
<br> <br>
</li> </li>
<li> If the header file uses typedef names such as <b>size_t </b>to refer <li> If the header file uses typedef names such as <b>size_t </b>to refer
to platform-dependent flavours of numeric types, you will need a corresponding to platform-dependent flavours of numeric types, you will need a corresponding
<b>ctypedef</b> statement, but you don't need to match the type exactly, <b>ctypedef</b> statement, but you don't need to match the type exactly,
just use something of the right general kind (int, float, etc). For example,</li> just use something of the right general kind (int, float, etc). For example,</li>
<ol> <ol>
<pre>ctypedef int size_t</pre> <pre>ctypedef int size_t</pre>
</ol> </ol>
will work okay whatever the actual size of a size_t is (provided the header will work okay whatever the actual size of a size_t is (provided the header
file defines it correctly). <br> file defines it correctly). <br>
&nbsp; <li> If the header file uses macros to define constants, translate &nbsp; <li> If the header file uses macros to define constants, translate
them into a dummy <b>enum</b> declaration.<br> them into a dummy <b>enum</b> declaration.<br>
...@@ -632,47 +632,47 @@ to platform-dependent flavours of numeric types, you will need a corresponding ...@@ -632,47 +632,47 @@ to platform-dependent flavours of numeric types, you will need a corresponding
&nbsp; <li> If the header file defines a function using a macro, declare &nbsp; <li> If the header file defines a function using a macro, declare
it as though it were an ordinary function, with appropriate argument and it as though it were an ordinary function, with appropriate argument and
result types.</li> result types.</li>
</ol> </ol>
A few more tricks and tips: A few more tricks and tips:
<ul> <ul>
<li> If you want to include a C header because it's needed by another <li> If you want to include a C header because it's needed by another
header, but don't want to use any declarations from it, put <tt><font size="+1">pass</font></tt> in the extern-from block:</li> header, but don't want to use any declarations from it, put <tt><font size="+1">pass</font></tt> in the extern-from block:</li>
</ul> </ul>
<ul> <ul>
<ul> <ul>
<tt>cdef extern from "spam.h":</tt> <br> <tt>cdef extern from "spam.h":</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; pass</tt> </ul> <tt>&nbsp;&nbsp;&nbsp; pass</tt> </ul>
</ul> </ul>
<ul> <ul>
<li> If you want to include some external declarations, but don't want <li> If you want to include some external declarations, but don't want
to specify a header file (because it's included by some other header that to specify a header file (because it's included by some other header that
you've already included) you can put <tt>*</tt> in place of the header file you've already included) you can put <tt>*</tt> in place of the header file
name:</li> name:</li>
</ul> </ul>
<blockquote> <blockquote><tt>cdef extern from *:</tt> <br> <blockquote> <blockquote><tt>cdef extern from *:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote> <tt>&nbsp;&nbsp;&nbsp; ...</tt></blockquote>
</blockquote> </blockquote>
<h4> <a name="StructDeclStyles"></a>Styles of struct, union and enum declaration</h4> <h4> <a name="StructDeclStyles"></a>Styles of struct, union and enum declaration</h4>
There are two main ways that structs, unions and enums can be declared There are two main ways that structs, unions and enums can be declared
in C header files: using a tag name, or using a typedef. There are also some in C header files: using a tag name, or using a typedef. There are also some
variations based on various combinations of these. variations based on various combinations of these.
<p>It's important to make the Cython declarations match the style used in the <p>It's important to make the Cython declarations match the style used in the
header file, so that Cython can emit the right sort of references to the type header file, so that Cython can emit the right sort of references to the type
in the code it generates. To make this possible, Cython provides two different in the code it generates. To make this possible, Cython provides two different
...@@ -680,13 +680,13 @@ syntaxes for declaring a struct, union or enum type. The style introduced ...@@ -680,13 +680,13 @@ syntaxes for declaring a struct, union or enum type. The style introduced
above corresponds to the use of a tag name. To get the other style, you prefix above corresponds to the use of a tag name. To get the other style, you prefix
the declaration with <b>ctypedef</b>, as illustrated below. </p> the declaration with <b>ctypedef</b>, as illustrated below. </p>
<p>The following table shows the various possible styles that can be found <p>The following table shows the various possible styles that can be found
in a header file, and the corresponding Cython declaration that you should in a header file, and the corresponding Cython declaration that you should
put in the <b>cdef exern from </b>block. Struct declarations are used as put in the <b>cdef exern from </b>block. Struct declarations are used as
an example; the same applies equally to union and enum declarations. </p> an example; the same applies equally to union and enum declarations. </p>
<p>Note that in all the cases below, you refer to the type in Cython code simply <p>Note that in all the cases below, you refer to the type in Cython code simply
as <tt><font size="+1">Foo</font></tt>, not <tt><font size="+1">struct Foo</font></tt>. as <tt><font size="+1">Foo</font></tt>, not <tt><font size="+1">struct Foo</font></tt>.
<br> <br>
...@@ -695,7 +695,7 @@ as <tt><font size="+1">Foo</font></tt>, not <tt><font size="+1">struct Foo</font ...@@ -695,7 +695,7 @@ as <tt><font size="+1">Foo</font></tt>, not <tt><font size="+1">struct Foo</font
<tr bgcolor="#8cbc1c" valign="top"> <tr bgcolor="#8cbc1c" valign="top">
<td bgcolor="#8cbc1c">&nbsp;</td> <td bgcolor="#8cbc1c">&nbsp;</td>
<td bgcolor="#ff9933" nowrap="nowrap"><b>C code</b></td> <td bgcolor="#ff9933" nowrap="nowrap"><b>C code</b></td>
<td bgcolor="#66cccc" valign="top"><b>Possibilities for corresponding <td bgcolor="#66cccc" valign="top"><b>Possibilities for corresponding
Cython code</b></td> Cython code</b></td>
<td bgcolor="#99cc33" valign="top"><b>Comments</b></td> <td bgcolor="#99cc33" valign="top"><b>Comments</b></td>
</tr> </tr>
...@@ -706,7 +706,7 @@ Cython code</b></td> ...@@ -706,7 +706,7 @@ Cython code</b></td>
<tt>};</tt></td> <tt>};</tt></td>
<td bgcolor="#66cccc"><tt>cdef struct Foo:</tt> <br> <td bgcolor="#66cccc"><tt>cdef struct Foo:</tt> <br>
<tt>&nbsp; ...</tt></td> <tt>&nbsp; ...</tt></td>
<td>Cython will refer to the type as <tt>struct Foo </tt>in the generated <td>Cython will refer to the type as <tt>struct Foo </tt>in the generated
C code<tt>.</tt></td> C code<tt>.</tt></td>
</tr> </tr>
<tr bgcolor="#8cbc1c" valign="top"> <tr bgcolor="#8cbc1c" valign="top">
...@@ -728,7 +728,7 @@ foo {</tt> <br> ...@@ -728,7 +728,7 @@ foo {</tt> <br>
<td bgcolor="#66cccc" nowrap="nowrap" valign="top"><tt>cdef struct foo:</tt> <br> <td bgcolor="#66cccc" nowrap="nowrap" valign="top"><tt>cdef struct foo:</tt> <br>
<tt>&nbsp; ...</tt> <br> <tt>&nbsp; ...</tt> <br>
<tt>ctypedef foo Foo #optional</tt></td> <tt>ctypedef foo Foo #optional</tt></td>
<td rowspan="2" valign="top">If the C header uses both a tag and a typedef <td rowspan="2" valign="top">If the C header uses both a tag and a typedef
with <i>different</i> names, you can use either form of declaration in Cython with <i>different</i> names, you can use either form of declaration in Cython
(although if you need to forward reference the type, you'll have to use (although if you need to forward reference the type, you'll have to use
the first form).</td> the first form).</td>
...@@ -744,84 +744,84 @@ the first form).</td> ...@@ -744,84 +744,84 @@ the first form).</td>
<tt>} Foo;</tt></td> <tt>} Foo;</tt></td>
<td bgcolor="#66cccc" valign="top"><tt>cdef struct Foo:</tt> <br> <td bgcolor="#66cccc" valign="top"><tt>cdef struct Foo:</tt> <br>
<tt>&nbsp; ...</tt></td> <tt>&nbsp; ...</tt></td>
<td>If the header uses the <i>same</i> name for the tag and the typedef, <td>If the header uses the <i>same</i> name for the tag and the typedef,
you won't be able to include a <b>ctypedef</b> for it -- but then, it's not you won't be able to include a <b>ctypedef</b> for it -- but then, it's not
necessary.</td> necessary.</td>
</tr> </tr>
</tbody> </table> </tbody> </table>
</p> </p>
<h4> <a name="AccessingAPI"></a>Accessing Python/C API routines</h4> <h4> <a name="AccessingAPI"></a>Accessing Python/C API routines</h4>
One particular use of the <b>cdef extern from</b> statement is for gaining One particular use of the <b>cdef extern from</b> statement is for gaining
access to routines in the Python/C API. For example, access to routines in the Python/C API. For example,
<blockquote> <pre>cdef extern from "Python.h":</pre> <blockquote> <pre>cdef extern from "Python.h":</pre>
<pre>&nbsp;&nbsp;&nbsp; object PyString_FromStringAndSize(char *s, int len)</pre> <pre>&nbsp;&nbsp;&nbsp; object PyString_FromStringAndSize(char *s, int len)</pre>
</blockquote> </blockquote>
will allow you to create Python strings containing null bytes. will allow you to create Python strings containing null bytes.
<p> </p> <p> </p>
<hr width="100%"> <hr width="100%">
<h3> <a name="CNameSpecs"></a>Resolving naming conflicts - C name specifications</h3> <h3> <a name="CNameSpecs"></a>Resolving naming conflicts - C name specifications</h3>
Each Cython module has a single module-level namespace for both Python Each Cython module has a single module-level namespace for both Python
and C names. This can be inconvenient if you want to wrap some external and C names. This can be inconvenient if you want to wrap some external
C functions and provide the Python user with Python functions of the same C functions and provide the Python user with Python functions of the same
names. names.
<p>Cython 0.8 provides a couple of different ways of solving this problem. <p>Cython 0.8 provides a couple of different ways of solving this problem.
The best way, especially if you have many C functions to wrap, is probably The best way, especially if you have many C functions to wrap, is probably
to put the extern C function declarations into a different namespace using to put the extern C function declarations into a different namespace using
the facilities described in the section on <a href="sharing.html">sharing the facilities described in the section on <a href="sharing.html">sharing
declarations between Cython modules</a>. </p> declarations between Cython modules</a>. </p>
<p>The other way is to use a <b>c name specification</b> to give different <p>The other way is to use a <b>c name specification</b> to give different
Cython and C names to the C function. Suppose, for example, that you want Cython and C names to the C function. Suppose, for example, that you want
to wrap an external function called <tt>eject_tomato</tt>. If you declare to wrap an external function called <tt>eject_tomato</tt>. If you declare
it as </p> it as </p>
<blockquote> <pre>cdef extern void c_eject_tomato "eject_tomato" (float speed)</pre> <blockquote> <pre>cdef extern void c_eject_tomato "eject_tomato" (float speed)</pre>
</blockquote> </blockquote>
then its name inside the Cython module will be <tt>c_eject_tomato</tt>, then its name inside the Cython module will be <tt>c_eject_tomato</tt>,
whereas its name in C will be <tt>eject_tomato</tt>. You can then wrap it whereas its name in C will be <tt>eject_tomato</tt>. You can then wrap it
with with
<blockquote> <pre>def eject_tomato(speed):<br>&nbsp; c_eject_tomato(speed)</pre> <blockquote> <pre>def eject_tomato(speed):<br>&nbsp; c_eject_tomato(speed)</pre>
</blockquote> </blockquote>
so that users of your module can refer to it as <tt>eject_tomato</tt>. so that users of your module can refer to it as <tt>eject_tomato</tt>.
<p>Another use for this feature is referring to external names that happen <p>Another use for this feature is referring to external names that happen
to be Cython keywords. For example, if you want to call an external function to be Cython keywords. For example, if you want to call an external function
called <tt>print</tt>, you can rename it to something else in your Cython called <tt>print</tt>, you can rename it to something else in your Cython
module. </p> module. </p>
<p>As well as functions, C names can be specified for variables, structs, <p>As well as functions, C names can be specified for variables, structs,
unions, enums, struct and union members, and enum values. For example, </p> unions, enums, struct and union members, and enum values. For example, </p>
<blockquote> <pre>cdef extern int one "ein", two "zwei"<br>cdef extern float three "drei"<br><br>cdef struct spam "SPAM":<br>&nbsp; int i "eye"</pre> <blockquote> <pre>cdef extern int one "ein", two "zwei"<br>cdef extern float three "drei"<br><br>cdef struct spam "SPAM":<br>&nbsp; int i "eye"</pre>
<tt>cdef enum surprise "inquisition":</tt> <br> <tt>cdef enum surprise "inquisition":</tt> <br>
<tt>&nbsp; first "alpha"</tt> <br> <tt>&nbsp; first "alpha"</tt> <br>
<tt>&nbsp; second "beta" = 3</tt></blockquote> <tt>&nbsp; second "beta" = 3</tt></blockquote>
<hr width="100%"> <hr width="100%">
<h3> <a name="PublicDecls"></a>Public Declarations</h3> <h3> <a name="PublicDecls"></a>Public Declarations</h3>
You can make C variables and functions defined in a Cython module accessible You can make C variables and functions defined in a Cython module accessible
to external C code (or another Cython module) using the <b><tt>public</tt></b> keyword, as follows: to external C code (or another Cython module) using the <b><tt>public</tt></b> keyword, as follows:
<blockquote><tt>cdef public int spam # public variable declaration</tt> <p><tt>cdef public void grail(int num_nuns): # public function declaration</tt> <br> <blockquote><tt>cdef public int spam # public variable declaration</tt> <p><tt>cdef public void grail(int num_nuns): # public function declaration</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; ...</tt></p> <tt>&nbsp;&nbsp;&nbsp; ...</tt></p>
</blockquote> </blockquote>
If there are any <tt>public</tt> declarations in a Cython module, a <b>.h</b> file is generated containing equivalent C declarations for inclusion in other If there are any <tt>public</tt> declarations in a Cython module, a <b>.h</b> file is generated containing equivalent C declarations for inclusion in other
C code. C code.
<p>Cython also generates a <b>.pxi</b> file containing Cython versions of the <p>Cython also generates a <b>.pxi</b> file containing Cython versions of the
declarations for inclusion in another Cython module using the <b><a href="#IncludeStatement">include</a></b> statement. If you use this, you declarations for inclusion in another Cython module using the <b><a href="#IncludeStatement">include</a></b> statement. If you use this, you
will need to arrange for the module using the declarations to be linked will need to arrange for the module using the declarations to be linked
...@@ -829,35 +829,35 @@ against the module defining them, and for both modules to be available to ...@@ -829,35 +829,35 @@ against the module defining them, and for both modules to be available to
the dynamic linker at run time. I haven't tested this, so I can't say how the dynamic linker at run time. I haven't tested this, so I can't say how
well it will work on the various platforms. </p> well it will work on the various platforms. </p>
<blockquote>NOTE: If all you want to export is an extension type, there is <blockquote>NOTE: If all you want to export is an extension type, there is
now a better way -- see <a href="sharing.html">Sharing Declarations Between now a better way -- see <a href="sharing.html">Sharing Declarations Between
Cython Modules</a>.</blockquote> Cython Modules</a>.</blockquote>
<h2> <hr width="100%">Extension Types <h2> <hr width="100%">Extension Types
<hr width="100%"></h2> <hr width="100%"></h2>
One of the most powerful features of Cython is the ability to easily create One of the most powerful features of Cython is the ability to easily create
new built-in Python types, called <b>extension types</b>. This is a major new built-in Python types, called <b>extension types</b>. This is a major
topic in itself, so there is a&nbsp; <a href="extension_types.html">separate topic in itself, so there is a&nbsp; <a href="extension_types.html">separate
page</a> devoted to it. page</a> devoted to it.
<h2> <hr width="100%">Sharing Declarations Between Cython Modules <h2> <hr width="100%">Sharing Declarations Between Cython Modules
<hr width="100%"></h2> <hr width="100%"></h2>
Cython 0.8 introduces a substantial new set of facilities allowing a Cython Cython 0.8 introduces a substantial new set of facilities allowing a Cython
module to easily import and use C declarations and extension types from another module to easily import and use C declarations and extension types from another
Cython module. You can now create a set of co-operating Cython modules just Cython module. You can now create a set of co-operating Cython modules just
as easily as you can create a set of co-operating Python modules. There is as easily as you can create a set of co-operating Python modules. There is
a <a href="sharing.html">separate page</a> devoted to this topic. a <a href="sharing.html">separate page</a> devoted to this topic.
<h2> <hr width="100%"><a name="Limitations"></a>Limitations <h2> <hr width="100%"><a name="Limitations"></a>Limitations
<hr width="100%"></h2> <hr width="100%"></h2>
<h3> <a name="Unsupported"></a>Unsupported Python features</h3> <h3> <a name="Unsupported"></a>Unsupported Python features</h3>
Cython is not quite a full superset of Python. The following restrictions Cython is not quite a full superset of Python. The following restrictions
apply: apply:
<blockquote> <li> Function definitions (whether using <b>def</b> or <b>cdef</b>) <blockquote> <li> Function definitions (whether using <b>def</b> or <b>cdef</b>)
cannot be nested within other function definitions.<br> cannot be nested within other function definitions.<br>
</li> </li>
...@@ -870,17 +870,17 @@ a <a href="sharing.html">separate page</a> devoted to this topic. ...@@ -870,17 +870,17 @@ a <a href="sharing.html">separate page</a> devoted to this topic.
&nbsp; <li> Generators cannot be defined in Cython.<br> &nbsp; <li> Generators cannot be defined in Cython.<br>
<br> <br>
</li> </li>
<li> The <tt>globals()</tt> and <tt>locals()</tt> functions cannot be <li> The <tt>globals()</tt> and <tt>locals()</tt> functions cannot be
used.</li> used.</li>
</blockquote> </blockquote>
The above restrictions will most likely remain, since removing them would The above restrictions will most likely remain, since removing them would
be difficult and they're not really needed for Cython's intended applications. be difficult and they're not really needed for Cython's intended applications.
<p>There are also some temporary limitations, which may eventually be lifted, including: <p>There are also some temporary limitations, which may eventually be lifted, including:
</p> </p>
<blockquote> <li> Class and function definitions cannot be placed inside <blockquote> <li> Class and function definitions cannot be placed inside
control structures.<br> control structures.<br>
</li> </li>
...@@ -898,54 +898,54 @@ docstrings.<br> ...@@ -898,54 +898,54 @@ docstrings.<br>
because Cython doesn't optimize them away, and won't even accept them in because Cython doesn't optimize them away, and won't even accept them in
places where executable statements are not allowed.</li> places where executable statements are not allowed.</li>
</blockquote> </blockquote>
<h3> <a name="SemanticDifferences"></a>Semantic differences between Python <h3> <a name="SemanticDifferences"></a>Semantic differences between Python
and Cython</h3> and Cython</h3>
<h4> Behaviour of class scopes</h4> <h4> Behaviour of class scopes</h4>
In Python, referring to a method of a class inside the class definition, In Python, referring to a method of a class inside the class definition,
i.e. while the class is being defined, yields a plain function object, but i.e. while the class is being defined, yields a plain function object, but
in Cython it yields an unbound method<sup><font size="-2"><a href="#Footnote2">2</a></font></sup>. A consequence of this is that the in Cython it yields an unbound method<sup><font size="-2"><a href="#Footnote2">2</a></font></sup>. A consequence of this is that the
usual idiom for using the classmethod and staticmethod functions, e.g. usual idiom for using the classmethod and staticmethod functions, e.g.
<blockquote> <pre>class Spam:</pre> <blockquote> <pre>class Spam:</pre>
<pre>&nbsp; def method(cls):<br>&nbsp;&nbsp;&nbsp; ...</pre> <pre>&nbsp; def method(cls):<br>&nbsp;&nbsp;&nbsp; ...</pre>
<pre>&nbsp; method = classmethod(method)</pre> <pre>&nbsp; method = classmethod(method)</pre>
</blockquote> </blockquote>
will not work in Cython. This can be worked around by defining the function will not work in Cython. This can be worked around by defining the function
<i>outside</i> the class, and then assigning the result of classmethod or <i>outside</i> the class, and then assigning the result of classmethod or
staticmethod inside the class, i.e. staticmethod inside the class, i.e.
<blockquote> <pre>def Spam_method(cls):<br>&nbsp; ...</pre> <blockquote> <pre>def Spam_method(cls):<br>&nbsp; ...</pre>
<pre>class Spam:</pre> <pre>class Spam:</pre>
<pre>&nbsp; method = classmethod(Spam_method)</pre> <pre>&nbsp; method = classmethod(Spam_method)</pre>
</blockquote> </blockquote>
<h1> <hr width="100%"><font size="+0">Footnotes</font> <hr width="100%"></h1> <h1> <hr width="100%"><font size="+0">Footnotes</font> <hr width="100%"></h1>
<a name="Footnote1"></a>1. A problem with const could arise if you have <a name="Footnote1"></a>1. A problem with const could arise if you have
something like something like
<blockquote> <pre>cdef extern from "grail.h":<br>&nbsp; char *nun</pre> <blockquote> <pre>cdef extern from "grail.h":<br>&nbsp; char *nun</pre>
</blockquote> </blockquote>
where grail.h actually contains where grail.h actually contains
<blockquote> <pre>extern const char *nun;</pre> <blockquote> <pre>extern const char *nun;</pre>
</blockquote> </blockquote>
and you do and you do
<blockquote> <pre>cdef void languissement(char *s):<br>&nbsp; #something that doesn't change s</pre> <blockquote> <pre>cdef void languissement(char *s):<br>&nbsp; #something that doesn't change s</pre>
<pre>...</pre> <pre>...</pre>
<pre>languissement(nun)</pre> <pre>languissement(nun)</pre>
</blockquote> </blockquote>
which will cause the C compiler to complain. You can work around it by which will cause the C compiler to complain. You can work around it by
casting away the constness: casting away the constness:
<blockquote> <pre>languissement(&lt;char *&gt;nun)</pre> <blockquote> <pre>languissement(&lt;char *&gt;nun)</pre>
</blockquote> </blockquote>
<hr width="100%"><a name="Footnote2"></a>2. The reason for the different behaviour <hr width="100%"><a name="Footnote2"></a>2. The reason for the different behaviour
of class scopes is that Cython-defined Python functions are PyCFunction objects, of class scopes is that Cython-defined Python functions are PyCFunction objects,
not PyFunction objects, and are not recognised by the machinery that creates not PyFunction objects, and are not recognised by the machinery that creates
......
/* The following styles size, place, and layer the slide components. /* The following styles size, place, and layer the slide components.
Edit these if you want to change the overall slide layout. Edit these if you want to change the overall slide layout.
The commented lines can be uncommented (and modified, if necessary) The commented lines can be uncommented (and modified, if necessary)
to help you with the rearrangement process. */ to help you with the rearrangement process. */
/* target = 1024x768 */ /* target = 1024x768 */
......
...@@ -59,7 +59,7 @@ html>body div#controls {position: fixed; padding: 0 0 1em 0; ...@@ -59,7 +59,7 @@ html>body div#controls {position: fixed; padding: 0 0 1em 0;
top: auto;} top: auto;}
div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; div#controls form {position: absolute; bottom: 0; right: 0; width: 100%;
margin: 0; padding: 0;} margin: 0; padding: 0;}
#controls #navLinks a {padding: 0; margin: 0 0.5em; #controls #navLinks a {padding: 0; margin: 0 0.5em;
background: #f0f0f0; border: none; color: #545454; background: #f0f0f0; border: none; color: #545454;
cursor: pointer;} cursor: pointer;}
#controls #navList {height: 1em;} #controls #navList {height: 1em;}
......
/* Do not edit or override these styles! The system will likely break if you do. */ /* Do not edit or override these styles! The system will likely break if you do. */
div#header, div#footer, div#controls, .slide {position: absolute;} div#header, div#footer, div#controls, .slide {position: absolute;}
html>body div#header, html>body div#footer, html>body div#header, html>body div#footer,
html>body div#controls, html>body .slide {position: fixed;} html>body div#controls, html>body .slide {position: fixed;}
.handout {display: none;} .handout {display: none;}
.layout {display: block;} .layout {display: block;}
......
// S5 v1.1 slides.js -- released into the Public Domain // S5 v1.1 slides.js -- released into the Public Domain
// //
// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information // Please see http://www.meyerweb.com/eric/tools/s5/credits.html for information
// about all the wonderful and talented contributors to this code! // about all the wonderful and talented contributors to this code!
var undef; var undef;
...@@ -64,7 +64,7 @@ function nodeValue(node) { ...@@ -64,7 +64,7 @@ function nodeValue(node) {
var children = node.childNodes; var children = node.childNodes;
for (var i = 0; i < children.length; ++i) { for (var i = 0; i < children.length; ++i) {
result += nodeValue(children[i]); result += nodeValue(children[i]);
} }
} }
else if (node.nodeType == 3) { else if (node.nodeType == 3) {
result = node.nodeValue; result = node.nodeValue;
...@@ -106,8 +106,8 @@ function currentSlide() { ...@@ -106,8 +106,8 @@ function currentSlide() {
} else { } else {
cs = document.currentSlide; cs = document.currentSlide;
} }
cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' +
'<span id="csSep">\/<\/span> ' + '<span id="csSep">\/<\/span> ' +
'<span id="csTotal">' + (smax-1) + '<\/span>'; '<span id="csTotal">' + (smax-1) + '<\/span>';
if (snum == 0) { if (snum == 0) {
cs.style.visibility = 'hidden'; cs.style.visibility = 'hidden';
...@@ -460,7 +460,7 @@ function notOperaFix() { ...@@ -460,7 +460,7 @@ function notOperaFix() {
function getIncrementals(obj) { function getIncrementals(obj) {
var incrementals = new Array(); var incrementals = new Array();
if (!obj) if (!obj)
return incrementals; return incrementals;
var children = obj.childNodes; var children = obj.childNodes;
for (var i = 0; i < children.length; i++) { for (var i = 0; i < children.length; i++) {
......
...@@ -4,13 +4,13 @@ ...@@ -4,13 +4,13 @@
<meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"><title>Sharing Declarations Between Cython Modules</title></head> <meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"><title>Sharing Declarations Between Cython Modules</title></head>
<body> <body>
<h1> <hr width="100%">Sharing Declarations Between Cython Modules <h1> <hr width="100%">Sharing Declarations Between Cython Modules
<hr width="100%"></h1> <hr width="100%"></h1>
This section describes a new set of facilities introduced in Cython 0.8 This section describes a new set of facilities introduced in Cython 0.8
for making C declarations and extension types in one Cython module available for making C declarations and extension types in one Cython module available
for use in another Cython module. These facilities are closely modelled on for use in another Cython module. These facilities are closely modelled on
the Python import mechanism, and can be thought of as a compile-time version the Python import mechanism, and can be thought of as a compile-time version
of it. of it.
<h2> Contents</h2> <h2> Contents</h2>
<ul> <ul>
<li> <a href="#DefAndImpFiles">Definition and Implementation files</a></li> <li> <a href="#DefAndImpFiles">Definition and Implementation files</a></li>
...@@ -21,7 +21,7 @@ of it. ...@@ -21,7 +21,7 @@ of it.
<li> <a href="#CImportStatement">The <tt>cimport</tt> statement</a></li> <li> <a href="#CImportStatement">The <tt>cimport</tt> statement</a></li>
<ul> <ul>
<li> <a href="#SearchPaths">Search paths for definition files</a></li> <li> <a href="#SearchPaths">Search paths for definition files</a></li>
<li> <a href="#ResolvingNamingConflicts">Using <tt>cimport</tt> to resolve <li> <a href="#ResolvingNamingConflicts">Using <tt>cimport</tt> to resolve
naming conflicts</a></li> naming conflicts</a></li>
</ul> </ul>
<li> <a href="#SharingExtensionTypes">Sharing extension types</a></li> <li> <a href="#SharingExtensionTypes">Sharing extension types</a></li>
...@@ -31,31 +31,31 @@ naming conflicts</a></li> ...@@ -31,31 +31,31 @@ naming conflicts</a></li>
a <tt>.pxd</tt> suffix, containing C declarations that are to be available a <tt>.pxd</tt> suffix, containing C declarations that are to be available
to other Cython modules, and an <i>implementation file</i> with a <tt>.pyx</tt> to other Cython modules, and an <i>implementation file</i> with a <tt>.pyx</tt>
suffix, containing everything else. When a module wants to use something suffix, containing everything else. When a module wants to use something
declared in another module's definition file, it imports it using the <a href="#CImportStatement"><b>cimport</b> statement</a>. declared in another module's definition file, it imports it using the <a href="#CImportStatement"><b>cimport</b> statement</a>.
<h3> <a name="WhatDefFileContains"></a>What a Definition File contains</h3> <h3> <a name="WhatDefFileContains"></a>What a Definition File contains</h3>
A definition file can contain: A definition file can contain:
<ul> <ul>
<li> Any kind of C type declaration.</li> <li> Any kind of C type declaration.</li>
<li> <b>extern</b> C function or variable declarations.</li> <li> <b>extern</b> C function or variable declarations.</li>
<li> The definition part of an extension type (<a href="#SharingExtensionTypes">see below</a>).</li> <li> The definition part of an extension type (<a href="#SharingExtensionTypes">see below</a>).</li>
</ul> </ul>
It cannot currently contain any non-extern C function or variable declarations It cannot currently contain any non-extern C function or variable declarations
(although this may be possible in a future version). (although this may be possible in a future version).
<p>It cannot contain the implementations of any C or Python functions, or <p>It cannot contain the implementations of any C or Python functions, or
any Python class definitions, or any executable statements. </p> any Python class definitions, or any executable statements. </p>
<blockquote>NOTE: You don't need to (and shouldn't) declare anything in a <blockquote>NOTE: You don't need to (and shouldn't) declare anything in a
declaration file <b>public</b> in order to make it available to other Cython declaration file <b>public</b> in order to make it available to other Cython
modules; its mere presence in a definition file does that. You only need a modules; its mere presence in a definition file does that. You only need a
public declaration if you want to make something available to external C code.</blockquote> public declaration if you want to make something available to external C code.</blockquote>
<h3> <a name="WhatImpFileContains"></a>What an Implementation File contains</h3> <h3> <a name="WhatImpFileContains"></a>What an Implementation File contains</h3>
An implementation file can contain any kind of Cython statement, although An implementation file can contain any kind of Cython statement, although
there are some restrictions on the implementation part of an extension type there are some restrictions on the implementation part of an extension type
if the corresponding definition file also defines that type (see below). if the corresponding definition file also defines that type (see below).
<h2> <a name="CImportStatement"></a>The <tt>cimport</tt> statement</h2> <h2> <a name="CImportStatement"></a>The <tt>cimport</tt> statement</h2>
The <b>cimport</b> statement is used in a definition or implementation The <b>cimport</b> statement is used in a definition or implementation
file to gain access to names declared in another definition file. Its syntax file to gain access to names declared in another definition file. Its syntax
exactly parallels that of the normal Python import statement: exactly parallels that of the normal Python import statement:
<blockquote><tt>cimport </tt><i>module</i><tt> [, </tt><i>module</i><tt>...]</tt></blockquote> <blockquote><tt>cimport </tt><i>module</i><tt> [, </tt><i>module</i><tt>...]</tt></blockquote>
<blockquote><tt>from </tt><i>module</i><tt> cimport </tt><i>name</i><tt> <blockquote><tt>from </tt><i>module</i><tt> cimport </tt><i>name</i><tt>
[as </tt><i>name</i><tt>] [, </tt><i>name</i><tt> [as </tt><i>name</i><tt>] [as </tt><i>name</i><tt>] [, </tt><i>name</i><tt> [as </tt><i>name</i><tt>]
...@@ -90,10 +90,10 @@ exactly parallels that of the normal Python import statement: ...@@ -90,10 +90,10 @@ exactly parallels that of the normal Python import statement:
</tr> </tr>
</tbody> </table> </tbody> </table>
<p>It is important to understand that the <b>cimport</b> statement can <i>only</i> <p>It is important to understand that the <b>cimport</b> statement can <i>only</i>
be used to import C data types, external C functions and variables, and extension be used to import C data types, external C functions and variables, and extension
types. It cannot be used to import any Python objects, and (with one exception) types. It cannot be used to import any Python objects, and (with one exception)
it doesn't imply any Python import at run time. If you want to refer to any it doesn't imply any Python import at run time. If you want to refer to any
Python names from a module that you have cimported, you will have to include Python names from a module that you have cimported, you will have to include
a regular <b>import</b> statement for it as well. </p> a regular <b>import</b> statement for it as well. </p>
<p>The exception is that when you use <b>cimport</b> to import an extension <p>The exception is that when you use <b>cimport</b> to import an extension
type, its type object is imported at run time and made available by the type, its type object is imported at run time and made available by the
...@@ -103,7 +103,7 @@ types is covered in more detail <a href="#SharingExtensionTypes">below</a>. ...@@ -103,7 +103,7 @@ types is covered in more detail <a href="#SharingExtensionTypes">below</a>.
<h3> <a name="SearchPaths"></a>Search paths for definition files</h3> <h3> <a name="SearchPaths"></a>Search paths for definition files</h3>
When you <b>cimport</b> a module called <tt>modulename</tt>, the Cython When you <b>cimport</b> a module called <tt>modulename</tt>, the Cython
compiler searches for a file called <tt>modulename.pxd</tt> along the search compiler searches for a file called <tt>modulename.pxd</tt> along the search
path for include files, as specified by <b>-I</b> command line options. path for include files, as specified by <b>-I</b> command line options.
<p>Also, whenever you compile a file <tt>modulename.pyx</tt>, the corresponding <p>Also, whenever you compile a file <tt>modulename.pyx</tt>, the corresponding
definition file <tt>modulename.pxd</tt> is first searched for along the definition file <tt>modulename.pxd</tt> is first searched for along the
same path, and if found, it is processed before processing the <tt>.pyx</tt> same path, and if found, it is processed before processing the <tt>.pyx</tt>
...@@ -146,7 +146,7 @@ type's C attributes and C methods.<br> ...@@ -146,7 +146,7 @@ type's C attributes and C methods.<br>
<br> <br>
The implementation part must implement all of the C methods declared in The implementation part must implement all of the C methods declared in
the definition part, and may not add any further C attributes. It may also the definition part, and may not add any further C attributes. It may also
define Python methods. define Python methods.
<p>Here is an example of a module which defines and exports an extension <p>Here is an example of a module which defines and exports an extension
type, and another module which uses it. <br> type, and another module which uses it. <br>
&nbsp; <table cellpadding="5" cols="2" width="100%"> &nbsp; <table cellpadding="5" cols="2" width="100%">
...@@ -188,9 +188,9 @@ type, and another module which uses it. <br> ...@@ -188,9 +188,9 @@ type, and another module which uses it. <br>
<li> There is a <tt>cdef class Shrubbery</tt> declaration in both Shrubbing.pxd <li> There is a <tt>cdef class Shrubbery</tt> declaration in both Shrubbing.pxd
and Shrubbing.pyx. When the Shrubbing module is compiled, these two declarations and Shrubbing.pyx. When the Shrubbing module is compiled, these two declarations
are combined into one.</li> are combined into one.</li>
&nbsp; <li> In Landscaping.pyx, the <tt>cimport Shrubbing</tt> declaration &nbsp; <li> In Landscaping.pyx, the <tt>cimport Shrubbing</tt> declaration
allows us to refer to the Shrubbery type as <tt>Shrubbing.Shrubbery</tt>. allows us to refer to the Shrubbery type as <tt>Shrubbing.Shrubbery</tt>.
But it doesn't bind the name <tt>Shrubbery</tt> in Landscaping's module namespace But it doesn't bind the name <tt>Shrubbery</tt> in Landscaping's module namespace
at run time, so to access <tt>Shrubbery.standard_shrubbery</tt> we also at run time, so to access <tt>Shrubbery.standard_shrubbery</tt> we also
need to <tt>import Shrubbing</tt>.</li> need to <tt>import Shrubbing</tt>.</li>
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"><title>Special Methods of Extenstion Types</title></head> <meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]"><title>Special Methods of Extenstion Types</title></head>
<body> <body>
<h1> <hr width="100%">Special Methods of Extension Types <h1> <hr width="100%">Special Methods of Extension Types
<hr width="100%"></h1> <hr width="100%"></h1>
This page describes the special methods currently supported by Cython extension This page describes the special methods currently supported by Cython extension
types. A complete list of all the special methods appears in the table at types. A complete list of all the special methods appears in the table at
the bottom. Some of these methods behave differently from their Python counterparts the bottom. Some of these methods behave differently from their Python counterparts
or have no direct Python counterparts, and require special mention. or have no direct Python counterparts, and require special mention.
<p><span style="font-weight: bold;">Note:</span><i> Everything said on this page applies only to </i><span style="font-weight: bold;">extension</span><i style="font-weight: bold;"> <p><span style="font-weight: bold;">Note:</span><i> Everything said on this page applies only to </i><span style="font-weight: bold;">extension</span><i style="font-weight: bold;">
</i><span style="font-weight: bold;">types</span><i>, defined with the </i><span style="font-weight: bold; font-family: monospace;">cdef class</span><i> statement. It doesn't apply&nbsp; </i><span style="font-weight: bold;">types</span><i>, defined with the </i><span style="font-weight: bold; font-family: monospace;">cdef class</span><i> statement. It doesn't apply&nbsp;
to classes defined with the Python </i><span style="font-family: monospace;">class</span><i><span style="font-family: monospace;"> </span>statement, where the normal to classes defined with the Python </i><span style="font-family: monospace;">class</span><i><span style="font-family: monospace;"> </span>statement, where the normal
...@@ -20,19 +20,19 @@ to classes defined with the Python </i><span style="font-family: monospace;">cla ...@@ -20,19 +20,19 @@ to classes defined with the Python </i><span style="font-family: monospace;">cla
types. You can place a docstring in the source to serve as a comment, but types. You can place a docstring in the source to serve as a comment, but
it won't show up in the corresponding <span style="font-family: monospace;">__doc__</span> attribute at run time. (This it won't show up in the corresponding <span style="font-family: monospace;">__doc__</span> attribute at run time. (This
is a Python limitation -- there's nowhere in the PyTypeObject data structure is a Python limitation -- there's nowhere in the PyTypeObject data structure
to put such docstrings.) to put such docstrings.)
<h2> <font size="+1">Initialisation methods: <tt>__new__</tt> and <tt>__init__</tt></font></h2> <h2> <font size="+1">Initialisation methods: <tt>__new__</tt> and <tt>__init__</tt></font></h2>
There are two methods concerned with initialising the object<tt>.</tt> There are two methods concerned with initialising the object<tt>.</tt>
<p>The <b><tt>__new__</tt></b> method is where you should perform basic C-level <p>The <b><tt>__new__</tt></b> method is where you should perform basic C-level
initialisation of the object, including allocation of any C data structures initialisation of the object, including allocation of any C data structures
that your object will own. You need to be careful what you do in the __new__ that your object will own. You need to be careful what you do in the __new__
method, because the object may not yet be a valid Python object when it is method, because the object may not yet be a valid Python object when it is
called. Therefore, you must not invoke any Python operations which might touch called. Therefore, you must not invoke any Python operations which might touch
the object; in particular, do not try to call any of its methods. </p> the object; in particular, do not try to call any of its methods. </p>
<p>Unlike the corresponding method in Python, your <tt>__new__</tt> method <p>Unlike the corresponding method in Python, your <tt>__new__</tt> method
is <i>not</i> responsible for <i>creating</i> the object. By the time your is <i>not</i> responsible for <i>creating</i> the object. By the time your
<tt>__new__</tt> method is called, memory has been allocated for the object <tt>__new__</tt> method is called, memory has been allocated for the object
and any C attributes it has have been initialised to 0 or null. (Any Python and any C attributes it has have been initialised to 0 or null. (Any Python
attributes have also been initialised to <tt>None</tt>, but you probably shouldn't attributes have also been initialised to <tt>None</tt>, but you probably shouldn't
rely on that.) Your <tt>__new__</tt> method is guaranteed to be called exactly rely on that.) Your <tt>__new__</tt> method is guaranteed to be called exactly
once.<br> once.<br>
...@@ -44,11 +44,11 @@ If you need to pass a modified argument list to the base type, you will have ...@@ -44,11 +44,11 @@ If you need to pass a modified argument list to the base type, you will have
to do the relevant part of the initialisation in the <tt>__init__</tt> method to do the relevant part of the initialisation in the <tt>__init__</tt> method
instead (where the normal rules for calling inherited methods apply).<br> instead (where the normal rules for calling inherited methods apply).<br>
</p> </p>
<p>Note that the first parameter of the <tt>__new__</tt> method is the object <p>Note that the first parameter of the <tt>__new__</tt> method is the object
to be initialised, not the class of the object as it is in Python. </p> to be initialised, not the class of the object as it is in Python. </p>
<p>Any initialisation which cannot safely be done in the <tt>__new__</tt> <p>Any initialisation which cannot safely be done in the <tt>__new__</tt>
method should be done in the <b><tt>__init__</tt></b> method. By the time method should be done in the <b><tt>__init__</tt></b> method. By the time
<tt>__init__</tt> is called, the object is a fully valid Python object and <tt>__init__</tt> is called, the object is a fully valid Python object and
all operations are safe. Under some circumstances it is possible for <tt>__init__</tt> all operations are safe. Under some circumstances it is possible for <tt>__init__</tt>
to be called more than once or not to be called at all, so your other methods to be called more than once or not to be called at all, so your other methods
should be designed to be robust in such situations. </p> should be designed to be robust in such situations. </p>
...@@ -57,27 +57,27 @@ to be called more than once or not to be called at all, so your other methods ...@@ -57,27 +57,27 @@ to be called more than once or not to be called at all, so your other methods
If you anticipate subclassing your extension type in Python, you may find If you anticipate subclassing your extension type in Python, you may find
it useful to give the <tt>__new__</tt> method * and ** arguments so that it useful to give the <tt>__new__</tt> method * and ** arguments so that
it can accept and ignore extra arguments. Otherwise, any Python subclass it can accept and ignore extra arguments. Otherwise, any Python subclass
which has an <tt>__init__</tt> with a different signature will have to override which has an <tt>__init__</tt> with a different signature will have to override
<tt>__new__</tt> as well as <tt>__init__</tt>, which the writer of a Python <tt>__new__</tt> as well as <tt>__init__</tt>, which the writer of a Python
class wouldn't expect to have to do. </p> class wouldn't expect to have to do. </p>
<h2> <font size="+1">Finalization method: <tt>__dealloc__</tt><tt></tt></font></h2> <h2> <font size="+1">Finalization method: <tt>__dealloc__</tt><tt></tt></font></h2>
The counterpart to the <tt>__new__</tt> method is the <b><tt>__dealloc__</tt></b> The counterpart to the <tt>__new__</tt> method is the <b><tt>__dealloc__</tt></b>
method, which should perform the inverse of the <tt>__new__</tt> method. method, which should perform the inverse of the <tt>__new__</tt> method.
Any C data structures that you allocated in your <tt>__new__</tt> method Any C data structures that you allocated in your <tt>__new__</tt> method
should be freed in your <tt>__dealloc__</tt> method. should be freed in your <tt>__dealloc__</tt> method.
<p>You need to be careful what you do in a <tt>__dealloc__</tt> method. By <p>You need to be careful what you do in a <tt>__dealloc__</tt> method. By
the time your <tt>__dealloc__</tt> method is called, the object may already the time your <tt>__dealloc__</tt> method is called, the object may already
have been partially destroyed and may not be in a valid state as far as Python have been partially destroyed and may not be in a valid state as far as Python
is concerned, so you should avoid invoking any Python operations which might is concerned, so you should avoid invoking any Python operations which might
touch the object. In particular, don't call any other methods of the object touch the object. In particular, don't call any other methods of the object
or do anything which might cause the object to be resurrected. It's best if or do anything which might cause the object to be resurrected. It's best if
you stick to just deallocating C data. </p> you stick to just deallocating C data. </p>
<p>You don't need to worry about deallocating Python attributes of your object, <p>You don't need to worry about deallocating Python attributes of your object,
because that will be done for you by Cython after your <tt>__dealloc__</tt> because that will be done for you by Cython after your <tt>__dealloc__</tt>
method returns.<br> method returns.<br>
<br> <br>
<b>Note:</b> There is no <tt>__del__</tt> method for extension types. (Earlier <b>Note:</b> There is no <tt>__del__</tt> method for extension types. (Earlier
versions of the Cython documentation stated that there was, but this turned versions of the Cython documentation stated that there was, but this turned
out to be incorrect.)<br> out to be incorrect.)<br>
</p> </p>
<h2><font size="+1">Arithmetic methods</font></h2> <h2><font size="+1">Arithmetic methods</font></h2>
...@@ -85,7 +85,7 @@ out to be incorrect.)<br> ...@@ -85,7 +85,7 @@ out to be incorrect.)<br>
from their Python counterparts. There are no separate "reversed" versions from their Python counterparts. There are no separate "reversed" versions
of these methods (<tt>__radd__</tt>, etc.) Instead, if the first operand of these methods (<tt>__radd__</tt>, etc.) Instead, if the first operand
cannot perform the operation, the <i>same</i> method of the second operand cannot perform the operation, the <i>same</i> method of the second operand
is called, with the operands in the <i>same order</i>. is called, with the operands in the <i>same order</i>.
<p>This means that you can't rely on the first parameter of these methods <p>This means that you can't rely on the first parameter of these methods
being "self", and you should test the types of both operands before deciding being "self", and you should test the types of both operands before deciding
what to do. If you can't handle the combination of types you've been given, what to do. If you can't handle the combination of types you've been given,
...@@ -96,8 +96,8 @@ is called, with the operands in the <i>same order</i>. ...@@ -96,8 +96,8 @@ is called, with the operands in the <i>same order</i>.
<h2> <font size="+1">Rich comparisons</font></h2> <h2> <font size="+1">Rich comparisons</font></h2>
There are no separate methods for the individual rich comparison operations There are no separate methods for the individual rich comparison operations
(<tt>__eq__</tt>, <tt>__le__</tt>, etc.) Instead there is a single method (<tt>__eq__</tt>, <tt>__le__</tt>, etc.) Instead there is a single method
<tt>__richcmp__</tt> which takes an integer indicating which operation is <tt>__richcmp__</tt> which takes an integer indicating which operation is
to be performed, as follows: to be performed, as follows:
<ul> <ul>
<ul> <ul>
&nbsp; <table nosave="" border="0" cellpadding="5" cellspacing="0"> &nbsp; <table nosave="" border="0" cellpadding="5" cellspacing="0">
...@@ -140,11 +140,11 @@ to be performed, as follows: ...@@ -140,11 +140,11 @@ to be performed, as follows:
a method called <b><tt>__next__</tt></b>, <i>not</i> <tt>next</tt>. The Python a method called <b><tt>__next__</tt></b>, <i>not</i> <tt>next</tt>. The Python
system will automatically supply a <tt>next</tt> method which calls your system will automatically supply a <tt>next</tt> method which calls your
<span style="font-family: monospace;">__next__</span>. <b>Do NOT explicitly give your type a <tt>next</tt> method</b>, <span style="font-family: monospace;">__next__</span>. <b>Do NOT explicitly give your type a <tt>next</tt> method</b>,
or bad things could happen (see note 3). or bad things could happen (see note 3).
<h2> <font size="+1">Special Method Table</font></h2> <h2> <font size="+1">Special Method Table</font></h2>
This table lists all of the special methods together with their parameter This table lists all of the special methods together with their parameter
and return types. A parameter named <b>self</b> is of the type the method and return types. A parameter named <b>self</b> is of the type the method
belongs to. Other untyped parameters are generic Python objects. belongs to. Other untyped parameters are generic Python objects.
<p>You don't have to declare your method as taking these parameter types. <p>You don't have to declare your method as taking these parameter types.
If you declare different types, conversions will be performed as necessary. If you declare different types, conversions will be performed as necessary.
<br> <br>
...@@ -586,14 +586,14 @@ or bad things could happen (see note 3). ...@@ -586,14 +586,14 @@ or bad things could happen (see note 3).
</tbody> </table> </tbody> </table>
</p> </p>
<p>Note 1: The buffer interface is intended for use by C code and is not <p>Note 1: The buffer interface is intended for use by C code and is not
directly accessible from Python. It is described in the <a href="http://www.python.org/doc/current/api/api.html">Python/C API Reference directly accessible from Python. It is described in the <a href="http://www.python.org/doc/current/api/api.html">Python/C API Reference
Manual</a> under sections <a href="http://www.python.org/doc/current/api/abstract-buffer.html">6.6</a> Manual</a> under sections <a href="http://www.python.org/doc/current/api/abstract-buffer.html">6.6</a>
and <a href="http://www.python.org/doc/current/api/buffer-structs.html">10.6</a>. and <a href="http://www.python.org/doc/current/api/buffer-structs.html">10.6</a>.
</p> </p>
<p>Note 2: Descriptor objects are part of the support mechanism for new-style <p>Note 2: Descriptor objects are part of the support mechanism for new-style
Python classes. See the <a href="http://www.python.org/doc/2.2.1/whatsnew/sect-rellinks.html#SECTION000320000000000000000">discussion Python classes. See the <a href="http://www.python.org/doc/2.2.1/whatsnew/sect-rellinks.html#SECTION000320000000000000000">discussion
of descriptors in the Python documentation</a>. See also <a href="http://www.python.org/peps/pep-0252.html">PEP 252, "Making Types Look of descriptors in the Python documentation</a>. See also <a href="http://www.python.org/peps/pep-0252.html">PEP 252, "Making Types Look
More Like Classes"</a>, and <a href="http://www.python.org/peps/pep-0253.html">PEP 253, "Subtyping Built-In More Like Classes"</a>, and <a href="http://www.python.org/peps/pep-0253.html">PEP 253, "Subtyping Built-In
Types"</a>. </p> Types"</a>. </p>
<p>Note 3: If your type defines a <tt>__new__</tt> method, any method called <p>Note 3: If your type defines a <tt>__new__</tt> method, any method called
<tt>new</tt> that you define will be overwritten with the system-supplied <tt>new</tt> that you define will be overwritten with the system-supplied
......
...@@ -2,7 +2,7 @@ PYTHON?=python ...@@ -2,7 +2,7 @@ PYTHON?=python
TESTOPTS?= TESTOPTS?=
REPO = git://github.com/cython/cython.git REPO = git://github.com/cython/cython.git
all: local all: local
local: local:
${PYTHON} setup.py build_ext --inplace ${PYTHON} setup.py build_ext --inplace
...@@ -23,8 +23,8 @@ clean: ...@@ -23,8 +23,8 @@ clean:
@echo Cleaning Source @echo Cleaning Source
@rm -fr build @rm -fr build
@rm -f *.py[co] */*.py[co] */*/*.py[co] */*/*/*.py[co] @rm -f *.py[co] */*.py[co] */*/*.py[co] */*/*/*.py[co]
@rm -f *.so */*.so */*/*.so @rm -f *.so */*.so */*/*.so
@rm -f *.pyd */*.pyd */*/*.pyd @rm -f *.pyd */*.pyd */*/*.pyd
@rm -f *~ */*~ */*/*~ @rm -f *~ */*~ */*/*~
@rm -f core */core @rm -f core */core
@rm -f Cython/Compiler/*.c @rm -f Cython/Compiler/*.c
......
...@@ -9,14 +9,14 @@ ...@@ -9,14 +9,14 @@
<!-- <!--
Disclaimer: IANAL. This file is a derivative work of KDE's Python Disclaimer: IANAL. This file is a derivative work of KDE's Python
syntax file. KDE does not specify a license for the syntax file python.xml syntax file. KDE does not specify a license for the syntax file python.xml
in it's katepart component. However, katepart and KATE as a whole is in it's katepart component. However, katepart and KATE as a whole is
released with LGPL v2. Assuing python.xml is LGPL'd, this file is hereby released with LGPL v2. Assuing python.xml is LGPL'd, this file is hereby
released with the same license. Note that this only applies to this XML released with the same license. Note that this only applies to this XML
file. It does not apply to any work written using this file to highlighting file. It does not apply to any work written using this file to highlighting
syntax. Any changes you make to this file will be covered by the LGPL, syntax. Any changes you make to this file will be covered by the LGPL,
but it does not to my knowledge taint your source code. At least not but it does not to my knowledge taint your source code. At least not
any more than using KDE would do. Sturla Molden any more than using KDE would do. Sturla Molden
Thus: Thus:
...@@ -69,10 +69,10 @@ Boston, MA 02110-1301, USA. ...@@ -69,10 +69,10 @@ Boston, MA 02110-1301, USA.
</list> </list>
<list name="keyw" > <list name="keyw" >
<item> extern </item> <item> extern </item>
<item> api </item> <item> api </item>
<item> del </item> <item> del </item>
<item> global </item> <item> global </item>
<item> property </item> <item> property </item>
<item> nogil </item> <item> nogil </item>
<item> gil </item> <item> gil </item>
<item> inline </item> <item> inline </item>
...@@ -80,7 +80,7 @@ Boston, MA 02110-1301, USA. ...@@ -80,7 +80,7 @@ Boston, MA 02110-1301, USA.
<list name="access"> <list name="access">
<item> readonly </item> <item> readonly </item>
<item> public </item> <item> public </item>
</list> </list>
<list name="operators"> <list name="operators">
<item> and </item> <item> and </item>
<item> assert </item> <item> assert </item>
...@@ -89,7 +89,7 @@ Boston, MA 02110-1301, USA. ...@@ -89,7 +89,7 @@ Boston, MA 02110-1301, USA.
<item> by </item> <item> by </item>
<item> not </item> <item> not </item>
<item> or </item> <item> or </item>
<item> sizeof </item> <item> sizeof </item>
</list> </list>
<list name="commands"> <list name="commands">
<!-- <item> exec </item> --> <!-- <item> exec </item> -->
...@@ -216,7 +216,7 @@ Boston, MA 02110-1301, USA. ...@@ -216,7 +216,7 @@ Boston, MA 02110-1301, USA.
</list> </list>
<list name="cythonmodule"> <list name="cythonmodule">
<item> cython </item> <item> cython </item>
</list> </list>
<list name="numpytypes"> <list name="numpytypes">
<item> dtype </item> <item> dtype </item>
<item> flatiter </item> <item> flatiter </item>
...@@ -244,48 +244,48 @@ Boston, MA 02110-1301, USA. ...@@ -244,48 +244,48 @@ Boston, MA 02110-1301, USA.
<item> cfloat_t </item> <item> cfloat_t </item>
<item> cdouble_t </item> <item> cdouble_t </item>
<item> clongdouble_t </item> <item> clongdouble_t </item>
<item> complex_t </item> <item> complex_t </item>
<item> npy_int8 </item> <item> npy_int8 </item>
<item> npy_int16 </item> <item> npy_int16 </item>
<item> npy_int32 </item> <item> npy_int32 </item>
<item> npy_int64 </item> <item> npy_int64 </item>
<item> npy_int96 </item> <item> npy_int96 </item>
<item> npy_int128 </item> <item> npy_int128 </item>
<item> npy_uint8 </item> <item> npy_uint8 </item>
<item> npy_uint16 </item> <item> npy_uint16 </item>
<item> npy_uint32 </item> <item> npy_uint32 </item>
<item> npy_uint64 </item> <item> npy_uint64 </item>
<item> npy_uint96 </item> <item> npy_uint96 </item>
<item> npy_uint128 </item> <item> npy_uint128 </item>
<item> npy_float32 </item> <item> npy_float32 </item>
<item> npy_float64 </item> <item> npy_float64 </item>
<item> npy_float80 </item> <item> npy_float80 </item>
<item> npy_float96 </item> <item> npy_float96 </item>
<item> npy_float128 </item> <item> npy_float128 </item>
<item> npy_complex64 </item> <item> npy_complex64 </item>
<item> npy_complex128 </item> <item> npy_complex128 </item>
<item> npy_complex120 </item> <item> npy_complex120 </item>
<item> npy_complex192 </item> <item> npy_complex192 </item>
<item> npy_complex256 </item> <item> npy_complex256 </item>
<item> npy_cfloat </item> <item> npy_cfloat </item>
<item> npy_cdouble </item> <item> npy_cdouble </item>
<item> npy_clongdouble </item> <item> npy_clongdouble </item>
<item> npy_bool </item> <item> npy_bool </item>
<item> npy_byte </item> <item> npy_byte </item>
<item> npy_short </item> <item> npy_short </item>
<item> npy_int </item> <item> npy_int </item>
<item> npy_long </item> <item> npy_long </item>
<item> npy_longlong </item> <item> npy_longlong </item>
<item> npy_ubyte </item> <item> npy_ubyte </item>
<item> npy_ushort </item> <item> npy_ushort </item>
<item> npy_uint </item> <item> npy_uint </item>
<item> npy_ulong </item> <item> npy_ulong </item>
<item> npy_ulonglong </item> <item> npy_ulonglong </item>
<item> npy_float </item> <item> npy_float </item>
<item> npy_double </item> <item> npy_double </item>
<item> npy_longdouble </item> <item> npy_longdouble </item>
<item> npy_intp </item> <item> npy_intp </item>
</list> </list>
<list name="numpyfuncs"> <list name="numpyfuncs">
<item> DataSource </item> <item> DataSource </item>
<item> MachAr </item> <item> MachAr </item>
...@@ -868,43 +868,43 @@ Boston, MA 02110-1301, USA. ...@@ -868,43 +868,43 @@ Boston, MA 02110-1301, USA.
<item>WindowsError</item> <item>WindowsError</item>
<item>ZeroDivisionError</item> <item>ZeroDivisionError</item>
</list> </list>
<contexts> <contexts>
<context name="Normal" attribute="Normal Text" lineEndContext="#stay"> <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
<keyword attribute="Definition Keyword" String="cdef" context="cdefname"/> <keyword attribute="Definition Keyword" String="cdef" context="cdefname"/>
<keyword attribute="Definition Keyword" String="defs" context="defname"/> <keyword attribute="Definition Keyword" String="defs" context="defname"/>
<keyword attribute="Definition Keyword" String="keyw" context="#stay"/> <keyword attribute="Definition Keyword" String="keyw" context="#stay"/>
<keyword attribute="Import Keyword" String="imports" context="#stay"/> <keyword attribute="Import Keyword" String="imports" context="#stay"/>
<keyword attribute="Preprocessor" String="prep" context="#stay"/> <keyword attribute="Preprocessor" String="prep" context="#stay"/>
<keyword attribute="Operator" String="operators" context="#stay"/> <keyword attribute="Operator" String="operators" context="#stay"/>
<keyword attribute="Command Keyword" String="commands" context="#stay"/> <keyword attribute="Command Keyword" String="commands" context="#stay"/>
<keyword attribute="Flow Control Keyword" String="flow" context="#stay"/> <keyword attribute="Flow Control Keyword" String="flow" context="#stay"/>
<keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/> <keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/>
<keyword attribute="Special Variable" String="specialvars" context="#stay"/> <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
<keyword attribute="Special Variable" String="exceptions" context="#stay"/> <keyword attribute="Special Variable" String="exceptions" context="#stay"/>
<keyword attribute="Special Variable" String="overloaders" context="#stay"/> <keyword attribute="Special Variable" String="overloaders" context="#stay"/>
<keyword attribute="C Type" context="#stay" String="ctypes" /> <keyword attribute="C Type" context="#stay" String="ctypes" />
<keyword attribute="Python Type" context="#stay" String="pytypes" /> <keyword attribute="Python Type" context="#stay" String="pytypes" />
<RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/> <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/>
<RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/> <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/>
<RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/> <RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/>
<RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/> <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
<RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/> <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/>
<RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/> <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/>
<RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/> <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/>
<keyword attribute="NumPyAttr" String="numpyselector" context="numpy"/> <keyword attribute="NumPyAttr" String="numpyselector" context="numpy"/>
<RegExpr attribute="Decorator" String="@[a-zA-Z_][a-zA-Z_0-9\.]+" context="#stay"/> <RegExpr attribute="Decorator" String="@[a-zA-Z_][a-zA-Z_0-9\.]+" context="#stay"/>
<RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/> <RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
<RegExpr attribute="Raw String" String="[rR]'''" context="Raw Tripple A-string"/> <RegExpr attribute="Raw String" String="[rR]'''" context="Raw Tripple A-string"/>
...@@ -916,115 +916,115 @@ Boston, MA 02110-1301, USA. ...@@ -916,115 +916,115 @@ Boston, MA 02110-1301, USA.
<RegExpr attribute="Comment" String="#.*$" context="#stay"/> <RegExpr attribute="Comment" String="#.*$" context="#stay"/>
<RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment" beginRegion="Tripple A-region"/> <RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment" beginRegion="Tripple A-region"/>
<RegExpr attribute="Comment" String="^\s*&quot;&quot;&quot;" context="Tripple Q-comment" beginRegion="Tripple Q-region"/> <RegExpr attribute="Comment" String="^\s*&quot;&quot;&quot;" context="Tripple Q-comment" beginRegion="Tripple Q-region"/>
<StringDetect attribute="String" String="'''" context="Tripple A-string" beginRegion="Tripple A-region"/> <StringDetect attribute="String" String="'''" context="Tripple A-string" beginRegion="Tripple A-region"/>
<StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string" beginRegion="Tripple Q-region"/> <StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string" beginRegion="Tripple Q-region"/>
<DetectChar attribute="String" char="'" context="Single A-string"/> <DetectChar attribute="String" char="'" context="Single A-string"/>
<DetectChar attribute="String" char="&quot;" context="Single Q-string"/> <DetectChar attribute="String" char="&quot;" context="Single Q-string"/>
<DetectChar attribute="Operator" char="(" context="parenthesis" /> <DetectChar attribute="Operator" char="(" context="parenthesis" />
<DetectChar attribute="Operator" char="[" context="bracet" /> <DetectChar attribute="Operator" char="[" context="bracet" />
<DetectChar attribute="Operator" char="{" context="dict" /> <DetectChar attribute="Operator" char="{" context="dict" />
<RegExpr attribute="Operator" String="[+*/%\|=;\!&lt;&gt;!^&amp;~-]" context="#stay"/> <RegExpr attribute="Operator" String="[+*/%\|=;\!&lt;&gt;!^&amp;~-]" context="#stay"/>
<RegExpr attribute="String Substitution" String="%[a-zA-Z]" context="#stay"/> <RegExpr attribute="String Substitution" String="%[a-zA-Z]" context="#stay"/>
</context> </context>
<context name="numpy" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> <context name="numpy" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
<!-- highlight types in numpy.pxd after cimport numpy --> <!-- highlight types in numpy.pxd after cimport numpy -->
<keyword attribute="Import Keyword" context="#pop" String="as" /> <keyword attribute="Import Keyword" context="#pop" String="as" />
<DetectChar attribute="Dot" context="#stay" char="." /> <DetectChar attribute="Dot" context="#stay" char="." />
<keyword attribute="NumPy Type" context="#pop" String="numpytypes" /> <keyword attribute="NumPy Type" context="#pop" String="numpytypes" />
<keyword attribute="NumPy Function" context="#pop" String="numpyfuncs" /> <keyword attribute="NumPy Function" context="#pop" String="numpyfuncs" />
</context> </context>
<context name="parenthesis" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="parenthesis" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
<DetectChar attribute="Operator" char=")" context="#pop" /> <DetectChar attribute="Operator" char=")" context="#pop" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="bracet" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="bracet" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
<StringDetect attribute="Normal" String="readonly" context="#stay" /> <StringDetect attribute="Normal" String="readonly" context="#stay" />
<DetectChar attribute="Operator" char="]" context="#pop" /> <DetectChar attribute="Operator" char="]" context="#pop" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="dict" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="dict" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
<DetectChar attribute="Operator" char="}" context="#pop" /> <DetectChar attribute="Operator" char="}" context="#pop" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="defname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> <context name="defname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
<RegExpr attribute="Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/> <RegExpr attribute="Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
<DetectChar attribute="Operator" char="(" context="callargs" /> <DetectChar attribute="Operator" char="(" context="callargs" />
<DetectChar attribute="Operator" char="[" context="callbracket" /> <DetectChar attribute="Operator" char="[" context="callbracket" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
<DetectChar attribute="Operator" char=")" context="#pop#pop" /> <DetectChar attribute="Operator" char=")" context="#pop#pop" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="callbracket" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="callbracket" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
<DetectChar attribute="Operator" char="]" context="#pop#pop" /> <DetectChar attribute="Operator" char="]" context="#pop#pop" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="cdefname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> <context name="cdefname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
<keyword attribute="Definition Keyword" String="defs" context="defname"/> <keyword attribute="Definition Keyword" String="defs" context="defname"/>
<keyword attribute="Definition Keyword" String="keyw" context="#stay"/> <keyword attribute="Definition Keyword" String="keyw" context="#stay"/>
<keyword attribute="Definition Keyword" String="access" context="#stay"/> <keyword attribute="Definition Keyword" String="access" context="#stay"/>
<keyword attribute="Import Keyword" String="imports" context="#stay"/> <keyword attribute="Import Keyword" String="imports" context="#stay"/>
<keyword attribute="Special Variable" String="specialvars" context="#stay"/> <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
<keyword attribute="C Type" context="#pop" String="ctypes" /> <keyword attribute="C Type" context="#pop" String="ctypes" />
<keyword attribute="Python Type" context="#pop" String="pytypes" /> <keyword attribute="Python Type" context="#pop" String="pytypes" />
<RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/> <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/>
<RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/> <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/>
<RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/> <RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/>
<RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/> <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
<RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/> <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/>
<RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/> <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/>
<RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/> <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/>
<keyword attribute="NumPyAttr" String="numpyselector" context="numpy2"/> <keyword attribute="NumPyAttr" String="numpyselector" context="numpy2"/>
<RegExpr attribute="C Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/> <RegExpr attribute="C Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
<DetectChar attribute="Operator" char="(" context="callargs" /> <DetectChar attribute="Operator" char="(" context="callargs" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
<DetectChar attribute="Operator" char=")" context="#pop#pop" /> <DetectChar attribute="Operator" char=")" context="#pop#pop" />
<IncludeRules context="Normal" /> <IncludeRules context="Normal" />
</context> </context>
<context name="numpy2" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> <context name="numpy2" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
<!-- highlight types in numpy.pxd after cimport numpy --> <!-- highlight types in numpy.pxd after cimport numpy -->
<DetectChar attribute="Dot" context="#stay" char="." /> <DetectChar attribute="Dot" context="#stay" char="." />
<keyword attribute="NumPy Type" context="#pop#pop" String="numpytypes" /> <keyword attribute="NumPy Type" context="#pop#pop" String="numpytypes" />
</context> </context>
<context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="True"> <context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="True">
<StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Tripple A-region"/> <StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Tripple A-region"/>
</context> </context>
......
...@@ -31,7 +31,7 @@ def analyse(source_path=None, code=None): ...@@ -31,7 +31,7 @@ def analyse(source_path=None, code=None):
raise ValueError("Either 'source_path' or 'code' is required.") raise ValueError("Either 'source_path' or 'code' is required.")
scoped_names = {} scoped_names = {}
statement_iter = jedi.names(source=code, path=source_path, all_scopes=True) statement_iter = jedi.names(source=code, path=source_path, all_scopes=True)
for statement in statement_iter: for statement in statement_iter:
parent = statement.parent() parent = statement.parent()
scope = parent._definition scope = parent._definition
...@@ -45,7 +45,7 @@ def analyse(source_path=None, code=None): ...@@ -45,7 +45,7 @@ def analyse(source_path=None, code=None):
names = scoped_names[key] names = scoped_names[key]
except KeyError: except KeyError:
names = scoped_names[key] = defaultdict(set) names = scoped_names[key] = defaultdict(set)
position = statement.start_pos if statement.name in names else None position = statement.start_pos if statement.name in names else None
for name_type in evaluator.find_types(scope, statement.name, position=position ,search_global=True): for name_type in evaluator.find_types(scope, statement.name, position=position ,search_global=True):
...@@ -60,8 +60,8 @@ def analyse(source_path=None, code=None): ...@@ -60,8 +60,8 @@ def analyse(source_path=None, code=None):
type_name = None type_name = None
else: else:
try: try:
type_name = type(name_type.obj).__name__ type_name = type(name_type.obj).__name__
except AttributeError as error: except AttributeError as error:
type_name = None type_name = None
if type_name is not None: if type_name is not None:
names[str(statement.name)].add(type_name) names[str(statement.name)].add(type_name)
......
...@@ -20,14 +20,14 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -20,14 +20,14 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ +
+<!-- +<!--
+ +
+Disclaimer: IANAL. This file is a derivative work of KDE's Python +Disclaimer: IANAL. This file is a derivative work of KDE's Python
+syntax file. KDE does not specify a license for the syntax file python.xml +syntax file. KDE does not specify a license for the syntax file python.xml
+in it's katepart component. However, katepart and KATE as a whole is +in it's katepart component. However, katepart and KATE as a whole is
+released with LGPL v2. Assuing python.xml is LGPL'd, this file is hereby +released with LGPL v2. Assuing python.xml is LGPL'd, this file is hereby
+released with the same license. Note that this only applies to this XML +released with the same license. Note that this only applies to this XML
+file. It does not apply to any work written using this file to highlighting +file. It does not apply to any work written using this file to highlighting
+syntax. Any changes you make to this file will be covered by the LGPL, +syntax. Any changes you make to this file will be covered by the LGPL,
+but it does not to my knowledge taint your source code. At least not +but it does not to my knowledge taint your source code. At least not
+any more than using KDE would do. Sturla Molden +any more than using KDE would do. Sturla Molden
+ +
+Thus: +Thus:
...@@ -80,10 +80,10 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -80,10 +80,10 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ </list> + </list>
+ <list name="keyw" > + <list name="keyw" >
+ <item> extern </item> + <item> extern </item>
+ <item> api </item> + <item> api </item>
+ <item> del </item> + <item> del </item>
+ <item> global </item> + <item> global </item>
+ <item> property </item> + <item> property </item>
+ <item> nogil </item> + <item> nogil </item>
+ <item> gil </item> + <item> gil </item>
+ <item> inline </item> + <item> inline </item>
...@@ -91,7 +91,7 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -91,7 +91,7 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ <list name="access"> + <list name="access">
+ <item> readonly </item> + <item> readonly </item>
+ <item> public </item> + <item> public </item>
+ </list> + </list>
+ <list name="operators"> + <list name="operators">
+ <item> and </item> + <item> and </item>
+ <item> assert </item> + <item> assert </item>
...@@ -100,7 +100,7 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -100,7 +100,7 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ <item> by </item> + <item> by </item>
+ <item> not </item> + <item> not </item>
+ <item> or </item> + <item> or </item>
+ <item> sizeof </item> + <item> sizeof </item>
+ </list> + </list>
+ <list name="commands"> + <list name="commands">
+ <!-- <item> exec </item> --> + <!-- <item> exec </item> -->
...@@ -227,7 +227,7 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -227,7 +227,7 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ </list> + </list>
+ <list name="cythonmodule"> + <list name="cythonmodule">
+ <item> cython </item> + <item> cython </item>
+ </list> + </list>
+ <list name="numpytypes"> + <list name="numpytypes">
+ <item> dtype </item> + <item> dtype </item>
+ <item> flatiter </item> + <item> flatiter </item>
...@@ -255,48 +255,48 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -255,48 +255,48 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ <item> cfloat_t </item> + <item> cfloat_t </item>
+ <item> cdouble_t </item> + <item> cdouble_t </item>
+ <item> clongdouble_t </item> + <item> clongdouble_t </item>
+ <item> complex_t </item> + <item> complex_t </item>
+ <item> npy_int8 </item> + <item> npy_int8 </item>
+ <item> npy_int16 </item> + <item> npy_int16 </item>
+ <item> npy_int32 </item> + <item> npy_int32 </item>
+ <item> npy_int64 </item> + <item> npy_int64 </item>
+ <item> npy_int96 </item> + <item> npy_int96 </item>
+ <item> npy_int128 </item> + <item> npy_int128 </item>
+ <item> npy_uint8 </item> + <item> npy_uint8 </item>
+ <item> npy_uint16 </item> + <item> npy_uint16 </item>
+ <item> npy_uint32 </item> + <item> npy_uint32 </item>
+ <item> npy_uint64 </item> + <item> npy_uint64 </item>
+ <item> npy_uint96 </item> + <item> npy_uint96 </item>
+ <item> npy_uint128 </item> + <item> npy_uint128 </item>
+ <item> npy_float32 </item> + <item> npy_float32 </item>
+ <item> npy_float64 </item> + <item> npy_float64 </item>
+ <item> npy_float80 </item> + <item> npy_float80 </item>
+ <item> npy_float96 </item> + <item> npy_float96 </item>
+ <item> npy_float128 </item> + <item> npy_float128 </item>
+ <item> npy_complex64 </item> + <item> npy_complex64 </item>
+ <item> npy_complex128 </item> + <item> npy_complex128 </item>
+ <item> npy_complex120 </item> + <item> npy_complex120 </item>
+ <item> npy_complex192 </item> + <item> npy_complex192 </item>
+ <item> npy_complex256 </item> + <item> npy_complex256 </item>
+ <item> npy_cfloat </item> + <item> npy_cfloat </item>
+ <item> npy_cdouble </item> + <item> npy_cdouble </item>
+ <item> npy_clongdouble </item> + <item> npy_clongdouble </item>
+ <item> npy_bool </item> + <item> npy_bool </item>
+ <item> npy_byte </item> + <item> npy_byte </item>
+ <item> npy_short </item> + <item> npy_short </item>
+ <item> npy_int </item> + <item> npy_int </item>
+ <item> npy_long </item> + <item> npy_long </item>
+ <item> npy_longlong </item> + <item> npy_longlong </item>
+ <item> npy_ubyte </item> + <item> npy_ubyte </item>
+ <item> npy_ushort </item> + <item> npy_ushort </item>
+ <item> npy_uint </item> + <item> npy_uint </item>
+ <item> npy_ulong </item> + <item> npy_ulong </item>
+ <item> npy_ulonglong </item> + <item> npy_ulonglong </item>
+ <item> npy_float </item> + <item> npy_float </item>
+ <item> npy_double </item> + <item> npy_double </item>
+ <item> npy_longdouble </item> + <item> npy_longdouble </item>
+ <item> npy_intp </item> + <item> npy_intp </item>
+ </list> + </list>
+ <list name="numpyfuncs"> + <list name="numpyfuncs">
+ <item> DataSource </item> + <item> DataSource </item>
+ <item> MachAr </item> + <item> MachAr </item>
...@@ -879,43 +879,43 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -879,43 +879,43 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ <item>WindowsError</item> + <item>WindowsError</item>
+ <item>ZeroDivisionError</item> + <item>ZeroDivisionError</item>
+ </list> + </list>
+ +
+ <contexts> + <contexts>
+ +
+ <context name="Normal" attribute="Normal Text" lineEndContext="#stay"> + <context name="Normal" attribute="Normal Text" lineEndContext="#stay">
+ +
+ <keyword attribute="Definition Keyword" String="cdef" context="cdefname"/> + <keyword attribute="Definition Keyword" String="cdef" context="cdefname"/>
+ <keyword attribute="Definition Keyword" String="defs" context="defname"/> + <keyword attribute="Definition Keyword" String="defs" context="defname"/>
+ <keyword attribute="Definition Keyword" String="keyw" context="#stay"/> + <keyword attribute="Definition Keyword" String="keyw" context="#stay"/>
+ +
+ <keyword attribute="Import Keyword" String="imports" context="#stay"/> + <keyword attribute="Import Keyword" String="imports" context="#stay"/>
+ <keyword attribute="Preprocessor" String="prep" context="#stay"/> + <keyword attribute="Preprocessor" String="prep" context="#stay"/>
+ <keyword attribute="Operator" String="operators" context="#stay"/> + <keyword attribute="Operator" String="operators" context="#stay"/>
+ <keyword attribute="Command Keyword" String="commands" context="#stay"/> + <keyword attribute="Command Keyword" String="commands" context="#stay"/>
+ <keyword attribute="Flow Control Keyword" String="flow" context="#stay"/> + <keyword attribute="Flow Control Keyword" String="flow" context="#stay"/>
+ <keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/> + <keyword attribute="Builtin Function" String="builtinfuncs" context="#stay"/>
+ +
+ <keyword attribute="Special Variable" String="specialvars" context="#stay"/> + <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
+ <keyword attribute="Special Variable" String="exceptions" context="#stay"/> + <keyword attribute="Special Variable" String="exceptions" context="#stay"/>
+ <keyword attribute="Special Variable" String="overloaders" context="#stay"/> + <keyword attribute="Special Variable" String="overloaders" context="#stay"/>
+ +
+ <keyword attribute="C Type" context="#stay" String="ctypes" /> + <keyword attribute="C Type" context="#stay" String="ctypes" />
+ <keyword attribute="Python Type" context="#stay" String="pytypes" /> + <keyword attribute="Python Type" context="#stay" String="pytypes" />
+ +
+ <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/> + <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/>
+ <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/> + <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/>
+ <RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/> + <RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/>
+ +
+ <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/> + <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
+ <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/> + <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/>
+ +
+ <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/> + <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/>
+ <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/> + <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/>
+ +
+ <keyword attribute="NumPyAttr" String="numpyselector" context="numpy"/> + <keyword attribute="NumPyAttr" String="numpyselector" context="numpy"/>
+ +
+ <RegExpr attribute="Decorator" String="@[a-zA-Z_][a-zA-Z_0-9\.]+" context="#stay"/> + <RegExpr attribute="Decorator" String="@[a-zA-Z_][a-zA-Z_0-9\.]+" context="#stay"/>
+ +
+ <RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/> + <RegExpr attribute="Normal" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
+ +
+ <RegExpr attribute="Raw String" String="[rR]'''" context="Raw Tripple A-string"/> + <RegExpr attribute="Raw String" String="[rR]'''" context="Raw Tripple A-string"/>
...@@ -927,115 +927,115 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml ...@@ -927,115 +927,115 @@ diff -r db4133d43a7e -r 0a6ce52272f6 Tools/cython-numpy-mode-kate.xml
+ <RegExpr attribute="Comment" String="#.*$" context="#stay"/> + <RegExpr attribute="Comment" String="#.*$" context="#stay"/>
+ <RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment" beginRegion="Tripple A-region"/> + <RegExpr attribute="Comment" String="^\s*'''" context="Tripple A-comment" beginRegion="Tripple A-region"/>
+ <RegExpr attribute="Comment" String="^\s*&quot;&quot;&quot;" context="Tripple Q-comment" beginRegion="Tripple Q-region"/> + <RegExpr attribute="Comment" String="^\s*&quot;&quot;&quot;" context="Tripple Q-comment" beginRegion="Tripple Q-region"/>
+ +
+ <StringDetect attribute="String" String="'''" context="Tripple A-string" beginRegion="Tripple A-region"/> + <StringDetect attribute="String" String="'''" context="Tripple A-string" beginRegion="Tripple A-region"/>
+ <StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string" beginRegion="Tripple Q-region"/> + <StringDetect attribute="String" String="&quot;&quot;&quot;" context="Tripple Q-string" beginRegion="Tripple Q-region"/>
+ <DetectChar attribute="String" char="'" context="Single A-string"/> + <DetectChar attribute="String" char="'" context="Single A-string"/>
+ <DetectChar attribute="String" char="&quot;" context="Single Q-string"/> + <DetectChar attribute="String" char="&quot;" context="Single Q-string"/>
+ +
+ +
+ <DetectChar attribute="Operator" char="(" context="parenthesis" /> + <DetectChar attribute="Operator" char="(" context="parenthesis" />
+ +
+ <DetectChar attribute="Operator" char="[" context="bracet" /> + <DetectChar attribute="Operator" char="[" context="bracet" />
+ +
+ <DetectChar attribute="Operator" char="{" context="dict" /> + <DetectChar attribute="Operator" char="{" context="dict" />
+ +
+ <RegExpr attribute="Operator" String="[+*/%\|=;\!&lt;&gt;!^&amp;~-]" context="#stay"/> + <RegExpr attribute="Operator" String="[+*/%\|=;\!&lt;&gt;!^&amp;~-]" context="#stay"/>
+ +
+ <RegExpr attribute="String Substitution" String="%[a-zA-Z]" context="#stay"/> + <RegExpr attribute="String Substitution" String="%[a-zA-Z]" context="#stay"/>
+ +
+ </context> + </context>
+ +
+ <context name="numpy" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> + <context name="numpy" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
+ <!-- highlight types in numpy.pxd after cimport numpy --> + <!-- highlight types in numpy.pxd after cimport numpy -->
+ <keyword attribute="Import Keyword" context="#pop" String="as" /> + <keyword attribute="Import Keyword" context="#pop" String="as" />
+ <DetectChar attribute="Dot" context="#stay" char="." /> + <DetectChar attribute="Dot" context="#stay" char="." />
+ <keyword attribute="NumPy Type" context="#pop" String="numpytypes" /> + <keyword attribute="NumPy Type" context="#pop" String="numpytypes" />
+ <keyword attribute="NumPy Function" context="#pop" String="numpyfuncs" /> + <keyword attribute="NumPy Function" context="#pop" String="numpyfuncs" />
+ </context> + </context>
+ +
+ <context name="parenthesis" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="parenthesis" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <DetectChar attribute="Operator" char=")" context="#pop" /> + <DetectChar attribute="Operator" char=")" context="#pop" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ <context name="bracet" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="bracet" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <StringDetect attribute="Normal" String="readonly" context="#stay" /> + <StringDetect attribute="Normal" String="readonly" context="#stay" />
+ <DetectChar attribute="Operator" char="]" context="#pop" /> + <DetectChar attribute="Operator" char="]" context="#pop" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ <context name="dict" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="dict" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <DetectChar attribute="Operator" char="}" context="#pop" /> + <DetectChar attribute="Operator" char="}" context="#pop" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ <context name="defname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> + <context name="defname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
+ <RegExpr attribute="Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/> + <RegExpr attribute="Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
+ <DetectChar attribute="Operator" char="(" context="callargs" /> + <DetectChar attribute="Operator" char="(" context="callargs" />
+ <DetectChar attribute="Operator" char="[" context="callbracket" /> + <DetectChar attribute="Operator" char="[" context="callbracket" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ <context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <DetectChar attribute="Operator" char=")" context="#pop#pop" /> + <DetectChar attribute="Operator" char=")" context="#pop#pop" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ <context name="callbracket" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="callbracket" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <DetectChar attribute="Operator" char="]" context="#pop#pop" /> + <DetectChar attribute="Operator" char="]" context="#pop#pop" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ +
+ <context name="cdefname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> + <context name="cdefname" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
+ <keyword attribute="Definition Keyword" String="defs" context="defname"/> + <keyword attribute="Definition Keyword" String="defs" context="defname"/>
+ <keyword attribute="Definition Keyword" String="keyw" context="#stay"/> + <keyword attribute="Definition Keyword" String="keyw" context="#stay"/>
+ <keyword attribute="Definition Keyword" String="access" context="#stay"/> + <keyword attribute="Definition Keyword" String="access" context="#stay"/>
+ <keyword attribute="Import Keyword" String="imports" context="#stay"/> + <keyword attribute="Import Keyword" String="imports" context="#stay"/>
+ <keyword attribute="Special Variable" String="specialvars" context="#stay"/> + <keyword attribute="Special Variable" String="specialvars" context="#stay"/>
+ +
+ <keyword attribute="C Type" context="#pop" String="ctypes" /> + <keyword attribute="C Type" context="#pop" String="ctypes" />
+ <keyword attribute="Python Type" context="#pop" String="pytypes" /> + <keyword attribute="Python Type" context="#pop" String="pytypes" />
+ +
+ <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/> + <RegExpr attribute="Hex" String="0[Xx][0-9a-fA-F]+" context="#stay"/>
+ <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/> + <RegExpr attribute="Octal" String="0[1-9][0-9]*" context="#stay"/>
+ <RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/> + <RegExpr attribute="Binary" String="0[Bb][0-9a-fA-F]+" context="#stay"/>
+ +
+ <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/> + <RegExpr attribute="Complex" String=" ((([0-9]*\.[0-9]+|[0-9]+\.)|([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.))[eE](\+|-)?[0-9]+)|[0-9]+)[jJ]" context="#stay"/>
+ <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/> + <RegExpr attribute="Float" String="([0-9]+\.[0-9]*|\.[0-9]+)([eE][0-9]+)?" context="#stay"/>
+ +
+ <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/> + <RegExpr attribute="Int" String="([1-9][0-9]*([eE][0-9]+)?|0)" context="#stay"/>
+ <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/> + <RegExpr attribute="Long" String="[1-9][0-9]*([eE][0-9.]+)?[Ll]" context="#stay"/>
+ +
+ <keyword attribute="NumPyAttr" String="numpyselector" context="numpy2"/> + <keyword attribute="NumPyAttr" String="numpyselector" context="numpy2"/>
+ +
+ <RegExpr attribute="C Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/> + <RegExpr attribute="C Definition Name" String="[a-zA-Z_][a-zA-Z_0-9]+" context="#stay"/>
+ <DetectChar attribute="Operator" char="(" context="callargs" /> + <DetectChar attribute="Operator" char="(" context="callargs" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ <context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="callargs" attribute="Normal Text" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <DetectChar attribute="Operator" char=")" context="#pop#pop" /> + <DetectChar attribute="Operator" char=")" context="#pop#pop" />
+ <IncludeRules context="Normal" /> + <IncludeRules context="Normal" />
+ </context> + </context>
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ <context name="numpy2" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True"> + <context name="numpy2" attribute="Normal Text" lineEndContext="#pop" noIndentationBasedFolding="True">
+ <!-- highlight types in numpy.pxd after cimport numpy --> + <!-- highlight types in numpy.pxd after cimport numpy -->
+ <DetectChar attribute="Dot" context="#stay" char="." /> + <DetectChar attribute="Dot" context="#stay" char="." />
+ <keyword attribute="NumPy Type" context="#pop#pop" String="numpytypes" /> + <keyword attribute="NumPy Type" context="#pop#pop" String="numpytypes" />
+ </context> + </context>
+ +
+ +
+ +
+ +
+ <context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="True"> + <context name="Tripple A-comment" attribute="Comment" lineEndContext="#stay" noIndentationBasedFolding="True">
+ <StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Tripple A-region"/> + <StringDetect attribute="Comment" String="'''" context="#pop" endRegion="Tripple A-region"/>
+ </context> + </context>
......
...@@ -133,7 +133,7 @@ def set_basic_vars(env): ...@@ -133,7 +133,7 @@ def set_basic_vars(env):
# this work, we need to know whether PYEXTCC accepts /c and /Fo or -c -o. # this work, we need to know whether PYEXTCC accepts /c and /Fo or -c -o.
# This is difficult with the current way tools work in scons. # This is difficult with the current way tools work in scons.
pycc, pycxx, pylink = pyext_coms(sys.platform) pycc, pycxx, pylink = pyext_coms(sys.platform)
env['PYEXTLINKFLAGSEND'] = SCons.Util.CLVar('$LINKFLAGSEND') env['PYEXTLINKFLAGSEND'] = SCons.Util.CLVar('$LINKFLAGSEND')
env['PYEXTCCCOM'] = pycc env['PYEXTCCCOM'] = pycc
...@@ -157,7 +157,7 @@ def _set_configuration_nodistutils(env): ...@@ -157,7 +157,7 @@ def _set_configuration_nodistutils(env):
for k, v in def_cfg.items(): for k, v in def_cfg.items():
ifnotset(env, k, v) ifnotset(env, k, v)
ifnotset(env, 'PYEXT_ALLOW_UNDEFINED', ifnotset(env, 'PYEXT_ALLOW_UNDEFINED',
SCons.Util.CLVar('$ALLOW_UNDEFINED')) SCons.Util.CLVar('$ALLOW_UNDEFINED'))
ifnotset(env, 'PYEXTLINKFLAGS', SCons.Util.CLVar('$LDMODULEFLAGS')) ifnotset(env, 'PYEXTLINKFLAGS', SCons.Util.CLVar('$LDMODULEFLAGS'))
...@@ -178,12 +178,12 @@ def set_configuration(env, use_distutils): ...@@ -178,12 +178,12 @@ def set_configuration(env, use_distutils):
# We define commands as strings so that we can either execute them using # We define commands as strings so that we can either execute them using
# eval (same python for scons and distutils) or by executing them through # eval (same python for scons and distutils) or by executing them through
# the shell. # the shell.
dist_cfg = {'PYEXTCC': ("sysconfig.get_config_var('CC')", False), dist_cfg = {'PYEXTCC': ("sysconfig.get_config_var('CC')", False),
'PYEXTCFLAGS': ("sysconfig.get_config_var('CFLAGS')", True), 'PYEXTCFLAGS': ("sysconfig.get_config_var('CFLAGS')", True),
'PYEXTCCSHARED': ("sysconfig.get_config_var('CCSHARED')", False), 'PYEXTCCSHARED': ("sysconfig.get_config_var('CCSHARED')", False),
'PYEXTLINKFLAGS': ("sysconfig.get_config_var('LDFLAGS')", True), 'PYEXTLINKFLAGS': ("sysconfig.get_config_var('LDFLAGS')", True),
'PYEXTLINK': ("sysconfig.get_config_var('LDSHARED')", False), 'PYEXTLINK': ("sysconfig.get_config_var('LDSHARED')", False),
'PYEXTINCPATH': ("sysconfig.get_python_inc()", False), 'PYEXTINCPATH': ("sysconfig.get_python_inc()", False),
'PYEXTSUFFIX': ("sysconfig.get_config_var('SO')", False)} 'PYEXTSUFFIX': ("sysconfig.get_config_var('SO')", False)}
from distutils import sysconfig from distutils import sysconfig
...@@ -208,7 +208,7 @@ def generate(env): ...@@ -208,7 +208,7 @@ def generate(env):
if 'PYEXT_USE_DISTUTILS' not in env: if 'PYEXT_USE_DISTUTILS' not in env:
env['PYEXT_USE_DISTUTILS'] = False env['PYEXT_USE_DISTUTILS'] = False
# This sets all constructions variables used for pyext builders. # This sets all constructions variables used for pyext builders.
set_basic_vars(env) set_basic_vars(env)
set_configuration(env, env['PYEXT_USE_DISTUTILS']) set_configuration(env, env['PYEXT_USE_DISTUTILS'])
......
...@@ -6,21 +6,21 @@ Background ...@@ -6,21 +6,21 @@ Background
The "Old Cython Users Guide" is a derivative of the old Pyrex documentation. The "Old Cython Users Guide" is a derivative of the old Pyrex documentation.
It underwent substantial editing by Peter Alexandar It underwent substantial editing by Peter Alexandar
to become the Reference Guide, which is oriented around bullet points to become the Reference Guide, which is oriented around bullet points
and lists rather than prose. This transition was incomplete. and lists rather than prose. This transition was incomplete.
At nearly the same time, Robert, Dag, and Stefan wrote a tutorial as At nearly the same time, Robert, Dag, and Stefan wrote a tutorial as
part of the SciPy proceedings. It was felt that the content there was part of the SciPy proceedings. It was felt that the content there was
cleaner and more up to date than anything else, and this became the cleaner and more up to date than anything else, and this became the
basis for the "Getting Started" and "Tutorials" sections. However, basis for the "Getting Started" and "Tutorials" sections. However,
it simply doesn't have as much content as the old documentation used to. it simply doesn't have as much content as the old documentation used to.
Eventually, it seems all of the old users manual could be whittled Eventually, it seems all of the old users manual could be whittled
down into independent tutorial topics. Much discussion of what we'd down into independent tutorial topics. Much discussion of what we'd
like to see is at like to see is at
http://www.mail-archive.com/cython-dev@codespeak.net/msg06945.html http://www.mail-archive.com/cython-dev@codespeak.net/msg06945.html
There is currently a huge amount of redundancy, but no one section has There is currently a huge amount of redundancy, but no one section has
it all. it all.
Also, we should go through the wiki enhancement proposal list Also, we should go through the wiki enhancement proposal list
and make sure to transfer the (done) ones into the user manual. and make sure to transfer the (done) ones into the user manual.
...@@ -77,5 +77,5 @@ def integrate_f2(double a, double b, int N): ...@@ -77,5 +77,5 @@ def integrate_f2(double a, double b, int N):
for i in range(N): for i in range(N):
s += f2(a+i*dx) s += f2(a+i*dx)
return s * dx return s * dx
timeit(integrate_f2, "Typed func") timeit(integrate_f2, "Typed func")
...@@ -25,7 +25,7 @@ Originally based on the well-known Pyrex [Pyrex]_, the Cython project ...@@ -25,7 +25,7 @@ Originally based on the well-known Pyrex [Pyrex]_, the Cython project
has approached this problem by means of a source code compiler that has approached this problem by means of a source code compiler that
translates Python code to equivalent C code. This code is executed translates Python code to equivalent C code. This code is executed
within the CPython runtime environment, but at the speed of compiled C within the CPython runtime environment, but at the speed of compiled C
and with the ability to call directly into C libraries. and with the ability to call directly into C libraries.
At the same time, it keeps the original interface of the Python At the same time, it keeps the original interface of the Python
source code, which makes it directly usable from Python code. These source code, which makes it directly usable from Python code. These
two-fold characteristics enable Cython's two major use cases: two-fold characteristics enable Cython's two major use cases:
...@@ -48,7 +48,7 @@ language. ...@@ -48,7 +48,7 @@ language.
.. [IronPython] Jim Hugunin et al., http://www.codeplex.com/IronPython. .. [IronPython] Jim Hugunin et al., http://www.codeplex.com/IronPython.
.. [Jython] J. Huginin, B. Warsaw, F. Bock, et al., .. [Jython] J. Huginin, B. Warsaw, F. Bock, et al.,
Jython: Python for the Java platform, http://www.jython.org. Jython: Python for the Java platform, http://www.jython.org.
.. [PyPy] The PyPy Group, PyPy: a Python implementation written in Python, .. [PyPy] The PyPy Group, PyPy: a Python implementation written in Python,
http://pypy.org. http://pypy.org.
.. [Pyrex] G. Ewing, Pyrex: C-Extensions for Python, .. [Pyrex] G. Ewing, Pyrex: C-Extensions for Python,
http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
......
Appendix: Installing MinGW on Windows Appendix: Installing MinGW on Windows
===================================== =====================================
1. Download the MinGW installer from 1. Download the MinGW installer from
http://www.mingw.org/wiki/HOWTO_Install_the_MinGW_GCC_Compiler_Suite. http://www.mingw.org/wiki/HOWTO_Install_the_MinGW_GCC_Compiler_Suite.
(As of this (As of this
writing, the download link is a bit difficult to find; it's under writing, the download link is a bit difficult to find; it's under
"About" in the menu on the left-hand side). You want the file "About" in the menu on the left-hand side). You want the file
......
...@@ -15,5 +15,5 @@ for Python users, so this list may change in the future. ...@@ -15,5 +15,5 @@ for Python users, so this list may change in the future.
print(range(-n, n))`` will print an empty list, since ``-n`` wraps print(range(-n, n))`` will print an empty list, since ``-n`` wraps
around to a large positive integer prior to being passed to the around to a large positive integer prior to being passed to the
``range`` function. ``range`` function.
- Python's ``float`` type actually wraps C ``double`` values, and - Python's ``float`` type actually wraps C ``double`` values, and
the ``int`` type in Python 2.x wraps C ``long`` values. the ``int`` type in Python 2.x wraps C ``long`` values.
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
'title': 'Cython Tutorial', 'title': 'Cython Tutorial',
'paper_abstract': ''' 'paper_abstract': '''
Cython is a programming language based on Python with extra Cython is a programming language based on Python with extra
syntax to provide static type declarations. This takes advantage of the syntax to provide static type declarations. This takes advantage of the
benefits of Python while allowing one to achieve the speed of C. benefits of Python while allowing one to achieve the speed of C.
In this paper we describe the Cython language and show how it can In this paper we describe the Cython language and show how it can
be used both to write optimized code and to interface with external be used both to write optimized code and to interface with external
C libraries. C libraries.
''', ''',
'authors': [ 'authors': [
{'first_names': 'Stefan', {'first_names': 'Stefan',
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
Profiling Profiling
********* *********
This part describes the profiling abilities of Cython. If you are familiar This part describes the profiling abilities of Cython. If you are familiar
with profiling pure Python code, you can only read the first section with profiling pure Python code, you can only read the first section
(:ref:`profiling_basics`). If you are not familiar with Python profiling you (:ref:`profiling_basics`). If you are not familiar with Python profiling you
should also read the tutorial (:ref:`profiling_tutorial`) which takes you should also read the tutorial (:ref:`profiling_tutorial`) which takes you
...@@ -17,7 +17,7 @@ through a complete example step by step. ...@@ -17,7 +17,7 @@ through a complete example step by step.
Cython Profiling Basics Cython Profiling Basics
======================= =======================
Profiling in Cython is controlled by a compiler directive. Profiling in Cython is controlled by a compiler directive.
It can be set either for an entire file or on a per function basis It can be set either for an entire file or on a per function basis
via a Cython decorator. via a Cython decorator.
...@@ -26,7 +26,7 @@ Enabling profiling for a complete source file ...@@ -26,7 +26,7 @@ Enabling profiling for a complete source file
Profiling is enabled for a complete source file via a global directive to the Profiling is enabled for a complete source file via a global directive to the
Cython compiler at the top of a file:: Cython compiler at the top of a file::
# cython: profile=True # cython: profile=True
Note that profiling gives a slight overhead to each function call therefore making Note that profiling gives a slight overhead to each function call therefore making
...@@ -35,7 +35,7 @@ often). ...@@ -35,7 +35,7 @@ often).
Once enabled, your Cython code will behave just like Python code when called Once enabled, your Cython code will behave just like Python code when called
from the cProfile module. This means you can just profile your Cython code from the cProfile module. This means you can just profile your Cython code
together with your Python code using the same tools as for Python code alone. together with your Python code using the same tools as for Python code alone.
Disabling profiling function wise Disabling profiling function wise
--------------------------------- ---------------------------------
...@@ -111,7 +111,7 @@ Profiling Tutorial ...@@ -111,7 +111,7 @@ Profiling Tutorial
================== ==================
This will be a complete tutorial, start to finish, of profiling Python code, This will be a complete tutorial, start to finish, of profiling Python code,
turning it into Cython code and keep profiling until it is fast enough. turning it into Cython code and keep profiling until it is fast enough.
As a toy example, we would like to evaluate the summation of the reciprocals of As a toy example, we would like to evaluate the summation of the reciprocals of
squares up to a certain integer :math:`n` for evaluating :math:`\pi`. The squares up to a certain integer :math:`n` for evaluating :math:`\pi`. The
...@@ -120,8 +120,8 @@ relation we want to use has been proven by Euler in 1735 and is known as the ...@@ -120,8 +120,8 @@ relation we want to use has been proven by Euler in 1735 and is known as the
.. math:: .. math::
\pi^2 = 6 \sum_{k=1}^{\infty} \frac{1}{k^2} = \pi^2 = 6 \sum_{k=1}^{\infty} \frac{1}{k^2} =
6 \lim_{k \to \infty} \big( \frac{1}{1^2} + 6 \lim_{k \to \infty} \big( \frac{1}{1^2} +
\frac{1}{2^2} + \dots + \frac{1}{k^2} \big) \approx \frac{1}{2^2} + \dots + \frac{1}{k^2} \big) \approx
6 \big( \frac{1}{1^2} + \frac{1}{2^2} + \dots + \frac{1}{n^2} \big) 6 \big( \frac{1}{1^2} + \frac{1}{2^2} + \dots + \frac{1}{n^2} \big)
...@@ -139,7 +139,7 @@ A simple Python code for evaluating the truncated sum looks like this:: ...@@ -139,7 +139,7 @@ A simple Python code for evaluating the truncated sum looks like this::
for k in range(1,n+1): for k in range(1,n+1):
val += recip_square(k) val += recip_square(k)
return (6 * val)**.5 return (6 * val)**.5
On my box, this needs approximately 4 seconds to run the function with the On my box, this needs approximately 4 seconds to run the function with the
default n. The higher we choose n, the better will be the approximation for default n. The higher we choose n, the better will be the approximation for
:math:`\pi`. An experienced Python programmer will already see plenty of :math:`\pi`. An experienced Python programmer will already see plenty of
...@@ -186,7 +186,7 @@ Python `profiling documentation <http://docs.python.org/library/profile.html>`_ ...@@ -186,7 +186,7 @@ Python `profiling documentation <http://docs.python.org/library/profile.html>`_
for the nitty gritty details. The most important columns here are totime (total for the nitty gritty details. The most important columns here are totime (total
time spent in this function **not** counting functions that were called by this time spent in this function **not** counting functions that were called by this
function) and cumtime (total time spent in this function **also** counting the function) and cumtime (total time spent in this function **also** counting the
functions called by this function). Looking at the tottime column, we see that functions called by this function). Looking at the tottime column, we see that
approximately half the time is spent in approx_pi and the other half is spent approximately half the time is spent in approx_pi and the other half is spent
in recip_square. Also half a second is spent in range ... of course we should in recip_square. Also half a second is spent in range ... of course we should
have used xrange for such a big iteration. And in fact, just changing range to have used xrange for such a big iteration. And in fact, just changing range to
...@@ -213,7 +213,7 @@ anyway at some time to get the loop run faster. Here is our first Cython version ...@@ -213,7 +213,7 @@ anyway at some time to get the loop run faster. Here is our first Cython version
Note the second line: We have to tell Cython that profiling should be enabled. Note the second line: We have to tell Cython that profiling should be enabled.
This makes the Cython code slightly slower, but without this we would not get This makes the Cython code slightly slower, but without this we would not get
meaningful output from the cProfile module. The rest of the code is mostly meaningful output from the cProfile module. The rest of the code is mostly
unchanged, I only typed some variables which will likely speed things up a bit. unchanged, I only typed some variables which will likely speed things up a bit.
We also need to modify our profiling script to import the Cython module directly. We also need to modify our profiling script to import the Cython module directly.
Here is the complete version adding the import of the pyximport module:: Here is the complete version adding the import of the pyximport module::
......
...@@ -45,6 +45,6 @@ Python modules. ...@@ -45,6 +45,6 @@ Python modules.
http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
.. [ShedSkin] M. Dufour, J. Coughlan, ShedSkin, .. [ShedSkin] M. Dufour, J. Coughlan, ShedSkin,
http://code.google.com/p/shedskin/ http://code.google.com/p/shedskin/
.. [SWIG] David M. Beazley et al., .. [SWIG] David M. Beazley et al.,
SWIG: An Easy to Use Tool for Integrating Scripting Languages with C and C++, SWIG: An Easy to Use Tool for Integrating Scripting Languages with C and C++,
http://www.swig.org. http://www.swig.org.
...@@ -99,7 +99,7 @@ overheads. Consider this code: ...@@ -99,7 +99,7 @@ overheads. Consider this code:
rect = Rectangle(x0, y0, x1, y1) rect = Rectangle(x0, y0, x1, y1)
return rect.area() return rect.area()
.. note:: .. note::
in earlier versions of Cython, the :keyword:`cpdef` keyword is in earlier versions of Cython, the :keyword:`cpdef` keyword is
``rdef`` - but has the same effect). ``rdef`` - but has the same effect).
...@@ -116,13 +116,13 @@ storing a Rectangle object, then invoking the area method will require: ...@@ -116,13 +116,13 @@ storing a Rectangle object, then invoking the area method will require:
* an attribute lookup for the area method * an attribute lookup for the area method
* packing a tuple for arguments and a dict for keywords (both empty in this case) * packing a tuple for arguments and a dict for keywords (both empty in this case)
* using the Python API to call the method * using the Python API to call the method
and within the area method itself: and within the area method itself:
* parsing the tuple and keywords * parsing the tuple and keywords
* executing the calculation code * executing the calculation code
* converting the result to a python object and returning it * converting the result to a python object and returning it
So within Cython, it is possible to achieve massive optimisations by So within Cython, it is possible to achieve massive optimisations by
using strong typing in declaration and casting of variables. For tight loops using strong typing in declaration and casting of variables. For tight loops
......
...@@ -35,7 +35,7 @@ The main difference is that you can use the :keyword:`cdef` statement to define ...@@ -35,7 +35,7 @@ The main difference is that you can use the :keyword:`cdef` statement to define
attributes. The attributes may be Python objects (either generic or of a attributes. The attributes may be Python objects (either generic or of a
particular extension type), or they may be of any C data type. So you can use particular extension type), or they may be of any C data type. So you can use
extension types to wrap arbitrary C data structures and provide a Python-like extension types to wrap arbitrary C data structures and provide a Python-like
interface to them. interface to them.
.. _readonly: .. _readonly:
...@@ -117,35 +117,35 @@ The same consideration applies to local variables, for example,:: ...@@ -117,35 +117,35 @@ The same consideration applies to local variables, for example,::
Type Testing and Casting Type Testing and Casting
------------------------ ------------------------
Suppose I have a method :meth:`quest` which returns an object of type :class:`Shrubbery`. Suppose I have a method :meth:`quest` which returns an object of type :class:`Shrubbery`.
To access it's width I could write:: To access it's width I could write::
cdef Shrubbery sh = quest() cdef Shrubbery sh = quest()
print sh.width print sh.width
which requires the use of a local variable and performs a type test on assignment. which requires the use of a local variable and performs a type test on assignment.
If you *know* the return value of :meth:`quest` will be of type :class:`Shrubbery` If you *know* the return value of :meth:`quest` will be of type :class:`Shrubbery`
you can use a cast to write:: you can use a cast to write::
print (<Shrubbery>quest()).width print (<Shrubbery>quest()).width
This may be dangerous if :meth:`quest()` is not actually a :class:`Shrubbery`, as it This may be dangerous if :meth:`quest()` is not actually a :class:`Shrubbery`, as it
will try to access width as a C struct member which may not exist. At the C level, will try to access width as a C struct member which may not exist. At the C level,
rather than raising an :class:`AttributeError`, either an nonsensical result will be rather than raising an :class:`AttributeError`, either an nonsensical result will be
returned (interpreting whatever data is at that address as an int) or a segfault returned (interpreting whatever data is at that address as an int) or a segfault
may result from trying to access invalid memory. Instead, one can write:: may result from trying to access invalid memory. Instead, one can write::
print (<Shrubbery?>quest()).width print (<Shrubbery?>quest()).width
which performs a type check (possibly raising a :class:`TypeError`) before making the which performs a type check (possibly raising a :class:`TypeError`) before making the
cast and allowing the code to proceed. cast and allowing the code to proceed.
To explicitly test the type of an object, use the :meth:`isinstance` method. By default, To explicitly test the type of an object, use the :meth:`isinstance` method. By default,
in Python, the :meth:`isinstance` method checks the :class:`__class__` attribute of the in Python, the :meth:`isinstance` method checks the :class:`__class__` attribute of the
first argument to determine if it is of the required type. However, this is potentially first argument to determine if it is of the required type. However, this is potentially
unsafe as the :class:`__class__` attribute can be spoofed or changed, but the C structure unsafe as the :class:`__class__` attribute can be spoofed or changed, but the C structure
of an extension type must be correct to access its :keyword:`cdef` attributes and call its :keyword:`cdef` methods. Cython detects if the second argument is a known extension of an extension type must be correct to access its :keyword:`cdef` attributes and call its :keyword:`cdef` methods. Cython detects if the second argument is a known extension
type and does a type check instead, analogous to Pyrex's :meth:`typecheck`. type and does a type check instead, analogous to Pyrex's :meth:`typecheck`.
The old behavior is always available by passing a tuple as the second parameter:: The old behavior is always available by passing a tuple as the second parameter::
print isinstance(sh, Shrubbery) # Check the type of sh print isinstance(sh, Shrubbery) # Check the type of sh
...@@ -207,7 +207,7 @@ with checking that it has the right type. ...@@ -207,7 +207,7 @@ with checking that it has the right type.
be ``None``. be ``None``.
* When comparing a value with ``None``, keep in mind that, if ``x`` is a Python * When comparing a value with ``None``, keep in mind that, if ``x`` is a Python
object, ``x is None`` and ``x is not None`` are very efficient because they object, ``x is None`` and ``x is not None`` are very efficient because they
translate directly to C pointer comparisons, whereas ``x == None`` and translate directly to C pointer comparisons, whereas ``x == None`` and
``x != None``, or simply using ``x`` as a boolean value (as in ``if x: ...``) ``x != None``, or simply using ``x`` as a boolean value (as in ``if x: ...``)
will invoke Python operations and therefore be much slower. will invoke Python operations and therefore be much slower.
...@@ -260,7 +260,7 @@ There is also a special (deprecated) legacy syntax for defining properties in an ...@@ -260,7 +260,7 @@ There is also a special (deprecated) legacy syntax for defining properties in an
def __del__(self): def __del__(self):
# This is called when the property is deleted. # This is called when the property is deleted.
The :meth:`__get__`, :meth:`__set__` and :meth:`__del__` methods are all The :meth:`__get__`, :meth:`__set__` and :meth:`__del__` methods are all
optional; if they are omitted, an exception will be raised when the optional; if they are omitted, an exception will be raised when the
...@@ -269,7 +269,7 @@ corresponding operation is attempted. ...@@ -269,7 +269,7 @@ corresponding operation is attempted.
Here's a complete example. It defines a property which adds to a list each Here's a complete example. It defines a property which adds to a list each
time it is written to, returns the list when it is read, and empties the list time it is written to, returns the list when it is read, and empties the list
when it is deleted.:: when it is deleted.::
# cheesy.pyx # cheesy.pyx
cdef class CheeseShop: cdef class CheeseShop:
...@@ -494,7 +494,7 @@ object called :attr:`__weakref__`. For example,:: ...@@ -494,7 +494,7 @@ object called :attr:`__weakref__`. For example,::
cdef class ExplodingAnimal: cdef class ExplodingAnimal:
"""This animal will self-destruct when it is """This animal will self-destruct when it is
no longer strongly referenced.""" no longer strongly referenced."""
cdef object __weakref__ cdef object __weakref__
...@@ -546,7 +546,7 @@ can participate in cycles could cause memory leaks :: ...@@ -546,7 +546,7 @@ can participate in cycles could cause memory leaks ::
cdef str name cdef str name
cdef tuple addresses cdef tuple addresses
If you can be sure addresses will contain only references to strings, If you can be sure addresses will contain only references to strings,
the above would be safe, and it may yield a significant speedup, depending on the above would be safe, and it may yield a significant speedup, depending on
your usage pattern. your usage pattern.
...@@ -604,7 +604,7 @@ built-in complex object.:: ...@@ -604,7 +604,7 @@ built-in complex object.::
2. As well as the name of the extension type, the module in which its type 2. As well as the name of the extension type, the module in which its type
object can be found is also specified. See the implicit importing section object can be found is also specified. See the implicit importing section
below. below.
3. When declaring an external extension type, you don't declare any 3. When declaring an external extension type, you don't declare any
methods. Declaration of methods is not required in order to call them, methods. Declaration of methods is not required in order to call them,
...@@ -662,7 +662,7 @@ You can also specify an alternative name under which to import the type using ...@@ -662,7 +662,7 @@ You can also specify an alternative name under which to import the type using
an as clause, for example,:: an as clause, for example,::
cdef extern class My.Nested.Package.Spam as Yummy: cdef extern class My.Nested.Package.Spam as Yummy:
... ...
which corresponds to the implicit import statement:: which corresponds to the implicit import statement::
......
...@@ -52,7 +52,7 @@ C header file, like this:: ...@@ -52,7 +52,7 @@ C header file, like this::
The ``cdef extern`` from clause does three things: The ``cdef extern`` from clause does three things:
1. It directs Cython to place a ``#include`` statement for the named header file in 1. It directs Cython to place a ``#include`` statement for the named header file in
the generated C code. the generated C code.
2. It prevents Cython from generating any C code 2. It prevents Cython from generating any C code
for the declarations found in the associated block. for the declarations found in the associated block.
3. It treats all declarations within the block as though they started with 3. It treats all declarations within the block as though they started with
...@@ -92,8 +92,8 @@ match the C ones, and in some cases they shouldn't or can't. In particular: ...@@ -92,8 +92,8 @@ match the C ones, and in some cases they shouldn't or can't. In particular:
ctypedef int word ctypedef int word
will work okay whatever the actual size of a :c:type:`word` is (provided the header will work okay whatever the actual size of a :c:type:`word` is (provided the header
file defines it correctly). Conversion to and from Python types, if any, will also file defines it correctly). Conversion to and from Python types, if any, will also
be used for this new type. be used for this new type.
#. If the header file uses macros to define constants, translate them into a #. If the header file uses macros to define constants, translate them into a
normal external variable declaration. You can also declare them as an normal external variable declaration. You can also declare them as an
...@@ -118,7 +118,7 @@ A few more tricks and tips: ...@@ -118,7 +118,7 @@ A few more tricks and tips:
pass pass
* If you want to include a system header, put angle brackets inside the quotes:: * If you want to include a system header, put angle brackets inside the quotes::
cdef extern from "<sysheader.h>": cdef extern from "<sysheader.h>":
... ...
...@@ -390,8 +390,8 @@ C code wanting to use these functions or extension types needs to include the ...@@ -390,8 +390,8 @@ C code wanting to use these functions or extension types needs to include the
header and call the :func:`import_modulename` function. The other functions header and call the :func:`import_modulename` function. The other functions
can then be called and the extension types used as usual. can then be called and the extension types used as usual.
If the C code wanting to use these functions is part of more than one shared If the C code wanting to use these functions is part of more than one shared
library or executable, then :func:`import_modulename` function needs to be library or executable, then :func:`import_modulename` function needs to be
called in each of the shared libraries which use these functions. If you called in each of the shared libraries which use these functions. If you
crash with a segmentation fault (SIGSEGV on linux) when calling into one of crash with a segmentation fault (SIGSEGV on linux) when calling into one of
these api calls, this is likely an indication that the shared library which these api calls, this is likely an indication that the shared library which
...@@ -411,7 +411,7 @@ made available when you include :file:`modulename_api.h`.:: ...@@ -411,7 +411,7 @@ made available when you include :file:`modulename_api.h`.::
print "Time travel achieved" print "Time travel achieved"
.. sourcecode:: c .. sourcecode:: c
# marty.c # marty.c
#include "delorean_api.h" #include "delorean_api.h"
...@@ -420,7 +420,7 @@ made available when you include :file:`modulename_api.h`.:: ...@@ -420,7 +420,7 @@ made available when you include :file:`modulename_api.h`.::
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
import_delorean(); import_delorean();
car.speed = atoi(argv[1]); car.speed = atoi(argv[1]);
car.power = atof(argv[2]); car.power = atof(argv[2]);
activate(&car); activate(&car);
} }
......
...@@ -169,7 +169,7 @@ passed in directly using a normal C function call. ...@@ -169,7 +169,7 @@ passed in directly using a normal C function call.
Functions declared using :keyword:`cdef`, like Python functions, will return a :keyword:`False` Functions declared using :keyword:`cdef`, like Python functions, will return a :keyword:`False`
value when execution leaves the function body without an explicit return value. This is in value when execution leaves the function body without an explicit return value. This is in
contrast to C/C++, which leaves the return value undefined. contrast to C/C++, which leaves the return value undefined.
A more complete comparison of the pros and cons of these different method A more complete comparison of the pros and cons of these different method
types can be found at :ref:`early-binding-for-speed`. types can be found at :ref:`early-binding-for-speed`.
......
...@@ -398,10 +398,10 @@ If you pass a non-contiguous buffer, for example ...@@ -398,10 +398,10 @@ If you pass a non-contiguous buffer, for example
you will get a ``ValueError`` at runtime:: you will get a ``ValueError`` at runtime::
/Users/mb312/dev_trees/minimal-cython/mincy.pyx in init mincy (mincy.c:17267)() /Users/mb312/dev_trees/minimal-cython/mincy.pyx in init mincy (mincy.c:17267)()
69 69
70 # But this isn't 70 # But this isn't
---> 71 c_contiguous = np.array(c_contig, order='F') ---> 71 c_contiguous = np.array(c_contig, order='F')
72 72
73 # Show the sum of all the arrays before altering it 73 # Show the sum of all the arrays before altering it
/Users/mb312/dev_trees/minimal-cython/stringsource in View.MemoryView.memoryview_cwrapper (mincy.c:9995)() /Users/mb312/dev_trees/minimal-cython/stringsource in View.MemoryView.memoryview_cwrapper (mincy.c:9995)()
......
...@@ -20,13 +20,13 @@ information on this. ...@@ -20,13 +20,13 @@ information on this.
The style of this tutorial will not fit everybody, so you can also consider: The style of this tutorial will not fit everybody, so you can also consider:
* Robert Bradshaw's `slides on cython for SciPy2008 * Robert Bradshaw's `slides on cython for SciPy2008
<http://wiki.sagemath.org/scipy08?action=AttachFile&do=get&target=scipy-cython.tgz>`_ <http://wiki.sagemath.org/scipy08?action=AttachFile&do=get&target=scipy-cython.tgz>`_
(a higher-level and quicker introduction) (a higher-level and quicker introduction)
* Basic Cython documentation (see `Cython front page <http://cython.org>`_). * Basic Cython documentation (see `Cython front page <http://cython.org>`_).
* ``[:enhancements/buffer:Spec for the efficient indexing]`` * ``[:enhancements/buffer:Spec for the efficient indexing]``
.. Note:: .. Note::
The fast array access documented below is a completely new feature, and The fast array access documented below is a completely new feature, and
there may be bugs waiting to be discovered. It might be a good idea to do there may be bugs waiting to be discovered. It might be a good idea to do
a manual sanity check on the C code Cython generates before using this for a manual sanity check on the C code Cython generates before using this for
...@@ -71,7 +71,7 @@ However there are several options to automate these steps: ...@@ -71,7 +71,7 @@ However there are several options to automate these steps:
excellent support for using Cython and NumPy from an interactive command excellent support for using Cython and NumPy from an interactive command
line (like IPython) or through a notebook interface (like line (like IPython) or through a notebook interface (like
Maple/Mathematica). See `this documentation Maple/Mathematica). See `this documentation
<http://www.sagemath.org/doc/prog/node40.html>`_. <http://www.sagemath.org/doc/prog/node40.html>`_.
2. A version of `pyximport <http://www.prescod.net/pyximport/>`_ is shipped 2. A version of `pyximport <http://www.prescod.net/pyximport/>`_ is shipped
with Cython, so that you can import pyx-files dynamically into Python and with Cython, so that you can import pyx-files dynamically into Python and
have them compiled automatically (See :ref:`pyximport`). have them compiled automatically (See :ref:`pyximport`).
...@@ -79,7 +79,7 @@ However there are several options to automate these steps: ...@@ -79,7 +79,7 @@ However there are several options to automate these steps:
which automate the process, this is the preferred method for full programs. which automate the process, this is the preferred method for full programs.
4. Manual compilation (see below) 4. Manual compilation (see below)
.. Note:: .. Note::
If using another interactive command line environment than SAGE, like If using another interactive command line environment than SAGE, like
IPython or Python itself, it is important that you restart the process IPython or Python itself, it is important that you restart the process
when you recompile the module. It is not enough to issue an "import" when you recompile the module. It is not enough to issue an "import"
...@@ -200,7 +200,7 @@ run a Python session to test both the Python version (imported from ...@@ -200,7 +200,7 @@ run a Python session to test both the Python version (imported from
[2, 2, 2], [2, 2, 2],
[1, 1, 1]]) [1, 1, 1]])
In [4]: import convolve1 In [4]: import convolve1
In [4]: convolve1.naive_convolve(np.array([[1, 1, 1]], dtype=np.int), In [4]: convolve1.naive_convolve(np.array([[1, 1, 1]], dtype=np.int),
... np.array([[1],[2],[1]], dtype=np.int)) ... np.array([[1],[2],[1]], dtype=np.int))
Out [4]: Out [4]:
array([[1, 1, 1], array([[1, 1, 1],
...@@ -347,7 +347,7 @@ Showing the changes needed to produce :file:`convolve3.pyx` only:: ...@@ -347,7 +347,7 @@ Showing the changes needed to produce :file:`convolve3.pyx` only::
def naive_convolve(np.ndarray[DTYPE_t, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g): def naive_convolve(np.ndarray[DTYPE_t, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g):
... ...
cdef np.ndarray[DTYPE_t, ndim=2] h = ... cdef np.ndarray[DTYPE_t, ndim=2] h = ...
Usage: Usage:
.. sourcecode:: ipython .. sourcecode:: ipython
...@@ -381,7 +381,7 @@ The array lookups are still slowed down by two factors: ...@@ -381,7 +381,7 @@ The array lookups are still slowed down by two factors:
@cython.boundscheck(False) # turn off bounds-checking for entire function @cython.boundscheck(False) # turn off bounds-checking for entire function
def naive_convolve(np.ndarray[DTYPE_t, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g): def naive_convolve(np.ndarray[DTYPE_t, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g):
... ...
Now bounds checking is not performed (and, as a side-effect, if you ''do'' Now bounds checking is not performed (and, as a side-effect, if you ''do''
happen to access out of bounds you will in the best case crash your program happen to access out of bounds you will in the best case crash your program
and in the worst case corrupt data). It is possible to switch bounds-checking and in the worst case corrupt data). It is possible to switch bounds-checking
...@@ -477,14 +477,14 @@ or may not happen depending on available developer time and resources for ...@@ -477,14 +477,14 @@ or may not happen depending on available developer time and resources for
Cython. Cython.
1. Support for efficient access to structs/records stored in arrays; currently 1. Support for efficient access to structs/records stored in arrays; currently
only primitive types are allowed. only primitive types are allowed.
2. Support for efficient access to complex floating point types in arrays. The 2. Support for efficient access to complex floating point types in arrays. The
main obstacle here is getting support for efficient complex datatypes in main obstacle here is getting support for efficient complex datatypes in
Cython. Cython.
3. Calling NumPy/SciPy functions currently has a Python call overhead; it 3. Calling NumPy/SciPy functions currently has a Python call overhead; it
would be possible to take a short-cut from Cython directly to C. (This does would be possible to take a short-cut from Cython directly to C. (This does
however require some isolated and incremental changes to those libraries; however require some isolated and incremental changes to those libraries;
mail the Cython mailing list for details). mail the Cython mailing list for details).
4. Efficient code that is generic with respect to the number of dimensions. 4. Efficient code that is generic with respect to the number of dimensions.
This can probably be done today by calling the NumPy C multi-dimensional This can probably be done today by calling the NumPy C multi-dimensional
iterator API directly; however it would be nice to have for-loops over iterator API directly; however it would be nice to have for-loops over
......
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
Differences between Cython and Pyrex Differences between Cython and Pyrex
************************************** **************************************
.. warning:: .. warning::
Both Cython and Pyrex are moving targets. It has come to the point Both Cython and Pyrex are moving targets. It has come to the point
that an explicit list of all the differences between the two that an explicit list of all the differences between the two
projects would be laborious to list and track, but hopefully projects would be laborious to list and track, but hopefully
this high-level list gives an idea of the differences that this high-level list gives an idea of the differences that
are present. It should be noted that both projects make an effort are present. It should be noted that both projects make an effort
at mutual compatibility, but Cython's goal is to be as close to at mutual compatibility, but Cython's goal is to be as close to
and complete as Python as reasonable. and complete as Python as reasonable.
Python 3 Support Python 3 Support
...@@ -75,7 +75,7 @@ Conditional expressions as described in ...@@ -75,7 +75,7 @@ Conditional expressions as described in
http://www.python.org/dev/peps/pep-0308/:: http://www.python.org/dev/peps/pep-0308/::
X if C else Y X if C else Y
Only one of ``X`` and ``Y`` is evaluated (depending on the value of C). Only one of ``X`` and ``Y`` is evaluated (depending on the value of C).
...@@ -89,10 +89,10 @@ keyword passed on to the C compiler. These can be as fast as macros.:: ...@@ -89,10 +89,10 @@ keyword passed on to the C compiler. These can be as fast as macros.::
cdef inline int something_fast(int a, int b): cdef inline int something_fast(int a, int b):
return a*a + b return a*a + b
Note that class-level :keyword:`cdef` functions are handled via a virtual Note that class-level :keyword:`cdef` functions are handled via a virtual
function table, so the compiler won't be able to inline them in almost all function table, so the compiler won't be able to inline them in almost all
cases. cases.
Assignment on declaration (e.g. "cdef int spam = 5") Assignment on declaration (e.g. "cdef int spam = 5")
====================================================== ======================================================
...@@ -103,24 +103,24 @@ In Pyrex, one must write:: ...@@ -103,24 +103,24 @@ In Pyrex, one must write::
i = 2 i = 2
j = 5 j = 5
k = 7 k = 7
Now, with cython, one can write:: Now, with cython, one can write::
cdef int i = 2, j = 5, k = 7 cdef int i = 2, j = 5, k = 7
The expression on the right hand side can be arbitrarily complicated, e.g.:: The expression on the right hand side can be arbitrarily complicated, e.g.::
cdef int n = python_call(foo(x,y), a + b + c) - 32 cdef int n = python_call(foo(x,y), a + b + c) - 32
'by' expression in for loop (e.g. "for i from 0 <= i < 10 by 2") 'by' expression in for loop (e.g. "for i from 0 <= i < 10 by 2")
================================================================== ==================================================================
:: ::
for i from 0 <= i < 10 by 2: for i from 0 <= i < 10 by 2:
print i print i
yields:: yields::
...@@ -207,7 +207,7 @@ method on the class directly, e.g.:: ...@@ -207,7 +207,7 @@ method on the class directly, e.g.::
x.foo() # will check to see if overridden x.foo() # will check to see if overridden
A.foo(x) # will call A's implementation whether overridden or not A.foo(x) # will call A's implementation whether overridden or not
See :ref:`early-binding-for-speed` for explanation and usage tips. See :ref:`early-binding-for-speed` for explanation and usage tips.
.. _automatic-range-conversion: .. _automatic-range-conversion:
...@@ -216,9 +216,9 @@ Automatic range conversion ...@@ -216,9 +216,9 @@ Automatic range conversion
This will convert statements of the form ``for i in range(...)`` to ``for i This will convert statements of the form ``for i in range(...)`` to ``for i
from ...`` when ``i`` is any cdef'd integer type, and the direction (i.e. sign from ...`` when ``i`` is any cdef'd integer type, and the direction (i.e. sign
of step) can be determined. of step) can be determined.
.. warning:: .. warning::
This may change the semantics if the range causes This may change the semantics if the range causes
assignment to ``i`` to overflow. Specifically, if this option is set, an error assignment to ``i`` to overflow. Specifically, if this option is set, an error
...@@ -256,7 +256,7 @@ functions in the ``.pxd`` file by writing ``cdef foo(x=*)``. The number of ...@@ -256,7 +256,7 @@ functions in the ``.pxd`` file by writing ``cdef foo(x=*)``. The number of
arguments may increase on subclassing, but the argument types and order must arguments may increase on subclassing, but the argument types and order must
remain the same. There is a slight performance penalty in some cases when a 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 cdef/cpdef function without any optional is overridden with one that does have
default argument values. default argument values.
For example, one can have the ``.pxd`` file:: For example, one can have the ``.pxd`` file::
...@@ -279,7 +279,7 @@ with corresponding ``.pyx`` file:: ...@@ -279,7 +279,7 @@ with corresponding ``.pyx`` file::
cpdef foo(self, x=True, int k=3) cpdef foo(self, x=True, int k=3)
print "C", x, k print "C", x, k
.. note:: .. note::
this also demonstrates how :keyword:`cpdef` functions can override this also demonstrates how :keyword:`cpdef` functions can override
:keyword:`cdef` functions. :keyword:`cdef` functions.
...@@ -330,13 +330,13 @@ From __future__ directives ...@@ -330,13 +330,13 @@ From __future__ directives
Cython supports several ``from __future__ import ...`` directives, namely Cython supports several ``from __future__ import ...`` directives, namely
``absolute_import``, ``unicode_literals``, ``print_function`` and ``division``. ``absolute_import``, ``unicode_literals``, ``print_function`` and ``division``.
With statements are always enabled. With statements are always enabled.
Pure Python mode Pure Python mode
================ ================
Cython has support for compiling ``.py`` files, and Cython has support for compiling ``.py`` files, and
accepting type annotations using decorators and other accepting type annotations using decorators and other
valid Python syntax. This allows the same source to valid Python syntax. This allows the same source to
be interpreted as straight Python, or compiled for be interpreted as straight Python, or compiled for
optimized results. See :ref:`pure-mode` for more details. optimized results. See :ref:`pure-mode` for more details.
...@@ -24,9 +24,9 @@ statement. ...@@ -24,9 +24,9 @@ statement.
A ``.pxd`` file that consists solely of extern declarations does not need A ``.pxd`` file that consists solely of extern declarations does not need
to correspond to an actual ``.pyx`` file or Python module. This can make it a to correspond to an actual ``.pyx`` file or Python module. This can make it a
convenient place to put common declarations, for example declarations of convenient place to put common declarations, for example declarations of
functions from an :ref:`external library <external-C-code>` that one functions from an :ref:`external library <external-C-code>` that one
wants to use in several modules. wants to use in several modules.
What a Definition File contains What a Definition File contains
...@@ -40,9 +40,9 @@ A definition file can contain: ...@@ -40,9 +40,9 @@ A definition file can contain:
* The definition part of an extension type (see below). * The definition part of an extension type (see below).
It cannot contain the implementations of any C or Python functions, or any It cannot contain the implementations of any C or Python functions, or any
Python class definitions, or any executable statements. It is needed when one Python class definitions, or any executable statements. It is needed when one
wants to access :keyword:`cdef` attributes and methods, or to inherit from wants to access :keyword:`cdef` attributes and methods, or to inherit from
:keyword:`cdef` classes defined in this module. :keyword:`cdef` classes defined in this module.
.. note:: .. note::
...@@ -57,9 +57,9 @@ What an Implementation File contains ...@@ -57,9 +57,9 @@ What an Implementation File contains
An implementation file can contain any kind of Cython statement, although there An implementation file can contain any kind of Cython statement, although there
are some restrictions on the implementation part of an extension type if the are some restrictions on the implementation part of an extension type if the
corresponding definition file also defines that type (see below). corresponding definition file also defines that type (see below).
If one doesn't need to :keyword:`cimport` anything from this module, then this If one doesn't need to :keyword:`cimport` anything from this module, then this
is the only file one needs. is the only file one needs.
.. _cimport: .. _cimport:
...@@ -79,16 +79,16 @@ statement:: ...@@ -79,16 +79,16 @@ statement::
Here is an example. :file:`dishes.pxd` is a definition file which exports a 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 C data type. :file:`restaurant.pyx` is an implementation file which imports and
uses it. uses it.
:file:`dishes.pxd`:: :file:`dishes.pxd`::
cdef enum otherstuff: cdef enum otherstuff:
sausage, eggs, lettuce sausage, eggs, lettuce
cdef struct spamdish: cdef struct spamdish:
int oz_of_spam int oz_of_spam
otherstuff filler otherstuff filler
:file:`restaurant.pyx`:: :file:`restaurant.pyx`::
cimport dishes cimport dishes
...@@ -102,7 +102,7 @@ uses it. ...@@ -102,7 +102,7 @@ uses it.
cdef spamdish d cdef spamdish d
prepare(&d) prepare(&d)
print "%d oz spam, filler no. %d" % (d.oz_of_spam, d.filler) print "%d oz spam, filler no. %d" % (d.oz_of_spam, d.filler)
It is important to understand that the :keyword:`cimport` statement can only 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 be used to import C data types, C functions and variables, and extension
types. It cannot be used to import any Python objects, and (with one types. It cannot be used to import any Python objects, and (with one
...@@ -113,9 +113,9 @@ to include a regular import statement for it as well. ...@@ -113,9 +113,9 @@ to include a regular import statement for it as well.
The exception is that when you use :keyword:`cimport` to import an extension type, its The exception is that when you use :keyword:`cimport` to import an extension type, its
type object is imported at run time and made available by the name under which type object is imported at run time and made available by the name under which
you imported it. Using :keyword:`cimport` to import extension types is covered in more you imported it. Using :keyword:`cimport` to import extension types is covered in more
detail below. detail below.
If a ``.pxd`` file changes, any modules that :keyword:`cimport` from it may need to be If a ``.pxd`` file changes, any modules that :keyword:`cimport` from it may need to be
recompiled. The ``Cython.Build.cythonize`` utility can take care of this for you. recompiled. The ``Cython.Build.cythonize`` utility can take care of this for you.
...@@ -137,7 +137,7 @@ include path (but not ``sys.path``), and if found, it is processed before ...@@ -137,7 +137,7 @@ include path (but not ``sys.path``), and if found, it is processed before
processing the ``.pyx`` file. processing the ``.pyx`` file.
Using cimport to resolve naming conflicts Using cimport to resolve naming conflicts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :keyword:`cimport` mechanism provides a clean and simple way to solve the The :keyword:`cimport` mechanism provides a clean and simple way to solve the
...@@ -146,11 +146,11 @@ name. All you need to do is put the extern C declarations into a ``.pxd`` file ...@@ -146,11 +146,11 @@ name. All you need to do is put the extern C declarations into a ``.pxd`` file
for an imaginary module, and :keyword:`cimport` that module. You can then 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. refer to the C functions by qualifying them with the name of the module.
Here's an example: Here's an example:
:file:`c_lunch.pxd`:: :file:`c_lunch.pxd`::
cdef extern from "lunch.h": cdef extern from "lunch.h":
void eject_tomato(float) void eject_tomato(float)
:file:`lunch.pyx`:: :file:`lunch.pyx`::
...@@ -163,7 +163,7 @@ You don't need any :file:`c_lunch.pyx` file, because the only things defined ...@@ -163,7 +163,7 @@ 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 in :file:`c_lunch.pxd` are extern C entities. There won't be any actual
``c_lunch`` module at run time, but that doesn't matter; the ``c_lunch`` module at run time, but that doesn't matter; the
:file:`c_lunch.pxd` file has done its job of providing an additional namespace :file:`c_lunch.pxd` file has done its job of providing an additional namespace
at compile time. at compile time.
Sharing C Functions Sharing C Functions
...@@ -199,7 +199,7 @@ example: ...@@ -199,7 +199,7 @@ example:
When a module exports a C function in this way, an object appears in the When a module exports a C function in this way, an object appears in the
module dictionary under the function's name. However, you can't make use of module dictionary under the function's name. However, you can't make use of
this object from Python, nor can you use it from Cython using a normal import this object from Python, nor can you use it from Cython using a normal import
statement; you have to use :keyword:`cimport`. statement; you have to use :keyword:`cimport`.
Sharing Extension Types Sharing Extension Types
......
...@@ -44,7 +44,7 @@ would be:: ...@@ -44,7 +44,7 @@ would be::
setup( setup(
ext_modules = cythonize("example.pyx") ext_modules = cythonize("example.pyx")
) )
To understand the :file:`setup.py` more fully look at the official To understand the :file:`setup.py` more fully look at the official
:mod:`distutils` documentation. To compile the extension for use in the :mod:`distutils` documentation. To compile the extension for use in the
......
...@@ -11,22 +11,22 @@ mention. ...@@ -11,22 +11,22 @@ mention.
.. Note: Everything said on this page applies only to extension types, defined .. Note: Everything said on this page applies only to extension types, defined
with the :keyword:`cdef class` statement. It doesn't apply to classes defined with the with the :keyword:`cdef class` statement. It doesn't apply to classes defined with the
Python :keyword:`class` statement, where the normal Python rules apply. Python :keyword:`class` statement, where the normal Python rules apply.
Declaration Declaration
------------ ------------
Special methods of extension types must be declared with :keyword:`def`, not Special methods of extension types must be declared with :keyword:`def`, not
:keyword:`cdef`. This does not impact their performance--Python uses different :keyword:`cdef`. This does not impact their performance--Python uses different
calling conventions to invoke these special methods. calling conventions to invoke these special methods.
Docstrings Docstrings
----------- -----------
Currently, docstrings are not fully supported in some special methods of extension Currently, docstrings are not fully supported in some special methods of extension
types. You can place a docstring in the source to serve as a comment, but it types. You can place a docstring in the source to serve as a comment, but it
won't show up in the corresponding :attr:`__doc__` attribute at run time. (This won't show up in the corresponding :attr:`__doc__` attribute at run time. (This
seems to be is a Python limitation -- there's nowhere in the `PyTypeObject` seems to be is a Python limitation -- there's nowhere in the `PyTypeObject`
data structure to put such docstrings.) data structure to put such docstrings.)
Initialisation methods: :meth:`__cinit__` and :meth:`__init__` Initialisation methods: :meth:`__cinit__` and :meth:`__init__`
--------------------------------------------------------------- ---------------------------------------------------------------
...@@ -36,7 +36,7 @@ The :meth:`__cinit__` method is where you should perform basic C-level ...@@ -36,7 +36,7 @@ The :meth:`__cinit__` method is where you should perform basic C-level
initialisation of the object, including allocation of any C data structures initialisation of the object, including allocation of any C data structures
that your object will own. You need to be careful what you do in the that your object will own. You need to be careful what you do in the
:meth:`__cinit__` method, because the object may not yet be fully valid Python :meth:`__cinit__` method, because the object may not yet be fully valid Python
object when it is called. Therefore, you should be careful invoking any Python object when it is called. Therefore, you should be careful invoking any Python
operations which might touch the object; in particular, its methods. operations which might touch the object; in particular, its methods.
By the time your :meth:`__cinit__` method is called, memory has been allocated for the By the time your :meth:`__cinit__` method is called, memory has been allocated for the
...@@ -67,15 +67,15 @@ ignore extra arguments. Otherwise, any Python subclass which has an ...@@ -67,15 +67,15 @@ ignore extra arguments. Otherwise, any Python subclass which has an
:meth:`__init__` with a different signature will have to override :meth:`__init__` with a different signature will have to override
:meth:`__new__` [#]_ as well as :meth:`__init__`, which the writer of a Python :meth:`__new__` [#]_ as well as :meth:`__init__`, which the writer of a Python
class wouldn't expect to have to do. Alternatively, as a convenience, if you declare class wouldn't expect to have to do. Alternatively, as a convenience, if you declare
your :meth:`__cinit__`` method to take no arguments (other than self) it your :meth:`__cinit__`` method to take no arguments (other than self) it
will simply ignore any extra arguments passed to the constructor without will simply ignore any extra arguments passed to the constructor without
complaining about the signature mismatch. complaining about the signature mismatch.
.. Note: Older Cython files may use :meth:`__new__` rather than :meth:`__cinit__`. The two are synonyms. .. Note: Older Cython files may use :meth:`__new__` rather than :meth:`__cinit__`. The two are synonyms.
The name change from :meth:`__new__` to :meth:`__cinit__` was to avoid The name change from :meth:`__new__` to :meth:`__cinit__` was to avoid
confusion with Python :meth:`__new__` (which is an entirely different confusion with Python :meth:`__new__` (which is an entirely different
concept) and eventually the use of :meth:`__new__` in Cython will be concept) and eventually the use of :meth:`__new__` in Cython will be
disallowed to pave the way for supporting Python-style :meth:`__new__` disallowed to pave the way for supporting Python-style :meth:`__new__`
.. [#] http://docs.python.org/reference/datamodel.html#object.__new__ .. [#] http://docs.python.org/reference/datamodel.html#object.__new__
...@@ -84,8 +84,8 @@ Finalization method: :meth:`__dealloc__` ...@@ -84,8 +84,8 @@ Finalization method: :meth:`__dealloc__`
The counterpart to the :meth:`__cinit__` method is the :meth:`__dealloc__` The counterpart to the :meth:`__cinit__` method is the :meth:`__dealloc__`
method, which should perform the inverse of the :meth:`__cinit__` method. Any method, which should perform the inverse of the :meth:`__cinit__` method. Any
C data that you explicitly allocated (e.g. via malloc) in your C data that you explicitly allocated (e.g. via malloc) in your
:meth:`__cinit__` method should be freed in your :meth:`__dealloc__` method. :meth:`__cinit__` method should be freed in your :meth:`__dealloc__` method.
You need to be careful what you do in a :meth:`__dealloc__` method. By the time your You need to be careful what you do in a :meth:`__dealloc__` method. By the time your
:meth:`__dealloc__` method is called, the object may already have been partially :meth:`__dealloc__` method is called, the object may already have been partially
...@@ -97,7 +97,7 @@ deallocating C data. ...@@ -97,7 +97,7 @@ deallocating C data.
You don't need to worry about deallocating Python attributes of your object, You don't need to worry about deallocating Python attributes of your object,
because that will be done for you by Cython after your :meth:`__dealloc__` method because that will be done for you by Cython after your :meth:`__dealloc__` method
returns. returns.
When subclassing extension types, be aware that the :meth:`__dealloc__` method When subclassing extension types, be aware that the :meth:`__dealloc__` method
of the superclass will always be called, even if it is overridden. This is in of the superclass will always be called, even if it is overridden. This is in
...@@ -116,8 +116,8 @@ operation, the same method of the second operand is called, with the operands ...@@ -116,8 +116,8 @@ operation, the same method of the second operand is called, with the operands
in the same order. in the same order.
This means that you can't rely on the first parameter of these methods being This means that you can't rely on the first parameter of these methods being
"self" or being the right type, and you should test the types of both operands "self" or being the right type, and you should test the types of both operands
before deciding what to do. If you can't handle the combination of types you've before deciding what to do. If you can't handle the combination of types you've
been given, you should return `NotImplemented`. been given, you should return `NotImplemented`.
This also applies to the in-place arithmetic method :meth:`__ipow__`. It doesn't apply This also applies to the in-place arithmetic method :meth:`__ipow__`. It doesn't apply
...@@ -131,17 +131,17 @@ There are no separate methods for the individual rich comparison operations ...@@ -131,17 +131,17 @@ There are no separate methods for the individual rich comparison operations
(:meth:`__eq__`, :meth:`__le__`, etc.) Instead there is a single method (:meth:`__eq__`, :meth:`__le__`, etc.) Instead there is a single method
:meth:`__richcmp__` which takes an integer indicating which operation is to be :meth:`__richcmp__` which takes an integer indicating which operation is to be
performed, as follows: performed, as follows:
+-----+-----+ +-----+-----+
| < | 0 | | < | 0 |
+-----+-----+ +-----+-----+
| == | 2 | | == | 2 |
+-----+-----+ +-----+-----+
| > | 4 | | > | 4 |
+-----+-----+ +-----+-----+
| <= | 1 | | <= | 1 |
+-----+-----+ +-----+-----+
| != | 3 | | != | 3 |
+-----+-----+ +-----+-----+
| >= | 5 | | >= | 5 |
+-----+-----+ +-----+-----+
...@@ -164,7 +164,7 @@ with no type specified in the table are generic Python objects. ...@@ -164,7 +164,7 @@ with no type specified in the table are generic Python objects.
You don't have to declare your method as taking these parameter types. If you You don't have to declare your method as taking these parameter types. If you
declare different types, conversions will be performed as necessary. declare different types, conversions will be performed as necessary.
General General
^^^^^^^ ^^^^^^^
...@@ -335,7 +335,7 @@ Buffer interface [:PEP:`3118`] (no Python equivalents - see note 1) ...@@ -335,7 +335,7 @@ Buffer interface [:PEP:`3118`] (no Python equivalents - see note 1)
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description | | Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+ +=======================+=======================================+=============+=====================================================+
| __getbuffer__ | self, Py_buffer `*view`, int flags | | | | __getbuffer__ | self, Py_buffer `*view`, int flags | | |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __releasebuffer__ | self, Py_buffer `*view` | | | | __releasebuffer__ | self, Py_buffer `*view` | | |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
...@@ -346,7 +346,7 @@ Buffer interface [legacy] (no Python equivalents - see note 1) ...@@ -346,7 +346,7 @@ Buffer interface [legacy] (no Python equivalents - see note 1)
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| Name | Parameters | Return type | Description | | Name | Parameters | Return type | Description |
+=======================+=======================================+=============+=====================================================+ +=======================+=======================================+=============+=====================================================+
| __getreadbuffer__ | self, Py_ssize_t i, void `**p` | | | | __getreadbuffer__ | self, Py_ssize_t i, void `**p` | | |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
| __getwritebuffer__ | self, Py_ssize_t i, void `**p` | | | | __getwritebuffer__ | self, Py_ssize_t i, void `**p` | | |
+-----------------------+---------------------------------------+-------------+-----------------------------------------------------+ +-----------------------+---------------------------------------+-------------+-----------------------------------------------------+
......
== Pyximport == == Pyximport ==
Download: pyx-import-1.0.tar.gz Download: pyx-import-1.0.tar.gz
<http://www.prescod.net/pyximport/pyximport-1.0.tar.gz> <http://www.prescod.net/pyximport/pyximport-1.0.tar.gz>
...@@ -31,7 +31,7 @@ python -c "import foo" ...@@ -31,7 +31,7 @@ python -c "import foo"
See help(pyximport.install) to learn its options for controlling the See help(pyximport.install) to learn its options for controlling the
default behavior of "import" and "reload". default behavior of "import" and "reload".
== Dependency Handling == == Dependency Handling ==
In Pyximport 1.1 it is possible to declare that your module depends on In Pyximport 1.1 it is possible to declare that your module depends on
multiple files, (likely ".h" and ".pxd" files). If your Pyrex module is multiple files, (likely ".h" and ".pxd" files). If your Pyrex module is
...@@ -46,7 +46,7 @@ modification time of your ".pyx" source file. Future versions may do ...@@ -46,7 +46,7 @@ modification time of your ".pyx" source file. Future versions may do
something more sophisticated like informing distutils of the something more sophisticated like informing distutils of the
dependencies directly. dependencies directly.
== Limitations == == Limitations ==
Pyximport does not give you any control over how your Pyrex file is Pyximport does not give you any control over how your Pyrex file is
compiled. Usually the defaults are fine. You might run into problems if compiled. Usually the defaults are fine. You might run into problems if
...@@ -59,7 +59,7 @@ something went wrong and why. And if nothing went wrong it will give you ...@@ -59,7 +59,7 @@ something went wrong and why. And if nothing went wrong it will give you
the warm fuzzy that pyximport really did rebuild your module as it was the warm fuzzy that pyximport really did rebuild your module as it was
supposed to. supposed to.
== For further thought and discussion == == For further thought and discussion ==
"setup.py install" does not modify sitecustomize.py for you. Should it? "setup.py install" does not modify sitecustomize.py for you. Should it?
Modifying Python's "standard interpreter" behaviour may be more than Modifying Python's "standard interpreter" behaviour may be more than
......
""" """
Import hooks; when installed with the install() function, these hooks Import hooks; when installed with the install() function, these hooks
allow importing .pyx files as if they were Python modules. allow importing .pyx files as if they were Python modules.
If you want the hook installed every time you run Python If you want the hook installed every time you run Python
you can add it to your Python version by adding these lines to you can add it to your Python version by adding these lines to
sitecustomize.py (which you can create from scratch in site-packages sitecustomize.py (which you can create from scratch in site-packages
if it doesn't exist there or somewhere else on your python path):: if it doesn't exist there or somewhere else on your python path)::
import pyximport import pyximport
...@@ -79,8 +79,8 @@ def _info(message, *args): ...@@ -79,8 +79,8 @@ def _info(message, *args):
# Performance problem: for every PYX file that is imported, we will # Performance problem: for every PYX file that is imported, we will
# invoke the whole distutils infrastructure even if the module is # invoke the whole distutils infrastructure even if the module is
# already built. It might be more efficient to only do it when the # already built. It might be more efficient to only do it when the
# mod time of the .pyx is newer than the mod time of the .so but # mod time of the .pyx is newer than the mod time of the .so but
# the question is how to get distutils to tell me the name of the .so # the question is how to get distutils to tell me the name of the .so
# before it builds it. Maybe it is easy...but maybe the peformance # before it builds it. Maybe it is easy...but maybe the peformance
...@@ -94,7 +94,7 @@ def get_distutils_extension(modname, pyxfilename, language_level=None): ...@@ -94,7 +94,7 @@ def get_distutils_extension(modname, pyxfilename, language_level=None):
# import hashlib # import hashlib
# except ImportError: # except ImportError:
# import md5 as hashlib # import md5 as hashlib
# extra = "_" + hashlib.md5(open(pyxfilename).read()).hexdigest() # extra = "_" + hashlib.md5(open(pyxfilename).read()).hexdigest()
# modname = modname + extra # modname = modname + extra
extension_mod,setup_args = handle_special_build(modname, pyxfilename) extension_mod,setup_args = handle_special_build(modname, pyxfilename)
if not extension_mod: if not extension_mod:
...@@ -113,7 +113,7 @@ def handle_special_build(modname, pyxfilename): ...@@ -113,7 +113,7 @@ def handle_special_build(modname, pyxfilename):
special_build = os.path.splitext(pyxfilename)[0] + PYXBLD_EXT special_build = os.path.splitext(pyxfilename)[0] + PYXBLD_EXT
ext = None ext = None
setup_args={} setup_args={}
if os.path.exists(special_build): if os.path.exists(special_build):
# globls = {} # globls = {}
# locs = {} # locs = {}
# execfile(special_build, globls, locs) # execfile(special_build, globls, locs)
...@@ -126,11 +126,11 @@ def handle_special_build(modname, pyxfilename): ...@@ -126,11 +126,11 @@ def handle_special_build(modname, pyxfilename):
make_setup_args = getattr(mod, 'make_setup_args',None) make_setup_args = getattr(mod, 'make_setup_args',None)
if make_setup_args: if make_setup_args:
setup_args = make_setup_args() setup_args = make_setup_args()
assert isinstance(setup_args,dict), ("make_setup_args in %s did not return a dict" assert isinstance(setup_args,dict), ("make_setup_args in %s did not return a dict"
% special_build) % special_build)
assert set or setup_args, ("neither make_ext nor make_setup_args %s" assert set or setup_args, ("neither make_ext nor make_setup_args %s"
% special_build) % special_build)
ext.sources = [os.path.join(os.path.dirname(special_build), source) ext.sources = [os.path.join(os.path.dirname(special_build), source)
for source in ext.sources] for source in ext.sources]
return ext, setup_args return ext, setup_args
...@@ -142,7 +142,7 @@ def handle_dependencies(pyxfilename): ...@@ -142,7 +142,7 @@ def handle_dependencies(pyxfilename):
# by default let distutils decide whether to rebuild on its own # by default let distutils decide whether to rebuild on its own
# (it has a better idea of what the output file will be) # (it has a better idea of what the output file will be)
# but we know more about dependencies so force a rebuild if # but we know more about dependencies so force a rebuild if
# some of the dependencies are newer than the pyxfile. # some of the dependencies are newer than the pyxfile.
if os.path.exists(dependfile): if os.path.exists(dependfile):
depends = open(dependfile).readlines() depends = open(dependfile).readlines()
...@@ -153,7 +153,7 @@ def handle_dependencies(pyxfilename): ...@@ -153,7 +153,7 @@ def handle_dependencies(pyxfilename):
files = [dependfile] files = [dependfile]
for depend in depends: for depend in depends:
fullpath = os.path.join(os.path.dirname(dependfile), fullpath = os.path.join(os.path.dirname(dependfile),
depend) depend)
files.extend(glob.glob(fullpath)) files.extend(glob.glob(fullpath))
# only for unit testing to see we did the right thing # only for unit testing to see we did the right thing
...@@ -191,7 +191,7 @@ def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False, language_l ...@@ -191,7 +191,7 @@ def build_module(name, pyxfilename, pyxbuild_dir=None, inplace=False, language_l
inplace=inplace, inplace=inplace,
reload_support=pyxargs.reload_support) reload_support=pyxargs.reload_support)
assert os.path.exists(so_path), "Cannot find: %s" % so_path assert os.path.exists(so_path), "Cannot find: %s" % so_path
junkpath = os.path.join(os.path.dirname(so_path), name+"_*") #very dangerous with --inplace ? yes, indeed, trying to eat my files ;) junkpath = os.path.join(os.path.dirname(so_path), name+"_*") #very dangerous with --inplace ? yes, indeed, trying to eat my files ;)
junkstuff = glob.glob(junkpath) junkstuff = glob.glob(junkpath)
for path in junkstuff: for path in junkstuff:
...@@ -249,7 +249,7 @@ class PyxImporter(object): ...@@ -249,7 +249,7 @@ class PyxImporter(object):
def find_module(self, fullname, package_path=None): def find_module(self, fullname, package_path=None):
if fullname in sys.modules and not pyxargs.reload_support: if fullname in sys.modules and not pyxargs.reload_support:
return None # only here when reload() return None # only here when reload()
try: try:
fp, pathname, (ext,mode,ty) = imp.find_module(fullname,package_path) fp, pathname, (ext,mode,ty) = imp.find_module(fullname,package_path)
if fp: fp.close() # Python should offer a Default-Loader to avoid this double find/open! if fp: fp.close() # Python should offer a Default-Loader to avoid this double find/open!
...@@ -520,7 +520,7 @@ def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True, ...@@ -520,7 +520,7 @@ def install(pyximport=True, pyimport=False, build_dir=None, build_in_temp=True,
setup_args = {} setup_args = {}
if not build_dir: if not build_dir:
build_dir = os.path.join(os.path.expanduser('~'), '.pyxbld') build_dir = os.path.join(os.path.expanduser('~'), '.pyxbld')
global pyxargs global pyxargs
pyxargs = PyxArgs() #$pycheck_no pyxargs = PyxArgs() #$pycheck_no
pyxargs.build_dir = build_dir pyxargs.build_dir = build_dir
......
...@@ -46,7 +46,7 @@ def test(): ...@@ -46,7 +46,7 @@ def test():
build_file.write(""" build_file.write("""
from distutils.extension import Extension from distutils.extension import Extension
def make_ext(name, filename): def make_ext(name, filename):
return Extension(name=name, sources=[filename]) return Extension(name=name, sources=[filename])
""") """)
build_file.close() build_file.close()
......
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