Commit e6fe1a89 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents 7077456c 6a774aad
...@@ -7,7 +7,12 @@ from Cython.Utils import EncodedString ...@@ -7,7 +7,12 @@ from Cython.Utils import EncodedString
from Cython.Compiler.Errors import CompileError from Cython.Compiler.Errors import CompileError
import Interpreter import Interpreter
import PyrexTypes import PyrexTypes
from sets import Set as set
try:
set
except NameError:
from sets import Set as set
import textwrap import textwrap
# Code cleanup ideas: # Code cleanup ideas:
......
...@@ -12,7 +12,7 @@ Cython language. Cython is based on Pyrex by Greg Ewing. ...@@ -12,7 +12,7 @@ Cython language. Cython is based on Pyrex by Greg Ewing.
Usage: cython [options] sourcefile.pyx ... Usage: cython [options] sourcefile.pyx ...
Options: Options:
-v, --version Display version number of cython compiler -V, --version Display version number of cython compiler
-l, --create-listing Write error messages to a listing file -l, --create-listing Write error messages to a listing file
-I, --include-dir <directory> Search for include files in named directory -I, --include-dir <directory> Search for include files in named directory
(multiply include directories are allowed). (multiply include directories are allowed).
...@@ -21,6 +21,7 @@ Options: ...@@ -21,6 +21,7 @@ Options:
-t, --timestamps Only compile newer source files (implied with -r) -t, --timestamps Only compile newer source files (implied with -r)
-f, --force Compile all source files (overrides implied -t) -f, --force Compile all source files (overrides implied -t)
-q, --quiet Don't print module names in recursive mode -q, --quiet Don't print module names in recursive mode
-v, --verbose Be verbose, print file names on multiple compilation
-p, --embed-positions If specified, the positions in Cython files of each -p, --embed-positions If specified, the positions in Cython files of each
function definition is embedded in its docstring. function definition is embedded in its docstring.
-z, --pre-import <module> If specified, assume undeclared names in this -z, --pre-import <module> If specified, assume undeclared names in this
...@@ -34,7 +35,7 @@ Options: ...@@ -34,7 +35,7 @@ Options:
are searched from) are searched from)
-D, --no-docstrings Remove docstrings. -D, --no-docstrings Remove docstrings.
-a, --annotate Produce an colorized version of the source. -a, --annotate Produce a colorized HTML version of the source.
--convert-range Convert for loops using range() function to for...from loops. --convert-range Convert for loops using range() function to for...from loops.
--cplus Output a c++ rather than c file. --cplus Output a c++ rather than c file.
-O, --option <name>=<value>[,<name=value,...] Overrides an optimization/code generation option -O, --option <name>=<value>[,<name=value,...] Overrides an optimization/code generation option
...@@ -72,7 +73,7 @@ def parse_command_line(args): ...@@ -72,7 +73,7 @@ def parse_command_line(args):
while args: while args:
if args[0].startswith("-"): if args[0].startswith("-"):
option = pop_arg() option = pop_arg()
if option in ("-v", "--version"): if option in ("-V", "--version"):
options.show_version = 1 options.show_version = 1
elif option in ("-l", "--create-listing"): elif option in ("-l", "--create-listing"):
options.use_listing_file = 1 options.use_listing_file = 1
...@@ -97,6 +98,8 @@ def parse_command_line(args): ...@@ -97,6 +98,8 @@ def parse_command_line(args):
options.timestamps = 1 options.timestamps = 1
elif option in ("-f", "--force"): elif option in ("-f", "--force"):
options.timestamps = 0 options.timestamps = 0
elif option in ("-v", "--verbose"):
options.verbose += 1
elif option in ("-p", "--embed-positions"): elif option in ("-p", "--embed-positions"):
Options.embed_pos_in_docstring = 1 Options.embed_pos_in_docstring = 1
elif option in ("-z", "--pre-import"): elif option in ("-z", "--pre-import"):
......
...@@ -10,7 +10,10 @@ from PyrexTypes import py_object_type, typecast ...@@ -10,7 +10,10 @@ from PyrexTypes import py_object_type, typecast
from TypeSlots import method_coexist from TypeSlots import method_coexist
from Scanning import SourceDescriptor from Scanning import SourceDescriptor
from Cython.StringIOTree import StringIOTree from Cython.StringIOTree import StringIOTree
from sets import Set as set try:
set
except NameError:
from sets import Set as set
class FunctionState(object): class FunctionState(object):
# return_label string function return point label # return_label string function return point label
...@@ -515,11 +518,18 @@ class CCodeWriter(object): ...@@ -515,11 +518,18 @@ class CCodeWriter(object):
self.marker = None self.marker = None
return self return self
def put_safe(self, code):
# put code, but ignore {}
self.write(code)
self.bol = 0
def put(self, code): def put(self, code):
fix_indent = False
dl = code.count("{") - code.count("}") dl = code.count("{") - code.count("}")
if dl < 0: if dl < 0:
self.level += dl self.level += dl
elif dl == 0 and code.startswith('}'): elif dl == 0 and code.startswith('}'):
fix_indent = True
self.level -= 1 self.level -= 1
if self.bol: if self.bol:
self.indent() self.indent()
...@@ -527,7 +537,7 @@ class CCodeWriter(object): ...@@ -527,7 +537,7 @@ class CCodeWriter(object):
self.bol = 0 self.bol = 0
if dl > 0: if dl > 0:
self.level += dl self.level += dl
elif dl == 0 and code.startswith('}'): elif fix_indent:
self.level += 1 self.level += 1
return self return self
...@@ -616,7 +626,7 @@ class CCodeWriter(object): ...@@ -616,7 +626,7 @@ class CCodeWriter(object):
self.put(entry.type.declaration_code(entry.cname, self.put(entry.type.declaration_code(entry.cname,
dll_linkage = dll_linkage)) dll_linkage = dll_linkage))
if entry.init is not None: if entry.init is not None:
self.put(" = %s" % entry.type.literal_code(entry.init)) self.put_safe(" = %s" % entry.type.literal_code(entry.init))
self.putln(";") self.putln(";")
def put_temp_declarations(self, func_context): def put_temp_declarations(self, func_context):
......
...@@ -14,6 +14,7 @@ from Builtin import list_type, tuple_type, dict_type ...@@ -14,6 +14,7 @@ from Builtin import list_type, tuple_type, dict_type
import Symtab import Symtab
import Options import Options
from Annotate import AnnotationItem from Annotate import AnnotationItem
from Cython import Utils
from Cython.Debugging import print_call_chain from Cython.Debugging import print_call_chain
from DebugFlags import debug_disposal_code, debug_temp_alloc, \ from DebugFlags import debug_disposal_code, debug_temp_alloc, \
...@@ -639,10 +640,10 @@ class CharNode(ConstNode): ...@@ -639,10 +640,10 @@ class CharNode(ConstNode):
type = PyrexTypes.c_char_type type = PyrexTypes.c_char_type
def compile_time_value(self, denv): def compile_time_value(self, denv):
return ord(self.value) return ord(self.value.byteencode())
def calculate_result_code(self): def calculate_result_code(self):
return "'%s'" % self.value return "'%s'" % Utils.escape_character(self.value.byteencode())
class IntNode(ConstNode): class IntNode(ConstNode):
...@@ -707,8 +708,7 @@ class StringNode(ConstNode): ...@@ -707,8 +708,7 @@ class StringNode(ConstNode):
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
if dst_type.is_int: if dst_type.is_int:
if not self.type.is_pyobject and len(self.entry.init) == 1: if not self.type.is_pyobject and len(self.entry.init) == 1:
# we use the *encoded* value here return CharNode(self.pos, value=self.value)
return CharNode(self.pos, value=self.entry.init)
else: else:
error(self.pos, "Only coerce single-character ascii strings can be used as ints.") error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
return self return self
...@@ -737,6 +737,32 @@ class StringNode(ConstNode): ...@@ -737,6 +737,32 @@ class StringNode(ConstNode):
return self.entry.cname return self.entry.cname
class UnicodeNode(PyConstNode):
# entry Symtab.Entry
type = PyrexTypes.c_unicode_type
def analyse_types(self, env):
self.entry = env.add_string_const(self.value)
env.add_py_string(self.entry)
def calculate_result_code(self):
return self.entry.pystring_cname
def _coerce_to(self, dst_type, env):
if not dst_type.is_pyobject:
node = StringNode(self.pos, entry = entry, type = py_object_type)
return ConstNode.coerce_to(node, dst_type, env)
else:
return self
# We still need to perform normal coerce_to processing on the
# result, because we might be coercing to an extension type,
# in which case a type test node will be needed.
def compile_time_value(self, env):
return self.value
class IdentifierStringNode(ConstNode): class IdentifierStringNode(ConstNode):
# A Python string that behaves like an identifier, e.g. for # A Python string that behaves like an identifier, e.g. for
# keyword arguments in a call, or for imported names # keyword arguments in a call, or for imported names
...@@ -870,8 +896,6 @@ class NameNode(AtomicExprNode): ...@@ -870,8 +896,6 @@ class NameNode(AtomicExprNode):
env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment') env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
if self.entry.is_declared_generic: if self.entry.is_declared_generic:
self.result_ctype = py_object_type self.result_ctype = py_object_type
if self.entry.is_pyglobal and self.entry.is_member:
env.use_utility_code(type_cache_invalidation_code)
def analyse_types(self, env): def analyse_types(self, env):
if self.entry is None: if self.entry is None:
...@@ -1025,7 +1049,7 @@ class NameNode(AtomicExprNode): ...@@ -1025,7 +1049,7 @@ class NameNode(AtomicExprNode):
self.interned_cname, self.interned_cname,
rhs.py_result())) rhs.py_result()))
# in Py2.6+, we need to invalidate the method cache # in Py2.6+, we need to invalidate the method cache
code.putln("__Pyx_TypeModified(%s);" % code.putln("PyType_Modified(%s);" %
entry.scope.parent_type.typeptr_cname) entry.scope.parent_type.typeptr_cname)
else: else:
code.put_error_if_neg(self.pos, code.put_error_if_neg(self.pos,
...@@ -1348,6 +1372,9 @@ class IndexNode(ExprNode): ...@@ -1348,6 +1372,9 @@ class IndexNode(ExprNode):
self.is_buffer_access = False self.is_buffer_access = False
self.base.analyse_types(env) self.base.analyse_types(env)
# Handle the case where base is a literal char* (and we expect a string, not an int)
if isinstance(self.base, StringNode):
self.base = self.base.coerce_to_pyobject(env)
skip_child_analysis = False skip_child_analysis = False
buffer_access = False buffer_access = False
...@@ -4433,43 +4460,6 @@ static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) { ...@@ -4433,43 +4460,6 @@ static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
#------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------
type_cache_invalidation_code = [
"""
#if PY_VERSION_HEX >= 0x02060000
/* #define __Pyx_TypeModified(t) PyType_Modified(t) */ /* Py3.0beta1 */
static void __Pyx_TypeModified(PyTypeObject* type); /*proto*/
#else
#define __Pyx_TypeModified(t)
#endif
""","""
#if PY_VERSION_HEX >= 0x02060000
/* copied from typeobject.c in Python 3.0a5 */
static void __Pyx_TypeModified(PyTypeObject* type) {
PyObject *raw, *ref;
Py_ssize_t i, n;
if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
return;
raw = type->tp_subclasses;
if (raw != NULL) {
n = PyList_GET_SIZE(raw);
for (i = 0; i < n; i++) {
ref = PyList_GET_ITEM(raw, i);
ref = PyWeakref_GET_OBJECT(ref);
if (ref != Py_None) {
__Pyx_TypeModified((PyTypeObject *)ref);
}
}
}
type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
}
#endif
"""
]
#------------------------------------------------------------------------------------
# If the is_unsigned flag is set, we need to do some extra work to make # If the is_unsigned flag is set, we need to do some extra work to make
# sure the index doesn't become negative. # sure the index doesn't become negative.
......
...@@ -63,8 +63,9 @@ def make_lexicon(): ...@@ -63,8 +63,9 @@ def make_lexicon():
three_oct = octdigit + octdigit + octdigit three_oct = octdigit + octdigit + octdigit
two_hex = hexdigit + hexdigit two_hex = hexdigit + hexdigit
four_hex = two_hex + two_hex four_hex = two_hex + two_hex
escapeseq = Str("\\") + (two_oct | three_oct | two_hex | escapeseq = Str("\\") + (two_oct | three_oct |
Str('u') + four_hex | Str('x') + two_hex | AnyChar) Str('u') + four_hex | Str('x') + two_hex |
Str('U') + four_hex + four_hex | AnyChar)
deco = Str("@") deco = Str("@")
......
...@@ -189,7 +189,9 @@ class Context: ...@@ -189,7 +189,9 @@ class Context:
scope = None scope = None
pxd_pathname = None pxd_pathname = None
if not module_name_pattern.match(module_name): if not module_name_pattern.match(module_name):
raise CompileError((path, 0, 0), if pos is None:
pos = (module_name, 0, 0)
raise CompileError(pos,
"'%s' is not a valid module name" % module_name) "'%s' is not a valid module name" % module_name)
if "." not in module_name and relative_to: if "." not in module_name and relative_to:
if debug_find_module: if debug_find_module:
...@@ -477,13 +479,6 @@ def create_default_resultobj(compilation_source, options): ...@@ -477,13 +479,6 @@ def create_default_resultobj(compilation_source, options):
else: else:
c_suffix = ".c" c_suffix = ".c"
result.c_file = Utils.replace_suffix(source_desc.filename, c_suffix) result.c_file = Utils.replace_suffix(source_desc.filename, c_suffix)
# The below doesn't make any sense? Why is it there?
c_stat = None
if result.c_file:
try:
c_stat = os.stat(result.c_file)
except EnvironmentError:
pass
return result return result
def run_pipeline(source, options, full_module_name = None): def run_pipeline(source, options, full_module_name = None):
...@@ -615,8 +610,6 @@ def compile_single(source, options, full_module_name = None): ...@@ -615,8 +610,6 @@ def compile_single(source, options, full_module_name = None):
recursion. recursion.
""" """
return run_pipeline(source, options, full_module_name) return run_pipeline(source, options, full_module_name)
# context = Context(options.include_path)
# return context.compile(source, options, full_module_name)
def compile_multiple(sources, options): def compile_multiple(sources, options):
...@@ -636,15 +629,14 @@ def compile_multiple(sources, options): ...@@ -636,15 +629,14 @@ def compile_multiple(sources, options):
timestamps = recursive timestamps = recursive
verbose = options.verbose or ((recursive or timestamps) and not options.quiet) verbose = options.verbose or ((recursive or timestamps) and not options.quiet)
for source in sources: for source in sources:
context = Context(options.include_path) # to be removed later
if source not in processed: if source not in processed:
# Compiling multiple sources in one context doesn't quite
# work properly yet.
if not timestamps or context.c_file_out_of_date(source): if not timestamps or context.c_file_out_of_date(source):
if verbose: if verbose:
sys.stderr.write("Compiling %s\n" % source) sys.stderr.write("Compiling %s\n" % source)
result = context.compile(source, options) result = run_pipeline(source, options)
# Compiling multiple sources in one context doesn't quite
# work properly yet.
results.add(source, result) results.add(source, result)
processed.add(source) processed.add(source)
if recursive: if recursive:
...@@ -674,10 +666,7 @@ def compile(source, options = None, c_compile = 0, c_link = 0, ...@@ -674,10 +666,7 @@ def compile(source, options = None, c_compile = 0, c_link = 0,
and not options.recursive: and not options.recursive:
return compile_single(source, options, full_module_name) return compile_single(source, options, full_module_name)
else: else:
# Hack it for wednesday dev1 return compile_multiple(source, options)
assert len(source) == 1
return compile_single(source[0], options)
# return compile_multiple(source, options)
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
......
...@@ -23,7 +23,7 @@ import Version ...@@ -23,7 +23,7 @@ import Version
from Errors import error, warning from Errors import error, warning
from PyrexTypes import py_object_type from PyrexTypes import py_object_type
from Cython.Utils import open_new_file, replace_suffix from Cython.Utils import open_new_file, replace_suffix, escape_byte_string, EncodedString
def check_c_classes(module_node): def check_c_classes(module_node):
...@@ -45,9 +45,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -45,9 +45,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def analyse_declarations(self, env): def analyse_declarations(self, env):
if Options.embed_pos_in_docstring: if Options.embed_pos_in_docstring:
env.doc = 'File: %s (starting at line %s)'%Nodes.relative_position(self.pos) env.doc = EncodedString(u'File: %s (starting at line %s)' % Nodes.relative_position(self.pos))
if not self.doc is None: if not self.doc is None:
env.doc = env.doc + '\\n' + self.doc env.doc = EncodedString(env.doc + u'\\n' + self.doc)
env.doc.encoding = self.doc.encoding
else: else:
env.doc = self.doc env.doc = self.doc
self.body.analyse_declarations(env) self.body.analyse_declarations(env)
...@@ -423,6 +424,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -423,6 +424,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #define Py_SIZE(ob) ((PyVarObject*)(ob))->ob_size)") code.putln(" #define Py_SIZE(ob) ((PyVarObject*)(ob))->ob_size)")
code.putln(" #define PyVarObject_HEAD_INIT(type, size) \\") code.putln(" #define PyVarObject_HEAD_INIT(type, size) \\")
code.putln(" PyObject_HEAD_INIT(type) size,") code.putln(" PyObject_HEAD_INIT(type) size,")
code.putln(" #define PyType_Modified(t)")
code.putln("") code.putln("")
code.putln(" typedef struct {") code.putln(" typedef struct {")
code.putln(" void *buf;") code.putln(" void *buf;")
...@@ -513,7 +515,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -513,7 +515,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static const char **%s;' % Naming.filetable_cname) code.putln('static const char **%s;' % Naming.filetable_cname)
if env.doc: if env.doc:
code.putln('') code.putln('')
code.putln('static char %s[] = "%s";' % (env.doc_cname, env.doc)) code.putln('static char %s[] = "%s";' % (
env.doc_cname, escape_byte_string(env.doc.utf8encode())))
def generate_extern_c_macro_definition(self, code): def generate_extern_c_macro_definition(self, code):
name = Naming.extern_c_macro name = Naming.extern_c_macro
......
...@@ -12,7 +12,8 @@ import TypeSlots ...@@ -12,7 +12,8 @@ import TypeSlots
from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \ from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
StructOrUnionScope, PyClassScope, CClassScope StructOrUnionScope, PyClassScope, CClassScope
from Cython.Utils import open_new_file, replace_suffix, EncodedString from Cython.Utils import open_new_file, replace_suffix
from Cython.Utils import EncodedString, escape_byte_string
import Options import Options
import ControlFlow import ControlFlow
...@@ -762,7 +763,7 @@ class CEnumDefItemNode(StatNode): ...@@ -762,7 +763,7 @@ class CEnumDefItemNode(StatNode):
else: else:
value = self.name value = self.name
entry = env.declare_const(self.name, enum_entry.type, entry = env.declare_const(self.name, enum_entry.type,
value, self.pos, cname = self.cname) value, self.pos, cname = self.cname, visibility = enum_entry.visibility)
enum_entry.enum_values.append(entry) enum_entry.enum_values.append(entry)
...@@ -945,6 +946,8 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -945,6 +946,8 @@ class FuncDefNode(StatNode, BlockNode):
if err_val is not None or exc_check: if err_val is not None or exc_check:
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name) code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
else: else:
warning(self.entry.pos, "Unraisable exception in function '%s'." \
% self.entry.qualified_name, 0)
code.putln( code.putln(
'__Pyx_WriteUnraisable("%s");' % '__Pyx_WriteUnraisable("%s");' %
self.entry.qualified_name) self.entry.qualified_name)
...@@ -1516,7 +1519,7 @@ class DefNode(FuncDefNode): ...@@ -1516,7 +1519,7 @@ class DefNode(FuncDefNode):
code.putln( code.putln(
'static char %s[] = "%s";' % ( 'static char %s[] = "%s";' % (
self.entry.doc_cname, self.entry.doc_cname,
self.entry.doc)) escape_byte_string(self.entry.doc.utf8encode())))
if with_pymethdef: if with_pymethdef:
code.put( code.put(
"static PyMethodDef %s = " % "static PyMethodDef %s = " %
...@@ -4281,11 +4284,12 @@ static int __Pyx_CheckKeywordStrings( ...@@ -4281,11 +4284,12 @@ static int __Pyx_CheckKeywordStrings(
} }
if (unlikely(!kw_allowed) && unlikely(key)) { if (unlikely(!kw_allowed) && unlikely(key)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"'%s' is an invalid keyword argument for this function",
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
"'%s' is an invalid keyword argument for this function",
PyString_AsString(key)); PyString_AsString(key));
#else #else
PyUnicode_AsString(key)); "'%U' is an invalid keyword argument for this function",
key);
#endif #endif
return 0; return 0;
} }
...@@ -4456,9 +4460,9 @@ static void __Pyx_AddTraceback(const char *funcname) { ...@@ -4456,9 +4460,9 @@ static void __Pyx_AddTraceback(const char *funcname) {
if (!py_srcfile) goto bad; if (!py_srcfile) goto bad;
if (%(CLINENO)s) { if (%(CLINENO)s) {
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3
py_funcname = PyString_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s); py_funcname = PyString_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
#else #else
py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%u)", funcname, %(CFILENAME)s, %(CLINENO)s); py_funcname = PyUnicode_FromFormat( "%%s (%%s:%%d)", funcname, %(CFILENAME)s, %(CLINENO)s);
#endif #endif
} }
else { else {
......
...@@ -22,7 +22,7 @@ class SwitchTransform(Visitor.VisitorTransform): ...@@ -22,7 +22,7 @@ class SwitchTransform(Visitor.VisitorTransform):
""" """
This transformation tries to turn long if statements into C switch statements. This transformation tries to turn long if statements into C switch statements.
The requirement is that every clause be an (or of) var == value, where the var The requirement is that every clause be an (or of) var == value, where the var
is common among all clauses and both var and value are not Python objects. is common among all clauses and both var and value are ints.
""" """
def extract_conditions(self, cond): def extract_conditions(self, cond):
...@@ -66,6 +66,8 @@ class SwitchTransform(Visitor.VisitorTransform): ...@@ -66,6 +66,8 @@ class SwitchTransform(Visitor.VisitorTransform):
return node return node
elif common_var is not None and not is_common_value(var, common_var): elif common_var is not None and not is_common_value(var, common_var):
return node return node
elif not var.type.is_int or sum([not cond.type.is_int for cond in conditions]):
return node
else: else:
common_var = var common_var = var
cases.append(Nodes.SwitchCaseNode(pos = if_clause.pos, cases.append(Nodes.SwitchCaseNode(pos = if_clause.pos,
......
...@@ -5,7 +5,10 @@ from Cython.Compiler.ExprNodes import * ...@@ -5,7 +5,10 @@ from Cython.Compiler.ExprNodes import *
from Cython.Compiler.TreeFragment import TreeFragment from Cython.Compiler.TreeFragment import TreeFragment
from Cython.Utils import EncodedString from Cython.Utils import EncodedString
from Cython.Compiler.Errors import CompileError from Cython.Compiler.Errors import CompileError
from sets import Set as set try:
set
except NameError:
from sets import Set as set
import copy import copy
class NormalizeTree(CythonTransform): class NormalizeTree(CythonTransform):
...@@ -356,7 +359,7 @@ class ResolveOptions(CythonTransform): ...@@ -356,7 +359,7 @@ class ResolveOptions(CythonTransform):
for option in options: for option in options:
name, value = option name, value = option
optdict[name] = value optdict[name] = value
return self.visit_with_options(node, options) return self.visit_with_options(node, optdict)
else: else:
return self.visit_Node(node) return self.visit_Node(node)
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
# Pyrex Parser # Pyrex Parser
# #
import os, re import os
import re
import sys
from types import ListType, TupleType from types import ListType, TupleType
from Scanning import PyrexScanner, FileSourceDescriptor from Scanning import PyrexScanner, FileSourceDescriptor
import Nodes import Nodes
...@@ -491,6 +493,8 @@ def p_atom(s): ...@@ -491,6 +493,8 @@ def p_atom(s):
kind, value = p_cat_string_literal(s) kind, value = p_cat_string_literal(s)
if kind == 'c': if kind == 'c':
return ExprNodes.CharNode(pos, value = value) return ExprNodes.CharNode(pos, value = value)
elif kind == 'u':
return ExprNodes.UnicodeNode(pos, value = value)
else: else:
return ExprNodes.StringNode(pos, value = value) return ExprNodes.StringNode(pos, value = value)
elif sy == 'IDENT': elif sy == 'IDENT':
...@@ -584,43 +588,43 @@ def p_string_literal(s): ...@@ -584,43 +588,43 @@ def p_string_literal(s):
sy = s.sy sy = s.sy
#print "p_string_literal: sy =", sy, repr(s.systring) ### #print "p_string_literal: sy =", sy, repr(s.systring) ###
if sy == 'CHARS': if sy == 'CHARS':
systr = s.systring chars.append(s.systring)
if len(systr) == 1 and systr in "'\"\n":
chars.append('\\')
chars.append(systr)
elif sy == 'ESCAPE': elif sy == 'ESCAPE':
systr = s.systring systr = s.systring
if is_raw: if is_raw:
if systr == '\\\n': if systr == '\\\n':
chars.append(r'\\\n') chars.append('\\\n')
elif systr == r'\"': elif systr == '\\\"':
chars.append(r'\\\"') chars.append('"')
elif systr == r'\\': elif systr == '\\\'':
chars.append(r'\\\\') chars.append("'")
else: else:
chars.append('\\' + systr) chars.append(systr)
else: else:
c = systr[1] c = systr[1]
if c in "'\"\\abfnrtv01234567": if c in "01234567":
chars.append(systr) chars.append(chr(int(systr[1:], 8)))
elif c in "'\"\\":
chars.append(c)
elif c in "abfnrtv":
chars.append(Utils.char_from_escape_sequence(systr))
elif c == '\n': elif c == '\n':
pass pass
elif c in 'ux': elif c in 'Uux':
if kind == 'u': if kind == 'u' or c == 'x':
try: chrval = int(systr[2:], 16)
chars.append( if chrval > 1114111: # sys.maxunicode:
systr.encode("ASCII").decode('unicode_escape'))
except UnicodeDecodeError:
s.error("Invalid unicode escape '%s'" % systr, s.error("Invalid unicode escape '%s'" % systr,
pos = pos) pos = pos)
elif c == 'x': strval = unichr(chrval)
chars.append('\\x0' + systr[2:])
else: else:
chars.append(systr) # unicode escapes in plain byte strings are not unescaped
strval = systr
chars.append(strval)
else: else:
chars.append(r'\\' + systr[1:]) chars.append('\\' + systr[1:])
elif sy == 'NEWLINE': elif sy == 'NEWLINE':
chars.append(r'\n') chars.append('\n')
elif sy == 'END_STRING': elif sy == 'END_STRING':
break break
elif sy == 'EOF': elif sy == 'EOF':
...@@ -629,8 +633,11 @@ def p_string_literal(s): ...@@ -629,8 +633,11 @@ def p_string_literal(s):
s.error( s.error(
"Unexpected token %r:%r in string literal" % "Unexpected token %r:%r in string literal" %
(sy, s.systring)) (sy, s.systring))
string = u''.join(chars)
if kind == 'c' and len(string) != 1:
error(pos, u"invalid character literal: %r" % string)
s.next() s.next()
value = Utils.EncodedString( u''.join(chars) ) value = Utils.EncodedString(string)
if kind != 'u': if kind != 'u':
value.encoding = s.source_encoding value.encoding = s.source_encoding
#print "p_string_literal: value =", repr(value) ### #print "p_string_literal: value =", repr(value) ###
...@@ -1630,7 +1637,7 @@ def p_buffer_access(s, base_type_node): ...@@ -1630,7 +1637,7 @@ def p_buffer_access(s, base_type_node):
# s.sy == '[' # s.sy == '['
pos = s.position() pos = s.position()
s.next() s.next()
if s.sy == ']': if s.sy == ']' or s.sy == 'INT':
# not buffer, could be [] on C type nameless array arguments # not buffer, could be [] on C type nameless array arguments
s.put_back('[', '[') s.put_back('[', '[')
return base_type_node return base_type_node
...@@ -1881,7 +1888,7 @@ def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0) ...@@ -1881,7 +1888,7 @@ def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0)
if 'pxd' in s.level: if 'pxd' in s.level:
if s.sy not in ['*', '?']: if s.sy not in ['*', '?']:
error(pos, "default values cannot be specified in pxd files, use ? or *") error(pos, "default values cannot be specified in pxd files, use ? or *")
default = 1 default = ExprNodes.BoolNode(1)
s.next() s.next()
else: else:
default = p_simple_expr(s) default = p_simple_expr(s)
......
...@@ -292,6 +292,13 @@ class BuiltinObjectType(PyObjectType): ...@@ -292,6 +292,13 @@ class BuiltinObjectType(PyObjectType):
def type_test_code(self, arg): def type_test_code(self, arg):
return 'likely(Py%s_CheckExact(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", Py_TYPE(%s)->tp_name), 0)' % (self.name[0].upper() + self.name[1:], arg, arg, self.name, arg) return 'likely(Py%s_CheckExact(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", Py_TYPE(%s)->tp_name), 0)' % (self.name[0].upper() + self.name[1:], arg, arg, self.name, arg)
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
return self.base_declaration_code(self.name, entity_code)
else:
return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
class PyExtensionType(PyObjectType): class PyExtensionType(PyObjectType):
# #
...@@ -996,20 +1003,6 @@ class CStringType: ...@@ -996,20 +1003,6 @@ class CStringType:
return '"%s"' % Utils.escape_byte_string(value) return '"%s"' % Utils.escape_byte_string(value)
class CUTF8StringType:
# Mixin class for C unicode types.
is_string = 1
is_unicode = 1
to_py_function = "PyUnicode_DecodeUTF8"
exception_value = "NULL"
def literal_code(self, value):
assert isinstance(value, str)
return '"%s"' % Utils.escape_byte_string(value)
class CCharArrayType(CStringType, CArrayType): class CCharArrayType(CStringType, CArrayType):
# C 'char []' type. # C 'char []' type.
...@@ -1018,16 +1011,6 @@ class CCharArrayType(CStringType, CArrayType): ...@@ -1018,16 +1011,6 @@ class CCharArrayType(CStringType, CArrayType):
def __init__(self, size): def __init__(self, size):
CArrayType.__init__(self, c_char_type, size) CArrayType.__init__(self, c_char_type, size)
class CUTF8CharArrayType(CUTF8StringType, CArrayType):
# C 'char []' type.
parsetuple_format = "s"
pymemberdef_typecode = "T_STRING_INPLACE"
def __init__(self, size):
CArrayType.__init__(self, c_char_type, size)
class CCharPtrType(CStringType, CPtrType): class CCharPtrType(CStringType, CPtrType):
...@@ -1040,6 +1023,29 @@ class CCharPtrType(CStringType, CPtrType): ...@@ -1040,6 +1023,29 @@ class CCharPtrType(CStringType, CPtrType):
CPtrType.__init__(self, c_char_type) CPtrType.__init__(self, c_char_type)
class UnicodeType(BuiltinObjectType):
# The Python unicode type.
is_string = 1
is_unicode = 1
parsetuple_format = "U"
def __init__(self):
BuiltinObjectType.__init__(self, "unicode", "PyUnicodeObject")
def literal_code(self, value):
assert isinstance(value, str)
return '"%s"' % Utils.escape_byte_string(value)
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
return self.base_declaration_code(self.name, entity_code)
else:
return "%s %s[]" % (public_decl("char", dll_linkage), entity_code)
class ErrorType(PyrexType): class ErrorType(PyrexType):
# Used to prevent propagation of error messages. # Used to prevent propagation of error messages.
...@@ -1105,7 +1111,7 @@ c_longdouble_type = CFloatType(8, typestring="g") ...@@ -1105,7 +1111,7 @@ c_longdouble_type = CFloatType(8, typestring="g")
c_null_ptr_type = CNullPtrType(c_void_type) c_null_ptr_type = CNullPtrType(c_void_type)
c_char_array_type = CCharArrayType(None) c_char_array_type = CCharArrayType(None)
c_utf8_char_array_type = CUTF8CharArrayType(None) c_unicode_type = UnicodeType()
c_char_ptr_type = CCharPtrType() c_char_ptr_type = CCharPtrType()
c_char_ptr_ptr_type = CPtrType(c_char_ptr_type) c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type) c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type)
......
...@@ -38,7 +38,10 @@ def hash_source_file(path): ...@@ -38,7 +38,10 @@ def hash_source_file(path):
# Try to calculate a hash code for the given source file. # Try to calculate a hash code for the given source file.
# Returns an empty string if the file cannot be accessed. # Returns an empty string if the file cannot be accessed.
#print "Hashing", path ### #print "Hashing", path ###
import md5 try:
from hashlib import md5 as new_md5
except ImportError:
from md5 import new as new_md5
try: try:
try: try:
f = open(path, "rU") f = open(path, "rU")
...@@ -54,7 +57,7 @@ def hash_source_file(path): ...@@ -54,7 +57,7 @@ def hash_source_file(path):
# tabs by a single space. # tabs by a single space.
import re import re
text = re.sub("[ \t]+", " ", text) text = re.sub("[ \t]+", " ", text)
hash = md5.new(text).hexdigest() hash = new_md5(text).hexdigest()
return hash return hash
def open_pickled_lexicon(expected_hash): def open_pickled_lexicon(expected_hash):
......
...@@ -15,7 +15,10 @@ from TypeSlots import \ ...@@ -15,7 +15,10 @@ from TypeSlots import \
get_special_method_signature, get_property_accessor_signature get_special_method_signature, get_property_accessor_signature
import ControlFlow import ControlFlow
import __builtin__ import __builtin__
from sets import Set as set try:
set
except NameError:
from sets import Set as set
possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
...@@ -287,14 +290,14 @@ class Scope: ...@@ -287,14 +290,14 @@ class Scope:
def qualify_name(self, name): def qualify_name(self, name):
return "%s.%s" % (self.qualified_name, name) return "%s.%s" % (self.qualified_name, name)
def declare_const(self, name, type, value, pos, cname = None): def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
# Add an entry for a named constant. # Add an entry for a named constant.
if not cname: if not cname:
if self.in_cinclude: if self.in_cinclude:
cname = name cname = name
else: else:
cname = self.mangle(Naming.enum_prefix, name) cname = self.mangle(Naming.enum_prefix, name)
entry = self.declare(name, cname, type, pos, 'private') entry = self.declare(name, cname, type, pos, visibility)
entry.is_const = 1 entry.is_const = 1
entry.value = value entry.value = value
return entry return entry
...@@ -502,7 +505,7 @@ class Scope: ...@@ -502,7 +505,7 @@ class Scope:
else: else:
cname = self.new_const_cname() cname = self.new_const_cname()
if value.is_unicode: if value.is_unicode:
c_type = PyrexTypes.c_utf8_char_array_type c_type = PyrexTypes.c_unicode_type
value = value.utf8encode() value = value.utf8encode()
else: else:
c_type = PyrexTypes.c_char_array_type c_type = PyrexTypes.c_char_array_type
......
...@@ -26,10 +26,6 @@ class TestBufferParsing(CythonTest): ...@@ -26,10 +26,6 @@ class TestBufferParsing(CythonTest):
# print bufnode.dump() # print bufnode.dump()
# should put more here... # should put more here...
def test_type_fail(self):
self.not_parseable("Expected: type",
u"cdef object[2] x")
def test_type_pos(self): def test_type_pos(self):
self.parse(u"cdef object[short unsigned int, 3] x") self.parse(u"cdef object[short unsigned int, 3] x")
......
...@@ -28,6 +28,10 @@ class BasicVisitor(object): ...@@ -28,6 +28,10 @@ class BasicVisitor(object):
if m is not None: if m is not None:
break break
else: else:
print type(self), type(obj)
print self.access_path
print self.access_path[-1][0].pos
print self.access_path[-1][0].__dict__
raise RuntimeError("Visitor does not accept object: %s" % obj) raise RuntimeError("Visitor does not accept object: %s" % obj)
self.dispatch_table[mname] = m self.dispatch_table[mname] = m
return m(obj) return m(obj)
......
...@@ -118,32 +118,28 @@ ...@@ -118,32 +118,28 @@
# just to be sure you understand what is going on. # just to be sure you understand what is going on.
# #
################################################################# #################################################################
cdef extern from "Python.h":
ctypedef void PyObject
ctypedef void PyTypeObject
ctypedef struct FILE
include 'python_ref.pxi' from python_ref cimport *
include 'python_exc.pxi' from python_exc cimport *
include 'python_module.pxi' from python_module cimport *
include 'python_mem.pxi' from python_mem cimport *
include 'python_tuple.pxi' from python_tuple cimport *
include 'python_list.pxi' from python_list cimport *
include 'python_object.pxi' from python_object cimport *
include 'python_sequence.pxi' from python_sequence cimport *
include 'python_mapping.pxi' from python_mapping cimport *
include 'python_iterator.pxi' from python_iterator cimport *
include 'python_type.pxi' from python_type cimport *
include 'python_number.pxi' from python_number cimport *
include 'python_int.pxi' from python_int cimport *
include 'python_bool.pxi' from python_bool cimport *
include 'python_long.pxi' from python_long cimport *
include 'python_float.pxi' from python_float cimport *
include 'python_complex.pxi' from python_complex cimport *
include 'python_string.pxi' from python_string cimport *
include 'python_dict.pxi' from python_dict cimport *
include 'python_instance.pxi' from python_instance cimport *
include 'python_function.pxi' from python_function cimport *
include 'python_method.pxi' from python_method cimport *
include 'python_set.pxi' from python_set cimport *
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef void PyObject
ctypedef void PyTypeObject ctypedef void PyTypeObject
ctypedef struct PyObject:
Py_ssize_t ob_refcnt
PyTypeObject *ob_type
ctypedef struct FILE ctypedef struct FILE
......
...@@ -70,40 +70,21 @@ EXAMPLE: ...@@ -70,40 +70,21 @@ EXAMPLE:
>>> b = a.insertion_point() >>> b = a.insertion_point()
>>> a.write('third\n') >>> a.write('third\n')
>>> b.write('second\n') >>> b.write('second\n')
>>> print a.getvalue() >>> a.getvalue().split()
first ['first', 'second', 'third']
second
third
<BLANKLINE>
>>> c = b.insertion_point() >>> c = b.insertion_point()
>>> d = c.insertion_point() >>> d = c.insertion_point()
>>> d.write('alpha\n') >>> d.write('alpha\n')
>>> b.write('gamma\n') >>> b.write('gamma\n')
>>> c.write('beta\n') >>> c.write('beta\n')
>>> print b.getvalue() >>> b.getvalue().split()
second ['second', 'alpha', 'beta', 'gamma']
alpha
beta
gamma
<BLANKLINE>
>>> i = StringIOTree() >>> i = StringIOTree()
>>> d.insert(i) >>> d.insert(i)
>>> i.write('inserted\n') >>> i.write('inserted\n')
>>> out = StringIO() >>> out = StringIO()
>>> a.copyto(out) >>> a.copyto(out)
>>> print out.getvalue() >>> out.getvalue().split()
first ['first', 'second', 'alpha', 'inserted', 'beta', 'gamma', 'third']
second """
alpha \ No newline at end of file
inserted
beta
gamma
third
<BLANKLINE>
"""
if __name__ == "__main__":
import doctest
doctest.testmod()
...@@ -99,8 +99,53 @@ class EncodedString(unicode): ...@@ -99,8 +99,53 @@ class EncodedString(unicode):
# return unicode.__eq__(self, other) and \ # return unicode.__eq__(self, other) and \
# getattr(other, 'encoding', '') == self.encoding # getattr(other, 'encoding', '') == self.encoding
char_from_escape_sequence = {
r'\a' : '\a',
r'\b' : '\b',
r'\f' : '\f',
r'\n' : '\n',
r'\r' : '\r',
r'\t' : '\t',
r'\v' : '\v',
}.get
def _to_escape_sequence(s):
if s in '\n\r\t':
return repr(s)[1:-1]
elif s == '"':
return r'\"'
else:
# within a character sequence, oct passes much better than hex
return ''.join(['\\%03o' % ord(c) for c in s])
_c_special = ('\0', '\n', '\r', '\t', '??', '"')
_c_special_replacements = zip(_c_special, map(_to_escape_sequence, _c_special))
def _build_specials_test():
subexps = []
for special in _c_special:
regexp = ''.join(['[%s]' % c for c in special])
subexps.append(regexp)
return re.compile('|'.join(subexps)).search
_has_specials = _build_specials_test()
def escape_character(c):
if c in '\n\r\t\\':
return repr(c)[1:-1]
elif c == "'":
return "\\'"
elif ord(c) < 32:
# hex works well for characters
return "\\x%02X" % ord(c)
else:
return c
def escape_byte_string(s): def escape_byte_string(s):
s = s.replace('\0', r'\x00') s = s.replace('\\', '\\\\')
if _has_specials(s):
for special, replacement in _c_special_replacements:
s = s.replace(special, replacement)
try: try:
s.decode("ASCII") s.decode("ASCII")
return s return s
...@@ -111,7 +156,7 @@ def escape_byte_string(s): ...@@ -111,7 +156,7 @@ def escape_byte_string(s):
for c in s: for c in s:
o = ord(c) o = ord(c)
if o >= 128: if o >= 128:
append('\\x%X' % o) append('\\%3o' % o)
else: else:
append(c) append(c)
return ''.join(l) return ''.join(l)
......
...@@ -265,6 +265,7 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -265,6 +265,7 @@ class CythonRunTestCase(CythonCompileTestCase):
try: try:
self.runCompileTest() self.runCompileTest()
if not self.cythononly: if not self.cythononly:
sys.stderr.write('running doctests in %s ...\n' % self.module)
doctest.DocTestSuite(self.module).run(result) doctest.DocTestSuite(self.module).run(result)
except Exception: except Exception:
result.addError(self, sys.exc_info()) result.addError(self, sys.exc_info())
...@@ -276,7 +277,7 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -276,7 +277,7 @@ class CythonRunTestCase(CythonCompileTestCase):
class CythonUnitTestCase(CythonCompileTestCase): class CythonUnitTestCase(CythonCompileTestCase):
def shortDescription(self): def shortDescription(self):
return "compiling and running unit tests in " + self.module return "compiling tests in " + self.module
def run(self, result=None): def run(self, result=None):
if result is None: if result is None:
...@@ -284,6 +285,7 @@ class CythonUnitTestCase(CythonCompileTestCase): ...@@ -284,6 +285,7 @@ class CythonUnitTestCase(CythonCompileTestCase):
result.startTest(self) result.startTest(self)
try: try:
self.runCompileTest() self.runCompileTest()
sys.stderr.write('running tests in %s ...\n' % self.module)
unittest.defaultTestLoader.loadTestsFromName(self.module).run(result) unittest.defaultTestLoader.loadTestsFromName(self.module).run(result)
except Exception: except Exception:
result.addError(self, sys.exc_info()) result.addError(self, sys.exc_info())
...@@ -380,6 +382,9 @@ if __name__ == '__main__': ...@@ -380,6 +382,9 @@ if __name__ == '__main__':
parser.add_option("--cython-only", dest="cythononly", parser.add_option("--cython-only", dest="cythononly",
action="store_true", default=False, action="store_true", default=False,
help="only compile pyx to c, do not run C compiler or run the tests") help="only compile pyx to c, do not run C compiler or run the tests")
parser.add_option("--sys-pyregr", dest="system_pyregr",
action="store_true", default=False,
help="run the regression tests of the CPython installation")
parser.add_option("-C", "--coverage", dest="coverage", parser.add_option("-C", "--coverage", dest="coverage",
action="store_true", default=False, action="store_true", default=False,
help="collect source coverage data for the Compiler") help="collect source coverage data for the Compiler")
...@@ -392,6 +397,13 @@ if __name__ == '__main__': ...@@ -392,6 +397,13 @@ if __name__ == '__main__':
options, cmd_args = parser.parse_args() options, cmd_args = parser.parse_args()
if sys.version_info[0] >= 3:
# make sure we do not import (or run) Cython itself
options.doctests = False
options.with_cython = False
options.unittests = False
options.pyregr = False
if options.coverage: if options.coverage:
import coverage import coverage
coverage.erase() coverage.erase()
...@@ -420,11 +432,11 @@ if __name__ == '__main__': ...@@ -420,11 +432,11 @@ if __name__ == '__main__':
if WITH_CYTHON: if WITH_CYTHON:
from Cython.Compiler.Version import version from Cython.Compiler.Version import version
print("Running tests against Cython %s" % version) sys.stderr.write("Running tests against Cython %s\n" % version)
else: else:
print("Running tests without Cython.") sys.stderr.write("Running tests without Cython.\n")
print("Python %s" % sys.version) sys.stderr.write("Python %s\n" % sys.version)
print("") sys.stderr.write("\n")
import re import re
selectors = [ re.compile(r, re.I|re.U).search for r in cmd_args ] selectors = [ re.compile(r, re.I|re.U).search for r in cmd_args ]
...@@ -443,7 +455,16 @@ if __name__ == '__main__': ...@@ -443,7 +455,16 @@ if __name__ == '__main__':
filetests = TestBuilder(ROOTDIR, WORKDIR, selectors, filetests = TestBuilder(ROOTDIR, WORKDIR, selectors,
options.annotate_source, options.cleanup_workdir, options.annotate_source, options.cleanup_workdir,
options.cleanup_sharedlibs, options.pyregr, options.cythononly) options.cleanup_sharedlibs, options.pyregr, options.cythononly)
test_suite.addTests([filetests.build_suite()]) test_suite.addTest(filetests.build_suite())
if options.system_pyregr:
filetests = TestBuilder(ROOTDIR, WORKDIR, selectors,
options.annotate_source, options.cleanup_workdir,
options.cleanup_sharedlibs, True)
test_suite.addTest(
filetests.handle_directory(
os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test'),
'pyregr'))
unittest.TextTestRunner(verbosity=options.verbosity).run(test_suite) unittest.TextTestRunner(verbosity=options.verbosity).run(test_suite)
......
...@@ -11,3 +11,9 @@ cdef extern from *: ...@@ -11,3 +11,9 @@ cdef extern from *:
ctypedef MyStruct* MyStructP ctypedef MyStruct* MyStructP
cdef void baz(MyStructP[]) cdef void baz(MyStructP[])
cdef struct OtherStruct:
int a
a = sizeof(int[23][34])
b = sizeof(OtherStruct[43])
...@@ -14,7 +14,7 @@ cimport python_buffer ...@@ -14,7 +14,7 @@ cimport python_buffer
cimport stdio cimport stdio
cimport cython cimport cython
cimport refcount from python_ref cimport PyObject
__test__ = {} __test__ = {}
setup_string = u""" setup_string = u"""
...@@ -726,7 +726,7 @@ def decref(*args): ...@@ -726,7 +726,7 @@ def decref(*args):
for item in args: Py_DECREF(item) for item in args: Py_DECREF(item)
def get_refcount(x): def get_refcount(x):
return refcount.CyTest_GetRefcount(x) return (<PyObject*>x).ob_refcnt
@testcase @testcase
def printbuf_object(object[object] buf, shape): def printbuf_object(object[object] buf, shape):
...@@ -749,7 +749,7 @@ def printbuf_object(object[object] buf, shape): ...@@ -749,7 +749,7 @@ def printbuf_object(object[object] buf, shape):
""" """
cdef int i cdef int i
for i in range(shape[0]): for i in range(shape[0]):
print repr(buf[i]), refcount.CyTest_GetRefcount(buf[i]) print repr(buf[i]), (<PyObject*>buf[i]).ob_refcnt
@testcase @testcase
def assign_to_object(object[object] buf, int idx, obj): def assign_to_object(object[object] buf, int idx, obj):
......
__doc__ = u""" __doc__ = u"""
>>> test_c(u'abc') >>> test_c('abc')
fileabc fileabc
typeabc typeabc
>>> print test_file_py(u'abc') >>> print(test_file_py('abc'))
abc abc
>>> print range(u'abc') >>> print(range('abc'))
rangeabc rangeabc
""" """
def test_file_py(file): def test_file_py(file):
assert isinstance(file, (str, unicode)), \
u"not a string, found '%s' instead" % file.__class__.__name__
return file return file
cdef test_file_c(file): cdef test_file_c(file):
assert isinstance(file, (str, unicode)), \
u"not a string, found '%s' instead" % file.__class__.__name__
return u'file' + file return u'file' + file
......
cdef class A:
cpdef foo(self, bint a=*, b=*)
__doc__ = """
>>> a = A()
>>> a.foo()
(True, 'yo')
>>> a.foo(False)
(False, 'yo')
>>> a.foo(10, 'yes')
(True, 'yes')
"""
cdef class A:
cpdef foo(self, bint a=True, b="yo"):
return a, b
__doc__ = u"""
>>> s = test()
>>> assert s == ''.join([chr(i) for i in range(1,49)]), s
"""
def test():
cdef char s[50]
s[ 0] = c'\0'
s[ 1] = c'\x01'
s[ 2] = c'\x02'
s[ 3] = c'\x03'
s[ 4] = c'\x04'
s[ 5] = c'\x05'
s[ 6] = c'\x06'
s[ 7] = c'\x07'
s[ 8] = c'\x08'
s[ 9] = c'\x09'
s[10] = c'\x0A'
s[11] = c'\x0B'
s[12] = c'\x0C'
s[13] = c'\x0D'
s[14] = c'\x0E'
s[15] = c'\x0F'
s[16] = c'\x10'
s[17] = c'\x11'
s[18] = c'\x12'
s[19] = c'\x13'
s[20] = c'\x14'
s[21] = c'\x15'
s[22] = c'\x16'
s[23] = c'\x17'
s[24] = c'\x18'
s[25] = c'\x19'
s[26] = c'\x1A'
s[27] = c'\x1B'
s[28] = c'\x1C'
s[29] = c'\x1D'
s[30] = c'\x1E'
s[31] = c'\x1F'
s[32] = c'\x20'
s[33] = c'\x21'
s[34] = c'\x22'
s[35] = c'\x23'
s[36] = c'\x24'
s[37] = c'\x25'
s[38] = c'\x26'
s[39] = c'\x27'
s[40] = c'\x28'
s[41] = c'\x29'
s[42] = c'\x2A'
s[43] = c'\x2B'
s[44] = c'\x2C'
s[45] = c'\x2D'
s[46] = c'\x2E'
s[47] = c'\x2F'
s[48] = c'\x30'
s[49] = c'\x00'
assert s[ 0] == c'\x00'
assert s[49] == c'\0'
return &s[1]
__doc__ = u"""
>>> test_str(1)
b'b'
>>> test_unicode_ascii(2)
u'c'
>>> test_unicode(2) == u'\u00e4'
True
>>> test_int_list(2)
3
>>> test_str_list(1)
b'bcd'
>>> test_int_tuple(2)
3
>>> test_str_tuple(0)
b'a'
>>> test_mix_tuple(1)
b'abc'
>>> test_mix_tuple(0)
1
"""
import sys
if sys.version_info[0] < 3:
__doc__ = __doc__.replace(" b'", " '")
else:
__doc__ = __doc__.replace(" u'", " '")
def test_str(n):
return "abcd"[n]
def test_unicode_ascii(n):
return u"abcd"[n]
def test_unicode(n):
return u"\u00fc\u00f6\u00e4"[n]
def test_int_list(n):
return [1,2,3,4][n]
def test_str_list(n):
return ["a","bcd","efg","xyz"][n]
def test_int_tuple(n):
return (1,2,3,4)[n]
def test_str_tuple(n):
return ("a","bcd","efg","xyz")[n]
def test_mix_tuple(n):
return (1, "abc", u"\u00fc", 1.1)[n]
__doc__ = u"""
>>> py_strings = [
... b'\\x1234',
... b'\\x0A12\\x0C34',
... b'\\x0A57',
... b'\\x0A',
... b'\\'',
... b"\\'",
... b"\\"",
... b'\\"',
... b'abc\\x12def',
... u'\\u1234',
... u'\\U00001234',
... b'\\u1234',
... b'\\U00001234',
... b'\\n\\r\\t',
... b':>',
... b'??>',
... b'\\0\\0\\0',
... ]
>>> for i, (py_string, (c_string, length)) in enumerate(zip(py_strings, c_strings)):
... assert py_string == c_string, "%d: %r != %r" % (i, py_string, c_string)
... assert len(py_string) == length, (
... "%d: wrong length of %r, got %d, expected %d" % (
... i, py_string, len(py_string), length))
... assert len(c_string) == length, (
... "%d: wrong length of %r, got %d, expected %d" % (
... i, c_string, len(c_string), length))
"""
import sys
if sys.version_info[0] < 3:
__doc__ = __doc__.replace(u" b'", u" '").replace(u' b"', u' "')
else:
__doc__ = __doc__.replace(u" u'", u" '").replace(u' u"', u' "')
c_strings = [
(b'\x1234', 3),
(b'\x0A12\x0C34', 6),
(b'\x0A57', 3),
(b'\x0A', 1),
(b'\'', 1),
(b"\'", 1),
(b"\"", 1),
(b'\"', 1),
(b'abc\x12def', 7),
(u'\u1234', 1),
(u'\U00001234', 1),
(b'\u1234', 6),
(b'\U00001234', 10),
(b'\n\r\t', 3),
(b':>', 2),
(b'??>', 3),
(b'\0\0\0', 3),
]
...@@ -12,12 +12,12 @@ exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> ...@@ -12,12 +12,12 @@ exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
>>> with_exception(None) >>> with_exception(None)
enter enter
value value
exit <type 'type'> <class 'withstat.MyException'> <type 'traceback'> exit <type 'type'> <type 'MyException'> <type 'traceback'>
outer except outer except
>>> with_exception(True) >>> with_exception(True)
enter enter
value value
exit <type 'type'> <class 'withstat.MyException'> <type 'traceback'> exit <type 'type'> <type 'MyException'> <type 'traceback'>
>>> multitarget() >>> multitarget()
enter enter
1 2 3 4 5 1 2 3 4 5
...@@ -32,20 +32,23 @@ enter ...@@ -32,20 +32,23 @@ enter
exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'> exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
""" """
def typename(t):
return u"<type '%s'>" % type(t).__name__
class MyException(Exception): class MyException(Exception):
pass pass
class ContextManager: class ContextManager(object):
def __init__(self, value, exit_ret = None): def __init__(self, value, exit_ret = None):
self.value = value self.value = value
self.exit_ret = exit_ret self.exit_ret = exit_ret
def __exit__(self, a, b, tb): def __exit__(self, a, b, tb):
print "exit", type(a), type(b), type(tb) print u"exit", typename(a), typename(b), typename(tb)
return self.exit_ret return self.exit_ret
def __enter__(self): def __enter__(self):
print "enter" print u"enter"
return self.value return self.value
def no_as(): def no_as():
......
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