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 ...@@ -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):
...@@ -737,6 +738,29 @@ class StringNode(ConstNode): ...@@ -737,6 +738,29 @@ 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.
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 +894,6 @@ class NameNode(AtomicExprNode): ...@@ -870,8 +894,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 +1047,7 @@ class NameNode(AtomicExprNode): ...@@ -1025,7 +1047,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,
...@@ -4433,43 +4455,6 @@ static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) { ...@@ -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 # 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.
......
...@@ -64,7 +64,8 @@ def make_lexicon(): ...@@ -64,7 +64,8 @@ def make_lexicon():
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 | 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("@") 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,15 @@ def compile_multiple(sources, options): ...@@ -636,15 +629,15 @@ 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.
context = Context(options.include_path) # to be removed later
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 +667,7 @@ def compile(source, options = None, c_compile = 0, c_link = 0, ...@@ -674,10 +667,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
def check_c_classes(module_node): def check_c_classes(module_node):
...@@ -423,6 +423,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -423,6 +423,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 +514,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -513,7 +514,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):
......
...@@ -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:])))
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(r'\\' + 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
......
...@@ -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")
......
...@@ -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)
......
...@@ -259,6 +259,7 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -259,6 +259,7 @@ class CythonRunTestCase(CythonCompileTestCase):
result.startTest(self) result.startTest(self)
try: try:
self.runCompileTest() self.runCompileTest()
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())
...@@ -270,7 +271,7 @@ class CythonRunTestCase(CythonCompileTestCase): ...@@ -270,7 +271,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:
...@@ -278,6 +279,7 @@ class CythonUnitTestCase(CythonCompileTestCase): ...@@ -278,6 +279,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())
...@@ -371,6 +373,9 @@ if __name__ == '__main__': ...@@ -371,6 +373,9 @@ if __name__ == '__main__':
parser.add_option("--no-pyregr", dest="pyregr", parser.add_option("--no-pyregr", dest="pyregr",
action="store_false", default=True, action="store_false", default=True,
help="do not run the regression tests of CPython in tests/pyregr/") 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", 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")
...@@ -383,6 +388,13 @@ if __name__ == '__main__': ...@@ -383,6 +388,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()
...@@ -411,11 +423,11 @@ if __name__ == '__main__': ...@@ -411,11 +423,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 ]
...@@ -434,7 +446,16 @@ if __name__ == '__main__': ...@@ -434,7 +446,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.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) 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])
__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
......
__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'> ...@@ -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