Commit e842344f authored by Stefan Behnel's avatar Stefan Behnel

merge

parents a5e49f6e ddc68024
...@@ -943,6 +943,15 @@ class CCodeWriter(object): ...@@ -943,6 +943,15 @@ class CCodeWriter(object):
def put_finish_refcount_context(self): def put_finish_refcount_context(self):
self.putln("__Pyx_FinishRefcountContext();") self.putln("__Pyx_FinishRefcountContext();")
def put_trace_call(self, name, pos):
self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]));
def put_trace_exception(self):
self.putln("__Pyx_TraceException();")
def put_trace_return(self, retvalue_cname):
self.putln("__Pyx_TraceReturn(%s);" % retvalue_cname)
class PyrexCodeWriter(object): class PyrexCodeWriter(object):
# f file output file # f file output file
......
...@@ -2578,6 +2578,9 @@ class GeneralCallNode(CallNode): ...@@ -2578,6 +2578,9 @@ class GeneralCallNode(CallNode):
if self.starstar_arg: if self.starstar_arg:
self.starstar_arg.analyse_types(env) self.starstar_arg.analyse_types(env)
if not self.function.type.is_pyobject: if not self.function.type.is_pyobject:
if self.function.type.is_error:
self.type = error_type
return error_type
if hasattr(self.function, 'entry') and not self.function.entry.as_variable: if hasattr(self.function, 'entry') and not self.function.entry.as_variable:
error(self.pos, "Keyword arguments not allowed in cdef functions.") error(self.pos, "Keyword arguments not allowed in cdef functions.")
else: else:
...@@ -2592,6 +2595,7 @@ class GeneralCallNode(CallNode): ...@@ -2592,6 +2595,7 @@ class GeneralCallNode(CallNode):
self.is_temp = 1 self.is_temp = 1
def generate_result_code(self, code): def generate_result_code(self, code):
if self.type.is_error: return
if self.keyword_args and self.starstar_arg: if self.keyword_args and self.starstar_arg:
code.put_error_if_neg(self.pos, code.put_error_if_neg(self.pos,
"PyDict_Update(%s, %s)" % ( "PyDict_Update(%s, %s)" % (
......
...@@ -573,6 +573,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -573,6 +573,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static PyObject *%s;' % env.module_cname) code.putln('static PyObject *%s;' % env.module_cname)
code.putln('static PyObject *%s;' % Naming.builtins_cname) code.putln('static PyObject *%s;' % Naming.builtins_cname)
code.putln('static PyObject *%s;' % Naming.empty_tuple) code.putln('static PyObject *%s;' % Naming.empty_tuple)
code.putln('static PyObject *%s;' % Naming.empty_bytes)
if Options.pre_import is not None: if Options.pre_import is not None:
code.putln('static PyObject *%s;' % Naming.preimport_cname) code.putln('static PyObject *%s;' % Naming.preimport_cname)
code.putln('static int %s;' % Naming.lineno_cname) code.putln('static int %s;' % Naming.lineno_cname)
...@@ -588,8 +589,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -588,8 +589,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static char %s[] = "%s";' % ( code.putln('static char %s[] = "%s";' % (
env.doc_cname, escape_byte_string(docstr))) env.doc_cname, escape_byte_string(docstr)))
env.use_utility_code(streq_utility_code)
# XXX this is a mess # XXX this is a mess
for utility_code in PyrexTypes.c_int_from_py_function.specialize_list: for utility_code in PyrexTypes.c_int_from_py_function.specialize_list:
env.use_utility_code(utility_code) env.use_utility_code(utility_code)
...@@ -1556,6 +1555,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1556,6 +1555,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname) code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
def generate_import_star(self, env, code): def generate_import_star(self, env, code):
env.use_utility_code(streq_utility_code)
code.putln() code.putln()
code.putln("char* %s_type_names[] = {" % Naming.import_star) code.putln("char* %s_type_names[] = {" % Naming.import_star)
for name, entry in env.entries.items(): for name, entry in env.entries.items():
...@@ -1648,6 +1648,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1648,6 +1648,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("#endif") code.putln("#endif")
code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos))); code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
code.putln("#if PY_MAJOR_VERSION < 3");
code.putln("%s = PyString_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
code.putln("#else");
code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
code.putln("#endif");
code.putln("/*--- Library function declarations ---*/") code.putln("/*--- Library function declarations ---*/")
env.generate_library_function_declarations(code) env.generate_library_function_declarations(code)
...@@ -2475,6 +2480,7 @@ static __Pyx_RefnannyAPIStruct *__Pyx_Refnanny = NULL; ...@@ -2475,6 +2480,7 @@ static __Pyx_RefnannyAPIStruct *__Pyx_Refnanny = NULL;
#define __Pyx_XGOTREF(r) if((r) == NULL) ; else __Pyx_GOTREF(r) #define __Pyx_XGOTREF(r) if((r) == NULL) ; else __Pyx_GOTREF(r)
""") """)
main_method = UtilityCode( main_method = UtilityCode(
impl = """ impl = """
#if PY_MAJOR_VERSION < 3 || (!defined(WIN32) && !defined(MS_WINDOWS)) #if PY_MAJOR_VERSION < 3 || (!defined(WIN32) && !defined(MS_WINDOWS))
......
...@@ -74,6 +74,7 @@ c_api_tab_cname = pyrex_prefix + "c_api_tab" ...@@ -74,6 +74,7 @@ c_api_tab_cname = pyrex_prefix + "c_api_tab"
gilstate_cname = pyrex_prefix + "state" gilstate_cname = pyrex_prefix + "state"
skip_dispatch_cname = pyrex_prefix + "skip_dispatch" skip_dispatch_cname = pyrex_prefix + "skip_dispatch"
empty_tuple = pyrex_prefix + "empty_tuple" empty_tuple = pyrex_prefix + "empty_tuple"
empty_bytes = pyrex_prefix + "empty_bytes"
print_function = pyrex_prefix + "print" print_function = pyrex_prefix + "print"
print_function_kwargs = pyrex_prefix + "print_kwargs" print_function_kwargs = pyrex_prefix + "print_kwargs"
cleanup_cname = pyrex_prefix + "module_cleanup" cleanup_cname = pyrex_prefix + "module_cleanup"
...@@ -83,6 +84,8 @@ import_star = pyrex_prefix + "import_star" ...@@ -83,6 +84,8 @@ import_star = pyrex_prefix + "import_star"
import_star_set = pyrex_prefix + "import_star_set" import_star_set = pyrex_prefix + "import_star_set"
cur_scope_cname = pyrex_prefix + "cur_scope" cur_scope_cname = pyrex_prefix + "cur_scope"
enc_scope_cname = pyrex_prefix + "enc_scope" enc_scope_cname = pyrex_prefix + "enc_scope"
frame_cname = pyrex_prefix + "frame"
frame_code_cname = pyrex_prefix + "frame_code"
line_c_macro = "__LINE__" line_c_macro = "__LINE__"
......
...@@ -801,25 +801,18 @@ class CVarDefNode(StatNode): ...@@ -801,25 +801,18 @@ class CVarDefNode(StatNode):
self.dest_scope = dest_scope self.dest_scope = dest_scope
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
need_property = False # If the field is an external typedef, we cannot be sure about the type,
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
if (dest_scope.is_c_class_scope if (dest_scope.is_c_class_scope
and self.visibility == 'public' and self.visibility == 'public'
and base_type.is_pyobject and base_type.is_pyobject
and (base_type.is_builtin_type or base_type.is_extension_type)): and (base_type.is_builtin_type or base_type.is_extension_type)):
# If the field is settable and extension type, then the CPython mechanism does self.need_properties = []
# not do enough type-checking for us.
need_property = True
elif (base_type.is_typedef and base_type.typedef_is_external
and (self.visibility in ('public', 'readonly'))):
# If the field is an external typedef, we cannot be sure about the type,
# so do conversion ourself rather than rely on the CPython mechanism (through
# a property; made in AnalyseDeclarationsTransform).
need_property = True need_property = True
if need_property:
visibility = 'private' visibility = 'private'
self.need_properties = []
else: else:
need_property = False
visibility = self.visibility visibility = self.visibility
for declarator in self.declarators: for declarator in self.declarators:
...@@ -1009,6 +1002,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1009,6 +1002,7 @@ class FuncDefNode(StatNode, BlockNode):
py_func = None py_func = None
assmt = None assmt = None
needs_closure = False needs_closure = False
modifiers = []
def analyse_default_values(self, env): def analyse_default_values(self, env):
genv = env.global_scope() genv = env.global_scope()
...@@ -1062,6 +1056,15 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1062,6 +1056,15 @@ class FuncDefNode(StatNode, BlockNode):
is_getbuffer_slot = (self.entry.name == "__getbuffer__" and is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
self.entry.scope.is_c_class_scope) self.entry.scope.is_c_class_scope)
if code.globalstate.directives['profile'] is None:
profile = 'inline' not in self.modifiers and not lenv.nogil
else:
profile = code.globalstate.directives['profile']
if profile and lenv.nogil:
error(self.pos, "Cannot profile nogil function.")
if profile:
code.globalstate.use_utility_code(trace_utility_code)
# Generate C code for header and body of function # Generate C code for header and body of function
code.enter_cfunc_scope() code.enter_cfunc_scope()
code.return_from_error_cleanup_label = code.new_label() code.return_from_error_cleanup_label = code.new_label()
...@@ -1108,6 +1111,8 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1108,6 +1111,8 @@ class FuncDefNode(StatNode, BlockNode):
env.use_utility_code(force_init_threads_utility_code) env.use_utility_code(force_init_threads_utility_code)
code.putln("PyGILState_STATE _save = PyGILState_Ensure();") code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
# ----- Automatic lead-ins for certain special functions # ----- Automatic lead-ins for certain special functions
if profile:
code.put_trace_call(self.entry.name, self.pos)
if not lenv.nogil: if not lenv.nogil:
code.put_setup_refcount_context(self.entry.name) code.put_setup_refcount_context(self.entry.name)
if is_getbuffer_slot: if is_getbuffer_slot:
...@@ -1172,6 +1177,9 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1172,6 +1177,9 @@ class FuncDefNode(StatNode, BlockNode):
err_val = self.error_value() err_val = self.error_value()
exc_check = self.caller_will_check_exceptions() exc_check = self.caller_will_check_exceptions()
if err_val is not None or exc_check: if err_val is not None or exc_check:
# TODO: Fix exception tracing (though currently unused by cProfile).
# code.globalstate.use_utility_code(get_exception_tuple_utility_code)
# code.put_trace_exception()
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name) code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
else: else:
warning(self.entry.pos, "Unraisable exception in function '%s'." \ warning(self.entry.pos, "Unraisable exception in function '%s'." \
...@@ -1201,9 +1209,6 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1201,9 +1209,6 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Non-error return cleanup # ----- Non-error return cleanup
# If you add anything here, remember to add a condition to the
# if-test above in the error block (so that it can jump past this
# block).
code.put_label(code.return_label) code.put_label(code.return_label)
for entry in lenv.buffer_entries: for entry in lenv.buffer_entries:
if entry.used: if entry.used:
...@@ -1235,6 +1240,17 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1235,6 +1240,17 @@ class FuncDefNode(StatNode, BlockNode):
code.put_finish_refcount_context() code.put_finish_refcount_context()
if self.entry.is_special and self.entry.name == "__hash__":
# Returning -1 for __hash__ is supposed to signal an error
# We do as Python instances and coerce -1 into -2.
code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (Naming.retval_cname, Naming.retval_cname))
if profile:
if self.return_type.is_pyobject:
code.put_trace_return(Naming.retval_cname)
else:
code.put_trace_return("Py_None")
if acquire_gil: if acquire_gil:
code.putln("PyGILState_Release(_save);") code.putln("PyGILState_Release(_save);")
...@@ -1334,7 +1350,7 @@ class CFuncDefNode(FuncDefNode): ...@@ -1334,7 +1350,7 @@ class CFuncDefNode(FuncDefNode):
return self.entry.name return self.entry.name
def analyse_declarations(self, env): def analyse_declarations(self, env):
directive_locals = self.directive_locals = env.directives['locals'] self.directive_locals.update(env.directives['locals'])
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
# The 2 here is because we need both function and argument names. # The 2 here is because we need both function and argument names.
name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None)) name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
...@@ -5414,7 +5430,6 @@ static void __Pyx_AddTraceback(const char *funcname) { ...@@ -5414,7 +5430,6 @@ static void __Pyx_AddTraceback(const char *funcname) {
PyObject *py_srcfile = 0; PyObject *py_srcfile = 0;
PyObject *py_funcname = 0; PyObject *py_funcname = 0;
PyObject *py_globals = 0; PyObject *py_globals = 0;
PyObject *empty_string = 0;
PyCodeObject *py_code = 0; PyCodeObject *py_code = 0;
PyFrameObject *py_frame = 0; PyFrameObject *py_frame = 0;
...@@ -5441,12 +5456,6 @@ static void __Pyx_AddTraceback(const char *funcname) { ...@@ -5441,12 +5456,6 @@ static void __Pyx_AddTraceback(const char *funcname) {
if (!py_funcname) goto bad; if (!py_funcname) goto bad;
py_globals = PyModule_GetDict(%(GLOBALS)s); py_globals = PyModule_GetDict(%(GLOBALS)s);
if (!py_globals) goto bad; if (!py_globals) goto bad;
#if PY_MAJOR_VERSION < 3
empty_string = PyString_FromStringAndSize("", 0);
#else
empty_string = PyBytes_FromStringAndSize("", 0);
#endif
if (!empty_string) goto bad;
py_code = PyCode_New( py_code = PyCode_New(
0, /*int argcount,*/ 0, /*int argcount,*/
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
...@@ -5455,7 +5464,7 @@ static void __Pyx_AddTraceback(const char *funcname) { ...@@ -5455,7 +5464,7 @@ static void __Pyx_AddTraceback(const char *funcname) {
0, /*int nlocals,*/ 0, /*int nlocals,*/
0, /*int stacksize,*/ 0, /*int stacksize,*/
0, /*int flags,*/ 0, /*int flags,*/
empty_string, /*PyObject *code,*/ %(EMPTY_BYTES)s, /*PyObject *code,*/
%(EMPTY_TUPLE)s, /*PyObject *consts,*/ %(EMPTY_TUPLE)s, /*PyObject *consts,*/
%(EMPTY_TUPLE)s, /*PyObject *names,*/ %(EMPTY_TUPLE)s, /*PyObject *names,*/
%(EMPTY_TUPLE)s, /*PyObject *varnames,*/ %(EMPTY_TUPLE)s, /*PyObject *varnames,*/
...@@ -5464,7 +5473,7 @@ static void __Pyx_AddTraceback(const char *funcname) { ...@@ -5464,7 +5473,7 @@ static void __Pyx_AddTraceback(const char *funcname) {
py_srcfile, /*PyObject *filename,*/ py_srcfile, /*PyObject *filename,*/
py_funcname, /*PyObject *name,*/ py_funcname, /*PyObject *name,*/
%(LINENO)s, /*int firstlineno,*/ %(LINENO)s, /*int firstlineno,*/
empty_string /*PyObject *lnotab*/ %(EMPTY_BYTES)s /*PyObject *lnotab*/
); );
if (!py_code) goto bad; if (!py_code) goto bad;
py_frame = PyFrame_New( py_frame = PyFrame_New(
...@@ -5479,7 +5488,6 @@ static void __Pyx_AddTraceback(const char *funcname) { ...@@ -5479,7 +5488,6 @@ static void __Pyx_AddTraceback(const char *funcname) {
bad: bad:
Py_XDECREF(py_srcfile); Py_XDECREF(py_srcfile);
Py_XDECREF(py_funcname); Py_XDECREF(py_funcname);
Py_XDECREF(empty_string);
Py_XDECREF(py_code); Py_XDECREF(py_code);
Py_XDECREF(py_frame); Py_XDECREF(py_frame);
} }
...@@ -5490,6 +5498,7 @@ bad: ...@@ -5490,6 +5498,7 @@ bad:
'CLINENO': Naming.clineno_cname, 'CLINENO': Naming.clineno_cname,
'GLOBALS': Naming.module_cname, 'GLOBALS': Naming.module_cname,
'EMPTY_TUPLE' : Naming.empty_tuple, 'EMPTY_TUPLE' : Naming.empty_tuple,
'EMPTY_BYTES' : Naming.empty_bytes,
}) })
restore_exception_utility_code = UtilityCode( restore_exception_utility_code = UtilityCode(
...@@ -5704,6 +5713,31 @@ bad: ...@@ -5704,6 +5713,31 @@ bad:
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
get_exception_tuple_utility_code = UtilityCode(proto="""
static PyObject *__Pyx_GetExceptionTuple(void); /*proto*/
""",
impl = """
static PyObject *__Pyx_GetExceptionTuple(void) {
PyObject *type = NULL, *value = NULL, *tb = NULL;
if (__Pyx_GetException(&type, &value, &tb) == 0) {
PyObject* exc_info = PyTuple_New(3);
if (exc_info) {
Py_INCREF(type);
Py_INCREF(value);
Py_INCREF(tb);
PyTuple_SET_ITEM(exc_info, 0, type);
PyTuple_SET_ITEM(exc_info, 1, value);
PyTuple_SET_ITEM(exc_info, 2, tb);
return exc_info;
}
}
return NULL;
}
""",
requires=[get_exception_utility_code])
#------------------------------------------------------------------------------------
reset_exception_utility_code = UtilityCode( reset_exception_utility_code = UtilityCode(
proto = """ proto = """
static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ static INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
...@@ -5749,3 +5783,143 @@ proto=""" ...@@ -5749,3 +5783,143 @@ proto="""
""") """)
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
# Note that cPython ignores PyTrace_EXCEPTION,
# but maybe some other profilers don't.
trace_utility_code = UtilityCode(proto="""
#ifndef CYTHON_TRACING
#define CYTHON_TRACING 1
#endif
#ifndef CYTHON_TRACING_REUSE_FRAME
#define CYTHON_TRACING_REUSE_FRAME 0
#endif
#if CYTHON_TRACING
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"
#if CYTHON_TRACING_REUSE_FRAME
#define CYTHON_FRAME_MODIFIER static
#define CYTHON_FRAME_DEL
#else
#define CYTHON_FRAME_MODIFIER
#define CYTHON_FRAME_DEL Py_DECREF(%(FRAME)s)
#endif
#define __Pyx_TraceCall(funcname, srcfile, firstlineno) \\
static PyCodeObject *%(FRAME_CODE)s = NULL; \\
CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL; \\
int __Pyx_use_tracing = 0; \\
if (PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
__Pyx_use_tracing = __Pyx_TraceSetupAndCall(&%(FRAME_CODE)s, &%(FRAME)s, funcname, srcfile, firstlineno); \\
}
#define __Pyx_TraceException() \\
if (__Pyx_use_tracing && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
PyObject *exc_info = __Pyx_GetExceptionTuple(); \\
if (exc_info) { \\
PyThreadState_GET()->c_profilefunc( \\
PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_EXCEPTION, exc_info); \\
Py_DECREF(exc_info); \\
} \\
}
#define __Pyx_TraceReturn(result) \\
if (__Pyx_use_tracing && PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc) { \\
PyThreadState_GET()->c_profilefunc( \\
PyThreadState_GET()->c_profileobj, %(FRAME)s, PyTrace_RETURN, (PyObject*)result); \\
CYTHON_FRAME_DEL; \\
}
static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno); /*proto*/
static int __Pyx_TraceSetupAndCall(PyCodeObject** code, PyFrameObject** frame, const char *funcname, const char *srcfile, int firstlineno); /*proto*/
#else
#define __Pyx_TraceCall(funcname, srcfile, firstlineno)
#define __Pyx_TraceException()
#define __Pyx_TraceReturn(result)
#endif /* CYTHON_TRACING */
"""
% {
"FRAME": Naming.frame_cname,
"FRAME_CODE": Naming.frame_code_cname,
},
impl = """
#if CYTHON_TRACING
static int __Pyx_TraceSetupAndCall(PyCodeObject** code,
PyFrameObject** frame,
const char *funcname,
const char *srcfile,
int firstlineno) {
if (*frame == NULL || !CYTHON_TRACING_REUSE_FRAME) {
if (*code == NULL) {
*code = __Pyx_createFrameCodeObject(funcname, srcfile, firstlineno);
if (*code == NULL) return 0;
}
*frame = PyFrame_New(
PyThreadState_GET(), /*PyThreadState *tstate*/
*code, /*PyCodeObject *code*/
PyModule_GetDict(%(MODULE)s), /*PyObject *globals*/
0 /*PyObject *locals*/
);
if (*frame == NULL) return 0;
}
else {
(*frame)->f_tstate = PyThreadState_GET();
}
return PyThreadState_GET()->c_profilefunc(PyThreadState_GET()->c_profileobj, *frame, PyTrace_CALL, NULL) == 0;
}
static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const char *srcfile, int firstlineno) {
PyObject *py_srcfile = 0;
PyObject *py_funcname = 0;
PyCodeObject *py_code = 0;
#if PY_MAJOR_VERSION < 3
py_funcname = PyString_FromString(funcname);
py_srcfile = PyString_FromString(srcfile);
#else
py_funcname = PyUnicode_FromString(funcname);
py_srcfile = PyUnicode_FromString(srcfile);
#endif
if (!py_funcname | !py_srcfile) goto bad;
py_code = PyCode_New(
0, /*int argcount,*/
#if PY_MAJOR_VERSION >= 3
0, /*int kwonlyargcount,*/
#endif
0, /*int nlocals,*/
0, /*int stacksize,*/
0, /*int flags,*/
%(EMPTY_BYTES)s, /*PyObject *code,*/
%(EMPTY_TUPLE)s, /*PyObject *consts,*/
%(EMPTY_TUPLE)s, /*PyObject *names,*/
%(EMPTY_TUPLE)s, /*PyObject *varnames,*/
%(EMPTY_TUPLE)s, /*PyObject *freevars,*/
%(EMPTY_TUPLE)s, /*PyObject *cellvars,*/
py_srcfile, /*PyObject *filename,*/
py_funcname, /*PyObject *name,*/
firstlineno, /*int firstlineno,*/
%(EMPTY_BYTES)s /*PyObject *lnotab*/
);
bad:
Py_XDECREF(py_srcfile);
Py_XDECREF(py_funcname);
return py_code;
}
#endif /* CYTHON_TRACING */
""" % {
'EMPTY_TUPLE' : Naming.empty_tuple,
'EMPTY_BYTES' : Naming.empty_bytes,
"MODULE": Naming.module_cname,
})
...@@ -67,10 +67,11 @@ option_defaults = { ...@@ -67,10 +67,11 @@ option_defaults = {
'wraparound' : True, 'wraparound' : True,
'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this... 'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this...
'callspec' : "", 'callspec' : "",
'profile': None,
} }
# Override types possibilities above, if needed # Override types possibilities above, if needed
option_types = { } option_types = { 'profile': bool }
for key, val in option_defaults.items(): for key, val in option_defaults.items():
if key not in option_types: if key not in option_types:
......
...@@ -625,12 +625,6 @@ property NAME: ...@@ -625,12 +625,6 @@ property NAME:
ATTR = value ATTR = value
""", level='c_class') """, level='c_class')
readonly_property = TreeFragment(u"""
property NAME:
def __get__(self):
return ATTR
""", level='c_class')
def __call__(self, root): def __call__(self, root):
self.env_stack = [root.scope] self.env_stack = [root.scope]
# needed to determine if a cdef var is declared after it's used. # needed to determine if a cdef var is declared after it's used.
...@@ -707,7 +701,7 @@ property NAME: ...@@ -707,7 +701,7 @@ property NAME:
# mechanism for them. # mechanism for them.
stats = [] stats = []
for entry in node.need_properties: for entry in node.need_properties:
property = self.create_Property(entry, node.visibility == 'readonly') property = self.create_Property(entry)
property.analyse_declarations(node.dest_scope) property.analyse_declarations(node.dest_scope)
self.visit(property) self.visit(property)
stats.append(property) stats.append(property)
...@@ -715,10 +709,7 @@ property NAME: ...@@ -715,10 +709,7 @@ property NAME:
else: else:
return None return None
def create_Property(self, entry, readonly): def create_Property(self, entry):
if readonly:
template = self.readonly_property
else:
template = self.basic_property template = self.basic_property
property = template.substitute({ property = template.substitute({
u"ATTR": AttributeNode(pos=entry.pos, u"ATTR": AttributeNode(pos=entry.pos,
......
...@@ -171,6 +171,19 @@ class CTypedefType(BaseType): ...@@ -171,6 +171,19 @@ class CTypedefType(BaseType):
self.typedef_base_type = base_type self.typedef_base_type = base_type
self.typedef_is_external = is_external self.typedef_is_external = is_external
# Make typecodes in external typedefs use typesize-neutral macros
if is_external:
typecode = None
if base_type.is_int:
if base_type.signed == 0:
typecode = "__Pyx_T_UNSIGNED_INT"
else:
typecode = "__Pyx_T_SIGNED_INT"
elif base_type.is_float and not rank_to_type_name[base_type.rank] == "long double":
typecode = "__Pyx_T_FLOATING"
if typecode:
self.pymemberdef_typecode = "%s(%s)" % (typecode, cname)
def resolve(self): def resolve(self):
return self.typedef_base_type.resolve() return self.typedef_base_type.resolve()
...@@ -814,13 +827,14 @@ static %(type)s __pyx_PyObject_As_%(type_name)s(PyObject* o); /* proto */ ...@@ -814,13 +827,14 @@ static %(type)s __pyx_PyObject_As_%(type_name)s(PyObject* o); /* proto */
""", """,
impl=""" impl="""
static %(type)s __pyx_PyObject_As_%(type_name)s(PyObject* o) { static %(type)s __pyx_PyObject_As_%(type_name)s(PyObject* o) {
if (PyComplex_Check(o)) { if (PyComplex_CheckExact(o)) {
return %(type_name)s_from_parts( return %(type_name)s_from_parts(
(%(real_type)s)((PyComplexObject *)o)->cval.real, (%(real_type)s)((PyComplexObject *)o)->cval.real,
(%(real_type)s)((PyComplexObject *)o)->cval.imag); (%(real_type)s)((PyComplexObject *)o)->cval.imag);
} }
else { else {
return %(type_name)s_from_parts(%(type_convert)s(o), 0); Py_complex cval = PyComplex_AsCComplex(o);
return %(type_name)s_from_parts((%(real_type)s)cval.real, (%(real_type)s)cval.imag);
} }
} }
""") """)
...@@ -1726,6 +1740,40 @@ static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); ...@@ -1726,6 +1740,40 @@ static INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
#endif #endif
#endif #endif
#if !defined(T_ULONGLONG)
#define __Pyx_T_UNSIGNED_INT(x) \\
((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : -1))))
#else
#define __Pyx_T_UNSIGNED_INT(x) \\
((sizeof(x) == sizeof(unsigned char)) ? T_UBYTE : \\
((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
((sizeof(x) == sizeof(unsigned int)) ? T_UINT : \\
((sizeof(x) == sizeof(unsigned long)) ? T_ULONG : \\
((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))))
#endif
#if !defined(T_LONGLONG)
#define __Pyx_T_SIGNED_INT(x) \\
((sizeof(x) == sizeof(char)) ? T_BYTE : \\
((sizeof(x) == sizeof(short)) ? T_SHORT : \\
((sizeof(x) == sizeof(int)) ? T_INT : \\
((sizeof(x) == sizeof(long)) ? T_LONG : -1))))
#else
#define __Pyx_T_SIGNED_INT(x) \\
((sizeof(x) == sizeof(char)) ? T_BYTE : \\
((sizeof(x) == sizeof(short)) ? T_SHORT : \\
((sizeof(x) == sizeof(int)) ? T_INT : \\
((sizeof(x) == sizeof(long)) ? T_LONG : \\
((sizeof(x) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))))
#endif
#define __Pyx_T_FLOATING(x) \\
((sizeof(x) == sizeof(float)) ? T_FLOAT : \\
((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1))
#if !defined(T_SIZET) #if !defined(T_SIZET)
#if !defined(T_ULONGLONG) #if !defined(T_ULONGLONG)
#define T_SIZET \\ #define T_SIZET \\
......
...@@ -1583,8 +1583,14 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/ ...@@ -1583,8 +1583,14 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
impl = """ impl = """
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) { static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
/* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */ /* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
/* if (!PyObject_TypeCheck(method, &PyMethodDescr_Type)) { */ static PyTypeObject *methoddescr_type = NULL;
if (__Pyx_StrEq(Py_TYPE(method)->tp_name, "method_descriptor")) { /* cdef classes */ if (methoddescr_type == NULL) {
PyObject *meth = __Pyx_GetAttrString((PyObject*)&PyList_Type, "append");
if (!meth) return NULL;
methoddescr_type = Py_TYPE(meth);
Py_DECREF(meth);
}
if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */
PyMethodDescrObject *descr = (PyMethodDescrObject *)method; PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
return PyDescr_NewClassMethod(descr->d_type, descr->d_method); return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
} }
......
cdef extern from "Python.h":
ctypedef struct PyObject
ctypedef struct Py_buffer:
void *buf
Py_ssize_t len
int readonly
char *format
int ndim
Py_ssize_t *shape
Py_ssize_t *strides
Py_ssize_t *suboffsets
Py_ssize_t itemsize
void *internal
int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) except -1
void PyObject_ReleaseBuffer(PyObject* obj, Py_buffer* view)
void PyErr_Format(int, char*, ...)
enum:
PyExc_TypeError
# int PyObject_GetBuffer(PyObject *obj, Py_buffer *view,
# int flags)
# NumPy static imports for Cython # NumPy static imports for Cython
# #
# If any of the PyArray_* functions are called, import_array must be
# called first.
#
# This also defines backwards-compatability buffer acquisition # This also defines backwards-compatability buffer acquisition
# code for use in Python 2.x (or Python <= 2.5 when NumPy starts # code for use in Python 2.x (or Python <= 2.5 when NumPy starts
# implementing PEP-3118 directly). # implementing PEP-3118 directly).
#
# Because of laziness, the format string of the buffer is statically # Because of laziness, the format string of the buffer is statically
# allocated. Increase the size if this is not enough, or submit a # allocated. Increase the size if this is not enough, or submit a
# patch to do this properly. # patch to do this properly.
#
# Author: Dag Sverre Seljebotn
#
DEF _buffer_format_string_len = 255 DEF _buffer_format_string_len = 255
cimport python_buffer as pybuf cimport python_buffer as pybuf
cimport stdlib cimport stdlib
cimport stdio
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef int Py_intptr_t ctypedef int Py_intptr_t
...@@ -20,43 +26,124 @@ cdef extern from "Python.h": ...@@ -20,43 +26,124 @@ cdef extern from "Python.h":
cdef extern from "numpy/arrayobject.h": cdef extern from "numpy/arrayobject.h":
ctypedef Py_intptr_t npy_intp ctypedef Py_intptr_t npy_intp
cdef enum: cdef enum NPY_TYPES:
NPY_BOOL, NPY_BOOL
NPY_BYTE, NPY_UBYTE, NPY_BYTE
NPY_SHORT, NPY_USHORT, NPY_UBYTE
NPY_INT, NPY_UINT, NPY_SHORT
NPY_LONG, NPY_ULONG, NPY_USHORT
NPY_LONGLONG, NPY_ULONGLONG, NPY_INT
NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE, NPY_UINT
NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE, NPY_LONG
NPY_OBJECT, NPY_ULONG
NPY_STRING, NPY_UNICODE, NPY_LONGLONG
NPY_VOID, NPY_ULONGLONG
NPY_NTYPES, NPY_FLOAT
NPY_NOTYPE, NPY_DOUBLE
NPY_CHAR, NPY_LONGDOUBLE
NPY_USERDEF, NPY_CFLOAT
NPY_CDOUBLE
NPY_C_CONTIGUOUS, NPY_CLONGDOUBLE
NPY_OBJECT
NPY_STRING
NPY_UNICODE
NPY_VOID
NPY_NTYPES
NPY_NOTYPE
enum NPY_ORDER:
NPY_ANYORDER
NPY_CORDER
NPY_FORTRANORDER
enum NPY_CLIPMODE:
NPY_CLIP
NPY_WRAP
NPY_RAISE
enum NPY_SCALARKIND:
NPY_NOSCALAR,
NPY_BOOL_SCALAR,
NPY_INTPOS_SCALAR,
NPY_INTNEG_SCALAR,
NPY_FLOAT_SCALAR,
NPY_COMPLEX_SCALAR,
NPY_OBJECT_SCALAR
enum NPY_SORTKIND:
NPY_QUICKSORT
NPY_HEAPSORT
NPY_MERGESORT
cdef enum requirements:
NPY_C_CONTIGUOUS
NPY_F_CONTIGUOUS NPY_F_CONTIGUOUS
NPY_CONTIGUOUS
NPY_FORTRAN
NPY_OWNDATA
NPY_FORCECAST
NPY_ENSURECOPY
NPY_ENSUREARRAY
NPY_ELEMENTSTRIDES
NPY_ALIGNED
NPY_NOTSWAPPED
NPY_WRITEABLE
NPY_UPDATEIFCOPY
NPY_ARR_HAS_DESCR
NPY_BEHAVED
NPY_BEHAVED_NS
NPY_CARRAY
NPY_CARRAY_RO
NPY_FARRAY
NPY_FARRAY_RO
NPY_DEFAULT
NPY_IN_ARRAY
NPY_OUT_ARRAY
NPY_INOUT_ARRAY
NPY_IN_FARRAY
NPY_OUT_FARRAY
NPY_INOUT_FARRAY
NPY_UPDATE_ALL
cdef enum:
NPY_MAXDIMS
npy_intp NPY_MAX_ELSIZE
ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *)
ctypedef class numpy.dtype [object PyArray_Descr]: ctypedef class numpy.dtype [object PyArray_Descr]:
# Use PyDataType_* macros when possible, however there are no macros
# for accessing some of the fields, so some are defined. Please
# ask on cython-dev if you need more.
cdef int type_num cdef int type_num
cdef int itemsize "elsize" cdef int itemsize "elsize"
cdef char byteorder cdef char byteorder
cdef object fields cdef object fields
cdef object names cdef object names
ctypedef extern class numpy.flatiter [object PyArrayIterObject]:
# Use through macros
pass
ctypedef extern class numpy.broadcast [object PyArrayMultiIterObject]:
# Use through macros
pass
ctypedef class numpy.ndarray [object PyArrayObject]: ctypedef class numpy.ndarray [object PyArrayObject]:
cdef __cythonbufferdefaults__ = {"mode": "strided"} cdef __cythonbufferdefaults__ = {"mode": "strided"}
cdef: cdef:
# Only taking a few of the most commonly used and stable fields.
# One should use PyArray_* macros instead to access the C fields.
char *data char *data
int ndim "nd" int ndim "nd"
npy_intp *shape "dimensions" npy_intp *shape "dimensions"
npy_intp *strides npy_intp *strides
int flags
dtype descr dtype descr
# Note: This syntax (function definition in pxd files) is an # Note: This syntax (function definition in pxd files) is an
...@@ -161,17 +248,7 @@ cdef extern from "numpy/arrayobject.h": ...@@ -161,17 +248,7 @@ cdef extern from "numpy/arrayobject.h":
# info.shape was stored after info.strides in the same block # info.shape was stored after info.strides in the same block
cdef void* PyArray_DATA(ndarray arr) ctypedef signed char npy_bool
cdef int PyArray_TYPE(ndarray arr)
cdef int PyArray_NDIM(ndarray arr)
cdef int PyArray_ISWRITEABLE(ndarray arr)
cdef npy_intp* PyArray_STRIDES(ndarray arr)
cdef npy_intp* PyArray_DIMS(ndarray arr)
cdef int PyArray_ITEMSIZE(ndarray arr)
cdef int PyArray_CHKFLAGS(ndarray arr, int flags)
cdef int PyArray_HASFIELDS(ndarray arr)
cdef int PyDataType_HASFIELDS(dtype obj)
ctypedef signed char npy_byte ctypedef signed char npy_byte
ctypedef signed short npy_short ctypedef signed short npy_short
...@@ -216,16 +293,352 @@ cdef extern from "numpy/arrayobject.h": ...@@ -216,16 +293,352 @@ cdef extern from "numpy/arrayobject.h":
ctypedef long double complex npy_complex256 ctypedef long double complex npy_complex256
ctypedef struct npy_cfloat: ctypedef struct npy_cfloat:
float real double real
float imag double imag
ctypedef struct npy_cdouble: ctypedef struct npy_cdouble:
float real double real
float imag double imag
ctypedef struct npy_clongdouble: ctypedef struct npy_clongdouble:
float real double real
float imag double imag
ctypedef struct PyArray_Dims:
npy_intp *ptr
int len
void import_array()
#
# Macros from ndarrayobject.h
#
bint PyArray_CHKFLAGS(ndarray m, int flags)
bint PyArray_ISISCONTIGUOUS(ndarray m)
bint PyArray_ISWRITEABLE(ndarray m)
bint PyArray_ISALIGNED(ndarray m)
int PyArray_NDIM(ndarray)
bint PyArray_ISONESEGMENT(ndarray)
bint PyArray_ISFORTRAN(ndarray)
int PyArray_FORTRANIF(ndarray)
void* PyArray_DATA(ndarray)
char* PyArray_BYTES(ndarray)
npy_intp* PyArray_DIMS(ndarray)
npy_intp* PyArray_STRIDES(ndarray)
npy_intp PyArray_DIM(ndarray, size_t)
npy_intp PyArray_STRIDE(ndarray, size_t)
# object PyArray_BASE(ndarray) wrong refcount semantics
# dtype PyArray_DESCR(ndarray) wrong refcount semantics
int PyArray_FLAGS(ndarray)
npy_intp PyArray_ITEMSIZE(ndarray)
int PyArray_TYPE(ndarray arr)
object PyArray_GETITEM(ndarray arr, void *itemptr)
int PyArray_SETITEM(ndarray arr, void *itemptr, object obj)
bint PyTypeNum_ISBOOL(int)
bint PyTypeNum_ISUNSIGNED(int)
bint PyTypeNum_ISSIGNED(int)
bint PyTypeNum_ISINTEGER(int)
bint PyTypeNum_ISFLOAT(int)
bint PyTypeNum_ISNUMBER(int)
bint PyTypeNum_ISSTRING(int)
bint PyTypeNum_ISCOMPLEX(int)
bint PyTypeNum_ISPYTHON(int)
bint PyTypeNum_ISFLEXIBLE(int)
bint PyTypeNum_ISUSERDEF(int)
bint PyTypeNum_ISEXTENDED(int)
bint PyTypeNum_ISOBJECT(int)
bint PyDataType_ISBOOL(dtype)
bint PyDataType_ISUNSIGNED(dtype)
bint PyDataType_ISSIGNED(dtype)
bint PyDataType_ISINTEGER(dtype)
bint PyDataType_ISFLOAT(dtype)
bint PyDataType_ISNUMBER(dtype)
bint PyDataType_ISSTRING(dtype)
bint PyDataType_ISCOMPLEX(dtype)
bint PyDataType_ISPYTHON(dtype)
bint PyDataType_ISFLEXIBLE(dtype)
bint PyDataType_ISUSERDEF(dtype)
bint PyDataType_ISEXTENDED(dtype)
bint PyDataType_ISOBJECT(dtype)
bint PyDataType_HASFIELDS(dtype)
bint PyArray_ISBOOL(ndarray)
bint PyArray_ISUNSIGNED(ndarray)
bint PyArray_ISSIGNED(ndarray)
bint PyArray_ISINTEGER(ndarray)
bint PyArray_ISFLOAT(ndarray)
bint PyArray_ISNUMBER(ndarray)
bint PyArray_ISSTRING(ndarray)
bint PyArray_ISCOMPLEX(ndarray)
bint PyArray_ISPYTHON(ndarray)
bint PyArray_ISFLEXIBLE(ndarray)
bint PyArray_ISUSERDEF(ndarray)
bint PyArray_ISEXTENDED(ndarray)
bint PyArray_ISOBJECT(ndarray)
bint PyArray_HASFIELDS(ndarray)
bint PyArray_ISVARIABLE(ndarray)
bint PyArray_SAFEALIGNEDCOPY(ndarray)
bint PyArray_ISNBO(ndarray)
bint PyArray_IsNativeByteOrder(ndarray)
bint PyArray_ISNOTSWAPPED(ndarray)
bint PyArray_ISBYTESWAPPED(ndarray)
bint PyArray_FLAGSWAP(ndarray, int)
bint PyArray_ISCARRAY(ndarray)
bint PyArray_ISCARRAY_RO(ndarray)
bint PyArray_ISFARRAY(ndarray)
bint PyArray_ISFARRAY_RO(ndarray)
bint PyArray_ISBEHAVED(ndarray)
bint PyArray_ISBEHAVED_RO(ndarray)
bint PyDataType_ISNOTSWAPPED(dtype)
bint PyDataType_ISBYTESWAPPED(dtype)
bint PyArray_DescrCheck(object)
bint PyArray_Check(object)
bint PyArray_CheckExact(object)
# Cannot be supported due to out arg:
# bint PyArray_HasArrayInterfaceType(object, dtype, object, object&)
# bint PyArray_HasArrayInterface(op, out)
bint PyArray_IsZeroDim(object)
# Cannot be supported due to ## ## in macro:
# bint PyArray_IsScalar(object, verbatim work)
bint PyArray_CheckScalar(object)
bint PyArray_IsPythonNumber(object)
bint PyArray_IsPythonScalar(object)
bint PyArray_IsAnyScalar(object)
bint PyArray_CheckAnyScalar(object)
ndarray PyArray_GETCONTIGUOUS(ndarray)
bint PyArray_SAMESHAPE(ndarray, ndarray)
npy_intp PyArray_SIZE(ndarray)
npy_intp PyArray_NBYTES(ndarray)
object PyArray_FROM_O(object)
object PyArray_FROM_OF(object m, int flags)
bint PyArray_FROM_OT(object m, int type)
bint PyArray_FROM_OTF(object m, int type, int flags)
object PyArray_FROMANY(object m, int type, int min, int max, int flags)
bint PyArray_ZEROS(ndarray m, dims, int type, int fortran)
object PyArray_EMPTY(object m, dims, int type, int fortran)
void PyArray_FILLWBYTE(object, int val)
npy_intp PyArray_REFCOUNT(object)
object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
unsigned char PyArray_EquivArrTypes(ndarray a1, ndarray a2)
bint PyArray_EquivByteorders(int b1, int b2)
object PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
object PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
#object PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, dtype descr)
object PyArray_ToScalar(void* data, ndarray arr)
void* PyArray_GETPTR1(ndarray m, npy_intp i)
void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j)
void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k)
void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l)
void PyArray_XDECREF_ERR(ndarray)
# Cannot be supported due to out arg
# void PyArray_DESCR_REPLACE(descr)
object PyArray_Copy(ndarray)
object PyArray_FromObject(object op, int type, int min_depth, int max_depth)
object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth)
object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth)
object PyArray_Cast(ndarray mp, int type_num)
object PyArray_Take(ndarray ap, object items, int axis)
object PyArray_Put(ndarray ap, object items, object values)
# Functions from __multiarray_api.h
# Functions taking dtype and returning object/ndarray are disabled
# for now as they steal dtype references. I'm conservative and disable
# more than is probably needed until it can be checked further.
int PyArray_SetNumericOps (object)
object PyArray_GetNumericOps ()
int PyArray_INCREF (ndarray)
int PyArray_XDECREF (ndarray)
void PyArray_SetStringFunction (object, int)
dtype PyArray_DescrFromType (int)
object PyArray_TypeObjectFromType (int)
char * PyArray_Zero (ndarray)
char * PyArray_One (ndarray)
#object PyArray_CastToType (ndarray, dtype, int)
int PyArray_CastTo (ndarray, ndarray)
int PyArray_CastAnyTo (ndarray, ndarray)
int PyArray_CanCastSafely (int, int)
npy_bool PyArray_CanCastTo (dtype, dtype)
int PyArray_ObjectType (object, int)
dtype PyArray_DescrFromObject (object, dtype)
#ndarray* PyArray_ConvertToCommonType (object, int *)
dtype PyArray_DescrFromScalar (object)
dtype PyArray_DescrFromTypeObject (object)
npy_intp PyArray_Size (object)
#object PyArray_Scalar (void *, dtype, object)
#object PyArray_FromScalar (object, dtype)
void PyArray_ScalarAsCtype (object, void *)
#int PyArray_CastScalarToCtype (object, void *, dtype)
#int PyArray_CastScalarDirect (object, dtype, void *, int)
object PyArray_ScalarFromObject (object)
#PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int)
object PyArray_FromDims (int, int *, int)
#object PyArray_FromDimsAndDataAndDescr (int, int *, dtype, char *)
#object PyArray_FromAny (object, dtype, int, int, int, object)
object PyArray_EnsureArray (object)
object PyArray_EnsureAnyArray (object)
#object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *)
#object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *)
#object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp)
#object PyArray_FromIter (object, dtype, npy_intp)
object PyArray_Return (ndarray)
#object PyArray_GetField (ndarray, dtype, int)
#int PyArray_SetField (ndarray, dtype, int, object)
object PyArray_Byteswap (ndarray, npy_bool)
object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER)
int PyArray_MoveInto (ndarray, ndarray)
int PyArray_CopyInto (ndarray, ndarray)
int PyArray_CopyAnyInto (ndarray, ndarray)
int PyArray_CopyObject (ndarray, object)
object PyArray_NewCopy (ndarray, NPY_ORDER)
object PyArray_ToList (ndarray)
object PyArray_ToString (ndarray, NPY_ORDER)
int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *)
int PyArray_Dump (object, object, int)
object PyArray_Dumps (object, int)
int PyArray_ValidType (int)
void PyArray_UpdateFlags (ndarray, int)
object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object)
#object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object)
#dtype PyArray_DescrNew (dtype)
dtype PyArray_DescrNewFromType (int)
double PyArray_GetPriority (object, double)
object PyArray_IterNew (object)
object PyArray_MultiIterNew (int, ...)
int PyArray_PyIntAsInt (object)
npy_intp PyArray_PyIntAsIntp (object)
int PyArray_Broadcast (broadcast)
void PyArray_FillObjectArray (ndarray, object)
int PyArray_FillWithScalar (ndarray, object)
npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *)
dtype PyArray_DescrNewByteorder (dtype, char)
object PyArray_IterAllButAxis (object, int *)
#object PyArray_CheckFromAny (object, dtype, int, int, int, object)
#object PyArray_FromArray (ndarray, dtype, int)
object PyArray_FromInterface (object)
object PyArray_FromStructInterface (object)
#object PyArray_FromArrayAttr (object, dtype, object)
#NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*)
int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND)
object PyArray_NewFlagsObject (object)
npy_bool PyArray_CanCastScalar (type, type)
#int PyArray_CompareUCS4 (npy_ucs4 *, npy_ucs4 *, register size_t)
int PyArray_RemoveSmallest (broadcast)
int PyArray_ElementStrides (object)
void PyArray_Item_INCREF (char *, dtype)
void PyArray_Item_XDECREF (char *, dtype)
object PyArray_FieldNames (object)
object PyArray_Transpose (ndarray, PyArray_Dims *)
object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE)
object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE)
object PyArray_PutMask (ndarray, object, object)
object PyArray_Repeat (ndarray, object, int)
object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE)
int PyArray_Sort (ndarray, int, NPY_SORTKIND)
object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE)
object PyArray_ArgMax (ndarray, int, ndarray)
object PyArray_ArgMin (ndarray, int, ndarray)
object PyArray_Reshape (ndarray, object)
object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
object PyArray_Squeeze (ndarray)
#object PyArray_View (ndarray, dtype, type)
object PyArray_SwapAxes (ndarray, int, int)
object PyArray_Max (ndarray, int, ndarray)
object PyArray_Min (ndarray, int, ndarray)
object PyArray_Ptp (ndarray, int, ndarray)
object PyArray_Mean (ndarray, int, int, ndarray)
object PyArray_Trace (ndarray, int, int, int, int, ndarray)
object PyArray_Diagonal (ndarray, int, int, int)
object PyArray_Clip (ndarray, object, object, ndarray)
object PyArray_Conjugate (ndarray, ndarray)
object PyArray_Nonzero (ndarray)
object PyArray_Std (ndarray, int, int, ndarray, int)
object PyArray_Sum (ndarray, int, int, ndarray)
object PyArray_CumSum (ndarray, int, int, ndarray)
object PyArray_Prod (ndarray, int, int, ndarray)
object PyArray_CumProd (ndarray, int, int, ndarray)
object PyArray_All (ndarray, int, ndarray)
object PyArray_Any (ndarray, int, ndarray)
object PyArray_Compress (ndarray, object, int, ndarray)
object PyArray_Flatten (ndarray, NPY_ORDER)
object PyArray_Ravel (ndarray, NPY_ORDER)
npy_intp PyArray_MultiplyList (npy_intp *, int)
int PyArray_MultiplyIntList (int *, int)
void * PyArray_GetPtr (ndarray, npy_intp*)
int PyArray_CompareLists (npy_intp *, npy_intp *, int)
#int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype)
#int PyArray_As1D (object*, char **, int *, int)
#int PyArray_As2D (object*, char ***, int *, int *, int)
int PyArray_Free (object, void *)
#int PyArray_Converter (object, object*)
int PyArray_IntpFromSequence (object, npy_intp *, int)
object PyArray_Concatenate (object, int)
object PyArray_InnerProduct (object, object)
object PyArray_MatrixProduct (object, object)
object PyArray_CopyAndTranspose (object)
object PyArray_Correlate (object, object, int)
int PyArray_TypestrConvert (int, int)
#int PyArray_DescrConverter (object, dtype*)
#int PyArray_DescrConverter2 (object, dtype*)
int PyArray_IntpConverter (object, PyArray_Dims *)
#int PyArray_BufferConverter (object, chunk)
int PyArray_AxisConverter (object, int *)
int PyArray_BoolConverter (object, npy_bool *)
int PyArray_ByteorderConverter (object, char *)
int PyArray_OrderConverter (object, NPY_ORDER *)
unsigned char PyArray_EquivTypes (dtype, dtype)
#object PyArray_Zeros (int, npy_intp *, dtype, int)
#object PyArray_Empty (int, npy_intp *, dtype, int)
object PyArray_Where (object, object, object)
object PyArray_Arange (double, double, double, int)
#object PyArray_ArangeObj (object, object, object, dtype)
int PyArray_SortkindConverter (object, NPY_SORTKIND *)
object PyArray_LexSort (object, int)
object PyArray_Round (ndarray, int, ndarray)
unsigned char PyArray_EquivTypenums (int, int)
int PyArray_RegisterDataType (dtype)
int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *)
int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND)
#void PyArray_InitArrFuncs (PyArray_ArrFuncs *)
object PyArray_IntTupleFromIntp (int, npy_intp *)
int PyArray_TypeNumFromName (char *)
int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *)
#int PyArray_OutputConverter (object, ndarray*)
object PyArray_BroadcastToShape (object, npy_intp *, int)
void _PyArray_SigintHandler (int)
void* _PyArray_GetSigintBuf ()
#int PyArray_DescrAlignConverter (object, dtype*)
#int PyArray_DescrAlignConverter2 (object, dtype*)
int PyArray_SearchsideConverter (object, void *)
object PyArray_CheckAxis (ndarray, int *, int)
npy_intp PyArray_OverflowMultiplyList (npy_intp *, int)
int PyArray_CompareString (char *, char *, size_t)
# Typedefs that matches the runtime dtype objects in # Typedefs that matches the runtime dtype objects in
# the numpy module. # the numpy module.
...@@ -252,8 +665,8 @@ ctypedef npy_float64 float64_t ...@@ -252,8 +665,8 @@ ctypedef npy_float64 float64_t
#ctypedef npy_float80 float80_t #ctypedef npy_float80 float80_t
#ctypedef npy_float128 float128_t #ctypedef npy_float128 float128_t
ctypedef npy_complex64 complex64_t ctypedef float complex complex64_t
ctypedef npy_complex128 complex128_t ctypedef double complex complex128_t
# The int types are mapped a bit surprising -- # The int types are mapped a bit surprising --
# numpy.int corresponds to 'l' and numpy.long to 'q' # numpy.int corresponds to 'l' and numpy.long to 'q'
......
...@@ -28,5 +28,5 @@ cdef extern from *: ...@@ -28,5 +28,5 @@ cdef extern from *:
# 0xC (release candidate) # 0xC (release candidate)
# 0xF (final) # 0xF (final)
char[] PY_VERSION char PY_VERSION[]
char[] PY_PATCHLEVEL_REVISION char PY_PATCHLEVEL_REVISION[]
CC = gcc
CYTHON = ./../bin/cython
CYTHON_FREEZE = ../../bin/cython_freeze.py
CFLAGS = -fPIC -g -O2 -Wall -Wextra
CPPFLAGS = -I /usr/include/python2.6
LDFLAGS = -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
LDLIBS = /usr/lib/python2.6/config/libpython2.6.a \
-lm -ldl -pthread -lutil -lz
# Name of executable
TARGET = nCr
# List of Cython source files, with main module first.
CYTHON_SOURCE = combinatorics.pyx cmath.pyx
all : $(TARGET)
$(TARGET) : $(TARGET).o $(CYTHON_SOURCE:.pyx=.o)
$(TARGET).c :
$(CYTHON_FREEZE) $(CYTHON_SOURCE:.pyx=) > $@
%.c : %.pyx
$(CYTHON) $(CYTHONFLAGS) $^
clean:
$(RM) *.o *.c $(TARGET)
.PHONY: clean
.SECONDARY: $(CYTHON_SOURCE:.pyx=.c)
NAME
====
cython_freeze.py - create a C file for embedding Cython modules
SYNOPSIS
========
cython_freeze.py module [...]
DESCRIPTION
===========
**cython_freeze.py** generates a C source file to embed a Python interpreter
with one or more Cython modules built in. This allows one to create a single
executable from Cython code, without having to have separate shared objects
for each Cython module.
A major advantage of this approach is that it allows debuging with gprof(1),
which does not work with shared objects.
Note that this method differs from ``cython --embed``. The ``--embed`` options
modifies the resulting C source file to include a ``main()`` function, so it
can only be used on a single Cython module. The advantage ``--embed`` is
simplicity. This module, on the other hand, can be used with multiple
modules, but it requires another C source file to be created.
EXAMPLE
=======
In the example directory, there exist two Cython modules:
cmath.pyx
A module that interfaces with the -lm library.
combinatorics.pyx
A module that implements n-choose-r using cmath.
Both modules have the Python idiom ``if __name__ == "__main__"``, which only
execute if that module is the "main" module. If run as main, cmath prints the
factorial of the argument, while combinatorics prints n-choose-r.
The provided Makefile creates an executable, *nCr*, using combinatorics as the
"main" module. It basically performs the following (ignoring the compiler
flags)::
$ cython_freeze.py combintorics cmath > nCr.c
$ cython combinatorics.pyx
$ cython cmath.pyx
$ gcc nCr.c -o nCr.o
$ gcc combinatorics.c -o combinatorics.o
$ gcc cmath.c -o cmath.o
$ gcc nCr.o combinatorics.o cmath.o -o nCr
Because the combinatorics module was listed first, its ``__name__`` is set
to ``"__main__"``, while cmath's is set to ``"cmath"``. The executable now
contains a Python interpreter and both Cython modules. ::
$ ./nCr
USAGE: ./nCr n r
Prints n-choose-r.
$ ./nCr 15812351235 12
5.10028093999e+113
PREREQUISITES
=============
Cython 0.11.2 (or newer, assuming the API does not change)
SEE ALSO
========
* `Python <http://www.python.org>`_
* `Cython <http://www.cython.org>`_
* `freeze.py <http://wiki.python.org/moin/Freeze>`_
cdef extern from "math.h":
double c_lgamma "lgamma" (double)
double c_exp "exp" (double)
def exp(n):
"""Return e**n."""
return c_exp(n)
def lfactorial(n):
"""Return an estimate of the log factorial of n."""
return c_lgamma(n+1)
def factorial(n):
"""Return an estimate of the factorial of n."""
return c_exp( c_lgamma(n+1) )
if __name__ == "__main__":
import sys
if len(sys.argv) != 2:
sys.stderr.write("USAGE: %s n\nPrints n!.\n" % sys.argv[0])
sys.exit(1)
n = map(float, sys.argv[1:])
print factorial(n)
import cmath
def nCr(n, r):
"""Return the number of ways to choose r elements of a set of n."""
return cmath.exp( cmath.lfactorial(n) - cmath.lfactorial(r)
- cmath.lfactorial(n-r) )
if __name__ == "__main__":
import sys
if len(sys.argv) != 3:
sys.stderr.write("USAGE: %s n r\nPrints n-choose-r.\n" % sys.argv[0])
sys.exit(1)
n, r = map(float, sys.argv[1:])
print nCr(n, r)
...@@ -4,6 +4,12 @@ from distutils.core import setup ...@@ -4,6 +4,12 @@ from distutils.core import setup
from distutils.extension import Extension from distutils.extension import Extension
from Cython.Distutils import build_ext from Cython.Distutils import build_ext
try:
from numpy.distutils.misc_util import get_numpy_include_dirs
numpy_include_dirs = get_numpy_include_dirs()
except:
numpy_include_dirs = []
ext_modules=[ ext_modules=[
Extension("primes", ["primes.pyx"]), Extension("primes", ["primes.pyx"]),
Extension("spam", ["spam.pyx"]), Extension("spam", ["spam.pyx"]),
...@@ -11,7 +17,7 @@ ext_modules=[ ...@@ -11,7 +17,7 @@ ext_modules=[
for file in glob.glob("*.pyx"): for file in glob.glob("*.pyx"):
if file != "numeric_demo.pyx": if file != "numeric_demo.pyx":
ext_modules.append(Extension(file[:-4], [file])) ext_modules.append(Extension(file[:-4], [file], include_dirs = numpy_include_dirs))
setup( setup(
name = 'Demos', name = 'Demos',
......
#!/usr/bin/env python
"""
Create a C file for embedding one or more Cython source files.
Requires Cython 0.11.2 (or perhaps newer).
See README.rst for more details.
"""
import sys
if len(sys.argv) < 2:
print >>sys.stderr, "USAGE: %s module [module ...]" % sys.argv[0]
sys.exit(1)
def format_modname(name):
if name.endswith('.pyx'):
name = name[:-4]
return name.replace('.','_')
modules = [format_modname(x) for x in sys.argv[1:]]
print """
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#if PY_MAJOR_VERSION < 3
# define MODINIT(name) init ## name
#else
# define MODINIT(name) PyInit_ ## name
#endif
"""
for name in modules:
print "PyMODINIT_FUNC MODINIT(%s) (void);" % name
print """
static struct _inittab inittab[] = {"""
for name in modules:
print ' {"%(name)s", MODINIT(%(name)s)},' % {'name' : name}
print """ {NULL, NULL}
};
extern int __pyx_module_is_main_%(main)s;
#if PY_MAJOR_VERSION < 3 || (!defined(WIN32) && !defined(MS_WINDOWS))
int main(int argc, char** argv) {
#else
int wmain(int argc, wchar_t **argv) {
#endif
int r = 0;
PyObject *m = NULL;
if (PyImport_ExtendInittab(inittab)) {
fprintf(stderr, "No memory\\n");
exit(1);
}
Py_SetProgramName(argv[0]);
Py_Initialize();
PySys_SetArgv(argc, argv);
__pyx_module_is_main_%(main)s = 1;
m = PyImport_ImportModule(inittab[0].name);
if (!m) {
r = 1;
PyErr_Print(); /* This exits with the right code if SystemExit. */
if (Py_FlushLine()); PyErr_Clear();
}
Py_XDECREF(m);
Py_Finalize();
return r;
}
""" % {'main' : modules[0]}
...@@ -14,3 +14,6 @@ large_consts_T237 ...@@ -14,3 +14,6 @@ large_consts_T237
bad_c_struct_T252 bad_c_struct_T252
missing_baseclass_in_predecl_T262 missing_baseclass_in_predecl_T262
ifelseexpr_T267 ifelseexpr_T267
# Not yet enabled
profile_test
cimport python_bool
cimport python_buffer
cimport python_complex
cimport python_dict
cimport python_exc
cimport python_float
cimport python_function
cimport python_instance
cimport python_int
cimport python_iterator
cimport python_list
cimport python_long
cimport python_mapping
cimport python_mem
cimport python_method
cimport python_module
cimport python_number
cimport python_object
cimport python_parse
cimport python
cimport python_ref
cimport python_sequence
cimport python_set
cimport python_string
cimport python_tuple
cimport python_type
cimport python_unicode
cimport python_version
cimport stdio
cimport stdlib
nonexisting(3, with_kw_arg=4)
_ERRORS = u"""
1:11: undeclared name not builtin: nonexisting
"""
...@@ -4,6 +4,21 @@ ...@@ -4,6 +4,21 @@
[2, 1] [2, 1]
>>> a.g() >>> a.g()
(False, True) (False, True)
>>> del_item({1: 'a', 2: 'b'}, 1)
{2: 'b'}
>>> del_item(range(10), 2)
[0, 1, 3, 4, 5, 6, 7, 8, 9]
>>> del_dict({1: 'a', 2: 'b'}, 1)
{2: 'b'}
>>> del_list(range(5), 3)
[0, 1, 2, 4]
>>> del_int(range(5), 3)
[0, 1, 2, 4]
>>> del_list_int(range(5), 3)
[0, 1, 2, 4]
>>> del_int({-1: 'neg', 1: 'pos'}, -1)
{1: 'pos'}
""" """
class A: class A:
...@@ -16,3 +31,23 @@ class A: ...@@ -16,3 +31,23 @@ class A:
self.a = 3 self.a = 3
del self.a del self.a
return (hasattr(self, u"a"), hasattr(self, u"g")) return (hasattr(self, u"a"), hasattr(self, u"g"))
def del_item(L, o):
del L[o]
return L
def del_dict(dict D, o):
del D[o]
return D
def del_list(list L, o):
del L[o]
return L
def del_int(L, int i):
del L[i]
return L
def del_list_int(L, int i):
del L[i]
return L
typedef float FloatTypedef;
typedef double DoubleTypedef; typedef double DoubleTypedef;
typedef long double LongDoubleTypedef;
typedef char CharTypedef;
typedef short ShortTypedef;
typedef int IntTypedef;
typedef long LongTypedef;
#if defined(T_LONGLONG)
typedef PY_LONG_LONG LongLongTypedef;
#else
typedef long LongLongTypedef;
#endif
typedef unsigned char UCharTypedef;
typedef unsigned short UShortTypedef;
typedef unsigned int UIntTypedef;
typedef unsigned long ULongTypedef;
#if defined(T_LONGLONG)
typedef unsigned PY_LONG_LONG ULongLongTypedef;
#else
typedef unsigned long ULongLongTypedef;
#endif
__doc__ = u"""
>>> hash(A(5))
5
>>> hash(A(-1))
-2
>>> hash(A(-2))
-2
>>> hash(A(100))
Traceback (most recent call last):
...
TypeError: That's kind of a round number...
>>> __hash__(-1)
-1
"""
cdef class A:
cdef long a
def __init__(self, a):
self.a = a
def __hash__(self):
if self.a == 100:
raise TypeError, "That's kind of a round number..."
else:
return self.a
cpdef long __hash__(long x):
return x
...@@ -195,6 +195,11 @@ try: ...@@ -195,6 +195,11 @@ try:
... ...
ValueError: Item size of buffer (1 byte) does not match size of 'int' (4 bytes) ValueError: Item size of buffer (1 byte) does not match size of 'int' (4 bytes)
>>> test_complextypes()
1,1
1,1
8,16
""" """
except: except:
__doc__ = u"" __doc__ = u""
...@@ -376,3 +381,15 @@ def test_unpacked_align(np.ndarray[UnpackedStruct] arr): ...@@ -376,3 +381,15 @@ def test_unpacked_align(np.ndarray[UnpackedStruct] arr):
arr[0].a = 22 arr[0].a = 22
arr[0].b = 23 arr[0].b = 23
return repr(arr).replace('<', '!').replace('>', '!') return repr(arr).replace('<', '!').replace('>', '!')
def test_complextypes():
cdef np.complex64_t x64 = 1, y64 = 1j
cdef np.complex128_t x128 = 1, y128 = 1j
x64 = x64 + y64
print "%.0f,%.0f" % (x64.real, x64.imag)
x128 = x128 + y128
print "%.0f,%.0f" % (x128.real, x128.imag)
print "%d,%d" % (sizeof(x64), sizeof(x128))
__doc__ = u"""
>>> import os, tempfile, cProfile as profile, pstats
>>> statsfile = tempfile.mkstemp()[1]
>>> profile.runctx("test_profile(100)", locals(), globals(), statsfile)
>>> s = pstats.Stats(statsfile)
>>> short_stats = dict([(k[2], v[1]) for k,v in s.stats.items()])
>>> short_stats['f_def']
100
>>> short_stats['f_cdef']
100
>>> short_stats['f_inline']
Traceback (most recent call last):
...
KeyError: 'f_inline'
>>> short_stats['f_inline_prof']
100
>>> short_stats['f_noprof']
Traceback (most recent call last):
...
KeyError: 'f_noprof'
>>> short_stats['f_raise']
100
>>> os.unlink(statsfile)
"""
cimport cython
def test_profile(long N):
cdef long i, n = 0
for i from 0 <= i < N:
n += f_def(i)
n += f_cdef(i)
n += f_inline(i)
n += f_inline_prof(i)
n += f_noprof(i)
try:
n += f_raise(i+2)
except RuntimeError:
pass
return n
def f_def(long a):
return a
cdef long f_cdef(long a):
return a
cdef inline long f_inline(long a):
return a
@cython.profile(True)
cdef inline long f_inline_prof(long a):
return a
@cython.profile(False)
cdef int f_noprof(long a):
return a
cdef long f_raise(long) except -2:
raise RuntimeError
""" """
>>> f() >>> f()
42.0 42.0 42.0 42.0
42.0
>>> global_vars(12.0)
12.0 12.0
>>> readonly() >>> readonly()
Traceback (most recent call last): Traceback (most recent call last):
... ...
AttributeError: attribute 'var_nf' of 'typedfieldbug_T303.MyClass' objects is not writable TypeError: readonly attribute
>>> longdouble_access()
Traceback (most recent call last):
...
SystemError: bad memberdescr type
""" """
cdef extern from "external_defs.h": cdef extern from "external_defs.h":
ctypedef float DoubleTypedef ctypedef float DoubleTypedef
ctypedef float LongDoubleTypedef
cdef public DoubleTypedef global_tdef
cdef public double global_double
cdef class MyClass: cdef class MyClass:
cdef readonly: cdef readonly:
double var_d double actual_double
DoubleTypedef var_nf DoubleTypedef float_isreally_double
cdef public: LongDoubleTypedef float_isreally_longdouble
DoubleTypedef var_mutable
def __init__(self): def __init__(self):
self.var_d = 42.0 self.actual_double = 42.0
self.var_nf = 42.0 self.float_isreally_double = 42.0
self.var_mutable = 1 self.float_isreally_longdouble = 42.0
def global_vars(x):
global global_tdef, global_double
global_tdef = x
global_double = x
print global_tdef, global_double
def f(): def f():
c = MyClass() c = MyClass()
c.var_mutable = 42.0 print c.actual_double
print c.var_d, c.var_nf, c.var_mutable print c.float_isreally_double
def longdouble_access():
c = MyClass()
print c.float_isreally_longdouble
def readonly(): def readonly():
c = MyClass() c = MyClass()
c.var_nf = 3 c.actual_double = 3
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