Commit 82acc1f8 authored by Robert Bradshaw's avatar Robert Bradshaw

merge dag and devel branches

parents a19e36ee 2fbc1d54
......@@ -7,7 +7,12 @@ from Cython.Utils import EncodedString
from Cython.Compiler.Errors import CompileError
import Interpreter
import PyrexTypes
from sets import Set as set
try:
set
except NameError:
from sets import Set as set
import textwrap
# Code cleanup ideas:
......
......@@ -12,7 +12,7 @@ Cython language. Cython is based on Pyrex by Greg Ewing.
Usage: cython [options] sourcefile.pyx ...
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
-I, --include-dir <directory> Search for include files in named directory
(multiply include directories are allowed).
......@@ -21,6 +21,7 @@ Options:
-t, --timestamps Only compile newer source files (implied with -r)
-f, --force Compile all source files (overrides implied -t)
-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
function definition is embedded in its docstring.
-z, --pre-import <module> If specified, assume undeclared names in this
......@@ -34,7 +35,7 @@ Options:
are searched from)
-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.
--cplus Output a c++ rather than c file.
-O, --option <name>=<value>[,<name=value,...] Overrides an optimization/code generation option
......@@ -72,7 +73,7 @@ def parse_command_line(args):
while args:
if args[0].startswith("-"):
option = pop_arg()
if option in ("-v", "--version"):
if option in ("-V", "--version"):
options.show_version = 1
elif option in ("-l", "--create-listing"):
options.use_listing_file = 1
......@@ -97,6 +98,8 @@ def parse_command_line(args):
options.timestamps = 1
elif option in ("-f", "--force"):
options.timestamps = 0
elif option in ("-v", "--verbose"):
options.verbose += 1
elif option in ("-p", "--embed-positions"):
Options.embed_pos_in_docstring = 1
elif option in ("-z", "--pre-import"):
......
......@@ -10,7 +10,10 @@ from PyrexTypes import py_object_type, typecast
from TypeSlots import method_coexist
from Scanning import SourceDescriptor
from Cython.StringIOTree import StringIOTree
from sets import Set as set
try:
set
except NameError:
from sets import Set as set
class FunctionState(object):
# return_label string function return point label
......@@ -515,11 +518,18 @@ class CCodeWriter(object):
self.marker = None
return self
def put_safe(self, code):
# put code, but ignore {}
self.write(code)
self.bol = 0
def put(self, code):
fix_indent = False
dl = code.count("{") - code.count("}")
if dl < 0:
self.level += dl
elif dl == 0 and code.startswith('}'):
fix_indent = True
self.level -= 1
if self.bol:
self.indent()
......@@ -527,7 +537,7 @@ class CCodeWriter(object):
self.bol = 0
if dl > 0:
self.level += dl
elif dl == 0 and code.startswith('}'):
elif fix_indent:
self.level += 1
return self
......@@ -616,7 +626,7 @@ class CCodeWriter(object):
self.put(entry.type.declaration_code(entry.cname,
dll_linkage = dll_linkage))
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(";")
def put_temp_declarations(self, func_context):
......
......@@ -14,6 +14,7 @@ from Builtin import list_type, tuple_type, dict_type
import Symtab
import Options
from Annotate import AnnotationItem
from Cython import Utils
from Cython.Debugging import print_call_chain
from DebugFlags import debug_disposal_code, debug_temp_alloc, \
......@@ -639,10 +640,10 @@ class CharNode(ConstNode):
type = PyrexTypes.c_char_type
def compile_time_value(self, denv):
return ord(self.value)
return ord(self.value.byteencode())
def calculate_result_code(self):
return "'%s'" % self.value
return "'%s'" % Utils.escape_character(self.value.byteencode())
class IntNode(ConstNode):
......@@ -737,6 +738,29 @@ class StringNode(ConstNode):
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.
class IdentifierStringNode(ConstNode):
# A Python string that behaves like an identifier, e.g. for
# keyword arguments in a call, or for imported names
......@@ -870,8 +894,6 @@ class NameNode(AtomicExprNode):
env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
if self.entry.is_declared_generic:
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):
if self.entry is None:
......@@ -1025,7 +1047,7 @@ class NameNode(AtomicExprNode):
self.interned_cname,
rhs.py_result()))
# 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)
else:
code.put_error_if_neg(self.pos,
......@@ -4433,43 +4455,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
# sure the index doesn't become negative.
......
......@@ -64,7 +64,8 @@ def make_lexicon():
two_hex = hexdigit + hexdigit
four_hex = two_hex + two_hex
escapeseq = Str("\\") + (two_oct | three_oct | two_hex |
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("@")
......
......@@ -189,7 +189,9 @@ class Context:
scope = None
pxd_pathname = None
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)
if "." not in module_name and relative_to:
if debug_find_module:
......@@ -477,13 +479,6 @@ def create_default_resultobj(compilation_source, options):
else:
c_suffix = ".c"
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
def run_pipeline(source, options, full_module_name = None):
......@@ -615,8 +610,6 @@ def compile_single(source, options, full_module_name = None):
recursion.
"""
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):
......@@ -636,15 +629,15 @@ def compile_multiple(sources, options):
timestamps = recursive
verbose = options.verbose or ((recursive or timestamps) and not options.quiet)
for source in sources:
context = Context(options.include_path) # to be removed later
if source not in processed:
# Compiling multiple sources in one context doesn't quite
# work properly yet.
context = Context(options.include_path) # to be removed later
if not timestamps or context.c_file_out_of_date(source):
if verbose:
sys.stderr.write("Compiling %s\n" % source)
result = context.compile(source, options)
# Compiling multiple sources in one context doesn't quite
# work properly yet.
result = run_pipeline(source, options)
results.add(source, result)
processed.add(source)
if recursive:
......@@ -674,10 +667,7 @@ def compile(source, options = None, c_compile = 0, c_link = 0,
and not options.recursive:
return compile_single(source, options, full_module_name)
else:
# Hack it for wednesday dev1
assert len(source) == 1
return compile_single(source[0], options)
# return compile_multiple(source, options)
return compile_multiple(source, options)
#------------------------------------------------------------------------
#
......
......@@ -23,7 +23,7 @@ import Version
from Errors import error, warning
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
def check_c_classes(module_node):
......@@ -423,6 +423,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #define Py_SIZE(ob) ((PyVarObject*)(ob))->ob_size)")
code.putln(" #define PyVarObject_HEAD_INIT(type, size) \\")
code.putln(" PyObject_HEAD_INIT(type) size,")
code.putln(" #define PyType_Modified(t)")
code.putln("")
code.putln(" typedef struct {")
code.putln(" void *buf;")
......@@ -513,7 +514,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static const char **%s;' % Naming.filetable_cname)
if env.doc:
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):
name = Naming.extern_c_macro
......
......@@ -12,7 +12,8 @@ import TypeSlots
from PyrexTypes import py_object_type, error_type, CTypedefType, CFuncType
from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
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 ControlFlow
......@@ -762,7 +763,7 @@ class CEnumDefItemNode(StatNode):
else:
value = self.name
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)
......@@ -945,6 +946,8 @@ class FuncDefNode(StatNode, BlockNode):
if err_val is not None or exc_check:
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
else:
warning(self.entry.pos, "Unraisable exception in function '%s'." \
% self.entry.qualified_name, 0)
code.putln(
'__Pyx_WriteUnraisable("%s");' %
self.entry.qualified_name)
......@@ -1516,7 +1519,7 @@ class DefNode(FuncDefNode):
code.putln(
'static char %s[] = "%s";' % (
self.entry.doc_cname,
self.entry.doc))
escape_byte_string(self.entry.doc.utf8encode())))
if with_pymethdef:
code.put(
"static PyMethodDef %s = " %
......@@ -4281,11 +4284,12 @@ static int __Pyx_CheckKeywordStrings(
}
if (unlikely(!kw_allowed) && unlikely(key)) {
PyErr_Format(PyExc_TypeError,
"'%s' is an invalid keyword argument for this function",
#if PY_MAJOR_VERSION < 3
"'%s' is an invalid keyword argument for this function",
PyString_AsString(key));
#else
PyUnicode_AsString(key));
"'%U' is an invalid keyword argument for this function",
key);
#endif
return 0;
}
......@@ -4456,9 +4460,9 @@ static void __Pyx_AddTraceback(const char *funcname) {
if (!py_srcfile) goto bad;
if (%(CLINENO)s) {
#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
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
}
else {
......
......@@ -22,7 +22,7 @@ class SwitchTransform(Visitor.VisitorTransform):
"""
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
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):
......@@ -66,6 +66,8 @@ class SwitchTransform(Visitor.VisitorTransform):
return node
elif common_var is not None and not is_common_value(var, common_var):
return node
elif not var.type.is_int or sum([not cond.type.is_int for cond in conditions]):
return node
else:
common_var = var
cases.append(Nodes.SwitchCaseNode(pos = if_clause.pos,
......
......@@ -5,7 +5,10 @@ from Cython.Compiler.ExprNodes import *
from Cython.Compiler.TreeFragment import TreeFragment
from Cython.Utils import EncodedString
from Cython.Compiler.Errors import CompileError
from sets import Set as set
try:
set
except NameError:
from sets import Set as set
import copy
class NormalizeTree(CythonTransform):
......
......@@ -2,7 +2,9 @@
# Pyrex Parser
#
import os, re
import os
import re
import sys
from types import ListType, TupleType
from Scanning import PyrexScanner, FileSourceDescriptor
import Nodes
......@@ -491,6 +493,8 @@ def p_atom(s):
kind, value = p_cat_string_literal(s)
if kind == 'c':
return ExprNodes.CharNode(pos, value = value)
elif kind == 'u':
return ExprNodes.UnicodeNode(pos, value = value)
else:
return ExprNodes.StringNode(pos, value = value)
elif sy == 'IDENT':
......@@ -584,43 +588,43 @@ def p_string_literal(s):
sy = s.sy
#print "p_string_literal: sy =", sy, repr(s.systring) ###
if sy == 'CHARS':
systr = s.systring
if len(systr) == 1 and systr in "'\"\n":
chars.append('\\')
chars.append(systr)
chars.append(s.systring)
elif sy == 'ESCAPE':
systr = s.systring
if is_raw:
if systr == '\\\n':
chars.append(r'\\\n')
elif systr == r'\"':
chars.append(r'\\\"')
elif systr == r'\\':
chars.append(r'\\\\')
chars.append('\\\n')
elif systr == '\\\"':
chars.append('"')
elif systr == '\\\'':
chars.append("'")
else:
chars.append('\\' + systr)
chars.append(systr)
else:
c = systr[1]
if c in "'\"\\abfnrtv01234567":
chars.append(systr)
if c in "01234567":
chars.append(chr(int(systr[1:])))
elif c in "'\"\\":
chars.append(c)
elif c in "abfnrtv":
chars.append(Utils.char_from_escape_sequence(systr))
elif c == '\n':
pass
elif c in 'ux':
if kind == 'u':
try:
chars.append(
systr.encode("ASCII").decode('unicode_escape'))
except UnicodeDecodeError:
elif c in 'Uux':
if kind == 'u' or c == 'x':
chrval = int(systr[2:], 16)
if chrval > 1114111: # sys.maxunicode:
s.error("Invalid unicode escape '%s'" % systr,
pos = pos)
elif c == 'x':
chars.append('\\x0' + systr[2:])
strval = unichr(chrval)
else:
chars.append(systr)
# unicode escapes in plain byte strings are not unescaped
strval = systr
chars.append(strval)
else:
chars.append(r'\\' + systr[1:])
elif sy == 'NEWLINE':
chars.append(r'\n')
chars.append('\n')
elif sy == 'END_STRING':
break
elif sy == 'EOF':
......@@ -629,8 +633,11 @@ def p_string_literal(s):
s.error(
"Unexpected token %r:%r in string literal" %
(sy, s.systring))
string = u''.join(chars)
if kind == 'c' and len(string) != 1:
error(pos, u"invalid character literal: %r" % string)
s.next()
value = Utils.EncodedString( u''.join(chars) )
value = Utils.EncodedString(string)
if kind != 'u':
value.encoding = s.source_encoding
#print "p_string_literal: value =", repr(value) ###
......@@ -1630,7 +1637,7 @@ def p_buffer_access(s, base_type_node):
# s.sy == '['
pos = s.position()
s.next()
if s.sy == ']':
if s.sy == ']' or s.sy == 'INT':
# not buffer, could be [] on C type nameless array arguments
s.put_back('[', '[')
return base_type_node
......
......@@ -292,6 +292,13 @@ class BuiltinObjectType(PyObjectType):
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)
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):
#
......@@ -996,20 +1003,6 @@ class CStringType:
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):
# C 'char []' type.
......@@ -1018,16 +1011,6 @@ class CCharArrayType(CStringType, CArrayType):
def __init__(self, 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):
......@@ -1040,6 +1023,29 @@ class CCharPtrType(CStringType, CPtrType):
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):
# Used to prevent propagation of error messages.
......@@ -1105,7 +1111,7 @@ c_longdouble_type = CFloatType(8, typestring="g")
c_null_ptr_type = CNullPtrType(c_void_type)
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_ptr_type = CPtrType(c_char_ptr_type)
c_py_ssize_t_ptr_type = CPtrType(c_py_ssize_t_type)
......
......@@ -38,7 +38,10 @@ def hash_source_file(path):
# Try to calculate a hash code for the given source file.
# Returns an empty string if the file cannot be accessed.
#print "Hashing", path ###
import md5
try:
from hashlib import md5 as new_md5
except ImportError:
from md5 import new as new_md5
try:
try:
f = open(path, "rU")
......@@ -54,7 +57,7 @@ def hash_source_file(path):
# tabs by a single space.
import re
text = re.sub("[ \t]+", " ", text)
hash = md5.new(text).hexdigest()
hash = new_md5(text).hexdigest()
return hash
def open_pickled_lexicon(expected_hash):
......
......@@ -15,7 +15,10 @@ from TypeSlots import \
get_special_method_signature, get_property_accessor_signature
import ControlFlow
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
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
......@@ -287,14 +290,14 @@ class Scope:
def qualify_name(self, 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.
if not cname:
if self.in_cinclude:
cname = name
else:
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.value = value
return entry
......@@ -502,7 +505,7 @@ class Scope:
else:
cname = self.new_const_cname()
if value.is_unicode:
c_type = PyrexTypes.c_utf8_char_array_type
c_type = PyrexTypes.c_unicode_type
value = value.utf8encode()
else:
c_type = PyrexTypes.c_char_array_type
......
......@@ -26,10 +26,6 @@ class TestBufferParsing(CythonTest):
# print bufnode.dump()
# should put more here...
def test_type_fail(self):
self.not_parseable("Expected: type",
u"cdef object[2] x")
def test_type_pos(self):
self.parse(u"cdef object[short unsigned int, 3] x")
......
......@@ -70,40 +70,21 @@ EXAMPLE:
>>> b = a.insertion_point()
>>> a.write('third\n')
>>> b.write('second\n')
>>> print a.getvalue()
first
second
third
<BLANKLINE>
>>> a.getvalue().split()
['first', 'second', 'third']
>>> c = b.insertion_point()
>>> d = c.insertion_point()
>>> d.write('alpha\n')
>>> b.write('gamma\n')
>>> c.write('beta\n')
>>> print b.getvalue()
second
alpha
beta
gamma
<BLANKLINE>
>>> b.getvalue().split()
['second', 'alpha', 'beta', 'gamma']
>>> i = StringIOTree()
>>> d.insert(i)
>>> i.write('inserted\n')
>>> out = StringIO()
>>> a.copyto(out)
>>> print out.getvalue()
first
second
alpha
inserted
beta
gamma
third
<BLANKLINE>
"""
if __name__ == "__main__":
import doctest
doctest.testmod()
>>> out.getvalue().split()
['first', 'second', 'alpha', 'inserted', 'beta', 'gamma', 'third']
"""
\ No newline at end of file
......@@ -99,8 +99,53 @@ class EncodedString(unicode):
# return unicode.__eq__(self, other) and \
# 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):
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:
s.decode("ASCII")
return s
......@@ -111,7 +156,7 @@ def escape_byte_string(s):
for c in s:
o = ord(c)
if o >= 128:
append('\\x%X' % o)
append('\\%3o' % o)
else:
append(c)
return ''.join(l)
......
......@@ -259,6 +259,7 @@ class CythonRunTestCase(CythonCompileTestCase):
result.startTest(self)
try:
self.runCompileTest()
sys.stderr.write('running doctests in %s ...\n' % self.module)
doctest.DocTestSuite(self.module).run(result)
except Exception:
result.addError(self, sys.exc_info())
......@@ -270,7 +271,7 @@ class CythonRunTestCase(CythonCompileTestCase):
class CythonUnitTestCase(CythonCompileTestCase):
def shortDescription(self):
return "compiling and running unit tests in " + self.module
return "compiling tests in " + self.module
def run(self, result=None):
if result is None:
......@@ -278,6 +279,7 @@ class CythonUnitTestCase(CythonCompileTestCase):
result.startTest(self)
try:
self.runCompileTest()
sys.stderr.write('running tests in %s ...\n' % self.module)
unittest.defaultTestLoader.loadTestsFromName(self.module).run(result)
except Exception:
result.addError(self, sys.exc_info())
......@@ -371,6 +373,9 @@ if __name__ == '__main__':
parser.add_option("--no-pyregr", dest="pyregr",
action="store_false", default=True,
help="do not run the regression tests of CPython in tests/pyregr/")
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",
action="store_true", default=False,
help="collect source coverage data for the Compiler")
......@@ -383,6 +388,13 @@ if __name__ == '__main__':
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:
import coverage
coverage.erase()
......@@ -411,11 +423,11 @@ if __name__ == '__main__':
if WITH_CYTHON:
from Cython.Compiler.Version import version
print("Running tests against Cython %s" % version)
sys.stderr.write("Running tests against Cython %s\n" % version)
else:
print("Running tests without Cython.")
print("Python %s" % sys.version)
print("")
sys.stderr.write("Running tests without Cython.\n")
sys.stderr.write("Python %s\n" % sys.version)
sys.stderr.write("\n")
import re
selectors = [ re.compile(r, re.I|re.U).search for r in cmd_args ]
......@@ -434,7 +446,16 @@ if __name__ == '__main__':
filetests = TestBuilder(ROOTDIR, WORKDIR, selectors,
options.annotate_source, options.cleanup_workdir,
options.cleanup_sharedlibs, options.pyregr)
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)
......
......@@ -11,3 +11,9 @@ cdef extern from *:
ctypedef MyStruct* MyStructP
cdef void baz(MyStructP[])
cdef struct OtherStruct:
int a
a = sizeof(int[23][34])
b = sizeof(OtherStruct[43])
__doc__ = u"""
>>> test_c(u'abc')
>>> test_c('abc')
fileabc
typeabc
>>> print test_file_py(u'abc')
>>> print(test_file_py('abc'))
abc
>>> print range(u'abc')
>>> print(range('abc'))
rangeabc
"""
def test_file_py(file):
assert isinstance(file, (str, unicode)), \
u"not a string, found '%s' instead" % file.__class__.__name__
return 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
......
__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'
>>> 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'>
>>> with_exception(None)
enter
value
exit <type 'type'> <class 'withstat.MyException'> <type 'traceback'>
exit <type 'type'> <type 'MyException'> <type 'traceback'>
outer except
>>> with_exception(True)
enter
value
exit <type 'type'> <class 'withstat.MyException'> <type 'traceback'>
exit <type 'type'> <type 'MyException'> <type 'traceback'>
>>> multitarget()
enter
1 2 3 4 5
......@@ -32,20 +32,23 @@ enter
exit <type 'NoneType'> <type 'NoneType'> <type 'NoneType'>
"""
def typename(t):
return u"<type '%s'>" % type(t).__name__
class MyException(Exception):
pass
class ContextManager:
class ContextManager(object):
def __init__(self, value, exit_ret = None):
self.value = value
self.exit_ret = exit_ret
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
def __enter__(self):
print "enter"
print u"enter"
return self.value
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