Commit e0edfcea authored by Vitja Makarov's avatar Vitja Makarov

Merge remote branch 'upstream/master'

parents 61a825b7 76723265
...@@ -86,6 +86,7 @@ class AnnotationCCodeWriter(CCodeWriter): ...@@ -86,6 +86,7 @@ class AnnotationCCodeWriter(CCodeWriter):
html_filename = os.path.splitext(target_filename)[0] + ".html" html_filename = os.path.splitext(target_filename)[0] + ".html"
f = codecs.open(html_filename, "w", encoding="UTF-8") f = codecs.open(html_filename, "w", encoding="UTF-8")
f.write(u'<!-- Generated by Cython %s on %s -->\n' % (Version.version, time.asctime()))
f.write(u'<html>\n') f.write(u'<html>\n')
f.write(u""" f.write(u"""
<head> <head>
......
...@@ -76,6 +76,25 @@ bad: ...@@ -76,6 +76,25 @@ bad:
} }
""") """)
hasattr_utility_code = UtilityCode(
proto = """
static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); /*proto*/
""",
impl = """
static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) {
PyObject *v = PyObject_GetAttr(o, n);
if (v) {
Py_DECREF(v);
return 1;
}
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
return 0;
}
return -1;
}
""")
pyexec_utility_code = UtilityCode( pyexec_utility_code = UtilityCode(
proto = """ proto = """
#if PY_VERSION_HEX < 0x02040000 #if PY_VERSION_HEX < 0x02040000
...@@ -365,7 +384,8 @@ builtin_function_table = [ ...@@ -365,7 +384,8 @@ builtin_function_table = [
utility_code = getattr3_utility_code), utility_code = getattr3_utility_code),
BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr", BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr",
utility_code = getattr3_utility_code), # Pyrex compatibility utility_code = getattr3_utility_code), # Pyrex compatibility
BuiltinFunction('hasattr', "OO", "b", "PyObject_HasAttr"), BuiltinFunction('hasattr', "OO", "b", "__Pyx_HasAttr",
utility_code = hasattr_utility_code),
BuiltinFunction('hash', "O", "h", "PyObject_Hash"), BuiltinFunction('hash', "O", "h", "PyObject_Hash"),
#('hex', "", "", ""), #('hex', "", "", ""),
#('id', "", "", ""), #('id', "", "", ""),
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import sys import sys
from Cython.Utils import open_new_file from Cython.Utils import open_new_file
from DebugFlags import debug_exception_on_error import DebugFlags
import Options import Options
...@@ -156,7 +156,7 @@ def error(position, message): ...@@ -156,7 +156,7 @@ def error(position, message):
if position is None: if position is None:
raise InternalError(message) raise InternalError(message)
err = CompileError(position, message) err = CompileError(position, message)
if debug_exception_on_error: raise Exception(err) # debug if DebugFlags.debug_exception_on_error: raise Exception(err) # debug
report_error(err) report_error(err)
return err return err
......
...@@ -371,7 +371,7 @@ class ExprNode(Node): ...@@ -371,7 +371,7 @@ class ExprNode(Node):
def nonlocally_immutable(self): def nonlocally_immutable(self):
# Returns whether this variable is a safe reference, i.e. # Returns whether this variable is a safe reference, i.e.
# can't be modified as part of globals or closures. # can't be modified as part of globals or closures.
return self.is_temp return self.is_temp or self.type.is_array or self.type.is_cfunction
# --------------- Type Analysis ------------------ # --------------- Type Analysis ------------------
...@@ -1483,6 +1483,8 @@ class NameNode(AtomicExprNode): ...@@ -1483,6 +1483,8 @@ class NameNode(AtomicExprNode):
return 1 return 1
def nonlocally_immutable(self): def nonlocally_immutable(self):
if ExprNode.nonlocally_immutable(self):
return True
entry = self.entry entry = self.entry
return entry and (entry.is_local or entry.is_arg) and not entry.in_closure return entry and (entry.is_local or entry.is_arg) and not entry.in_closure
...@@ -3045,10 +3047,11 @@ class SimpleCallNode(CallNode): ...@@ -3045,10 +3047,11 @@ class SimpleCallNode(CallNode):
if i == 0 and self.self is not None: if i == 0 and self.self is not None:
continue # self is ok continue # self is ok
arg = self.args[i] arg = self.args[i]
if arg.is_name and arg.entry and ( if arg.nonlocally_immutable():
(arg.entry.is_local and not arg.entry.in_closure) # locals, C functions, unassignable types are safe.
or arg.entry.type.is_cfunction): pass
# local variables and C functions are safe elif arg.type.is_cpp_class:
# Assignment has side effects, avoid.
pass pass
elif env.nogil and arg.type.is_pyobject: elif env.nogil and arg.type.is_pyobject:
# can't copy a Python reference into a temp in nogil # can't copy a Python reference into a temp in nogil
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Cython Top Level # Cython Top Level
# #
import os, sys, re import os, sys, re, codecs
if sys.version_info[:2] < (2, 3): if sys.version_info[:2] < (2, 3):
sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n") sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n")
sys.exit(1) sys.exit(1)
...@@ -607,6 +607,14 @@ def run_pipeline(source, options, full_module_name = None): ...@@ -607,6 +607,14 @@ def run_pipeline(source, options, full_module_name = None):
# Set up result object # Set up result object
result = create_default_resultobj(source, options) result = create_default_resultobj(source, options)
if options.annotate is None:
# By default, decide based on whether an html file already exists.
html_filename = os.path.splitext(result.c_file)[0] + ".html"
if os.path.exists(html_filename):
line = codecs.open(html_filename, "r", encoding="UTF-8").readline()
if line.startswith(u'<!-- Generated by Cython'):
options.annotate = True
# Get pipeline # Get pipeline
if source_ext.lower() == '.py': if source_ext.lower() == '.py':
pipeline = context.create_py_pipeline(options, result) pipeline = context.create_py_pipeline(options, result)
...@@ -826,7 +834,7 @@ default_options = dict( ...@@ -826,7 +834,7 @@ default_options = dict(
errors_to_stderr = 1, errors_to_stderr = 1,
cplus = 0, cplus = 0,
output_file = None, output_file = None,
annotate = False, annotate = None,
generate_pxi = 0, generate_pxi = 0,
working_path = "", working_path = "",
recursive = 0, recursive = 0,
......
...@@ -1745,9 +1745,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1745,9 +1745,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("{") code.putln("{")
tempdecl_code = code.insertion_point() tempdecl_code = code.insertion_point()
env.use_utility_code(check_binary_version_utility_code)
code.putln("__Pyx_check_binary_version();")
code.putln("#if CYTHON_REFNANNY") code.putln("#if CYTHON_REFNANNY")
code.putln("void* __pyx_refnanny = NULL;") code.putln("void* __pyx_refnanny = NULL;")
code.putln("__Pyx_RefNanny = __Pyx_RefNannyImportAPI(\"refnanny\");") code.putln("__Pyx_RefNanny = __Pyx_RefNannyImportAPI(\"refnanny\");")
...@@ -1760,6 +1757,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1760,6 +1757,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3) code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3)
code.putln("#endif") code.putln("#endif")
env.use_utility_code(check_binary_version_utility_code)
code.putln("if ( __Pyx_check_binary_version() < 0) %s" % code.error_goto(self.pos))
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("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos))); code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
...@@ -2666,8 +2666,6 @@ int %(wmain_method)s(int argc, wchar_t **argv) { ...@@ -2666,8 +2666,6 @@ int %(wmain_method)s(int argc, wchar_t **argv) {
#else #else
static int __Pyx_main(int argc, wchar_t **argv) { static int __Pyx_main(int argc, wchar_t **argv) {
#endif #endif
int r = 0;
PyObject* m = NULL;
/* 754 requires that FP exceptions run in "no stop" mode by default, /* 754 requires that FP exceptions run in "no stop" mode by default,
* and until C vendors implement C99's ways to control FP exceptions, * and until C vendors implement C99's ways to control FP exceptions,
* Python requires non-stop mode. Alas, some platforms enable FP * Python requires non-stop mode. Alas, some platforms enable FP
...@@ -2679,29 +2677,30 @@ static int __Pyx_main(int argc, wchar_t **argv) { ...@@ -2679,29 +2677,30 @@ static int __Pyx_main(int argc, wchar_t **argv) {
m = fpgetmask(); m = fpgetmask();
fpsetmask(m & ~FP_X_OFL); fpsetmask(m & ~FP_X_OFL);
#endif #endif
if (argc) { if (argc && argv)
Py_SetProgramName(argv[0]); Py_SetProgramName(argv[0]);
}
Py_Initialize(); Py_Initialize();
if (argc) { if (argc && argv)
PySys_SetArgv(argc, argv); PySys_SetArgv(argc, argv);
{ /* init module '%(module_name)s' as '__main__' */
PyObject* m = NULL;
%(module_is_main)s = 1;
#if PY_MAJOR_VERSION < 3
init%(module_name)s();
#else
m = PyInit_%(module_name)s();
#endif
if (PyErr_Occurred()) {
PyErr_Print(); /* This exits with the right code if SystemExit. */
#if PY_MAJOR_VERSION < 3
if (Py_FlushLine()) PyErr_Clear();
#endif
return 1;
}
Py_XDECREF(m);
} }
%(module_is_main)s = 1;
#if PY_MAJOR_VERSION < 3
init%(module_name)s();
#else
m = PyInit_%(module_name)s();
#endif
if (PyErr_Occurred() != NULL) {
r = 1;
PyErr_Print(); /* This exits with the right code if SystemExit. */
#if PY_MAJOR_VERSION < 3
if (Py_FlushLine()) PyErr_Clear();
#endif
}
Py_XDECREF(m);
Py_Finalize(); Py_Finalize();
return r; return 0;
} }
...@@ -2860,35 +2859,21 @@ check_binary_version_utility_code = UtilityCode(proto=""" ...@@ -2860,35 +2859,21 @@ check_binary_version_utility_code = UtilityCode(proto="""
static int __Pyx_check_binary_version(void); static int __Pyx_check_binary_version(void);
""", impl=""" """, impl="""
static int __Pyx_check_binary_version(void) { static int __Pyx_check_binary_version(void) {
int res = -1; char ctversion[4], rtversion[4];
PyObject *major_info = NULL; PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
PyObject *minor_info = NULL; PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
PyObject *version_info = PySys_GetObject("version_info"); if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
if (version_info == NULL) goto bad; char message[200];
major_info = PySequence_GetItem(version_info, 0); PyOS_snprintf(message, sizeof(message),
if (major_info == NULL || !PyInt_CheckExact(major_info)) goto bad; "compiletime version %s of module '%.100s' "
minor_info = PySequence_GetItem(version_info, 1); "does not match runtime version %s",
if (minor_info == NULL || !PyInt_CheckExact(minor_info)) goto bad; ctversion, __Pyx_MODULE_NAME, rtversion);
if (PyInt_AsLong(major_info) == PY_MAJOR_VERSION && PyInt_AsLong(minor_info) == PY_MINOR_VERSION) {
res = 0;
} else {
char warning[200];
PyOS_snprintf(warning, sizeof(warning),
"compiletime version (%d, %d) of module %s does not match runtime version (%ld, %ld)",
PY_MAJOR_VERSION, PY_MINOR_VERSION,
__Pyx_MODULE_NAME,
PyInt_AsLong(major_info), PyInt_AsLong(minor_info));
#if PY_VERSION_HEX < 0x02050000 #if PY_VERSION_HEX < 0x02050000
PyErr_Warn(NULL, warning); return PyErr_Warn(NULL, message);
#else #else
PyErr_WarnEx(NULL, warning, 0); return PyErr_WarnEx(NULL, message, 1);
#endif #endif
res = 1;
} }
bad: return 0;
Py_XDECREF(version_info);
Py_XDECREF(major_info);
Py_XDECREF(minor_info);
return res;
} }
""") """)
...@@ -648,6 +648,9 @@ class CArgDeclNode(Node): ...@@ -648,6 +648,9 @@ class CArgDeclNode(Node):
is_self_arg = 0 is_self_arg = 0
is_type_arg = 0 is_type_arg = 0
is_generic = 1 is_generic = 1
kw_only = 0
not_none = 0
or_none = 0
type = None type = None
name_declarator = None name_declarator = None
default_value = None default_value = None
...@@ -733,6 +736,9 @@ class CSimpleBaseTypeNode(CBaseTypeNode): ...@@ -733,6 +736,9 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
child_attrs = [] child_attrs = []
arg_name = None # in case the argument name was interpreted as a type arg_name = None # in case the argument name was interpreted as a type
module_path = []
is_basic_c_type = False
complex = False
def analyse(self, env, could_be_name = False): def analyse(self, env, could_be_name = False):
# Return type descriptor. # Return type descriptor.
...@@ -1901,6 +1907,9 @@ class DefNode(FuncDefNode): ...@@ -1901,6 +1907,9 @@ class DefNode(FuncDefNode):
entry = None entry = None
acquire_gil = 0 acquire_gil = 0
self_in_stararg = 0 self_in_stararg = 0
star_arg = None
starstar_arg = None
doc = None
def __init__(self, pos, **kwds): def __init__(self, pos, **kwds):
FuncDefNode.__init__(self, pos, **kwds) FuncDefNode.__init__(self, pos, **kwds)
...@@ -2283,6 +2292,8 @@ class DefNode(FuncDefNode): ...@@ -2283,6 +2292,8 @@ class DefNode(FuncDefNode):
arg.hdr_type.declaration_code(arg.hdr_cname)) arg.hdr_type.declaration_code(arg.hdr_cname))
if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]: if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
arg_code_list.append("CYTHON_UNUSED PyObject *unused") arg_code_list.append("CYTHON_UNUSED PyObject *unused")
if (self.entry.scope.is_c_class_scope and self.entry.name == "__ipow__"):
arg_code_list.append("CYTHON_UNUSED PyObject *unused")
if sig.has_generic_args: if sig.has_generic_args:
arg_code_list.append( arg_code_list.append(
"PyObject *%s, PyObject *%s" "PyObject *%s, PyObject *%s"
...@@ -3308,6 +3319,7 @@ class CClassDefNode(ClassDefNode): ...@@ -3308,6 +3319,7 @@ class CClassDefNode(ClassDefNode):
objstruct_name = None objstruct_name = None
typeobj_name = None typeobj_name = None
decorators = None decorators = None
shadow = False
def analyse_declarations(self, env): def analyse_declarations(self, env):
#print "CClassDefNode.analyse_declarations:", self.class_name #print "CClassDefNode.analyse_declarations:", self.class_name
...@@ -3398,7 +3410,10 @@ class CClassDefNode(ClassDefNode): ...@@ -3398,7 +3410,10 @@ class CClassDefNode(ClassDefNode):
visibility = self.visibility, visibility = self.visibility,
typedef_flag = self.typedef_flag, typedef_flag = self.typedef_flag,
api = self.api, api = self.api,
buffer_defaults = buffer_defaults) buffer_defaults = buffer_defaults,
shadow = self.shadow)
if self.shadow:
home_scope.lookup(self.class_name).as_variable = self.entry
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, self.pos) env.add_imported_entry(self.class_name, self.entry, self.pos)
self.scope = scope = self.entry.type.scope self.scope = scope = self.entry.type.scope
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
# Cython - Compilation-wide options and pragma declarations # Cython - Compilation-wide options and pragma declarations
# #
cache_builtins = 1 # Perform lookups on builtin names only once cache_builtins = True # Perform lookups on builtin names only once
embed_pos_in_docstring = 0 embed_pos_in_docstring = False
gcc_branch_hints = 1 gcc_branch_hints = True
pre_import = None pre_import = None
docstrings = True docstrings = True
...@@ -14,9 +14,9 @@ docstrings = True ...@@ -14,9 +14,9 @@ docstrings = True
# 0: None, 1+: interned objects, 2+: cdef globals, 3+: types objects # 0: None, 1+: interned objects, 2+: cdef globals, 3+: types objects
# Mostly for reducing noise for Valgrind, only executes at process exit # Mostly for reducing noise for Valgrind, only executes at process exit
# (when all memory will be reclaimed anyways). # (when all memory will be reclaimed anyways).
generate_cleanup_code = 0 generate_cleanup_code = False
annotate = 0 annotate = False
# This will abort the compilation on the first error occured rather than trying # This will abort the compilation on the first error occured rather than trying
# to keep going and printing further error messages. # to keep going and printing further error messages.
...@@ -29,19 +29,19 @@ fast_fail = False ...@@ -29,19 +29,19 @@ fast_fail = False
# i to overflow. Specifically, if this option is set, an error will be # i to overflow. Specifically, if this option is set, an error will be
# raised before the loop is entered, wheras without this option the loop # raised before the loop is entered, wheras without this option the loop
# will execute until an overflowing value is encountered. # will execute until an overflowing value is encountered.
convert_range = 1 convert_range = True
# Enable this to allow one to write your_module.foo = ... to overwrite the # Enable this to allow one to write your_module.foo = ... to overwrite the
# definition if the cpdef function foo, at the cost of an extra dictionary # definition if the cpdef function foo, at the cost of an extra dictionary
# lookup on every call. # lookup on every call.
# If this is 0 it simply creates a wrapper. # If this is 0 it simply creates a wrapper.
lookup_module_cpdef = 0 lookup_module_cpdef = False
# This will set local variables to None rather than NULL which may cause # This will set local variables to None rather than NULL which may cause
# surpress what would be an UnboundLocalError in pure Python but eliminates # surpress what would be an UnboundLocalError in pure Python but eliminates
# checking for NULL on every use, and can decref rather than xdecref at the end. # checking for NULL on every use, and can decref rather than xdecref at the end.
# WARNING: This is a work in progress, may currently segfault. # WARNING: This is a work in progress, may currently segfault.
init_local_none = 1 init_local_none = True
# Whether or not to embed the Python interpreter, for use in making a # Whether or not to embed the Python interpreter, for use in making a
# standalone executable or calling from external libraries. # standalone executable or calling from external libraries.
...@@ -50,7 +50,7 @@ init_local_none = 1 ...@@ -50,7 +50,7 @@ init_local_none = 1
embed = None embed = None
# Disables function redefinition, allowing all functions to be declared at # Disables function redefinition, allowing all functions to be declared at
# module creation time. For legacy code only. # module creation time. For legacy code only, needed for some circular imports.
disable_function_redefinition = False disable_function_redefinition = False
......
...@@ -1039,6 +1039,27 @@ property NAME: ...@@ -1039,6 +1039,27 @@ property NAME:
return ATTR return ATTR
""", level='c_class') """, level='c_class')
struct_or_union_wrapper = TreeFragment(u"""
cdef class NAME:
cdef TYPE value
def __init__(self, MEMBER=None):
cdef int count
count = 0
INIT_ASSIGNMENTS
if IS_UNION and count > 1:
raise ValueError, "At most one union member should be specified."
def __str__(self):
return STR_FORMAT % MEMBER_TUPLE
def __repr__(self):
return REPR_FORMAT % MEMBER_TUPLE
""")
init_assignment = TreeFragment(u"""
if VALUE is not None:
ATTR = VALUE
count += 1
""")
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.
...@@ -1121,6 +1142,80 @@ property NAME: ...@@ -1121,6 +1142,80 @@ property NAME:
node.analyse_declarations(self.env_stack[-1]) node.analyse_declarations(self.env_stack[-1])
return node return node
def visit_CStructOrUnionDefNode(self, node):
# Create a wrapper node if needed.
# We want to use the struct type information (so it can't happen
# before this phase) but also create new objects to be declared
# (so it can't happen later).
# Note that we don't return the original node, as it is
# never used after this phase.
if True: # private (default)
return None
self_value = ExprNodes.AttributeNode(
pos = node.pos,
obj = ExprNodes.NameNode(pos=node.pos, name=u"self"),
attribute = EncodedString(u"value"))
var_entries = node.entry.type.scope.var_entries
attributes = []
for entry in var_entries:
attributes.append(ExprNodes.AttributeNode(pos = entry.pos,
obj = self_value,
attribute = entry.name))
# __init__ assignments
init_assignments = []
for entry, attr in zip(var_entries, attributes):
# TODO: branch on visibility
init_assignments.append(self.init_assignment.substitute({
u"VALUE": ExprNodes.NameNode(entry.pos, name = entry.name),
u"ATTR": attr,
}, pos = entry.pos))
# create the class
str_format = u"%s(%s)" % (node.entry.type.name, ("%s, " * len(attributes))[:-2])
wrapper_class = self.struct_or_union_wrapper.substitute({
u"INIT_ASSIGNMENTS": Nodes.StatListNode(node.pos, stats = init_assignments),
u"IS_UNION": ExprNodes.BoolNode(node.pos, value = not node.entry.type.is_struct),
u"MEMBER_TUPLE": ExprNodes.TupleNode(node.pos, args=attributes),
u"STR_FORMAT": ExprNodes.StringNode(node.pos, value = EncodedString(str_format)),
u"REPR_FORMAT": ExprNodes.StringNode(node.pos, value = EncodedString(str_format.replace("%s", "%r"))),
}, pos = node.pos).stats[0]
wrapper_class.class_name = node.name
wrapper_class.shadow = True
class_body = wrapper_class.body.stats
# fix value type
assert isinstance(class_body[0].base_type, Nodes.CSimpleBaseTypeNode)
class_body[0].base_type.name = node.name
# fix __init__ arguments
init_method = class_body[1]
assert isinstance(init_method, Nodes.DefNode) and init_method.name == '__init__'
arg_template = init_method.args[1]
if not node.entry.type.is_struct:
arg_template.kw_only = True
del init_method.args[1]
for entry, attr in zip(var_entries, attributes):
arg = copy.deepcopy(arg_template)
arg.declarator.name = entry.name
init_method.args.append(arg)
# setters/getters
for entry, attr in zip(var_entries, attributes):
# TODO: branch on visibility
if entry.type.is_pyobject:
template = self.basic_pyobject_property
else:
template = self.basic_property
property = template.substitute({
u"ATTR": attr,
}, pos = entry.pos).stats[0]
property.name = entry.name
wrapper_class.body.stats.append(property)
wrapper_class.analyse_declarations(self.env_stack[-1])
return self.visit_CClassDefNode(wrapper_class)
# Some nodes are no longer needed after declaration # Some nodes are no longer needed after declaration
# analysis and can be dropped. The analysis was performed # analysis and can be dropped. The analysis was performed
# on these nodes in a seperate recursive process from the # on these nodes in a seperate recursive process from the
...@@ -1142,9 +1237,6 @@ property NAME: ...@@ -1142,9 +1237,6 @@ property NAME:
else: else:
return None return None
def visit_CStructOrUnionDefNode(self, node):
return None
def visit_CNameDeclaratorNode(self, node): def visit_CNameDeclaratorNode(self, node):
if node.name in self.seen_vars_stack[-1]: if node.name in self.seen_vars_stack[-1]:
entry = self.env_stack[-1].lookup(node.name) entry = self.env_stack[-1].lookup(node.name)
......
...@@ -329,7 +329,7 @@ class Scope(object): ...@@ -329,7 +329,7 @@ class Scope(object):
# Return the module-level scope containing this scope. # Return the module-level scope containing this scope.
return self.outer_scope.builtin_scope() return self.outer_scope.builtin_scope()
def declare(self, name, cname, type, pos, visibility): def declare(self, name, cname, type, pos, visibility, shadow = 0):
# Create new entry, and add to dictionary if # Create new entry, and add to dictionary if
# name is not None. Reports a warning if already # name is not None. Reports a warning if already
# declared. # declared.
...@@ -339,7 +339,7 @@ class Scope(object): ...@@ -339,7 +339,7 @@ class Scope(object):
# See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
warning(pos, "'%s' is a reserved name in C." % cname, -1) warning(pos, "'%s' is a reserved name in C." % cname, -1)
entries = self.entries entries = self.entries
if name and name in entries: if name and name in entries and not shadow:
if visibility == 'extern': if visibility == 'extern':
warning(pos, "'%s' redeclared " % name, 0) warning(pos, "'%s' redeclared " % name, 0)
elif visibility != 'ignore': elif visibility != 'ignore':
...@@ -352,7 +352,8 @@ class Scope(object): ...@@ -352,7 +352,8 @@ class Scope(object):
# entries[name].overloaded_alternatives.append(entry) # entries[name].overloaded_alternatives.append(entry)
# else: # else:
# entries[name] = entry # entries[name] = entry
entries[name] = entry if not shadow:
entries[name] = entry
entry.scope = self entry.scope = self
entry.visibility = visibility entry.visibility = visibility
return entry return entry
...@@ -373,11 +374,11 @@ class Scope(object): ...@@ -373,11 +374,11 @@ class Scope(object):
return entry return entry
def declare_type(self, name, type, pos, def declare_type(self, name, type, pos,
cname = None, visibility = 'private', defining = 1): cname = None, visibility = 'private', defining = 1, shadow = 0):
# Add an entry for a type definition. # Add an entry for a type definition.
if not cname: if not cname:
cname = name cname = name
entry = self.declare(name, cname, type, pos, visibility) entry = self.declare(name, cname, type, pos, visibility, shadow)
entry.is_type = 1 entry.is_type = 1
if defining: if defining:
self.type_entries.append(entry) self.type_entries.append(entry)
...@@ -1029,7 +1030,7 @@ class ModuleScope(Scope): ...@@ -1029,7 +1030,7 @@ class ModuleScope(Scope):
def declare_c_class(self, name, pos, defining = 0, implementing = 0, def declare_c_class(self, name, pos, defining = 0, implementing = 0,
module_name = None, base_type = None, objstruct_cname = None, module_name = None, base_type = None, objstruct_cname = None,
typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0, typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
buffer_defaults = None): buffer_defaults = None, shadow = 0):
# If this is a non-extern typedef class, expose the typedef, but use # If this is a non-extern typedef class, expose the typedef, but use
# the non-typedef struct internally to avoid needing forward # the non-typedef struct internally to avoid needing forward
# declarations for anonymous structs. # declarations for anonymous structs.
...@@ -1044,7 +1045,7 @@ class ModuleScope(Scope): ...@@ -1044,7 +1045,7 @@ class ModuleScope(Scope):
# Look for previous declaration as a type # Look for previous declaration as a type
# #
entry = self.lookup_here(name) entry = self.lookup_here(name)
if entry: if entry and not shadow:
type = entry.type type = entry.type
if not (entry.is_type and type.is_extension_type): if not (entry.is_type and type.is_extension_type):
entry = None # Will cause redeclaration and produce an error entry = None # Will cause redeclaration and produce an error
...@@ -1060,7 +1061,7 @@ class ModuleScope(Scope): ...@@ -1060,7 +1061,7 @@ class ModuleScope(Scope):
# #
# Make a new entry if needed # Make a new entry if needed
# #
if not entry: if not entry or shadow:
type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern') type = PyrexTypes.PyExtensionType(name, typedef_flag, base_type, visibility == 'extern')
type.pos = pos type.pos = pos
type.buffer_defaults = buffer_defaults type.buffer_defaults = buffer_defaults
...@@ -1072,7 +1073,7 @@ class ModuleScope(Scope): ...@@ -1072,7 +1073,7 @@ class ModuleScope(Scope):
type.module_name = self.qualified_name type.module_name = self.qualified_name
type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name) type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
entry = self.declare_type(name, type, pos, visibility = visibility, entry = self.declare_type(name, type, pos, visibility = visibility,
defining = 0) defining = 0, shadow = shadow)
entry.is_cclass = True entry.is_cclass = True
if objstruct_cname: if objstruct_cname:
type.objstruct_cname = objstruct_cname type.objstruct_cname = objstruct_cname
......
...@@ -603,7 +603,7 @@ PyNumberMethods = ( ...@@ -603,7 +603,7 @@ PyNumberMethods = (
MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"), MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"),
MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3 = False), MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3 = False),
MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"), MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"),
MethodSlot(ternaryfunc, "nb_inplace_power", "__ipow__"), # NOT iternaryfunc!!! MethodSlot(ibinaryfunc, "nb_inplace_power", "__ipow__"), # actually ternaryfunc!!!
MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"), MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"),
MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__"), MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__"),
MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__"), MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__"),
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
cdef extern from *: cdef extern from *:
ctypedef char const_char "const char" ctypedef char const_char "const char"
cdef extern from "locale.h": cdef extern from "locale.h" nogil:
struct lconv: struct lconv:
char *decimal_point char *decimal_point
......
cdef extern from "math.h": cdef extern from "math.h" nogil:
enum: M_E enum: M_E
enum: M_LOG2E enum: M_LOG2E
......
...@@ -9,9 +9,12 @@ local: ...@@ -9,9 +9,12 @@ local:
.git: REV := $(shell cat .gitrev) .git: REV := $(shell cat .gitrev)
.git: TMPDIR := $(shell mktemp -d tmprepo.XXXXXX) .git: TMPDIR := $(shell mktemp -d tmprepo.XXXXXX)
.git: .git:
rm -rf $(TMPDIR)
git clone $(REPO) $(TMPDIR) git clone $(REPO) $(TMPDIR)
cd $(TMPDIR); git checkout -b working $(REV) cd $(TMPDIR); git checkout -b working $(REV)
mv $(TMPDIR)/{.git,.hgtags,.hgignore} . mv $(TMPDIR)/.hgtags .
mv $(TMPDIR)/.hgignore .
mv $(TMPDIR)/.git .
mv $(TMPDIR)/Doc/s5 Doc/s5 mv $(TMPDIR)/Doc/s5 Doc/s5
rm -rf $(TMPDIR) rm -rf $(TMPDIR)
......
...@@ -26,16 +26,16 @@ See LICENSE.txt. ...@@ -26,16 +26,16 @@ See LICENSE.txt.
-------------------------- --------------------------
Note that Cython used to ship the Mercurial (hg) repository in its source Note that Cython used to ship the full version control repository in its source
distribution, but no longer does so due to space constraints. To get the distribution, but no longer does so due to space constraints. To get the
full source history, make sure you have hg installed, then step into the full source history, make sure you have git installed, then step into the
base directory of the Cython source distribution and type base directory of the Cython source distribution and type
make repo make repo
Alternatively, check out the latest developer repository from Alternatively, check out the latest developer repository from
http://hg.cython.org/cython-devel https://github.com/cython/cython
......
...@@ -3,9 +3,6 @@ from distutils.sysconfig import get_python_lib ...@@ -3,9 +3,6 @@ from distutils.sysconfig import get_python_lib
import os, os.path import os, os.path
import sys import sys
if 'sdist' in sys.argv and sys.platform != "win32":
assert os.system("git show-ref -s HEAD > .gitrev") == 0
if sys.platform == "darwin": if sys.platform == "darwin":
# Don't create resource files on OS X tar. # Don't create resource files on OS X tar.
os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true' os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
...@@ -18,6 +15,15 @@ def add_command_class(name, cls): ...@@ -18,6 +15,15 @@ def add_command_class(name, cls):
cmdclasses[name] = cls cmdclasses[name] = cls
setup_args['cmdclass'] = cmdclasses setup_args['cmdclass'] = cmdclasses
from distutils.command.sdist import sdist as sdist_orig
class sdist(sdist_orig):
def run(self):
if (sys.platform != "win32" and
os.path.isdir('.git')):
assert os.system("git show-ref -s HEAD > .gitrev") == 0
sdist_orig.run(self)
add_command_class('sdist', sdist)
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
import lib2to3.refactor import lib2to3.refactor
from distutils.command.build_py \ from distutils.command.build_py \
......
...@@ -13,7 +13,6 @@ cpp_structs ...@@ -13,7 +13,6 @@ cpp_structs
with_statement_module_level_T536 with_statement_module_level_T536
function_as_method_T494 function_as_method_T494
closure_inside_cdef_T554 closure_inside_cdef_T554
ipow_crash_T562
pure_mode_cmethod_inheritance_T583 pure_mode_cmethod_inheritance_T583
genexpr_iterable_lookup_T600 genexpr_iterable_lookup_T600
for_from_pyvar_loop_T601 for_from_pyvar_loop_T601
......
class Foo:
@property
def foo(self):
return None
@property
def bar(self):
raise AttributeError
@property
def baz(self):
return int(1)/int(0)
def wrap_hasattr(obj, name):
"""
>>> wrap_hasattr(None, "abc")
False
>>> wrap_hasattr(list, "append")
True
>>> wrap_hasattr(Foo(), "foo")
True
>>> wrap_hasattr(Foo(), "spam")
False
>>> wrap_hasattr(Foo(), "bar")
False
>>> wrap_hasattr(Foo(), "baz") #doctest: +ELLIPSIS
Traceback (most recent call last):
...
ZeroDivisionError: ...
"""
return hasattr(obj, name)
class IPOW:
"""
>>> IPOW().__ipow__('a')
a
>>> x = IPOW()
>>> x **= 'z'
z
"""
def __ipow__(self, other):
print ("%s" % other)
cdef class CrashIPOW: cdef class CrashIPOW:
""" """
>>> CrashIPOW().__ipow__('a') >>> CrashIPOW().__ipow__('a')
a
>>> x = CrashIPOW()
>>> x **= 'z'
z
""" """
def __ipow__(self, other, mod): def __ipow__(self, other):
print "%s, %s" % (other, mod) print ("%s" % other)
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