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
Hide 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
...
@@ -247,14 +247,7 @@ class ExprNode(Node):
...
@@ -247,14 +247,7 @@ class ExprNode(Node):
# whether this node with a memoryview type should be broadcast
# whether this node with a memoryview type should be broadcast
memslice_broadcast
=
False
memslice_broadcast
=
False
try
:
child_attrs
=
property
(
fget
=
operator
.
attrgetter
(
'subexprs'
))
_get_child_attrs
=
operator
.
attrgetter
(
'subexprs'
)
except
AttributeError
:
# Python 2.3
def
__get_child_attrs
(
self
):
return
self
.
subexprs
_get_child_attrs
=
__get_child_attrs
child_attrs
=
property
(
fget
=
_get_child_attrs
)
def
not_implemented
(
self
,
method_name
):
def
not_implemented
(
self
,
method_name
):
print_call_chain
(
method_name
,
"not implemented"
)
###
print_call_chain
(
method_name
,
"not implemented"
)
###
...
@@ -304,8 +297,6 @@ class ExprNode(Node):
...
@@ -304,8 +297,6 @@ class ExprNode(Node):
return
typecast
(
type
,
py_object_type
,
self
.
result
())
return
typecast
(
type
,
py_object_type
,
self
.
result
())
return
typecast
(
type
,
self
.
ctype
(),
self
.
result
())
return
typecast
(
type
,
self
.
ctype
(),
self
.
result
())
return
typecast
(
type
,
self
.
ctype
(),
self
.
result
())
def
py_result
(
self
):
def
py_result
(
self
):
# Return the result code cast to PyObject *.
# Return the result code cast to PyObject *.
return
self
.
result_as
(
py_object_type
)
return
self
.
result_as
(
py_object_type
)
...
@@ -434,7 +425,7 @@ class ExprNode(Node):
...
@@ -434,7 +425,7 @@ class ExprNode(Node):
def
analyse_as_extension_type
(
self
,
env
):
def
analyse_as_extension_type
(
self
,
env
):
# If this node can be interpreted as a reference to an
# If this node can be interpreted as a reference to an
# extension type, return its type, else None.
# extension type
or builtin type
, return its type, else None.
return
None
return
None
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
):
...
@@ -806,6 +797,23 @@ class ExprNode(Node):
...
@@ -806,6 +797,23 @@ class ExprNode(Node):
else
:
else
:
return
self
return
self
@
classmethod
def
from_node
(
cls
,
node
,
**
kwargs
):
"""Instantiate this node class from another node, properly
copying over all attributes that one would forget otherwise.
"""
attributes
=
"cf_state cf_maybe_null cf_is_null"
.
split
()
for
attr_name
in
attributes
:
if
attr_name
in
kwargs
:
continue
try
:
value
=
getattr
(
node
,
attr_name
)
except
AttributeError
:
pass
else
:
kwargs
[
attr_name
]
=
value
return
cls
(
node
.
pos
,
**
kwargs
)
class
AtomicExprNode
(
ExprNode
):
class
AtomicExprNode
(
ExprNode
):
# Abstract base class for expression nodes which have
# Abstract base class for expression nodes which have
...
@@ -1083,6 +1091,15 @@ class BytesNode(ConstNode):
...
@@ -1083,6 +1091,15 @@ class BytesNode(ConstNode):
# start off as Python 'bytes' to support len() in O(1)
# start off as Python 'bytes' to support len() in O(1)
type
=
bytes_type
type
=
bytes_type
def
calculate_constant_result
(
self
):
self
.
constant_result
=
self
.
value
def
as_sliced_node
(
self
,
start
,
stop
,
step
=
None
):
value
=
StringEncoding
.
BytesLiteral
(
self
.
value
[
start
:
stop
:
step
])
value
.
encoding
=
self
.
value
.
encoding
return
BytesNode
(
self
.
pos
,
value
=
value
,
constant_result
=
value
)
def
compile_time_value
(
self
,
denv
):
def
compile_time_value
(
self
,
denv
):
return
self
.
value
return
self
.
value
...
@@ -1164,6 +1181,25 @@ class UnicodeNode(PyConstNode):
...
@@ -1164,6 +1181,25 @@ class UnicodeNode(PyConstNode):
bytes_value
=
None
bytes_value
=
None
type
=
unicode_type
type
=
unicode_type
def
calculate_constant_result
(
self
):
self
.
constant_result
=
self
.
value
def
as_sliced_node
(
self
,
start
,
stop
,
step
=
None
):
if
_string_contains_surrogates
(
self
.
value
[:
stop
]):
# this is unsafe as it may give different results in different runtimes
return
None
value
=
StringEncoding
.
EncodedString
(
self
.
value
[
start
:
stop
:
step
])
value
.
encoding
=
self
.
value
.
encoding
if
self
.
bytes_value
is
not
None
:
bytes_value
=
StringEncoding
.
BytesLiteral
(
self
.
bytes_value
[
start
:
stop
:
step
])
bytes_value
.
encoding
=
self
.
bytes_value
.
encoding
else
:
bytes_value
=
None
return
UnicodeNode
(
self
.
pos
,
value
=
value
,
bytes_value
=
bytes_value
,
constant_result
=
value
)
def
coerce_to
(
self
,
dst_type
,
env
):
def
coerce_to
(
self
,
dst_type
,
env
):
if
dst_type
is
self
.
type
:
if
dst_type
is
self
.
type
:
pass
pass
...
@@ -1190,21 +1226,7 @@ class UnicodeNode(PyConstNode):
...
@@ -1190,21 +1226,7 @@ class UnicodeNode(PyConstNode):
## and (0xDC00 <= self.value[1] <= 0xDFFF))
## and (0xDC00 <= self.value[1] <= 0xDFFF))
def
contains_surrogates
(
self
):
def
contains_surrogates
(
self
):
# Check if the unicode string contains surrogate code points
return
_string_contains_surrogates
(
self
.
value
)
# on a CPython platform with wide (UCS-4) or narrow (UTF-16)
# Unicode, i.e. characters that would be spelled as two
# separate code units on a narrow platform.
for
c
in
map
(
ord
,
self
.
value
):
if
c
>
65535
:
# can only happen on wide platforms
return
True
# We only look for the first code unit (D800-DBFF) of a
# surrogate pair - if we find one, the other one
# (DC00-DFFF) is likely there, too. If we don't find it,
# any second code unit cannot make for a surrogate pair by
# itself.
if
0xD800
<=
c
<=
0xDBFF
:
return
True
return
False
def
generate_evaluation_code
(
self
,
code
):
def
generate_evaluation_code
(
self
,
code
):
self
.
result_code
=
code
.
get_py_string_const
(
self
.
value
)
self
.
result_code
=
code
.
get_py_string_const
(
self
.
value
)
...
@@ -1229,6 +1251,24 @@ class StringNode(PyConstNode):
...
@@ -1229,6 +1251,24 @@ class StringNode(PyConstNode):
is_identifier
=
None
is_identifier
=
None
unicode_value
=
None
unicode_value
=
None
def
calculate_constant_result
(
self
):
self
.
constant_result
=
self
.
value
def
as_sliced_node
(
self
,
start
,
stop
,
step
=
None
):
value
=
type
(
self
.
value
)(
self
.
value
[
start
:
stop
:
step
])
value
.
encoding
=
self
.
value
.
encoding
if
self
.
unicode_value
is
not
None
:
if
_string_contains_surrogates
(
self
.
unicode_value
[:
stop
]):
# this is unsafe as it may give different results in different runtimes
return
None
unicode_value
=
StringEncoding
.
EncodedString
(
self
.
unicode_value
[
start
:
stop
:
step
])
else
:
unicode_value
=
None
return
StringNode
(
self
.
pos
,
value
=
value
,
unicode_value
=
unicode_value
,
constant_result
=
value
,
is_identifier
=
self
.
is_identifier
)
def
coerce_to
(
self
,
dst_type
,
env
):
def
coerce_to
(
self
,
dst_type
,
env
):
if
dst_type
is
not
py_object_type
and
not
str_type
.
subtype_of
(
dst_type
):
if
dst_type
is
not
py_object_type
and
not
str_type
.
subtype_of
(
dst_type
):
# if dst_type is Builtin.bytes_type:
# if dst_type is Builtin.bytes_type:
...
@@ -1263,35 +1303,24 @@ class IdentifierStringNode(StringNode):
...
@@ -1263,35 +1303,24 @@ class IdentifierStringNode(StringNode):
is_identifier
=
True
is_identifier
=
True
class
LongNode
(
AtomicExprNode
):
def
_string_contains_surrogates
(
ustring
):
# Python long integer literal
"""
#
Check if the unicode string contains surrogate code points
# value string
on a CPython platform with wide (UCS-4) or narrow (UTF-16)
Unicode, i.e. characters that would be spelled as two
type
=
py_object_type
separate code units on a narrow platform.
"""
def
calculate_constant_result
(
self
):
for
c
in
map
(
ord
,
ustring
):
self
.
constant_result
=
Utils
.
str_to_number
(
self
.
value
)
if
c
>
65535
:
# can only happen on wide platforms
return
True
def
compile_time_value
(
self
,
denv
):
# We only look for the first code unit (D800-DBFF) of a
return
Utils
.
str_to_number
(
self
.
value
)
# surrogate pair - if we find one, the other one
# (DC00-DFFF) is likely there, too. If we don't find it,
def
analyse_types
(
self
,
env
):
# any second code unit cannot make for a surrogate pair by
self
.
is_temp
=
1
# itself.
return
self
if
0xD800
<=
c
<=
0xDBFF
:
return
True
def
may_be_none
(
self
):
return
False
return
False
gil_message
=
"Constructing Python long int"
def
generate_result_code
(
self
,
code
):
code
.
putln
(
'%s = PyLong_FromString((char *)"%s", 0, 0); %s'
%
(
self
.
result
(),
self
.
value
,
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
class
ImagNode
(
AtomicExprNode
):
class
ImagNode
(
AtomicExprNode
):
...
@@ -1499,10 +1528,10 @@ class NameNode(AtomicExprNode):
...
@@ -1499,10 +1528,10 @@ class NameNode(AtomicExprNode):
entry
=
self
.
entry
entry
=
self
.
entry
if
not
entry
:
if
not
entry
:
entry
=
env
.
lookup
(
self
.
name
)
entry
=
env
.
lookup
(
self
.
name
)
if
entry
and
entry
.
is_type
and
entry
.
type
.
is_extension_type
:
if
entry
and
entry
.
is_type
:
return
entry
.
type
if
entry
.
type
.
is_extension_type
or
entry
.
type
.
is_builtin_type
:
else
:
return
entry
.
type
return
None
return
None
def
analyse_target_declaration
(
self
,
env
):
def
analyse_target_declaration
(
self
,
env
):
if
not
self
.
entry
:
if
not
self
.
entry
:
...
@@ -1580,6 +1609,7 @@ class NameNode(AtomicExprNode):
...
@@ -1580,6 +1609,7 @@ class NameNode(AtomicExprNode):
self
.
is_temp
=
False
self
.
is_temp
=
False
self
.
is_used_as_rvalue
=
True
self
.
is_used_as_rvalue
=
True
self
.
use_managed_ref
=
True
self
.
use_managed_ref
=
True
return
self
def
nogil_check
(
self
,
env
):
def
nogil_check
(
self
,
env
):
self
.
nogil
=
True
self
.
nogil
=
True
...
@@ -2611,7 +2641,7 @@ class IndexNode(ExprNode):
...
@@ -2611,7 +2641,7 @@ class IndexNode(ExprNode):
return
py_object_type
return
py_object_type
index_type
=
self
.
index
.
infer_type
(
env
)
index_type
=
self
.
index
.
infer_type
(
env
)
if
index_type
and
index_type
.
is_int
or
isinstance
(
self
.
index
,
(
IntNode
,
LongNode
)
):
if
index_type
and
index_type
.
is_int
or
isinstance
(
self
.
index
,
IntNode
):
# indexing!
# indexing!
if
base_type
is
unicode_type
:
if
base_type
is
unicode_type
:
# Py_UCS4 will automatically coerce to a unicode string
# Py_UCS4 will automatically coerce to a unicode string
...
@@ -2655,18 +2685,18 @@ class IndexNode(ExprNode):
...
@@ -2655,18 +2685,18 @@ class IndexNode(ExprNode):
return
py_object_type
return
py_object_type
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
):
self
.
analyse_base_and_index_types
(
env
,
getting
=
1
)
return
self
.
analyse_base_and_index_types
(
env
,
getting
=
True
)
return
self
def
analyse_target_types
(
self
,
env
):
def
analyse_target_types
(
self
,
env
):
self
.
analyse_base_and_index_types
(
env
,
setting
=
1
)
node
=
self
.
analyse_base_and_index_types
(
env
,
setting
=
True
)
if
self
.
type
.
is_const
:
if
node
.
type
.
is_const
:
error
(
self
.
pos
,
"Assignment to const dereference"
)
error
(
self
.
pos
,
"Assignment to const dereference"
)
if
not
self
.
is_lvalue
():
if
not
node
.
is_lvalue
():
error
(
self
.
pos
,
"Assignment to non-lvalue of type '%s'"
%
self
.
type
)
error
(
self
.
pos
,
"Assignment to non-lvalue of type '%s'"
%
node
.
type
)
return
self
return
node
def
analyse_base_and_index_types
(
self
,
env
,
getting
=
0
,
setting
=
0
,
analyse_base
=
True
):
def
analyse_base_and_index_types
(
self
,
env
,
getting
=
False
,
setting
=
False
,
analyse_base
=
True
):
# Note: This might be cleaned up by having IndexNode
# Note: This might be cleaned up by having IndexNode
# parsed in a saner way and only construct the tuple if
# parsed in a saner way and only construct the tuple if
# needed.
# needed.
...
@@ -2690,7 +2720,7 @@ class IndexNode(ExprNode):
...
@@ -2690,7 +2720,7 @@ class IndexNode(ExprNode):
# Do not visit child tree if base is undeclared to avoid confusing
# Do not visit child tree if base is undeclared to avoid confusing
# error messages
# error messages
self
.
type
=
PyrexTypes
.
error_type
self
.
type
=
PyrexTypes
.
error_type
return
return
self
is_slice
=
isinstance
(
self
.
index
,
SliceNode
)
is_slice
=
isinstance
(
self
.
index
,
SliceNode
)
...
@@ -2739,9 +2769,10 @@ class IndexNode(ExprNode):
...
@@ -2739,9 +2769,10 @@ class IndexNode(ExprNode):
if
len
(
indices
)
-
len
(
newaxes
)
>
self
.
base
.
type
.
ndim
:
if
len
(
indices
)
-
len
(
newaxes
)
>
self
.
base
.
type
.
ndim
:
self
.
type
=
error_type
self
.
type
=
error_type
return
error
(
indices
[
self
.
base
.
type
.
ndim
].
pos
,
error
(
indices
[
self
.
base
.
type
.
ndim
].
pos
,
"Too many indices specified for type %s"
%
"Too many indices specified for type %s"
%
self
.
base
.
type
)
self
.
base
.
type
)
return
self
axis_idx
=
0
axis_idx
=
0
for
i
,
index
in
enumerate
(
indices
[:]):
for
i
,
index
in
enumerate
(
indices
[:]):
...
@@ -2784,7 +2815,8 @@ class IndexNode(ExprNode):
...
@@ -2784,7 +2815,8 @@ class IndexNode(ExprNode):
else
:
else
:
self
.
type
=
error_type
self
.
type
=
error_type
return
error
(
index
.
pos
,
"Invalid index for memoryview specified"
)
error
(
index
.
pos
,
"Invalid index for memoryview specified"
)
return
self
self
.
memslice_index
=
self
.
memslice_index
and
not
self
.
memslice_slice
self
.
memslice_index
=
self
.
memslice_index
and
not
self
.
memslice_slice
self
.
original_indices
=
indices
self
.
original_indices
=
indices
...
@@ -2849,7 +2881,7 @@ class IndexNode(ExprNode):
...
@@ -2849,7 +2881,7 @@ class IndexNode(ExprNode):
if
not
MemoryView
.
validate_axes
(
self
.
pos
,
axes
):
if
not
MemoryView
.
validate_axes
(
self
.
pos
,
axes
):
self
.
type
=
error_type
self
.
type
=
error_type
return
return
self
self
.
type
=
PyrexTypes
.
MemoryViewSliceType
(
self
.
type
=
PyrexTypes
.
MemoryViewSliceType
(
self
.
base
.
type
.
dtype
,
axes
)
self
.
base
.
type
.
dtype
,
axes
)
...
@@ -2920,15 +2952,15 @@ class IndexNode(ExprNode):
...
@@ -2920,15 +2952,15 @@ class IndexNode(ExprNode):
PyrexTypes
.
c_py_ssize_t_type
,
env
)
PyrexTypes
.
c_py_ssize_t_type
,
env
)
elif
not
self
.
index
.
type
.
is_int
:
elif
not
self
.
index
.
type
.
is_int
:
error
(
self
.
pos
,
error
(
self
.
pos
,
"Invalid index type '%s'"
%
"Invalid index type '%s'"
%
self
.
index
.
type
)
self
.
index
.
type
)
elif
base_type
.
is_cpp_class
:
elif
base_type
.
is_cpp_class
:
function
=
env
.
lookup_operator
(
"[]"
,
[
self
.
base
,
self
.
index
])
function
=
env
.
lookup_operator
(
"[]"
,
[
self
.
base
,
self
.
index
])
if
function
is
None
:
if
function
is
None
:
error
(
self
.
pos
,
"Indexing '%s' not supported for index type '%s'"
%
(
base_type
,
self
.
index
.
type
))
error
(
self
.
pos
,
"Indexing '%s' not supported for index type '%s'"
%
(
base_type
,
self
.
index
.
type
))
self
.
type
=
PyrexTypes
.
error_type
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
self
.
result_code
=
"<error>"
return
return
self
func_type
=
function
.
type
func_type
=
function
.
type
if
func_type
.
is_ptr
:
if
func_type
.
is_ptr
:
func_type
=
func_type
.
base_type
func_type
=
func_type
.
base_type
...
@@ -2940,11 +2972,12 @@ class IndexNode(ExprNode):
...
@@ -2940,11 +2972,12 @@ class IndexNode(ExprNode):
self
.
parse_indexed_fused_cdef
(
env
)
self
.
parse_indexed_fused_cdef
(
env
)
else
:
else
:
error
(
self
.
pos
,
error
(
self
.
pos
,
"Attempting to index non-array type '%s'"
%
"Attempting to index non-array type '%s'"
%
base_type
)
base_type
)
self
.
type
=
PyrexTypes
.
error_type
self
.
type
=
PyrexTypes
.
error_type
self
.
wrap_in_nonecheck_node
(
env
,
getting
)
self
.
wrap_in_nonecheck_node
(
env
,
getting
)
return
self
def
wrap_in_nonecheck_node
(
self
,
env
,
getting
):
def
wrap_in_nonecheck_node
(
self
,
env
,
getting
):
if
not
env
.
directives
[
'nonecheck'
]
or
not
self
.
base
.
may_be_none
():
if
not
env
.
directives
[
'nonecheck'
]
or
not
self
.
base
.
may_be_none
():
...
@@ -3455,23 +3488,15 @@ class SliceIndexNode(ExprNode):
...
@@ -3455,23 +3488,15 @@ class SliceIndexNode(ExprNode):
self
.
base
=
self
.
base
.
analyse_types
(
env
)
self
.
base
=
self
.
base
.
analyse_types
(
env
)
if
self
.
base
.
type
.
is_memoryviewslice
:
if
self
.
base
.
type
.
is_memoryviewslice
:
# Gross hack here! But we do not know the type until this point,
# and we cannot create and return a new node. So we change the
# type...
none_node
=
NoneNode
(
self
.
pos
)
none_node
=
NoneNode
(
self
.
pos
)
index
=
SliceNode
(
self
.
pos
,
index
=
SliceNode
(
self
.
pos
,
start
=
self
.
start
or
none_node
,
start
=
self
.
start
or
none_node
,
stop
=
self
.
stop
or
none_node
,
stop
=
self
.
stop
or
none_node
,
step
=
none_node
)
step
=
none_node
)
del
self
.
start
index_node
=
IndexNode
(
self
.
pos
,
index
,
base
=
self
.
base
)
del
self
.
stop
return
index_node
.
analyse_base_and_index_types
(
self
.
index
=
index
env
,
getting
=
getting
,
setting
=
not
getting
,
self
.
__class__
=
IndexNode
analyse_base
=
False
)
self
.
analyse_base_and_index_types
(
env
,
getting
=
getting
,
setting
=
not
getting
,
analyse_base
=
False
)
return
self
if
self
.
start
:
if
self
.
start
:
self
.
start
=
self
.
start
.
analyse_types
(
env
)
self
.
start
=
self
.
start
.
analyse_types
(
env
)
...
@@ -3929,23 +3954,6 @@ class SimpleCallNode(CallNode):
...
@@ -3929,23 +3954,6 @@ class SimpleCallNode(CallNode):
self
.
is_temp
=
1
self
.
is_temp
=
1
else
:
else
:
self
.
args
=
[
arg
.
analyse_types
(
env
)
for
arg
in
self
.
args
]
self
.
args
=
[
arg
.
analyse_types
(
env
)
for
arg
in
self
.
args
]
if
self
.
self
and
func_type
.
args
:
# Coerce 'self' to the type expected by the method.
self_arg
=
func_type
.
args
[
0
]
if
self_arg
.
not_none
:
# C methods must do the None test for self at *call* time
self
.
self
=
self
.
self
.
as_none_safe_node
(
"'NoneType' object has no attribute '%s'"
,
error
=
'PyExc_AttributeError'
,
format_args
=
[
self
.
function
.
entry
.
name
])
expected_type
=
self_arg
.
type
if
self_arg
.
accept_builtin_subtypes
:
self
.
coerced_self
=
CMethodSelfCloneNode
(
self
.
self
)
else
:
self
.
coerced_self
=
CloneNode
(
self
.
self
)
self
.
coerced_self
=
self
.
coerced_self
.
coerce_to
(
expected_type
,
env
)
# Insert coerced 'self' argument into argument list.
self
.
args
.
insert
(
0
,
self
.
coerced_self
)
self
.
analyse_c_function_call
(
env
)
self
.
analyse_c_function_call
(
env
)
return
self
return
self
...
@@ -3965,6 +3973,11 @@ class SimpleCallNode(CallNode):
...
@@ -3965,6 +3973,11 @@ class SimpleCallNode(CallNode):
self
.
type
=
error_type
self
.
type
=
error_type
return
return
if
self
.
self
:
args
=
[
self
.
self
]
+
self
.
args
else
:
args
=
self
.
args
if
self
.
function
.
type
.
is_cpp_class
:
if
self
.
function
.
type
.
is_cpp_class
:
overloaded_entry
=
self
.
function
.
type
.
scope
.
lookup
(
"operator()"
)
overloaded_entry
=
self
.
function
.
type
.
scope
.
lookup
(
"operator()"
)
if
overloaded_entry
is
None
:
if
overloaded_entry
is
None
:
...
@@ -3986,7 +3999,7 @@ class SimpleCallNode(CallNode):
...
@@ -3986,7 +3999,7 @@ class SimpleCallNode(CallNode):
else
:
else
:
alternatives
=
overloaded_entry
.
all_alternatives
()
alternatives
=
overloaded_entry
.
all_alternatives
()
entry
=
PyrexTypes
.
best_match
(
self
.
args
,
alternatives
,
self
.
pos
,
env
)
entry
=
PyrexTypes
.
best_match
(
args
,
alternatives
,
self
.
pos
,
env
)
if
not
entry
:
if
not
entry
:
self
.
type
=
PyrexTypes
.
error_type
self
.
type
=
PyrexTypes
.
error_type
...
@@ -3998,24 +4011,60 @@ class SimpleCallNode(CallNode):
...
@@ -3998,24 +4011,60 @@ class SimpleCallNode(CallNode):
self
.
function
.
type
=
entry
.
type
self
.
function
.
type
=
entry
.
type
func_type
=
self
.
function_type
()
func_type
=
self
.
function_type
()
else
:
else
:
entry
=
None
func_type
=
self
.
function_type
()
func_type
=
self
.
function_type
()
if
not
func_type
.
is_cfunction
:
if
not
func_type
.
is_cfunction
:
error
(
self
.
pos
,
"Calling non-function type '%s'"
%
func_type
)
error
(
self
.
pos
,
"Calling non-function type '%s'"
%
func_type
)
self
.
type
=
PyrexTypes
.
error_type
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
self
.
result_code
=
"<error>"
return
return
# Check no. of args
# Check no. of args
max_nargs
=
len
(
func_type
.
args
)
max_nargs
=
len
(
func_type
.
args
)
expected_nargs
=
max_nargs
-
func_type
.
optional_arg_count
expected_nargs
=
max_nargs
-
func_type
.
optional_arg_count
actual_nargs
=
len
(
self
.
args
)
actual_nargs
=
len
(
args
)
if
func_type
.
optional_arg_count
and
expected_nargs
!=
actual_nargs
:
if
func_type
.
optional_arg_count
and
expected_nargs
!=
actual_nargs
:
self
.
has_optional_args
=
1
self
.
has_optional_args
=
1
self
.
is_temp
=
1
self
.
is_temp
=
1
# check 'self' argument
if
entry
and
entry
.
is_cmethod
and
func_type
.
args
:
formal_arg
=
func_type
.
args
[
0
]
arg
=
args
[
0
]
if
formal_arg
.
not_none
:
if
self
.
self
:
self
.
self
=
self
.
self
.
as_none_safe_node
(
"'NoneType' object has no attribute '%s'"
,
error
=
'PyExc_AttributeError'
,
format_args
=
[
entry
.
name
])
else
:
# unbound method
arg
=
arg
.
as_none_safe_node
(
"descriptor '%s' requires a '%s' object but received a 'NoneType'"
,
format_args
=
[
entry
.
name
,
formal_arg
.
type
.
name
])
if
self
.
self
:
if
formal_arg
.
accept_builtin_subtypes
:
arg
=
CMethodSelfCloneNode
(
self
.
self
)
else
:
arg
=
CloneNode
(
self
.
self
)
arg
=
self
.
coerced_self
=
arg
.
coerce_to
(
formal_arg
.
type
,
env
)
elif
formal_arg
.
type
.
is_builtin_type
:
# special case: unbound methods of builtins accept subtypes
arg
=
arg
.
coerce_to
(
formal_arg
.
type
,
env
)
if
arg
.
type
.
is_builtin_type
and
isinstance
(
arg
,
PyTypeTestNode
):
arg
.
exact_builtin_type
=
False
args
[
0
]
=
arg
# Coerce arguments
# Coerce arguments
some_args_in_temps
=
False
some_args_in_temps
=
False
for
i
in
xrange
(
min
(
max_nargs
,
actual_nargs
)):
for
i
in
xrange
(
min
(
max_nargs
,
actual_nargs
)):
formal_type
=
func_type
.
args
[
i
].
type
formal_arg
=
func_type
.
args
[
i
]
arg
=
self
.
args
[
i
].
coerce_to
(
formal_type
,
env
)
formal_type
=
formal_arg
.
type
arg
=
args
[
i
].
coerce_to
(
formal_type
,
env
)
if
formal_arg
.
not_none
:
# C methods must do the None checks at *call* time
arg
=
arg
.
as_none_safe_node
(
"cannot pass None into a C function argument that is declared 'not None'"
)
if
arg
.
is_temp
:
if
arg
.
is_temp
:
if
i
>
0
:
if
i
>
0
:
# first argument in temp doesn't impact subsequent arguments
# first argument in temp doesn't impact subsequent arguments
...
@@ -4035,19 +4084,21 @@ class SimpleCallNode(CallNode):
...
@@ -4035,19 +4084,21 @@ class SimpleCallNode(CallNode):
if
i
>
0
:
# first argument doesn't matter
if
i
>
0
:
# first argument doesn't matter
some_args_in_temps
=
True
some_args_in_temps
=
True
arg
=
arg
.
coerce_to_temp
(
env
)
arg
=
arg
.
coerce_to_temp
(
env
)
self
.
args
[
i
]
=
arg
args
[
i
]
=
arg
# handle additional varargs parameters
# handle additional varargs parameters
for
i
in
xrange
(
max_nargs
,
actual_nargs
):
for
i
in
xrange
(
max_nargs
,
actual_nargs
):
arg
=
self
.
args
[
i
]
arg
=
args
[
i
]
if
arg
.
type
.
is_pyobject
:
if
arg
.
type
.
is_pyobject
:
arg_ctype
=
arg
.
type
.
default_coerced_ctype
()
arg_ctype
=
arg
.
type
.
default_coerced_ctype
()
if
arg_ctype
is
None
:
if
arg_ctype
is
None
:
error
(
self
.
args
[
i
].
pos
,
error
(
self
.
args
[
i
].
pos
,
"Python object cannot be passed as a varargs parameter"
)
"Python object cannot be passed as a varargs parameter"
)
else
:
else
:
self
.
args
[
i
]
=
arg
=
arg
.
coerce_to
(
arg_ctype
,
env
)
args
[
i
]
=
arg
=
arg
.
coerce_to
(
arg_ctype
,
env
)
if
arg
.
is_temp
and
i
>
0
:
if
arg
.
is_temp
and
i
>
0
:
some_args_in_temps
=
True
some_args_in_temps
=
True
if
some_args_in_temps
:
if
some_args_in_temps
:
# if some args are temps and others are not, they may get
# if some args are temps and others are not, they may get
# constructed in the wrong order (temps first) => make
# constructed in the wrong order (temps first) => make
...
@@ -4057,7 +4108,7 @@ class SimpleCallNode(CallNode):
...
@@ -4057,7 +4108,7 @@ class SimpleCallNode(CallNode):
for
i
in
xrange
(
actual_nargs
-
1
):
for
i
in
xrange
(
actual_nargs
-
1
):
if
i
==
0
and
self
.
self
is
not
None
:
if
i
==
0
and
self
.
self
is
not
None
:
continue
# self is ok
continue
# self is ok
arg
=
self
.
args
[
i
]
arg
=
args
[
i
]
if
arg
.
nonlocally_immutable
():
if
arg
.
nonlocally_immutable
():
# locals, C functions, unassignable types are safe.
# locals, C functions, unassignable types are safe.
pass
pass
...
@@ -4076,6 +4127,8 @@ class SimpleCallNode(CallNode):
...
@@ -4076,6 +4127,8 @@ class SimpleCallNode(CallNode):
warning
(
arg
.
pos
,
"Argument evaluation order in C function call is undefined and may not be as expected"
,
0
)
warning
(
arg
.
pos
,
"Argument evaluation order in C function call is undefined and may not be as expected"
,
0
)
break
break
self
.
args
[:]
=
args
# Calc result type and code fragment
# Calc result type and code fragment
if
isinstance
(
self
.
function
,
NewExprNode
):
if
isinstance
(
self
.
function
,
NewExprNode
):
self
.
type
=
PyrexTypes
.
CPtrType
(
self
.
function
.
class_type
)
self
.
type
=
PyrexTypes
.
CPtrType
(
self
.
function
.
class_type
)
...
@@ -4697,19 +4750,21 @@ class AttributeNode(ExprNode):
...
@@ -4697,19 +4750,21 @@ class AttributeNode(ExprNode):
return
self
.
obj
.
type_dependencies
(
env
)
return
self
.
obj
.
type_dependencies
(
env
)
def
infer_type
(
self
,
env
):
def
infer_type
(
self
,
env
):
if
self
.
analyse_as_cimported_attribute
(
env
,
0
):
# FIXME: this is way too redundant with analyse_types()
return
self
.
entry
.
type
node
=
self
.
analyse_as_cimported_attribute_node
(
env
,
target
=
False
)
elif
self
.
analyse_as_unbound_cmethod
(
env
):
if
node
is
not
None
:
return
self
.
entry
.
type
return
node
.
entry
.
type
else
:
node
=
self
.
analyse_as_unbound_cmethod_node
(
env
)
obj_type
=
self
.
obj
.
infer_type
(
env
)
if
node
is
not
None
:
self
.
analyse_attribute
(
env
,
obj_type
=
obj_type
)
return
node
.
entry
.
type
if
obj_type
.
is_builtin_type
and
self
.
type
.
is_cfunction
:
obj_type
=
self
.
obj
.
infer_type
(
env
)
# special case: C-API replacements for C methods of
self
.
analyse_attribute
(
env
,
obj_type
=
obj_type
)
# builtin types cannot be inferred as C functions as
if
obj_type
.
is_builtin_type
and
self
.
type
.
is_cfunction
:
# that would prevent their use as bound methods
# special case: C-API replacements for C methods of
return
py_object_type
# builtin types cannot be inferred as C functions as
return
self
.
type
# that would prevent their use as bound methods
return
py_object_type
return
self
.
type
def
analyse_target_declaration
(
self
,
env
):
def
analyse_target_declaration
(
self
,
env
):
pass
pass
...
@@ -4724,21 +4779,19 @@ class AttributeNode(ExprNode):
...
@@ -4724,21 +4779,19 @@ class AttributeNode(ExprNode):
def
analyse_types
(
self
,
env
,
target
=
0
):
def
analyse_types
(
self
,
env
,
target
=
0
):
self
.
initialized_check
=
env
.
directives
[
'initializedcheck'
]
self
.
initialized_check
=
env
.
directives
[
'initializedcheck'
]
if
self
.
analyse_as_cimported_attribute
(
env
,
target
):
node
=
self
.
analyse_as_cimported_attribute_node
(
env
,
target
)
self
.
entry
.
used
=
True
if
node
is
None
and
not
target
:
elif
not
target
and
self
.
analyse_as_unbound_cmethod
(
env
):
node
=
self
.
analyse_as_unbound_cmethod_node
(
env
)
self
.
entry
.
used
=
True
if
node
is
None
:
else
:
node
=
self
.
analyse_as_ordinary_attribute_node
(
env
,
target
)
self
.
analyse_as_ordinary_attribute
(
env
,
target
)
assert
node
is
not
None
if
self
.
entry
:
if
node
.
entry
:
self
.
entry
.
used
=
True
node
.
entry
.
used
=
True
if
node
.
is_attribute
:
# may be mutated in a namenode now :)
node
.
wrap_obj_in_nonecheck
(
env
)
if
self
.
is_attribute
:
return
node
self
.
wrap_obj_in_nonecheck
(
env
)
return
self
def
analyse_as_cimported_attribute
(
self
,
env
,
target
):
def
analyse_as_cimported_attribute
_node
(
self
,
env
,
target
):
# Try to interpret this as a reference to an imported
# Try to interpret this as a reference to an imported
# C const, type, var or function. If successful, mutates
# C const, type, var or function. If successful, mutates
# this node into a NameNode and returns 1, otherwise
# this node into a NameNode and returns 1, otherwise
...
@@ -4747,33 +4800,36 @@ class AttributeNode(ExprNode):
...
@@ -4747,33 +4800,36 @@ class AttributeNode(ExprNode):
if
module_scope
:
if
module_scope
:
entry
=
module_scope
.
lookup_here
(
self
.
attribute
)
entry
=
module_scope
.
lookup_here
(
self
.
attribute
)
if
entry
and
(
if
entry
and
(
entry
.
is_cglobal
or
entry
.
is_cfunction
entry
.
is_cglobal
or
entry
.
is_cfunction
or
entry
.
is_type
or
entry
.
is_const
):
or
entry
.
is_type
or
entry
.
is_const
):
self
.
mutate_into_name_node
(
env
,
entry
,
target
)
# FIXME
return
self
.
as_name_node
(
env
,
entry
,
target
)
entry
.
used
=
1
return
None
return
1
return
0
def
analyse_as_unbound_cmethod
(
self
,
env
):
def
analyse_as_unbound_cmethod
_node
(
self
,
env
):
# Try to interpret this as a reference to an unbound
# Try to interpret this as a reference to an unbound
# C method of an extension type
. If successful, mutates
# C method of an extension type
or builtin type. If successful,
#
this node into a NameNode and returns 1
, otherwise
#
creates a corresponding NameNode and returns it
, otherwise
# returns
0
.
# returns
None
.
type
=
self
.
obj
.
analyse_as_extension_type
(
env
)
type
=
self
.
obj
.
analyse_as_extension_type
(
env
)
if
type
:
if
type
:
entry
=
type
.
scope
.
lookup_here
(
self
.
attribute
)
entry
=
type
.
scope
.
lookup_here
(
self
.
attribute
)
if
entry
and
entry
.
is_cmethod
:
if
entry
and
entry
.
is_cmethod
:
# Create a temporary entry describing the C method
if
type
.
is_builtin_type
:
# as an ordinary function.
if
not
self
.
is_called
:
ubcm_entry
=
Symtab
.
Entry
(
entry
.
name
,
# must handle this as Python object
"%s->%s"
%
(
type
.
vtabptr_cname
,
entry
.
cname
),
return
None
entry
.
type
)
ubcm_entry
=
entry
ubcm_entry
.
is_cfunction
=
1
else
:
ubcm_entry
.
func_cname
=
entry
.
func_cname
# Create a temporary entry describing the C method
ubcm_entry
.
is_unbound_cmethod
=
1
# as an ordinary function.
self
.
mutate_into_name_node
(
env
,
ubcm_entry
,
None
)
# FIXME
ubcm_entry
=
Symtab
.
Entry
(
entry
.
name
,
return
1
"%s->%s"
%
(
type
.
vtabptr_cname
,
entry
.
cname
),
return
0
entry
.
type
)
ubcm_entry
.
is_cfunction
=
1
ubcm_entry
.
func_cname
=
entry
.
func_cname
ubcm_entry
.
is_unbound_cmethod
=
1
return
self
.
as_name_node
(
env
,
ubcm_entry
,
target
=
False
)
return
None
def
analyse_as_type
(
self
,
env
):
def
analyse_as_type
(
self
,
env
):
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
...
@@ -4791,8 +4847,9 @@ class AttributeNode(ExprNode):
...
@@ -4791,8 +4847,9 @@ class AttributeNode(ExprNode):
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
if
module_scope
:
if
module_scope
:
entry
=
module_scope
.
lookup_here
(
self
.
attribute
)
entry
=
module_scope
.
lookup_here
(
self
.
attribute
)
if
entry
and
entry
.
is_type
and
entry
.
type
.
is_extension_type
:
if
entry
and
entry
.
is_type
:
return
entry
.
type
if
entry
.
type
.
is_extension_type
or
entry
.
type
.
is_builtin_type
:
return
entry
.
type
return
None
return
None
def
analyse_as_module
(
self
,
env
):
def
analyse_as_module
(
self
,
env
):
...
@@ -4805,20 +4862,18 @@ class AttributeNode(ExprNode):
...
@@ -4805,20 +4862,18 @@ class AttributeNode(ExprNode):
return
entry
.
as_module
return
entry
.
as_module
return
None
return
None
def
mutate_into
_name_node
(
self
,
env
,
entry
,
target
):
def
as
_name_node
(
self
,
env
,
entry
,
target
):
#
Mutate this node into a NameN
ode and complete the
#
Create a corresponding NameNode from this n
ode and complete the
# analyse_types phase.
# analyse_types phase.
self
.
__class__
=
NameNode
node
=
NameNode
.
from_node
(
self
,
name
=
self
.
attribute
,
entry
=
entry
)
self
.
name
=
self
.
attribute
self
.
entry
=
entry
del
self
.
obj
del
self
.
attribute
if
target
:
if
target
:
NameNode
.
analyse_target_types
(
self
,
env
)
# FIXME
node
=
node
.
analyse_target_types
(
env
)
else
:
else
:
NameNode
.
analyse_rvalue_entry
(
self
,
env
)
node
=
node
.
analyse_rvalue_entry
(
env
)
node
.
entry
.
used
=
1
return
node
def
analyse_as_ordinary_attribute
(
self
,
env
,
target
):
def
analyse_as_ordinary_attribute
_node
(
self
,
env
,
target
):
self
.
obj
=
self
.
obj
.
analyse_types
(
env
)
self
.
obj
=
self
.
obj
.
analyse_types
(
env
)
self
.
analyse_attribute
(
env
)
self
.
analyse_attribute
(
env
)
if
self
.
entry
and
self
.
entry
.
is_cmethod
and
not
self
.
is_called
:
if
self
.
entry
and
self
.
entry
.
is_cmethod
and
not
self
.
is_called
:
...
@@ -4835,6 +4890,7 @@ class AttributeNode(ExprNode):
...
@@ -4835,6 +4890,7 @@ class AttributeNode(ExprNode):
error
(
self
.
pos
,
"Assignment to an immutable object field"
)
error
(
self
.
pos
,
"Assignment to an immutable object field"
)
#elif self.type.is_memoryviewslice and not target:
#elif self.type.is_memoryviewslice and not target:
# self.is_temp = True
# self.is_temp = True
return
self
def
analyse_attribute
(
self
,
env
,
obj_type
=
None
):
def
analyse_attribute
(
self
,
env
,
obj_type
=
None
):
# Look up attribute and set self.type and self.member.
# Look up attribute and set self.type and self.member.
...
@@ -6760,14 +6816,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
...
@@ -6760,14 +6816,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
):
if
self
.
binding
:
if
self
.
binding
:
if
self
.
specialized_cpdefs
or
self
.
is_specialization
:
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"FusedFunction"
,
"CythonFunction.c"
))
else
:
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CythonFunction"
,
"CythonFunction.c"
))
self
.
analyse_default_args
(
env
)
self
.
analyse_default_args
(
env
)
#TODO(craig,haoyu) This should be moved to a better place
#TODO(craig,haoyu) This should be moved to a better place
self
.
set_qualified_name
(
env
,
self
.
def_node
.
name
)
self
.
set_qualified_name
(
env
,
self
.
def_node
.
name
)
return
self
return
self
...
@@ -6867,14 +6916,18 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
...
@@ -6867,14 +6916,18 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
def
generate_cyfunction_code
(
self
,
code
):
def
generate_cyfunction_code
(
self
,
code
):
def_node
=
self
.
def_node
if
self
.
specialized_cpdefs
:
if
self
.
specialized_cpdefs
:
constructor
=
"__pyx_FusedFunction_NewEx"
def_node
=
self
.
specialized_cpdefs
[
0
]
def_node
=
self
.
specialized_cpdefs
[
0
]
elif
self
.
is_specialization
:
else
:
def_node
=
self
.
def_node
if
self
.
specialized_cpdefs
or
self
.
is_specialization
:
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"FusedFunction"
,
"CythonFunction.c"
))
constructor
=
"__pyx_FusedFunction_NewEx"
constructor
=
"__pyx_FusedFunction_NewEx"
else
:
else
:
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CythonFunction"
,
"CythonFunction.c"
))
constructor
=
"__Pyx_CyFunction_NewEx"
constructor
=
"__Pyx_CyFunction_NewEx"
if
self
.
code_object
:
if
self
.
code_object
:
...
@@ -9199,6 +9252,11 @@ class CmpNode(object):
...
@@ -9199,6 +9252,11 @@ class CmpNode(object):
self
.
special_bool_cmp_utility_code
=
UtilityCode
.
load_cached
(
"PyDictContains"
,
"ObjectHandling.c"
)
self
.
special_bool_cmp_utility_code
=
UtilityCode
.
load_cached
(
"PyDictContains"
,
"ObjectHandling.c"
)
self
.
special_bool_cmp_function
=
"__Pyx_PyDict_Contains"
self
.
special_bool_cmp_function
=
"__Pyx_PyDict_Contains"
return
True
return
True
elif
self
.
operand2
.
type
is
Builtin
.
unicode_type
:
self
.
operand2
=
self
.
operand2
.
as_none_safe_node
(
"'NoneType' object is not iterable"
)
self
.
special_bool_cmp_utility_code
=
UtilityCode
.
load_cached
(
"PyUnicodeContains"
,
"StringTools.c"
)
self
.
special_bool_cmp_function
=
"__Pyx_PyUnicode_Contains"
return
True
else
:
else
:
if
not
self
.
operand2
.
type
.
is_pyobject
:
if
not
self
.
operand2
.
type
.
is_pyobject
:
self
.
operand2
=
self
.
operand2
.
coerce_to_pyobject
(
env
)
self
.
operand2
=
self
.
operand2
.
coerce_to_pyobject
(
env
)
...
@@ -9717,6 +9775,8 @@ class PyTypeTestNode(CoercionNode):
...
@@ -9717,6 +9775,8 @@ class PyTypeTestNode(CoercionNode):
# object is an instance of a particular extension type.
# object is an instance of a particular extension type.
# This node borrows the result of its argument node.
# This node borrows the result of its argument node.
exact_builtin_type
=
True
def
__init__
(
self
,
arg
,
dst_type
,
env
,
notnone
=
False
):
def
__init__
(
self
,
arg
,
dst_type
,
env
,
notnone
=
False
):
# The arg is know to be a Python object, and
# The arg is know to be a Python object, and
# the dst_type is known to be an extension type.
# the dst_type is known to be an extension type.
...
@@ -9758,12 +9818,17 @@ class PyTypeTestNode(CoercionNode):
...
@@ -9758,12 +9818,17 @@ class PyTypeTestNode(CoercionNode):
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
if
self
.
type
.
typeobj_is_available
():
if
self
.
type
.
typeobj_is_available
():
if
not
self
.
type
.
is_builtin_type
:
if
self
.
type
.
is_builtin_type
:
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"ExtTypeTest"
,
"ObjectHandling.c"
))
type_test
=
self
.
type
.
type_test_code
(
code
.
putln
(
self
.
arg
.
py_result
(),
"if (!(%s)) %s"
%
(
self
.
notnone
,
exact
=
self
.
exact_builtin_type
)
self
.
type
.
type_test_code
(
self
.
arg
.
py_result
(),
self
.
notnone
),
else
:
code
.
error_goto
(
self
.
pos
)))
type_test
=
self
.
type
.
type_test_code
(
self
.
arg
.
py_result
(),
self
.
notnone
)
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"ExtTypeTest"
,
"ObjectHandling.c"
))
code
.
putln
(
"if (!(%s)) %s"
%
(
type_test
,
code
.
error_goto
(
self
.
pos
)))
else
:
else
:
error
(
self
.
pos
,
"Cannot test type of extern C class "
error
(
self
.
pos
,
"Cannot test type of extern C class "
"without type object name specification"
)
"without type object name specification"
)
...
...
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
(
""
)
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
(
"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
from
Cython.Compiler
import
TypeSlots
from
Cython.Compiler.ExprNodes
import
not_a_constant
import
cython
import
cython
cython
.
declare
(
UtilityCode
=
object
,
EncodedString
=
object
,
BytesLiteral
=
object
,
cython
.
declare
(
UtilityCode
=
object
,
EncodedString
=
object
,
BytesLiteral
=
object
,
Nodes
=
object
,
ExprNodes
=
object
,
PyrexTypes
=
object
,
Builtin
=
object
,
Nodes
=
object
,
ExprNodes
=
object
,
PyrexTypes
=
object
,
Builtin
=
object
,
...
@@ -1787,13 +1789,14 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
...
@@ -1787,13 +1789,14 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
node
=
ExprNodes
.
PythonCapiCallNode
(
node
=
ExprNodes
.
PythonCapiCallNode
(
coerce_node
.
pos
,
"__Pyx_PyBytes_GetItemInt"
,
coerce_node
.
pos
,
"__Pyx_PyBytes_GetItemInt"
,
self
.
PyBytes_GetItemInt_func_type
,
self
.
PyBytes_GetItemInt_func_type
,
args
=
[
args
=
[
arg
.
base
.
as_none_safe_node
(
"'NoneType' object is not subscriptable"
),
arg
.
base
.
as_none_safe_node
(
"'NoneType' object is not subscriptable"
),
index_node
.
coerce_to
(
PyrexTypes
.
c_py_ssize_t_type
,
env
),
index_node
.
coerce_to
(
PyrexTypes
.
c_py_ssize_t_type
,
env
),
bound_check_node
,
bound_check_node
,
],
],
is_temp
=
True
,
is_temp
=
True
,
utility_code
=
load_c_utility
(
'bytes_index'
))
utility_code
=
UtilityCode
.
load_cached
(
'bytes_index'
,
'StringTools.c'
))
if
coerce_node
.
type
is
not
PyrexTypes
.
c_char_type
:
if
coerce_node
.
type
is
not
PyrexTypes
.
c_char_type
:
node
=
node
.
coerce_to
(
coerce_node
.
type
,
env
)
node
=
node
.
coerce_to
(
coerce_node
.
type
,
env
)
return
node
return
node
...
@@ -2140,14 +2143,22 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
...
@@ -2140,14 +2143,22 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
Pyx_tp_new_func_type
=
PyrexTypes
.
CFuncType
(
Pyx_tp_new_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"type"
,
Builtin
.
type_type
,
None
)
PyrexTypes
.
CFuncTypeArg
(
"type"
,
PyrexTypes
.
py_object_type
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"args"
,
Builtin
.
tuple_type
,
None
),
])
])
def
_handle_simple_slot__new__
(
self
,
node
,
args
,
is_unbound_method
):
Pyx_tp_new_kwargs_func_type
=
PyrexTypes
.
CFuncType
(
"""Replace 'exttype.__new__(exttype)' by a call to exttype->tp_new()
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"type"
,
PyrexTypes
.
py_object_type
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"args"
,
Builtin
.
tuple_type
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"kwargs"
,
Builtin
.
dict_type
,
None
),
])
def
_handle_any_slot__new__
(
self
,
node
,
args
,
is_unbound_method
,
kwargs
=
None
):
"""Replace 'exttype.__new__(exttype, ...)' by a call to exttype->tp_new()
"""
"""
obj
=
node
.
function
.
obj
obj
=
node
.
function
.
obj
if
not
is_unbound_method
or
len
(
args
)
!=
1
:
if
not
is_unbound_method
or
len
(
args
)
<
1
:
return
node
return
node
type_arg
=
args
[
0
]
type_arg
=
args
[
0
]
if
not
obj
.
is_name
or
not
type_arg
.
is_name
:
if
not
obj
.
is_name
or
not
type_arg
.
is_name
:
...
@@ -2165,21 +2176,53 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
...
@@ -2165,21 +2176,53 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
# different types - may or may not lead to an error at runtime
# different types - may or may not lead to an error at runtime
return
node
return
node
# FIXME: we could potentially look up the actual tp_new C
args_tuple
=
ExprNodes
.
TupleNode
(
node
.
pos
,
args
=
args
[
1
:])
# method of the extension type and call that instead of the
args_tuple
=
args_tuple
.
analyse_types
(
# generic slot. That would also allow us to pass parameters
self
.
current_env
(),
skip_children
=
True
)
# efficiently.
if
not
type_arg
.
type_entry
:
if
type_arg
.
type_entry
:
ext_type
=
type_arg
.
type_entry
.
type
if
ext_type
.
is_extension_type
and
ext_type
.
typeobj_cname
:
tp_slot
=
TypeSlots
.
ConstructorSlot
(
"tp_new"
,
'__new__'
)
slot_func_cname
=
TypeSlots
.
get_slot_function
(
ext_type
.
scope
,
tp_slot
)
if
slot_func_cname
:
cython_scope
=
self
.
context
.
cython_scope
PyTypeObjectPtr
=
PyrexTypes
.
CPtrType
(
cython_scope
.
lookup
(
'PyTypeObject'
).
type
)
pyx_tp_new_kwargs_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"type"
,
PyTypeObjectPtr
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"args"
,
PyrexTypes
.
py_object_type
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"kwargs"
,
PyrexTypes
.
py_object_type
,
None
),
])
type_arg
=
ExprNodes
.
CastNode
(
type_arg
,
PyTypeObjectPtr
)
if
not
kwargs
:
kwargs
=
ExprNodes
.
NullNode
(
node
.
pos
,
type
=
PyrexTypes
.
py_object_type
)
# hack?
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
slot_func_cname
,
pyx_tp_new_kwargs_func_type
,
args
=
[
type_arg
,
args_tuple
,
kwargs
],
is_temp
=
True
)
else
:
# arbitrary variable, needs a None check for safety
# arbitrary variable, needs a None check for safety
type_arg
=
type_arg
.
as_none_safe_node
(
type_arg
=
type_arg
.
as_none_safe_node
(
"object.__new__(X): X is not a type object (NoneType)"
)
"object.__new__(X): X is not a type object (NoneType)"
)
return
ExprNodes
.
PythonCapiCallNode
(
utility_code
=
UtilityCode
.
load_cached
(
'tp_new'
,
'ObjectHandling.c'
)
node
.
pos
,
"__Pyx_tp_new"
,
self
.
Pyx_tp_new_func_type
,
if
kwargs
:
args
=
[
type_arg
],
return
ExprNodes
.
PythonCapiCallNode
(
utility_code
=
tpnew_utility_code
,
node
.
pos
,
"__Pyx_tp_new_kwargs"
,
self
.
Pyx_tp_new_kwargs_func_type
,
is_temp
=
node
.
is_temp
args
=
[
type_arg
,
args_tuple
,
kwargs
],
utility_code
=
utility_code
,
is_temp
=
node
.
is_temp
)
else
:
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"__Pyx_tp_new"
,
self
.
Pyx_tp_new_func_type
,
args
=
[
type_arg
,
args_tuple
],
utility_code
=
utility_code
,
is_temp
=
node
.
is_temp
)
)
### methods of builtin types
### methods of builtin types
...
@@ -2341,7 +2384,8 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
...
@@ -2341,7 +2384,8 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
method_name
=
node
.
function
.
attribute
method_name
=
node
.
function
.
attribute
if
method_name
==
'istitle'
:
if
method_name
==
'istitle'
:
# istitle() doesn't directly map to Py_UNICODE_ISTITLE()
# istitle() doesn't directly map to Py_UNICODE_ISTITLE()
utility_code
=
load_c_utility
(
"py_unicode_istitle"
)
utility_code
=
UtilityCode
.
load_cached
(
"py_unicode_istitle"
,
"StringTools.c"
)
function_name
=
'__Pyx_Py_UNICODE_ISTITLE'
function_name
=
'__Pyx_Py_UNICODE_ISTITLE'
else
:
else
:
utility_code
=
None
utility_code
=
None
...
@@ -2897,41 +2941,9 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
...
@@ -2897,41 +2941,9 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
args
[
arg_index
]
=
args
[
arg_index
].
coerce_to_boolean
(
self
.
current_env
())
args
[
arg_index
]
=
args
[
arg_index
].
coerce_to_boolean
(
self
.
current_env
())
unicode_tailmatch_utility_code
=
load_c_utility
(
'unicode_tailmatch'
)
unicode_tailmatch_utility_code
=
UtilityCode
.
load_cached
(
'unicode_tailmatch'
,
'StringTools.c'
)
bytes_tailmatch_utility_code
=
UtilityCode
.
load_cached
(
'bytes_tailmatch'
,
'StringTools.c'
)
bytes_tailmatch_utility_code
=
load_c_utility
(
'bytes_tailmatch'
)
str_tailmatch_utility_code
=
UtilityCode
.
load_cached
(
'str_tailmatch'
,
'StringTools.c'
)
str_tailmatch_utility_code
=
UtilityCode
(
proto
=
'''
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.
impl
=
'''
static CYTHON_INLINE int __Pyx_PyStr_Tailmatch(PyObject* self, PyObject* arg, Py_ssize_t start,
Py_ssize_t end, int direction)
{
if (PY_MAJOR_VERSION < 3)
return __Pyx_PyBytes_Tailmatch(self, arg, start, end, direction);
else
return __Pyx_PyUnicode_Tailmatch(self, arg, start, end, direction);
}
'''
,
requires
=
[
unicode_tailmatch_utility_code
,
bytes_tailmatch_utility_code
]
)
tpnew_utility_code
=
UtilityCode
(
proto
=
"""
static CYTHON_INLINE PyObject* __Pyx_tp_new(PyObject* type_obj) {
return (PyObject*) (((PyTypeObject*)(type_obj))->tp_new(
(PyTypeObject*)(type_obj), %(TUPLE)s, NULL));
}
"""
%
{
'TUPLE'
:
Naming
.
empty_tuple
}
)
class
ConstantFolding
(
Visitor
.
VisitorTransform
,
SkipDeclarations
):
class
ConstantFolding
(
Visitor
.
VisitorTransform
,
SkipDeclarations
):
...
@@ -2991,8 +3003,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
...
@@ -2991,8 +3003,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
import
traceback
,
sys
import
traceback
,
sys
traceback
.
print_exc
(
file
=
sys
.
stdout
)
traceback
.
print_exc
(
file
=
sys
.
stdout
)
NODE_TYPE_ORDER
=
[
ExprNodes
.
CharNode
,
ExprNodes
.
Int
Node
,
NODE_TYPE_ORDER
=
[
ExprNodes
.
BoolNode
,
ExprNodes
.
Char
Node
,
ExprNodes
.
Long
Node
,
ExprNodes
.
FloatNode
]
ExprNodes
.
Int
Node
,
ExprNodes
.
FloatNode
]
def
_widest_node_class
(
self
,
*
nodes
):
def
_widest_node_class
(
self
,
*
nodes
):
try
:
try
:
...
@@ -3011,13 +3023,13 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
...
@@ -3011,13 +3023,13 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
return
node
return
node
if
not
node
.
operand
.
is_literal
:
if
not
node
.
operand
.
is_literal
:
return
node
return
node
if
isinstance
(
node
,
ExprNodes
.
NotNode
)
:
if
node
.
operator
==
'!'
:
return
ExprNodes
.
BoolNode
(
node
.
pos
,
value
=
bool
(
node
.
constant_result
),
return
ExprNodes
.
BoolNode
(
node
.
pos
,
value
=
bool
(
node
.
constant_result
),
constant_result
=
bool
(
node
.
constant_result
))
constant_result
=
bool
(
node
.
constant_result
))
elif
isinstance
(
node
.
operand
,
ExprNodes
.
BoolNode
):
elif
isinstance
(
node
.
operand
,
ExprNodes
.
BoolNode
):
return
ExprNodes
.
IntNode
(
node
.
pos
,
value
=
str
(
int
(
node
.
constant_result
)),
return
ExprNodes
.
IntNode
(
node
.
pos
,
value
=
str
(
int
(
node
.
constant_result
)),
type
=
PyrexTypes
.
c_int_type
,
type
=
PyrexTypes
.
c_int_type
,
constant_result
=
int
(
node
.
constant_result
))
constant_result
=
int
(
node
.
constant_result
))
elif
node
.
operator
==
'+'
:
elif
node
.
operator
==
'+'
:
return
self
.
_handle_UnaryPlusNode
(
node
)
return
self
.
_handle_UnaryPlusNode
(
node
)
elif
node
.
operator
==
'-'
:
elif
node
.
operator
==
'-'
:
...
@@ -3025,20 +3037,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
...
@@ -3025,20 +3037,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
return
node
return
node
def
_handle_UnaryMinusNode
(
self
,
node
):
def
_handle_UnaryMinusNode
(
self
,
node
):
if
isinstance
(
node
.
operand
,
ExprNodes
.
LongNode
):
def
_negate
(
value
):
return
ExprNodes
.
LongNode
(
node
.
pos
,
value
=
'-'
+
node
.
operand
.
value
,
if
value
.
startswith
(
'-'
):
constant_result
=
node
.
constant_result
)
value
=
value
[
1
:]
else
:
value
=
'-'
+
value
return
value
if
isinstance
(
node
.
operand
,
ExprNodes
.
FloatNode
):
if
isinstance
(
node
.
operand
,
ExprNodes
.
FloatNode
):
# this is a safe operation
# this is a safe operation
return
ExprNodes
.
FloatNode
(
node
.
pos
,
value
=
'-'
+
node
.
operand
.
value
,
return
ExprNodes
.
FloatNode
(
node
.
pos
,
value
=
_negate
(
node
.
operand
.
value
)
,
constant_result
=
node
.
constant_result
)
constant_result
=
node
.
constant_result
)
node_type
=
node
.
operand
.
type
node_type
=
node
.
operand
.
type
if
node_type
.
is_int
and
node_type
.
signed
or
\
if
node_type
.
is_int
and
node_type
.
signed
or
\
isinstance
(
node
.
operand
,
ExprNodes
.
IntNode
)
and
node_type
.
is_pyobject
:
isinstance
(
node
.
operand
,
ExprNodes
.
IntNode
)
and
node_type
.
is_pyobject
:
return
ExprNodes
.
IntNode
(
node
.
pos
,
value
=
'-'
+
node
.
operand
.
value
,
return
ExprNodes
.
IntNode
(
node
.
pos
,
value
=
_negate
(
node
.
operand
.
value
)
,
type
=
node_type
,
type
=
node_type
,
longness
=
node
.
operand
.
longness
,
longness
=
node
.
operand
.
longness
,
constant_result
=
node
.
constant_result
)
constant_result
=
node
.
constant_result
)
return
node
return
node
def
_handle_UnaryPlusNode
(
self
,
node
):
def
_handle_UnaryPlusNode
(
self
,
node
):
...
@@ -3083,18 +3099,26 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
...
@@ -3083,18 +3099,26 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
widest_type
=
PyrexTypes
.
widest_numeric_type
(
type1
,
type2
)
widest_type
=
PyrexTypes
.
widest_numeric_type
(
type1
,
type2
)
else
:
else
:
widest_type
=
PyrexTypes
.
py_object_type
widest_type
=
PyrexTypes
.
py_object_type
target_class
=
self
.
_widest_node_class
(
operand1
,
operand2
)
target_class
=
self
.
_widest_node_class
(
operand1
,
operand2
)
if
target_class
is
None
:
if
target_class
is
None
:
return
node
return
node
elif
target_class
is
ExprNodes
.
IntNode
:
if
target_class
is
ExprNodes
.
BoolNode
and
node
.
operator
in
'+-//<<%**>>'
:
# C arithmetic results in at least an int type
target_class
=
ExprNodes
.
IntNode
if
target_class
is
ExprNodes
.
CharNode
and
node
.
operator
in
'+-//<<%**>>&|^'
:
# C arithmetic results in at least an int type
target_class
=
ExprNodes
.
IntNode
if
target_class
is
ExprNodes
.
IntNode
:
unsigned
=
getattr
(
operand1
,
'unsigned'
,
''
)
and
\
unsigned
=
getattr
(
operand1
,
'unsigned'
,
''
)
and
\
getattr
(
operand2
,
'unsigned'
,
''
)
getattr
(
operand2
,
'unsigned'
,
''
)
longness
=
"LL"
[:
max
(
len
(
getattr
(
operand1
,
'longness'
,
''
)),
longness
=
"LL"
[:
max
(
len
(
getattr
(
operand1
,
'longness'
,
''
)),
len
(
getattr
(
operand2
,
'longness'
,
''
)))]
len
(
getattr
(
operand2
,
'longness'
,
''
)))]
new_node
=
ExprNodes
.
IntNode
(
pos
=
node
.
pos
,
new_node
=
ExprNodes
.
IntNode
(
pos
=
node
.
pos
,
unsigned
=
unsigned
,
longness
=
longness
,
unsigned
=
unsigned
,
longness
=
longness
,
value
=
str
(
node
.
constant_result
),
value
=
str
(
int
(
node
.
constant_result
)
),
constant_result
=
node
.
constant_result
)
constant_result
=
int
(
node
.
constant_result
)
)
# IntNode is smart about the type it chooses, so we just
# IntNode is smart about the type it chooses, so we just
# make sure we were not smarter this time
# make sure we were not smarter this time
if
widest_type
.
is_pyobject
or
new_node
.
type
.
is_pyobject
:
if
widest_type
.
is_pyobject
or
new_node
.
type
.
is_pyobject
:
...
@@ -3102,7 +3126,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
...
@@ -3102,7 +3126,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
else
:
else
:
new_node
.
type
=
PyrexTypes
.
widest_numeric_type
(
widest_type
,
new_node
.
type
)
new_node
.
type
=
PyrexTypes
.
widest_numeric_type
(
widest_type
,
new_node
.
type
)
else
:
else
:
if
isinstance
(
node
,
ExprNodes
.
BoolNode
)
:
if
target_class
is
ExprNodes
.
BoolNode
:
node_value
=
node
.
constant_result
node_value
=
node
.
constant_result
else
:
else
:
node_value
=
str
(
node
.
constant_result
)
node_value
=
str
(
node
.
constant_result
)
...
@@ -3178,10 +3202,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
...
@@ -3178,10 +3202,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
def
visit_SliceIndexNode
(
self
,
node
):
def
visit_SliceIndexNode
(
self
,
node
):
self
.
_calculate_const
(
node
)
self
.
_calculate_const
(
node
)
# normalise start/stop values
# normalise start/stop values
if
node
.
start
and
node
.
start
.
constant_result
is
None
:
if
node
.
start
is
None
or
node
.
start
.
constant_result
is
None
:
node
.
start
=
None
start
=
node
.
start
=
None
if
node
.
stop
and
node
.
stop
.
constant_result
is
None
:
else
:
node
.
stop
=
None
start
=
node
.
start
.
constant_result
if
node
.
stop
is
None
or
node
.
stop
.
constant_result
is
None
:
stop
=
node
.
stop
=
None
else
:
stop
=
node
.
stop
.
constant_result
# cut down sliced constant sequences
if
node
.
constant_result
is
not
not_a_constant
:
base
=
node
.
base
if
base
.
is_sequence_constructor
:
base
.
args
=
base
.
args
[
start
:
stop
]
return
base
elif
base
.
is_string_literal
:
base
=
base
.
as_sliced_node
(
start
,
stop
)
if
base
is
not
None
:
return
base
return
node
return
node
def
visit_ForInStatNode
(
self
,
node
):
def
visit_ForInStatNode
(
self
,
node
):
...
...
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,7 +746,8 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -746,7 +746,8 @@ 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)
self.run_tests(result)
if not self.cython_only:
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...
self.success = True
self.success = True
...
@@ -761,8 +762,7 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -761,8 +762,7 @@ 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):
def run_test(result):
def run_test(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