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
This diff is collapsed.
This diff is collapsed.
/* 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>
......
This diff is collapsed.
...@@ -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
......
This diff is collapsed.
...@@ -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)
......
This diff is collapsed.
...@@ -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