Commit 86d1bd4a authored by Vitja Makarov's avatar Vitja Makarov

Merge remote branch 'upstream/master'

Conflicts:
	Cython/Compiler/Nodes.py
parents bb8cd827 9f2c79e1
......@@ -151,7 +151,7 @@ def cython_inline(code,
if m.groups()[0] == 'numpy':
import numpy
c_include_dirs.append(numpy.get_include())
cflags.append('-Wno-unused')
# cflags.append('-Wno-unused')
module_body, func_body = extract_func_code(code)
params = ', '.join(['%s %s' % a for a in arg_sigs])
module_code = """
......
......@@ -366,7 +366,7 @@ builtin_function_table = [
BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr",
utility_code = getattr3_utility_code), # Pyrex compatibility
BuiltinFunction('hasattr', "OO", "b", "PyObject_HasAttr"),
BuiltinFunction('hash', "O", "l", "PyObject_Hash"),
BuiltinFunction('hash', "O", "h", "PyObject_Hash"),
#('hex', "", "", ""),
#('id', "", "", ""),
#('input', "", "", ""),
......@@ -503,6 +503,7 @@ builtin_structs_table = [
("shape", PyrexTypes.c_py_ssize_t_ptr_type),
("strides", PyrexTypes.c_py_ssize_t_ptr_type),
("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)),
("internal", PyrexTypes.c_void_ptr_type),
]),
('Py_complex', 'Py_complex',
......
......@@ -2073,14 +2073,17 @@ class IndexNode(ExprNode):
if index_type and index_type.is_int or isinstance(self.index, (IntNode, LongNode)):
# indexing!
if base_type is unicode_type:
# Py_UNICODE will automatically coerce to a unicode string
# if required, so this is safe. We only infer Py_UNICODE
# Py_UCS4 will automatically coerce to a unicode string
# if required, so this is safe. We only infer Py_UCS4
# when the index is a C integer type. Otherwise, we may
# need to use normal Python item access, in which case
# it's faster to return the one-char unicode string than
# to receive it, throw it away, and potentially rebuild it
# on a subsequent PyObject coercion.
return PyrexTypes.c_py_unicode_type
return PyrexTypes.c_py_ucs4_type
elif base_type is str_type:
# always returns str - Py2: bytes, Py3: unicode
return base_type
elif isinstance(self.base, BytesNode):
#if env.global_scope().context.language_level >= 3:
# # infering 'char' can be made to work in Python 3 mode
......@@ -2091,8 +2094,8 @@ class IndexNode(ExprNode):
return base_type.base_type
# may be slicing or indexing, we don't know
if base_type is unicode_type:
# this type always returns its own type on Python indexing/slicing
if base_type in (unicode_type, str_type):
# these types always returns their own type on Python indexing/slicing
return base_type
else:
# TODO: Handle buffers (hopefully without too much redundancy).
......@@ -2200,7 +2203,7 @@ class IndexNode(ExprNode):
if self.index.type.is_int and base_type is unicode_type:
# Py_UNICODE/Py_UCS4 will automatically coerce to a unicode string
# if required, so this is fast and safe
self.type = PyrexTypes.c_py_unicode_type
self.type = PyrexTypes.c_py_ucs4_type
elif is_slice and base_type in (bytes_type, str_type, unicode_type, list_type, tuple_type):
self.type = base_type
else:
......@@ -6721,11 +6724,43 @@ static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE cha
""",
impl="""
static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE character) {
Py_UNICODE* pos;
const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
for (pos=char_start; pos < char_start+length; pos++) {
if (unlikely(character == pos[0])) return 1;
}
return 0;
}
""")
py_ucs4_in_unicode_utility_code = UtilityCode(
proto="""
static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character); /*proto*/
""",
# additionally handles surrogate pairs in 16bit Unicode builds
impl="""
static CYTHON_INLINE int __Pyx_UnicodeContainsUCS4(PyObject* unicode, Py_UCS4 character) {
Py_UNICODE* pos;
Py_UNICODE uchar;
const Py_ssize_t length = PyUnicode_GET_SIZE(unicode);
Py_UNICODE* char_start = PyUnicode_AS_UNICODE(unicode);
#if Py_UNICODE_SIZE == 2
if (unlikely(character > 65535)) {
Py_UNICODE high_val, low_val;
high_val = (Py_UNICODE) (0xD800 | (((character - 0x10000) >> 10) & ((1<<10)-1)));
low_val = (Py_UNICODE) (0xDC00 | ( (character - 0x10000) & ((1<<10)-1)));
for (pos=char_start; pos < char_start+length-1; pos++) {
if (unlikely(high_val == pos[0]) & unlikely(low_val == pos[1])) return 1;
}
return 0;
}
#endif
uchar = (Py_UNICODE) character;
for (pos=char_start; pos < char_start+length; pos++) {
if (character == pos[0]) return 1;
if (unlikely(uchar == pos[0])) return 1;
}
return 0;
}
......@@ -6823,7 +6858,12 @@ class PrimaryCmpNode(ExprNode, CmpNode):
error(self.pos, "Cascading comparison not yet supported for 'int_val in string'.")
return
if self.operand2.type is unicode_type:
self.uchar_test_type = PyrexTypes.widest_numeric_type(
self.operand1.type, PyrexTypes.c_py_unicode_type)
if self.uchar_test_type is PyrexTypes.c_py_unicode_type:
env.use_utility_code(pyunicode_in_unicode_utility_code)
else:
env.use_utility_code(py_ucs4_in_unicode_utility_code)
else:
if self.operand1.type is PyrexTypes.c_uchar_type:
self.operand1 = self.operand1.coerce_to(PyrexTypes.c_char_type, env)
......@@ -6913,10 +6953,13 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand1.result(),
self.operand2.result())
elif self.is_c_string_contains():
if self.operand2.type is bytes_type:
method = "__Pyx_BytesContains"
else:
if self.operand2.type is unicode_type:
if self.uchar_test_type is PyrexTypes.c_py_unicode_type:
method = "__Pyx_UnicodeContains"
else:
method = "__Pyx_UnicodeContainsUCS4"
else:
method = "__Pyx_BytesContains"
if self.operator == "not_in":
negation = "!"
else:
......
......@@ -610,6 +610,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#define PyBoolObject PyLongObject
#endif
#if PY_VERSION_HEX < 0x03020000
typedef long Py_hash_t;
#define __Pyx_PyInt_FromHash_t PyInt_FromLong
#define __Pyx_PyInt_AsHash_t PyInt_AsLong
#else
#define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
#define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t
#endif
""")
code.put("""
......
......@@ -2654,7 +2654,7 @@ class DefNode(FuncDefNode):
max_positional_args, Naming.args_cname))
code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
if self.starstar_arg:
code.put_decref(self.starstar_arg.entry.cname, py_object_type)
code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
if self.needs_closure:
code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type)
code.put_finish_refcount_context()
......@@ -5308,7 +5308,7 @@ class GILStatNode(TryFinallyStatNode):
code.putln("#endif")
else:
code.putln("#ifdef WITH_THREAD")
code.putln("PyThreadState *_save;")
code.putln("PyThreadState *_save = NULL;")
code.putln("#endif")
code.putln("Py_UNBLOCK_THREADS")
TryFinallyStatNode.generate_execution_code(self, code)
......
......@@ -2184,7 +2184,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
PyUnicode_uchar_predicate_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_bint_type, [
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_unicode_type, None),
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None),
])
def _inject_unicode_predicate(self, node, args, is_unbound_method):
......@@ -2222,8 +2222,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
_handle_simple_method_unicode_isupper = _inject_unicode_predicate
PyUnicode_uchar_conversion_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_py_unicode_type, [
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_unicode_type, None),
PyrexTypes.c_py_ucs4_type, [
PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None),
])
def _inject_unicode_character_conversion(self, node, args, is_unbound_method):
......@@ -2703,10 +2703,18 @@ py_unicode_istitle_utility_code = UtilityCode(
# Py_UNICODE_ISTITLE() doesn't match unicode.istitle() as the latter
# additionally allows character that comply with Py_UNICODE_ISUPPER()
proto = '''
#if PY_VERSION_HEX < 0x030200A2
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar); /* proto */
#else
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UCS4 uchar); /* proto */
#endif
''',
impl = '''
#if PY_VERSION_HEX < 0x030200A2
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UNICODE uchar) {
#else
static CYTHON_INLINE int __Pyx_Py_UNICODE_ISTITLE(Py_UCS4 uchar) {
#endif
return Py_UNICODE_ISTITLE(uchar) || Py_UNICODE_ISUPPER(uchar);
}
''')
......
......@@ -965,7 +965,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
if (high_val >= 0xD800 && high_val <= 0xDBFF) {
Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1];
if (low_val >= 0xDC00 && low_val <= 0xDFFF) {
return 0x10000 | ((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1));
return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)));
}
}
}
......@@ -1056,6 +1056,14 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
''')
class CPyHashTType(CIntType):
to_py_function = "__Pyx_PyInt_FromHash_t"
from_py_function = "__Pyx_PyInt_AsHash_t"
def sign_and_name(self):
return "Py_hash_t"
class CPySSizeTType(CIntType):
to_py_function = "PyInt_FromSsize_t"
......@@ -1522,7 +1530,7 @@ class CArrayType(CType):
def __init__(self, base_type, size):
self.base_type = base_type
self.size = size
if base_type is c_char_type:
if base_type in (c_char_type, c_uchar_type, c_schar_type):
self.is_string = 1
def __repr__(self):
......@@ -2381,6 +2389,7 @@ c_returncode_type = CReturnCodeType(RANK_INT)
c_bint_type = CBIntType(RANK_INT)
c_py_unicode_type = CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED)
c_py_ucs4_type = CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
c_py_hash_t_type = CPyHashTType(RANK_LONG+0.5, SIGNED)
c_py_ssize_t_type = CPySSizeTType(RANK_LONG+0.5, SIGNED)
c_ssize_t_type = CSSizeTType(RANK_LONG+0.5, SIGNED)
c_size_t_type = CSizeTType(RANK_LONG+0.5, UNSIGNED)
......@@ -2443,6 +2452,7 @@ modifiers_and_name_to_type = {
(1, 0, "bint"): c_bint_type,
(0, 0, "Py_UNICODE"): c_py_unicode_type,
(0, 0, "Py_UCS4"): c_py_ucs4_type,
(2, 0, "Py_hash_t"): c_py_hash_t_type,
(2, 0, "Py_ssize_t"): c_py_ssize_t_type,
(2, 0, "ssize_t") : c_ssize_t_type,
(0, 0, "size_t") : c_size_t_type,
......@@ -2692,6 +2702,8 @@ def parse_basic_type(name):
signed = 0
elif name == 'Py_UCS4':
signed = 0
elif name == 'Py_hash_t':
signed = 2
elif name == 'Py_ssize_t':
signed = 2
elif name == 'ssize_t':
......
......@@ -32,6 +32,7 @@ class Signature(object):
# 'b' bint
# 'I' int *
# 'l' long
# 'h' Py_hash_t
# 'z' Py_ssize_t
# 'Z' Py_ssize_t *
# 's' char *
......@@ -52,6 +53,7 @@ class Signature(object):
'b': PyrexTypes.c_bint_type,
'I': PyrexTypes.c_int_ptr_type,
'l': PyrexTypes.c_long_type,
'h': PyrexTypes.c_py_hash_t_type,
'z': PyrexTypes.c_py_ssize_t_type,
'Z': PyrexTypes.c_py_ssize_t_ptr_type,
's': PyrexTypes.c_char_ptr_type,
......@@ -69,6 +71,7 @@ class Signature(object):
'b': "-1",
'l': "-1",
'r': "-1",
'h': "-1",
'z': "-1",
}
......@@ -534,7 +537,7 @@ setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObjec
delattrofunc = Signature("TO", 'r')
cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *);
reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *);
hashfunc = Signature("T", "l") # typedef long (*hashfunc)(PyObject *);
hashfunc = Signature("T", "h") # typedef Py_hash_t (*hashfunc)(PyObject *);
# typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
richcmpfunc = Signature("OOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *);
......
from __future__ import with_statement
import os
import re
import sys
import uuid
import shutil
import warnings
import textwrap
import unittest
import tempfile
import subprocess
import distutils.core
from distutils import sysconfig
#import distutils.core
#from distutils import sysconfig
from distutils import ccompiler
import runtests
......@@ -22,8 +20,12 @@ from Cython.Debugger import Cygdb as cygdb
root = os.path.dirname(os.path.abspath(__file__))
codefile = os.path.join(root, 'codefile')
cfuncs_file = os.path.join(root, 'cfuncs.c')
with open(codefile) as f:
source_to_lineno = dict((line.strip(), i + 1) for i, line in enumerate(f))
f = open(codefile)
try:
source_to_lineno = dict([ (line.strip(), i + 1) for i, line in enumerate(f) ])
finally:
f.close()
# Cython.Distutils.__init__ imports build_ext from build_ext which means we
# can't access the module anymore. Get it from sys.modules instead.
......@@ -205,8 +207,11 @@ class GdbDebuggerTestCase(DebuggerTestCase):
self.gdb_command_file = cygdb.make_command_file(self.tempdir,
prefix_code)
with open(self.gdb_command_file, 'a') as f:
f = open(self.gdb_command_file, 'a')
try:
f.write(code)
finally:
f.close()
args = ['gdb', '-batch', '-x', self.gdb_command_file, '-n', '--args',
sys.executable, '-c', 'import codefile']
......
__version__ = "0.14.1rc3"
__version__ = "0.14.1+"
# Void cython.* directives (for case insensitive operating systems).
from Cython.Shadow import *
......@@ -6,6 +6,7 @@ import re
import gc
import codecs
import shutil
import time
import unittest
import doctest
import operator
......@@ -97,7 +98,7 @@ KEEP_2X_FILES = [
os.path.join('Cython', 'Debugger', 'libpython.py'),
]
COMPILER = None
INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]
CFLAGS = os.getenv('CFLAGS', '').split()
......@@ -177,7 +178,8 @@ class TestBuilder(object):
self.handle_directory(path, filename))
if sys.platform not in ['win32'] and sys.version_info[0] < 3:
# Non-Windows makefile, can't run Cython under Py3.
if [1 for selector in self.selectors if selector("embedded")]:
if [1 for selector in self.selectors if selector("embedded")] \
and not [1 for selector in self.exclude_selectors if selector("embedded")]:
suite.addTest(unittest.makeSuite(EmbedTest))
return suite
......@@ -194,7 +196,10 @@ class TestBuilder(object):
if context == "build" and filename.endswith(".srctree"):
if not [ 1 for match in self.selectors if match(filename) ]:
continue
suite.addTest(EndToEndTest(filename, workdir, self.cleanup_workdir))
if self.exclude_selectors:
if [1 for match in self.exclude_selectors if match(filename)]:
continue
suite.addTest(EndToEndTest(os.path.join(path, filename), workdir, self.cleanup_workdir))
continue
if not (filename.endswith(".pyx") or filename.endswith(".py")):
continue
......@@ -409,20 +414,24 @@ class CythonCompileTestCase(unittest.TestCase):
if incdir:
build_extension.include_dirs.append(incdir)
build_extension.finalize_options()
if COMPILER:
build_extension.compiler = COMPILER
ext_include_dirs = []
for match, get_additional_include_dirs in EXT_DEP_INCLUDES:
if match(module):
ext_include_dirs += get_additional_include_dirs()
self.copy_related_files(test_directory, workdir, module)
ext_compile_flags = CFLAGS[:]
if build_extension.compiler == 'mingw32':
ext_compile_flags.append('-Wno-format')
if extra_extension_args is None:
extra_extension_args = {}
self.copy_related_files(test_directory, workdir, module)
extension = Extension(
module,
sources = self.find_source_files(workdir, module),
include_dirs = ext_include_dirs,
extra_compile_args = CFLAGS,
extra_compile_args = ext_compile_flags,
**extra_extension_args
)
if self.language == 'cpp':
......@@ -709,8 +718,7 @@ def collect_unittests(path, module_prefix, suite, selectors):
if include_debugger:
skipped_dirs = []
else:
cython_dir = os.path.dirname(os.path.abspath(__file__))
skipped_dirs = [os.path.join(cython_dir, 'Cython', 'Debugger')]
skipped_dirs = ['Cython' + os.path.sep + 'Debugger' + os.path.sep]
for dirpath, dirnames, filenames in os.walk(path):
if dirpath != path and "__init__.py" not in filenames:
......@@ -786,8 +794,9 @@ class EndToEndTest(unittest.TestCase):
cython_root = os.path.dirname(os.path.abspath(__file__))
def __init__(self, treefile, workdir, cleanup_workdir=True):
self.name = os.path.splitext(os.path.basename(treefile))[0]
self.treefile = treefile
self.workdir = os.path.join(workdir, os.path.splitext(treefile)[0])
self.workdir = os.path.join(workdir, self.name)
self.cleanup_workdir = cleanup_workdir
cython_syspath = self.cython_root
for path in sys.path[::-1]:
......@@ -800,12 +809,11 @@ class EndToEndTest(unittest.TestCase):
unittest.TestCase.__init__(self)
def shortDescription(self):
return "End-to-end %s" % self.treefile
return "End-to-end %s" % self.name
def setUp(self):
from Cython.TestUtils import unpack_source_tree
_, self.commands = unpack_source_tree(
os.path.join('tests', 'build', self.treefile), self.workdir)
_, self.commands = unpack_source_tree(self.treefile, self.workdir)
self.old_dir = os.getcwd()
os.chdir(self.workdir)
if self.workdir not in sys.path:
......@@ -813,7 +821,13 @@ class EndToEndTest(unittest.TestCase):
def tearDown(self):
if self.cleanup_workdir:
for trial in range(5):
try:
shutil.rmtree(self.workdir)
except OSError:
time.sleep(0.1)
else:
break
os.chdir(self.old_dir)
def runTest(self):
......@@ -1006,6 +1020,8 @@ def main():
parser.add_option("--no-cython", dest="with_cython",
action="store_false", default=True,
help="do not run the Cython compiler, only the C compiler")
parser.add_option("--compiler", dest="compiler", default=None,
help="C compiler type")
parser.add_option("--no-c", dest="use_c",
action="store_false", default=True,
help="do not test C compilation")
......@@ -1123,7 +1139,7 @@ def main():
# RUN ALL TESTS!
UNITTEST_MODULE = "Cython"
UNITTEST_ROOT = os.path.join(os.getcwd(), UNITTEST_MODULE)
UNITTEST_ROOT = os.path.join(os.path.dirname(__file__), UNITTEST_MODULE)
if WITH_CYTHON:
if os.path.exists(WORKDIR):
for path in os.listdir(WORKDIR):
......@@ -1189,6 +1205,9 @@ def main():
if sys.platform in ['win32', 'cygwin'] and sys.version_info < (2,6):
exclude_selectors += [ lambda x: x == "run.specialfloat" ]
global COMPILER
if options.compiler:
COMPILER = options.compiler
languages = []
if options.use_c:
languages.append('c')
......
......@@ -272,8 +272,8 @@ setup(
name = 'Cython',
version = version,
url = 'http://www.cython.org',
author = 'Greg Ewing, Robert Bradshaw, Stefan Behnel, Dag Seljebotn, et al.',
author_email = 'cython-dev@codespeak.net',
author = 'Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.',
author_email = 'cython-devel@python.org',
description = "The Cython compiler for writing C extensions for the Python language.",
long_description = """\
The Cython language makes writing C extensions for the Python language as
......
......@@ -8,9 +8,14 @@ PYTHON -c "import a"
from Cython.Build.Dependencies import cythonize
from distutils.core import setup
import sys
if sys.platform == 'win32':
MATH_LIBS = []
else:
MATH_LIBS = ['m']
setup(
ext_modules = cythonize("*.pyx", aliases={'MATH_LIBS': ['m']}),
ext_modules = cythonize("*.pyx", aliases={'MATH_LIBS': MATH_LIBS}),
)
######## my_lib.pxd ########
......
cdef extern int a "c_a", b "c_b"
cdef extern from "cnamespec.h":
int a "c_a", b "c_b"
cdef struct foo "c_foo":
int i "c_i"
......
......@@ -2,13 +2,13 @@
extern "C" {
#endif
extern DL_EXPORT(void) e1(void);
extern DL_EXPORT(void *) e2(void);
extern DL_EXPORT(int*) e2(void);
#ifdef __cplusplus
}
#endif
void e1(void) {return;}
void *e2(void) {return 0;}
int* e2(void) {return 0;}
......
......@@ -7,9 +7,10 @@ cdef void f():
cdef int (*h)()
h = <int ()()>f # this is an error
h = <int (*)()>f # this is OK
_ERRORS = u"""
1:19: Array element cannot be a function
2:18: Function cannot return an array
3:18: Function cannot return a function
8:10: Function cannot return a function
8:5: Cannot cast to a function type
......
def outer(int x, *args, **kwargs):
"""
>>> inner = outer(1, 2, a=3)
>>> inner()
(1, (2,), {'a': 3})
>>> inner = outer('abc', 2, a=3)
Traceback (most recent call last):
TypeError: an integer is required
"""
def inner():
return x, args, kwargs
return inner
......@@ -195,3 +195,25 @@ def index_and_in():
for i in range(1,9):
if u'abcdefgh'[-i] in u'abCDefGh':
print i
# special test for narrow builds
high_uchar = u'\U00012345'
high_ustring0 = u'\U00012345\U00012346abc'
high_ustring1 = u'\U00012346\U00012345abc'
high_ustring_end = u'\U00012346abc\U00012344\U00012345'
high_ustring_no = u'\U00012346\U00012346abc'
def uchar_in(Py_UCS4 uchar, unicode ustring):
"""
>>> uchar_in(high_uchar, high_ustring0)
True
>>> uchar_in(high_uchar, high_ustring1)
True
>>> uchar_in(high_uchar, high_ustring_end)
True
>>> uchar_in(high_uchar, high_ustring_no)
False
"""
assert uchar == 0x12345, ('%X' % uchar)
return uchar in ustring
......@@ -94,15 +94,15 @@ def indexing():
b = b"abc"
assert typeof(b) == "bytes object", typeof(b)
b1 = b[1]
assert typeof(b1) == "Python object", typeof(b1)
assert typeof(b1) == "Python object", typeof(b1) # Py2: bytes, Py3: int
u = u"xyz"
assert typeof(u) == "unicode object", typeof(u)
u1 = u[1]
assert typeof(u1) == "Py_UNICODE", typeof(u1)
assert typeof(u1) == "Py_UCS4", typeof(u1)
s = "xyz"
assert typeof(s) == "str object", typeof(s)
s1 = s[1]
assert typeof(s1) == "Python object", typeof(s1)
assert typeof(s1) == "str object", typeof(s1)
L = [1,2,3]
assert typeof(L) == "list object", typeof(L)
L1 = L[1]
......@@ -296,6 +296,7 @@ def loop_over_bytes():
Python object
"""
cdef bytes bytes_string = b'abcdefg'
# bytes in Py2, int in Py3
for c in bytes_string:
pass
return typeof(c)
......@@ -303,9 +304,10 @@ def loop_over_bytes():
def loop_over_str():
"""
>>> print( loop_over_str() )
Python object
str object
"""
cdef str string = 'abcdefg'
# str (bytes) in Py2, str (unicode) in Py3
for c in string:
pass
return typeof(c)
......@@ -313,9 +315,10 @@ def loop_over_str():
def loop_over_unicode():
"""
>>> print( loop_over_unicode() )
Py_UNICODE
Py_UCS4
"""
cdef unicode ustring = u'abcdefg'
# Py_UCS4 can represent any Unicode character
for uchar in ustring:
pass
return typeof(uchar)
......
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