Commit 39d60c71 authored by Stefan Behnel's avatar Stefan Behnel

merged in latest cython-devel (with minor merge fixes)

parents cad41704 137545fd
...@@ -132,6 +132,7 @@ class CodeWriter(TreeVisitor): ...@@ -132,6 +132,7 @@ class CodeWriter(TreeVisitor):
def visit_IntNode(self, node): def visit_IntNode(self, node):
self.put(node.value) self.put(node.value)
# FIXME: represent string nodes correctly
def visit_StringNode(self, node): def visit_StringNode(self, node):
value = node.value value = node.value
if value.encoding is not None: if value.encoding is not None:
......
from Cython.Compiler.Visitor import VisitorTransform, ScopeTrackingTransform, TreeVisitor from Cython.Compiler.Visitor import VisitorTransform, ScopeTrackingTransform, TreeVisitor
from Nodes import StatListNode, SingleAssignmentNode, CFuncDefNode from Nodes import StatListNode, SingleAssignmentNode, CFuncDefNode
from ExprNodes import (DictNode, DictItemNode, NameNode, UnicodeNode, NoneNode, from ExprNodes import DictNode, DictItemNode, NameNode, UnicodeNode, NoneNode, \
ExprNode, AttributeNode, ModuleRefNode, DocstringRefNode) ExprNode, AttributeNode, ModuleRefNode, DocstringRefNode
from PyrexTypes import py_object_type from PyrexTypes import py_object_type
from Builtin import dict_type from Builtin import dict_type
from StringEncoding import EncodedString from StringEncoding import EncodedString
...@@ -10,6 +10,8 @@ import Naming ...@@ -10,6 +10,8 @@ import Naming
class AutoTestDictTransform(ScopeTrackingTransform): class AutoTestDictTransform(ScopeTrackingTransform):
# Handles autotestdict directive # Handles autotestdict directive
blacklist = ['__cinit__', '__dealloc__', '__richcmp__', '__nonzero__']
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
self.scope_type = 'module' self.scope_type = 'module'
self.scope_node = node self.scope_node = node
...@@ -62,6 +64,12 @@ class AutoTestDictTransform(ScopeTrackingTransform): ...@@ -62,6 +64,12 @@ class AutoTestDictTransform(ScopeTrackingTransform):
parent = ModuleRefNode(pos) parent = ModuleRefNode(pos)
name = node.entry.name name = node.entry.name
elif self.scope_type in ('pyclass', 'cclass'): elif self.scope_type in ('pyclass', 'cclass'):
if isinstance(node, CFuncDefNode):
name = node.py_func.name
else:
name = node.name
if self.scope_type == 'cclass' and name in self.blacklist:
return node
mod = ModuleRefNode(pos) mod = ModuleRefNode(pos)
if self.scope_type == 'pyclass': if self.scope_type == 'pyclass':
clsname = self.scope_node.name clsname = self.scope_node.name
......
...@@ -3,9 +3,7 @@ from Cython.Compiler.Nodes import DefNode, CFuncDefNode ...@@ -3,9 +3,7 @@ from Cython.Compiler.Nodes import DefNode, CFuncDefNode
from Cython.Compiler.Errors import CompileError from Cython.Compiler.Errors import CompileError
from Cython.Compiler.StringEncoding import EncodedString from Cython.Compiler.StringEncoding import EncodedString
from Cython.Compiler import Options from Cython.Compiler import Options
from Cython.Compiler import PyrexTypes from Cython.Compiler import PyrexTypes, ExprNodes
class EmbedSignature(CythonTransform): class EmbedSignature(CythonTransform):
...@@ -16,15 +14,26 @@ class EmbedSignature(CythonTransform): ...@@ -16,15 +14,26 @@ class EmbedSignature(CythonTransform):
self.class_node = None self.class_node = None
def _fmt_arg_defv(self, arg): def _fmt_arg_defv(self, arg):
if not arg.default: default_val = arg.default
if not default_val:
return None return None
try: try:
denv = self.denv # XXX denv = self.denv # XXX
ctval = arg.default.compile_time_value(self.denv) ctval = default_val.compile_time_value(self.denv)
return '%r' % ctval repr_val = '%r' % ctval
if isinstance(default_val, ExprNodes.UnicodeNode):
if repr_val[:1] != 'u':
return u'u%s' % repr_val
elif isinstance(default_val, ExprNodes.BytesNode):
if repr_val[:1] != 'b':
return u'b%s' % repr_val
elif isinstance(default_val, ExprNodes.StringNode):
if repr_val[:1] in ('u', 'b'):
repr_val[1:]
return repr_val
except Exception: except Exception:
try: try:
return arg.default.name # XXX return default_val.name # XXX
except AttributeError: except AttributeError:
return '<???>' return '<???>'
......
...@@ -392,13 +392,15 @@ def init_builtins(): ...@@ -392,13 +392,15 @@ def init_builtins():
init_builtin_funcs() init_builtin_funcs()
init_builtin_types() init_builtin_types()
init_builtin_structs() init_builtin_structs()
global list_type, tuple_type, dict_type, set_type, bytes_type, unicode_type, type_type global list_type, tuple_type, dict_type, set_type, type_type
global bytes_type, str_type, unicode_type
type_type = builtin_scope.lookup('type').type type_type = builtin_scope.lookup('type').type
list_type = builtin_scope.lookup('list').type list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type tuple_type = builtin_scope.lookup('tuple').type
dict_type = builtin_scope.lookup('dict').type dict_type = builtin_scope.lookup('dict').type
set_type = builtin_scope.lookup('set').type set_type = builtin_scope.lookup('set').type
bytes_type = builtin_scope.lookup('bytes').type bytes_type = builtin_scope.lookup('bytes').type
str_type = builtin_scope.lookup('str').type
unicode_type = builtin_scope.lookup('unicode').type unicode_type = builtin_scope.lookup('unicode').type
init_builtins() init_builtins()
...@@ -39,12 +39,12 @@ Options: ...@@ -39,12 +39,12 @@ Options:
--line-directives Produce #line directives pointing to the .pyx source --line-directives Produce #line directives pointing to the .pyx source
--cplus Output a c++ rather than c file. --cplus Output a c++ rather than c file.
--embed Embed the Python interpreter in a main() method. --embed Embed the Python interpreter in a main() method.
--directive <name>=<value>[,<name=value,...] Overrides a compiler directive -X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
""" """
#The following experimental options are supported only on MacOSX: #The following experimental options are supported only on MacOSX:
# -C, --compile Compile generated .c file to .o file # -C, --compile Compile generated .c file to .o file
# -X, --link Link .o file to produce extension module (implies -C) # --link Link .o file to produce extension module (implies -C)
# -+, --cplus Use C++ compiler for compiling and linking # -+, --cplus Use C++ compiler for compiling and linking
# Additional .o files to link may be supplied when using -X.""" # Additional .o files to link may be supplied when using -X."""
...@@ -81,11 +81,7 @@ def parse_command_line(args): ...@@ -81,11 +81,7 @@ def parse_command_line(args):
options.use_listing_file = 1 options.use_listing_file = 1
elif option in ("-C", "--compile"): elif option in ("-C", "--compile"):
options.c_only = 0 options.c_only = 0
elif option in ("-X", "--link"): elif option in ("--link"):
if option == "-X":
print >>sys.stderr, "Deprecation warning: The -X command line switch will be changed to a"
print >>sys.stderr, "shorthand for --directive in Cython 0.12. Please use --link instead."
print >>sys.stderr
options.c_only = 0 options.c_only = 0
options.obj_only = 0 options.obj_only = 0
elif option in ("-+", "--cplus"): elif option in ("-+", "--cplus"):
...@@ -126,7 +122,7 @@ def parse_command_line(args): ...@@ -126,7 +122,7 @@ def parse_command_line(args):
options.emit_linenums = True options.emit_linenums = True
elif option in ("-X", "--directive"): elif option in ("-X", "--directive"):
try: try:
options.compiler_directives = Options.parse_option_list(pop_arg()) options.compiler_directives = Options.parse_directive_list(pop_arg())
except ValueError, e: except ValueError, e:
sys.stderr.write("Error in compiler directive: %s\n" % e.message) sys.stderr.write("Error in compiler directive: %s\n" % e.message)
sys.exit(1) sys.exit(1)
......
...@@ -289,7 +289,8 @@ class PyObjectConst(object): ...@@ -289,7 +289,8 @@ class PyObjectConst(object):
possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match possible_bytes_identifier = re.compile(r"(?![0-9])\w+$".encode('ASCII')).match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match nice_identifier = re.compile('^[a-zA-Z0-9_]+$').match
find_alphanums = re.compile('([a-zA-Z0-9]+)').findall
class StringConst(object): class StringConst(object):
"""Global info about a C string constant held by GlobalState. """Global info about a C string constant held by GlobalState.
...@@ -304,19 +305,31 @@ class StringConst(object): ...@@ -304,19 +305,31 @@ class StringConst(object):
self.escaped_value = StringEncoding.escape_byte_string(byte_string) self.escaped_value = StringEncoding.escape_byte_string(byte_string)
self.py_strings = None self.py_strings = None
def get_py_string_const(self, encoding, identifier=None): def get_py_string_const(self, encoding, identifier=None, is_str=False):
py_strings = self.py_strings py_strings = self.py_strings
text = self.text text = self.text
if encoding is not None:
encoding = encoding.upper()
key = (bool(identifier), encoding) is_str = bool(identifier or is_str)
is_unicode = encoding is None and not is_str
if encoding is None:
# unicode string
encoding_key = None
else:
# bytes or str
encoding = encoding.lower()
if encoding in ('utf8', 'utf-8', 'ascii', 'usascii', 'us-ascii'):
encoding = None
encoding_key = None
else:
encoding_key = ''.join(find_alphanums(encoding))
key = (is_str, is_unicode, encoding_key)
if py_strings is not None and key in py_strings: if py_strings is not None and key in py_strings:
py_string = py_strings[key] py_string = py_strings[key]
else: else:
if py_strings is None: if py_strings is None:
self.py_strings = {} self.py_strings = {}
is_unicode = encoding is None
if identifier: if identifier:
intern = True intern = True
elif identifier is None: elif identifier is None:
...@@ -330,14 +343,13 @@ class StringConst(object): ...@@ -330,14 +343,13 @@ class StringConst(object):
prefix = Naming.interned_str_prefix prefix = Naming.interned_str_prefix
else: else:
prefix = Naming.py_const_prefix prefix = Naming.py_const_prefix
pystring_cname = "%s%s%s_%s" % ( pystring_cname = "%s%s_%s" % (
prefix, prefix,
is_unicode and 'u' or 'b', (is_str and 's') or (is_unicode and 'u') or 'b',
identifier and 'i' or '',
self.cname[len(Naming.const_prefix):]) self.cname[len(Naming.const_prefix):])
py_string = PyStringConst( py_string = PyStringConst(
pystring_cname, is_unicode, bool(identifier), intern) pystring_cname, encoding, is_unicode, is_str, intern)
self.py_strings[key] = py_string self.py_strings[key] = py_string
return py_string return py_string
...@@ -346,14 +358,16 @@ class PyStringConst(object): ...@@ -346,14 +358,16 @@ class PyStringConst(object):
"""Global info about a Python string constant held by GlobalState. """Global info about a Python string constant held by GlobalState.
""" """
# cname string # cname string
# unicode boolean # encoding string
# intern boolean # intern boolean
# identifier boolean # is_unicode boolean
# is_str boolean
def __init__(self, cname, is_unicode, identifier=False, intern=False): def __init__(self, cname, encoding, is_unicode, is_str=False, intern=False):
self.cname = cname self.cname = cname
self.identifier = identifier self.encoding = encoding
self.unicode = is_unicode self.is_str = is_str
self.is_unicode = is_unicode
self.intern = intern self.intern = intern
def __lt__(self, other): def __lt__(self, other):
...@@ -393,7 +407,6 @@ class GlobalState(object): ...@@ -393,7 +407,6 @@ class GlobalState(object):
code_layout = [ code_layout = [
'h_code', 'h_code',
'complex_numbers_utility_code',
'utility_code_proto_before_types', 'utility_code_proto_before_types',
'type_declarations', 'type_declarations',
'utility_code_proto', 'utility_code_proto',
...@@ -511,6 +524,11 @@ class GlobalState(object): ...@@ -511,6 +524,11 @@ class GlobalState(object):
w.putln("}") w.putln("}")
w.exit_cfunc_scope() w.exit_cfunc_scope()
if Options.generate_cleanup_code:
w = self.parts['cleanup_globals']
w.putln("}")
w.exit_cfunc_scope()
if Options.generate_cleanup_code: if Options.generate_cleanup_code:
w = self.parts['cleanup_module'] w = self.parts['cleanup_module']
w.putln("}") w.putln("}")
...@@ -545,12 +563,15 @@ class GlobalState(object): ...@@ -545,12 +563,15 @@ class GlobalState(object):
c = self.new_string_const(text, byte_string) c = self.new_string_const(text, byte_string)
return c return c
def get_py_string_const(self, text, identifier=None): def get_py_string_const(self, text, identifier=None, is_str=False):
# return a Python string constant, creating a new one if necessary # return a Python string constant, creating a new one if necessary
c_string = self.get_string_const(text) c_string = self.get_string_const(text)
py_string = c_string.get_py_string_const(text.encoding, identifier) py_string = c_string.get_py_string_const(text.encoding, identifier, is_str)
return py_string return py_string
def get_interned_identifier(self, text):
return self.get_py_string_const(text, identifier=True)
def new_string_const(self, text, byte_string): def new_string_const(self, text, byte_string):
cname = self.new_string_const_cname(byte_string) cname = self.new_string_const_cname(byte_string)
c = StringConst(cname, text, byte_string) c = StringConst(cname, text, byte_string)
...@@ -577,7 +598,7 @@ class GlobalState(object): ...@@ -577,7 +598,7 @@ class GlobalState(object):
return self.new_const_cname() return self.new_const_cname()
if len(value) < 20 and nice_identifier(value): if len(value) < 20 and nice_identifier(value):
return "%s%s" % (Naming.const_prefix, value) return "%s_%s" % (Naming.const_prefix, value)
else: else:
return self.new_const_cname() return self.new_const_cname()
...@@ -596,7 +617,7 @@ class GlobalState(object): ...@@ -596,7 +617,7 @@ class GlobalState(object):
def add_cached_builtin_decl(self, entry): def add_cached_builtin_decl(self, entry):
if Options.cache_builtins: if Options.cache_builtins:
if self.should_declare(entry.cname, entry): if self.should_declare(entry.cname, entry):
interned_cname = self.get_py_string_const(entry.name, True).cname interned_cname = self.get_interned_identifier(entry.name).cname
self.put_pyobject_decl(entry) self.put_pyobject_decl(entry)
w = self.parts['cached_builtins'] w = self.parts['cached_builtins']
w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % ( w.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
...@@ -644,18 +665,26 @@ class GlobalState(object): ...@@ -644,18 +665,26 @@ class GlobalState(object):
w.putln("static __Pyx_StringTabEntry %s[] = {" % w.putln("static __Pyx_StringTabEntry %s[] = {" %
Naming.stringtab_cname) Naming.stringtab_cname)
for c_cname, _, py_string in py_strings: for c_cname, _, py_string in py_strings:
if not py_string.is_str or not py_string.encoding or \
py_string.encoding in ('ASCII', 'USASCII', 'US-ASCII',
'UTF8', 'UTF-8'):
encoding = '0'
else:
encoding = '"%s"' % py_string.encoding.lower()
decls_writer.putln( decls_writer.putln(
"static PyObject *%s;" % py_string.cname) "static PyObject *%s;" % py_string.cname)
w.putln( w.putln(
"{&%s, %s, sizeof(%s), %d, %d, %d}," % ( "{&%s, %s, sizeof(%s), %s, %d, %d, %d}," % (
py_string.cname, py_string.cname,
c_cname, c_cname,
c_cname, c_cname,
py_string.unicode, encoding,
py_string.intern, py_string.is_unicode,
py_string.identifier py_string.is_str,
py_string.intern
)) ))
w.putln("{0, 0, 0, 0, 0, 0}") w.putln("{0, 0, 0, 0, 0, 0, 0}")
w.putln("};") w.putln("};")
init_globals = self.parts['init_globals'] init_globals = self.parts['init_globals']
...@@ -718,8 +747,9 @@ class GlobalState(object): ...@@ -718,8 +747,9 @@ class GlobalState(object):
u'*/', u'*[inserted by cython to avoid comment closer]/' u'*/', u'*[inserted by cython to avoid comment closer]/'
).replace( ).replace(
u'/*', u'/[inserted by cython to avoid comment start]*' u'/*', u'/[inserted by cython to avoid comment start]*'
).encode('ASCII', 'replace').decode('ASCII') )
for line in source_desc.get_lines()] for line in source_desc.get_lines(encoding='ASCII',
error_handling='ignore')]
if len(F) == 0: F.append(u'') if len(F) == 0: F.append(u'')
self.input_file_contents[source_desc] = F self.input_file_contents[source_desc] = F
return F return F
...@@ -889,8 +919,8 @@ class CCodeWriter(object): ...@@ -889,8 +919,8 @@ class CCodeWriter(object):
def get_string_const(self, text): def get_string_const(self, text):
return self.globalstate.get_string_const(text).cname return self.globalstate.get_string_const(text).cname
def get_py_string_const(self, text, identifier=None): def get_py_string_const(self, text, identifier=None, is_str=False):
return self.globalstate.get_py_string_const(text, identifier).cname return self.globalstate.get_py_string_const(text, identifier, is_str).cname
def get_argument_default_const(self, type): def get_argument_default_const(self, type):
return self.globalstate.get_py_const(type).cname return self.globalstate.get_py_const(type).cname
...@@ -899,7 +929,7 @@ class CCodeWriter(object): ...@@ -899,7 +929,7 @@ class CCodeWriter(object):
return self.get_py_string_const(text) return self.get_py_string_const(text)
def intern_identifier(self, text): def intern_identifier(self, text):
return self.get_py_string_const(text, True) return self.get_py_string_const(text, identifier=True)
# code generation # code generation
...@@ -1244,10 +1274,10 @@ class CCodeWriter(object): ...@@ -1244,10 +1274,10 @@ class CCodeWriter(object):
return self.globalstate.lookup_filename(filename) return self.globalstate.lookup_filename(filename)
def put_setup_refcount_context(self, name): def put_setup_refcount_context(self, name):
self.putln('__Pyx_SetupRefcountContext("%s");' % name) self.putln('__Pyx_RefNannySetupContext("%s");' % name)
def put_finish_refcount_context(self): def put_finish_refcount_context(self):
self.putln("__Pyx_FinishRefcountContext();") self.putln("__Pyx_RefNannyFinishContext();")
def put_trace_call(self, name, pos): 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])); self.putln('__Pyx_TraceCall("%s", %s[%s], %s);' % (name, Naming.filetable_cname, self.lookup_filename(pos[0]), pos[1]));
......
This diff is collapsed.
...@@ -87,6 +87,7 @@ class Context(object): ...@@ -87,6 +87,7 @@ class Context(object):
from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods
from TypeInference import MarkAssignments
from ParseTreeTransforms import AlignFunctionDefinitions, GilCheck from ParseTreeTransforms import AlignFunctionDefinitions, GilCheck
from AnalysedTreeTransforms import AutoTestDictTransform from AnalysedTreeTransforms import AutoTestDictTransform
from AutoDocTransforms import EmbedSignature from AutoDocTransforms import EmbedSignature
...@@ -131,6 +132,7 @@ class Context(object): ...@@ -131,6 +132,7 @@ class Context(object):
CreateClosureClasses(self), CreateClosureClasses(self),
AutoTestDictTransform(self), AutoTestDictTransform(self),
EmbedSignature(self), EmbedSignature(self),
MarkAssignments(self),
TransformBuiltinMethods(self), TransformBuiltinMethods(self),
IntroduceBufferAuxiliaryVars(self), IntroduceBufferAuxiliaryVars(self),
_check_c_declarations, _check_c_declarations,
......
This diff is collapsed.
This diff is collapsed.
...@@ -20,6 +20,11 @@ try: ...@@ -20,6 +20,11 @@ try:
except NameError: except NameError:
from functools import reduce from functools import reduce
try:
set
except NameError:
from sets import Set as set
def unwrap_node(node): def unwrap_node(node):
while isinstance(node, UtilNodes.ResultRefNode): while isinstance(node, UtilNodes.ResultRefNode):
node = node.expression node = node.expression
...@@ -224,7 +229,7 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -224,7 +229,7 @@ class IterationTransform(Visitor.VisitorTransform):
bound2 = args[1].coerce_to_integer(self.current_scope) bound2 = args[1].coerce_to_integer(self.current_scope)
step = step.coerce_to_integer(self.current_scope) step = step.coerce_to_integer(self.current_scope)
if not isinstance(bound2, ExprNodes.ConstNode): if not bound2.is_literal:
# stop bound must be immutable => keep it in a temp var # stop bound must be immutable => keep it in a temp var
bound2_is_temp = True bound2_is_temp = True
bound2 = UtilNodes.LetRefNode(bound2) bound2 = UtilNodes.LetRefNode(bound2)
...@@ -416,12 +421,12 @@ class SwitchTransform(Visitor.VisitorTransform): ...@@ -416,12 +421,12 @@ class SwitchTransform(Visitor.VisitorTransform):
and cond.operator == '==' and cond.operator == '=='
and not cond.is_python_comparison()): and not cond.is_python_comparison()):
if is_common_value(cond.operand1, cond.operand1): if is_common_value(cond.operand1, cond.operand1):
if isinstance(cond.operand2, ExprNodes.ConstNode): if cond.operand2.is_literal:
return cond.operand1, [cond.operand2] return cond.operand1, [cond.operand2]
elif hasattr(cond.operand2, 'entry') and cond.operand2.entry and cond.operand2.entry.is_const: elif hasattr(cond.operand2, 'entry') and cond.operand2.entry and cond.operand2.entry.is_const:
return cond.operand1, [cond.operand2] return cond.operand1, [cond.operand2]
if is_common_value(cond.operand2, cond.operand2): if is_common_value(cond.operand2, cond.operand2):
if isinstance(cond.operand1, ExprNodes.ConstNode): if cond.operand1.is_literal:
return cond.operand2, [cond.operand1] return cond.operand2, [cond.operand1]
elif hasattr(cond.operand1, 'entry') and cond.operand1.entry and cond.operand1.entry.is_const: elif hasattr(cond.operand1, 'entry') and cond.operand1.entry and cond.operand1.entry.is_const:
return cond.operand2, [cond.operand1] return cond.operand2, [cond.operand1]
...@@ -517,6 +522,46 @@ class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations): ...@@ -517,6 +522,46 @@ class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations):
visit_Node = Visitor.VisitorTransform.recurse_to_children visit_Node = Visitor.VisitorTransform.recurse_to_children
class DropRefcountingTransform(Visitor.VisitorTransform):
"""Drop ref-counting in safe places.
"""
visit_Node = Visitor.VisitorTransform.recurse_to_children
def visit_ParallelAssignmentNode(self, node):
left, right, temps = [], [], []
for stat in node.stats:
if isinstance(stat, Nodes.SingleAssignmentNode):
lhs = unwrap_node(stat.lhs)
if not isinstance(lhs, ExprNodes.NameNode):
return node
left.append(lhs)
rhs = unwrap_node(stat.rhs)
if isinstance(rhs, ExprNodes.CoerceToTempNode):
temps.append(rhs)
rhs = rhs.arg
if not isinstance(rhs, ExprNodes.NameNode):
return node
right.append(rhs)
else:
return node
for name_node in left + right:
if name_node.entry.is_builtin or name_node.entry.is_pyglobal:
return node
left_names = [n.name for n in left]
right_names = [n.name for n in right]
if set(left_names) != set(right_names):
return node
if len(set(left_names)) != len(right):
return node
for name_node in left + right + temps:
name_node.use_managed_ref = False
return node
class OptimizeBuiltinCalls(Visitor.VisitorTransform): class OptimizeBuiltinCalls(Visitor.VisitorTransform):
"""Optimize some common methods calls and instantiation patterns """Optimize some common methods calls and instantiation patterns
for builtin types. for builtin types.
...@@ -853,10 +898,11 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -853,10 +898,11 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
encoding_node = args[1] encoding_node = args[1]
if isinstance(encoding_node, ExprNodes.CoerceToPyTypeNode): if isinstance(encoding_node, ExprNodes.CoerceToPyTypeNode):
encoding_node = encoding_node.arg encoding_node = encoding_node.arg
if not isinstance(encoding_node, (ExprNodes.UnicodeNode, ExprNodes.StringNode)): if not isinstance(encoding_node, (ExprNodes.UnicodeNode, ExprNodes.StringNode,
ExprNodes.BytesNode)):
return node return node
encoding = encoding_node.value encoding = encoding_node.value
encoding_node = ExprNodes.StringNode(encoding_node.pos, value=encoding, encoding_node = ExprNodes.BytesNode(encoding_node.pos, value=encoding,
type=PyrexTypes.c_char_ptr_type) type=PyrexTypes.c_char_ptr_type)
if len(args) == 3: if len(args) == 3:
...@@ -864,13 +910,14 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -864,13 +910,14 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
if isinstance(error_handling_node, ExprNodes.CoerceToPyTypeNode): if isinstance(error_handling_node, ExprNodes.CoerceToPyTypeNode):
error_handling_node = error_handling_node.arg error_handling_node = error_handling_node.arg
if not isinstance(error_handling_node, if not isinstance(error_handling_node,
(ExprNodes.UnicodeNode, ExprNodes.StringNode)): (ExprNodes.UnicodeNode, ExprNodes.StringNode,
ExprNodes.BytesNode)):
return node return node
error_handling = error_handling_node.value error_handling = error_handling_node.value
if error_handling == 'strict': if error_handling == 'strict':
error_handling_node = null_node error_handling_node = null_node
else: else:
error_handling_node = ExprNodes.StringNode( error_handling_node = ExprNodes.BytesNode(
error_handling_node.pos, value=error_handling, error_handling_node.pos, value=error_handling,
type=PyrexTypes.c_char_ptr_type) type=PyrexTypes.c_char_ptr_type)
else: else:
...@@ -887,7 +934,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform): ...@@ -887,7 +934,7 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
else: else:
value = BytesLiteral(value) value = BytesLiteral(value)
value.encoding = encoding value.encoding = encoding
return ExprNodes.StringNode( return ExprNodes.BytesNode(
string_node.pos, value=value, type=Builtin.bytes_type) string_node.pos, value=value, type=Builtin.bytes_type)
if error_handling == 'strict': if error_handling == 'strict':
...@@ -1030,8 +1077,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -1030,8 +1077,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
# the compiler, but we do not aggregate them into a # the compiler, but we do not aggregate them into a
# constant node to prevent any loss of precision. # constant node to prevent any loss of precision.
return node return node
if not isinstance(node.operand1, ExprNodes.ConstNode) or \ if not node.operand1.is_literal or not node.operand2.is_literal:
not isinstance(node.operand2, ExprNodes.ConstNode):
# We calculate other constants to make them available to # We calculate other constants to make them available to
# the compiler, but we only aggregate constant nodes # the compiler, but we only aggregate constant nodes
# recursively, so non-const nodes are straight out. # recursively, so non-const nodes are straight out.
......
...@@ -55,7 +55,7 @@ embed = False ...@@ -55,7 +55,7 @@ embed = False
# Declare compiler directives # Declare compiler directives
option_defaults = { directive_defaults = {
'boundscheck' : True, 'boundscheck' : True,
'nonecheck' : False, 'nonecheck' : False,
'embedsignature' : False, 'embedsignature' : False,
...@@ -65,9 +65,10 @@ option_defaults = { ...@@ -65,9 +65,10 @@ option_defaults = {
'cdivision_warnings': False, 'cdivision_warnings': False,
'always_allow_keywords': False, 'always_allow_keywords': False,
'wraparound' : True, 'wraparound' : True,
'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this... 'ccomplex' : False, # use C99/C++ for complex types and arith
'callspec' : "", 'callspec' : "",
'profile': False, 'profile': False,
'infer_types': False,
'autotestdict': True, 'autotestdict': True,
# test support # test support
...@@ -76,35 +77,35 @@ option_defaults = { ...@@ -76,35 +77,35 @@ option_defaults = {
} }
# Override types possibilities above, if needed # Override types possibilities above, if needed
option_types = {} directive_types = {}
for key, val in option_defaults.items(): for key, val in directive_defaults.items():
if key not in option_types: if key not in directive_types:
option_types[key] = type(val) directive_types[key] = type(val)
option_scopes = { # defaults to available everywhere directive_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement' # 'module', 'function', 'class', 'with statement'
'autotestdict' : ('module',), 'autotestdict' : ('module',),
'test_assert_path_exists' : ('function',), 'test_assert_path_exists' : ('function',),
'test_fail_if_path_exists' : ('function',), 'test_fail_if_path_exists' : ('function',),
} }
def parse_option_value(name, value): def parse_directive_value(name, value):
""" """
Parses value as an option value for the given name and returns Parses value as an option value for the given name and returns
the interpreted value. None is returned if the option does not exist. the interpreted value. None is returned if the option does not exist.
>>> print parse_option_value('nonexisting', 'asdf asdfd') >>> print parse_directive_value('nonexisting', 'asdf asdfd')
None None
>>> parse_option_value('boundscheck', 'True') >>> parse_directive_value('boundscheck', 'True')
True True
>>> parse_option_value('boundscheck', 'true') >>> parse_directive_value('boundscheck', 'true')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: boundscheck directive must be set to True or False ValueError: boundscheck directive must be set to True or False
""" """
type = option_types.get(name) type = directive_types.get(name)
if not type: return None if not type: return None
if type is bool: if type is bool:
if value == "True": return True if value == "True": return True
...@@ -118,25 +119,25 @@ def parse_option_value(name, value): ...@@ -118,25 +119,25 @@ def parse_option_value(name, value):
else: else:
assert False assert False
def parse_option_list(s): def parse_directive_list(s):
""" """
Parses a comma-seperated list of pragma options. Whitespace Parses a comma-seperated list of pragma options. Whitespace
is not considered. is not considered.
>>> parse_option_list(' ') >>> parse_directive_list(' ')
{} {}
>>> (parse_option_list('boundscheck=True') == >>> (parse_directive_list('boundscheck=True') ==
... {'boundscheck': True}) ... {'boundscheck': True})
True True
>>> parse_option_list(' asdf') >>> parse_directive_list(' asdf')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: Expected "=" in option "asdf" ValueError: Expected "=" in option "asdf"
>>> parse_option_list('boundscheck=hey') >>> parse_directive_list('boundscheck=hey')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: Must pass a boolean value for option "boundscheck" ValueError: Must pass a boolean value for option "boundscheck"
>>> parse_option_list('unknown=True') >>> parse_directive_list('unknown=True')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValueError: Unknown option: "unknown" ValueError: Unknown option: "unknown"
...@@ -148,7 +149,7 @@ def parse_option_list(s): ...@@ -148,7 +149,7 @@ def parse_option_list(s):
if not '=' in item: raise ValueError('Expected "=" in option "%s"' % item) if not '=' in item: raise ValueError('Expected "=" in option "%s"' % item)
name, value = item.strip().split('=') name, value = item.strip().split('=')
try: try:
type = option_types[name] type = directive_types[name]
except KeyError: except KeyError:
raise ValueError('Unknown option: "%s"' % name) raise ValueError('Unknown option: "%s"' % name)
if type is bool: if type is bool:
......
This diff is collapsed.
...@@ -14,7 +14,7 @@ from Cython.Compiler.Scanning import PyrexScanner, FileSourceDescriptor ...@@ -14,7 +14,7 @@ from Cython.Compiler.Scanning import PyrexScanner, FileSourceDescriptor
import Nodes import Nodes
import ExprNodes import ExprNodes
import StringEncoding import StringEncoding
from StringEncoding import EncodedString, BytesLiteral, _str, _bytes from StringEncoding import EncodedString, BytesLiteral, _unicode, _bytes
from ModuleNode import ModuleNode from ModuleNode import ModuleNode
from Errors import error, warning, InternalError from Errors import error, warning, InternalError
from Cython import Utils from Cython import Utils
...@@ -387,8 +387,7 @@ def p_call(s, function): ...@@ -387,8 +387,7 @@ def p_call(s, function):
s.error("Expected an identifier before '='", s.error("Expected an identifier before '='",
pos = arg.pos) pos = arg.pos)
encoded_name = EncodedString(arg.name) encoded_name = EncodedString(arg.name)
keyword = ExprNodes.IdentifierStringNode(arg.pos, keyword = ExprNodes.IdentifierStringNode(arg.pos, value = encoded_name)
value = encoded_name)
arg = p_simple_expr(s) arg = p_simple_expr(s)
keyword_args.append((keyword, arg)) keyword_args.append((keyword, arg))
else: else:
...@@ -579,6 +578,8 @@ def p_atom(s): ...@@ -579,6 +578,8 @@ def p_atom(s):
return ExprNodes.CharNode(pos, value = value) return ExprNodes.CharNode(pos, value = value)
elif kind == 'u': elif kind == 'u':
return ExprNodes.UnicodeNode(pos, value = value) return ExprNodes.UnicodeNode(pos, value = value)
elif kind == 'b':
return ExprNodes.BytesNode(pos, value = value)
else: else:
return ExprNodes.StringNode(pos, value = value) return ExprNodes.StringNode(pos, value = value)
elif sy == 'IDENT': elif sy == 'IDENT':
...@@ -610,8 +611,10 @@ def p_name(s, name): ...@@ -610,8 +611,10 @@ def p_name(s, name):
return ExprNodes.IntNode(pos, value = rep, longness = "L") return ExprNodes.IntNode(pos, value = rep, longness = "L")
elif isinstance(value, float): elif isinstance(value, float):
return ExprNodes.FloatNode(pos, value = rep) return ExprNodes.FloatNode(pos, value = rep)
elif isinstance(value, (_str, _bytes)): elif isinstance(value, _unicode):
return ExprNodes.StringNode(pos, value = value) return ExprNodes.UnicodeNode(pos, value = value)
elif isinstance(value, _bytes):
return ExprNodes.BytesNode(pos, value = value)
else: else:
error(pos, "Invalid type for compile-time constant: %s" error(pos, "Invalid type for compile-time constant: %s"
% value.__class__.__name__) % value.__class__.__name__)
...@@ -619,24 +622,20 @@ def p_name(s, name): ...@@ -619,24 +622,20 @@ def p_name(s, name):
def p_cat_string_literal(s): def p_cat_string_literal(s):
# A sequence of one or more adjacent string literals. # A sequence of one or more adjacent string literals.
# Returns (kind, value) where kind in ('b', 'c', 'u') # Returns (kind, value) where kind in ('b', 'c', 'u', '')
kind, value = p_string_literal(s) kind, value = p_string_literal(s)
if s.sy != 'BEGIN_STRING':
return kind, value
if kind != 'c': if kind != 'c':
strings = [value] strings = [value]
while s.sy == 'BEGIN_STRING': while s.sy == 'BEGIN_STRING':
pos = s.position()
next_kind, next_value = p_string_literal(s) next_kind, next_value = p_string_literal(s)
if next_kind == 'c': if next_kind == 'c':
error(s.position(), error(pos, "Cannot concatenate char literal with another string or char literal")
"Cannot concatenate char literal with another string or char literal")
elif next_kind != kind: elif next_kind != kind:
# we have to switch to unicode now error(pos, "Cannot mix string literals of different types, expected %s'', got %s''" %
if kind == 'b': (kind, next_kind))
# concatenating a unicode string to byte strings
strings = [u''.join([s.decode(s.encoding) for s in strings])]
elif kind == 'u':
# concatenating a byte string to unicode strings
strings.append(next_value.decode(next_value.encoding))
kind = 'u'
else: else:
strings.append(next_value) strings.append(next_value)
if kind == 'u': if kind == 'u':
...@@ -669,8 +668,6 @@ def p_string_literal(s): ...@@ -669,8 +668,6 @@ def p_string_literal(s):
if Future.unicode_literals in s.context.future_directives: if Future.unicode_literals in s.context.future_directives:
if kind == '': if kind == '':
kind = 'u' kind = 'u'
elif kind == '':
kind = 'b'
if kind == 'u': if kind == 'u':
chars = StringEncoding.UnicodeLiteralBuilder() chars = StringEncoding.UnicodeLiteralBuilder()
else: else:
...@@ -935,7 +932,7 @@ def p_expression_or_assignment(s): ...@@ -935,7 +932,7 @@ def p_expression_or_assignment(s):
rhs = p_expr(s) rhs = p_expr(s)
return Nodes.InPlaceAssignmentNode(lhs.pos, operator = operator, lhs = lhs, rhs = rhs) return Nodes.InPlaceAssignmentNode(lhs.pos, operator = operator, lhs = lhs, rhs = rhs)
expr = expr_list[0] expr = expr_list[0]
if isinstance(expr, ExprNodes.StringNode): if isinstance(expr, (ExprNodes.UnicodeNode, ExprNodes.StringNode, ExprNodes.BytesNode)):
return Nodes.PassStatNode(expr.pos) return Nodes.PassStatNode(expr.pos)
else: else:
return Nodes.ExprStatNode(expr.pos, expr = expr) return Nodes.ExprStatNode(expr.pos, expr = expr)
...@@ -966,7 +963,7 @@ def flatten_parallel_assignments(input, output): ...@@ -966,7 +963,7 @@ def flatten_parallel_assignments(input, output):
# individual elements. This transformation is applied # individual elements. This transformation is applied
# recursively, so that nested structures get matched as well. # recursively, so that nested structures get matched as well.
rhs = input[-1] rhs = input[-1]
if not rhs.is_sequence_constructor: if not rhs.is_sequence_constructor or not sum([lhs.is_sequence_constructor for lhs in input[:-1]]):
output.append(input) output.append(input)
return return
...@@ -1170,8 +1167,7 @@ def p_import_statement(s): ...@@ -1170,8 +1167,7 @@ def p_import_statement(s):
else: else:
if as_name and "." in dotted_name: if as_name and "." in dotted_name:
name_list = ExprNodes.ListNode(pos, args = [ name_list = ExprNodes.ListNode(pos, args = [
ExprNodes.IdentifierStringNode( ExprNodes.IdentifierStringNode(pos, value = EncodedString("*"))])
pos, value = EncodedString("*"))])
else: else:
name_list = None name_list = None
stat = Nodes.SingleAssignmentNode(pos, stat = Nodes.SingleAssignmentNode(pos,
...@@ -1756,8 +1752,8 @@ def p_positional_and_keyword_args(s, end_sy_set, type_positions=(), type_keyword ...@@ -1756,8 +1752,8 @@ def p_positional_and_keyword_args(s, end_sy_set, type_positions=(), type_keyword
parsed_type = True parsed_type = True
else: else:
arg = p_simple_expr(s) arg = p_simple_expr(s)
keyword_node = ExprNodes.IdentifierStringNode(arg.pos, keyword_node = ExprNodes.IdentifierStringNode(
value = EncodedString(ident)) arg.pos, value = EncodedString(ident))
keyword_args.append((keyword_node, arg)) keyword_args.append((keyword_node, arg))
was_keyword = True was_keyword = True
else: else:
...@@ -2628,7 +2624,7 @@ def p_compiler_directive_comments(s): ...@@ -2628,7 +2624,7 @@ def p_compiler_directive_comments(s):
if m: if m:
name = m.group(1) name = m.group(1)
try: try:
value = Options.parse_option_value(str(name), str(m.group(2).strip())) value = Options.parse_directive_value(str(name), str(m.group(2).strip()))
if value is not None: # can be False! if value is not None: # can be False!
result[name] = value result[name] = value
except ValueError, e: except ValueError, e:
...@@ -2639,7 +2635,7 @@ def p_compiler_directive_comments(s): ...@@ -2639,7 +2635,7 @@ def p_compiler_directive_comments(s):
def p_module(s, pxd, full_module_name): def p_module(s, pxd, full_module_name):
pos = s.position() pos = s.position()
option_comments = p_compiler_directive_comments(s) directive_comments = p_compiler_directive_comments(s)
s.parse_comments = False s.parse_comments = False
doc = p_doc_string(s) doc = p_doc_string(s)
...@@ -2654,7 +2650,7 @@ def p_module(s, pxd, full_module_name): ...@@ -2654,7 +2650,7 @@ def p_module(s, pxd, full_module_name):
repr(s.sy), repr(s.systring))) repr(s.sy), repr(s.systring)))
return ModuleNode(pos, doc = doc, body = body, return ModuleNode(pos, doc = doc, body = body,
full_module_name = full_module_name, full_module_name = full_module_name,
option_comments = option_comments) directive_comments = directive_comments)
#---------------------------------------------- #----------------------------------------------
# #
......
This diff is collapsed.
...@@ -9,6 +9,7 @@ import os ...@@ -9,6 +9,7 @@ import os
import platform import platform
import stat import stat
import sys import sys
import codecs
from time import time from time import time
import cython import cython
...@@ -279,8 +280,12 @@ class FileSourceDescriptor(SourceDescriptor): ...@@ -279,8 +280,12 @@ class FileSourceDescriptor(SourceDescriptor):
self.filename = filename self.filename = filename
self._cmp_name = filename self._cmp_name = filename
def get_lines(self): def get_lines(self, encoding=None, error_handling=None):
return Utils.open_source_file(self.filename) if not encoding:
return Utils.open_source_file(self.filename)
else:
return codecs.open(self.filename, "rU", encoding=encoding,
errors=error_handling)
def get_description(self): def get_description(self):
return self.filename return self.filename
...@@ -307,9 +312,13 @@ class StringSourceDescriptor(SourceDescriptor): ...@@ -307,9 +312,13 @@ class StringSourceDescriptor(SourceDescriptor):
self.codelines = [x + "\n" for x in code.split("\n")] self.codelines = [x + "\n" for x in code.split("\n")]
self._cmp_name = name self._cmp_name = name
def get_lines(self): def get_lines(self, encoding=None, error_handling=None):
return self.codelines if not encoding:
return self.codelines
else:
return [ line.encode(encoding, error_handling).decode(encoding)
for line in self.codelines ]
def get_description(self): def get_description(self):
return self.name return self.name
...@@ -454,7 +463,6 @@ class PyrexScanner(Scanner): ...@@ -454,7 +463,6 @@ class PyrexScanner(Scanner):
sy = systring sy = systring
else: else:
systring = EncodedString(systring) systring = EncodedString(systring)
systring.encoding = self.source_encoding
self.sy = sy self.sy = sy
self.systring = systring self.systring = systring
if False: # debug_scanner: if False: # debug_scanner:
......
...@@ -6,14 +6,14 @@ import re ...@@ -6,14 +6,14 @@ import re
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
_str, _bytes = str, bytes _unicode, _str, _bytes = str, str, bytes
IS_PYTHON3 = True IS_PYTHON3 = True
else: else:
_str, _bytes = unicode, str _unicode, _str, _bytes = unicode, str, str
IS_PYTHON3 = False IS_PYTHON3 = False
empty_bytes = _bytes() empty_bytes = _bytes()
empty_str = _str() empty_unicode = _unicode()
join_bytes = empty_bytes.join join_bytes = empty_bytes.join
...@@ -27,7 +27,7 @@ class UnicodeLiteralBuilder(object): ...@@ -27,7 +27,7 @@ class UnicodeLiteralBuilder(object):
if isinstance(characters, _bytes): if isinstance(characters, _bytes):
# this came from a Py2 string literal in the parser code # this came from a Py2 string literal in the parser code
characters = characters.decode("ASCII") characters = characters.decode("ASCII")
assert isinstance(characters, _str), str(type(characters)) assert isinstance(characters, _unicode), str(type(characters))
self.chars.append(characters) self.chars.append(characters)
def append_charval(self, char_number): def append_charval(self, char_number):
...@@ -45,7 +45,7 @@ class BytesLiteralBuilder(object): ...@@ -45,7 +45,7 @@ class BytesLiteralBuilder(object):
self.target_encoding = target_encoding self.target_encoding = target_encoding
def append(self, characters): def append(self, characters):
if isinstance(characters, _str): if isinstance(characters, _unicode):
characters = characters.encode(self.target_encoding) characters = characters.encode(self.target_encoding)
assert isinstance(characters, _bytes), str(type(characters)) assert isinstance(characters, _bytes), str(type(characters))
self.chars.append(characters) self.chars.append(characters)
...@@ -63,7 +63,7 @@ class BytesLiteralBuilder(object): ...@@ -63,7 +63,7 @@ class BytesLiteralBuilder(object):
# this *must* return a byte string! # this *must* return a byte string!
return self.getstring() return self.getstring()
class EncodedString(_str): class EncodedString(_unicode):
# unicode string subclass to keep track of the original encoding. # unicode string subclass to keep track of the original encoding.
# 'encoding' is None for unicode strings and the source encoding # 'encoding' is None for unicode strings and the source encoding
# otherwise # otherwise
...@@ -82,7 +82,7 @@ class EncodedString(_str): ...@@ -82,7 +82,7 @@ class EncodedString(_str):
is_unicode = property(is_unicode) is_unicode = property(is_unicode)
class BytesLiteral(_bytes): class BytesLiteral(_bytes):
# str subclass that is compatible with EncodedString # bytes subclass that is compatible with EncodedString
encoding = None encoding = None
def byteencode(self): def byteencode(self):
......
...@@ -8,7 +8,7 @@ from Errors import warning, error, InternalError ...@@ -8,7 +8,7 @@ from Errors import warning, error, InternalError
from StringEncoding import EncodedString from StringEncoding import EncodedString
import Options, Naming import Options, Naming
import PyrexTypes import PyrexTypes
from PyrexTypes import py_object_type from PyrexTypes import py_object_type, unspecified_type
import TypeSlots import TypeSlots
from TypeSlots import \ from TypeSlots import \
pyfunction_signature, pymethod_signature, \ pyfunction_signature, pymethod_signature, \
...@@ -115,9 +115,10 @@ class Entry(object): ...@@ -115,9 +115,10 @@ class Entry(object):
# api boolean Generate C API for C class or function # api boolean Generate C API for C class or function
# utility_code string Utility code needed when this entry is used # utility_code string Utility code needed when this entry is used
# #
# buffer_aux BufferAux or None Extra information needed for buffer variables # buffer_aux BufferAux or None Extra information needed for buffer variables
# inline_func_in_pxd boolean Hacky special case for inline function in pxd file. # inline_func_in_pxd boolean Hacky special case for inline function in pxd file.
# Ideally this should not be necesarry. # Ideally this should not be necesarry.
# assignments [ExprNode] List of expressions that get assigned to this entry.
inline_func_in_pxd = False inline_func_in_pxd = False
borrowed = 0 borrowed = 0
...@@ -173,6 +174,10 @@ class Entry(object): ...@@ -173,6 +174,10 @@ class Entry(object):
self.type = type self.type = type
self.pos = pos self.pos = pos
self.init = init self.init = init
self.assignments = []
def __repr__(self):
return "Entry(name=%s, type=%s)" % (self.name, self.type)
def redeclared(self, pos): def redeclared(self, pos):
error(pos, "'%s' does not match previous declaration" % self.name) error(pos, "'%s' does not match previous declaration" % self.name)
...@@ -344,7 +349,11 @@ class Scope(object): ...@@ -344,7 +349,11 @@ class Scope(object):
cname = name cname = name
else: else:
cname = self.mangle(Naming.type_prefix, name) cname = self.mangle(Naming.type_prefix, name)
type = PyrexTypes.CTypedefType(cname, base_type, (visibility == 'extern')) try:
type = PyrexTypes.create_typedef_type(cname, base_type, (visibility == 'extern'))
except ValueError, e:
error(pos, e.message)
type = PyrexTypes.error_type
entry = self.declare_type(name, type, pos, cname, visibility) entry = self.declare_type(name, type, pos, cname, visibility)
type.qualified_name = entry.qualified_name type.qualified_name = entry.qualified_name
return entry return entry
...@@ -365,6 +374,7 @@ class Scope(object): ...@@ -365,6 +374,7 @@ class Scope(object):
entry = self.declare_type(name, type, pos, cname, entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None) visibility = visibility, defining = scope is not None)
self.sue_entries.append(entry) self.sue_entries.append(entry)
type.entry = entry
else: else:
if not (entry.is_type and entry.type.is_struct_or_union if not (entry.is_type and entry.type.is_struct_or_union
and entry.type.kind == kind): and entry.type.kind == kind):
...@@ -513,7 +523,7 @@ class Scope(object): ...@@ -513,7 +523,7 @@ class Scope(object):
if entry.as_module: if entry.as_module:
scope = entry.as_module scope = entry.as_module
else: else:
error(pos, "'%s' is not a cimported module" % scope.qualified_name) error(pos, "'%s' is not a cimported module" % '.'.join(path))
return None return None
return scope return scope
...@@ -555,6 +565,10 @@ class Scope(object): ...@@ -555,6 +565,10 @@ class Scope(object):
if name in self.entries: if name in self.entries:
return 1 return 1
return 0 return 0
def infer_types(self):
from TypeInference import get_type_inferer
get_type_inferer().infer_types(self)
class PreImportScope(Scope): class PreImportScope(Scope):
...@@ -827,6 +841,8 @@ class ModuleScope(Scope): ...@@ -827,6 +841,8 @@ class ModuleScope(Scope):
if not visibility in ('private', 'public', 'extern'): if not visibility in ('private', 'public', 'extern'):
error(pos, "Module-level variable cannot be declared %s" % visibility) error(pos, "Module-level variable cannot be declared %s" % visibility)
if not is_cdef: if not is_cdef:
if type is unspecified_type:
type = py_object_type
if not (type.is_pyobject and not type.is_extension_type): if not (type.is_pyobject and not type.is_extension_type):
raise InternalError( raise InternalError(
"Non-cdef global variable is not a generic Python object") "Non-cdef global variable is not a generic Python object")
...@@ -1056,6 +1072,10 @@ class ModuleScope(Scope): ...@@ -1056,6 +1072,10 @@ class ModuleScope(Scope):
var_entry.is_cglobal = 1 var_entry.is_cglobal = 1
var_entry.is_readonly = 1 var_entry.is_readonly = 1
entry.as_variable = var_entry entry.as_variable = var_entry
def infer_types(self):
from TypeInference import PyObjectTypeInferer
PyObjectTypeInferer().infer_types(self)
class LocalScope(Scope): class LocalScope(Scope):
...@@ -1087,7 +1107,7 @@ class LocalScope(Scope): ...@@ -1087,7 +1107,7 @@ class LocalScope(Scope):
cname, visibility, is_cdef) cname, visibility, is_cdef)
if type.is_pyobject and not Options.init_local_none: if type.is_pyobject and not Options.init_local_none:
entry.init = "0" entry.init = "0"
entry.init_to_none = type.is_pyobject and Options.init_local_none entry.init_to_none = (type.is_pyobject or type.is_unspecified) and Options.init_local_none
entry.is_local = 1 entry.is_local = 1
self.var_entries.append(entry) self.var_entries.append(entry)
return entry return entry
...@@ -1188,7 +1208,7 @@ class StructOrUnionScope(Scope): ...@@ -1188,7 +1208,7 @@ class StructOrUnionScope(Scope):
def declare_cfunction(self, name, type, pos, def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', defining = 0, cname = None, visibility = 'private', defining = 0,
api = 0, in_pxd = 0, modifiers = ()): api = 0, in_pxd = 0, modifiers = ()):
self.declare_var(name, type, pos, cname, visibility) return self.declare_var(name, type, pos, cname, visibility)
class ClassScope(Scope): class ClassScope(Scope):
# Abstract base class for namespace of # Abstract base class for namespace of
...@@ -1235,6 +1255,8 @@ class PyClassScope(ClassScope): ...@@ -1235,6 +1255,8 @@ class PyClassScope(ClassScope):
def declare_var(self, name, type, pos, def declare_var(self, name, type, pos,
cname = None, visibility = 'private', is_cdef = 0): cname = None, visibility = 'private', is_cdef = 0):
if type is unspecified_type:
type = py_object_type
# Add an entry for a class attribute. # Add an entry for a class attribute.
entry = Scope.declare_var(self, name, type, pos, entry = Scope.declare_var(self, name, type, pos,
cname, visibility, is_cdef) cname, visibility, is_cdef)
...@@ -1321,6 +1343,8 @@ class CClassScope(ClassScope): ...@@ -1321,6 +1343,8 @@ class CClassScope(ClassScope):
"Non-generic Python attribute cannot be exposed for writing from Python") "Non-generic Python attribute cannot be exposed for writing from Python")
return entry return entry
else: else:
if type is unspecified_type:
type = py_object_type
# Add an entry for a class attribute. # Add an entry for a class attribute.
entry = Scope.declare_var(self, name, type, pos, entry = Scope.declare_var(self, name, type, pos,
cname, visibility, is_cdef) cname, visibility, is_cdef)
...@@ -1477,15 +1501,22 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method) { ...@@ -1477,15 +1501,22 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
} }
if (PyObject_TypeCheck(method, methoddescr_type)) { /* cdef classes */ 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); #if PY_VERSION_HEX < 0x03020000
PyTypeObject *d_type = descr->d_type;
#else
PyTypeObject *d_type = descr->d_common.d_type;
#endif
return PyDescr_NewClassMethod(d_type, descr->d_method);
} }
else if (PyMethod_Check(method)) { /* python classes */ else if (PyMethod_Check(method)) { /* python classes */
return PyClassMethod_New(PyMethod_GET_FUNCTION(method)); return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
} }
else if (PyCFunction_Check(method)) { else if (PyCFunction_Check(method)) {
return PyClassMethod_New(method); return PyClassMethod_New(method);
} }
PyErr_Format(PyExc_TypeError, "Class-level classmethod() can only be called on a method_descriptor or instance method."); PyErr_Format(PyExc_TypeError,
"Class-level classmethod() can only be called on"
"a method_descriptor or instance method.");
return NULL; return NULL;
} }
""") """)
import ExprNodes
from PyrexTypes import py_object_type, unspecified_type, spanning_type
from Visitor import CythonTransform
try:
set
except NameError:
# Python 2.3
from sets import Set as set
class TypedExprNode(ExprNodes.ExprNode):
# Used for declaring assignments of a specified type whithout a known entry.
def __init__(self, type):
self.type = type
object_expr = TypedExprNode(py_object_type)
class MarkAssignments(CythonTransform):
def mark_assignment(self, lhs, rhs):
if isinstance(lhs, ExprNodes.NameNode):
if lhs.entry is None:
# TODO: This shouldn't happen...
# It looks like comprehension loop targets are not declared soon enough.
return
lhs.entry.assignments.append(rhs)
elif isinstance(lhs, ExprNodes.SequenceNode):
for arg in lhs.args:
self.mark_assignment(arg, object_expr)
else:
# Could use this info to infer cdef class attributes...
pass
def visit_SingleAssignmentNode(self, node):
self.mark_assignment(node.lhs, node.rhs)
self.visitchildren(node)
return node
def visit_CascadedAssignmentNode(self, node):
for lhs in node.lhs_list:
self.mark_assignment(lhs, node.rhs)
self.visitchildren(node)
return node
def visit_InPlaceAssignmentNode(self, node):
self.mark_assignment(node.lhs, node.create_binop_node())
self.visitchildren(node)
return node
def visit_ForInStatNode(self, node):
# TODO: Remove redundancy with range optimization...
is_range = False
sequence = node.iterator.sequence
if isinstance(sequence, ExprNodes.SimpleCallNode):
function = sequence.function
if sequence.self is None and \
isinstance(function, ExprNodes.NameNode) and \
function.name in ('range', 'xrange'):
is_range = True
self.mark_assignment(node.target, sequence.args[0])
if len(sequence.args) > 1:
self.mark_assignment(node.target, sequence.args[1])
if len(sequence.args) > 2:
self.mark_assignment(node.target,
ExprNodes.binop_node(node.pos,
'+',
sequence.args[0],
sequence.args[2]))
if not is_range:
self.mark_assignment(node.target, object_expr)
self.visitchildren(node)
return node
def visit_ForFromStatNode(self, node):
self.mark_assignment(node.target, node.bound1)
if node.step is not None:
self.mark_assignment(node.target,
ExprNodes.binop_node(node.pos,
'+',
node.bound1,
node.step))
self.visitchildren(node)
return node
def visit_ExceptClauseNode(self, node):
if node.target is not None:
self.mark_assignment(node.target, object_expr)
self.visitchildren(node)
return node
def visit_FromCImportStatNode(self, node):
pass # Can't be assigned to...
def visit_FromImportStatNode(self, node):
for name, target in node.items:
if name != "*":
self.mark_assignment(target, object_expr)
self.visitchildren(node)
return node
class PyObjectTypeInferer:
"""
If it's not declared, it's a PyObject.
"""
def infer_types(self, scope):
"""
Given a dict of entries, map all unspecified types to a specified type.
"""
for name, entry in scope.entries.items():
if entry.type is unspecified_type:
entry.type = py_object_type
class SimpleAssignmentTypeInferer:
"""
Very basic type inference.
"""
# TODO: Implement a real type inference algorithm.
# (Something more powerful than just extending this one...)
def infer_types(self, scope):
dependancies_by_entry = {} # entry -> dependancies
entries_by_dependancy = {} # dependancy -> entries
ready_to_infer = []
for name, entry in scope.entries.items():
if entry.type is unspecified_type:
all = set()
for expr in entry.assignments:
all.update(expr.type_dependencies(scope))
if all:
dependancies_by_entry[entry] = all
for dep in all:
if dep not in entries_by_dependancy:
entries_by_dependancy[dep] = set([entry])
else:
entries_by_dependancy[dep].add(entry)
else:
ready_to_infer.append(entry)
def resolve_dependancy(dep):
if dep in entries_by_dependancy:
for entry in entries_by_dependancy[dep]:
entry_deps = dependancies_by_entry[entry]
entry_deps.remove(dep)
if not entry_deps and entry != dep:
del dependancies_by_entry[entry]
ready_to_infer.append(entry)
# Try to infer things in order...
while True:
while ready_to_infer:
entry = ready_to_infer.pop()
types = [expr.infer_type(scope) for expr in entry.assignments]
if types:
entry.type = reduce(spanning_type, types)
else:
# List comprehension?
# print "No assignments", entry.pos, entry
entry.type = py_object_type
resolve_dependancy(entry)
# Deal with simple circular dependancies...
for entry, deps in dependancies_by_entry.items():
if len(deps) == 1 and deps == set([entry]):
types = [expr.infer_type(scope) for expr in entry.assignments if expr.type_dependencies(scope) == ()]
if types:
entry.type = reduce(spanning_type, types)
types = [expr.infer_type(scope) for expr in entry.assignments]
entry.type = reduce(spanning_type, types) # might be wider...
resolve_dependancy(entry)
del dependancies_by_entry[entry]
if ready_to_infer:
break
if not ready_to_infer:
break
# We can't figure out the rest with this algorithm, let them be objects.
for entry in dependancies_by_entry:
entry.type = py_object_type
def get_type_inferer():
return SimpleAssignmentTypeInferer()
...@@ -10,6 +10,7 @@ from Nodes import Node ...@@ -10,6 +10,7 @@ from Nodes import Node
from ExprNodes import AtomicExprNode from ExprNodes import AtomicExprNode
class TempHandle(object): class TempHandle(object):
# THIS IS DEPRECATED, USE LetRefNode instead
temp = None temp = None
needs_xdecref = False needs_xdecref = False
def __init__(self, type): def __init__(self, type):
...@@ -23,6 +24,7 @@ class TempHandle(object): ...@@ -23,6 +24,7 @@ class TempHandle(object):
return CleanupTempRefNode(pos, handle=self, type=self.type) return CleanupTempRefNode(pos, handle=self, type=self.type)
class TempRefNode(AtomicExprNode): class TempRefNode(AtomicExprNode):
# THIS IS DEPRECATED, USE LetRefNode instead
# handle TempHandle # handle TempHandle
def analyse_types(self, env): def analyse_types(self, env):
...@@ -52,6 +54,7 @@ class TempRefNode(AtomicExprNode): ...@@ -52,6 +54,7 @@ class TempRefNode(AtomicExprNode):
rhs.free_temps(code) rhs.free_temps(code)
class CleanupTempRefNode(TempRefNode): class CleanupTempRefNode(TempRefNode):
# THIS IS DEPRECATED, USE LetRefNode instead
# handle TempHandle # handle TempHandle
def generate_assignment_code(self, rhs, code): def generate_assignment_code(self, rhs, code):
...@@ -63,6 +66,8 @@ class CleanupTempRefNode(TempRefNode): ...@@ -63,6 +66,8 @@ class CleanupTempRefNode(TempRefNode):
self.handle.needs_cleanup = False self.handle.needs_cleanup = False
class TempsBlockNode(Node): class TempsBlockNode(Node):
# THIS IS DEPRECATED, USE LetNode instead
""" """
Creates a block which allocates temporary variables. Creates a block which allocates temporary variables.
This is used by transforms to output constructs that need This is used by transforms to output constructs that need
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
DEF _buffer_format_string_len = 255 DEF _buffer_format_string_len = 255
cimport python_buffer as pybuf cimport python_buffer as pybuf
from python_object cimport PyObject from python_ref cimport PyObject, Py_INCREF, Py_XDECREF
cimport stdlib cimport stdlib
cimport stdio cimport stdio
...@@ -151,6 +151,7 @@ cdef extern from "numpy/arrayobject.h": ...@@ -151,6 +151,7 @@ cdef extern from "numpy/arrayobject.h":
npy_intp *shape "dimensions" npy_intp *shape "dimensions"
npy_intp *strides npy_intp *strides
dtype descr dtype descr
PyObject* base
# Note: This syntax (function definition in pxd files) is an # Note: This syntax (function definition in pxd files) is an
# experimental exception made for __getbuffer__ and __releasebuffer__ # experimental exception made for __getbuffer__ and __releasebuffer__
...@@ -292,12 +293,6 @@ cdef extern from "numpy/arrayobject.h": ...@@ -292,12 +293,6 @@ cdef extern from "numpy/arrayobject.h":
ctypedef long double npy_float96 ctypedef long double npy_float96
ctypedef long double npy_float128 ctypedef long double npy_float128
ctypedef float complex npy_complex64
ctypedef double complex npy_complex128
ctypedef long double complex npy_complex120
ctypedef long double complex npy_complex192
ctypedef long double complex npy_complex256
ctypedef struct npy_cfloat: ctypedef struct npy_cfloat:
double real double real
double imag double imag
...@@ -310,6 +305,26 @@ cdef extern from "numpy/arrayobject.h": ...@@ -310,6 +305,26 @@ cdef extern from "numpy/arrayobject.h":
double real double real
double imag double imag
ctypedef struct npy_complex64:
double real
double imag
ctypedef struct npy_complex128:
double real
double imag
ctypedef struct npy_complex160:
double real
double imag
ctypedef struct npy_complex192:
double real
double imag
ctypedef struct npy_complex256:
double real
double imag
ctypedef struct PyArray_Dims: ctypedef struct PyArray_Dims:
npy_intp *ptr npy_intp *ptr
int len int len
...@@ -469,6 +484,13 @@ cdef extern from "numpy/arrayobject.h": ...@@ -469,6 +484,13 @@ cdef extern from "numpy/arrayobject.h":
object PyArray_Take(ndarray ap, object items, int axis) object PyArray_Take(ndarray ap, object items, int axis)
object PyArray_Put(ndarray ap, object items, object values) object PyArray_Put(ndarray ap, object items, object values)
void PyArray_ITER_RESET(flatiter it) nogil
void PyArray_ITER_NEXT(flatiter it) nogil
void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil
void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil
void* PyArray_ITER_DATA(flatiter it) nogil
bint PyArray_ITER_NOTDONE(flatiter it) nogil
void PyArray_MultiIter_RESET(broadcast multi) nogil void PyArray_MultiIter_RESET(broadcast multi) nogil
void PyArray_MultiIter_NEXT(broadcast multi) nogil void PyArray_MultiIter_NEXT(broadcast multi) nogil
void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil
...@@ -895,6 +917,21 @@ cdef extern from "numpy/ufuncobject.h": ...@@ -895,6 +917,21 @@ cdef extern from "numpy/ufuncobject.h":
(PyUFuncGenericFunction *, void **, char *, int, int, int, (PyUFuncGenericFunction *, void **, char *, int, int, int,
int, char *, char *, int, char *) int, char *, char *, int, char *)
void import_ufunc()
void import_ufunc() cdef inline void set_array_base(ndarray arr, object base):
cdef PyObject* baseptr
if base is None:
baseptr = NULL
else:
Py_INCREF(base) # important to do this before decref below!
baseptr = <PyObject*>base
Py_XDECREF(arr.base)
arr.base = baseptr
cdef inline object get_array_base(ndarray arr):
if arr.base is NULL:
return None
else:
return <object>arr.base
...@@ -125,6 +125,7 @@ from python_mem cimport * ...@@ -125,6 +125,7 @@ from python_mem cimport *
from python_tuple cimport * from python_tuple cimport *
from python_list cimport * from python_list cimport *
from python_object cimport * from python_object cimport *
from python_cobject cimport *
from python_sequence cimport * from python_sequence cimport *
from python_mapping cimport * from python_mapping cimport *
from python_iterator cimport * from python_iterator cimport *
......
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
############################################################################ ############################################################################
# 7.2.2 Boolean Objects # 7.2.2 Boolean Objects
......
# Please see the Python header files (object.h) for docs # Please see the Python header files (object.h/abstract.h) for docs
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
ctypedef struct bufferinfo:
void *buf
Py_ssize_t len
Py_ssize_t itemsize
int readonly
int ndim
char *format
Py_ssize_t *shape
Py_ssize_t *strides
Py_ssize_t *suboffsets
void *internal
ctypedef bufferinfo Py_buffer
cdef enum: cdef enum:
PyBUF_SIMPLE, PyBUF_SIMPLE,
...@@ -39,23 +25,85 @@ cdef extern from "Python.h": ...@@ -39,23 +25,85 @@ cdef extern from "Python.h":
PyBUF_WRITE, PyBUF_WRITE,
PyBUF_SHADOW PyBUF_SHADOW
int PyObject_CheckBuffer(PyObject* obj) bint PyObject_CheckBuffer(object obj)
int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) # Return 1 if obj supports the buffer interface otherwise 0.
void PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)
int PyObject_GetBuffer(object obj, Py_buffer *view, int flags) except -1
# Export obj into a Py_buffer, view. These arguments must never be
# NULL. The flags argument is a bit field indicating what kind of
# buffer the caller is prepared to deal with and therefore what
# kind of buffer the exporter is allowed to return. The buffer
# interface allows for complicated memory sharing possibilities,
# but some caller may not be able to handle all the complexity but
# may want to see if the exporter will let them take a simpler
# view to its memory.
# Some exporters may not be able to share memory in every possible
# way and may need to raise errors to signal to some consumers
# that something is just not possible. These errors should be a
# BufferError unless there is another error that is actually
# causing the problem. The exporter can use flags information to
# simplify how much of the Py_buffer structure is filled in with
# non-default values and/or raise an error if the object can’t
# support a simpler view of its memory.
# 0 is returned on success and -1 on error.
void PyBuffer_Release(object obj, object view)
# Release the buffer view over obj. This should be called when the
# buffer is no longer being used as it may free memory from it.
void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices)
# ??
int PyBuffer_SizeFromFormat(char *) # actually const char int PyBuffer_SizeFromFormat(char *) # actually const char
# Return the implied ~Py_buffer.itemsize from the struct-stype
# ~Py_buffer.format
int PyBuffer_ToContiguous(void *buf, Py_buffer *view, Py_ssize_t len, char fort) int PyBuffer_ToContiguous(void *buf, Py_buffer *view, Py_ssize_t len, char fort)
# ??
int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
int PyObject_CopyData(PyObject *dest, PyObject *src) # ??
int PyBuffer_IsContiguous(Py_buffer *view, char fort)
int PyObject_CopyToObject(object obj, void *buf, Py_ssize_t len, char fortran) except -1
# Copy len bytes of data pointed to by the contiguous chunk of
# memory pointed to by buf into the buffer exported by obj. The
# buffer must of course be writable. Return 0 on success and
# return -1 and raise an error on failure. If the object does not
# have a writable buffer, then an error is raised. If fortran is
# 'F', then if the object is multi-dimensional, then the data will
# be copied into the array in Fortran-style (first dimension
# varies the fastest). If fortran is 'C', then the data will be
# copied into the array in C-style (last dimension varies the
# fastest). If fortran is 'A', then it does not matter and the
# copy will be made in whatever way is more efficient.
int PyObject_CopyData(object dest, object src)
# Copy the data from the src buffer to the buffer of destination
bint PyBuffer_IsContiguous(Py_buffer *view, char fort)
# Return 1 if the memory defined by the view is C-style (fortran
# is 'C') or Fortran-style (fortran is 'F') contiguous or either
# one (fortran is 'A'). Return 0 otherwise.
void PyBuffer_FillContiguousStrides(int ndims, void PyBuffer_FillContiguousStrides(int ndims,
Py_ssize_t *shape, Py_ssize_t *shape,
Py_ssize_t *strides, Py_ssize_t *strides,
int itemsize, int itemsize,
char fort) char fort)
# Fill the strides array with byte-strides of a contiguous
# (Fortran-style if fort is 'F' or C-style otherwise) array of the
# given shape with the given number of bytes per element.
int PyBuffer_FillInfo(Py_buffer *view, void *buf, int PyBuffer_FillInfo(Py_buffer *view, void *buf,
Py_ssize_t len, int readonly, Py_ssize_t len, int readonly,
int flags) int flags) except -1
# Fill in a buffer-info structure, view, correctly for an exporter
# that can only share a contiguous chunk of memory of “unsigned
# bytes” of the given length. Return 0 on success and -1 (with
# raising an error) on error.
PyObject* PyObject_Format(PyObject* obj, object PyObject_Format(object obj, object format_spec)
PyObject *format_spec) # Takes an arbitrary object and returns the result of calling
# obj.__format__(format_spec).
from python_ref cimport PyObject
cdef extern from "Python.h":
###########################################################################
# Warning:
#
# The CObject API is deprecated as of Python 3.1. Please switch to
# the new Capsules API.
###########################################################################
int PyCObject_Check(object p)
# Return true if its argument is a PyCObject.
object PyCObject_FromVoidPtr(void* cobj, void (*destr)(void *))
# Return value: New reference.
#
# Create a PyCObject from the void * cobj. The destr function will
# be called when the object is reclaimed, unless it is NULL.
object PyCObject_FromVoidPtrAndDesc(void* cobj, void* desc, void (*destr)(void *, void *))
# Return value: New reference.
#
# Create a PyCObject from the void * cobj. The destr function will
# be called when the object is reclaimed. The desc argument can be
# used to pass extra callback data for the destructor function.
void* PyCObject_AsVoidPtr(object self)
# Return the object void * that the PyCObject self was created with.
void* PyCObject_GetDesc(object self)
# Return the description void * that the PyCObject self was created with.
int PyCObject_SetVoidPtr(object self, void* cobj)
# Set the void pointer inside self to cobj. The PyCObject must not
# have an associated destructor. Return true on success, false on
# failure.
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
ctypedef struct Py_complex ctypedef struct Py_complex
############################################################################ ############################################################################
......
from python_ref cimport PyObject
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
############################################################################ ############################################################################
# 7.4.1 Dictionary Objects # 7.4.1 Dictionary Objects
############################################################################ ############################################################################
# PyDictObject # PyDictObject
# This subtype of PyObject represents a Python dictionary object. #
# This subtype of PyObject represents a Python dictionary object
# (i.e. the 'dict' type).
# PyTypeObject PyDict_Type # PyTypeObject PyDict_Type
# This instance of PyTypeObject represents the Python dictionary type. This is exposed to Python programs as dict and types.DictType. #
# This instance of PyTypeObject represents the Python dictionary
# type. This is exposed to Python programs as dict and
# types.DictType.
bint PyDict_Check(object p) bint PyDict_Check(object p)
# Return true if p is a dict object or an instance of a subtype of # Return true if p is a dict object or an instance of a subtype of
...@@ -29,7 +38,7 @@ cdef extern from "Python.h": ...@@ -29,7 +38,7 @@ cdef extern from "Python.h":
void PyDict_Clear(object p) void PyDict_Clear(object p)
# Empty an existing dictionary of all key-value pairs. # Empty an existing dictionary of all key-value pairs.
int PyDict_Contains(object p, object key) int PyDict_Contains(object p, object key) except -1
# Determine if dictionary p contains key. If an item in p is # Determine if dictionary p contains key. If an item in p is
# matches key, return 1, otherwise return 0. On error, return # matches key, return 1, otherwise return 0. On error, return
# -1. This is equivalent to the Python expression "key in p". # -1. This is equivalent to the Python expression "key in p".
...@@ -38,22 +47,22 @@ cdef extern from "Python.h": ...@@ -38,22 +47,22 @@ cdef extern from "Python.h":
# Return value: New reference. # Return value: New reference.
# Return a new dictionary that contains the same key-value pairs as p. # Return a new dictionary that contains the same key-value pairs as p.
int PyDict_SetItem(object p, object key, object val) int PyDict_SetItem(object p, object key, object val) except -1
# Insert value into the dictionary p with a key of key. key must # Insert value into the dictionary p with a key of key. key must
# be hashable; if it isn't, TypeError will be raised. Return 0 on # be hashable; if it isn't, TypeError will be raised. Return 0 on
# success or -1 on failure. # success or -1 on failure.
int PyDict_SetItemString(object p, char *key, object val) int PyDict_SetItemString(object p, char *key, object val) except -1
# Insert value into the dictionary p using key as a key. key # Insert value into the dictionary p using key as a key. key
# should be a char*. The key object is created using # should be a char*. The key object is created using
# PyString_FromString(key). Return 0 on success or -1 on failure. # PyString_FromString(key). Return 0 on success or -1 on failure.
int PyDict_DelItem(object p, object key) int PyDict_DelItem(object p, object key) except -1
# Remove the entry in dictionary p with key key. key must be # Remove the entry in dictionary p with key key. key must be
# hashable; if it isn't, TypeError is raised. Return 0 on success # hashable; if it isn't, TypeError is raised. Return 0 on success
# or -1 on failure. # or -1 on failure.
int PyDict_DelItemString(object p, char *key) int PyDict_DelItemString(object p, char *key) except -1
# Remove the entry in dictionary p which has a key specified by # Remove the entry in dictionary p which has a key specified by
# the string key. Return 0 on success or -1 on failure. # the string key. Return 0 on success or -1 on failure.
...@@ -87,7 +96,8 @@ cdef extern from "Python.h": ...@@ -87,7 +96,8 @@ cdef extern from "Python.h":
# Python Library Reference). # Python Library Reference).
Py_ssize_t PyDict_Size(object p) Py_ssize_t PyDict_Size(object p)
# Return the number of items in the dictionary. This is equivalent to "len(p)" on a dictionary. # Return the number of items in the dictionary. This is equivalent
# to "len(p)" on a dictionary.
int PyDict_Next(object p, Py_ssize_t *ppos, PyObject* *pkey, PyObject* *pvalue) int PyDict_Next(object p, Py_ssize_t *ppos, PyObject* *pkey, PyObject* *pvalue)
# Iterate over all key-value pairs in the dictionary p. The int # Iterate over all key-value pairs in the dictionary p. The int
...@@ -128,7 +138,7 @@ cdef extern from "Python.h": ...@@ -128,7 +138,7 @@ cdef extern from "Python.h":
# Py_DECREF(o); # Py_DECREF(o);
# } # }
int PyDict_Merge(object a, object b, int override) int PyDict_Merge(object a, object b, int override) except -1
# Iterate over mapping object b adding key-value pairs to # Iterate over mapping object b adding key-value pairs to
# dictionary a. b may be a dictionary, or any object supporting # dictionary a. b may be a dictionary, or any object supporting
# PyMapping_Keys() and PyObject_GetItem(). If override is true, # PyMapping_Keys() and PyObject_GetItem(). If override is true,
...@@ -137,11 +147,11 @@ cdef extern from "Python.h": ...@@ -137,11 +147,11 @@ cdef extern from "Python.h":
# matching key in a. Return 0 on success or -1 if an exception was # matching key in a. Return 0 on success or -1 if an exception was
# raised. # raised.
int PyDict_Update(object a, object b) int PyDict_Update(object a, object b) except -1
# This is the same as PyDict_Merge(a, b, 1) in C, or a.update(b) # This is the same as PyDict_Merge(a, b, 1) in C, or a.update(b)
# in Python. Return 0 on success or -1 if an exception was raised. # in Python. Return 0 on success or -1 if an exception was raised.
int PyDict_MergeFromSeq2(object a, object seq2, int override) int PyDict_MergeFromSeq2(object a, object seq2, int override) except -1
# Update or merge into dictionary a, from the key-value pairs in # Update or merge into dictionary a, from the key-value pairs in
# seq2. seq2 must be an iterable object producing iterable objects # seq2. seq2 must be an iterable object producing iterable objects
# of length 2, viewed as key-value pairs. In case of duplicate # of length 2, viewed as key-value pairs. In case of duplicate
......
from python_ref cimport PyObject
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
##################################################################### #####################################################################
# 3. Exception Handling # 3. Exception Handling
......
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
############################################################################ ############################################################################
# 7.2.3 # 7.2.3
############################################################################ ############################################################################
# PyFloatObject # PyFloatObject
# This subtype of PyObject represents a Python floating point object. #
# This subtype of PyObject represents a Python floating point object.
# PyTypeObject PyFloat_Type # PyTypeObject PyFloat_Type
# This instance of PyTypeObject represents the Python floating point type. This is the same object as float and types.FloatType. #
# This instance of PyTypeObject represents the Python floating
# point type. This is the same object as float and
# types.FloatType.
bint PyFloat_Check(object p) bint PyFloat_Check(object p)
# Return true if its argument is a PyFloatObject or a subtype of # Return true if its argument is a PyFloatObject or a subtype of
...@@ -28,7 +32,8 @@ cdef extern from "Python.h": ...@@ -28,7 +32,8 @@ cdef extern from "Python.h":
# Create a PyFloatObject object from v, or NULL on failure. # Create a PyFloatObject object from v, or NULL on failure.
double PyFloat_AsDouble(object pyfloat) double PyFloat_AsDouble(object pyfloat)
# Return a C double representation of the contents of pyfloat. # Return a C double representation of the contents of pyfloat.
double PyFloat_AS_DOUBLE(object pyfloat) double PyFloat_AS_DOUBLE(object pyfloat)
# Return a C double representation of the contents of pyfloat, but without error checking. # Return a C double representation of the contents of pyfloat, but
# without error checking.
from python_ref cimport PyObject
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
############################################################################ ############################################################################
# 7.5.3 Function Objects # 7.5.3 Function Objects
############################################################################ ############################################################################
# There are a few functions specific to Python functions. # There are a few functions specific to Python functions.
# PyFunctionObject # PyFunctionObject
# The C structure used for functions. #
# The C structure used for functions.
# PyTypeObject PyFunction_Type # PyTypeObject PyFunction_Type
#
# This is an instance of PyTypeObject and represents the Python # This is an instance of PyTypeObject and represents the Python
# function type. It is exposed to Python programmers as # function type. It is exposed to Python programmers as
# types.FunctionType. # types.FunctionType.
...@@ -43,7 +49,7 @@ cdef extern from "Python.h": ...@@ -43,7 +49,7 @@ cdef extern from "Python.h":
# Return the argument default values of the function object # Return the argument default values of the function object
# op. This can be a tuple of arguments or NULL. # op. This can be a tuple of arguments or NULL.
int PyFunction_SetDefaults(object op, object defaults) int PyFunction_SetDefaults(object op, object defaults) except -1
# Set the argument default values for the function object # Set the argument default values for the function object
# op. defaults must be Py_None or a tuple. # op. defaults must be Py_None or a tuple.
# Raises SystemError and returns -1 on failure. # Raises SystemError and returns -1 on failure.
...@@ -53,7 +59,7 @@ cdef extern from "Python.h": ...@@ -53,7 +59,7 @@ cdef extern from "Python.h":
# Return the closure associated with the function object op. This # Return the closure associated with the function object op. This
# can be NULL or a tuple of cell objects. # can be NULL or a tuple of cell objects.
int PyFunction_SetClosure(object op, object closure) int PyFunction_SetClosure(object op, object closure) except -1
# Set the closure associated with the function object op. closure # Set the closure associated with the function object op. closure
# must be Py_None or a tuple of cell objects. # must be Py_None or a tuple of cell objects.
# Raises SystemError and returns -1 on failure. # Raises SystemError and returns -1 on failure.
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
############################################################################ ############################################################################
# 7.5.2 Instance Objects # 7.5.2 Instance Objects
############################################################################ ############################################################################
# PyTypeObject PyInstance_Type # PyTypeObject PyInstance_Type
# Type object for class instances. #
# int PyInstance_Check(PyObject *obj) # Type object for class instances.
int PyInstance_Check(object obj)
# Return true if obj is an instance. # Return true if obj is an instance.
object PyInstance_New(PyObject* cls, object arg, object kw) object PyInstance_New(object cls, object arg, object kw)
# Return value: New reference. # Return value: New reference.
# Create a new instance of a specific class. The parameters arg # Create a new instance of a specific class. The parameters arg
# and kw are used as the positional and keyword parameters to the # and kw are used as the positional and keyword parameters to the
......
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject ctypedef unsigned long long PY_LONG_LONG
############################################################################ ############################################################################
# Integer Objects # Integer Objects
...@@ -48,7 +48,7 @@ cdef extern from "Python.h": ...@@ -48,7 +48,7 @@ cdef extern from "Python.h":
# Create a new integer object with a value of ival. If the value # Create a new integer object with a value of ival. If the value
# exceeds LONG_MAX, a long integer object is returned. # exceeds LONG_MAX, a long integer object is returned.
long PyInt_AsLong(object io) long PyInt_AsLong(object io) except? -1
# Will first attempt to cast the object to a PyIntObject, if it is # Will first attempt to cast the object to a PyIntObject, if it is
# not already one, and then return its value. If there is an # not already one, and then return its value. If there is an
# error, -1 is returned, and the caller should check # error, -1 is returned, and the caller should check
...@@ -64,7 +64,6 @@ cdef extern from "Python.h": ...@@ -64,7 +64,6 @@ cdef extern from "Python.h":
# value as unsigned long. This function does not check for # value as unsigned long. This function does not check for
# overflow. # overflow.
ctypedef unsigned long long PY_LONG_LONG
PY_LONG_LONG PyInt_AsUnsignedLongLongMask(object io) PY_LONG_LONG PyInt_AsUnsignedLongLongMask(object io)
# Will first attempt to cast the object to a PyIntObject or # Will first attempt to cast the object to a PyIntObject or
# PyLongObject, if it is not already one, and then return its # PyLongObject, if it is not already one, and then return its
......
...@@ -3,7 +3,7 @@ cdef extern from "Python.h": ...@@ -3,7 +3,7 @@ cdef extern from "Python.h":
############################################################################ ############################################################################
# 6.5 Iterator Protocol # 6.5 Iterator Protocol
############################################################################ ############################################################################
int PyIter_Check(object o) bint PyIter_Check(object o)
# Return true if the object o supports the iterator protocol. # Return true if the object o supports the iterator protocol.
object PyIter_Next(object o) object PyIter_Next(object o)
......
from python_ref cimport PyObject
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
############################################################################ ############################################################################
# Lists # Lists
############################################################################ ############################################################################
object PyList_New(Py_ssize_t len) object PyList_New(Py_ssize_t len)
# Return a new list of length len on success, or NULL on # Return a new list of length len on success, or NULL on failure.
# failure. Note: If length is greater than zero, the returned list #
# object's items are set to NULL. Thus you cannot use abstract API # Note: If length is greater than zero, the returned list object's
# items are set to NULL. Thus you cannot use abstract API
# functions such as PySequence_SetItem() or expose the object to # functions such as PySequence_SetItem() or expose the object to
# Python code before setting all items to a real object with # Python code before setting all items to a real object with
# PyList_SetItem(). # PyList_SetItem().
bint PyList_Check(object p) bint PyList_Check(object p)
# Return true if p is a list object or an instance of a subtype of the list type. # Return true if p is a list object or an instance of a subtype of
# the list type.
bint PyList_CheckExact(object p) bint PyList_CheckExact(object p)
# Return true if p is a list object, but not an instance of a subtype of the list type. # Return true if p is a list object, but not an instance of a
# subtype of the list type.
Py_ssize_t PyList_Size(object list) Py_ssize_t PyList_Size(object list)
# Return the length of the list object in list; this is equivalent to "len(list)" on a list object. # Return the length of the list object in list; this is equivalent
# to "len(list)" on a list object.
Py_ssize_t PyList_GET_SIZE(object list) Py_ssize_t PyList_GET_SIZE(object list)
# Macro form of PyList_Size() without error checking. # Macro form of PyList_Size() without error checking.
...@@ -35,7 +40,7 @@ cdef extern from "Python.h": ...@@ -35,7 +40,7 @@ cdef extern from "Python.h":
# Return value: Borrowed reference. # Return value: Borrowed reference.
# Macro form of PyList_GetItem() without error checking. # Macro form of PyList_GetItem() without error checking.
int PyList_SetItem(object list, Py_ssize_t index, object item) int PyList_SetItem(object list, Py_ssize_t index, object item) except -1
# Set the item at index index in list to item. Return 0 on success # Set the item at index index in list to item. Return 0 on success
# or -1 on failure. Note: This function ``steals'' a reference to # or -1 on failure. Note: This function ``steals'' a reference to
# item and discards a reference to an item already in the list at # item and discards a reference to an item already in the list at
...@@ -49,12 +54,12 @@ cdef extern from "Python.h": ...@@ -49,12 +54,12 @@ cdef extern from "Python.h":
# to any item that it being replaced; any reference in list at # to any item that it being replaced; any reference in list at
# position i will be *leaked*. # position i will be *leaked*.
int PyList_Insert(object list, Py_ssize_t index, object item) int PyList_Insert(object list, Py_ssize_t index, object item) except -1
# Insert the item item into list list in front of index # Insert the item item into list list in front of index
# index. Return 0 if successful; return -1 and set an exception if # index. Return 0 if successful; return -1 and set an exception if
# unsuccessful. Analogous to list.insert(index, item). # unsuccessful. Analogous to list.insert(index, item).
int PyList_Append(object list, object item) int PyList_Append(object list, object item) except -1
# Append the object item at the end of list list. Return 0 if # Append the object item at the end of list list. Return 0 if
# successful; return -1 and set an exception if # successful; return -1 and set an exception if
# unsuccessful. Analogous to list.append(item). # unsuccessful. Analogous to list.append(item).
...@@ -65,17 +70,17 @@ cdef extern from "Python.h": ...@@ -65,17 +70,17 @@ cdef extern from "Python.h":
# between low and high. Return NULL and set an exception if # between low and high. Return NULL and set an exception if
# unsuccessful. Analogous to list[low:high]. # unsuccessful. Analogous to list[low:high].
int PyList_SetSlice(object list, Py_ssize_t low, Py_ssize_t high, object itemlist) int PyList_SetSlice(object list, Py_ssize_t low, Py_ssize_t high, object itemlist) except -1
# Set the slice of list between low and high to the contents of # Set the slice of list between low and high to the contents of
# itemlist. Analogous to list[low:high] = itemlist. The itemlist # itemlist. Analogous to list[low:high] = itemlist. The itemlist
# may be NULL, indicating the assignment of an empty list (slice # may be NULL, indicating the assignment of an empty list (slice
# deletion). Return 0 on success, -1 on failure. # deletion). Return 0 on success, -1 on failure.
int PyList_Sort(object list) int PyList_Sort(object list) except -1
# Sort the items of list in place. Return 0 on success, -1 on # Sort the items of list in place. Return 0 on success, -1 on
# failure. This is equivalent to "list.sort()". # failure. This is equivalent to "list.sort()".
int PyList_Reverse(object list) int PyList_Reverse(object list) except -1
# Reverse the items of list in place. Return 0 on success, -1 on # Reverse the items of list in place. Return 0 on success, -1 on
# failure. This is the equivalent of "list.reverse()". # failure. This is the equivalent of "list.reverse()".
......
from python_unicode cimport Py_UNICODE
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject ctypedef long long PY_LONG_LONG
ctypedef long PY_LONG_LONG ctypedef unsigned long long uPY_LONG_LONG
############################################################################ ############################################################################
# 7.2.3 Long Integer Objects # 7.2.3 Long Integer Objects
############################################################################ ############################################################################
# PyLongObject # PyLongObject
# This subtype of PyObject represents a Python long integer object. #
# This subtype of PyObject represents a Python long integer object.
# PyTypeObject PyLong_Type # PyTypeObject PyLong_Type
#
# This instance of PyTypeObject represents the Python long integer # This instance of PyTypeObject represents the Python long integer
# type. This is the same object as long and types.LongType. # type. This is the same object as long and types.LongType.
...@@ -29,8 +35,7 @@ cdef extern from "Python.h": ...@@ -29,8 +35,7 @@ cdef extern from "Python.h":
# Return value: New reference. # Return value: New reference.
# Return a new PyLongObject object from a C long long, or NULL on failure. # Return a new PyLongObject object from a C long long, or NULL on failure.
object PyLong_FromUnsignedLongLong(PY_LONG_LONG v) object PyLong_FromUnsignedLongLong(uPY_LONG_LONG v)
#PyObject* PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG v)
# Return value: New reference. # Return value: New reference.
# Return a new PyLongObject object from a C unsigned long long, or NULL on failure. # Return a new PyLongObject object from a C unsigned long long, or NULL on failure.
...@@ -51,8 +56,7 @@ cdef extern from "Python.h": ...@@ -51,8 +56,7 @@ cdef extern from "Python.h":
# inclusive. Leading spaces are ignored. If there are no digits, # inclusive. Leading spaces are ignored. If there are no digits,
# ValueError will be raised. # ValueError will be raised.
object PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
# object PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
# Return value: New reference. # Return value: New reference.
# Convert a sequence of Unicode digits to a Python long integer # Convert a sequence of Unicode digits to a Python long integer
# value. The first parameter, u, points to the first character of # value. The first parameter, u, points to the first character of
...@@ -82,7 +86,7 @@ cdef extern from "Python.h": ...@@ -82,7 +86,7 @@ cdef extern from "Python.h":
# cannot be represented as a long long, an OverflowError will be # cannot be represented as a long long, an OverflowError will be
# raised. # raised.
PY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong) uPY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong)
#unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong) #unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(object pylong)
# Return a C unsigned long long from a Python long integer. If # Return a C unsigned long long from a Python long integer. If
# pylong cannot be represented as an unsigned long long, an # pylong cannot be represented as an unsigned long long, an
...@@ -93,13 +97,12 @@ cdef extern from "Python.h": ...@@ -93,13 +97,12 @@ cdef extern from "Python.h":
# Return a C unsigned long from a Python long integer, without # Return a C unsigned long from a Python long integer, without
# checking for overflow. # checking for overflow.
PY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io) uPY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io)
#unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io) #unsigned PY_LONG_LONG PyLong_AsUnsignedLongLongMask(object io)
# Return a C unsigned long long from a Python long integer, # Return a C unsigned long long from a Python long integer,
# without checking for overflow. # without checking for overflow.
double PyLong_AsDouble(object pylong) except? -1.0
double PyLong_AsDouble(object pylong)
# Return a C double representation of the contents of pylong. If # Return a C double representation of the contents of pylong. If
# pylong cannot be approximately represented as a double, an # pylong cannot be approximately represented as a double, an
# OverflowError exception is raised and -1.0 will be returned. # OverflowError exception is raised and -1.0 will be returned.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
ctypedef void PyTypeObject
# The C structure of the objects used to describe built-in types. # The C structure of the objects used to describe built-in types.
############################################################################ ############################################################################
...@@ -38,7 +37,7 @@ cdef extern from "Python.h": ...@@ -38,7 +37,7 @@ cdef extern from "Python.h":
object PyType_GenericNew(object type, object args, object kwds) object PyType_GenericNew(object type, object args, object kwds)
# Return value: New reference. # Return value: New reference.
bint PyType_Ready(object type) bint PyType_Ready(object type) except -1
# Finalize a type object. This should be called on all type # Finalize a type object. This should be called on all type
# objects to finish their initialization. This function is # objects to finish their initialization. This function is
# responsible for adding inherited slots from a type's base # responsible for adding inherited slots from a type's base
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
cdef extern from "complex_numbers_c89_T398.h": pass
include "complex_numbers_T305.pyx"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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