Commit 91d8ecbc authored by Stefan Behnel's avatar Stefan Behnel

merged in latest cython-devel

parents deffc0ad 20de226f
...@@ -93,10 +93,13 @@ class AnnotationCCodeWriter(CCodeWriter): ...@@ -93,10 +93,13 @@ class AnnotationCCodeWriter(CCodeWriter):
body { font-family: courier; font-size: 12; } body { font-family: courier; font-size: 12; }
.code { font-size: 9; color: #444444; display: none; margin-left: 20px; } .code { font-size: 9; color: #444444; display: none; margin-left: 20px; }
.py_api { color: red; } .py_c_api { color: red; }
.pyx_api { color: #FF3000; } .py_macro_api { color: #FF7000; }
.py_macro_api { color: #FF8000; } .pyx_c_api { color: #FF3000; }
.error_goto { color: #FF8000; } .pyx_macro_api { color: #FF7000; }
.refnanny { color: #FFA000; }
.error_goto { color: #FFA000; }
.tag { } .tag { }
...@@ -126,10 +129,12 @@ function toggleDiv(id) { ...@@ -126,10 +129,12 @@ function toggleDiv(id) {
f.write(u'<p>Raw output: <a href="%s">%s</a>\n' % (c_file, c_file)) f.write(u'<p>Raw output: <a href="%s">%s</a>\n' % (c_file, c_file))
k = 0 k = 0
py_c_api = re.compile(u'(Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]+)') py_c_api = re.compile(u'(Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]+)\(')
pyx_api = re.compile(u'(__Pyx[A-Za-z_]+)\(') py_marco_api = re.compile(u'(Py[A-Z][a-z]+_[A-Z][A-Z_]+)\(')
py_marco_api = re.compile(u'(Py[A-Za-z]*_[A-Z][A-Z_]+)') pyx_c_api = re.compile(u'(__Pyx_[A-Z][a-z_][A-Za-z_]+)\(')
pyx_macro_api = re.compile(u'(__Pyx_[A-Z][A-Z_]+)\(')
error_goto = re.compile(ur'((; *if .*)? \{__pyx_filename = .*goto __pyx_L\w+;\})') error_goto = re.compile(ur'((; *if .*)? \{__pyx_filename = .*goto __pyx_L\w+;\})')
refnanny = re.compile(u'(__Pyx_X?(GOT|GIVE)REF|__Pyx_RefNanny[A-Za-z]+)')
for line in lines: for line in lines:
...@@ -139,14 +144,17 @@ function toggleDiv(id) { ...@@ -139,14 +144,17 @@ function toggleDiv(id) {
except KeyError: except KeyError:
code = '' code = ''
code, c_api_calls = py_c_api.subn(ur"<span class='py_api'>\1</span>", code) code, py_c_api_calls = py_c_api.subn(ur"<span class='py_c_api'>\1</span>(", code)
code, pyx_api_calls = pyx_api.subn(ur"<span class='pyx_api'>\1</span>(", code) code, pyx_c_api_calls = pyx_c_api.subn(ur"<span class='pyx_c_api'>\1</span>(", code)
code, macro_api_calls = py_marco_api.subn(ur"<span class='py_macro_api'>\1</span>", code) code, py_macro_api_calls = py_marco_api.subn(ur"<span class='py_macro_api'>\1</span>(", code)
code, pyx_macro_api_calls = pyx_macro_api.subn(ur"<span class='pyx_macro_api'>\1</span>(", code)
code, refnanny_calls = refnanny.subn(ur"<span class='refnanny'>\1</span>", code)
code, error_goto_calls = error_goto.subn(ur"<span class='error_goto'>\1</span>", code) code, error_goto_calls = error_goto.subn(ur"<span class='error_goto'>\1</span>", code)
code = code.replace(u"<span class='error_goto'>;", u";<span class='error_goto'>") code = code.replace(u"<span class='error_goto'>;", u";<span class='error_goto'>")
color = u"FFFF%02x" % int(255/(1+(5*c_api_calls+2*pyx_api_calls+macro_api_calls)/10.0)) score = 5*py_c_api_calls + 2*pyx_c_api_calls + py_macro_api_calls + pyx_macro_api_calls - refnanny_calls
color = u"FFFF%02x" % int(255/(1+score/10.0))
f.write(u"<pre class='line' style='background-color: #%s' onclick='toggleDiv(\"line%s\")'>" % (color, k)) f.write(u"<pre class='line' style='background-color: #%s' onclick='toggleDiv(\"line%s\")'>" % (color, k))
f.write(u" %d: " % k) f.write(u" %d: " % k)
......
...@@ -28,7 +28,7 @@ builtin_function_table = [ ...@@ -28,7 +28,7 @@ builtin_function_table = [
#('hex', "", "", ""), #('hex', "", "", ""),
#('id', "", "", ""), #('id', "", "", ""),
#('input', "", "", ""), #('input', "", "", ""),
('intern', "s", "O", "__Pyx_InternFromString"), ('intern', "O", "O", "__Pyx_Intern"),
('isinstance', "OO", "b", "PyObject_IsInstance"), ('isinstance', "OO", "b", "PyObject_IsInstance"),
('issubclass', "OO", "b", "PyObject_IsSubclass"), ('issubclass', "OO", "b", "PyObject_IsSubclass"),
('iter', "O", "O", "PyObject_GetIter"), ('iter', "O", "O", "PyObject_GetIter"),
...@@ -161,6 +161,9 @@ bad: ...@@ -161,6 +161,9 @@ bad:
pyexec_utility_code = UtilityCode( pyexec_utility_code = UtilityCode(
proto = """ proto = """
#if PY_VERSION_HEX < 0x02040000 #if PY_VERSION_HEX < 0x02040000
#ifndef Py_COMPILE_H
#include "compile.h"
#endif
#ifndef Py_EVAL_H #ifndef Py_EVAL_H
#include "eval.h" #include "eval.h"
#endif #endif
...@@ -237,12 +240,23 @@ bad: ...@@ -237,12 +240,23 @@ bad:
intern_utility_code = UtilityCode( intern_utility_code = UtilityCode(
proto = """ proto = """
#if PY_MAJOR_VERSION >= 3 static PyObject* __Pyx_Intern(PyObject* s); /* proto */
# define __Pyx_InternFromString(s) PyUnicode_InternFromString(s) """,
#else impl = '''
# define __Pyx_InternFromString(s) PyString_InternFromString(s) static PyObject* __Pyx_Intern(PyObject* s) {
#endif if (!(likely(PyString_CheckExact(s)))) {
""") PyErr_Format(PyExc_TypeError, "Expected str, got %s", Py_TYPE(s)->tp_name);
return 0;
}
Py_INCREF(s);
#if PY_MAJOR_VERSION >= 3
PyUnicode_InternInPlace(&s);
#else
PyString_InternInPlace(&s);
#endif
return s;
}
''')
def put_py23_set_init_utility_code(code, pos): def put_py23_set_init_utility_code(code, pos):
code.putln("#if PY_VERSION_HEX < 0x02040000") code.putln("#if PY_VERSION_HEX < 0x02040000")
......
This diff is collapsed.
...@@ -93,6 +93,7 @@ class Context(object): ...@@ -93,6 +93,7 @@ class Context(object):
from AutoDocTransforms import EmbedSignature from AutoDocTransforms import EmbedSignature
from Optimize import FlattenInListTransform, SwitchTransform, IterationTransform from Optimize import FlattenInListTransform, SwitchTransform, IterationTransform
from Optimize import OptimizeBuiltinCalls, ConstantFolding, FinalOptimizePhase from Optimize import OptimizeBuiltinCalls, ConstantFolding, FinalOptimizePhase
from Optimize import DropRefcountingTransform
from Buffer import IntroduceBufferAuxiliaryVars from Buffer import IntroduceBufferAuxiliaryVars
from ModuleNode import check_c_declarations, check_c_declarations_pxd from ModuleNode import check_c_declarations, check_c_declarations_pxd
...@@ -140,6 +141,7 @@ class Context(object): ...@@ -140,6 +141,7 @@ class Context(object):
OptimizeBuiltinCalls(), OptimizeBuiltinCalls(),
IterationTransform(), IterationTransform(),
SwitchTransform(), SwitchTransform(),
DropRefcountingTransform(),
FinalOptimizePhase(self), FinalOptimizePhase(self),
GilCheck(), GilCheck(),
# ClearResultCodes(self), # ClearResultCodes(self),
......
...@@ -515,11 +515,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -515,11 +515,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask") code.putln(" #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask")
code.putln(" #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask") code.putln(" #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask")
code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y)") code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y)")
code.putln(" #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y)")
code.putln("#else") code.putln("#else")
if Future.division in env.context.future_directives: if Future.division in env.context.future_directives:
code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y)") code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y)")
code.putln(" #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y)")
else: else:
code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y)") code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y)")
code.putln(" #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y)")
code.putln(" #define PyBytes_Type PyString_Type") code.putln(" #define PyBytes_Type PyString_Type")
code.putln("#endif") code.putln("#endif")
...@@ -871,7 +874,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -871,7 +874,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if scope.defines_any(["__setitem__", "__delitem__"]): if scope.defines_any(["__setitem__", "__delitem__"]):
self.generate_ass_subscript_function(scope, code) self.generate_ass_subscript_function(scope, code)
if scope.defines_any(["__setslice__", "__delslice__"]): if scope.defines_any(["__setslice__", "__delslice__"]):
warning(self.pos, "__setslice__ and __delslice__ are not supported by Python 3", 1) warning(self.pos, "__setslice__ and __delslice__ are not supported by Python 3, use __setitem__ and __getitem__ instead", 1)
self.generate_ass_slice_function(scope, code) self.generate_ass_slice_function(scope, code)
if scope.defines_any(["__getattr__","__getattribute__"]): if scope.defines_any(["__getattr__","__getattribute__"]):
self.generate_getattro_function(scope, code) self.generate_getattro_function(scope, code)
...@@ -1199,6 +1202,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1199,6 +1202,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# Setting and deleting a slice are both done through # Setting and deleting a slice are both done through
# the ass_slice method, so we dispatch to user's __setslice__ # the ass_slice method, so we dispatch to user's __setslice__
# or __delslice__, or raise an exception. # or __delslice__, or raise an exception.
code.putln("#if PY_MAJOR_VERSION >= 3")
code.putln("#error __setslice__ and __delslice__ not supported in Python 3.")
code.putln("#endif")
base_type = scope.parent_type.base_type base_type = scope.parent_type.base_type
set_entry = scope.lookup_here("__setslice__") set_entry = scope.lookup_here("__setslice__")
del_entry = scope.lookup_here("__delslice__") del_entry = scope.lookup_here("__delslice__")
......
...@@ -546,18 +546,24 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -546,18 +546,24 @@ class CFuncDeclaratorNode(CDeclaratorNode):
else: else:
if self.exception_value: if self.exception_value:
self.exception_value.analyse_const_expression(env) self.exception_value.analyse_const_expression(env)
exc_val = self.exception_value.get_constant_c_result_code()
if self.exception_check == '+': if self.exception_check == '+':
self.exception_value.analyse_types(env)
exc_val_type = self.exception_value.type exc_val_type = self.exception_value.type
if not exc_val_type.is_error and \ if not exc_val_type.is_error and \
not exc_val_type.is_pyobject and \ not exc_val_type.is_pyobject and \
not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0): not (exc_val_type.is_cfunction and not exc_val_type.return_type.is_pyobject and len(exc_val_type.args)==0):
error(self.exception_value.pos, error(self.exception_value.pos,
"Exception value must be a Python exception or cdef function with no arguments.") "Exception value must be a Python exception or cdef function with no arguments.")
exc_val = self.exception_value
else: else:
if not return_type.assignable_from(self.exception_value.type): if self.exception_value.analyse_const_expression(env):
error(self.exception_value.pos, exc_val = self.exception_value.get_constant_c_result_code()
"Exception value incompatible with function return type") if exc_val is None:
raise InternalError("get_constant_c_result_code not implemented for %s" %
self.exception_value.__class__.__name__)
if not return_type.assignable_from(self.exception_value.type):
error(self.exception_value.pos,
"Exception value incompatible with function return type")
exc_check = self.exception_check exc_check = self.exception_check
if return_type.is_array: if return_type.is_array:
error(self.pos, error(self.pos,
...@@ -1013,12 +1019,12 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1013,12 +1019,12 @@ class FuncDefNode(StatNode, BlockNode):
def create_local_scope(self, env): def create_local_scope(self, env):
genv = env genv = env
while env.is_py_class_scope or env.is_c_class_scope: while genv.is_py_class_scope or genv.is_c_class_scope:
env = env.outer_scope genv = env.outer_scope
if self.needs_closure: if self.needs_closure:
lenv = ClosureScope(name = self.entry.name, scope_name = self.entry.cname, outer_scope = genv) lenv = ClosureScope(name = self.entry.name, scope_name = self.entry.cname, outer_scope = genv)
else: else:
lenv = LocalScope(name = self.entry.name, outer_scope = genv) lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
lenv.return_type = self.return_type lenv.return_type = self.return_type
type = self.entry.type type = self.entry.type
if type.is_cfunction: if type.is_cfunction:
...@@ -2797,7 +2803,7 @@ class CClassDefNode(ClassDefNode): ...@@ -2797,7 +2803,7 @@ class CClassDefNode(ClassDefNode):
buffer_defaults = buffer_defaults) buffer_defaults = buffer_defaults)
if home_scope is not env and self.visibility == 'extern': if home_scope is not env and self.visibility == 'extern':
env.add_imported_entry(self.class_name, self.entry, pos) env.add_imported_entry(self.class_name, self.entry, pos)
scope = self.entry.type.scope self.scope = scope = self.entry.type.scope
if scope is not None: if scope is not None:
scope.directives = env.directives scope.directives = env.directives
...@@ -3266,7 +3272,7 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -3266,7 +3272,7 @@ class InPlaceAssignmentNode(AssignmentNode):
"+": "PyNumber_InPlaceAdd", "+": "PyNumber_InPlaceAdd",
"-": "PyNumber_InPlaceSubtract", "-": "PyNumber_InPlaceSubtract",
"*": "PyNumber_InPlaceMultiply", "*": "PyNumber_InPlaceMultiply",
"/": "PyNumber_InPlaceDivide", "/": "__Pyx_PyNumber_InPlaceDivide",
"%": "PyNumber_InPlaceRemainder", "%": "PyNumber_InPlaceRemainder",
"<<": "PyNumber_InPlaceLshift", "<<": "PyNumber_InPlaceLshift",
">>": "PyNumber_InPlaceRshift", ">>": "PyNumber_InPlaceRshift",
......
...@@ -25,6 +25,10 @@ try: ...@@ -25,6 +25,10 @@ try:
except NameError: except NameError:
from sets import Set as set from sets import Set as set
class FakePythonEnv(object):
"A fake environment for creating type test nodes etc."
nogil = False
def unwrap_node(node): def unwrap_node(node):
while isinstance(node, UtilNodes.ResultRefNode): while isinstance(node, UtilNodes.ResultRefNode):
node = node.expression node = node.expression
...@@ -297,11 +301,11 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -297,11 +301,11 @@ class IterationTransform(Visitor.VisitorTransform):
tuple_target = node.target tuple_target = node.target
def coerce_object_to(obj_node, dest_type): def coerce_object_to(obj_node, dest_type):
class FakeEnv(object):
nogil = False
if dest_type.is_pyobject: if dest_type.is_pyobject:
if dest_type.is_extension_type or dest_type.is_builtin_type: if dest_type != obj_node.type:
obj_node = ExprNodes.PyTypeTestNode(obj_node, dest_type, FakeEnv()) if dest_type.is_extension_type or dest_type.is_builtin_type:
obj_node = ExprNodes.PyTypeTestNode(
obj_node, dest_type, FakePythonEnv(), notnone=True)
result = ExprNodes.TypecastNode( result = ExprNodes.TypecastNode(
obj_node.pos, obj_node.pos,
operand = obj_node, operand = obj_node,
...@@ -316,7 +320,7 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -316,7 +320,7 @@ class IterationTransform(Visitor.VisitorTransform):
return temp_result.result() return temp_result.result()
def generate_execution_code(self, code): def generate_execution_code(self, code):
self.generate_result_code(code) self.generate_result_code(code)
return (temp_result, CoercedTempNode(dest_type, obj_node, FakeEnv())) return (temp_result, CoercedTempNode(dest_type, obj_node, FakePythonEnv()))
if isinstance(node.body, Nodes.StatListNode): if isinstance(node.body, Nodes.StatListNode):
body = node.body body = node.body
...@@ -528,39 +532,106 @@ class DropRefcountingTransform(Visitor.VisitorTransform): ...@@ -528,39 +532,106 @@ class DropRefcountingTransform(Visitor.VisitorTransform):
visit_Node = Visitor.VisitorTransform.recurse_to_children visit_Node = Visitor.VisitorTransform.recurse_to_children
def visit_ParallelAssignmentNode(self, node): def visit_ParallelAssignmentNode(self, node):
left, right, temps = [], [], [] left_names, right_names = [], []
left_indices, right_indices = [], []
temps = []
for stat in node.stats: for stat in node.stats:
if isinstance(stat, Nodes.SingleAssignmentNode): if isinstance(stat, Nodes.SingleAssignmentNode):
lhs = unwrap_node(stat.lhs) if not self._extract_operand(stat.lhs, left_names,
if not isinstance(lhs, ExprNodes.NameNode): left_indices, temps):
return node return node
left.append(lhs) if not self._extract_operand(stat.rhs, right_names,
rhs = unwrap_node(stat.rhs) right_indices, temps):
if isinstance(rhs, ExprNodes.CoerceToTempNode):
temps.append(rhs)
rhs = rhs.arg
if not isinstance(rhs, ExprNodes.NameNode):
return node return node
right.append(rhs) elif isinstance(stat, Nodes.CascadedAssignmentNode):
# FIXME
return node
else: else:
return node return node
for name_node in left + right: if left_names or right_names:
if name_node.entry.is_builtin or name_node.entry.is_pyglobal: # lhs/rhs names must be a non-redundant permutation
lnames = [n.name for n in left_names]
rnames = [n.name for n in right_names]
if set(lnames) != set(rnames):
return node
if len(set(lnames)) != len(right_names):
return node return node
left_names = [n.name for n in left] if left_indices or right_indices:
right_names = [n.name for n in right] # base name and index of index nodes must be a
if set(left_names) != set(right_names): # non-redundant permutation
return node lindices = []
if len(set(left_names)) != len(right): for lhs_node in left_indices:
index_id = self._extract_index_id(lhs_node)
if not index_id:
return node
lindices.append(index_id)
rindices = []
for rhs_node in right_indices:
index_id = self._extract_index_id(rhs_node)
if not index_id:
return node
rindices.append(index_id)
if set(lindices) != set(rindices):
return node
if len(set(lindices)) != len(right_indices):
return node
# really supporting IndexNode requires support in
# __Pyx_GetItemInt(), so let's stop short for now
return node return node
for name_node in left + right + temps: temp_args = [t.arg for t in temps]
name_node.use_managed_ref = False for temp in temps:
temp.use_managed_ref = False
for name_node in left_names + right_names:
if name_node not in temp_args:
name_node.use_managed_ref = False
for index_node in left_indices + right_indices:
index_node.use_managed_ref = False
return node return node
def _extract_operand(self, node, names, indices, temps):
node = unwrap_node(node)
if not node.type.is_pyobject:
return False
if isinstance(node, ExprNodes.CoerceToTempNode):
temps.append(node)
node = node.arg
if isinstance(node, ExprNodes.NameNode):
if node.entry.is_builtin or node.entry.is_pyglobal:
return False
names.append(node)
elif isinstance(node, ExprNodes.IndexNode):
if node.base.type != Builtin.list_type:
return False
if not node.index.type.is_int:
return False
if not isinstance(node.base, ExprNodes.NameNode):
return False
indices.append(node)
else:
return False
return True
def _extract_index_id(self, index_node):
base = index_node.base
index = index_node.index
if isinstance(index, ExprNodes.NameNode):
index_val = index.name
elif isinstance(index, ExprNodes.ConstNode):
# FIXME:
return None
else:
return None
return (base.name, index_val)
class OptimizeBuiltinCalls(Visitor.VisitorTransform): class OptimizeBuiltinCalls(Visitor.VisitorTransform):
"""Optimize some common methods calls and instantiation patterns """Optimize some common methods calls and instantiation patterns
...@@ -618,7 +689,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -618,7 +689,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
return function_handler(node, arg_tuple, kwargs) return function_handler(node, arg_tuple, kwargs)
else: else:
return function_handler(node, arg_tuple) return function_handler(node, arg_tuple)
elif isinstance(function, ExprNodes.AttributeNode): elif function.is_attribute:
arg_list = arg_tuple.args arg_list = arg_tuple.args
self_arg = function.obj self_arg = function.obj
obj_type = self_arg.type obj_type = self_arg.type
...@@ -648,6 +719,22 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -648,6 +719,22 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
else: else:
return node return node
def _error_wrong_arg_count(self, function_name, node, args, expected=None):
if not expected: # None or 0
arg_str = ''
elif isinstance(expected, basestring) or expected > 1:
arg_str = '...'
elif expected == 1:
arg_str = 'x'
else:
arg_str = ''
if expected is not None:
expected_str = 'expected %s, ' % expected
else:
expected_str = ''
error(node.pos, "%s(%s) called with wrong number of args, %sfound %d" % (
function_name, arg_str, expected_str, len(args)))
### builtin types ### builtin types
def _handle_general_function_dict(self, node, pos_args, kwargs): def _handle_general_function_dict(self, node, pos_args, kwargs):
...@@ -781,8 +868,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -781,8 +868,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
is_temp = node.is_temp is_temp = node.is_temp
) )
else: else:
error(node.pos, "getattr() called with wrong number of args, " self._error_wrong_arg_count('getattr', node, args, '2 or 3')
"expected 2 or 3, found %d" % len(args))
return node return node
Pyx_Type_func_type = PyrexTypes.CFuncType( Pyx_Type_func_type = PyrexTypes.CFuncType(
...@@ -831,8 +917,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -831,8 +917,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
def _handle_simple_method_list_append(self, node, args, is_unbound_method): def _handle_simple_method_list_append(self, node, args, is_unbound_method):
if len(args) != 2: if len(args) != 2:
error(node.pos, "list.append(x) called with wrong number of args, found %d" % self._error_wrong_arg_count('list.append', node, args, 2)
len(args))
return node return node
return self._substitute_method_call( return self._substitute_method_call(
node, "PyList_Append", self.PyList_Append_func_type, node, "PyList_Append", self.PyList_Append_func_type,
...@@ -853,8 +938,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -853,8 +938,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
def _handle_simple_method_list_reverse(self, node, args, is_unbound_method): def _handle_simple_method_list_reverse(self, node, args, is_unbound_method):
if len(args) != 1: if len(args) != 1:
error(node.pos, "list.reverse(x) called with wrong number of args, found %d" % self._error_wrong_arg_count('list.reverse', node, args, 1)
len(args))
return node return node
return self._substitute_method_call( return self._substitute_method_call(
node, "PyList_Reverse", self.single_param_func_type, node, "PyList_Reverse", self.single_param_func_type,
...@@ -882,8 +966,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -882,8 +966,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
def _handle_simple_method_unicode_encode(self, node, args, is_unbound_method): def _handle_simple_method_unicode_encode(self, node, args, is_unbound_method):
if len(args) < 1 or len(args) > 3: if len(args) < 1 or len(args) > 3:
error(node.pos, "unicode.encode(...) called with wrong number of args, found %d" % self._error_wrong_arg_count('unicode.encode', node, args, '1-3')
len(args))
return node return node
null_node = ExprNodes.NullNode(node.pos) null_node = ExprNodes.NullNode(node.pos)
...@@ -977,7 +1060,6 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -977,7 +1060,6 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
self_arg, "PyExc_AttributeError", self_arg, "PyExc_AttributeError",
"'NoneType' object has no attribute '%s'" % attr_name) "'NoneType' object has no attribute '%s'" % attr_name)
args[0] = self_arg args[0] = self_arg
# FIXME: args[0] may need a runtime None check (ticket #166)
return ExprNodes.PythonCapiCallNode( return ExprNodes.PythonCapiCallNode(
node.pos, name, func_type, node.pos, name, func_type,
args = args, args = args,
......
...@@ -724,6 +724,12 @@ property NAME: ...@@ -724,6 +724,12 @@ property NAME:
self.visitchildren(node) self.visitchildren(node)
return node return node
def visit_ClassDefNode(self, node):
self.env_stack.append(node.scope)
self.visitchildren(node)
self.env_stack.pop()
return node
def visit_FuncDefNode(self, node): def visit_FuncDefNode(self, node):
self.seen_vars_stack.append(set()) self.seen_vars_stack.append(set())
lenv = node.create_local_scope(self.env_stack[-1]) lenv = node.create_local_scope(self.env_stack[-1])
...@@ -1002,6 +1008,7 @@ class TransformBuiltinMethods(EnvTransform): ...@@ -1002,6 +1008,7 @@ class TransformBuiltinMethods(EnvTransform):
return node return node
def visit_AttributeNode(self, node): def visit_AttributeNode(self, node):
self.visitchildren(node)
return self.visit_cython_attribute(node) return self.visit_cython_attribute(node)
def visit_NameNode(self, node): def visit_NameNode(self, node):
...@@ -1023,8 +1030,15 @@ class TransformBuiltinMethods(EnvTransform): ...@@ -1023,8 +1030,15 @@ class TransformBuiltinMethods(EnvTransform):
# locals builtin # locals builtin
if isinstance(node.function, ExprNodes.NameNode): if isinstance(node.function, ExprNodes.NameNode):
if node.function.name == 'locals': if node.function.name == 'locals':
pos = node.pos
lenv = self.env_stack[-1] lenv = self.env_stack[-1]
entry = lenv.lookup_here('locals')
if entry:
# not the builtin 'locals'
return node
if len(node.args) > 0:
error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d" % len(node.args))
return node
pos = node.pos
items = [ExprNodes.DictItemNode(pos, items = [ExprNodes.DictItemNode(pos,
key=ExprNodes.StringNode(pos, value=var), key=ExprNodes.StringNode(pos, value=var),
value=ExprNodes.NameNode(pos, name=var)) for var in lenv.entries] value=ExprNodes.NameNode(pos, name=var)) for var in lenv.entries]
......
...@@ -967,6 +967,8 @@ def flatten_parallel_assignments(input, output): ...@@ -967,6 +967,8 @@ def flatten_parallel_assignments(input, output):
output.append(input) output.append(input)
return return
complete_assignments = []
rhs_size = len(rhs.args) rhs_size = len(rhs.args)
lhs_targets = [ [] for _ in range(rhs_size) ] lhs_targets = [ [] for _ in range(rhs_size) ]
starred_assignments = [] starred_assignments = []
...@@ -974,7 +976,7 @@ def flatten_parallel_assignments(input, output): ...@@ -974,7 +976,7 @@ def flatten_parallel_assignments(input, output):
if not lhs.is_sequence_constructor: if not lhs.is_sequence_constructor:
if lhs.is_starred: if lhs.is_starred:
error(lhs.pos, "starred assignment target must be in a list or tuple") error(lhs.pos, "starred assignment target must be in a list or tuple")
output.append([lhs,rhs]) complete_assignments.append(lhs)
continue continue
lhs_size = len(lhs.args) lhs_size = len(lhs.args)
starred_targets = sum([1 for expr in lhs.args if expr.is_starred]) starred_targets = sum([1 for expr in lhs.args if expr.is_starred])
...@@ -1005,6 +1007,10 @@ def flatten_parallel_assignments(input, output): ...@@ -1005,6 +1007,10 @@ def flatten_parallel_assignments(input, output):
for targets, expr in zip(lhs_targets, lhs.args): for targets, expr in zip(lhs_targets, lhs.args):
targets.append(expr) targets.append(expr)
if complete_assignments:
complete_assignments.append(rhs)
output.append(complete_assignments)
# recursively flatten partial assignments # recursively flatten partial assignments
for cascade, rhs in zip(lhs_targets, rhs.args): for cascade, rhs in zip(lhs_targets, rhs.args):
if cascade: if cascade:
......
...@@ -408,19 +408,24 @@ class BuiltinObjectType(PyObjectType): ...@@ -408,19 +408,24 @@ class BuiltinObjectType(PyObjectType):
def subtype_of(self, type): def subtype_of(self, type):
return type.is_pyobject and self.assignable_from(type) return type.is_pyobject and self.assignable_from(type)
def type_test_code(self, arg): def type_test_code(self, arg, notnone=False):
type_name = self.name type_name = self.name
if type_name == 'str': if type_name == 'str':
check = 'PyString_CheckExact' type_check = 'PyString_CheckExact'
elif type_name == 'set': elif type_name == 'set':
check = 'PyAnySet_CheckExact' type_check = 'PyAnySet_CheckExact'
elif type_name == 'frozenset': elif type_name == 'frozenset':
check = 'PyFrozenSet_CheckExact' type_check = 'PyFrozenSet_CheckExact'
elif type_name == 'bool': elif type_name == 'bool':
check = 'PyBool_Check' type_check = 'PyBool_Check'
else: else:
check = 'Py%s_CheckExact' % type_name.capitalize() type_check = 'Py%s_CheckExact' % type_name.capitalize()
return 'likely(%s(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", Py_TYPE(%s)->tp_name), 0)' % (check, arg, arg, self.name, arg)
check = 'likely(%s(%s))' % (type_check, arg)
if not notnone:
check = check + ('||((%s) == Py_None)' % arg)
error = '(PyErr_Format(PyExc_TypeError, "Expected %s, got %%.200s", Py_TYPE(%s)->tp_name), 0)' % (self.name, arg)
return check + '||' + error
def declaration_code(self, entity_code, def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0): for_display = 0, dll_linkage = None, pyrex = 0):
...@@ -504,9 +509,16 @@ class PyExtensionType(PyObjectType): ...@@ -504,9 +509,16 @@ class PyExtensionType(PyObjectType):
else: else:
return "%s *%s" % (base, entity_code) return "%s *%s" % (base, entity_code)
def type_test_code(self, py_arg): def type_test_code(self, py_arg, notnone=False):
return "__Pyx_TypeTest(%s, %s)" % (py_arg, self.typeptr_cname)
none_check = "((%s) == Py_None)" % py_arg
type_check = "likely(__Pyx_TypeTest(%s, %s))" % (
py_arg, self.typeptr_cname)
if notnone:
return type_check
else:
return "likely(%s || %s)" % (none_check, type_check)
def attributes_known(self): def attributes_known(self):
return self.scope is not None return self.scope is not None
...@@ -609,12 +621,14 @@ static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *); ...@@ -609,12 +621,14 @@ static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
""", """,
impl=""" impl="""
static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) { static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
const %(type)s neg_one = (%(type)s)-1, zero = 0;
const int is_unsigned = neg_one > zero;
if (sizeof(%(type)s) < sizeof(long)) { if (sizeof(%(type)s) < sizeof(long)) {
long val = __Pyx_PyInt_AsLong(x); long val = __Pyx_PyInt_AsLong(x);
if (unlikely(val != (long)(%(type)s)val)) { if (unlikely(val != (long)(%(type)s)val)) {
if (!unlikely(val == -1 && PyErr_Occurred())) { if (!unlikely(val == -1 && PyErr_Occurred())) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
(((%(type)s)-1) > ((%(type)s)0) && unlikely(val < 0)) ? (is_unsigned && unlikely(val < 0)) ?
"can't convert negative value to %(type)s" : "can't convert negative value to %(type)s" :
"value too large to convert to %(type)s"); "value too large to convert to %(type)s");
} }
...@@ -632,10 +646,12 @@ static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *); ...@@ -632,10 +646,12 @@ static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject *);
""", """,
impl=""" impl="""
static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) { static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
const %(type)s neg_one = (%(type)s)-1, zero = 0;
const int is_unsigned = neg_one > zero;
#if PY_VERSION_HEX < 0x03000000 #if PY_VERSION_HEX < 0x03000000
if (likely(PyInt_Check(x))) { if (likely(PyInt_Check(x))) {
long val = PyInt_AS_LONG(x); long val = PyInt_AS_LONG(x);
if (((%(type)s)-1) > ((%(type)s)0) && unlikely(val < 0)) { if (is_unsigned && unlikely(val < 0)) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to %(type)s"); "can't convert negative value to %(type)s");
return (%(type)s)-1; return (%(type)s)-1;
...@@ -644,14 +660,16 @@ static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) { ...@@ -644,14 +660,16 @@ static INLINE %(type)s __Pyx_PyInt_As%(SignWord)s%(TypeName)s(PyObject* x) {
} else } else
#endif #endif
if (likely(PyLong_Check(x))) { if (likely(PyLong_Check(x))) {
if (((%(type)s)-1) > ((%(type)s)0) && unlikely(Py_SIZE(x) < 0)) { if (is_unsigned) {
PyErr_SetString(PyExc_OverflowError, if (unlikely(Py_SIZE(x) < 0)) {
"can't convert negative value to %(type)s"); PyErr_SetString(PyExc_OverflowError,
return (%(type)s)-1; "can't convert negative value to %(type)s");
return (%(type)s)-1;
}
return PyLong_AsUnsigned%(TypeName)s(x);
} else {
return PyLong_As%(TypeName)s(x);
} }
return (((%(type)s)-1) < ((%(type)s)0)) ?
PyLong_As%(TypeName)s(x) :
PyLong_AsUnsigned%(TypeName)s(x);
} else { } else {
%(type)s val; %(type)s val;
PyObject *tmp = __Pyx_PyNumber_Int(x); PyObject *tmp = __Pyx_PyNumber_Int(x);
...@@ -669,35 +687,44 @@ static INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject *); ...@@ -669,35 +687,44 @@ static INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject *);
""", """,
impl=""" impl="""
static INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) { static INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) {
/**/ if (sizeof(%(type)s) == sizeof(char)) const %(type)s neg_one = (%(type)s)-1, zero = 0;
return (((%(type)s)-1) < ((%(type)s)0)) ? const int is_unsigned = neg_one > zero;
(%(type)s)__Pyx_PyInt_AsSignedChar(x) : if (sizeof(%(type)s) == sizeof(char)) {
(%(type)s)__Pyx_PyInt_AsUnsignedChar(x); if (is_unsigned)
else if (sizeof(%(type)s) == sizeof(short)) return (%(type)s)__Pyx_PyInt_AsUnsignedChar(x);
return (((%(type)s)-1) < ((%(type)s)0)) ? else
(%(type)s)__Pyx_PyInt_AsSignedShort(x) : return (%(type)s)__Pyx_PyInt_AsSignedChar(x);
(%(type)s)__Pyx_PyInt_AsUnsignedShort(x); } else if (sizeof(%(type)s) == sizeof(short)) {
else if (sizeof(%(type)s) == sizeof(int)) if (is_unsigned)
return (((%(type)s)-1) < ((%(type)s)0)) ? return (%(type)s)__Pyx_PyInt_AsUnsignedShort(x);
(%(type)s)__Pyx_PyInt_AsSignedInt(x) : else
(%(type)s)__Pyx_PyInt_AsUnsignedInt(x); return (%(type)s)__Pyx_PyInt_AsSignedShort(x);
else if (sizeof(%(type)s) == sizeof(long)) } else if (sizeof(%(type)s) == sizeof(int)) {
return (((%(type)s)-1) < ((%(type)s)0)) ? if (is_unsigned)
(%(type)s)__Pyx_PyInt_AsSignedLong(x) : return (%(type)s)__Pyx_PyInt_AsUnsignedInt(x);
(%(type)s)__Pyx_PyInt_AsUnsignedLong(x); else
else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) return (%(type)s)__Pyx_PyInt_AsSignedInt(x);
return (((%(type)s)-1) < ((%(type)s)0)) ? } else if (sizeof(%(type)s) == sizeof(long)) {
(%(type)s)__Pyx_PyInt_AsSignedLongLong(x) : if (is_unsigned)
(%(type)s)__Pyx_PyInt_AsUnsignedLongLong(x); return (%(type)s)__Pyx_PyInt_AsUnsignedLong(x);
else
return (%(type)s)__Pyx_PyInt_AsSignedLong(x);
} else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) {
if (is_unsigned)
return (%(type)s)__Pyx_PyInt_AsUnsignedLongLong(x);
else
return (%(type)s)__Pyx_PyInt_AsSignedLongLong(x);
#if 0 #if 0
else if (sizeof(%(type)s) > sizeof(short) && } else if (sizeof(%(type)s) > sizeof(short) &&
sizeof(%(type)s) < sizeof(int)) /* __int32 ILP64 ? */ sizeof(%(type)s) < sizeof(int)) { /* __int32 ILP64 ? */
return (((%(type)s)-1) < ((%(type)s)0)) ? if (is_unsigned)
(%(type)s)__Pyx_PyInt_AsSignedInt(x) : return (%(type)s)__Pyx_PyInt_AsUnsignedInt(x);
(%(type)s)__Pyx_PyInt_AsUnsignedInt(x); else
return (%(type)s)__Pyx_PyInt_AsSignedInt(x);
#endif #endif
PyErr_SetString(PyExc_TypeError, "%(TypeName)s"); }
return (%(type)s)-1; PyErr_SetString(PyExc_TypeError, "%(TypeName)s");
return (%(type)s)-1;
} }
""") """)
...@@ -707,16 +734,21 @@ static INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s); ...@@ -707,16 +734,21 @@ static INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s);
""", """,
impl=""" impl="""
static INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) { static INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) {
/**/ if (sizeof(%(type)s) < sizeof(long)) const %(type)s neg_one = (%(type)s)-1, zero = 0;
return PyInt_FromLong((long)val); const int is_unsigned = neg_one > zero;
else if (sizeof(%(type)s) == sizeof(long)) if (sizeof(%(type)s) < sizeof(long)) {
return (((%(type)s)-1) < ((%(type)s)0)) ? return PyInt_FromLong((long)val);
PyInt_FromLong((long)val) : } else if (sizeof(%(type)s) == sizeof(long)) {
PyLong_FromUnsignedLong((unsigned long)val); if (is_unsigned)
else /* (sizeof(%(type)s) > sizeof(long)) */ return PyLong_FromUnsignedLong((unsigned long)val);
return (((%(type)s)-1) < ((%(type)s)0)) ? else
PyLong_FromLongLong((PY_LONG_LONG)val) : return PyInt_FromLong((long)val);
PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val); } else { /* (sizeof(%(type)s) > sizeof(long)) */
if (is_unsigned)
return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val);
else
return PyLong_FromLongLong((PY_LONG_LONG)val);
}
} }
""") """)
...@@ -1282,10 +1314,17 @@ class CFuncType(CType): ...@@ -1282,10 +1314,17 @@ class CFuncType(CType):
arg_reprs = map(repr, self.args) arg_reprs = map(repr, self.args)
if self.has_varargs: if self.has_varargs:
arg_reprs.append("...") arg_reprs.append("...")
return "<CFuncType %s %s[%s]>" % ( if self.exception_value:
except_clause = " %r" % self.exception_value
else:
except_clause = ""
if self.exception_check:
except_clause += "?"
return "<CFuncType %s %s[%s]%s>" % (
repr(self.return_type), repr(self.return_type),
self.calling_convention_prefix(), self.calling_convention_prefix(),
",".join(arg_reprs)) ",".join(arg_reprs),
except_clause)
def calling_convention_prefix(self): def calling_convention_prefix(self):
cc = self.calling_convention cc = self.calling_convention
......
...@@ -1079,8 +1079,10 @@ class ModuleScope(Scope): ...@@ -1079,8 +1079,10 @@ class ModuleScope(Scope):
class LocalScope(Scope): class LocalScope(Scope):
def __init__(self, name, outer_scope): def __init__(self, name, outer_scope, parent_scope = None):
Scope.__init__(self, name, outer_scope, outer_scope) if parent_scope is None:
parent_scope = outer_scope
Scope.__init__(self, name, outer_scope, parent_scope)
def mangle(self, prefix, name): def mangle(self, prefix, name):
return prefix + name return prefix + name
......
...@@ -52,6 +52,33 @@ cdef extern from "numpy/arrayobject.h": ...@@ -52,6 +52,33 @@ cdef extern from "numpy/arrayobject.h":
NPY_NTYPES NPY_NTYPES
NPY_NOTYPE NPY_NOTYPE
NPY_INT8
NPY_INT16
NPY_INT32
NPY_INT64
NPY_INT128
NPY_INT256
NPY_UINT8
NPY_UINT16
NPY_UINT32
NPY_UINT64
NPY_UINT128
NPY_UINT256
NPY_FLOAT16
NPY_FLOAT32
NPY_FLOAT64
NPY_FLOAT80
NPY_FLOAT96
NPY_FLOAT128
NPY_FLOAT256
NPY_COMPLEX32
NPY_COMPLEX64
NPY_COMPLEX128
NPY_COMPLEX160
NPY_COMPLEX192
NPY_COMPLEX256
NPY_COMPLEX512
enum NPY_ORDER: enum NPY_ORDER:
NPY_ANYORDER NPY_ANYORDER
NPY_CORDER NPY_CORDER
...@@ -335,7 +362,7 @@ cdef extern from "numpy/arrayobject.h": ...@@ -335,7 +362,7 @@ cdef extern from "numpy/arrayobject.h":
# Macros from ndarrayobject.h # Macros from ndarrayobject.h
# #
bint PyArray_CHKFLAGS(ndarray m, int flags) bint PyArray_CHKFLAGS(ndarray m, int flags)
bint PyArray_ISISCONTIGUOUS(ndarray m) bint PyArray_ISCONTIGUOUS(ndarray m)
bint PyArray_ISWRITEABLE(ndarray m) bint PyArray_ISWRITEABLE(ndarray m)
bint PyArray_ISALIGNED(ndarray m) bint PyArray_ISALIGNED(ndarray m)
......
...@@ -125,7 +125,6 @@ from python_mem cimport * ...@@ -125,7 +125,6 @@ from python_mem cimport *
from python_tuple cimport * from python_tuple cimport *
from python_list cimport * from python_list cimport *
from python_object cimport * from python_object cimport *
from python_cobject cimport *
from python_sequence cimport * from python_sequence cimport *
from python_mapping cimport * from python_mapping cimport *
from python_iterator cimport * from python_iterator cimport *
...@@ -142,4 +141,18 @@ from python_dict cimport * ...@@ -142,4 +141,18 @@ from python_dict cimport *
from python_instance cimport * from python_instance cimport *
from python_function cimport * from python_function cimport *
from python_method cimport * from python_method cimport *
from python_weakref cimport *
from python_getargs cimport *
# Python <= 2.x
from python_cobject cimport *
# Python >= 2.4
from python_set cimport * from python_set cimport *
# Python >= 2.6
from python_buffer cimport *
from python_bytes cimport *
# Python >= 3.0
from python_pycapsule cimport *
...@@ -79,7 +79,7 @@ cdef extern from "Python.h": ...@@ -79,7 +79,7 @@ cdef extern from "Python.h":
# fastest). If fortran is 'A', then it does not matter and the # fastest). If fortran is 'A', then it does not matter and the
# copy will be made in whatever way is more efficient. # copy will be made in whatever way is more efficient.
int PyObject_CopyData(object dest, object src) int PyObject_CopyData(object dest, object src) except -1
# Copy the data from the src buffer to the buffer of destination # Copy the data from the src buffer to the buffer of destination
bint PyBuffer_IsContiguous(Py_buffer *view, char fort) bint PyBuffer_IsContiguous(Py_buffer *view, char fort)
......
from python_ref cimport PyObject
cdef extern from "Python.h":
ctypedef struct va_list
############################################################################
# 7.3.1 String Objects
############################################################################
# These functions raise TypeError when expecting a string
# parameter and are called with a non-string parameter.
# PyStringObject
# This subtype of PyObject represents a Python bytes object.
# PyTypeObject PyBytes_Type
# This instance of PyTypeObject represents the Python bytes type;
# it is the same object as bytes and types.BytesType in the Python
# layer.
bint PyBytes_Check(object o)
# Return true if the object o is a string object or an instance of
# a subtype of the string type.
bint PyBytes_CheckExact(object o)
# Return true if the object o is a string object, but not an instance of a subtype of the string type.
object PyBytes_FromString(char *v)
# Return value: New reference.
# Return a new string object with the value v on success, and NULL
# on failure. The parameter v must not be NULL; it will not be
# checked.
object PyBytes_FromStringAndSize(char *v, Py_ssize_t len)
# Return value: New reference.
# Return a new string object with the value v and length len on
# success, and NULL on failure. If v is NULL, the contents of the
# string are uninitialized.
object PyBytes_FromFormat(char *format, ...)
# Return value: New reference.
# Take a C printf()-style format string and a variable number of
# arguments, calculate the size of the resulting Python string and
# return a string with the values formatted into it. The variable
# arguments must be C types and must correspond exactly to the
# format characters in the format string. The following format
# characters are allowed:
# Format Characters Type Comment
# %% n/a The literal % character.
# %c int A single character, represented as an C int.
# %d int Exactly equivalent to printf("%d").
# %u unsigned int Exactly equivalent to printf("%u").
# %ld long Exactly equivalent to printf("%ld").
# %lu unsigned long Exactly equivalent to printf("%lu").
# %zd Py_ssize_t Exactly equivalent to printf("%zd").
# %zu size_t Exactly equivalent to printf("%zu").
# %i int Exactly equivalent to printf("%i").
# %x int Exactly equivalent to printf("%x").
# %s char* A null-terminated C character array.
# %p void* The hex representation of a C pointer.
# Mostly equivalent to printf("%p") except that it is guaranteed to
# start with the literal 0x regardless of what the platform's printf
# yields.
# An unrecognized format character causes all the rest of the
# format string to be copied as-is to the result string, and any
# extra arguments discarded.
object PyBytes_FromFormatV(char *format, va_list vargs)
# Return value: New reference.
# Identical to PyBytes_FromFormat() except that it takes exactly two arguments.
Py_ssize_t PyBytes_Size(object string) except -1
# Return the length of the string in string object string.
Py_ssize_t PyBytes_GET_SIZE(object string)
# Macro form of PyBytes_Size() but without error checking.
char* PyBytes_AsString(object string) except NULL
# Return a NUL-terminated representation of the contents of
# string. The pointer refers to the internal buffer of string, not
# a copy. The data must not be modified in any way, unless the
# string was just created using PyBytes_FromStringAndSize(NULL,
# size). It must not be deallocated. If string is a Unicode
# object, this function computes the default encoding of string
# and operates on that. If string is not a string object at all,
# PyBytes_AsString() returns NULL and raises TypeError.
char* PyBytes_AS_STRING(object string)
# Macro form of PyBytes_AsString() but without error
# checking. Only string objects are supported; no Unicode objects
# should be passed.
int PyBytes_AsStringAndSize(object obj, char **buffer, Py_ssize_t *length) except -1
# Return a NULL-terminated representation of the contents of the
# object obj through the output variables buffer and length.
#
# The function accepts both string and Unicode objects as
# input. For Unicode objects it returns the default encoded
# version of the object. If length is NULL, the resulting buffer
# may not contain NUL characters; if it does, the function returns
# -1 and a TypeError is raised.
# The buffer refers to an internal string buffer of obj, not a
# copy. The data must not be modified in any way, unless the
# string was just created using PyBytes_FromStringAndSize(NULL,
# size). It must not be deallocated. If string is a Unicode
# object, this function computes the default encoding of string
# and operates on that. If string is not a string object at all,
# PyBytes_AsStringAndSize() returns -1 and raises TypeError.
void PyBytes_Concat(PyObject **string, object newpart)
# Create a new string object in *string containing the contents of
# newpart appended to string; the caller will own the new
# reference. The reference to the old value of string will be
# stolen. If the new string cannot be created, the old reference
# to string will still be discarded and the value of *string will
# be set to NULL; the appropriate exception will be set.
void PyBytes_ConcatAndDel(PyObject **string, object newpart)
# Create a new string object in *string containing the contents of
# newpart appended to string. This version decrements the
# reference count of newpart.
int _PyBytes_Resize(PyObject **string, Py_ssize_t newsize) except -1
# A way to resize a string object even though it is
# ``immutable''. Only use this to build up a brand new string
# object; don't use this if the string may already be known in
# other parts of the code. It is an error to call this function if
# the refcount on the input string object is not one. Pass the
# address of an existing string object as an lvalue (it may be
# written into), and the new size desired. On success, *string
# holds the resized string object and 0 is returned; the address
# in *string may differ from its input value. If the reallocation
# fails, the original string object at *string is deallocated,
# *string is set to NULL, a memory exception is set, and -1 is
# returned.
object PyBytes_Format(object format, object args)
# Return value: New reference. Return a new string object from
# format and args. Analogous to format % args. The args argument
# must be a tuple.
void PyBytes_InternInPlace(PyObject **string)
# Intern the argument *string in place. The argument must be the
# address of a pointer variable pointing to a Python string
# object. If there is an existing interned string that is the same
# as *string, it sets *string to it (decrementing the reference
# count of the old string object and incrementing the reference
# count of the interned string object), otherwise it leaves
# *string alone and interns it (incrementing its reference
# count). (Clarification: even though there is a lot of talk about
# reference counts, think of this function as
# reference-count-neutral; you own the object after the call if
# and only if you owned it before the call.)
object PyBytes_InternFromString(char *v)
# Return value: New reference.
# A combination of PyBytes_FromString() and
# PyBytes_InternInPlace(), returning either a new string object
# that has been interned, or a new (``owned'') reference to an
# earlier interned string object with the same value.
object PyBytes_Decode(char *s, Py_ssize_t size, char *encoding, char *errors)
# Return value: New reference.
# Create an object by decoding size bytes of the encoded buffer s
# using the codec registered for encoding. encoding and errors
# have the same meaning as the parameters of the same name in the
# unicode() built-in function. The codec to be used is looked up
# using the Python codec registry. Return NULL if an exception was
# raised by the codec.
object PyBytes_AsDecodedObject(object str, char *encoding, char *errors)
# Return value: New reference.
# Decode a string object by passing it to the codec registered for
# encoding and return the result as Python object. encoding and
# errors have the same meaning as the parameters of the same name
# in the string encode() method. The codec to be used is looked up
# using the Python codec registry. Return NULL if an exception was
# raised by the codec.
object PyBytes_Encode(char *s, Py_ssize_t size, char *encoding, char *errors)
# Return value: New reference.
# Encode the char buffer of the given size by passing it to the
# codec registered for encoding and return a Python
# object. encoding and errors have the same meaning as the
# parameters of the same name in the string encode() method. The
# codec to be used is looked up using the Python codec
# registry. Return NULL if an exception was raised by the codec.
object PyBytes_AsEncodedObject(object str, char *encoding, char *errors)
# Return value: New reference.
# Encode a string object using the codec registered for encoding
# and return the result as Python object. encoding and errors have
# the same meaning as the parameters of the same name in the
# string encode() method. The codec to be used is looked up using
# the Python codec registry. Return NULL if an exception was
# raised by the codec.
...@@ -25,13 +25,13 @@ cdef extern from "Python.h": ...@@ -25,13 +25,13 @@ cdef extern from "Python.h":
# be called when the object is reclaimed. The desc argument can be # be called when the object is reclaimed. The desc argument can be
# used to pass extra callback data for the destructor function. # used to pass extra callback data for the destructor function.
void* PyCObject_AsVoidPtr(object self) void* PyCObject_AsVoidPtr(object self) except? NULL
# Return the object void * that the PyCObject self was created with. # Return the object void * that the PyCObject self was created with.
void* PyCObject_GetDesc(object self) void* PyCObject_GetDesc(object self) except? NULL
# Return the description void * that the PyCObject self was created with. # Return the description void * that the PyCObject self was created with.
int PyCObject_SetVoidPtr(object self, void* cobj) int PyCObject_SetVoidPtr(object self, void* cobj) except 0
# Set the void pointer inside self to cobj. The PyCObject must not # Set the void pointer inside self to cobj. The PyCObject must not
# have an associated destructor. Return true on success, false on # have an associated destructor. Return true on success, false on
# failure. # failure.
...@@ -29,11 +29,13 @@ cdef extern from "Python.h": ...@@ -29,11 +29,13 @@ cdef extern from "Python.h":
# Return value: New reference. # Return value: New reference.
# Return a new PyComplexObject object from real and imag. # Return a new PyComplexObject object from real and imag.
double PyComplex_RealAsDouble(object op) double PyComplex_RealAsDouble(object op) except? -1
# Return the real part of op as a C double. # Return the real part of op as a C double.
double PyComplex_ImagAsDouble(object op) double PyComplex_ImagAsDouble(object op) except? -1
# Return the imaginary part of op as a C double. # Return the imaginary part of op as a C double.
Py_complex PyComplex_AsCComplex(object op) Py_complex PyComplex_AsCComplex(object op)
# Return the Py_complex value of the complex number op. # Return the Py_complex value of the complex number op.
#
# Returns (-1+0i) in case of an error
...@@ -95,7 +95,7 @@ cdef extern from "Python.h": ...@@ -95,7 +95,7 @@ cdef extern from "Python.h":
# dictionary p, as in the dictionary method values() (see the # dictionary p, as in the dictionary method values() (see the
# Python Library Reference). # Python Library Reference).
Py_ssize_t PyDict_Size(object p) Py_ssize_t PyDict_Size(object p) except -1
# Return the number of items in the dictionary. This is equivalent # Return the number of items in the dictionary. This is equivalent
# to "len(p)" on a dictionary. # to "len(p)" on a dictionary.
......
...@@ -53,7 +53,7 @@ cdef extern from "Python.h": ...@@ -53,7 +53,7 @@ cdef extern from "Python.h":
# of a class, in the case of a class exception, or it may the a # of a class, in the case of a class exception, or it may the a
# subclass of the expected exception.) # subclass of the expected exception.)
int PyErr_ExceptionMatches(object exc) bint PyErr_ExceptionMatches(object exc)
# Equivalent to "PyErr_GivenExceptionMatches(PyErr_Occurred(), # Equivalent to "PyErr_GivenExceptionMatches(PyErr_Occurred(),
# exc)". This should only be called when an exception is actually # exc)". This should only be called when an exception is actually
# set; a memory access violation will occur if no exception has # set; a memory access violation will occur if no exception has
...@@ -126,7 +126,7 @@ cdef extern from "Python.h": ...@@ -126,7 +126,7 @@ cdef extern from "Python.h":
void PyErr_SetNone(object type) void PyErr_SetNone(object type)
# This is a shorthand for "PyErr_SetObject(type, Py_None)". # This is a shorthand for "PyErr_SetObject(type, Py_None)".
int PyErr_BadArgument() int PyErr_BadArgument() except 0
# This is a shorthand for "PyErr_SetString(PyExc_TypeError, # This is a shorthand for "PyErr_SetString(PyExc_TypeError,
# message)", where message indicates that a built-in operation was # message)", where message indicates that a built-in operation was
...@@ -196,7 +196,7 @@ cdef extern from "Python.h": ...@@ -196,7 +196,7 @@ cdef extern from "Python.h":
# (e.g. a Python/C API function) was invoked with an illegal # (e.g. a Python/C API function) was invoked with an illegal
# argument. It is mostly for internal use. # argument. It is mostly for internal use.
int PyErr_WarnEx(object category, char *message, int stacklevel) int PyErr_WarnEx(object category, char *message, int stacklevel) except -1
# Issue a warning message. The category argument is a warning # Issue a warning message. The category argument is a warning
# category (see below) or NULL; the message argument is a message # category (see below) or NULL; the message argument is a message
# string. stacklevel is a positive number giving a number of stack # string. stacklevel is a positive number giving a number of stack
...@@ -205,14 +205,14 @@ cdef extern from "Python.h": ...@@ -205,14 +205,14 @@ cdef extern from "Python.h":
# function calling PyErr_WarnEx(), 2 is the function above that, # function calling PyErr_WarnEx(), 2 is the function above that,
# and so forth. # and so forth.
int PyErr_WarnExplicit(object category, char *message, char *filename, int lineno, char *module, object registry) int PyErr_WarnExplicit(object category, char *message, char *filename, int lineno, char *module, object registry) except -1
# Issue a warning message with explicit control over all warning # Issue a warning message with explicit control over all warning
# attributes. This is a straightforward wrapper around the Python # attributes. This is a straightforward wrapper around the Python
# function warnings.warn_explicit(), see there for more # function warnings.warn_explicit(), see there for more
# information. The module and registry arguments may be set to # information. The module and registry arguments may be set to
# NULL to get the default effect described there. # NULL to get the default effect described there.
int PyErr_CheckSignals() int PyErr_CheckSignals() except -1
# This function interacts with Python's signal handling. It checks # This function interacts with Python's signal handling. It checks
# whether a signal has been sent to the processes and if so, # whether a signal has been sent to the processes and if so,
# invokes the corresponding signal handler. If the signal module # invokes the corresponding signal handler. If the signal module
......
...@@ -31,9 +31,9 @@ cdef extern from "Python.h": ...@@ -31,9 +31,9 @@ cdef extern from "Python.h":
# Return value: New reference. # Return value: New reference.
# Create a PyFloatObject object from v, or NULL on failure. # Create a PyFloatObject object from v, or NULL on failure.
double PyFloat_AsDouble(object pyfloat) double PyFloat_AsDouble(object pyfloat) except? -1
# Return a C double representation of the contents of pyfloat. # Return a C double representation of the contents of pyfloat.
double PyFloat_AS_DOUBLE(object pyfloat) double PyFloat_AS_DOUBLE(object pyfloat) except? -1
# Return a C double representation of the contents of pyfloat, but # Return a C double representation of the contents of pyfloat, but
# without error checking. # without error checking.
...@@ -30,21 +30,21 @@ cdef extern from "Python.h": ...@@ -30,21 +30,21 @@ cdef extern from "Python.h":
# the code object, the argument defaults and closure are set to # the code object, the argument defaults and closure are set to
# NULL. # NULL.
PyObject* PyFunction_GetCode(object op) PyObject* PyFunction_GetCode(object op) except? NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the code object associated with the function object op. # Return the code object associated with the function object op.
PyObject* PyFunction_GetGlobals(object op) PyObject* PyFunction_GetGlobals(object op) except? NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the globals dictionary associated with the function object op. # Return the globals dictionary associated with the function object op.
PyObject* PyFunction_GetModule(object op) PyObject* PyFunction_GetModule(object op) except? NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the __module__ attribute of the function object op. This # Return the __module__ attribute of the function object op. This
# is normally a string containing the module name, but can be set # is normally a string containing the module name, but can be set
# to any other object by Python code. # to any other object by Python code.
PyObject* PyFunction_GetDefaults(object op) PyObject* PyFunction_GetDefaults(object op) except? NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the argument default values of the function object # Return the argument default values of the function object
# op. This can be a tuple of arguments or NULL. # op. This can be a tuple of arguments or NULL.
...@@ -54,7 +54,7 @@ cdef extern from "Python.h": ...@@ -54,7 +54,7 @@ cdef extern from "Python.h":
# op. defaults must be Py_None or a tuple. # op. defaults must be Py_None or a tuple.
# Raises SystemError and returns -1 on failure. # Raises SystemError and returns -1 on failure.
PyObject* PyFunction_GetClosure(object op) PyObject* PyFunction_GetClosure(object op) except? NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the closure associated with the function object op. This # Return the closure associated with the function object op. This
# can be NULL or a tuple of cell objects. # can be NULL or a tuple of cell objects.
......
from python_ref cimport PyObject
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
##################################################################### #####################################################################
# 5.5 Parsing arguments and building values # 5.5 Parsing arguments and building values
##################################################################### #####################################################################
ctypedef struct va_list ctypedef struct va_list
int PyArg_ParseTuple(PyObject *args, char *format, ...) int PyArg_ParseTuple(object args, char *format, ...) except 0
int PyArg_VaParse(PyObject *args, char *format, va_list vargs) int PyArg_VaParse(object args, char *format, va_list vargs) except 0
int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, char *format, char *keywords[], ...) int PyArg_ParseTupleAndKeywords(object args, object kw, char *format, char *keywords[], ...) except 0
int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, char *format, char *keywords[], va_list vargs) int PyArg_VaParseTupleAndKeywords(object args, object kw, char *format, char *keywords[], va_list vargs) except 0
int PyArg_Parse(PyObject *args, char *format, ...) int PyArg_Parse(object args, char *format, ...) except 0
int PyArg_UnpackTuple(PyObject *args, char *name, Py_ssize_t min, Py_ssize_t max, ...) int PyArg_UnpackTuple(object args, char *name, Py_ssize_t min, Py_ssize_t max, ...) except 0
...@@ -58,18 +58,18 @@ cdef extern from "Python.h": ...@@ -58,18 +58,18 @@ cdef extern from "Python.h":
long PyInt_AS_LONG(object io) long PyInt_AS_LONG(object io)
# Return the value of the object io. No error checking is performed. # Return the value of the object io. No error checking is performed.
unsigned long PyInt_AsUnsignedLongMask(object io) unsigned long PyInt_AsUnsignedLongMask(object io) except? -1
# Will first attempt to cast the object to a PyIntObject or # Will first attempt to cast the object to a PyIntObject or
# PyLongObject, if it is not already one, and then return its # PyLongObject, if it is not already one, and then return its
# value as unsigned long. This function does not check for # value as unsigned long. This function does not check for
# overflow. # overflow.
PY_LONG_LONG PyInt_AsUnsignedLongLongMask(object io) PY_LONG_LONG PyInt_AsUnsignedLongLongMask(object io) except? -1
# Will first attempt to cast the object to a PyIntObject or # Will first attempt to cast the object to a PyIntObject or
# PyLongObject, if it is not already one, and then return its # PyLongObject, if it is not already one, and then return its
# value as unsigned long long, without checking for overflow. # value as unsigned long long, without checking for overflow.
Py_ssize_t PyInt_AsSsize_t(object io) Py_ssize_t PyInt_AsSsize_t(object io) except? -1
# Will first attempt to cast the object to a PyIntObject or # Will first attempt to cast the object to a PyIntObject or
# PyLongObject, if it is not already one, and then return its # PyLongObject, if it is not already one, and then return its
# value as Py_ssize_t. # value as Py_ssize_t.
......
...@@ -22,14 +22,14 @@ cdef extern from "Python.h": ...@@ -22,14 +22,14 @@ cdef extern from "Python.h":
# Return true if p is a list object, but not an instance of a # Return true if p is a list object, but not an instance of a
# subtype of the list type. # subtype of the list type.
Py_ssize_t PyList_Size(object list) Py_ssize_t PyList_Size(object list) except -1
# Return the length of the list object in list; this is equivalent # Return the length of the list object in list; this is equivalent
# to "len(list)" on a list object. # to "len(list)" on a list object.
Py_ssize_t PyList_GET_SIZE(object list) Py_ssize_t PyList_GET_SIZE(object list)
# Macro form of PyList_Size() without error checking. # Macro form of PyList_Size() without error checking.
PyObject* PyList_GetItem(object list, Py_ssize_t index) PyObject* PyList_GetItem(object list, Py_ssize_t index) except NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the object at position pos in the list pointed to by # Return the object at position pos in the list pointed to by
# p. The position must be positive, indexing from the end of the # p. The position must be positive, indexing from the end of the
......
...@@ -72,32 +72,32 @@ cdef extern from "Python.h": ...@@ -72,32 +72,32 @@ cdef extern from "Python.h":
# PyLong_AsVoidPtr(). If the integer is larger than LONG_MAX, a # PyLong_AsVoidPtr(). If the integer is larger than LONG_MAX, a
# positive long integer is returned. # positive long integer is returned.
long PyLong_AsLong(object pylong) long PyLong_AsLong(object pylong) except? -1
# Return a C long representation of the contents of pylong. If # Return a C long representation of the contents of pylong. If
# pylong is greater than LONG_MAX, an OverflowError is raised. # pylong is greater than LONG_MAX, an OverflowError is raised.
unsigned long PyLong_AsUnsignedLong(object pylong) unsigned long PyLong_AsUnsignedLong(object pylong) except? -1
# Return a C unsigned long representation of the contents of # Return a C unsigned long representation of the contents of
# pylong. If pylong is greater than ULONG_MAX, an OverflowError is # pylong. If pylong is greater than ULONG_MAX, an OverflowError is
# raised. # raised.
PY_LONG_LONG PyLong_AsLongLong(object pylong) PY_LONG_LONG PyLong_AsLongLong(object pylong) except? -1
# Return a C long long from a Python long integer. If pylong # Return a C long long from a Python long integer. If pylong
# cannot be represented as a long long, an OverflowError will be # cannot be represented as a long long, an OverflowError will be
# raised. # raised.
uPY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong) uPY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong) except? -1
#unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong) #unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong)
# Return a C unsigned long long from a Python long integer. If # Return a C unsigned long long from a Python long integer. If
# pylong cannot be represented as an unsigned long long, an # pylong cannot be represented as an unsigned long long, an
# OverflowError will be raised if the value is positive, or a # OverflowError will be raised if the value is positive, or a
# TypeError will be raised if the value is negative. # TypeError will be raised if the value is negative.
unsigned long PyLong_AsUnsignedLongMask(object io) unsigned long PyLong_AsUnsignedLongMask(object io) except? -1
# Return a C unsigned long from a Python long integer, without # Return a C unsigned long from a Python long integer, without
# checking for overflow. # checking for overflow.
uPY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io) uPY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io) except? -1
#unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io) #unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io)
# Return a C unsigned long long from a Python long integer, # Return a C unsigned long long from a Python long integer,
# without checking for overflow. # without checking for overflow.
...@@ -107,7 +107,7 @@ cdef extern from "Python.h": ...@@ -107,7 +107,7 @@ cdef extern from "Python.h":
# pylong cannot be approximately represented as a double, an # pylong cannot be approximately represented as a double, an
# OverflowError exception is raised and -1.0 will be returned. # OverflowError exception is raised and -1.0 will be returned.
void* PyLong_AsVoidPtr(object pylong) void* PyLong_AsVoidPtr(object pylong) except? NULL
# Convert a Python integer or long integer pylong to a C void # Convert a Python integer or long integer pylong to a C void
# pointer. If pylong cannot be converted, an OverflowError will be # pointer. If pylong cannot be converted, an OverflowError will be
# raised. This is only assured to produce a usable void pointer # raised. This is only assured to produce a usable void pointer
......
...@@ -21,7 +21,7 @@ cdef extern from "Python.h": ...@@ -21,7 +21,7 @@ cdef extern from "Python.h":
# otherwise self should be NULL and class should be the class # otherwise self should be NULL and class should be the class
# which provides the unbound method.. # which provides the unbound method..
PyObject* PyMethod_Class(object meth) PyObject* PyMethod_Class(object meth) except NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the class object from which the method meth was created; # Return the class object from which the method meth was created;
# if this was created from an instance, it will be the class of # if this was created from an instance, it will be the class of
...@@ -31,7 +31,7 @@ cdef extern from "Python.h": ...@@ -31,7 +31,7 @@ cdef extern from "Python.h":
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Macro version of PyMethod_Class() which avoids error checking. # Macro version of PyMethod_Class() which avoids error checking.
PyObject* PyMethod_Function(object meth) PyObject* PyMethod_Function(object meth) except NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the function object associated with the method meth. # Return the function object associated with the method meth.
...@@ -39,7 +39,7 @@ cdef extern from "Python.h": ...@@ -39,7 +39,7 @@ cdef extern from "Python.h":
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Macro version of PyMethod_Function() which avoids error checking. # Macro version of PyMethod_Function() which avoids error checking.
PyObject* PyMethod_Self(object meth) PyObject* PyMethod_Self(object meth) except? NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the instance associated with the method meth if it is bound, otherwise return NULL. # Return the instance associated with the method meth if it is bound, otherwise return NULL.
......
...@@ -90,7 +90,7 @@ cdef extern from "Python.h": ...@@ -90,7 +90,7 @@ cdef extern from "Python.h":
# and .pyo files). The magic number should be present in the first # and .pyo files). The magic number should be present in the first
# four bytes of the bytecode file, in little-endian byte order. # four bytes of the bytecode file, in little-endian byte order.
PyObject* PyImport_GetModuleDict() PyObject* PyImport_GetModuleDict() except NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the dictionary used for the module administration # Return the dictionary used for the module administration
# (a.k.a. sys.modules). Note that this is a per-interpreter # (a.k.a. sys.modules). Note that this is a per-interpreter
...@@ -139,7 +139,7 @@ cdef extern from "Python.h": ...@@ -139,7 +139,7 @@ cdef extern from "Python.h":
# filled in; the caller is responsible for providing a __file__ # filled in; the caller is responsible for providing a __file__
# attribute. # attribute.
PyObject* PyModule_GetDict(object module) PyObject* PyModule_GetDict(object module) except NULL
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Return the dictionary object that implements module's namespace; # Return the dictionary object that implements module's namespace;
# this object is the same as the __dict__ attribute of the module # this object is the same as the __dict__ attribute of the module
......
...@@ -236,7 +236,7 @@ cdef extern from "Python.h": ...@@ -236,7 +236,7 @@ cdef extern from "Python.h":
# Returns the o converted to a Python int or long on success or # Returns the o converted to a Python int or long on success or
# NULL with a TypeError exception raised on failure. # NULL with a TypeError exception raised on failure.
Py_ssize_t PyNumber_AsSsize_t(object o, object exc) Py_ssize_t PyNumber_AsSsize_t(object o, object exc) except? -1
# Returns o converted to a Py_ssize_t value if o can be # Returns o converted to a Py_ssize_t value if o can be
# interpreted as an integer. If o can be converted to a Python int # interpreted as an integer. If o can be converted to a Python int
# or long but the attempt to convert to a Py_ssize_t value would # or long but the attempt to convert to a Py_ssize_t value would
......
...@@ -49,7 +49,7 @@ cdef extern from "Python.h": ...@@ -49,7 +49,7 @@ cdef extern from "Python.h":
# PyCapsule_Import(). # PyCapsule_Import().
void* PyCapsule_GetPointer(object capsule, char *name) void* PyCapsule_GetPointer(object capsule, char *name) except? NULL
# Retrieve the pointer stored in the capsule. On failure, set an # Retrieve the pointer stored in the capsule. On failure, set an
# exception and return NULL. # exception and return NULL.
# #
...@@ -59,7 +59,7 @@ cdef extern from "Python.h": ...@@ -59,7 +59,7 @@ cdef extern from "Python.h":
# to compare capsule names. # to compare capsule names.
PyCapsule_Destructor PyCapsule_GetDestructor(object capsule) PyCapsule_Destructor PyCapsule_GetDestructor(object capsule) except? NULL
# Return the current destructor stored in the capsule. On failure, # Return the current destructor stored in the capsule. On failure,
# set an exception and return NULL. # set an exception and return NULL.
# #
...@@ -68,7 +68,7 @@ cdef extern from "Python.h": ...@@ -68,7 +68,7 @@ cdef extern from "Python.h":
# or PyErr_Occurred() to disambiguate. # or PyErr_Occurred() to disambiguate.
char* PyCapsule_GetName(object capsule) char* PyCapsule_GetName(object capsule) except? NULL
# Return the current name stored in the capsule. On failure, set # Return the current name stored in the capsule. On failure, set
# an exception and return NULL. # an exception and return NULL.
# #
...@@ -77,7 +77,7 @@ cdef extern from "Python.h": ...@@ -77,7 +77,7 @@ cdef extern from "Python.h":
# PyErr_Occurred() to disambiguate. # PyErr_Occurred() to disambiguate.
void* PyCapsule_GetContext(object capsule) void* PyCapsule_GetContext(object capsule) except? NULL
# Return the current context stored in the capsule. On failure, # Return the current context stored in the capsule. On failure,
# set an exception and return NULL. # set an exception and return NULL.
# #
...@@ -86,7 +86,7 @@ cdef extern from "Python.h": ...@@ -86,7 +86,7 @@ cdef extern from "Python.h":
# PyErr_Occurred() to disambiguate. # PyErr_Occurred() to disambiguate.
int PyCapsule_IsValid(object capsule, char *name) bint PyCapsule_IsValid(object capsule, char *name)
# Determines whether or not capsule is a valid capsule. A valid # Determines whether or not capsule is a valid capsule. A valid
# capsule is non-NULL, passes PyCapsule_CheckExact(), has a # capsule is non-NULL, passes PyCapsule_CheckExact(), has a
# non-NULL pointer stored in it, and its internal name matches the # non-NULL pointer stored in it, and its internal name matches the
...@@ -101,7 +101,7 @@ cdef extern from "Python.h": ...@@ -101,7 +101,7 @@ cdef extern from "Python.h":
# name passed in. Return 0 otherwise. This function will not fail. # name passed in. Return 0 otherwise. This function will not fail.
int PyCapsule_SetPointer(object capsule, void *pointer) int PyCapsule_SetPointer(object capsule, void *pointer) except -1
# Set the void pointer inside capsule to pointer. The pointer may # Set the void pointer inside capsule to pointer. The pointer may
# not be NULL. # not be NULL.
# #
...@@ -109,14 +109,14 @@ cdef extern from "Python.h": ...@@ -109,14 +109,14 @@ cdef extern from "Python.h":
# failure. # failure.
int PyCapsule_SetDestructor(object capsule, PyCapsule_Destructor destructor) int PyCapsule_SetDestructor(object capsule, PyCapsule_Destructor destructor) except -1
# Set the destructor inside capsule to destructor. # Set the destructor inside capsule to destructor.
# #
# Return 0 on success. Return nonzero and set an exception on # Return 0 on success. Return nonzero and set an exception on
# failure. # failure.
int PyCapsule_SetName(object capsule, char *name) int PyCapsule_SetName(object capsule, char *name) except -1
# Set the name inside capsule to name. If non-NULL, the name must # Set the name inside capsule to name. If non-NULL, the name must
# outlive the capsule. If the previous name stored in the capsule # outlive the capsule. If the previous name stored in the capsule
# was not NULL, no attempt is made to free it. # was not NULL, no attempt is made to free it.
...@@ -125,12 +125,12 @@ cdef extern from "Python.h": ...@@ -125,12 +125,12 @@ cdef extern from "Python.h":
# failure. # failure.
int PyCapsule_SetContext(object capsule, void *context) int PyCapsule_SetContext(object capsule, void *context) except -1
# Set the context pointer inside capsule to context. Return 0 on # Set the context pointer inside capsule to context. Return 0 on
# success. Return nonzero and set an exception on failure. # success. Return nonzero and set an exception on failure.
void* PyCapsule_Import(char *name, int no_block) void* PyCapsule_Import(char *name, int no_block) except? NULL
# Import a pointer to a C object from a capsule attribute in a # Import a pointer to a C object from a capsule attribute in a
# module. The name parameter should specify the full name to the # module. The name parameter should specify the full name to the
# attribute, as in module.attribute. The name stored in the # attribute, as in module.attribute. The name stored in the
......
...@@ -47,7 +47,7 @@ cdef extern from "Python.h": ...@@ -47,7 +47,7 @@ cdef extern from "Python.h":
bint PyFrozenSet_CheckExact(object p) bint PyFrozenSet_CheckExact(object p)
# Return true if p is a frozenset object but not an instance of a subtype. # Return true if p is a frozenset object but not an instance of a subtype.
PySet_New(object iterable) object PySet_New(object iterable)
# Return value: New reference. # Return value: New reference.
# Return a new set containing objects returned by the # Return a new set containing objects returned by the
# iterable. The iterable may be NULL to create a new empty # iterable. The iterable may be NULL to create a new empty
...@@ -55,7 +55,7 @@ cdef extern from "Python.h": ...@@ -55,7 +55,7 @@ cdef extern from "Python.h":
# TypeError if iterable is not actually iterable. The constructor # TypeError if iterable is not actually iterable. The constructor
# is also useful for copying a set (c=set(s)). # is also useful for copying a set (c=set(s)).
PyFrozenSet_New(object iterable) object PyFrozenSet_New(object iterable)
# Return value: New reference. # Return value: New reference.
# Return a new frozenset containing objects returned by the # Return a new frozenset containing objects returned by the
# iterable. The iterable may be NULL to create a new empty # iterable. The iterable may be NULL to create a new empty
......
...@@ -68,7 +68,7 @@ cdef extern from "Python.h": ...@@ -68,7 +68,7 @@ cdef extern from "Python.h":
# Return value: New reference. # Return value: New reference.
# Identical to PyString_FromFormat() except that it takes exactly two arguments. # Identical to PyString_FromFormat() except that it takes exactly two arguments.
Py_ssize_t PyString_Size(object string) Py_ssize_t PyString_Size(object string) except -1
# Return the length of the string in string object string. # Return the length of the string in string object string.
Py_ssize_t PyString_GET_SIZE(object string) Py_ssize_t PyString_GET_SIZE(object string)
......
...@@ -24,7 +24,7 @@ cdef extern from "Python.h": ...@@ -24,7 +24,7 @@ cdef extern from "Python.h":
# pointing to Python objects. "PyTuple_Pack(2, a, b)" is # pointing to Python objects. "PyTuple_Pack(2, a, b)" is
# equivalent to "Py_BuildValue("(OO)", a, b)". # equivalent to "Py_BuildValue("(OO)", a, b)".
int PyTuple_Size(object p) int PyTuple_Size(object p) except -1
# Take a pointer to a tuple object, and return the size of that tuple. # Take a pointer to a tuple object, and return the size of that tuple.
int PyTuple_GET_SIZE(object p) int PyTuple_GET_SIZE(object p)
......
...@@ -93,10 +93,10 @@ cdef extern from *: ...@@ -93,10 +93,10 @@ cdef extern from *:
# Return a read-only pointer to the Unicode object's internal # Return a read-only pointer to the Unicode object's internal
# Py_UNICODE buffer, NULL if unicode is not a Unicode object. # Py_UNICODE buffer, NULL if unicode is not a Unicode object.
Py_UNICODE* PyUnicode_AsUnicode(object o) Py_UNICODE* PyUnicode_AsUnicode(object o) except NULL
# Return the length of the Unicode object. # Return the length of the Unicode object.
Py_ssize_t PyUnicode_GetSize(object o) Py_ssize_t PyUnicode_GetSize(object o) except -1
# Coerce an encoded object obj to an Unicode object and return a # Coerce an encoded object obj to an Unicode object and return a
# reference with incremented refcount. # reference with incremented refcount.
......
from python_ref cimport PyObject
cdef extern from "Python.h":
bint PyWeakref_Check(object ob)
# Return true if ob is either a reference or proxy object.
bint PyWeakref_CheckRef(object ob)
# Return true if ob is a reference object.
bint PyWeakref_CheckProxy(ob)
# Return true if *ob* is a proxy object.
object PyWeakref_NewRef(object ob, object callback)
# Return a weak reference object for the object ob. This will
# always return a new reference, but is not guaranteed to create a
# new object; an existing reference object may be returned. The
# second parameter, callback, can be a callable object that
# receives notification when ob is garbage collected; it should
# accept a single parameter, which will be the weak reference
# object itself. callback may also be None or NULL. If ob is not
# a weakly-referencable object, or if callback is not callable,
# None, or NULL, this will return NULL and raise TypeError.
object PyWeakref_NewProxy(object ob, object callback)
# Return a weak reference proxy object for the object ob. This
# will always return a new reference, but is not guaranteed to
# create a new object; an existing proxy object may be returned.
# The second parameter, callback, can be a callable object that
# receives notification when ob is garbage collected; it should
# accept a single parameter, which will be the weak reference
# object itself. callback may also be None or NULL. If ob is not
# a weakly-referencable object, or if callback is not callable,
# None, or NULL, this will return NULL and raise TypeError.
PyObject* PyWeakref_GetObject(object ref)
# Return the referenced object from a weak reference, ref. If the
# referent is no longer live, returns None.
PyObject* PyWeakref_GET_OBJECT(object ref)
# Similar to PyWeakref_GetObject, but implemented as a macro that
# does no error checking.
"""
Tool to run Cython files (.pyx) into .c and .cpp.
TODO:
- Add support for dynamically selecting in-process Cython
through CYTHONINPROCESS variable.
- Have a CYTHONCPP option which turns on C++ in flags and
changes output extension at the same time
VARIABLES:
- CYTHON - The path to the "cython" command line tool.
- CYTHONFLAGS - Flags to pass to the "cython" command line tool.
AUTHORS:
- David Cournapeau
- Dag Sverre Seljebotn
"""
import SCons
from SCons.Builder import Builder
from SCons.Action import Action
#def cython_action(target, source, env):
# print target, source, env
# from Cython.Compiler.Main import compile as cython_compile
# res = cython_compile(str(source[0]))
cythonAction = Action("$CYTHONCOM")
def create_builder(env):
try:
cython = env['BUILDERS']['Cython']
except KeyError:
cython = SCons.Builder.Builder(
action = cythonAction,
emitter = {},
suffix = cython_suffix_emitter,
single_source = 1)
env['BUILDERS']['Cython'] = cython
return cython
def cython_suffix_emitter(env, source):
print 'emitter called'
return "$CYTHONCFILESUFFIX"
def generate(env):
env["CYTHON"] = "cython"
env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS -o $TARGET $SOURCE"
env["CYTHONCFILESUFFIX"] = ".c"
c_file, cxx_file = SCons.Tool.createCFileBuilders(env)
c_file.suffix['.pyx'] = cython_suffix_emitter
c_file.add_action('.pyx', cythonAction)
c_file.suffix['.py'] = cython_suffix_emitter
c_file.add_action('.py', cythonAction)
create_builder(env)
def exists(env):
try:
# import Cython
return True
except ImportError:
return False
"""SCons.Tool.pyext
Tool-specific initialization for python extensions builder.
AUTHORS:
- David Cournapeau
- Dag Sverre Seljebotn
"""
#
# __COPYRIGHT__
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import sys
import SCons
from SCons.Tool import SourceFileScanner, ProgramScanner
# Create common python builders
def createPythonObjectBuilder(env):
"""This is a utility function that creates the PythonObject Builder in an
Environment if it is not there already.
If it is already there, we return the existing one.
"""
try:
pyobj = env['BUILDERS']['PythonObject']
except KeyError:
pyobj = SCons.Builder.Builder(action = {},
emitter = {},
prefix = '$PYEXTOBJPREFIX',
suffix = '$PYEXTOBJSUFFIX',
src_builder = ['CFile', 'CXXFile'],
source_scanner = SourceFileScanner,
single_source = 1)
env['BUILDERS']['PythonObject'] = pyobj
return pyobj
def createPythonExtensionBuilder(env):
"""This is a utility function that creates the PythonExtension Builder in
an Environment if it is not there already.
If it is already there, we return the existing one.
"""
try:
pyext = env['BUILDERS']['PythonExtension']
except KeyError:
import SCons.Action
import SCons.Defaults
action = SCons.Action.Action("$PYEXTLINKCOM", "$PYEXTLINKCOMSTR")
action_list = [ SCons.Defaults.SharedCheck,
action]
pyext = SCons.Builder.Builder(action = action_list,
emitter = "$SHLIBEMITTER",
prefix = '$PYEXTPREFIX',
suffix = '$PYEXTSUFFIX',
target_scanner = ProgramScanner,
src_suffix = '$PYEXTOBJSUFFIX',
src_builder = 'PythonObject')
env['BUILDERS']['PythonExtension'] = pyext
return pyext
def pyext_coms(platform):
"""Return PYEXTCCCOM, PYEXTCXXCOM and PYEXTLINKCOM for the given
platform."""
if platform == 'win32':
pyext_cccom = "$PYEXTCC /Fo$TARGET /c $PYEXTCCSHARED "\
"$PYEXTCFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
"$_PYEXTCPPINCFLAGS $SOURCES"
pyext_cxxcom = "$PYEXTCXX /Fo$TARGET /c $PYEXTCSHARED "\
"$PYEXTCXXFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
"$_PYEXTCPPINCFLAGS $SOURCES"
pyext_linkcom = '${TEMPFILE("$PYEXTLINK $PYEXTLINKFLAGS '\
'/OUT:$TARGET.windows $( $_LIBDIRFLAGS $) '\
'$_LIBFLAGS $_PYEXTRUNTIME $SOURCES.windows")}'
else:
pyext_cccom = "$PYEXTCC -o $TARGET -c $PYEXTCCSHARED "\
"$PYEXTCFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
"$_PYEXTCPPINCFLAGS $SOURCES"
pyext_cxxcom = "$PYEXTCXX -o $TARGET -c $PYEXTCSHARED "\
"$PYEXTCXXFLAGS $PYEXTCCFLAGS $_CCCOMCOM "\
"$_PYEXTCPPINCFLAGS $SOURCES"
pyext_linkcom = "$PYEXTLINK -o $TARGET $PYEXTLINKFLAGS "\
"$SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_PYEXTRUNTIME"
if platform == 'darwin':
pyext_linkcom += ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
return pyext_cccom, pyext_cxxcom, pyext_linkcom
def set_basic_vars(env):
# Set construction variables which are independant on whether we are using
# distutils or not.
env['PYEXTCPPPATH'] = SCons.Util.CLVar('$PYEXTINCPATH')
env['_PYEXTCPPINCFLAGS'] = '$( ${_concat(INCPREFIX, PYEXTCPPPATH, '\
'INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'
env['PYEXTOBJSUFFIX'] = '$SHOBJSUFFIX'
env['PYEXTOBJPREFIX'] = '$SHOBJPREFIX'
env['PYEXTRUNTIME'] = SCons.Util.CLVar("")
# XXX: this should be handled with different flags
env['_PYEXTRUNTIME'] = '$( ${_concat(LIBLINKPREFIX, PYEXTRUNTIME, '\
'LIBLINKSUFFIX, __env__)} $)'
# XXX: This won't work in all cases (using mingw, for example). To make
# 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.
pycc, pycxx, pylink = pyext_coms(sys.platform)
env['PYEXTLINKFLAGSEND'] = SCons.Util.CLVar('$LINKFLAGSEND')
env['PYEXTCCCOM'] = pycc
env['PYEXTCXXCOM'] = pycxx
env['PYEXTLINKCOM'] = pylink
def _set_configuration_nodistutils(env):
# Set env variables to sensible values when not using distutils
def_cfg = {'PYEXTCC' : '$SHCC',
'PYEXTCFLAGS' : '$SHCFLAGS',
'PYEXTCCFLAGS' : '$SHCCFLAGS',
'PYEXTCXX' : '$SHCXX',
'PYEXTCXXFLAGS' : '$SHCXXFLAGS',
'PYEXTLINK' : '$LDMODULE',
'PYEXTSUFFIX' : '$LDMODULESUFFIX',
'PYEXTPREFIX' : ''}
if sys.platform == 'darwin':
def_cfg['PYEXTSUFFIX'] = '.so'
for k, v in def_cfg.items():
ifnotset(env, k, v)
ifnotset(env, 'PYEXT_ALLOW_UNDEFINED',
SCons.Util.CLVar('$ALLOW_UNDEFINED'))
ifnotset(env, 'PYEXTLINKFLAGS', SCons.Util.CLVar('$LDMODULEFLAGS'))
env.AppendUnique(PYEXTLINKFLAGS = env['PYEXT_ALLOW_UNDEFINED'])
def ifnotset(env, name, value):
if not env.has_key(name):
env[name] = value
def set_configuration(env, use_distutils):
"""Set construction variables which are platform dependants.
If use_distutils == True, use distutils configuration. Otherwise, use
'sensible' default.
Any variable already defined is untouched."""
# 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
# the shell.
dist_cfg = {'PYEXTCC': "sysconfig.get_config_var('CC')",
'PYEXTCFLAGS': "sysconfig.get_config_var('CFLAGS')",
'PYEXTCCSHARED': "sysconfig.get_config_var('CCSHARED')",
'PYEXTLINKFLAGS': "sysconfig.get_config_var('LDFLAGS')",
'PYEXTLINK': "sysconfig.get_config_var('LDSHARED')",
'PYEXTINCPATH': "sysconfig.get_python_inc()",
'PYEXTSUFFIX': "sysconfig.get_config_var('SO')"}
from distutils import sysconfig
# We set the python path even when not using distutils, because we rarely
# want to change this, even if not using distutils
ifnotset(env, 'PYEXTINCPATH', sysconfig.get_python_inc())
if use_distutils:
for k, v in dist_cfg.items():
ifnotset(env, k, eval(v))
else:
_set_configuration_nodistutils(env)
def generate(env):
"""Add Builders and construction variables for python extensions to an
Environment."""
if not env.has_key('PYEXT_USE_DISTUTILS'):
env['PYEXT_USE_DISTUTILS'] = False
# This sets all constructions variables used for pyext builders.
set_basic_vars(env)
set_configuration(env, env['PYEXT_USE_DISTUTILS'])
# Create the PythonObject builder
pyobj = createPythonObjectBuilder(env)
action = SCons.Action.Action("$PYEXTCCCOM", "$PYEXTCCCOMSTR")
pyobj.add_emitter('.c', SCons.Defaults.SharedObjectEmitter)
pyobj.add_action('.c', action)
action = SCons.Action.Action("$PYEXTCXXCOM", "$PYEXTCXXCOMSTR")
pyobj.add_emitter('$CXXFILESUFFIX', SCons.Defaults.SharedObjectEmitter)
pyobj.add_action('$CXXFILESUFFIX', action)
# Create the PythonExtension builder
createPythonExtensionBuilder(env)
def exists(env):
try:
# This is not quite right: if someone defines all variables by himself,
# it would work without distutils
from distutils import sysconfig
return True
except ImportError:
return False
...@@ -6,7 +6,6 @@ out_fname = pyx_to_dll("foo.pyx") ...@@ -6,7 +6,6 @@ out_fname = pyx_to_dll("foo.pyx")
import os import os
import sys import sys
import distutils
from distutils.dist import Distribution from distutils.dist import Distribution
from distutils.errors import DistutilsArgError, DistutilsError, CCompilerError from distutils.errors import DistutilsArgError, DistutilsError, CCompilerError
from distutils.extension import Extension from distutils.extension import Extension
...@@ -16,11 +15,13 @@ try: ...@@ -16,11 +15,13 @@ try:
HAS_CYTHON = True HAS_CYTHON = True
except ImportError: except ImportError:
HAS_CYTHON = False HAS_CYTHON = False
import shutil
DEBUG = 0 DEBUG = 0
_reloads={}
def pyx_to_dll(filename, ext = None, force_rebuild = 0, def pyx_to_dll(filename, ext = None, force_rebuild = 0,
build_in_temp=False, pyxbuild_dir=None): build_in_temp=False, pyxbuild_dir=None, setup_args={}, reload_support=False):
"""Compile a PYX file to a DLL and return the name of the generated .so """Compile a PYX file to a DLL and return the name of the generated .so
or .dll .""" or .dll ."""
assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename) assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename)
...@@ -37,7 +38,8 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0, ...@@ -37,7 +38,8 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0,
if not pyxbuild_dir: if not pyxbuild_dir:
pyxbuild_dir = os.path.join(path, "_pyxbld") pyxbuild_dir = os.path.join(path, "_pyxbld")
if DEBUG: script_args=setup_args.get("script_args",[])
if DEBUG or "--verbose" in script_args:
quiet = "--verbose" quiet = "--verbose"
else: else:
quiet = "--quiet" quiet = "--quiet"
...@@ -46,7 +48,11 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0, ...@@ -46,7 +48,11 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0,
args.append("--force") args.append("--force")
if HAS_CYTHON and build_in_temp: if HAS_CYTHON and build_in_temp:
args.append("--pyrex-c-in-temp") args.append("--pyrex-c-in-temp")
dist = Distribution({"script_name": None, "script_args": args}) sargs = setup_args.copy()
sargs.update(
{"script_name": None,
"script_args": args + script_args} )
dist = Distribution(sargs)
if not dist.ext_modules: if not dist.ext_modules:
dist.ext_modules = [] dist.ext_modules = []
dist.ext_modules.append(ext) dist.ext_modules.append(ext)
...@@ -60,6 +66,10 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0, ...@@ -60,6 +66,10 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0,
except ValueError: pass except ValueError: pass
dist.parse_config_files(config_files) dist.parse_config_files(config_files)
cfgfiles = dist.find_config_files()
try: cfgfiles.remove('setup.cfg')
except ValueError: pass
dist.parse_config_files(cfgfiles)
try: try:
ok = dist.parse_command_line() ok = dist.parse_command_line()
except DistutilsArgError: except DistutilsArgError:
...@@ -73,7 +83,39 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0, ...@@ -73,7 +83,39 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0,
try: try:
dist.run_commands() dist.run_commands()
return dist.get_command_obj("build_ext").get_outputs()[0] obj_build_ext = dist.get_command_obj("build_ext")
so_path = obj_build_ext.get_outputs()[0]
if obj_build_ext.inplace:
# Python distutils get_outputs()[ returns a wrong so_path
# when --inplace ; see http://bugs.python.org/issue5977
# workaround:
so_path = os.path.join(os.path.dirname(filename),
os.path.basename(so_path))
if reload_support:
org_path = so_path
timestamp = os.path.getmtime(org_path)
global _reloads
last_timestamp, last_path, count = _reloads.get(org_path, (None,None,0) )
if last_timestamp == timestamp:
so_path = last_path
else:
basename = os.path.basename(org_path)
while count < 100:
count += 1
r_path = os.path.join(obj_build_ext.build_lib,
basename + '.reload%s'%count)
try:
import shutil # late import / reload_support is: debugging
shutil.copy2(org_path, r_path)
so_path = r_path
except IOError:
continue
break
else:
# used up all 100 slots
raise ImportError("reload count for %s reached maximum"%org_path)
_reloads[org_path]=(timestamp, so_path, count)
return so_path
except KeyboardInterrupt: except KeyboardInterrupt:
sys.exit(1) sys.exit(1)
except (IOError, os.error): except (IOError, os.error):
...@@ -82,16 +124,7 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0, ...@@ -82,16 +124,7 @@ def pyx_to_dll(filename, ext = None, force_rebuild = 0,
if DEBUG: if DEBUG:
sys.stderr.write(error + "\n") sys.stderr.write(error + "\n")
raise raise
else:
raise RuntimeError(error)
except (DistutilsError, CCompilerError):
if DEBUG:
raise
else:
exc = sys.exc_info()[1]
raise RuntimeError(repr(exc))
if __name__=="__main__": if __name__=="__main__":
pyx_to_dll("dummy.pyx") pyx_to_dll("dummy.pyx")
......
This diff is collapsed.
...@@ -7,4 +7,3 @@ numpy_ValueError_T172 ...@@ -7,4 +7,3 @@ numpy_ValueError_T172
unsignedbehaviour_T184 unsignedbehaviour_T184
bad_c_struct_T252 bad_c_struct_T252
missing_baseclass_in_predecl_T262 missing_baseclass_in_predecl_T262
extended_unpacking_T409
cimport python_bool cimport python_bool
cimport python_buffer cimport python_buffer
cimport python_bytes
cimport python_cobject
cimport python_complex cimport python_complex
cimport python_dict cimport python_dict
cimport python_exc cimport python_exc
cimport python_float cimport python_float
cimport python_function cimport python_function
cimport python_getargs
cimport python_instance cimport python_instance
cimport python_int cimport python_int
cimport python_iterator cimport python_iterator
...@@ -16,8 +19,8 @@ cimport python_method ...@@ -16,8 +19,8 @@ cimport python_method
cimport python_module cimport python_module
cimport python_number cimport python_number
cimport python_object cimport python_object
cimport python_parse
cimport python cimport python
cimport python_pycapsule
cimport python_ref cimport python_ref
cimport python_sequence cimport python_sequence
cimport python_set cimport python_set
...@@ -26,5 +29,6 @@ cimport python_tuple ...@@ -26,5 +29,6 @@ cimport python_tuple
cimport python_type cimport python_type
cimport python_unicode cimport python_unicode
cimport python_version cimport python_version
cimport python_weakref
cimport stdio cimport stdio
cimport stdlib cimport stdlib
...@@ -33,3 +33,43 @@ def single_c(int a, int b): ...@@ -33,3 +33,43 @@ def single_c(int a, int b):
def cascaded_c(double a, double b, double c): def cascaded_c(double a, double b, double c):
return a < b < c return a < b < c
def typed_cmp(list L):
"""
>>> typed_cmp([1,2,3])
False
False
False
False
"""
print L is Ellipsis
print Ellipsis is L
print 1 == L
print L == 1.5
def pointer_cmp():
"""
>>> pointer_cmp()
True
False
True
"""
cdef int* a = NULL
cdef double* b = NULL
cdef double** c = NULL
print a is NULL
print b is not NULL
print c == NULL
def c_cmp(double a, int b, long c):
"""
>>> c_cmp(1, 2, 3)
True
>>> c_cmp(1.5, 2, 2)
True
>>> c_cmp(1.5, 2, 0)
False
>>> c_cmp(1, 1, 3)
False
"""
return a < b <= c
cdef int raise_py_error() except *:
raise TypeError("custom")
cdef extern from "cpp_exceptions_helper.cpp":
cdef int raise_int_raw "raise_int"(bint fire) except +
cdef int raise_int_value "raise_int"(bint fire) except +ValueError
cdef int raise_int_custom "raise_int"(bint fire) except +raise_py_error
cdef int raise_index_raw "raise_index"(bint fire) except +
cdef int raise_index_value "raise_index"(bint fire) except +ValueError
cdef int raise_index_custom "raise_index"(bint fire) except +raise_py_error
def test_int_raw(bint fire):
"""
>>> test_int_raw(False)
>>> test_int_raw(True)
Traceback (most recent call last):
...
RuntimeError: Unknown exception
"""
raise_int_raw(fire)
def test_int_value(bint fire):
"""
>>> test_int_value(False)
>>> test_int_value(True)
Traceback (most recent call last):
...
ValueError
"""
raise_int_value(fire)
def test_int_custom(bint fire):
"""
>>> test_int_custom(False)
>>> test_int_custom(True)
Traceback (most recent call last):
...
TypeError: custom
"""
raise_int_custom(fire)
def test_index_raw(bint fire):
"""
>>> test_index_raw(False)
>>> test_index_raw(True)
Traceback (most recent call last):
...
IndexError: c++ error
"""
raise_index_raw(fire)
def test_index_value(bint fire):
"""
>>> test_index_value(False)
>>> test_index_value(True)
Traceback (most recent call last):
...
ValueError: c++ error
"""
raise_index_value(fire)
def test_index_custom(bint fire):
"""
>>> test_index_custom(False)
>>> test_index_custom(True)
Traceback (most recent call last):
...
TypeError: custom
"""
raise_index_custom(fire)
#include <stdexcept>
int raise_int(int fire) {
if (fire) {
throw 1;
}
return 0;
}
int raise_index(int fire) {
if (fire) {
throw std::out_of_range("c++ error");
}
return 0;
}
...@@ -15,3 +15,17 @@ cdef int obj2int(object ob) except *: ...@@ -15,3 +15,17 @@ cdef int obj2int(object ob) except *:
def foo(a): def foo(a):
cdef int i = obj2int(a) cdef int i = obj2int(a)
CHKERR(i) CHKERR(i)
cdef int* except_expr(bint fire) except <int*>-1:
if fire:
raise RuntimeError
def test_except_expr(bint fire):
"""
>>> test_except_expr(False)
>>> test_except_expr(True)
Traceback (most recent call last):
...
RuntimeError
"""
except_expr(fire)
__doc__ = """
>>> simple()
(1, 2, [1, 2], [1, 2])
>>> extended()
(1, (), 2, [1, 2], [1, 2])
"""
def simple(): def simple():
"""
>>> simple()
([1, 2], [1, 2])
"""
d = e = [1,2]
return d, e
def simple_parallel():
"""
>>> simple_parallel()
(1, 2, [1, 2], [1, 2])
"""
a, c = d = e = [1,2] a, c = d = e = [1,2]
return a, c, d, e return a, c, d, e
def extended(): def extended():
"""
>>> extended()
(1, [], 2, [1, 2], [1, 2])
"""
a, *b, c = d = e = [1,2] a, *b, c = d = e = [1,2]
return a, b, c, d, e return a, b, c, d, e
from __future__ import division from __future__ import division
__doc__ = u"""
>>> doit(1,2)
(0.5, 0)
>>> doit(4,3)
(1.3333333333333333, 1)
>>> doit(4,3.0)
(1.3333333333333333, 1.0)
>>> doit(4,2)
(2.0, 2)
>>> constants()
(0.5, 0, 2.5, 2.0, 2.5, 2)
>>> py_mix(1)
(0.5, 0, 0.5, 0.0, 0.5, 0)
>>> py_mix_rev(4)
(0.25, 0, 1.25, 1.0, 1.25, 1)
>>> py_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
>>> py_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
>>> int_mix(1)
(0.5, 0, 0.5, 0.0, 0.5, 0)
>>> int_mix_rev(4)
(0.25, 0, 1.25, 1.0, 1.25, 1)
>>> float_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
>>> float_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
"""
def doit(x,y): def doit(x,y):
"""
>>> doit(1,2)
(0.5, 0)
>>> doit(4,3)
(1.3333333333333333, 1)
>>> doit(4,3.0)
(1.3333333333333333, 1.0)
>>> doit(4,2)
(2.0, 2)
"""
return x/y, x//y return x/y, x//y
def doit_inplace(x,y):
"""
>>> doit_inplace(1,2)
0.5
"""
x /= y
return x
def doit_inplace_floor(x,y):
"""
>>> doit_inplace_floor(1,2)
0
"""
x //= y
return x
def constants(): def constants():
"""
>>> constants()
(0.5, 0, 2.5, 2.0, 2.5, 2)
"""
return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2 return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2
def py_mix(a): def py_mix(a):
"""
>>> py_mix(1)
(0.5, 0, 0.5, 0.0, 0.5, 0)
>>> py_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
"""
return a/2, a//2, a/2.0, a//2.0, a/2, a//2 return a/2, a//2, a/2.0, a//2.0, a/2, a//2
def py_mix_rev(a): def py_mix_rev(a):
"""
>>> py_mix_rev(4)
(0.25, 0, 1.25, 1.0, 1.25, 1)
>>> py_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
"""
return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a
def int_mix(int a): def int_mix(int a):
"""
>>> int_mix(1)
(0.5, 0, 0.5, 0.0, 0.5, 0)
"""
return a/2, a//2, a/2.0, a//2.0, a/2, a//2 return a/2, a//2, a/2.0, a//2.0, a/2, a//2
def int_mix_rev(int a): def int_mix_rev(int a):
"""
>>> int_mix_rev(4)
(0.25, 0, 1.25, 1.0, 1.25, 1)
"""
return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a
def float_mix(float a): def float_mix(float a):
"""
>>> float_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
"""
return a/2, a//2, a/2.0, a//2.0, a/2, a//2 return a/2, a//2, a/2.0, a//2.0, a/2, a//2
def float_mix_rev(float a): def float_mix_rev(float a):
"""
>>> float_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
"""
return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a
__doc__ = u"""
>>> s == s_interned
True
>>> intern(s) is s_interned
True
>>> intern('abc') is s_interned
True
>>> intern('abc') is s_interned_dynamic
True
"""
s = 'abc'
s_interned = intern(s)
s_interned_dynamic = intern('a'+'b'+'c')
__doc__ = u""" __doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items()) >>> sorted( get_locals(1,2,3, k=5) .items())
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)] [('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
"""
import sys >>> in_locals('z')
IS_PY3 = sys.version_info[0] >= 3 True
>>> in_locals('args')
True
>>> in_locals('X')
False
"""
def get_locals(x, *args, **kwds): def get_locals(x, *args, **kwds):
cdef int z = 5 cdef int z = 5
if IS_PY3: y = "hi"
y = u"hi"
else:
y = "hi"
return locals() return locals()
def in_locals(x, *args, **kwds):
cdef int z = 5
y = "hi"
return x in locals()
def sorted(it): def sorted(it):
l = list(it) l = list(it)
l.sort() l.sort()
......
__doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items())
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
>>> sorted(get_locals_items(1,2,3, k=5))
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
>>> sorted(get_locals_items_listcomp(1,2,3, k=5))
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
"""
def get_locals(x, *args, **kwds):
cdef int z = 5
y = "hi"
return locals()
def get_locals_items(x, *args, **kwds):
cdef int z = 5
y = "hi"
return locals().items()
def get_locals_items_listcomp(x, *args, **kwds):
cdef int z = 5
y = "hi"
return [ item for item in locals().items() ]
def sorted(it):
l = list(it)
l.sort()
return l
__doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items())
[('args', (2, 3)), ('kwds', {'k': 5}), ('x', 1), ('y', 'hi'), ('z', 5)]
>>> get_locals_rebound(1,2,3)
'REBOUND'
"""
def get_locals(x, *args, **kwds):
cdef int z = 5
y = "hi"
return locals()
def get_locals_rebound(x, *args, **kwds):
cdef int z = 5
locals = _locals
y = "hi"
return locals()
def _locals(): return "REBOUND"
def sorted(it):
l = list(it)
l.sort()
return l
# Py2.x mixed true-div/floor-div behaviour of '/' operator # Py2.x mixed true-div/floor-div behaviour of '/' operator
__doc__ = u"""
>>> doit(1,2)
(0, 0)
>>> doit(4,3)
(1, 1)
>>> doit(4,3.0)
(1.3333333333333333, 1.0)
>>> doit(4,2)
(2, 2)
>>> constants()
(0, 0, 2.5, 2.0, 2, 2)
>>> py_mix(1)
(0, 0, 0.5, 0.0, 0, 0)
>>> py_mix_rev(4)
(0, 0, 1.25, 1.0, 1, 1)
>>> py_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
>>> py_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
>>> int_mix(1)
(0, 0, 0.5, 0.0, 0, 0)
>>> int_mix_rev(4)
(0, 0, 1.25, 1.0, 1, 1)
>>> float_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
>>> float_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
"""
def doit(x,y): def doit(x,y):
"""
>>> doit(1,2)
(0, 0)
>>> doit(4,3)
(1, 1)
>>> doit(4,3.0)
(1.3333333333333333, 1.0)
>>> doit(4,2)
(2, 2)
"""
return x/y, x//y return x/y, x//y
def doit_inplace(x,y):
"""
>>> doit_inplace(1,2)
0
"""
x /= y
return x
def doit_inplace_floor(x,y):
"""
>>> doit_inplace_floor(1,2)
0
"""
x //= y
return x
def constants(): def constants():
"""
>>> constants()
(0, 0, 2.5, 2.0, 2, 2)
"""
return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2 return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2
def py_mix(a): def py_mix(a):
"""
>>> py_mix(1)
(0, 0, 0.5, 0.0, 0, 0)
>>> py_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
"""
return a/2, a//2, a/2.0, a//2.0, a/2, a//2 return a/2, a//2, a/2.0, a//2.0, a/2, a//2
def py_mix_rev(a): def py_mix_rev(a):
"""
>>> py_mix_rev(4)
(0, 0, 1.25, 1.0, 1, 1)
>>> py_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
"""
return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a
def int_mix(int a): def int_mix(int a):
"""
>>> int_mix(1)
(0, 0, 0.5, 0.0, 0, 0)
"""
return a/2, a//2, a/2.0, a//2.0, a/2, a//2 return a/2, a//2, a/2.0, a//2.0, a/2, a//2
def int_mix_rev(int a): def int_mix_rev(int a):
"""
>>> int_mix_rev(4)
(0, 0, 1.25, 1.0, 1, 1)
"""
return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a
def float_mix(float a): def float_mix(float a):
"""
>>> float_mix(1.0)
(0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
"""
return a/2, a//2, a/2.0, a//2.0, a/2, a//2 return a/2, a//2, a/2.0, a//2.0, a/2, a//2
def float_mix_rev(float a): def float_mix_rev(float a):
"""
>>> float_mix_rev(4.0)
(0.25, 0.0, 1.25, 1.0, 1.25, 1.0)
"""
return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a return 1/a, 1//a, 5.0/a, 5.0//a, 5/a, 5//a
__doc__ = u"""
>>> swap(1,2)
(2, 1)
"""
cimport cython
@cython.test_assert_path_exists(
"//ParallelAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]/NameNode",
)
@cython.test_fail_if_path_exists(
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]",
)
def swap(a,b): def swap(a,b):
"""
>>> swap(1,2)
(2, 1)
"""
a,b = b,a a,b = b,a
return a,b return a,b
@cython.test_assert_path_exists(
"//ParallelAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]/NameNode",
)
@cython.test_fail_if_path_exists(
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]",
)
def swap5(a,b,c,d,e):
"""
>>> swap5(1,2,3,4,5)
(5, 4, 3, 2, 1)
"""
a,b,c,d,e = e,d,c,b,a
return a,b,c,d,e
@cython.test_assert_path_exists(
"//ParallelAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]/NameNode",
)
@cython.test_fail_if_path_exists(
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]",
)
cdef bint c_swap_cmp5(a, b, c, d, e):
a,b,c,d,e = e,d,c,b,a
return a > b > c > d > e
def swap_cmp5(a,b,c,d,e):
"""
>>> swap_cmp5(1,2,3,4,5)
True
"""
return c_swap_cmp5(a,b,c,d,e)
@cython.test_assert_path_exists(
"//ParallelAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode/NameNode",
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=True]/NameNode",
)
@cython.test_fail_if_path_exists(
"//ParallelAssignmentNode/SingleAssignmentNode//CoerceToTempNode[@use_managed_ref=False]",
)
def swap_py(a,b):
a,a = b,a
return a,b
@cython.test_assert_path_exists(
# "//ParallelAssignmentNode",
# "//ParallelAssignmentNode/SingleAssignmentNode",
# "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode",
# "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=False]",
)
@cython.test_fail_if_path_exists(
# "//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=True]",
)
def swap_list_items(list a, int i, int j):
"""
>>> l = [1,2,3,4]
>>> swap_list_items(l, 1, 2)
>>> l
[1, 3, 2, 4]
>>> swap_list_items(l, 3, 0)
>>> l
[4, 3, 2, 1]
>>> swap_list_items(l, 0, 5)
Traceback (most recent call last):
IndexError: list index out of range
>>> l
[4, 3, 2, 1]
"""
a[i], a[j] = a[j], a[i]
@cython.test_assert_path_exists(
"//ParallelAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode//IndexNode",
"//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=True]",
)
@cython.test_fail_if_path_exists(
"//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=False]",
)
def swap_list_items_py1(list a, int i, int j):
a[i], a[j] = a[j+1], a[i]
@cython.test_assert_path_exists(
"//ParallelAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode",
"//ParallelAssignmentNode/SingleAssignmentNode//IndexNode",
"//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=True]",
)
@cython.test_fail_if_path_exists(
"//ParallelAssignmentNode/SingleAssignmentNode//IndexNode[@use_managed_ref=False]",
)
def swap_list_items_py2(list a, int i, int j):
a[i], a[j] = a[i], a[i]
#cython: autotestdict=True
cdef class Foo:
pass
cdef class SubFoo(Foo):
pass
cdef class Bar:
pass
def foo1(arg):
"""
>>> foo1(Foo())
>>> foo1(SubFoo())
>>> foo1(None)
>>> foo1(123)
>>> foo1(Bar())
"""
cdef Foo val = <Foo>arg
def foo2(arg):
"""
>>> foo2(Foo())
>>> foo2(SubFoo())
>>> foo2(None)
>>> foo2(123)
Traceback (most recent call last):
...
TypeError: Cannot convert int to typetest_T417.Foo
>>> foo2(Bar())
Traceback (most recent call last):
...
TypeError: Cannot convert typetest_T417.Bar to typetest_T417.Foo
"""
cdef Foo val = arg
def foo3(arg):
"""
>>> foo3(Foo())
>>> foo3(SubFoo())
>>> foo3(None)
Traceback (most recent call last):
...
TypeError: Cannot convert NoneType to typetest_T417.Foo
>>> foo3(123)
Traceback (most recent call last):
...
TypeError: Cannot convert int to typetest_T417.Foo
>>> foo2(Bar())
Traceback (most recent call last):
...
TypeError: Cannot convert typetest_T417.Bar to typetest_T417.Foo
"""
cdef val = <Foo?>arg
cdef int count = 0
cdef object getFoo():
global count
count += 1
return Foo()
def test_getFoo():
"""
>>> test_getFoo()
1
"""
cdef int old_count = count
cdef Foo x = getFoo()
return count - old_count
def test_getFooCast():
"""
>>> test_getFooCast()
1
"""
cdef int old_count = count
cdef Foo x = <Foo?>getFoo()
return count - old_count
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