Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
c73a9b2d
Commit
c73a9b2d
authored
Feb 26, 2013
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'main/master'
Conflicts: Cython/Compiler/Options.py
parents
0ec2ff40
4ebc647c
Changes
30
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
1418 additions
and
533 deletions
+1418
-533
CHANGES.rst
CHANGES.rst
+9
-0
Cython/Compiler/Builtin.py
Cython/Compiler/Builtin.py
+14
-7
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+258
-193
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+63
-16
Cython/Compiler/Naming.py
Cython/Compiler/Naming.py
+2
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+3
-0
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+118
-80
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+5
-2
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+5
-0
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+2
-0
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+5
-5
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+2
-1
Cython/Compiler/TypeSlots.py
Cython/Compiler/TypeSlots.py
+14
-0
Cython/Compiler/Visitor.pxd
Cython/Compiler/Visitor.pxd
+5
-0
Cython/Compiler/Visitor.py
Cython/Compiler/Visitor.py
+11
-1
Cython/Utility/ObjectHandling.c
Cython/Utility/ObjectHandling.c
+8
-0
Cython/Utility/Optimize.c
Cython/Utility/Optimize.c
+0
-157
Cython/Utility/StringTools.c
Cython/Utility/StringTools.c
+188
-0
docs/src/userguide/extension_types.rst
docs/src/userguide/extension_types.rst
+49
-0
runtests.py
runtests.py
+3
-3
tests/errors/e_exttype_freelist.pyx
tests/errors/e_exttype_freelist.pyx
+24
-0
tests/run/constant_folding.py
tests/run/constant_folding.py
+133
-0
tests/run/constant_folding_cy.pyx
tests/run/constant_folding_cy.pyx
+82
-0
tests/run/ct_DEF.pyx
tests/run/ct_DEF.pyx
+9
-0
tests/run/exttype_freelist.pyx
tests/run/exttype_freelist.pyx
+93
-0
tests/run/tp_new.pyx
tests/run/tp_new.pyx
+42
-8
tests/run/tp_new_cimport.srctree
tests/run/tp_new_cimport.srctree
+86
-0
tests/run/unbound_special_methods.pyx
tests/run/unbound_special_methods.pyx
+69
-0
tests/run/unicode_slicing.pyx
tests/run/unicode_slicing.pyx
+97
-60
tests/run/unicodemethods.pyx
tests/run/unicodemethods.pyx
+19
-0
No files found.
CHANGES.rst
View file @
c73a9b2d
...
@@ -8,6 +8,15 @@ Cython Changelog
...
@@ -8,6 +8,15 @@ Cython Changelog
Features added
Features added
--------------
--------------
* A new class decorator ``@cython.freelist(N)`` creates a static freelist of N
instances for an extension type, thus avoiding the costly allocation step if
possible. This can speed up object instantiation by 20-30% in suitable
scenarios.
* Fast extension type instantiation using the ``Type.__new__(Type)`` idiom has
gained support for passing arguments. It is also a bit faster for types defined
inside of the module.
* The Python2-only dict methods ``.iter*()`` and ``.view*()`` (requires Python 2.7)
* The Python2-only dict methods ``.iter*()`` and ``.view*()`` (requires Python 2.7)
are automatically mapped to the equivalent keys/values/items methods in Python 3
are automatically mapped to the equivalent keys/values/items methods in Python 3
for typed dictionaries.
for typed dictionaries.
...
...
Cython/Compiler/Builtin.py
View file @
c73a9b2d
...
@@ -268,20 +268,26 @@ builtin_types_table = [
...
@@ -268,20 +268,26 @@ builtin_types_table = [
BuiltinAttribute
(
'imag'
,
'cval.imag'
,
field_type
=
PyrexTypes
.
c_double_type
),
BuiltinAttribute
(
'imag'
,
'cval.imag'
,
field_type
=
PyrexTypes
.
c_double_type
),
]),
]),
(
"bytes"
,
"PyBytes_Type"
,
[]),
(
"bytes"
,
"PyBytes_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PySequence_Contains"
),
(
"str"
,
"PyString_Type"
,
[]),
]),
(
"unicode"
,
"PyUnicode_Type"
,
[
BuiltinMethod
(
"join"
,
"TO"
,
"T"
,
"PyUnicode_Join"
),
(
"str"
,
"PyString_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PySequence_Contains"
),
]),
(
"unicode"
,
"PyUnicode_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PyUnicode_Contains"
),
BuiltinMethod
(
"join"
,
"TO"
,
"T"
,
"PyUnicode_Join"
),
]),
]),
(
"tuple"
,
"PyTuple_Type"
,
[]),
(
"tuple"
,
"PyTuple_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PySequence_Contains"
),
]),
(
"list"
,
"PyList_Type"
,
[
BuiltinMethod
(
"insert"
,
"TzO"
,
"r"
,
"PyList_Insert"
),
(
"list"
,
"PyList_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PySequence_Contains"
),
BuiltinMethod
(
"insert"
,
"TzO"
,
"r"
,
"PyList_Insert"
),
BuiltinMethod
(
"reverse"
,
"T"
,
"r"
,
"PyList_Reverse"
),
BuiltinMethod
(
"reverse"
,
"T"
,
"r"
,
"PyList_Reverse"
),
BuiltinMethod
(
"append"
,
"TO"
,
"r"
,
"__Pyx_PyList_Append"
,
BuiltinMethod
(
"append"
,
"TO"
,
"r"
,
"__Pyx_PyList_Append"
,
utility_code
=
UtilityCode
.
load
(
"ListAppend"
,
"Optimize.c"
)),
utility_code
=
UtilityCode
.
load
(
"ListAppend"
,
"Optimize.c"
)),
]),
]),
(
"dict"
,
"PyDict_Type"
,
[
BuiltinMethod
(
"items"
,
"T"
,
"O"
,
"__Pyx_PyDict_Items"
,
(
"dict"
,
"PyDict_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PyDict_Contains"
),
BuiltinMethod
(
"items"
,
"T"
,
"O"
,
"__Pyx_PyDict_Items"
,
utility_code
=
UtilityCode
.
load
(
"py_dict_items"
,
"Builtins.c"
)),
utility_code
=
UtilityCode
.
load
(
"py_dict_items"
,
"Builtins.c"
)),
BuiltinMethod
(
"keys"
,
"T"
,
"O"
,
"__Pyx_PyDict_Keys"
,
BuiltinMethod
(
"keys"
,
"T"
,
"O"
,
"__Pyx_PyDict_Keys"
,
utility_code
=
UtilityCode
.
load
(
"py_dict_keys"
,
"Builtins.c"
)),
utility_code
=
UtilityCode
.
load
(
"py_dict_keys"
,
"Builtins.c"
)),
...
@@ -309,7 +315,8 @@ builtin_types_table = [
...
@@ -309,7 +315,8 @@ builtin_types_table = [
]),
]),
# ("file", "PyFile_Type", []), # not in Py3
# ("file", "PyFile_Type", []), # not in Py3
(
"set"
,
"PySet_Type"
,
[
BuiltinMethod
(
"clear"
,
"T"
,
"r"
,
"PySet_Clear"
,
(
"set"
,
"PySet_Type"
,
[
BuiltinMethod
(
"__contains__"
,
"TO"
,
"b"
,
"PySequence_Contains"
),
BuiltinMethod
(
"clear"
,
"T"
,
"r"
,
"PySet_Clear"
,
utility_code
=
py_set_utility_code
),
utility_code
=
py_set_utility_code
),
# discard() and remove() have a special treatment for unhashable values
# discard() and remove() have a special treatment for unhashable values
# BuiltinMethod("discard", "TO", "r", "PySet_Discard",
# BuiltinMethod("discard", "TO", "r", "PySet_Discard",
...
...
Cython/Compiler/ExprNodes.py
View file @
c73a9b2d
This diff is collapsed.
Click to expand it.
Cython/Compiler/ModuleNode.py
View file @
c73a9b2d
...
@@ -1044,30 +1044,52 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -1044,30 +1044,52 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else
:
else
:
unused_marker
=
'CYTHON_UNUSED '
unused_marker
=
'CYTHON_UNUSED '
need_self_cast
=
type
.
vtabslot_cname
or
have_entries
or
cpp_class_attrs
if
base_type
:
freelist_size
=
0
# not currently supported
else
:
freelist_size
=
scope
.
directives
.
get
(
'freelist'
,
0
)
freelist_name
=
scope
.
mangle_internal
(
Naming
.
freelist_name
)
freecount_name
=
scope
.
mangle_internal
(
Naming
.
freecount_name
)
decls
=
code
.
globalstate
[
'decls'
]
decls
.
putln
(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/"
%
slot_func
)
code
.
putln
(
""
)
if
freelist_size
:
code
.
putln
(
"static %s[%d];"
%
(
scope
.
parent_type
.
declaration_code
(
freelist_name
),
freelist_size
))
code
.
putln
(
"static int %s = 0;"
%
freecount_name
)
code
.
putln
(
""
)
code
.
putln
(
""
)
code
.
putln
(
code
.
putln
(
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {"
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {"
%
(
scope
.
mangle_internal
(
"tp_new"
),
unused_marker
,
unused_marker
))
%
(
slot_func
,
unused_marker
,
unused_marker
))
need_self_cast
=
type
.
vtabslot_cname
or
have_entries
or
cpp_class_attrs
if
need_self_cast
:
if
need_self_cast
:
code
.
putln
(
code
.
putln
(
"%s;"
%
scope
.
parent_type
.
declaration_code
(
"p"
))
"%s;"
%
scope
.
parent_type
.
declaration_code
(
"p"
))
if
base_type
:
if
base_type
:
tp_new
=
TypeSlots
.
get_base_slot_function
(
scope
,
tp_slot
)
tp_new
=
TypeSlots
.
get_base_slot_function
(
scope
,
tp_slot
)
if
tp_new
is
None
:
if
tp_new
is
None
:
tp_new
=
"%s->tp_new"
%
base_type
.
typeptr_cname
tp_new
=
"%s->tp_new"
%
base_type
.
typeptr_cname
code
.
putln
(
code
.
putln
(
"PyObject *o = %s(t, a, k);"
%
tp_new
)
"PyObject *o = %s(t, a, k);"
%
tp_new
)
else
:
else
:
code
.
putln
(
code
.
putln
(
"PyObject *o;"
)
"PyObject *o = (*t->tp_alloc)(t, 0);"
)
if
freelist_size
:
code
.
putln
(
code
.
putln
(
"if ((%s > 0) & (t->tp_basicsize == sizeof(%s))) {"
%
(
"if (!o) return 0;"
)
freecount_name
,
type
.
declaration_code
(
""
,
deref
=
True
)))
code
.
putln
(
"o = (PyObject*)%s[--%s];"
%
(
freelist_name
,
freecount_name
))
code
.
putln
(
"PyObject_INIT(o, t);"
)
if
scope
.
needs_gc
():
code
.
putln
(
"PyObject_GC_Track(o);"
)
code
.
putln
(
"} else {"
)
code
.
putln
(
"o = (*t->tp_alloc)(t, 0);"
)
code
.
putln
(
"if (!o) return 0;"
)
if
freelist_size
and
not
base_type
:
code
.
putln
(
'}'
)
if
need_self_cast
:
if
need_self_cast
:
code
.
putln
(
code
.
putln
(
"p = %s;"
%
type
.
cast_code
(
"o"
))
"p = %s;"
%
type
.
cast_code
(
"o"
))
#if need_self_cast:
#if need_self_cast:
# self.generate_self_cast(scope, code)
# self.generate_self_cast(scope, code)
if
type
.
vtabslot_cname
:
if
type
.
vtabslot_cname
:
...
@@ -1191,8 +1213,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -1191,8 +1213,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
globalstate
.
use_utility_code
(
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CallNextTpDealloc"
,
"ExtensionTypes.c"
))
UtilityCode
.
load_cached
(
"CallNextTpDealloc"
,
"ExtensionTypes.c"
))
else
:
else
:
code
.
putln
(
freelist_size
=
scope
.
directives
.
get
(
'freelist'
,
0
)
"(*Py_TYPE(o)->tp_free)(o);"
)
if
freelist_size
:
freelist_name
=
scope
.
mangle_internal
(
Naming
.
freelist_name
)
freecount_name
=
scope
.
mangle_internal
(
Naming
.
freecount_name
)
type
=
scope
.
parent_type
code
.
putln
(
"if ((%s < %d) & (Py_TYPE(o)->tp_basicsize == sizeof(%s))) {"
%
(
freecount_name
,
freelist_size
,
type
.
declaration_code
(
""
,
deref
=
True
)))
code
.
putln
(
"%s[%s++] = %s;"
%
(
freelist_name
,
freecount_name
,
type
.
cast_code
(
"o"
)))
code
.
putln
(
"} else {"
)
code
.
putln
(
"(*Py_TYPE(o)->tp_free)(o);"
)
if
freelist_size
:
code
.
putln
(
"}"
)
code
.
putln
(
code
.
putln
(
"}"
)
"}"
)
...
@@ -2049,6 +2083,19 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -2049,6 +2083,19 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
PyrexTypes
.
py_object_type
,
PyrexTypes
.
py_object_type
,
clear_before_decref
=
True
,
clear_before_decref
=
True
,
nanny
=
False
)
nanny
=
False
)
for
entry
in
env
.
c_class_entries
:
cclass_type
=
entry
.
type
if
cclass_type
.
is_external
or
cclass_type
.
base_type
:
continue
if
cclass_type
.
scope
.
directives
.
get
(
'freelist'
,
0
):
scope
=
cclass_type
.
scope
freelist_name
=
scope
.
mangle_internal
(
Naming
.
freelist_name
)
freecount_name
=
scope
.
mangle_internal
(
Naming
.
freecount_name
)
code
.
putln
(
"while (%s > 0) {"
%
freecount_name
)
code
.
putln
(
"PyObject* o = (PyObject*)%s[--%s];"
%
(
freelist_name
,
freecount_name
))
code
.
putln
(
"(*Py_TYPE(o)->tp_free)(o);"
)
code
.
putln
(
"}"
)
# for entry in env.pynum_entries:
# for entry in env.pynum_entries:
# code.put_decref_clear(entry.cname,
# code.put_decref_clear(entry.cname,
# PyrexTypes.py_object_type,
# PyrexTypes.py_object_type,
...
...
Cython/Compiler/Naming.py
View file @
c73a9b2d
...
@@ -103,6 +103,8 @@ global_code_object_cache_find = pyrex_prefix + 'find_code_object'
...
@@ -103,6 +103,8 @@ global_code_object_cache_find = pyrex_prefix + 'find_code_object'
global_code_object_cache_insert
=
pyrex_prefix
+
'insert_code_object'
global_code_object_cache_insert
=
pyrex_prefix
+
'insert_code_object'
genexpr_id_ref
=
'genexpr'
genexpr_id_ref
=
'genexpr'
freelist_name
=
'freelist'
freecount_name
=
'freecount'
line_c_macro
=
"__LINE__"
line_c_macro
=
"__LINE__"
...
...
Cython/Compiler/Nodes.py
View file @
c73a9b2d
...
@@ -4189,6 +4189,9 @@ class CClassDefNode(ClassDefNode):
...
@@ -4189,6 +4189,9 @@ class CClassDefNode(ClassDefNode):
%
base_class_entry
.
type
.
name
)
%
base_class_entry
.
type
.
name
)
else
:
else
:
self
.
base_type
=
base_class_entry
.
type
self
.
base_type
=
base_class_entry
.
type
if
env
.
directives
.
get
(
'freelist'
,
0
)
>
0
:
warning
(
self
.
pos
,
"freelists cannot be used on subtypes, only the base class can manage them"
,
1
)
has_body
=
self
.
body
is
not
None
has_body
=
self
.
body
is
not
None
if
self
.
module_name
and
self
.
visibility
!=
'extern'
:
if
self
.
module_name
and
self
.
visibility
!=
'extern'
:
module_path
=
self
.
module_name
.
split
(
"."
)
module_path
=
self
.
module_name
.
split
(
"."
)
...
...
Cython/Compiler/Optimize.py
View file @
c73a9b2d
This diff is collapsed.
Click to expand it.
Cython/Compiler/Options.py
View file @
c73a9b2d
...
@@ -125,7 +125,8 @@ directive_defaults = {
...
@@ -125,7 +125,8 @@ directive_defaults = {
# experimental, subject to change
# experimental, subject to change
'binding'
:
None
,
'binding'
:
None
,
'experimental_cpp_class_def'
:
False
'experimental_cpp_class_def'
:
False
,
'freelist'
:
0
,
}
}
# Extra warning directives
# Extra warning directives
...
@@ -155,6 +156,7 @@ directive_types = {
...
@@ -155,6 +156,7 @@ directive_types = {
'cclass'
:
None
,
'cclass'
:
None
,
'returns'
:
type
,
'returns'
:
type
,
'set_initial_path'
:
str
,
'set_initial_path'
:
str
,
'freelist'
:
int
,
'c_string_type'
:
one_of
(
'bytes'
,
'str'
,
'unicoode'
),
'c_string_type'
:
one_of
(
'bytes'
,
'str'
,
'unicoode'
),
}
}
...
@@ -172,7 +174,8 @@ directive_scopes = { # defaults to available everywhere
...
@@ -172,7 +174,8 @@ directive_scopes = { # defaults to available everywhere
'set_initial_path'
:
(
'module'
,),
'set_initial_path'
:
(
'module'
,),
'test_assert_path_exists'
:
(
'function'
,
'class'
,
'cclass'
),
'test_assert_path_exists'
:
(
'function'
,
'class'
,
'cclass'
),
'test_fail_if_path_exists'
:
(
'function'
,
'class'
,
'cclass'
),
'test_fail_if_path_exists'
:
(
'function'
,
'class'
,
'cclass'
),
# Avoid scope-specific to/from_py_functions.
'freelist'
:
(
'cclass'
,),
# Avoid scope-specific to/from_py_functions for c_string.
'c_string_type'
:
(
'module'
,),
'c_string_type'
:
(
'module'
,),
'c_string_encoding'
:
(
'module'
,),
'c_string_encoding'
:
(
'module'
,),
}
}
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
c73a9b2d
...
@@ -883,6 +883,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
...
@@ -883,6 +883,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
raise
PostParseError
(
pos
,
raise
PostParseError
(
pos
,
'The %s directive takes one compile-time boolean argument'
%
optname
)
'The %s directive takes one compile-time boolean argument'
%
optname
)
return
(
optname
,
args
[
0
].
value
)
return
(
optname
,
args
[
0
].
value
)
elif
directivetype
is
int
:
if
kwds
is
not
None
or
len
(
args
)
!=
1
or
not
isinstance
(
args
[
0
],
ExprNodes
.
IntNode
):
raise
PostParseError
(
pos
,
'The %s directive takes one compile-time integer argument'
%
optname
)
return
(
optname
,
int
(
args
[
0
].
value
))
elif
directivetype
is
str
:
elif
directivetype
is
str
:
if
kwds
is
not
None
or
len
(
args
)
!=
1
or
not
isinstance
(
args
[
0
],
(
ExprNodes
.
StringNode
,
if
kwds
is
not
None
or
len
(
args
)
!=
1
or
not
isinstance
(
args
[
0
],
(
ExprNodes
.
StringNode
,
ExprNodes
.
UnicodeNode
)):
ExprNodes
.
UnicodeNode
)):
...
...
Cython/Compiler/Parsing.py
View file @
c73a9b2d
...
@@ -693,6 +693,8 @@ def wrap_compile_time_constant(pos, value):
...
@@ -693,6 +693,8 @@ def wrap_compile_time_constant(pos, value):
rep
=
repr
(
value
)
rep
=
repr
(
value
)
if
value
is
None
:
if
value
is
None
:
return
ExprNodes
.
NoneNode
(
pos
)
return
ExprNodes
.
NoneNode
(
pos
)
elif
value
is
Ellipsis
:
return
ExprNodes
.
EllipsisNode
(
pos
)
elif
isinstance
(
value
,
bool
):
elif
isinstance
(
value
,
bool
):
return
ExprNodes
.
BoolNode
(
pos
,
value
=
value
)
return
ExprNodes
.
BoolNode
(
pos
,
value
=
value
)
elif
isinstance
(
value
,
int
):
elif
isinstance
(
value
,
int
):
...
...
Cython/Compiler/PyrexTypes.py
View file @
c73a9b2d
...
@@ -984,8 +984,8 @@ class BuiltinObjectType(PyObjectType):
...
@@ -984,8 +984,8 @@ class BuiltinObjectType(PyObjectType):
def
isinstance_code
(
self
,
arg
):
def
isinstance_code
(
self
,
arg
):
return
'%s(%s)'
%
(
self
.
type_check_function
(
exact
=
False
),
arg
)
return
'%s(%s)'
%
(
self
.
type_check_function
(
exact
=
False
),
arg
)
def
type_test_code
(
self
,
arg
,
notnone
=
False
):
def
type_test_code
(
self
,
arg
,
notnone
=
False
,
exact
=
True
):
type_check
=
self
.
type_check_function
(
exact
=
True
)
type_check
=
self
.
type_check_function
(
exact
=
exact
)
check
=
'likely(%s(%s))'
%
(
type_check
,
arg
)
check
=
'likely(%s(%s))'
%
(
type_check
,
arg
)
if
not
notnone
:
if
not
notnone
:
check
+=
'||((%s) == Py_None)'
%
arg
check
+=
'||((%s) == Py_None)'
%
arg
...
@@ -1033,9 +1033,6 @@ class PyExtensionType(PyObjectType):
...
@@ -1033,9 +1033,6 @@ class PyExtensionType(PyObjectType):
is_extension_type
=
1
is_extension_type
=
1
has_attributes
=
1
has_attributes
=
1
def
needs_nonecheck
(
self
):
return
True
objtypedef_cname
=
None
objtypedef_cname
=
None
def
__init__
(
self
,
name
,
typedef_flag
,
base_type
,
is_external
=
0
):
def
__init__
(
self
,
name
,
typedef_flag
,
base_type
,
is_external
=
0
):
...
@@ -1060,6 +1057,9 @@ class PyExtensionType(PyObjectType):
...
@@ -1060,6 +1057,9 @@ class PyExtensionType(PyObjectType):
if
scope
:
if
scope
:
scope
.
parent_type
=
self
scope
.
parent_type
=
self
def
needs_nonecheck
(
self
):
return
True
def
subtype_of_resolved_type
(
self
,
other_type
):
def
subtype_of_resolved_type
(
self
,
other_type
):
if
other_type
.
is_extension_type
or
other_type
.
is_builtin_type
:
if
other_type
.
is_extension_type
or
other_type
.
is_builtin_type
:
return
self
is
other_type
or
(
return
self
is
other_type
or
(
...
...
Cython/Compiler/Symtab.py
View file @
c73a9b2d
...
@@ -1310,6 +1310,7 @@ class ModuleScope(Scope):
...
@@ -1310,6 +1310,7 @@ class ModuleScope(Scope):
if
defining
or
implementing
:
if
defining
or
implementing
:
scope
=
CClassScope
(
name
=
name
,
outer_scope
=
self
,
scope
=
CClassScope
(
name
=
name
,
outer_scope
=
self
,
visibility
=
visibility
)
visibility
=
visibility
)
scope
.
directives
=
self
.
directives
.
copy
()
if
base_type
and
base_type
.
scope
:
if
base_type
and
base_type
.
scope
:
scope
.
declare_inherited_c_attributes
(
base_type
.
scope
)
scope
.
declare_inherited_c_attributes
(
base_type
.
scope
)
type
.
set_scope
(
scope
)
type
.
set_scope
(
scope
)
...
@@ -1891,7 +1892,7 @@ class CClassScope(ClassScope):
...
@@ -1891,7 +1892,7 @@ class CClassScope(ClassScope):
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
in_pxd
=
0
,
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
in_pxd
=
0
,
defining
=
0
,
modifiers
=
(),
utility_code
=
None
):
defining
=
0
,
modifiers
=
(),
utility_code
=
None
):
if
get_special_method_signature
(
name
):
if
get_special_method_signature
(
name
)
and
not
self
.
parent_type
.
is_builtin_type
:
error
(
pos
,
"Special methods must be declared with 'def', not 'cdef'"
)
error
(
pos
,
"Special methods must be declared with 'def', not 'cdef'"
)
args
=
type
.
args
args
=
type
.
args
if
not
args
:
if
not
args
:
...
...
Cython/Compiler/TypeSlots.py
View file @
c73a9b2d
...
@@ -493,11 +493,13 @@ def get_special_method_signature(name):
...
@@ -493,11 +493,13 @@ def get_special_method_signature(name):
else
:
else
:
return
None
return
None
def
get_property_accessor_signature
(
name
):
def
get_property_accessor_signature
(
name
):
# Return signature of accessor for an extension type
# Return signature of accessor for an extension type
# property, else None.
# property, else None.
return
property_accessor_signatures
.
get
(
name
)
return
property_accessor_signatures
.
get
(
name
)
def
get_base_slot_function
(
scope
,
slot
):
def
get_base_slot_function
(
scope
,
slot
):
# Returns the function implementing this slot in the baseclass.
# Returns the function implementing this slot in the baseclass.
# This is useful for enabling the compiler to optimize calls
# This is useful for enabling the compiler to optimize calls
...
@@ -511,6 +513,18 @@ def get_base_slot_function(scope, slot):
...
@@ -511,6 +513,18 @@ def get_base_slot_function(scope, slot):
return
parent_slot
return
parent_slot
return
None
return
None
def
get_slot_function
(
scope
,
slot
):
# Returns the function implementing this slot in the baseclass.
# This is useful for enabling the compiler to optimize calls
# that recursively climb the class hierarchy.
slot_code
=
slot
.
slot_code
(
scope
)
if
slot_code
!=
'0'
:
entry
=
scope
.
parent_scope
.
lookup_here
(
scope
.
parent_type
.
name
)
if
entry
.
visibility
!=
'extern'
:
return
slot_code
return
None
#------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------
#
#
# Signatures for generic Python functions and methods.
# Signatures for generic Python functions and methods.
...
...
Cython/Compiler/Visitor.pxd
View file @
c73a9b2d
...
@@ -28,8 +28,13 @@ cdef class EnvTransform(CythonTransform):
...
@@ -28,8 +28,13 @@ cdef class EnvTransform(CythonTransform):
cdef
public
list
env_stack
cdef
public
list
env_stack
cdef
class
MethodDispatcherTransform
(
EnvTransform
):
cdef
class
MethodDispatcherTransform
(
EnvTransform
):
@
cython
.
final
cdef
_visit_binop_node
(
self
,
node
)
@
cython
.
final
cdef
_find_handler
(
self
,
match_name
,
bint
has_kwargs
)
cdef
_find_handler
(
self
,
match_name
,
bint
has_kwargs
)
@
cython
.
final
cdef
_dispatch_to_handler
(
self
,
node
,
function
,
arg_list
,
kwargs
)
cdef
_dispatch_to_handler
(
self
,
node
,
function
,
arg_list
,
kwargs
)
@
cython
.
final
cdef
_dispatch_to_method_handler
(
self
,
attr_name
,
self_arg
,
cdef
_dispatch_to_method_handler
(
self
,
attr_name
,
self_arg
,
is_unbound_method
,
type_name
,
is_unbound_method
,
type_name
,
node
,
arg_list
,
kwargs
)
node
,
arg_list
,
kwargs
)
...
...
Cython/Compiler/Visitor.py
View file @
c73a9b2d
...
@@ -492,7 +492,17 @@ class MethodDispatcherTransform(EnvTransform):
...
@@ -492,7 +492,17 @@ class MethodDispatcherTransform(EnvTransform):
args
=
node
.
args
args
=
node
.
args
return
self
.
_dispatch_to_handler
(
node
,
function
,
args
,
None
)
return
self
.
_dispatch_to_handler
(
node
,
function
,
args
,
None
)
def
visit_PrimaryCmpNode
(
self
,
node
):
if
node
.
cascade
:
# not currently handled below
self
.
visitchildren
(
node
)
return
node
return
self
.
_visit_binop_node
(
node
)
def
visit_BinopNode
(
self
,
node
):
def
visit_BinopNode
(
self
,
node
):
return
self
.
_visit_binop_node
(
node
)
def
_visit_binop_node
(
self
,
node
):
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
# FIXME: could special case 'not_in'
# FIXME: could special case 'not_in'
special_method_name
=
find_special_method_for_binary_operator
(
node
.
operator
)
special_method_name
=
find_special_method_for_binary_operator
(
node
.
operator
)
...
@@ -591,7 +601,7 @@ class MethodDispatcherTransform(EnvTransform):
...
@@ -591,7 +601,7 @@ class MethodDispatcherTransform(EnvTransform):
if
self_arg
is
not
None
:
if
self_arg
is
not
None
:
arg_list
=
[
self_arg
]
+
list
(
arg_list
)
arg_list
=
[
self_arg
]
+
list
(
arg_list
)
if
kwargs
:
if
kwargs
:
return
method_handler
(
node
,
arg_list
,
kwargs
,
is_unbound_method
)
return
method_handler
(
node
,
arg_list
,
is_unbound_method
,
kwargs
)
else
:
else
:
return
method_handler
(
node
,
arg_list
,
is_unbound_method
)
return
method_handler
(
node
,
arg_list
,
is_unbound_method
)
...
...
Cython/Utility/ObjectHandling.c
View file @
c73a9b2d
...
@@ -650,3 +650,11 @@ bad:
...
@@ -650,3 +650,11 @@ bad:
__Pyx_PyObject_CallMethodTuple(obj, name, PyTuple_Pack(1, arg1))
__Pyx_PyObject_CallMethodTuple(obj, name, PyTuple_Pack(1, arg1))
#define __Pyx_PyObject_CallMethod0(obj, name) \
#define __Pyx_PyObject_CallMethod0(obj, name) \
__Pyx_PyObject_CallMethodTuple(obj, name, (Py_INCREF($empty_tuple), $empty_tuple))
__Pyx_PyObject_CallMethodTuple(obj, name, (Py_INCREF($empty_tuple), $empty_tuple))
/////////////// tp_new.proto ///////////////
#define __Pyx_tp_new(type_obj, args) __Pyx_tp_new_kwargs(type_obj, args, NULL)
static
CYTHON_INLINE
PyObject
*
__Pyx_tp_new_kwargs
(
PyObject
*
type_obj
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
return
(
PyObject
*
)
(((
PyTypeObject
*
)
type_obj
)
->
tp_new
((
PyTypeObject
*
)
type_obj
,
args
,
kwargs
));
}
Cython/Utility/Optimize.c
View file @
c73a9b2d
...
@@ -112,163 +112,6 @@ static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
...
@@ -112,163 +112,6 @@ static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
}
}
/////////////// py_unicode_istitle.proto ///////////////
// Py_UNICODE_ISTITLE() doesn't match unicode.istitle() as the latter
// additionally allows character that comply with Py_UNICODE_ISUPPER()
#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
);
}
/////////////// unicode_tailmatch.proto ///////////////
// Python's unicode.startswith() and unicode.endswith() support a
// tuple of prefixes/suffixes, whereas it's much more common to
// test for a single unicode string.
static
int
__Pyx_PyUnicode_Tailmatch
(
PyObject
*
s
,
PyObject
*
substr
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
if
(
unlikely
(
PyTuple_Check
(
substr
)))
{
Py_ssize_t
i
,
count
=
PyTuple_GET_SIZE
(
substr
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
int
result
;
#if CYTHON_COMPILING_IN_CPYTHON
result
=
PyUnicode_Tailmatch
(
s
,
PyTuple_GET_ITEM
(
substr
,
i
),
start
,
end
,
direction
);
#else
PyObject
*
sub
=
PySequence_GetItem
(
substr
,
i
);
if
(
unlikely
(
!
sub
))
return
-
1
;
result
=
PyUnicode_Tailmatch
(
s
,
sub
,
start
,
end
,
direction
);
Py_DECREF
(
sub
);
#endif
if
(
result
)
{
return
result
;
}
}
return
0
;
}
return
PyUnicode_Tailmatch
(
s
,
substr
,
start
,
end
,
direction
);
}
/////////////// bytes_tailmatch.proto ///////////////
static
int
__Pyx_PyBytes_SingleTailmatch
(
PyObject
*
self
,
PyObject
*
arg
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
const
char
*
self_ptr
=
PyBytes_AS_STRING
(
self
);
Py_ssize_t
self_len
=
PyBytes_GET_SIZE
(
self
);
const
char
*
sub_ptr
;
Py_ssize_t
sub_len
;
int
retval
;
#if PY_VERSION_HEX >= 0x02060000
Py_buffer
view
;
view
.
obj
=
NULL
;
#endif
if
(
PyBytes_Check
(
arg
)
)
{
sub_ptr
=
PyBytes_AS_STRING
(
arg
);
sub_len
=
PyBytes_GET_SIZE
(
arg
);
}
#if PY_MAJOR_VERSION < 3
// Python 2.x allows mixing unicode and str
else
if
(
PyUnicode_Check
(
arg
)
)
{
return
PyUnicode_Tailmatch
(
self
,
arg
,
start
,
end
,
direction
);
}
#endif
else
{
#if PY_VERSION_HEX < 0x02060000
if
(
unlikely
(
PyObject_AsCharBuffer
(
arg
,
&
sub_ptr
,
&
sub_len
)))
return
-
1
;
#else
if
(
unlikely
(
PyObject_GetBuffer
(
self
,
&
view
,
PyBUF_SIMPLE
)
==
-
1
))
return
-
1
;
sub_ptr
=
(
const
char
*
)
view
.
buf
;
sub_len
=
view
.
len
;
#endif
}
if
(
end
>
self_len
)
end
=
self_len
;
else
if
(
end
<
0
)
end
+=
self_len
;
if
(
end
<
0
)
end
=
0
;
if
(
start
<
0
)
start
+=
self_len
;
if
(
start
<
0
)
start
=
0
;
if
(
direction
>
0
)
{
/* endswith */
if
(
end
-
sub_len
>
start
)
start
=
end
-
sub_len
;
}
if
(
start
+
sub_len
<=
end
)
retval
=
!
memcmp
(
self_ptr
+
start
,
sub_ptr
,
sub_len
);
else
retval
=
0
;
#if PY_VERSION_HEX >= 0x02060000
if
(
view
.
obj
)
PyBuffer_Release
(
&
view
);
#endif
return
retval
;
}
static
int
__Pyx_PyBytes_Tailmatch
(
PyObject
*
self
,
PyObject
*
substr
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
if
(
unlikely
(
PyTuple_Check
(
substr
)))
{
Py_ssize_t
i
,
count
=
PyTuple_GET_SIZE
(
substr
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
int
result
;
#if CYTHON_COMPILING_IN_CPYTHON
result
=
__Pyx_PyBytes_SingleTailmatch
(
self
,
PyTuple_GET_ITEM
(
substr
,
i
),
start
,
end
,
direction
);
#else
PyObject
*
sub
=
PySequence_GetItem
(
substr
,
i
);
if
(
unlikely
(
!
sub
))
return
-
1
;
result
=
__Pyx_PyBytes_SingleTailmatch
(
self
,
sub
,
start
,
end
,
direction
);
Py_DECREF
(
sub
);
#endif
if
(
result
)
{
return
result
;
}
}
return
0
;
}
return
__Pyx_PyBytes_SingleTailmatch
(
self
,
substr
,
start
,
end
,
direction
);
}
/////////////// bytes_index.proto ///////////////
static
CYTHON_INLINE
char
__Pyx_PyBytes_GetItemInt
(
PyObject
*
bytes
,
Py_ssize_t
index
,
int
check_bounds
)
{
if
(
check_bounds
)
{
Py_ssize_t
size
=
PyBytes_GET_SIZE
(
bytes
);
if
(
unlikely
(
index
>=
size
)
|
((
index
<
0
)
&
unlikely
(
index
<
-
size
)))
{
PyErr_Format
(
PyExc_IndexError
,
"string index out of range"
);
return
-
1
;
}
}
if
(
index
<
0
)
index
+=
PyBytes_GET_SIZE
(
bytes
);
return
PyBytes_AS_STRING
(
bytes
)[
index
];
}
/////////////// dict_getitem_default.proto ///////////////
/////////////// dict_getitem_default.proto ///////////////
static
PyObject
*
__Pyx_PyDict_GetItemDefault
(
PyObject
*
d
,
PyObject
*
key
,
PyObject
*
default_value
);
/*proto*/
static
PyObject
*
__Pyx_PyDict_GetItemDefault
(
PyObject
*
d
,
PyObject
*
key
,
PyObject
*
default_value
);
/*proto*/
...
...
Cython/Utility/StringTools.c
View file @
c73a9b2d
...
@@ -109,6 +109,14 @@ static CYTHON_INLINE int __Pyx_PyUnicodeBufferContainsUCS4(Py_UNICODE* buffer, P
...
@@ -109,6 +109,14 @@ static CYTHON_INLINE int __Pyx_PyUnicodeBufferContainsUCS4(Py_UNICODE* buffer, P
}
}
//////////////////// PyUnicodeContains.proto ////////////////////
static
CYTHON_INLINE
int
__Pyx_PyUnicode_Contains
(
PyObject
*
substring
,
PyObject
*
text
,
int
eq
)
{
int
result
=
PyUnicode_Contains
(
text
,
substring
);
return
unlikely
(
result
<
0
)
?
result
:
(
result
==
(
eq
==
Py_EQ
));
}
//////////////////// StrEquals.proto ////////////////////
//////////////////// StrEquals.proto ////////////////////
//@requires: BytesEquals
//@requires: BytesEquals
//@requires: UnicodeEquals
//@requires: UnicodeEquals
...
@@ -410,3 +418,183 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring(
...
@@ -410,3 +418,183 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_Substring(
return
PyUnicode_FromUnicode
(
PyUnicode_AS_UNICODE
(
text
)
+
start
,
stop
-
start
);
return
PyUnicode_FromUnicode
(
PyUnicode_AS_UNICODE
(
text
)
+
start
,
stop
-
start
);
#endif
#endif
}
}
/////////////// py_unicode_istitle.proto ///////////////
// Py_UNICODE_ISTITLE() doesn't match unicode.istitle() as the latter
// additionally allows character that comply with Py_UNICODE_ISUPPER()
#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
);
}
/////////////// unicode_tailmatch.proto ///////////////
// Python's unicode.startswith() and unicode.endswith() support a
// tuple of prefixes/suffixes, whereas it's much more common to
// test for a single unicode string.
static
int
__Pyx_PyUnicode_Tailmatch
(
PyObject
*
s
,
PyObject
*
substr
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
if
(
unlikely
(
PyTuple_Check
(
substr
)))
{
Py_ssize_t
i
,
count
=
PyTuple_GET_SIZE
(
substr
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
int
result
;
#if CYTHON_COMPILING_IN_CPYTHON
result
=
PyUnicode_Tailmatch
(
s
,
PyTuple_GET_ITEM
(
substr
,
i
),
start
,
end
,
direction
);
#else
PyObject
*
sub
=
PySequence_GetItem
(
substr
,
i
);
if
(
unlikely
(
!
sub
))
return
-
1
;
result
=
PyUnicode_Tailmatch
(
s
,
sub
,
start
,
end
,
direction
);
Py_DECREF
(
sub
);
#endif
if
(
result
)
{
return
result
;
}
}
return
0
;
}
return
PyUnicode_Tailmatch
(
s
,
substr
,
start
,
end
,
direction
);
}
/////////////// bytes_tailmatch.proto ///////////////
static
int
__Pyx_PyBytes_SingleTailmatch
(
PyObject
*
self
,
PyObject
*
arg
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
const
char
*
self_ptr
=
PyBytes_AS_STRING
(
self
);
Py_ssize_t
self_len
=
PyBytes_GET_SIZE
(
self
);
const
char
*
sub_ptr
;
Py_ssize_t
sub_len
;
int
retval
;
#if PY_VERSION_HEX >= 0x02060000
Py_buffer
view
;
view
.
obj
=
NULL
;
#endif
if
(
PyBytes_Check
(
arg
)
)
{
sub_ptr
=
PyBytes_AS_STRING
(
arg
);
sub_len
=
PyBytes_GET_SIZE
(
arg
);
}
#if PY_MAJOR_VERSION < 3
// Python 2.x allows mixing unicode and str
else
if
(
PyUnicode_Check
(
arg
)
)
{
return
PyUnicode_Tailmatch
(
self
,
arg
,
start
,
end
,
direction
);
}
#endif
else
{
#if PY_VERSION_HEX < 0x02060000
if
(
unlikely
(
PyObject_AsCharBuffer
(
arg
,
&
sub_ptr
,
&
sub_len
)))
return
-
1
;
#else
if
(
unlikely
(
PyObject_GetBuffer
(
self
,
&
view
,
PyBUF_SIMPLE
)
==
-
1
))
return
-
1
;
sub_ptr
=
(
const
char
*
)
view
.
buf
;
sub_len
=
view
.
len
;
#endif
}
if
(
end
>
self_len
)
end
=
self_len
;
else
if
(
end
<
0
)
end
+=
self_len
;
if
(
end
<
0
)
end
=
0
;
if
(
start
<
0
)
start
+=
self_len
;
if
(
start
<
0
)
start
=
0
;
if
(
direction
>
0
)
{
/* endswith */
if
(
end
-
sub_len
>
start
)
start
=
end
-
sub_len
;
}
if
(
start
+
sub_len
<=
end
)
retval
=
!
memcmp
(
self_ptr
+
start
,
sub_ptr
,
sub_len
);
else
retval
=
0
;
#if PY_VERSION_HEX >= 0x02060000
if
(
view
.
obj
)
PyBuffer_Release
(
&
view
);
#endif
return
retval
;
}
static
int
__Pyx_PyBytes_Tailmatch
(
PyObject
*
self
,
PyObject
*
substr
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
if
(
unlikely
(
PyTuple_Check
(
substr
)))
{
Py_ssize_t
i
,
count
=
PyTuple_GET_SIZE
(
substr
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
int
result
;
#if CYTHON_COMPILING_IN_CPYTHON
result
=
__Pyx_PyBytes_SingleTailmatch
(
self
,
PyTuple_GET_ITEM
(
substr
,
i
),
start
,
end
,
direction
);
#else
PyObject
*
sub
=
PySequence_GetItem
(
substr
,
i
);
if
(
unlikely
(
!
sub
))
return
-
1
;
result
=
__Pyx_PyBytes_SingleTailmatch
(
self
,
sub
,
start
,
end
,
direction
);
Py_DECREF
(
sub
);
#endif
if
(
result
)
{
return
result
;
}
}
return
0
;
}
return
__Pyx_PyBytes_SingleTailmatch
(
self
,
substr
,
start
,
end
,
direction
);
}
/////////////// str_tailmatch.proto ///////////////
static
CYTHON_INLINE
int
__Pyx_PyStr_Tailmatch
(
PyObject
*
self
,
PyObject
*
arg
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
);
/////////////// str_tailmatch ///////////////
//@requires: bytes_tailmatch
//@requires: unicode_tailmatch
static
CYTHON_INLINE
int
__Pyx_PyStr_Tailmatch
(
PyObject
*
self
,
PyObject
*
arg
,
Py_ssize_t
start
,
Py_ssize_t
end
,
int
direction
)
{
// We do not use a C compiler macro here to avoid "unused function"
// warnings for the *_Tailmatch() function that is not being used in
// the specific CPython version. The C compiler will generate the same
// code anyway, and will usually just remove the unused function.
if
(
PY_MAJOR_VERSION
<
3
)
return
__Pyx_PyBytes_Tailmatch
(
self
,
arg
,
start
,
end
,
direction
);
else
return
__Pyx_PyUnicode_Tailmatch
(
self
,
arg
,
start
,
end
,
direction
);
}
/////////////// bytes_index.proto ///////////////
static
CYTHON_INLINE
char
__Pyx_PyBytes_GetItemInt
(
PyObject
*
bytes
,
Py_ssize_t
index
,
int
check_bounds
)
{
if
(
check_bounds
)
{
Py_ssize_t
size
=
PyBytes_GET_SIZE
(
bytes
);
if
(
unlikely
(
index
>=
size
)
|
((
index
<
0
)
&
unlikely
(
index
<
-
size
)))
{
PyErr_Format
(
PyExc_IndexError
,
"string index out of range"
);
return
-
1
;
}
}
if
(
index
<
0
)
index
+=
PyBytes_GET_SIZE
(
bytes
);
return
PyBytes_AS_STRING
(
bytes
)[
index
];
}
docs/src/userguide/extension_types.rst
View file @
c73a9b2d
...
@@ -339,6 +339,7 @@ subtyped at the C level by foreign code.
...
@@ -339,6 +339,7 @@ subtyped at the C level by foreign code.
C methods
C methods
=========
=========
Extension types can have C methods as well as Python methods. Like C
Extension types can have C methods as well as Python methods. Like C
functions, C methods are declared using :keyword:`cdef` or :keyword:`cpdef` instead of
functions, C methods are declared using :keyword:`cdef` or :keyword:`cpdef` instead of
:keyword:`def`. C methods are "virtual", and may be overridden in derived
:keyword:`def`. C methods are "virtual", and may be overridden in derived
...
@@ -379,6 +380,7 @@ method using the usual Python technique, i.e.::
...
@@ -379,6 +380,7 @@ method using the usual Python technique, i.e.::
Parrot.describe(self)
Parrot.describe(self)
Forward-declaring extension types
Forward-declaring extension types
===================================
===================================
...
@@ -405,6 +407,52 @@ definition, for example,::
...
@@ -405,6 +407,52 @@ definition, for example,::
cdef class A(B):
cdef class A(B):
# attributes and methods
# attributes and methods
Fast instantiation
===================
Cython provides two ways to speed up the instantiation of extension types.
The first one is a direct call to the ``__new__()`` special static method,
as known from Python. For an extension type ``Penguin``, you could use
the following code::
cdef class Penguin:
cdef object food
def __cinit__(self, food):
self.food = food
def __init__(self, food):
print("eating!")
normal_penguin = Penguin('fish')
fast_penguin = Penguin.__new__(Penguin, 'wheat') # note: not calling __init__() !
Note that the path through ``__new__()`` will *not* call the type's
``__init__()`` method (again, as known from Python). Thus, in the example
above, the first instantiation will print ``eating!``, but the second will
not. This is only one of the reasons why the ``__cinit__()`` method is
safer and preferable over the normal ``__init__()`` method for extension
types.
The second performance improvement applies to types that are often created
and deleted in a row, so that they can benefit from a freelist. Cython
provides the decorator ``@cython.freelist(N)`` for this, which creates a
statically sized freelist of ``N`` instances for a given type. Example::
cimport cython
@cython.freelist(8)
cdef class Penguin:
cdef object food
def __cinit__(self, food):
self.food = food
penguin = Penguin('fish 1')
penguin = None
penguin = Penguin('fish 2') # does not need to allocate memory!
Making extension types weak-referenceable
Making extension types weak-referenceable
==========================================
==========================================
...
@@ -418,6 +466,7 @@ object called :attr:`__weakref__`. For example,::
...
@@ -418,6 +466,7 @@ object called :attr:`__weakref__`. For example,::
cdef object __weakref__
cdef object __weakref__
Public and external extension types
Public and external extension types
====================================
====================================
...
...
runtests.py
View file @
c73a9b2d
...
@@ -746,6 +746,7 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -746,6 +746,7 @@ class CythonRunTestCase(CythonCompileTestCase):
self.success = False
self.success = False
self.runCompileTest()
self.runCompileTest()
failures, errors = len(result.failures), len(result.errors)
failures, errors = len(result.failures), len(result.errors)
if not self.cython_only:
self.run_tests(result)
self.run_tests(result)
if failures == len(result.failures) and errors == len(result.errors):
if failures == len(result.failures) and errors == len(result.errors):
# No new errors...
# No new errors...
...
@@ -761,7 +762,6 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -761,7 +762,6 @@ class CythonRunTestCase(CythonCompileTestCase):
pass
pass
def run_tests(self, result):
def run_tests(self, result):
if not self.cython_only:
self.run_doctests(self.module, result)
self.run_doctests(self.module, result)
def run_doctests(self, module_name, result):
def run_doctests(self, module_name, result):
...
...
tests/errors/e_exttype_freelist.pyx
0 → 100644
View file @
c73a9b2d
# mode: error
# tag: freelist, werror
cimport
cython
@
cython
.
freelist
(
8
)
cdef
class
ExtType
:
pass
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeObject
(
object
):
pass
cdef
class
ExtSubTypeOk
(
ExtType
):
pass
@
cython
.
freelist
(
8
)
cdef
class
ExtSubTypeFail
(
ExtType
):
pass
_ERRORS
=
"""
18:5: freelists cannot be used on subtypes, only the base class can manage them
"""
tests/run/constant_folding.py
0 → 100644
View file @
c73a9b2d
# coding=utf8
# mode: run
# tag: constant_folding
import
cython
@
cython
.
test_fail_if_path_exists
(
"//UnaryMinusNode"
,
"//UnaryPlusNode"
,
)
def
unop_floats
():
"""
>>> unop_floats()
(False, 2.0, -2.0, False, 2.0, -2.0, -2.0)
"""
not1
=
not
2.0
plus1
=
+
2.0
minus1
=
-
2.0
not3
=
not
not
not
2.0
plus3
=
+++
2.0
minus3
=
---
2.0
mix
=
+-++--
2.0
return
not1
,
plus1
,
minus1
,
not3
,
plus3
,
minus3
,
mix
@
cython
.
test_fail_if_path_exists
(
"//UnaryMinusNode"
,
"//UnaryPlusNode"
,
)
def
unop_ints
():
"""
>>> unop_ints()
(False, 2, -2, False, 2, -2, -2)
"""
not1
=
not
2
plus1
=
+
2
minus1
=
-
2
not3
=
not
not
not
2
plus3
=
+++
2
minus3
=
---
2
mix
=
+-++--
2
return
not1
,
plus1
,
minus1
,
not3
,
plus3
,
minus3
,
mix
@
cython
.
test_fail_if_path_exists
(
"//UnaryMinusNode"
,
"//UnaryPlusNode"
,
"//NotNode"
,
)
def
unop_bool
():
"""
>>> unop_bool()
(False, 1, -1, False, 1, -1, -1)
"""
not1
=
not
True
plus1
=
+
True
minus1
=
-
True
not3
=
not
not
not
True
plus3
=
+++
True
minus3
=
---
True
mix
=
+-++--
True
return
not1
,
plus1
,
minus1
,
not3
,
plus3
,
minus3
,
mix
@
cython
.
test_fail_if_path_exists
(
"//AddNode"
,
"//SubNode"
,
)
def
binop_bool
():
"""
>>> binop_bool()
(2, 1, 0, True, True, 1, False, 2, 2, -2, False, True, 1, False)
"""
plus1
=
True
+
True
pmix1
=
True
+
0
minus1
=
True
-
True
and1
=
True
&
True
or1
=
True
|
True
ormix1
=
True
|
0
xor1
=
True
^
True
plus3
=
False
+
True
+
False
+
True
pmix3
=
False
+
True
+
0
+
True
minus3
=
False
-
True
-
False
-
True
and3
=
False
&
True
&
False
&
True
or3
=
False
|
True
|
False
|
True
ormix3
=
False
|
0
|
False
|
True
xor3
=
False
^
True
^
False
^
True
return
plus1
,
pmix1
,
minus1
,
and1
,
or1
,
ormix1
,
xor1
,
plus3
,
pmix3
,
minus3
,
and3
,
or3
,
ormix3
,
xor3
@
cython
.
test_fail_if_path_exists
(
"//SliceIndexNode"
,
)
def
slicing2
():
"""
>>> slicing2()
([1, 2, 3, 4], [3, 4], [1, 2, 3, 4], [3, 4], (1, 2, 3, 4), (3, 4), (1, 2, 3, 4), (3, 4))
"""
lst0
=
[
1
,
2
,
3
,
4
][:]
lst1
=
[
1
,
2
,
3
,
4
][
2
:]
lst2
=
[
1
,
2
,
3
,
4
][:
4
]
lst3
=
[
1
,
2
,
3
,
4
][
2
:
4
]
tpl0
=
(
1
,
2
,
3
,
4
)[:]
tpl1
=
(
1
,
2
,
3
,
4
)[
2
:]
tpl2
=
(
1
,
2
,
3
,
4
)[:
4
]
tpl3
=
(
1
,
2
,
3
,
4
)[
2
:
4
]
return
lst0
,
lst1
,
lst2
,
lst3
,
tpl0
,
tpl1
,
tpl2
,
tpl3
@
cython
.
test_fail_if_path_exists
(
"//SliceIndexNode"
,
)
def
str_slicing2
():
"""
>>> a,b,c,d = str_slicing2()
>>> a == 'abc
\
\
xE9def'[:]
True
>>> b == 'abc
\
\
xE9def'[2:]
True
>>> c == 'abc
\
\
xE9def'[:4]
True
>>> d == 'abc
\
\
xE9def'[2:4]
True
"""
str0
=
'abc
\
xE9
def'
[:]
str1
=
'abc
\
xE9
def'
[
2
:]
str2
=
'abc
\
xE9
def'
[:
4
]
str3
=
'abc
\
xE9
def'
[
2
:
4
]
return
str0
,
str1
,
str2
,
str3
tests/run/constant_folding_cy.pyx
0 → 100644
View file @
c73a9b2d
# coding=utf8
# mode: run
# tag: constant_folding
cimport
cython
bstring
=
b'abc
\
xE9
def'
ustring
=
u'abc
\
xE9
def'
surrogates_ustring
=
u'abc
\
U00010000
def'
@
cython
.
test_fail_if_path_exists
(
"//SliceIndexNode"
,
)
def
bytes_slicing2
():
"""
>>> a,b,c,d = bytes_slicing2()
>>> a == bstring[:]
True
>>> b == bstring[2:]
True
>>> c == bstring[:4]
True
>>> d == bstring[2:4]
True
"""
str0
=
b'abc
\
xE9
def'
[:]
str1
=
b'abc
\
xE9
def'
[
2
:]
str2
=
b'abc
\
xE9
def'
[:
4
]
str3
=
b'abc
\
xE9
def'
[
2
:
4
]
return
str0
,
str1
,
str2
,
str3
@
cython
.
test_fail_if_path_exists
(
"//SliceIndexNode"
,
)
def
unicode_slicing2
():
"""
>>> a,b,c,d = unicode_slicing2()
>>> a == ustring[:]
True
>>> b == ustring[2:]
True
>>> c == ustring[:4]
True
>>> d == ustring[2:4]
True
"""
str0
=
u'abc
\
xE9
def'
[:]
str1
=
u'abc
\
xE9
def'
[
2
:]
str2
=
u'abc
\
xE9
def'
[:
4
]
str3
=
u'abc
\
xE9
def'
[
2
:
4
]
return
str0
,
str1
,
str2
,
str3
@
cython
.
test_assert_path_exists
(
"//SliceIndexNode"
,
)
def
unicode_slicing_unsafe_surrogates2
():
"""
>>> unicode_slicing_unsafe_surrogates2() == surrogates_ustring[2:]
True
"""
ustring
=
u'abc
\
U00010000
def'
[
2
:]
return
ustring
@
cython
.
test_fail_if_path_exists
(
"//SliceIndexNode"
,
)
def
unicode_slicing_safe_surrogates2
():
"""
>>> unicode_slicing_safe_surrogates2() == surrogates_ustring[:2]
True
>>> print(unicode_slicing_safe_surrogates2())
ab
"""
ustring
=
u'abc
\
U00010000
def'
[:
2
]
return
ustring
tests/run/ct_DEF.pyx
View file @
c73a9b2d
...
@@ -29,8 +29,10 @@ DEF TRUE = TRUE_FALSE[0]
...
@@ -29,8 +29,10 @@ DEF TRUE = TRUE_FALSE[0]
DEF
FALSE
=
TRUE_FALSE
[
1
]
DEF
FALSE
=
TRUE_FALSE
[
1
]
DEF
INT_TUPLE1
=
TUPLE
[:
2
]
DEF
INT_TUPLE1
=
TUPLE
[:
2
]
DEF
INT_TUPLE2
=
TUPLE
[
1
:
4
:
2
]
DEF
INT_TUPLE2
=
TUPLE
[
1
:
4
:
2
]
DEF
ELLIPSIS
=
...
DEF
EXPRESSION
=
int
(
float
(
2
*
2
))
+
int
(
str
(
2
))
+
int
(
max
(
1
,
2
,
3
))
+
sum
([
TWO
,
FIVE
])
DEF
EXPRESSION
=
int
(
float
(
2
*
2
))
+
int
(
str
(
2
))
+
int
(
max
(
1
,
2
,
3
))
+
sum
([
TWO
,
FIVE
])
def
c
():
def
c
():
"""
"""
>>> c()
>>> c()
...
@@ -148,6 +150,13 @@ def false():
...
@@ -148,6 +150,13 @@ def false():
cdef
bint
false
=
FALSE
cdef
bint
false
=
FALSE
return
false
return
false
def
ellipsis
():
"""
>>> ellipsis()
Ellipsis
"""
return
ELLIPSIS
@
cython
.
test_assert_path_exists
(
'//IntNode'
)
@
cython
.
test_assert_path_exists
(
'//IntNode'
)
@
cython
.
test_fail_if_path_exists
(
'//AddNode'
)
@
cython
.
test_fail_if_path_exists
(
'//AddNode'
)
def
expression
():
def
expression
():
...
...
tests/run/exttype_freelist.pyx
0 → 100644
View file @
c73a9b2d
# mode: run
# tag: freelist
cimport
cython
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeNoGC
:
"""
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
>>> obj = ExtTypeNoGC()
"""
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeWithGC
:
"""
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
>>> obj = ExtTypeWithGC()
"""
cdef
attribute
def
__init__
(
self
):
self
.
attribute
=
object
()
def
tpnew_ExtTypeWithGC
():
"""
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
>>> obj = tpnew_ExtTypeWithGC()
"""
return
ExtTypeWithGC
.
__new__
(
ExtTypeWithGC
)
cdef
class
ExtSubType
(
ExtTypeWithGC
):
"""
>>> obj = ExtSubType()
>>> obj = ExtSubType()
>>> obj = ExtSubType()
>>> obj = ExtSubType()
>>> obj = ExtSubType()
>>> obj = ExtSubType()
"""
cdef
class
LargerExtSubType
(
ExtSubType
):
"""
>>> obj = LargerExtSubType()
>>> obj = LargerExtSubType()
>>> obj = LargerExtSubType()
>>> obj = LargerExtSubType()
>>> obj = LargerExtSubType()
>>> obj = LargerExtSubType()
"""
cdef
attribute2
def
__cinit__
(
self
):
self
.
attribute2
=
object
()
@
cython
.
freelist
(
8
)
cdef
class
ExtTypeWithRefCycle
:
"""
>>> obj = first = ExtTypeWithRefCycle()
>>> obj.attribute is None
True
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj.attribute is first
True
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj = ExtTypeWithRefCycle(obj)
>>> obj.attribute is not None
True
>>> first.attribute = obj
>>> del obj, first
"""
cdef
public
attribute
def
__init__
(
self
,
obj
=
None
):
self
.
attribute
=
obj
tests/run/tp_new.pyx
View file @
c73a9b2d
...
@@ -2,28 +2,32 @@
...
@@ -2,28 +2,32 @@
cimport
cython
cimport
cython
cdef
class
MyType
:
cdef
class
MyType
:
def
__cinit__
(
self
):
cdef
public
args
,
kwargs
def
__cinit__
(
self
,
*
args
,
**
kwargs
):
self
.
args
,
self
.
kwargs
=
args
,
kwargs
print
"CINIT"
print
"CINIT"
def
__init__
(
self
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
print
"INIT"
print
"INIT"
cdef
class
MySubType
(
MyType
):
cdef
class
MySubType
(
MyType
):
def
__cinit__
(
self
):
def
__cinit__
(
self
,
*
args
,
**
kwargs
):
self
.
args
,
self
.
kwargs
=
args
,
kwargs
print
"CINIT(SUB)"
print
"CINIT(SUB)"
def
__init__
(
self
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
print
"INIT"
print
"INIT"
class
MyClass
(
object
):
class
MyClass
(
object
):
def
__cinit__
(
self
):
def
__cinit__
(
self
,
*
args
,
**
kwargs
):
self
.
args
,
self
.
kwargs
=
args
,
kwargs
print
"CINIT"
print
"CINIT"
def
__init__
(
self
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
print
"INIT"
print
"INIT"
class
MyTypeSubClass
(
MyType
):
class
MyTypeSubClass
(
MyType
):
def
__cinit__
(
self
):
def
__cinit__
(
self
,
*
args
,
**
kwargs
):
# not called: Python class!
# not called: Python class!
print
"CINIT(PYSUB)"
print
"CINIT(PYSUB)"
def
__init__
(
self
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
print
"INIT"
print
"INIT"
# only these can be safely optimised:
# only these can be safely optimised:
...
@@ -51,6 +55,36 @@ def make_new_typed_target():
...
@@ -51,6 +55,36 @@ def make_new_typed_target():
m
=
MyType
.
__new__
(
MyType
)
m
=
MyType
.
__new__
(
MyType
)
return
m
return
m
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new_with_args
():
"""
>>> isinstance(make_new_with_args(), MyType)
CINIT
(1, 2, 3)
{}
True
"""
m
=
MyType
.
__new__
(
MyType
,
1
,
2
,
3
)
print
m
.
args
print
m
.
kwargs
return
m
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new_with_args_kwargs
():
"""
>>> isinstance(make_new_with_args_kwargs(), MyType)
CINIT
(1, 2, 3)
{'a': 4}
True
"""
m
=
MyType
.
__new__
(
MyType
,
1
,
2
,
3
,
a
=
4
)
print
m
.
args
print
m
.
kwargs
return
m
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new_builtin
():
def
make_new_builtin
():
...
...
tests/run/tp_new_cimport.srctree
0 → 100644
View file @
c73a9b2d
PYTHON setup.py build_ext --inplace
PYTHON -c "import tp_new_tests; tp_new_tests.test_all()"
PYTHON -c "import tp_new_tests; tp_new_tests.test_sub()"
######## setup.py ########
from Cython.Build.Dependencies import cythonize
from distutils.core import setup
setup(
ext_modules = cythonize("**/*.pyx"),
)
######## tp_new_tests.py ########
def test_all():
test_a()
test_b()
test_a_in_b()
test_sub()
def test_a():
import a
assert isinstance(a.tpnew_ExtTypeA(), a.ExtTypeA)
assert a.tpnew_ExtTypeA().attrA == 123
def test_b():
import b
assert isinstance(b.tpnew_ExtTypeB(), b.ExtTypeB)
assert b.tpnew_ExtTypeB().attrB == 234
def test_a_in_b():
import a,b
assert isinstance(b.tpnew_ExtTypeA(), a.ExtTypeA)
assert b.tpnew_ExtTypeA().attrA == 123
def test_sub():
import b
assert isinstance(b.tpnew_SubExtTypeA(), b.SubExtTypeA)
assert b.tpnew_SubExtTypeA().attrAB == 345
assert b.tpnew_SubExtTypeA().attrA == 123
######## a.pxd ########
cdef class ExtTypeA:
cdef readonly attrA
######## a.pyx ########
cdef class ExtTypeA:
def __cinit__(self):
self.attrA = 123
def tpnew_ExtTypeA():
return ExtTypeA.__new__(ExtTypeA)
######## b.pxd ########
from a cimport ExtTypeA
cdef class ExtTypeB:
cdef readonly attrB
cdef class SubExtTypeA(ExtTypeA):
cdef readonly attrAB
######## b.pyx ########
from a cimport ExtTypeA
cdef class ExtTypeB:
def __cinit__(self):
self.attrB = 234
cdef class SubExtTypeA(ExtTypeA):
def __cinit__(self):
self.attrAB = 345
def tpnew_ExtTypeA():
return ExtTypeA.__new__(ExtTypeA)
def tpnew_ExtTypeB():
return ExtTypeB.__new__(ExtTypeB)
def tpnew_SubExtTypeA():
return SubExtTypeA.__new__(SubExtTypeA)
tests/run/unbound_special_methods.pyx
0 → 100644
View file @
c73a9b2d
# mode: run
# tag: special_method
cimport
cython
text
=
u'ab jd sdflk as sa sadas asdas fsdf '
@
cython
.
test_fail_if_path_exists
(
"//CoerceFromPyTypeNode"
)
@
cython
.
test_assert_path_exists
(
"//CoerceToPyTypeNode"
,
"//AttributeNode"
,
"//AttributeNode[@entry.cname = 'PyUnicode_Contains']"
)
def
unicode_contains
(
unicode
s
,
substring
):
"""
>>> unicode_contains(text, 'fl')
True
>>> unicode_contains(text, 'XYZ')
False
>>> unicode_contains(None, 'XYZ')
Traceback (most recent call last):
AttributeError: 'NoneType' object has no attribute '__contains__'
"""
return
s
.
__contains__
(
substring
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceFromPyTypeNode"
)
@
cython
.
test_assert_path_exists
(
# "//CoerceToPyTypeNode",
"//NameNode[@entry.cname = 'PyUnicode_Contains']"
)
def
unicode_contains_unbound
(
unicode
s
,
substring
):
"""
>>> unicode_contains_unbound(text, 'fl')
True
>>> unicode_contains_unbound(text, 'XYZ')
False
>>> unicode_contains_unbound(None, 'XYZ') # doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: descriptor '__contains__' requires a '...' object but received a 'NoneType'
"""
return
unicode
.
__contains__
(
s
,
substring
)
cdef
class
UnicodeSubclass
(
unicode
):
"""
>>> u = UnicodeSubclass(text)
>>> 'fl' in u
False
>>> 'XYZ' in u
True
>>> u.method('fl')
False
>>> u.method('XYZ')
True
>>> u.operator('fl')
False
>>> u.operator('XYZ')
True
"""
def
__contains__
(
self
,
substring
):
return
substring
not
in
(
self
+
u'x'
)
def
method
(
self
,
other
):
return
self
.
__contains__
(
other
)
def
operator
(
self
,
other
):
return
other
in
self
tests/run/unicode_slicing.pyx
View file @
c73a9b2d
# coding: utf-8
# coding: utf-8
__doc__
=
u"""
__doc__
=
u"""
>>>
do_slice1
(u'abcdef', 2, 3)
>>>
slice_start_end
(u'abcdef', 2, 3)
c
c
>>>
do_slice2
(u'abcdef', 2, 3)
>>>
slice_start
(u'abcdef', 2, 3)
cdef
cdef
>>>
do_slice3
(u'abcdef', 2, 3)
>>>
slice_end
(u'abcdef', 2, 3)
ab
ab
>>>
do_slice4
(u'abcdef', 2, 3)
>>>
slice_all
(u'abcdef', 2, 3)
abcdef
abcdef
>>>
do_slice5
(u'abcdef', 2, 3)
>>>
slice_start_none
(u'abcdef', 2, 3)
cdef
cdef
>>>
do_slice6
(u'abcdef', 2, 3)
>>>
slice_none_end
(u'abcdef', 2, 3)
ab
ab
>>>
do_slice7
(u'abcdef', 2, 3)
>>>
slice_none_none
(u'abcdef', 2, 3)
abcdef
abcdef
>>> do_slice1(u'abcdef', 2, 10)
>>> slice_start_end(u'abcdef', 2, 10)
cdef
cdef
>>>
do_slice2
(u'abcdef', 2, 10)
>>>
slice_start
(u'abcdef', 2, 10)
cdef
cdef
>>>
do_slice3
(u'abcdef', 2, 10)
>>>
slice_end
(u'abcdef', 2, 10)
ab
ab
>>>
do_slice4
(u'abcdef', 2, 10)
>>>
slice_all
(u'abcdef', 2, 10)
abcdef
abcdef
>>> do_slice1(u'abcdef', 0, 5)
>>> slice_start_end(u'abcdef', 0, 5)
abcde
abcde
>>>
do_slice2
(u'abcdef', 0, 5)
>>>
slice_start
(u'abcdef', 0, 5)
abcdef
abcdef
>>>
do_slice3
(u'abcdef', 0, 5)
>>>
slice_end
(u'abcdef', 0, 5)
<BLANKLINE>
<BLANKLINE>
>>>
do_slice4
(u'abcdef', 0, 5)
>>>
slice_all
(u'abcdef', 0, 5)
abcdef
abcdef
>>>
do_slice5
(u'abcdef', 0, 5)
>>>
slice_start_none
(u'abcdef', 0, 5)
abcdef
abcdef
>>>
do_slice6
(u'abcdef', 0, 5)
>>>
slice_none_end
(u'abcdef', 0, 5)
<BLANKLINE>
<BLANKLINE>
>>>
do_slice7
(u'abcdef', 0, 5)
>>>
slice_none_none
(u'abcdef', 0, 5)
abcdef
abcdef
>>> do_slice1(u'abcdef', -6, -1)
>>> slice_start_end(u'abcdef', -6, -1)
abcde
abcde
>>> do_slice2(u'abcdef', -6, -1)
>>> slice_start(u'abcdef', -6, -1)
abcdef
>>> slice_end(u'abcdef', -6, -1)
<BLANKLINE>
>>> slice_all(u'abcdef', -6, -1)
abcdef
>>> slice_start_none(u'abcdef', -6, -1)
abcdef
abcdef
>>>
do_slice3
(u'abcdef', -6, -1)
>>>
slice_none_end
(u'abcdef', -6, -1)
<BLANKLINE>
<BLANKLINE>
>>>
do_slice4
(u'abcdef', -6, -1)
>>>
slice_none_none
(u'abcdef', -6, -1)
abcdef
abcdef
>>> do_slice5(u'abcdef', -6, -1)
>>> slice_start_end(u'abcdef', -6, -7)
<BLANKLINE>
>>> slice_start(u'abcdef', -6, -7)
abcdef
>>> slice_end(u'abcdef', -6, -7)
<BLANKLINE>
>>> slice_all(u'abcdef', -6, -7)
abcdef
>>> slice_start_none(u'abcdef', -6, -7)
abcdef
abcdef
>>>
do_slice6(u'abcdef', -6, -1
)
>>>
slice_none_end(u'abcdef', -6, -7
)
<BLANKLINE>
<BLANKLINE>
>>>
do_slice7(u'abcdef', -6, -1
)
>>>
slice_none_none(u'abcdef', -6, -7
)
abcdef
abcdef
>>> do_slice1(u'aАbБcСdДeЕfФ', 2, 8)
>>> slice_start_end(u'abcdef', -7, -7)
<BLANKLINE>
>>> slice_start(u'abcdef', -7, -7)
abcdef
>>> slice_end(u'abcdef', -7, -7)
<BLANKLINE>
>>> slice_all(u'abcdef', -7, -7)
abcdef
>>> slice_start_none(u'abcdef', -7, -7)
abcdef
>>> slice_none_end(u'abcdef', -7, -7)
<BLANKLINE>
>>> slice_none_none(u'abcdef', -7, -7)
abcdef
>>> slice_start_end(u'aАbБcСdДeЕfФ', 2, 8)
bБcСdД
bБcСdД
>>>
do_slice2
(u'aАbБcСdДeЕfФ', 2, 8)
>>>
slice_start
(u'aАbБcСdДeЕfФ', 2, 8)
bБcСdДeЕfФ
bБcСdДeЕfФ
>>>
do_slice3
(u'aАbБcСdДeЕfФ', 2, 8)
>>>
slice_end
(u'aАbБcСdДeЕfФ', 2, 8)
aА
aА
>>>
do_slice4
(u'aАbБcСdДeЕfФ', 2, 8)
>>>
slice_all
(u'aАbБcСdДeЕfФ', 2, 8)
aАbБcСdДeЕfФ
aАbБcСdДeЕfФ
>>>
do_slice5
(u'aАbБcСdДeЕfФ', 2, 8)
>>>
slice_start_none
(u'aАbБcСdДeЕfФ', 2, 8)
bБcСdДeЕfФ
bБcСdДeЕfФ
>>>
do_slice6
(u'aАbБcСdДeЕfФ', 2, 8)
>>>
slice_none_end
(u'aАbБcСdДeЕfФ', 2, 8)
aА
aА
>>>
do_slice7
(u'aАbБcСdДeЕfФ', 2, 8)
>>>
slice_none_none
(u'aАbБcСdДeЕfФ', 2, 8)
aАbБcСdДeЕfФ
aАbБcСdДeЕfФ
>>> do_slice1(u'АБСДЕФ', 2, 4)
>>> slice_start_end(u'АБСДЕФ', 2, 4)
СД
СД
>>>
do_slice2
(u'АБСДЕФ', 2, 4)
>>>
slice_start
(u'АБСДЕФ', 2, 4)
СДЕФ
СДЕФ
>>>
do_slice3
(u'АБСДЕФ', 2, 4)
>>>
slice_end
(u'АБСДЕФ', 2, 4)
АБ
АБ
>>>
do_slice4
(u'АБСДЕФ', 2, 4)
>>>
slice_all
(u'АБСДЕФ', 2, 4)
АБСДЕФ
АБСДЕФ
>>>
do_slice5
(u'АБСДЕФ', 2, 4)
>>>
slice_start_none
(u'АБСДЕФ', 2, 4)
СДЕФ
СДЕФ
>>>
do_slice6
(u'АБСДЕФ', 2, 4)
>>>
slice_none_end
(u'АБСДЕФ', 2, 4)
АБ
АБ
>>>
do_slice7
(u'АБСДЕФ', 2, 4)
>>>
slice_none_none
(u'АБСДЕФ', 2, 4)
АБСДЕФ
АБСДЕФ
>>> do_slice1(u'АБСДЕФ', -4, -2)
>>> slice_start_end(u'АБСДЕФ', -4, -2)
СД
СД
>>>
do_slice2
(u'АБСДЕФ', -4, -2)
>>>
slice_start
(u'АБСДЕФ', -4, -2)
СДЕФ
СДЕФ
>>>
do_slice3
(u'АБСДЕФ', -4, -2)
>>>
slice_end
(u'АБСДЕФ', -4, -2)
АБ
АБ
>>>
do_slice4
(u'АБСДЕФ', -4, -2)
>>>
slice_all
(u'АБСДЕФ', -4, -2)
АБСДЕФ
АБСДЕФ
>>>
do_slice5
(u'АБСДЕФ', -4, -2)
>>>
slice_start_none
(u'АБСДЕФ', -4, -2)
СДЕФ
СДЕФ
>>>
do_slice6
(u'АБСДЕФ', -4, -2)
>>>
slice_none_end
(u'АБСДЕФ', -4, -2)
АБ
АБ
>>>
do_slice7
(u'АБСДЕФ', -4, -2)
>>>
slice_none_none
(u'АБСДЕФ', -4, -2)
АБСДЕФ
АБСДЕФ
>>> do_slice1(None, 2, 4)
>>> slice_start_end(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
>>>
do_slice2
(None, 2, 4)
>>>
slice_start
(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
>>>
do_slice3
(None, 2, 4)
>>>
slice_end
(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
>>>
do_slice4
(None, 2, 4)
>>>
slice_all
(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
>>>
do_slice5
(None, 2, 4)
>>>
slice_start_none
(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
>>>
do_slice6
(None, 2, 4)
>>>
slice_none_end
(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
>>>
do_slice7
(None, 2, 4)
>>>
slice_none_none
(None, 2, 4)
Traceback (most recent call last):
Traceback (most recent call last):
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
"""
"""
...
@@ -121,23 +158,23 @@ import sys
...
@@ -121,23 +158,23 @@ import sys
if
sys
.
version_info
[
0
]
>=
3
:
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u"(u'"
,
u"('"
).
replace
(
u" u'"
,
u" '"
)
__doc__
=
__doc__
.
replace
(
u"(u'"
,
u"('"
).
replace
(
u" u'"
,
u" '"
)
def
do_slice1
(
unicode
s
,
int
i
,
int
j
):
def
slice_start_end
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[
i
:
j
])
print
(
s
[
i
:
j
])
def
do_slice2
(
unicode
s
,
int
i
,
int
j
):
def
slice_start
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[
i
:])
print
(
s
[
i
:])
def
do_slice3
(
unicode
s
,
int
i
,
int
j
):
def
slice_end
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[:
i
])
print
(
s
[:
i
])
def
do_slice4
(
unicode
s
,
int
i
,
int
j
):
def
slice_all
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[:])
print
(
s
[:])
def
do_slice5
(
unicode
s
,
int
i
,
int
j
):
def
slice_start_none
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[
i
:
None
])
print
(
s
[
i
:
None
])
def
do_slice6
(
unicode
s
,
int
i
,
int
j
):
def
slice_none_end
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[
None
:
i
])
print
(
s
[
None
:
i
])
def
do_slice7
(
unicode
s
,
int
i
,
int
j
):
def
slice_none_none
(
unicode
s
,
int
i
,
int
j
):
print
(
s
[
None
:
None
])
print
(
s
[
None
:
None
])
tests/run/unicodemethods.pyx
View file @
c73a9b2d
...
@@ -364,6 +364,25 @@ def endswith_start_end(unicode s, sub, start, end):
...
@@ -364,6 +364,25 @@ def endswith_start_end(unicode s, sub, start, end):
return
'NO MATCH'
return
'NO MATCH'
# unicode.__contains__(s, sub)
@
cython
.
test_fail_if_path_exists
(
"//CoerceFromPyTypeNode"
,
"//AttributeNode"
)
@
cython
.
test_assert_path_exists
(
"//CoerceToPyTypeNode"
,
"//PrimaryCmpNode"
)
def
in_test
(
unicode
s
,
substring
):
"""
>>> in_test(text, 'sa')
True
>>> in_test(text, 'XYZ')
False
>>> in_test(None, 'sa')
Traceback (most recent call last):
TypeError: 'NoneType' object is not iterable
"""
return
substring
in
s
# unicode.find(s, sub, [start, [end]])
# unicode.find(s, sub, [start, [end]])
@
cython
.
test_fail_if_path_exists
(
@
cython
.
test_fail_if_path_exists
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment