Commit 0532e356 authored by Robert Bradshaw's avatar Robert Bradshaw

Merge branch 'master' into ctuple

Conflicts:
	Cython/Compiler/PyrexTypes.py
	Cython/Utility/TypeConversion.c
	tests/run/arrayassign.pyx
parents ed84c09d 611f4187
...@@ -49,3 +49,6 @@ c1a18ab6b0808e87f68d2f9d914c01934510aef5 0.18b1 ...@@ -49,3 +49,6 @@ c1a18ab6b0808e87f68d2f9d914c01934510aef5 0.18b1
52beb5b16df5b8a92bb6c8c47faf42370d73cb0f 0.19b2 52beb5b16df5b8a92bb6c8c47faf42370d73cb0f 0.19b2
4818f5b68eb4b4ea6ad7e415f6672b491e2461bc 0.19rc1 4818f5b68eb4b4ea6ad7e415f6672b491e2461bc 0.19rc1
48407fa3f3c9da84ab3dc103a6a2b1ca4c1beb2a 0.19 48407fa3f3c9da84ab3dc103a6a2b1ca4c1beb2a 0.19
58fc9a3feb83f571623a492256885d21945decb4 0.21.1
58fc9a3feb83f571623a492256885d21945decb4 0.21.1
d05a4acd45fca9bdc12cef82890ca569fbaae1a5 0.21.1
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
Cython Changelog Cython Changelog
================ ================
Latest Latest changes
====== ==============
Features added Features added
-------------- --------------
...@@ -11,12 +11,31 @@ Features added ...@@ -11,12 +11,31 @@ Features added
* C functions can coerce to Python functions, which allows passing them * C functions can coerce to Python functions, which allows passing them
around as callable objects. around as callable objects.
* New ``cythonize`` option ``-a`` to generate the annotated HTML source view. * C arrays can be assigned by value and auto-coerce from Python iterables
and to Python lists (and tuples).
* Extern C functions can now be declared as cpdef to export them to * Extern C functions can now be declared as cpdef to export them to
the module's Python namespace. Extern C functions in pxd files export the module's Python namespace. Extern C functions in pxd files export
their values to their own module, iff it exists. their values to their own module, iff it exists.
Bugs fixed
----------
* Mismatching 'except' declarations on signatures in .pxd and .pyx files failed
to produce a compile error.
Other changes
-------------
0.21.1 (2014-10-18)
===================
Features added
--------------
* New ``cythonize`` option ``-a`` to generate the annotated HTML source view.
* Missing C-API declarations in ``cpython.unicode`` were added. * Missing C-API declarations in ``cpython.unicode`` were added.
* Passing ``language='c++'`` into cythonize() globally enables C++ mode for * Passing ``language='c++'`` into cythonize() globally enables C++ mode for
...@@ -35,9 +54,6 @@ Features added ...@@ -35,9 +54,6 @@ Features added
Bugs fixed Bugs fixed
---------- ----------
* Mismatching 'except' declarations on signatures in .pxd and .pyx files failed
to produce a compile error.
* Reference leak for non-simple Python expressions in boolean and/or expressions. * Reference leak for non-simple Python expressions in boolean and/or expressions.
* To fix a name collision and to reflect availability on host platforms, * To fix a name collision and to reflect availability on host platforms,
...@@ -55,6 +71,8 @@ Bugs fixed ...@@ -55,6 +71,8 @@ Bugs fixed
if the already created module was used later on (e.g. through a if the already created module was used later on (e.g. through a
stale reference in sys.modules or elsewhere). stale reference in sys.modules or elsewhere).
* ``cythonize.py`` script was not installed on MS-Windows.
Other changes Other changes
------------- -------------
......
...@@ -966,14 +966,15 @@ class GlobalState(object): ...@@ -966,14 +966,15 @@ class GlobalState(object):
w.putln("") w.putln("")
w.putln("static void __Pyx_CleanupGlobals(void) {") w.putln("static void __Pyx_CleanupGlobals(void) {")
# code = self.parts['utility_code_proto']
# utility_code_def code.putln("")
# code.putln("/* --- Runtime support code (head) --- */")
code = self.parts['utility_code_def'] code = self.parts['utility_code_def']
if self.emit_linenums: if self.emit_linenums:
code.write('\n#line 1 "cython_utility"\n') code.write('\n#line 1 "cython_utility"\n')
code.putln("") code.putln("")
code.putln("/* Runtime support code */") code.putln("/* --- Runtime support code --- */")
def finalize_main_c_code(self): def finalize_main_c_code(self):
self.close_global_decls() self.close_global_decls()
......
This diff is collapsed.
...@@ -1312,10 +1312,9 @@ class CVarDefNode(StatNode): ...@@ -1312,10 +1312,9 @@ class CVarDefNode(StatNode):
return return
if type.is_cfunction: if type.is_cfunction:
self.entry = dest_scope.declare_cfunction(name, type, declarator.pos, self.entry = dest_scope.declare_cfunction(name, type, declarator.pos,
cname = cname, visibility = self.visibility, in_pxd = self.in_pxd, cname=cname, visibility=self.visibility, in_pxd=self.in_pxd,
api = self.api, modifiers = self.modifiers) api=self.api, modifiers=self.modifiers, overridable=self.overridable)
if self.entry is not None: if self.entry is not None:
self.entry.is_overridable = self.overridable
self.entry.directive_locals = copy.copy(self.directive_locals) self.entry.directive_locals = copy.copy(self.directive_locals)
if 'staticmethod' in env.directives: if 'staticmethod' in env.directives:
type.is_static_method = True type.is_static_method = True
...@@ -2274,8 +2273,9 @@ class CFuncDefNode(FuncDefNode): ...@@ -2274,8 +2273,9 @@ class CFuncDefNode(FuncDefNode):
type.is_static_method = self.is_static_method type.is_static_method = self.is_static_method
self.entry = env.declare_cfunction( self.entry = env.declare_cfunction(
name, type, self.pos, name, type, self.pos,
cname = cname, visibility = self.visibility, api = self.api, cname=cname, visibility=self.visibility, api=self.api,
defining = self.body is not None, modifiers = self.modifiers) defining=self.body is not None, modifiers=self.modifiers,
overridable=self.overridable)
self.entry.inline_func_in_pxd = self.inline_in_pxd self.entry.inline_func_in_pxd = self.inline_in_pxd
self.return_type = type.return_type self.return_type = type.return_type
if self.return_type.is_array and self.visibility != 'extern': if self.return_type.is_array and self.visibility != 'extern':
...@@ -4776,14 +4776,20 @@ class SingleAssignmentNode(AssignmentNode): ...@@ -4776,14 +4776,20 @@ class SingleAssignmentNode(AssignmentNode):
self.lhs.memslice_broadcast = True self.lhs.memslice_broadcast = True
self.rhs.memslice_broadcast = True self.rhs.memslice_broadcast = True
is_index_node = isinstance(self.lhs, ExprNodes.IndexNode) if (self.lhs.is_subscript and not self.rhs.type.is_memoryviewslice and
if (is_index_node and not self.rhs.type.is_memoryviewslice and
(self.lhs.memslice_slice or self.lhs.is_memslice_copy) and (self.lhs.memslice_slice or self.lhs.is_memslice_copy) and
(self.lhs.type.dtype.assignable_from(self.rhs.type) or (self.lhs.type.dtype.assignable_from(self.rhs.type) or
self.rhs.type.is_pyobject)): self.rhs.type.is_pyobject)):
# scalar slice assignment # scalar slice assignment
self.lhs.is_memslice_scalar_assignment = True self.lhs.is_memslice_scalar_assignment = True
dtype = self.lhs.type.dtype dtype = self.lhs.type.dtype
elif self.lhs.type.is_array:
if not isinstance(self.lhs, ExprNodes.SliceIndexNode):
# cannot assign to C array, only to its full slice
self.lhs = ExprNodes.SliceIndexNode(
self.lhs.pos, base=self.lhs, start=None, stop=None)
self.lhs = self.lhs.analyse_target_types(env)
dtype = self.lhs.type
else: else:
dtype = self.lhs.type dtype = self.lhs.type
......
This diff is collapsed.
...@@ -684,8 +684,8 @@ class Scope(object): ...@@ -684,8 +684,8 @@ class Scope(object):
self.pyfunc_entries.append(entry) self.pyfunc_entries.append(entry)
def declare_cfunction(self, name, type, pos, def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', api = 0, in_pxd = 0, cname=None, visibility='private', api=0, in_pxd=0,
defining = 0, modifiers = (), utility_code = None): defining=0, modifiers=(), utility_code=None, overridable=False):
# Add an entry for a C function. # Add an entry for a C function.
if not cname: if not cname:
if visibility != 'private' or api: if visibility != 'private' or api:
...@@ -696,6 +696,9 @@ class Scope(object): ...@@ -696,6 +696,9 @@ class Scope(object):
if entry: if entry:
if visibility != 'private' and visibility != entry.visibility: if visibility != 'private' and visibility != entry.visibility:
warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1) warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
if overridable != entry.is_overridable:
warning(pos, "Function '%s' previously declared as '%s'" % (
name, 'cpdef' if overridable else 'cdef'), 1)
if not entry.type.same_as(type): if not entry.type.same_as(type):
if visibility == 'extern' and entry.visibility == 'extern': if visibility == 'extern' and entry.visibility == 'extern':
can_override = False can_override = False
...@@ -721,6 +724,7 @@ class Scope(object): ...@@ -721,6 +724,7 @@ class Scope(object):
else: else:
entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers) entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
entry.func_cname = cname entry.func_cname = cname
entry.is_overridable = overridable
if in_pxd and visibility != 'extern': if in_pxd and visibility != 'extern':
entry.defined_in_pxd = 1 entry.defined_in_pxd = 1
if api: if api:
...@@ -734,6 +738,13 @@ class Scope(object): ...@@ -734,6 +738,13 @@ class Scope(object):
if utility_code: if utility_code:
assert not entry.utility_code, "duplicate utility code definition in entry %s (%s)" % (name, cname) assert not entry.utility_code, "duplicate utility code definition in entry %s (%s)" % (name, cname)
entry.utility_code = utility_code entry.utility_code = utility_code
if overridable:
# names of cpdef functions can be used as variables and can be assigned to
var_entry = Entry(name, cname, py_object_type) # FIXME: cname?
var_entry.is_variable = 1
var_entry.is_pyglobal = 1
var_entry.scope = entry.scope
entry.as_variable = var_entry
type.entry = entry type.entry = entry
return entry return entry
...@@ -892,13 +903,12 @@ class BuiltinScope(Scope): ...@@ -892,13 +903,12 @@ class BuiltinScope(Scope):
else: else:
warning(pos, "undeclared name not builtin: %s" % name, 2) warning(pos, "undeclared name not builtin: %s" % name, 2)
def declare_builtin_cfunction(self, name, type, cname, python_equiv = None, def declare_builtin_cfunction(self, name, type, cname, python_equiv=None, utility_code=None):
utility_code = None):
# If python_equiv == "*", the Python equivalent has the same name # If python_equiv == "*", the Python equivalent has the same name
# as the entry, otherwise it has the name specified by python_equiv. # as the entry, otherwise it has the name specified by python_equiv.
name = EncodedString(name) name = EncodedString(name)
entry = self.declare_cfunction(name, type, None, cname, visibility='extern', entry = self.declare_cfunction(name, type, None, cname, visibility='extern',
utility_code = utility_code) utility_code=utility_code)
if python_equiv: if python_equiv:
if python_equiv == "*": if python_equiv == "*":
python_equiv = name python_equiv = name
...@@ -1225,8 +1235,8 @@ class ModuleScope(Scope): ...@@ -1225,8 +1235,8 @@ class ModuleScope(Scope):
return entry return entry
def declare_cfunction(self, name, type, pos, def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', api = 0, in_pxd = 0, cname=None, visibility='private', api=0, in_pxd=0,
defining = 0, modifiers = (), utility_code = None): defining=0, modifiers=(), utility_code=None, overridable=False):
# Add an entry for a C function. # Add an entry for a C function.
if not cname: if not cname:
if visibility == 'extern' or (visibility == 'public' and defining): if visibility == 'extern' or (visibility == 'public' and defining):
...@@ -1243,8 +1253,9 @@ class ModuleScope(Scope): ...@@ -1243,8 +1253,9 @@ class ModuleScope(Scope):
entry.func_cname = cname entry.func_cname = cname
entry = Scope.declare_cfunction( entry = Scope.declare_cfunction(
self, name, type, pos, self, name, type, pos,
cname = cname, visibility = visibility, api = api, in_pxd = in_pxd, cname=cname, visibility=visibility, api=api, in_pxd=in_pxd,
defining = defining, modifiers = modifiers, utility_code = utility_code) defining=defining, modifiers=modifiers, utility_code=utility_code,
overridable=overridable)
return entry return entry
def declare_global(self, name, pos): def declare_global(self, name, pos):
...@@ -1683,8 +1694,10 @@ class StructOrUnionScope(Scope): ...@@ -1683,8 +1694,10 @@ class StructOrUnionScope(Scope):
return entry return entry
def declare_cfunction(self, name, type, pos, def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', api = 0, in_pxd = 0, cname=None, visibility='private', api=0, in_pxd=0,
defining = 0, modifiers = ()): # currently no utility code ... defining=0, modifiers=(), overridable=False): # currently no utility code ...
if overridable:
error(pos, "C struct/union member cannot be declared 'cpdef'")
return self.declare_var(name, type, pos, return self.declare_var(name, type, pos,
cname=cname, visibility=visibility) cname=cname, visibility=visibility)
...@@ -1953,8 +1966,8 @@ class CClassScope(ClassScope): ...@@ -1953,8 +1966,8 @@ class CClassScope(ClassScope):
return entry return entry
def declare_cfunction(self, name, type, pos, def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', api = 0, in_pxd = 0, cname=None, visibility='private', api=0, in_pxd=0,
defining = 0, modifiers = (), utility_code = None): defining=0, modifiers=(), utility_code=None, overridable=False):
if get_special_method_signature(name) and not self.parent_type.is_builtin_type: if get_special_method_signature(name) and not self.parent_type.is_builtin_type:
error(pos, "Special methods must be declared with 'def', not 'cdef'") error(pos, "Special methods must be declared with 'def', not 'cdef'")
args = type.args args = type.args
...@@ -1989,8 +2002,7 @@ class CClassScope(ClassScope): ...@@ -1989,8 +2002,7 @@ class CClassScope(ClassScope):
error(pos, error(pos,
"C method '%s' not previously declared in definition part of" "C method '%s' not previously declared in definition part of"
" extension type" % name) " extension type" % name)
entry = self.add_cfunction(name, type, pos, cname, entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
visibility, modifiers)
if defining: if defining:
entry.func_cname = self.mangle(Naming.func_prefix, name) entry.func_cname = self.mangle(Naming.func_prefix, name)
entry.utility_code = utility_code entry.utility_code = utility_code
...@@ -2020,7 +2032,7 @@ class CClassScope(ClassScope): ...@@ -2020,7 +2032,7 @@ class CClassScope(ClassScope):
# equivalent that must be accessible to support bound methods # equivalent that must be accessible to support bound methods
name = EncodedString(name) name = EncodedString(name)
entry = self.declare_cfunction(name, type, None, cname, visibility='extern', entry = self.declare_cfunction(name, type, None, cname, visibility='extern',
utility_code = utility_code) utility_code=utility_code)
var_entry = Entry(name, name, py_object_type) var_entry = Entry(name, name, py_object_type)
var_entry.is_variable = 1 var_entry.is_variable = 1
var_entry.is_builtin = 1 var_entry.is_builtin = 1
...@@ -2127,40 +2139,10 @@ class CppClassScope(Scope): ...@@ -2127,40 +2139,10 @@ class CppClassScope(Scope):
"C++ class member cannot be a Python object") "C++ class member cannot be a Python object")
return entry return entry
def check_base_default_constructor(self, pos):
# Look for default constructors in all base classes.
if self.default_constructor is None:
entry = self.lookup(self.name)
if not entry.type.base_classes:
self.default_constructor = True
return
for base_class in entry.type.base_classes:
if base_class is PyrexTypes.error_type:
continue
temp_entry = base_class.scope.lookup_here("<init>")
found = False
if temp_entry is None:
continue
for alternative in temp_entry.all_alternatives():
type = alternative.type
if type.is_ptr:
type = type.base_type
if not type.args:
found = True
break
if not found:
self.default_constructor = temp_entry.scope.name
error(pos, "no matching function for call to " \
"%s::%s()" % (temp_entry.scope.name, temp_entry.scope.name))
elif not self.default_constructor:
error(pos, "no matching function for call to %s::%s()" %
(self.default_constructor, self.default_constructor))
def declare_cfunction(self, name, type, pos, def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'extern', api = 0, in_pxd = 0, cname=None, visibility='extern', api=0, in_pxd=0,
defining = 0, modifiers = (), utility_code = None): defining=0, modifiers=(), utility_code=None, overridable=False):
if name in (self.name.split('::')[-1], '__init__') and cname is None: if name in (self.name.split('::')[-1], '__init__') and cname is None:
self.check_base_default_constructor(pos)
cname = self.type.cname cname = self.type.cname
name = '<init>' name = '<init>'
type.return_type = PyrexTypes.InvisibleVoidType() type.return_type = PyrexTypes.InvisibleVoidType()
...@@ -2197,9 +2179,9 @@ class CppClassScope(Scope): ...@@ -2197,9 +2179,9 @@ class CppClassScope(Scope):
for base_entry in base_scope.cfunc_entries: for base_entry in base_scope.cfunc_entries:
entry = self.declare_cfunction(base_entry.name, base_entry.type, entry = self.declare_cfunction(base_entry.name, base_entry.type,
base_entry.pos, base_entry.cname, base_entry.pos, base_entry.cname,
base_entry.visibility, 0, base_entry.visibility, api=0,
modifiers = base_entry.func_modifiers, modifiers=base_entry.func_modifiers,
utility_code = base_entry.utility_code) utility_code=base_entry.utility_code)
entry.is_inherited = 1 entry.is_inherited = 1
def specialize(self, values, type_entry): def specialize(self, values, type_entry):
...@@ -2218,7 +2200,7 @@ class CppClassScope(Scope): ...@@ -2218,7 +2200,7 @@ class CppClassScope(Scope):
e.type.specialize(values), e.type.specialize(values),
e.pos, e.pos,
e.cname, e.cname,
utility_code = e.utility_code) utility_code=e.utility_code)
else: else:
scope.declare_var(entry.name, scope.declare_var(entry.name,
entry.type.specialize(values), entry.type.specialize(values),
......
...@@ -94,7 +94,10 @@ class CythonUtilityCode(Code.UtilityCodeBase): ...@@ -94,7 +94,10 @@ class CythonUtilityCode(Code.UtilityCodeBase):
return False return False
def _equality_params(self): def _equality_params(self):
return self.impl, self.outer_module_scope, self.compiler_directives outer_scope = self.outer_module_scope
while isinstance(outer_scope, NonManglingModuleScope):
outer_scope = outer_scope.outer_scope
return self.impl, outer_scope, self.compiler_directives
def __hash__(self): def __hash__(self):
return hash(self.impl) return hash(self.impl)
......
...@@ -35,50 +35,39 @@ def test_gdb(): ...@@ -35,50 +35,39 @@ def test_gdb():
if have_gdb is not None: if have_gdb is not None:
return have_gdb return have_gdb
have_gdb = False
try: try:
p = subprocess.Popen(['gdb', '-v'], stdout=subprocess.PIPE) p = subprocess.Popen(['gdb', '-nx', '--version'], stdout=subprocess.PIPE)
have_gdb = True
except OSError: except OSError:
# gdb was not installed # gdb not found
have_gdb = False gdb_version = None
else: else:
gdb_version = p.stdout.read().decode('ascii', 'ignore') stdout, _ = p.communicate()
p.wait()
p.stdout.close()
if have_gdb:
# Based on Lib/test/test_gdb.py # Based on Lib/test/test_gdb.py
regex = "^GNU gdb [^\d]*(\d+)\.(\d+)" regex = "GNU gdb [^\d]*(\d+)\.(\d+)"
gdb_version_number = list(map(int, re.search(regex, gdb_version).groups())) gdb_version = re.match(regex, stdout.decode('ascii', 'ignore'))
if gdb_version:
gdb_version_number = list(map(int, gdb_version.groups()))
if gdb_version_number >= [7, 2]: if gdb_version_number >= [7, 2]:
python_version_script = tempfile.NamedTemporaryFile(mode='w+') have_gdb = True
try: with tempfile.NamedTemporaryFile(mode='w+') as python_version_script:
python_version_script.write( python_version_script.write(
'python import sys; print("%s %s" % sys.version_info[:2])') 'python import sys; print("%s %s" % sys.version_info[:2])')
python_version_script.flush() python_version_script.flush()
p = subprocess.Popen(['gdb', '-batch', '-x', python_version_script.name], p = subprocess.Popen(['gdb', '-batch', '-x', python_version_script.name],
stdout=subprocess.PIPE) stdout=subprocess.PIPE)
stdout, _ = p.communicate()
try: try:
python_version = p.stdout.read().decode('ascii') internal_python_version = list(map(int, stdout.decode('ascii', 'ignore').split()))
p.wait() if internal_python_version < [2, 6]:
finally:
p.stdout.close()
try:
python_version_number = list(map(int, python_version.split()))
except ValueError:
have_gdb = False have_gdb = False
finally: except ValueError:
python_version_script.close()
# Be Python 3 compatible
if (not have_gdb
or gdb_version_number < [7, 2]
or python_version_number < [2, 6]):
warnings.warn(
'Skipping gdb tests, need gdb >= 7.2 with Python >= 2.6')
have_gdb = False have_gdb = False
if not have_gdb:
warnings.warn('Skipping gdb tests, need gdb >= 7.2 with Python >= 2.6')
return have_gdb return have_gdb
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# than the standard C cast operator which can be written "<T>(expression)" in # than the standard C cast operator which can be written "<T>(expression)" in
# Cython. # Cython.
cdef extern from *: cdef extern from * nogil:
cdef T dynamic_cast[T](void *) except + # nullptr may also indicate failure cdef T dynamic_cast[T](void *) except + # nullptr may also indicate failure
cdef T static_cast[T](void *) cdef T static_cast[T](void *)
cdef T reinterpret_cast[T](void *) cdef T reinterpret_cast[T](void *)
......
# cython.* namespace for pure mode. # cython.* namespace for pure mode.
__version__ = "0.21.1pre" __version__ = "0.21.1"
# BEGIN shameless copy from Cython/minivect/minitypes.py # BEGIN shameless copy from Cython/minivect/minitypes.py
...@@ -365,6 +365,15 @@ to_repr = { ...@@ -365,6 +365,15 @@ to_repr = {
gs = globals() gs = globals()
# note: cannot simply name the unicode type here as 2to3 gets in the way and replaces it by str
try:
import __builtin__ as builtins
except ImportError: # Py3
import builtins
gs['unicode'] = typedef(getattr(builtins, 'unicode', str), 'unicode')
del builtins
for name in int_types: for name in int_types:
reprname = to_repr(name, name) reprname = to_repr(name, name)
gs[name] = typedef(py_int, reprname) gs[name] = typedef(py_int, reprname)
......
#################### FromPyStructUtility ####################
cdef extern from *:
ctypedef struct PyTypeObject:
char* tp_name
PyTypeObject *Py_TYPE(obj)
bint PyMapping_Check(obj)
object PyErr_Format(exc, const char *format, ...)
@cname("{{funcname}}")
cdef {{struct_name}} {{funcname}}(obj) except *:
cdef {{struct_name}} result
if not PyMapping_Check(obj):
PyErr_Format(TypeError, b"Expected %.16s, got %.200s", b"a mapping", Py_TYPE(obj).tp_name)
{{for member in var_entries:}}
try:
value = obj['{{member.name}}']
except KeyError:
raise ValueError("No value specified for struct attribute '{{member.name}}'")
result.{{member.cname}} = value
{{endfor}}
return result
#################### cfunc.to_py ####################
@cname("{{cname}}")
cdef object {{cname}}({{return_type.ctype}} (*f)({{ ', '.join(arg.type_cname for arg in args) }}) {{except_clause}}):
def wrap({{ ', '.join('{arg.ctype} {arg.name}'.format(arg=arg) for arg in args) }}):
"""wrap({{', '.join(('{arg.name}: {arg.type_displayname}'.format(arg=arg) if arg.type_displayname else arg.name) for arg in args)}}){{if return_type.type_displayname}} -> {{return_type.type_displayname}}{{endif}}"""
{{'' if return_type.type.is_void else 'return '}}f({{ ', '.join(arg.name for arg in args) }})
return wrap
#################### carray.from_py ####################
cdef extern from *:
object PyErr_Format(exc, const char *format, ...)
@cname("{{cname}}")
cdef int {{cname}}(object o, {{base_type}} *v, Py_ssize_t length) except -1:
cdef Py_ssize_t i = length
try:
i = len(o)
except (TypeError, OverflowError):
pass
if i == length:
for i, item in enumerate(o):
if i >= length:
break
v[i] = item
else:
i += 1 # convert index to length
if i == length:
return 0
PyErr_Format(
IndexError,
("too many values found during array assignment, expected %zd"
if i >= length else
"not enough values found during array assignment, expected %zd, got %zd"),
length, i)
#################### carray.to_py ####################
cdef extern from *:
void Py_INCREF(object o)
tuple PyTuple_New(Py_ssize_t size)
list PyList_New(Py_ssize_t size)
void PyTuple_SET_ITEM(object p, Py_ssize_t pos, object o)
void PyList_SET_ITEM(object p, Py_ssize_t pos, object o)
@cname("{{cname}}")
cdef inline list {{cname}}({{base_type}} *v, Py_ssize_t length):
cdef size_t i
cdef object value
l = PyList_New(length)
for i in range(<size_t>length):
value = v[i]
Py_INCREF(value)
PyList_SET_ITEM(l, i, value)
return l
@cname("{{to_tuple_cname}}")
cdef inline tuple {{to_tuple_cname}}({{base_type}} *v, Py_ssize_t length):
cdef size_t i
cdef object value
t = PyTuple_New(length)
for i in range(<size_t>length):
value = v[i]
Py_INCREF(value)
PyTuple_SET_ITEM(t, i, value)
return t
#################### cfunc.to_py ####################
@cname("{{cname}}")
cdef object {{cname}}({{return_type.ctype}} (*f)({{ ', '.join(arg.type_cname for arg in args) }}) {{except_clause}}):
def wrap({{ ', '.join('{arg.ctype} {arg.name}'.format(arg=arg) for arg in args) }}):
"""wrap({{', '.join(('{arg.name}: {arg.type_displayname}'.format(arg=arg) if arg.type_displayname else arg.name) for arg in args)}}){{if return_type.type_displayname}} -> {{return_type.type_displayname}}{{endif}}"""
{{'' if return_type.type.is_void else 'return '}}f({{ ', '.join(arg.name for arg in args) }})
return wrap
...@@ -587,7 +587,7 @@ static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject ...@@ -587,7 +587,7 @@ static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject
if (size == 0) if (size == 0)
return (*meth)(self, NULL); return (*meth)(self, NULL);
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)", "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)",
f->m_ml->ml_name, size); f->m_ml->ml_name, size);
return NULL; return NULL;
} }
...@@ -598,7 +598,7 @@ static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject ...@@ -598,7 +598,7 @@ static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject
if (size == 1) if (size == 1)
return (*meth)(self, PyTuple_GET_ITEM(arg, 0)); return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)", "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)",
f->m_ml->ml_name, size); f->m_ml->ml_name, size);
return NULL; return NULL;
} }
......
...@@ -215,6 +215,8 @@ static CYTHON_INLINE float __PYX_NAN() { ...@@ -215,6 +215,8 @@ static CYTHON_INLINE float __PYX_NAN() {
} }
#endif #endif
#define __Pyx_void_to_None(void_result) (void_result, Py_INCREF(Py_None), Py_None)
// Work around clang bug http://stackoverflow.com/questions/21847816/c-invoke-nested-template-class-destructor // Work around clang bug http://stackoverflow.com/questions/21847816/c-invoke-nested-template-class-destructor
#ifdef __cplusplus #ifdef __cplusplus
template<typename T> template<typename T>
......
...@@ -32,11 +32,11 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); ...@@ -32,11 +32,11 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
#define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_FromUString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s)
#define __Pyx_PyBytes_FromUString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s)
#define __Pyx_PyByteArray_FromUString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s)
#define __Pyx_PyStr_FromUString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s)
#define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s)
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
...@@ -311,42 +311,6 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { ...@@ -311,42 +311,6 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
} }
/////////////// FromPyStructUtility.proto ///////////////
static {{struct_type_decl}} {{funcname}}(PyObject *);
/////////////// FromPyStructUtility ///////////////
static {{struct_type_decl}} {{funcname}}(PyObject * o) {
{{struct_type_decl}} result;
PyObject *value = NULL;
if (!PyMapping_Check(o)) {
PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "a mapping", Py_TYPE(o)->tp_name);
goto bad;
}
{{for member in var_entries:}}
{{py:attr = "result." + member.cname}}
value = PyObject_GetItem(o, PYIDENT("{{member.name}}"));
if (!value) {
PyErr_Format(PyExc_ValueError, \
"No value specified for struct attribute '%.{{max(200, len(member.name))}}s'", "{{member.name}}");
goto bad;
}
{{attr}} = {{member.type.from_py_function}}(value);
if ({{member.type.error_condition(attr)}})
goto bad;
Py_DECREF(value);
{{endfor}}
return result;
bad:
Py_XDECREF(value);
return result;
}
/////////////// ToPyCTupleUtility.proto /////////////// /////////////// ToPyCTupleUtility.proto ///////////////
static PyObject* {{funcname}}({{struct_type_decl}}); static PyObject* {{funcname}}({{struct_type_decl}});
...@@ -395,6 +359,7 @@ bad: ...@@ -395,6 +359,7 @@ bad:
return result; return result;
} }
/////////////// ObjectAsUCS4.proto /////////////// /////////////// ObjectAsUCS4.proto ///////////////
static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject*); static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject*);
......
...@@ -28,6 +28,7 @@ clean: ...@@ -28,6 +28,7 @@ clean:
@rm -f core */core @rm -f core */core
@rm -f Cython/Compiler/*.c @rm -f Cython/Compiler/*.c
@rm -f Cython/Plex/*.c @rm -f Cython/Plex/*.c
@rm -f Cython/Tempita/*.c
@rm -f Cython/Runtime/refnanny.c @rm -f Cython/Runtime/refnanny.c
@(cd Demos; $(MAKE) clean) @(cd Demos; $(MAKE) clean)
......
docs/_static/cython-logo-light.png

4.68 KB | W: | H:

docs/_static/cython-logo-light.png

4.08 KB | W: | H:

docs/_static/cython-logo-light.png
docs/_static/cython-logo-light.png
docs/_static/cython-logo-light.png
docs/_static/cython-logo-light.png
  • 2-up
  • Swipe
  • Onion skin
docs/_static/cythonlogo.png

4.52 KB | W: | H:

docs/_static/cythonlogo.png

4.09 KB | W: | H:

docs/_static/cythonlogo.png
docs/_static/cythonlogo.png
docs/_static/cythonlogo.png
docs/_static/cythonlogo.png
  • 2-up
  • Swipe
  • Onion skin
docs/src/quickstart/htmlreport.png

50.4 KB | W: | H:

docs/src/quickstart/htmlreport.png

35.4 KB | W: | H:

docs/src/quickstart/htmlreport.png
docs/src/quickstart/htmlreport.png
docs/src/quickstart/htmlreport.png
docs/src/quickstart/htmlreport.png
  • 2-up
  • Swipe
  • Onion skin
docs/src/quickstart/ipython.png

125 KB | W: | H:

docs/src/quickstart/ipython.png

83.2 KB | W: | H:

docs/src/quickstart/ipython.png
docs/src/quickstart/ipython.png
docs/src/quickstart/ipython.png
docs/src/quickstart/ipython.png
  • 2-up
  • Swipe
  • Onion skin
docs/src/quickstart/sage.png

76.4 KB | W: | H:

docs/src/quickstart/sage.png

56.8 KB | W: | H:

docs/src/quickstart/sage.png
docs/src/quickstart/sage.png
docs/src/quickstart/sage.png
docs/src/quickstart/sage.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -158,7 +158,7 @@ Sharing C Functions ...@@ -158,7 +158,7 @@ Sharing C Functions
C functions defined at the top level of a module can be made available via C functions defined at the top level of a module can be made available via
:keyword:`cimport` by putting headers for them in the ``.pxd`` file, for :keyword:`cimport` by putting headers for them in the ``.pxd`` file, for
example,:: example:
:file:`volume.pxd`:: :file:`volume.pxd`::
......
...@@ -1714,7 +1714,7 @@ def main(): ...@@ -1714,7 +1714,7 @@ def main():
action="store_true", default=False, action="store_true", default=False,
help="only compile pyx to c, do not run C compiler or run the tests") help="only compile pyx to c, do not run C compiler or run the tests")
parser.add_option("--no-refnanny", dest="with_refnanny", parser.add_option("--no-refnanny", dest="with_refnanny",
action="store_false", default=True, action="store_false", default=not IS_PYPY,
help="do not regression test reference counting") help="do not regression test reference counting")
parser.add_option("--no-fork", dest="fork", parser.add_option("--no-fork", dest="fork",
action="store_false", default=True, action="store_false", default=True,
......
# mode: error
ctypedef int[1] int_array
ctypedef int[2] int_array2
cdef int_array x, y
x = y # not an error
cdef int_array *x_ptr = &x
x_ptr[0] = y # not an error
cdef class A:
cdef int_array value
def __init__(self):
self.value = x # not an error
cdef int_array2 z
z = x # error
x = z # error
cdef enum:
SIZE = 2
ctypedef int[SIZE] int_array_dyn
cdef int_array_dyn d
d = z # not an error
_ERRORS = u"""
20:2: Assignment to slice of wrong length, expected 2, got 1
21:2: Assignment to slice of wrong length, expected 1, got 2
"""
...@@ -10,24 +10,7 @@ cdef void foo(obj): ...@@ -10,24 +10,7 @@ cdef void foo(obj):
obj = p2 # error obj = p2 # error
ctypedef int[1] int_array
cdef int_array x, y
x = y # error
cdef int_array *x_ptr = &x
x_ptr[0] = y # error
cdef class A:
cdef int_array value
def __init__(self):
self.value = x # error
_ERRORS = u""" _ERRORS = u"""
17:2: Assignment to non-lvalue 'x'
20:5: Assignment to non-lvalue of type 'int_array'
25:12: Assignment to non-lvalue of type 'int_array'
7:19: Cannot assign type 'char *' to 'int' 7:19: Cannot assign type 'char *' to 'int'
8:20: Cannot convert Python object to 'int *' 8:20: Cannot convert Python object to 'int *'
10:20: Cannot convert 'int *' to Python object 10:20: Cannot convert 'int *' to Python object
......
...@@ -1935,9 +1935,9 @@ def test_borrowed_slice(): ...@@ -1935,9 +1935,9 @@ def test_borrowed_slice():
5 5
5 5
""" """
cdef int i, carray[10] cdef int i
for i in range(10): cdef int[10] carray
carray[i] = i carray[:] = range(10)
_borrowed(carray) _borrowed(carray)
_not_borrowed(carray) _not_borrowed(carray)
_not_borrowed2(carray) _not_borrowed2(carray)
......
# this doesn't work - it would reassign the array address! # mode: run
#
#def test_literal_list(): def test_literal_list():
# cdef int a[5] """
# a = [1,2,3,4,5] >>> test_literal_list()
# return (a[0], a[1], a[2], a[3], a[4]) (1, 2, 3, 4, 5)
"""
cdef int a[5]
a = [1,2,3,4,5]
return (a[0], a[1], a[2], a[3], a[4])
def test_literal_list_slice_all(): def test_literal_list_slice_all():
""" """
...@@ -128,20 +132,6 @@ def test_ptr_literal_list_slice_end(): ...@@ -128,20 +132,6 @@ def test_ptr_literal_list_slice_end():
a[:5] = [1,2,3,4,5] a[:5] = [1,2,3,4,5]
return (a[0], a[1], a[2], a[3], a[4]) return (a[0], a[1], a[2], a[3], a[4])
# tuples aren't supported (yet)
#
#def test_literal_tuple():
# cdef int a[5]
# a = (1,2,3,4,5)
# return (a[0], a[1], a[2], a[3], a[4])
# this would be nice to have:
#
#def test_list(list l):
# cdef int a[5]
# a[:] = l
# return (a[0], a[1], a[2], a[3], a[4])
def test_multiple_from_slice(): def test_multiple_from_slice():
""" """
>>> test_multiple_from_slice() >>> test_multiple_from_slice()
...@@ -159,3 +149,169 @@ def test_slice_from_multiple(): ...@@ -159,3 +149,169 @@ def test_slice_from_multiple():
cdef int *a = [6,5,4,3,2,1] cdef int *a = [6,5,4,3,2,1]
a[1:4] = -1, -2, -3 a[1:4] = -1, -2, -3
return a[0], a[1], a[2], a[3], a[4], a[5] return a[0], a[1], a[2], a[3], a[4], a[5]
def test_literal_tuple():
"""
>>> test_literal_tuple()
(1, 2, 3, 4, 5)
"""
cdef int a[5]
a = (1,2,3,4,5)
return (a[0], a[1], a[2], a[3], a[4])
def test_list(list l):
"""
>>> test_list([1, 2, 3, 4, 5])
(1, 2, 3, 4, 5)
"""
cdef int a[5]
a[:] = l
return (a[0], a[1], a[2], a[3], a[4])
def assign_all_from_pointer():
"""
>>> assign_all_from_pointer()
(1, 2, 3, 4, 5)
"""
cdef int *v = [1, 2, 3, 4, 5]
cdef int[5] a
a = v
return (a[0], a[1], a[2], a[3], a[4])
def assign_full_from_pointer():
"""
>>> assign_full_from_pointer()
(1, 2, 3, 4, 5)
"""
cdef int *v = [1, 2, 3, 4, 5]
cdef int[5] a
a[:] = v
return (a[0], a[1], a[2], a[3], a[4])
def assign_slice_end_from_pointer():
"""
>>> assign_slice_end_from_pointer()
(1, 2, 3, 4, 123)
"""
cdef int *v = [1, 2, 3, 4, 5]
cdef int[5] a
a[4] = 123
a[:4] = v
return (a[0], a[1], a[2], a[3], a[4])
def assign_slice_start_from_pointer():
"""
>>> assign_slice_start_from_pointer()
(123, 234, 1, 2, 3)
"""
cdef int *v = [1, 2, 3, 4, 5]
cdef int[5] a
a[0] = 123
a[1] = 234
a[2:] = v
return (a[0], a[1], a[2], a[3], a[4])
def assign_slice_start_end_from_pointer():
"""
>>> assign_slice_start_end_from_pointer()
(123, 234, 1, 2, 345)
"""
cdef int *v = [1, 2, 3, 4, 5]
cdef int[5] a
a[0] = 123
a[1] = 234
a[4] = 345
a[2:4] = v
return (a[0], a[1], a[2], a[3], a[4])
'''
# FIXME: make this work:
def assign_slice_start_end_from_sliced_pointer():
"""
>>> assign_slice_start_end_from_sliced_pointer()
(123, 234, 3, 4, 345)
"""
cdef int *v = [1, 2, 3, 4, 5]
cdef int[5] a
a[0] = 123
a[1] = 234
a[4] = 345
a[2:4] = v[2:4]
return (a[0], a[1], a[2], a[3], a[4])
def assign_from_longer_array_slice():
"""
>>> assign_from_longer_array_slice()
[3, 4, 5]
"""
cdef int[5] a
cdef int[3] b
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
b[0] = 11
b[1] = 12
b[2] = 13
b = a[2:]
return b
'''
def assign_slice_from_shorter_array():
"""
>>> assign_slice_from_shorter_array()
[1, 11, 12, 13, 5]
"""
cdef int[5] a
cdef int[3] b
a[0] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
b[0] = 11
b[1] = 12
b[2] = 13
a[1:4] = b
return a
cdef enum:
SIZE = 2
ctypedef int[SIZE] int_array_dyn
def assign_ptr_to_unknown_csize():
"""
>>> assign_ptr_to_unknown_csize()
[1, 2]
"""
cdef int* v = [1, 2, 3, 4, 5]
cdef int_array_dyn d
d = v
return d
def assign_to_wrong_csize():
"""
>>> assign_to_wrong_csize()
Traceback (most recent call last):
ValueError: Assignment to slice of wrong length, expected 3, got 2
"""
cdef int_array_dyn d
cdef int v[3]
v[0] = 1
v[1] = 2
v[2] = 3
d = v
return d
def from_int_array():
"""
>>> from_int_array()
[1, 2, 3]
"""
cdef int[3] v
v[0] = 1
v[1] = 2
v[2] = 3
return v
cpdef tuple tuple_from_int_array():
"""
>>> tuple_from_int_array()
(1, 2, 3)
"""
cdef int[3] v
v[0] = 1
v[1] = 2
v[2] = 3
assert isinstance(<tuple>v, tuple)
return v
cdef extern from "stdint.h":
ctypedef unsigned long uint32_t
def from_typedef_int_array():
"""
>>> from_typedef_int_array()
[1, 2, 3]
"""
cdef uint32_t[3] v
v[0] = 1
v[1] = 2
v[2] = 3
return v
cpdef tuple tuple_from_typedef_int_array():
"""
>>> tuple_from_typedef_int_array()
(1, 2, 3)
"""
cdef uint32_t[3] v
v[0] = 1
v[1] = 2
v[2] = 3
return v
def from_int_array_array():
"""
>>> from_int_array_array()
[[11, 12, 13], [21, 22, 23]]
"""
cdef int[2][3] v
v[0][0] = 11
v[0][1] = 12
v[0][2] = 13
v[1][0] = 21
v[1][1] = 22
v[1][2] = 23
return v
ctypedef struct MyStructType:
int x
double y
cdef struct MyStruct:
int x
double y
def from_struct_array():
"""
>>> a, b = from_struct_array()
>>> a['x'], a['y']
(1, 2.0)
>>> b['x'], b['y']
(3, 4.0)
"""
cdef MyStructType[2] v
cdef MyStruct[2] w
v[0] = MyStructType(1, 2)
v[1] = MyStructType(3, 4)
assert isinstance(<tuple>v, tuple)
assert isinstance(v, list)
w[0] = MyStruct(1, 2)
w[1] = MyStruct(3, 4)
assert (<object>w) == v
assert w == (<object>v)
return v
def to_int_array(x):
"""
>>> to_int_array([1, 2, 3])
(1, 2, 3)
>>> to_int_array([1, 2])
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 3, got 2
>>> to_int_array([1, 2, 3, 4])
Traceback (most recent call last):
IndexError: too many values found during array assignment, expected 3
"""
cdef int[3] v = x
return v[0], v[1], v[2]
def to_int_array_array(x):
"""
>>> to_int_array_array([[1, 2, 3], [4, 5, 6]])
(1, 2, 3, 4, 5, 6)
>>> to_int_array_array(iter([[1, 2, 3], [4, 5, 6]]))
(1, 2, 3, 4, 5, 6)
>>> to_int_array_array([[1, 2, 3]])
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 2, got 1
>>> to_int_array_array(iter([[1, 2, 3]]))
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 2, got 1
>>> to_int_array_array([[1, 2, 3], [4, 5]])
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 3, got 2
>>> to_int_array_array(iter([[1, 2, 3], [4, 5]]))
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 3, got 2
>>> to_int_array_array([[1, 2, 3, 4], [5, 6, 7]])
Traceback (most recent call last):
IndexError: too many values found during array assignment, expected 3
>>> to_int_array_array(iter([[1, 2, 3, 4], [5, 6, 7]]))
Traceback (most recent call last):
IndexError: too many values found during array assignment, expected 3
"""
cdef int[2][3] v = x
return v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2]
'''
# FIXME: this isn't currently allowed
cdef enum:
SIZE_A = 2
SIZE_B = 3
def to_int_array_array_enumsize(x):
"""
>>> to_int_array_array([[1, 2, 3], [4, 5, 6]])
(1, 2, 3, 4, 5, 6)
>>> to_int_array_array(iter([[1, 2, 3], [4, 5, 6]]))
(1, 2, 3, 4, 5, 6)
>>> to_int_array([1, 2])
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 3, got 2
>>> to_int_array([1, 2, 3, 4])
Traceback (most recent call last):
IndexError: too many values found during array assignment, expected 3
"""
cdef int[SIZE_A][SIZE_B] v = x
return v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2]
'''
'''
# FIXME: this isn't currently supported
def array_as_argument(int[2] x):
"""
>>> array_as_argument([1, 2])
(1, 2)
"""
return x[0], x[1]
'''
def to_int_array_slice(x):
"""
>>> to_int_array_slice([1, 2, 3])
(1, 2, 3)
>>> to_int_array_slice([1, 2])
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 3, got 2
>>> to_int_array_slice([1, 2, 3, 4])
Traceback (most recent call last):
IndexError: too many values found during array assignment, expected 3
"""
cdef int[3] v
v[:] = x[:3]
assert v[0] == x[0]
assert v[1] == x[1]
assert v[2] == x[2]
v[:3] = [0, 0, 0]
assert v[0] == 0
assert v[1] == 0
assert v[2] == 0
v[:] = x
return v[0], v[1], v[2]
def iterable_to_int_array(x):
"""
>>> iterable_to_int_array(iter([1, 2, 3]))
(1, 2, 3)
>>> iterable_to_int_array(iter([1, 2]))
Traceback (most recent call last):
IndexError: not enough values found during array assignment, expected 3, got 2
>>> iterable_to_int_array(iter([1, 2, 3, 4]))
Traceback (most recent call last):
IndexError: too many values found during array assignment, expected 3
"""
cdef int[3] v
v[:] = x
return v[0], v[1], v[2]
def to_struct_array(x):
"""
>>> a, b = to_struct_array(({'x': 1, 'y': 2}, {'x': 3, 'y': 4}))
>>> a['x'], a['y']
(1, 2.0)
>>> b['x'], b['y']
(3, 4.0)
"""
cdef MyStructType[2] v
v[:] = x
cdef MyStruct[2] w
w[:] = x
assert w[0].x == v[0].x
assert w[0].y == v[0].y
assert w[1].x == v[1].x
assert w[1].y == v[1].y
return v[0], w[1]
def to_struct_array_array(x):
"""
>>> (a1, a2, a3), (b1, b2, b3) = to_struct_array_array([
... ({'x': 11, 'y': 12}, {'x': 13, 'y': 14}, {'x': 15, 'y': 16}),
... ({'x': 21, 'y': 22}, {'x': 23, 'y': 24}, {'x': 25, 'y': 26}),
... ])
>>> a1['x'], a1['y']
(11, 12.0)
>>> b3['x'], b3['y']
(25, 26.0)
"""
cdef MyStructType[2][3] v = x
return v[0], v[1]
cpdef void unraisable():
"""
>>> unraisable()
here
"""
print('here')
raise RuntimeError()
cpdef void raisable() except *:
"""
>>> raisable()
Traceback (most recent call last):
...
RuntimeError
"""
print('here')
raise RuntimeError()
...@@ -14,6 +14,8 @@ Traceback (most recent call last): ...@@ -14,6 +14,8 @@ Traceback (most recent call last):
NameError: name 'log' is not defined NameError: name 'log' is not defined
>>> strchr('abcabc', ord('c')) >>> strchr('abcabc', ord('c'))
'cabc' 'cabc'
>>> strchr(needle=ord('c'), haystack='abcabc')
'cabc'
""" """
cdef extern from "math.h": cdef extern from "math.h":
......
cdef extern from "math.h":
cpdef double pxd_sqrt "sqrt"(double)
"""
>>> pxd_sqrt(9)
3.0
"""
import cython
if not cython.compiled:
from math import sqrt as pxd_sqrt
@cython.test_assert_path_exists('//SimpleCallNode/NameNode[@type.is_pyobject = False]')
def call_pxd_sqrt(x):
"""
>>> call_pxd_sqrt(9)
3.0
"""
return pxd_sqrt(x)
...@@ -7,7 +7,10 @@ cdef extern from "shapes.h" namespace "shapes": ...@@ -7,7 +7,10 @@ cdef extern from "shapes.h" namespace "shapes":
cdef cppclass Shape: cdef cppclass Shape:
float area() float area()
cdef cppclass Circle(Shape): cdef cppclass Ellipse(Shape):
Ellipse(int a, int b) except +
cdef cppclass Circle(Ellipse):
int radius int radius
Circle(int r) except + Circle(int r) except +
......
...@@ -41,10 +41,16 @@ namespace shapes { ...@@ -41,10 +41,16 @@ namespace shapes {
int side; int side;
}; };
class Circle : public Shape { class Ellipse : public Shape {
public: public:
Circle(int radius) { this->radius = radius; } Ellipse(int a, int b) { this->a = a; this->b = b; }
float area() const { return 3.1415926535897931f * radius; } float area() const { return 3.1415926535897931f * a * b; }
int a, b;
};
class Circle : public Ellipse {
public:
Circle(int radius) : Ellipse(radius, radius) { this->radius = radius; }
int radius; int radius;
}; };
......
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