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
416e3293
Commit
416e3293
authored
Nov 07, 2009
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
merged in latest cython-devel
parents
ae714eac
04c2f16b
Changes
33
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
643 additions
and
134 deletions
+643
-134
.hgtags
.hgtags
+1
-0
Cython/Compiler/Buffer.py
Cython/Compiler/Buffer.py
+3
-2
Cython/Compiler/CmdLine.py
Cython/Compiler/CmdLine.py
+4
-1
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+4
-2
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+2
-1
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+6
-2
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+4
-6
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+171
-3
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+36
-10
Cython/Compiler/Version.py
Cython/Compiler/Version.py
+1
-1
MANIFEST.in
MANIFEST.in
+1
-1
runtests.py
runtests.py
+24
-8
tests/bugs.txt
tests/bugs.txt
+0
-1
tests/compile/bufaccess_noassignT444.pyx
tests/compile/bufaccess_noassignT444.pyx
+4
-0
tests/compile/cpp_exceptions.h
tests/compile/cpp_exceptions.h
+0
-3
tests/compile/cpp_exceptions_T265.pyx
tests/compile/cpp_exceptions_T265.pyx
+0
-12
tests/run/bad_c_struct_T252.pyx
tests/run/bad_c_struct_T252.pyx
+4
-4
tests/run/cdivision_CEP_516.pyx
tests/run/cdivision_CEP_516.pyx
+15
-5
tests/run/complex_int_T446.pyx
tests/run/complex_int_T446.pyx
+46
-0
tests/run/complex_numbers_T305.pyx
tests/run/complex_numbers_T305.pyx
+43
-17
tests/run/cpp_exceptions.pyx
tests/run/cpp_exceptions.pyx
+1
-1
tests/run/cpp_exceptions_helper.h
tests/run/cpp_exceptions_helper.h
+0
-0
tests/run/forfrom.pyx
tests/run/forfrom.pyx
+3
-6
tests/run/index.pyx
tests/run/index.pyx
+8
-4
tests/run/int_literals.pyx
tests/run/int_literals.pyx
+12
-8
tests/run/ishimoto2.pyx
tests/run/ishimoto2.pyx
+3
-6
tests/run/list_pop.pyx
tests/run/list_pop.pyx
+81
-0
tests/run/modbody.pyx
tests/run/modbody.pyx
+6
-9
tests/run/new_style_exceptions.pyx
tests/run/new_style_exceptions.pyx
+3
-6
tests/run/profile_test.pyx
tests/run/profile_test.pyx
+4
-1
tests/run/r_bowden1.pyx
tests/run/r_bowden1.pyx
+7
-8
tests/run/tp_new.pyx
tests/run/tp_new.pyx
+139
-0
tests/run/typedfieldbug_T303.pyx
tests/run/typedfieldbug_T303.pyx
+7
-6
No files found.
.hgtags
View file @
416e3293
...
@@ -17,3 +17,4 @@ af6f1bed8cd40a2edefb57d3eacbc9274a8788b4 0.11.2.rc1
...
@@ -17,3 +17,4 @@ af6f1bed8cd40a2edefb57d3eacbc9274a8788b4 0.11.2.rc1
15ad532e2127840ae09dfbe46ccc80ac8c562f99 0.11.2
15ad532e2127840ae09dfbe46ccc80ac8c562f99 0.11.2
eb00d00a73c13b6aa8b440fe07cd7acb52a060e8 0.11.3.rc0
eb00d00a73c13b6aa8b440fe07cd7acb52a060e8 0.11.3.rc0
7c695fe49fd6912f52d995fe512d66baacf90ee6 0.11.3
7c695fe49fd6912f52d995fe512d66baacf90ee6 0.11.3
4208042ceeae634f5c0999b8ab75f69faf46b6db 0.12.alpha0
Cython/Compiler/Buffer.py
View file @
416e3293
...
@@ -245,8 +245,9 @@ def put_acquire_arg_buffer(entry, code, pos):
...
@@ -245,8 +245,9 @@ def put_acquire_arg_buffer(entry, code, pos):
# need to care about the buffer then.
# need to care about the buffer then.
put_unpack_buffer_aux_into_scope
(
buffer_aux
,
entry
.
type
.
mode
,
code
)
put_unpack_buffer_aux_into_scope
(
buffer_aux
,
entry
.
type
.
mode
,
code
)
def
get_release_buffer_code
(
entry
):
def
put_release_buffer_code
(
code
,
entry
):
return
"__Pyx_SafeReleaseBuffer(&%s)"
%
entry
.
buffer_aux
.
buffer_info_var
.
cname
code
.
globalstate
.
use_utility_code
(
acquire_utility_code
)
code
.
putln
(
"__Pyx_SafeReleaseBuffer(&%s);"
%
entry
.
buffer_aux
.
buffer_info_var
.
cname
)
def
get_getbuffer_call
(
code
,
obj_cname
,
buffer_aux
,
buffer_type
):
def
get_getbuffer_call
(
code
,
obj_cname
,
buffer_aux
,
buffer_type
):
ndim
=
buffer_type
.
ndim
ndim
=
buffer_type
.
ndim
...
...
Cython/Compiler/CmdLine.py
View file @
416e3293
...
@@ -17,7 +17,6 @@ Options:
...
@@ -17,7 +17,6 @@ Options:
-I, --include-dir <directory> Search for include files in named directory
-I, --include-dir <directory> Search for include files in named directory
(multiply include directories are allowed).
(multiply include directories are allowed).
-o, --output-file <filename> Specify name of generated C file
-o, --output-file <filename> Specify name of generated C file
-r, --recursive Recursively find and compile dependencies
-t, --timestamps Only compile newer source files (implied with -r)
-t, --timestamps Only compile newer source files (implied with -r)
-f, --force Compile all source files (overrides implied -t)
-f, --force Compile all source files (overrides implied -t)
-q, --quiet Don't print module names in recursive mode
-q, --quiet Don't print module names in recursive mode
...
@@ -40,6 +39,10 @@ Options:
...
@@ -40,6 +39,10 @@ Options:
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
"""
"""
# The following is broken http://trac.cython.org/cython_trac/ticket/379
# -r, --recursive Recursively find and compile dependencies
#The following experimental options are supported only on MacOSX:
#The following experimental options are supported only on MacOSX:
# -C, --compile Compile generated .c file to .o file
# -C, --compile Compile generated .c file to .o file
# --link Link .o file to produce extension module (implies -C)
# --link Link .o file to produce extension module (implies -C)
...
...
Cython/Compiler/Code.py
View file @
416e3293
...
@@ -408,8 +408,10 @@ class GlobalState(object):
...
@@ -408,8 +408,10 @@ class GlobalState(object):
code_layout = [
code_layout = [
'h_code',
'h_code',
'utility_code_proto_before_types',
'utility_code_proto_before_types',
'type_declarations',
'numeric_typedefs', # Let these detailed individual parts stay!,
'utility_code_proto',
'complex_type_declarations', # as the proper solution is to make a full DAG...
'type_declarations', # More coarse-grained blocks would simply hide
'utility_code_proto', # the ugliness, not fix it
'module_declarations',
'module_declarations',
'typeinfo',
'typeinfo',
'before_global_var',
'before_global_var',
...
...
Cython/Compiler/ExprNodes.py
View file @
416e3293
...
@@ -2572,7 +2572,7 @@ class SimpleCallNode(CallNode):
...
@@ -2572,7 +2572,7 @@ class SimpleCallNode(CallNode):
for
formal_arg
,
actual_arg
in
args
[
expected_nargs
:
actual_nargs
]:
for
formal_arg
,
actual_arg
in
args
[
expected_nargs
:
actual_nargs
]:
code
.
putln
(
"%s.%s = %s;"
%
(
code
.
putln
(
"%s.%s = %s;"
%
(
self
.
opt_arg_struct
,
self
.
opt_arg_struct
,
f
ormal_arg
.
name
,
f
unc_type
.
opt_arg_cname
(
formal_arg
.
name
)
,
actual_arg
.
result_as
(
formal_arg
.
type
)))
actual_arg
.
result_as
(
formal_arg
.
type
)))
exc_checks
=
[]
exc_checks
=
[]
if
self
.
type
.
is_pyobject
:
if
self
.
type
.
is_pyobject
:
...
@@ -5601,6 +5601,7 @@ class CoercionNode(ExprNode):
...
@@ -5601,6 +5601,7 @@ class CoercionNode(ExprNode):
# arg ExprNode node being coerced
# arg ExprNode node being coerced
subexprs
=
[
'arg'
]
subexprs
=
[
'arg'
]
constant_result
=
not_a_constant
def
__init__
(
self
,
arg
):
def
__init__
(
self
,
arg
):
self
.
pos
=
arg
.
pos
self
.
pos
=
arg
.
pos
...
...
Cython/Compiler/ModuleNode.py
View file @
416e3293
...
@@ -658,8 +658,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -658,8 +658,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def
generate_typedef
(
self
,
entry
,
code
):
def
generate_typedef
(
self
,
entry
,
code
):
base_type
=
entry
.
type
.
typedef_base_type
base_type
=
entry
.
type
.
typedef_base_type
code
.
putln
(
""
)
if
base_type
.
is_numeric
:
code
.
putln
(
"typedef %s;"
%
base_type
.
declaration_code
(
entry
.
cname
))
writer
=
code
.
globalstate
[
'numeric_typedefs'
]
else
:
writer
=
code
writer
.
putln
(
""
)
writer
.
putln
(
"typedef %s;"
%
base_type
.
declaration_code
(
entry
.
cname
))
def
sue_header_footer
(
self
,
type
,
kind
,
name
):
def
sue_header_footer
(
self
,
type
,
kind
,
name
):
if
type
.
typedef_flag
:
if
type
.
typedef_flag
:
...
...
Cython/Compiler/Nodes.py
View file @
416e3293
...
@@ -1180,7 +1180,7 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -1180,7 +1180,7 @@ class FuncDefNode(StatNode, BlockNode):
code
.
putln
(
"{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;"
)
code
.
putln
(
"{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;"
)
code
.
putln
(
"__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);"
)
code
.
putln
(
"__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);"
)
for
entry
in
lenv
.
buffer_entries
:
for
entry
in
lenv
.
buffer_entries
:
code
.
putln
(
"%s;"
%
Buffer
.
get_release_buffer_code
(
entry
)
)
Buffer
.
put_release_buffer_code
(
code
,
entry
)
#code.putln("%s = 0;" % entry.cname)
#code.putln("%s = 0;" % entry.cname)
code
.
putln
(
"__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}"
)
code
.
putln
(
"__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}"
)
...
@@ -1222,7 +1222,7 @@ class FuncDefNode(StatNode, BlockNode):
...
@@ -1222,7 +1222,7 @@ class FuncDefNode(StatNode, BlockNode):
code
.
put_label
(
code
.
return_label
)
code
.
put_label
(
code
.
return_label
)
for
entry
in
lenv
.
buffer_entries
:
for
entry
in
lenv
.
buffer_entries
:
if
entry
.
used
:
if
entry
.
used
:
code
.
putln
(
"%s;"
%
Buffer
.
get_release_buffer_code
(
entry
)
)
Buffer
.
put_release_buffer_code
(
code
,
entry
)
if
is_getbuffer_slot
:
if
is_getbuffer_slot
:
self
.
getbuffer_normal_cleanup
(
code
)
self
.
getbuffer_normal_cleanup
(
code
)
# ----- Return cleanup for both error and no-error return
# ----- Return cleanup for both error and no-error return
...
@@ -1519,13 +1519,11 @@ class CFuncDefNode(FuncDefNode):
...
@@ -1519,13 +1519,11 @@ class CFuncDefNode(FuncDefNode):
code
.
putln
(
'if (%s) {'
%
Naming
.
optional_args_cname
)
code
.
putln
(
'if (%s) {'
%
Naming
.
optional_args_cname
)
for
arg
in
self
.
args
:
for
arg
in
self
.
args
:
if
arg
.
default
:
if
arg
.
default
:
# FIXME: simple name prefixing doesn't work when
# argument name mangling is in place
code
.
putln
(
'if (%s->%sn > %s) {'
%
(
Naming
.
optional_args_cname
,
Naming
.
pyrex_prefix
,
i
))
code
.
putln
(
'if (%s->%sn > %s) {'
%
(
Naming
.
optional_args_cname
,
Naming
.
pyrex_prefix
,
i
))
declarator
=
arg
.
declarator
declarator
=
arg
.
declarator
while
not
hasattr
(
declarator
,
'name'
):
while
not
hasattr
(
declarator
,
'name'
):
declarator
=
declarator
.
base
declarator
=
declarator
.
base
code
.
putln
(
'%s = %s->%s;'
%
(
arg
.
cname
,
Naming
.
optional_args_cname
,
declarator
.
name
))
code
.
putln
(
'%s = %s->%s;'
%
(
arg
.
cname
,
Naming
.
optional_args_cname
,
self
.
type
.
opt_arg_cname
(
declarator
.
name
)
))
i
+=
1
i
+=
1
for
_
in
range
(
self
.
type
.
optional_arg_count
):
for
_
in
range
(
self
.
type
.
optional_arg_count
):
code
.
putln
(
'}'
)
code
.
putln
(
'}'
)
...
...
Cython/Compiler/Optimize.py
View file @
416e3293
...
@@ -7,6 +7,7 @@ import UtilNodes
...
@@ -7,6 +7,7 @@ import UtilNodes
import
TypeSlots
import
TypeSlots
import
Symtab
import
Symtab
import
Options
import
Options
import
Naming
from
Code
import
UtilityCode
from
Code
import
UtilityCode
from
StringEncoding
import
EncodedString
,
BytesLiteral
from
StringEncoding
import
EncodedString
,
BytesLiteral
...
@@ -755,7 +756,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -755,7 +756,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
### cleanup to avoid redundant coercions to/from Python types
### cleanup to avoid redundant coercions to/from Python types
def
visit_PyTypeTestNode
(
self
,
node
):
def
_visit_PyTypeTestNode
(
self
,
node
):
# disabled - appears to break assignments in some cases, and
# also drops a None check, which might still be required
"""Flatten redundant type checks after tree changes.
"""Flatten redundant type checks after tree changes.
"""
"""
old_arg
=
node
.
arg
old_arg
=
node
.
arg
...
@@ -832,6 +835,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -832,6 +835,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
else
:
else
:
return
function_handler
(
node
,
arg_tuple
)
return
function_handler
(
node
,
arg_tuple
)
elif
function
.
is_attribute
:
elif
function
.
is_attribute
:
attr_name
=
function
.
attribute
arg_list
=
arg_tuple
.
args
arg_list
=
arg_tuple
.
args
self_arg
=
function
.
obj
self_arg
=
function
.
obj
obj_type
=
self_arg
.
type
obj_type
=
self_arg
.
type
...
@@ -849,7 +853,12 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -849,7 +853,12 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
else
:
else
:
type_name
=
"object"
# safety measure
type_name
=
"object"
# safety measure
method_handler
=
self
.
_find_handler
(
method_handler
=
self
.
_find_handler
(
"method_%s_%s"
%
(
type_name
,
function
.
attribute
),
kwargs
)
"method_%s_%s"
%
(
type_name
,
attr_name
),
kwargs
)
if
method_handler
is
None
:
if
attr_name
in
TypeSlots
.
method_name_to_slot
\
or
attr_name
==
'__new__'
:
method_handler
=
self
.
_find_handler
(
"slot%s"
%
attr_name
,
kwargs
)
if
method_handler
is
None
:
if
method_handler
is
None
:
return
node
return
node
if
self_arg
is
not
None
:
if
self_arg
is
not
None
:
...
@@ -1030,6 +1039,51 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -1030,6 +1039,51 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
)
)
return
node
return
node
### special methods
Pyx_tp_new_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"type"
,
Builtin
.
type_type
,
None
)
])
def
_handle_simple_slot__new__
(
self
,
node
,
args
,
is_unbound_method
):
"""Replace 'exttype.__new__(exttype)' by a call to exttype->tp_new()
"""
obj
=
node
.
function
.
obj
if
not
is_unbound_method
or
len
(
args
)
!=
1
:
return
node
type_arg
=
args
[
0
]
if
not
obj
.
is_name
or
not
type_arg
.
is_name
:
# play safe
return
node
if
obj
.
type
!=
Builtin
.
type_type
or
type_arg
.
type
!=
Builtin
.
type_type
:
# not a known type, play safe
return
node
if
not
type_arg
.
type_entry
or
not
obj
.
type_entry
:
if
obj
.
name
!=
type_arg
.
name
:
return
node
# otherwise, we know it's a type and we know it's the same
# type for both - that should do
elif
type_arg
.
type_entry
!=
obj
.
type_entry
:
# different types - may or may not lead to an error at runtime
return
node
# FIXME: we could potentially look up the actual tp_new C method
# of the extension type and call that instead of the generic slot
if
not
type_arg
.
type_entry
:
# arbitrary variable, needs a None check for safety
type_arg
=
ExprNodes
.
NoneCheckNode
(
type_arg
,
"PyExc_TypeError"
,
"object.__new__(X): X is not a type object (NoneType)"
)
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"__Pyx_tp_new"
,
self
.
Pyx_tp_new_func_type
,
args
=
[
type_arg
],
utility_code
=
tpnew_utility_code
,
is_temp
=
node
.
is_temp
)
### methods of builtin types
### methods of builtin types
PyObject_Append_func_type
=
PyrexTypes
.
CFuncType
(
PyObject_Append_func_type
=
PyrexTypes
.
CFuncType
(
...
@@ -1050,6 +1104,40 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -1050,6 +1104,40 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
utility_code
=
append_utility_code
utility_code
=
append_utility_code
)
)
PyObject_Pop_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"list"
,
PyrexTypes
.
py_object_type
,
None
),
])
PyObject_PopIndex_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"list"
,
PyrexTypes
.
py_object_type
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"index"
,
PyrexTypes
.
c_long_type
,
None
),
])
def
_handle_simple_method_object_pop
(
self
,
node
,
args
,
is_unbound_method
):
# X.pop([n]) is almost always referring to a list
if
len
(
args
)
==
1
:
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"__Pyx_PyObject_Pop"
,
self
.
PyObject_Pop_func_type
,
args
=
args
,
is_temp
=
node
.
is_temp
,
utility_code
=
pop_utility_code
)
elif
len
(
args
)
==
2
:
if
isinstance
(
args
[
1
],
ExprNodes
.
CoerceToPyTypeNode
)
and
args
[
1
].
arg
.
type
.
is_int
:
original_type
=
args
[
1
].
arg
.
type
if
PyrexTypes
.
widest_numeric_type
(
original_type
,
PyrexTypes
.
c_py_ssize_t_type
)
==
PyrexTypes
.
c_py_ssize_t_type
:
args
[
1
]
=
args
[
1
].
arg
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"__Pyx_PyObject_PopIndex"
,
self
.
PyObject_PopIndex_func_type
,
args
=
args
,
is_temp
=
node
.
is_temp
,
utility_code
=
pop_index_utility_code
)
return
node
PyList_Append_func_type
=
PyrexTypes
.
CFuncType
(
PyList_Append_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
c_int_type
,
[
PyrexTypes
.
c_int_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"list"
,
PyrexTypes
.
py_object_type
,
None
),
PyrexTypes
.
CFuncTypeArg
(
"list"
,
PyrexTypes
.
py_object_type
,
None
),
...
@@ -1306,6 +1394,76 @@ impl = ""
...
@@ -1306,6 +1394,76 @@ impl = ""
)
)
pop_utility_code
=
UtilityCode
(
proto
=
"""
static INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
if (likely(PyList_CheckExact(L))
/* Check that both the size is positive and no reallocation shrinking needs to be done. */
&& likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
Py_SIZE(L) -= 1;
return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
}
else {
PyObject *r, *m;
m = __Pyx_GetAttrString(L, "pop");
if (!m) return NULL;
r = PyObject_CallObject(m, NULL);
Py_DECREF(m);
return r;
}
}
"""
,
impl
=
""
)
pop_index_utility_code
=
UtilityCode
(
proto
=
"""
static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix);
"""
,
impl
=
"""
static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
PyObject *r, *m, *t, *py_ix;
if (likely(PyList_CheckExact(L))) {
Py_ssize_t size = PyList_GET_SIZE(L);
if (likely(size > (((PyListObject*)L)->allocated >> 1))) {
if (ix < 0) {
ix += size;
}
if (likely(0 <= ix && ix < size)) {
Py_ssize_t i;
PyObject* v = PyList_GET_ITEM(L, ix);
Py_SIZE(L) -= 1;
size -= 1;
for(i=ix; i<size; i++) {
PyList_SET_ITEM(L, i, PyList_GET_ITEM(L, i+1));
}
return v;
}
}
}
py_ix = t = NULL;
m = __Pyx_GetAttrString(L, "pop");
if (!m) goto bad;
py_ix = PyInt_FromSsize_t(ix);
if (!py_ix) goto bad;
t = PyTuple_New(1);
if (!t) goto bad;
PyTuple_SET_ITEM(t, 0, py_ix);
py_ix = NULL;
r = PyObject_CallObject(m, t);
Py_DECREF(m);
Py_DECREF(t);
return r;
bad:
Py_XDECREF(m);
Py_XDECREF(t);
Py_XDECREF(py_ix);
return NULL;
}
"""
)
pytype_utility_code
=
UtilityCode
(
pytype_utility_code
=
UtilityCode
(
proto
=
"""
proto
=
"""
static INLINE PyObject* __Pyx_Type(PyObject* o) {
static INLINE PyObject* __Pyx_Type(PyObject* o) {
...
@@ -1317,6 +1475,16 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) {
...
@@ -1317,6 +1475,16 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) {
)
)
tpnew_utility_code
=
UtilityCode
(
proto
=
"""
static 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
):
"""Calculate the result of constant expressions to store it in
"""Calculate the result of constant expressions to store it in
``expr_node.constant_result``, and replace trivial cases by their
``expr_node.constant_result``, and replace trivial cases by their
...
...
Cython/Compiler/PyrexTypes.py
View file @
416e3293
...
@@ -871,6 +871,17 @@ class CComplexType(CNumericType):
...
@@ -871,6 +871,17 @@ class CComplexType(CNumericType):
scope
=
None
scope
=
None
def
__init__
(
self
,
real_type
):
def
__init__
(
self
,
real_type
):
while
real_type
.
is_typedef
and
not
real_type
.
typedef_is_external
:
real_type
=
real_type
.
typedef_base_type
if
real_type
.
is_typedef
and
real_type
.
typedef_is_external
:
# The below is not actually used: Coercions are currently disabled
# so that complex types of external types can not be created
self
.
funcsuffix
=
"_%s"
%
real_type
.
specalization_name
()
elif
hasattr
(
real_type
,
'math_h_modifier'
):
self
.
funcsuffix
=
real_type
.
math_h_modifier
else
:
self
.
funcsuffix
=
"_%s"
%
real_type
.
specalization_name
()
self
.
real_type
=
real_type
self
.
real_type
=
real_type
CNumericType
.
__init__
(
self
,
real_type
.
rank
+
0.5
,
real_type
.
signed
)
CNumericType
.
__init__
(
self
,
real_type
.
rank
+
0.5
,
real_type
.
signed
)
self
.
binops
=
{}
self
.
binops
=
{}
...
@@ -883,6 +894,12 @@ class CComplexType(CNumericType):
...
@@ -883,6 +894,12 @@ class CComplexType(CNumericType):
else
:
else
:
return
False
return
False
def
__ne__
(
self
,
other
):
if
isinstance
(
self
,
CComplexType
)
and
isinstance
(
other
,
CComplexType
):
return
self
.
real_type
!=
other
.
real_type
else
:
return
True
def
__lt__
(
self
,
other
):
def
__lt__
(
self
,
other
):
if
isinstance
(
self
,
CComplexType
)
and
isinstance
(
other
,
CComplexType
):
if
isinstance
(
self
,
CComplexType
)
and
isinstance
(
other
,
CComplexType
):
return
self
.
real_type
<
other
.
real_type
return
self
.
real_type
<
other
.
real_type
...
@@ -907,6 +924,14 @@ class CComplexType(CNumericType):
...
@@ -907,6 +924,14 @@ class CComplexType(CNumericType):
real_type_name
=
real_type_name
.
replace
(
'long__double'
,
'long_double'
)
real_type_name
=
real_type_name
.
replace
(
'long__double'
,
'long_double'
)
return
Naming
.
type_prefix
+
real_type_name
+
"_complex"
return
Naming
.
type_prefix
+
real_type_name
+
"_complex"
def
assignable_from
(
self
,
src_type
):
# Temporary hack/feature disabling, see #441
if
(
not
src_type
.
is_complex
and
src_type
.
is_numeric
and
src_type
.
is_typedef
and
src_type
.
typedef_is_external
):
return
False
else
:
return
super
(
CComplexType
,
self
).
assignable_from
(
src_type
)
def
assignable_from_resolved_type
(
self
,
src_type
):
def
assignable_from_resolved_type
(
self
,
src_type
):
return
(
src_type
.
is_complex
and
self
.
real_type
.
assignable_from_resolved_type
(
src_type
.
real_type
)
return
(
src_type
.
is_complex
and
self
.
real_type
.
assignable_from_resolved_type
(
src_type
.
real_type
)
or
src_type
.
is_numeric
and
self
.
real_type
.
assignable_from_resolved_type
(
src_type
)
or
src_type
.
is_numeric
and
self
.
real_type
.
assignable_from_resolved_type
(
src_type
)
...
@@ -927,7 +952,7 @@ class CComplexType(CNumericType):
...
@@ -927,7 +952,7 @@ class CComplexType(CNumericType):
CFuncType
(
self
,
[
CFuncTypeArg
(
"self"
,
self
,
None
)]),
CFuncType
(
self
,
[
CFuncTypeArg
(
"self"
,
self
,
None
)]),
pos
=
None
,
pos
=
None
,
defining
=
1
,
defining
=
1
,
cname
=
"__Pyx_c_conj%s"
%
self
.
real_type
.
math_h_modifier
)
cname
=
"__Pyx_c_conj%s"
%
self
.
funcsuffix
)
return
True
return
True
...
@@ -943,7 +968,7 @@ class CComplexType(CNumericType):
...
@@ -943,7 +968,7 @@ class CComplexType(CNumericType):
utility_code
.
specialize
(
utility_code
.
specialize
(
self
,
self
,
real_type
=
self
.
real_type
.
declaration_code
(
''
),
real_type
=
self
.
real_type
.
declaration_code
(
''
),
m
=
self
.
real_type
.
math_h_modifier
))
m
=
self
.
funcsuffix
))
return
True
return
True
def
create_to_py_utility_code
(
self
,
env
):
def
create_to_py_utility_code
(
self
,
env
):
...
@@ -960,7 +985,7 @@ class CComplexType(CNumericType):
...
@@ -960,7 +985,7 @@ class CComplexType(CNumericType):
utility_code
.
specialize
(
utility_code
.
specialize
(
self
,
self
,
real_type
=
self
.
real_type
.
declaration_code
(
''
),
real_type
=
self
.
real_type
.
declaration_code
(
''
),
m
=
self
.
real_type
.
math_h_modifier
))
m
=
self
.
funcsuffix
))
self
.
from_py_function
=
"__Pyx_PyComplex_As_"
+
self
.
specalization_name
()
self
.
from_py_function
=
"__Pyx_PyComplex_As_"
+
self
.
specalization_name
()
return
True
return
True
...
@@ -971,8 +996,7 @@ class CComplexType(CNumericType):
...
@@ -971,8 +996,7 @@ class CComplexType(CNumericType):
pass
pass
try
:
try
:
op_name
=
complex_ops
[
nargs
,
op
]
op_name
=
complex_ops
[
nargs
,
op
]
modifier
=
self
.
real_type
.
math_h_modifier
self
.
binops
[
nargs
,
op
]
=
func_name
=
"__Pyx_c_%s%s"
%
(
op_name
,
self
.
funcsuffix
)
self
.
binops
[
nargs
,
op
]
=
func_name
=
"__Pyx_c_%s%s"
%
(
op_name
,
modifier
)
return
func_name
return
func_name
except
KeyError
:
except
KeyError
:
return
None
return
None
...
@@ -1032,7 +1056,7 @@ proto="""
...
@@ -1032,7 +1056,7 @@ proto="""
"""
)
"""
)
complex_type_utility_code
=
UtilityCode
(
complex_type_utility_code
=
UtilityCode
(
proto_block
=
'
utility_code_proto_before_type
s'
,
proto_block
=
'
complex_type_declaration
s'
,
proto
=
"""
proto
=
"""
#if CYTHON_CCOMPLEX
#if CYTHON_CCOMPLEX
#ifdef __cplusplus
#ifdef __cplusplus
...
@@ -1113,7 +1137,7 @@ proto="""
...
@@ -1113,7 +1137,7 @@ proto="""
#define __Pyx_c_quot%(m)s(a, b) ((a)/(b))
#define __Pyx_c_quot%(m)s(a, b) ((a)/(b))
#define __Pyx_c_neg%(m)s(a) (-(a))
#define __Pyx_c_neg%(m)s(a) (-(a))
#ifdef __cplusplus
#ifdef __cplusplus
#define __Pyx_c_is_zero%(m)s(z) ((z)==
0.
0)
#define __Pyx_c_is_zero%(m)s(z) ((z)==
(%(real_type)s)
0)
#define __Pyx_c_conj%(m)s(z) (::std::conj(z))
#define __Pyx_c_conj%(m)s(z) (::std::conj(z))
/*#define __Pyx_c_abs%(m)s(z) (::std::abs(z))*/
/*#define __Pyx_c_abs%(m)s(z) (::std::abs(z))*/
#else
#else
...
@@ -1191,7 +1215,6 @@ impl="""
...
@@ -1191,7 +1215,6 @@ impl="""
#endif
#endif
"""
)
"""
)
class
CArrayType
(
CType
):
class
CArrayType
(
CType
):
# base_type CType Element type
# base_type CType Element type
# size integer or None Number of elements
# size integer or None Number of elements
...
@@ -1513,6 +1536,9 @@ class CFuncType(CType):
...
@@ -1513,6 +1536,9 @@ class CFuncType(CType):
s
=
self
.
declaration_code
(
"(*)"
,
with_calling_convention
=
False
)
s
=
self
.
declaration_code
(
"(*)"
,
with_calling_convention
=
False
)
return
'(%s)'
%
s
return
'(%s)'
%
s
def
opt_arg_cname
(
self
,
arg_name
):
return
self
.
op_arg_struct
.
base_type
.
scope
.
lookup
(
arg_name
).
cname
class
CFuncTypeArg
(
object
):
class
CFuncTypeArg
(
object
):
# name string
# name string
...
...
Cython/Compiler/Version.py
View file @
416e3293
version
=
'0.1
1.3
'
version
=
'0.1
2.alpha0
'
MANIFEST.in
View file @
416e3293
...
@@ -16,7 +16,7 @@ include Demos/embed/*
...
@@ -16,7 +16,7 @@ include Demos/embed/*
include Demos/freeze/*
include Demos/freeze/*
include Demos/Setup.py
include Demos/Setup.py
include Demos/Makefile*
include Demos/Makefile*
include Tools/
*
recursive-include Tools
*
recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt
recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt
include runtests.py
include runtests.py
...
...
runtests.py
View file @
416e3293
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
import
os
import
os
import
sys
import
sys
import
re
import
re
import
gc
import
codecs
import
codecs
import
shutil
import
shutil
import
unittest
import
unittest
...
@@ -99,7 +100,7 @@ class ErrorWriter(object):
...
@@ -99,7 +100,7 @@ class ErrorWriter(object):
class
TestBuilder
(
object
):
class
TestBuilder
(
object
):
def
__init__
(
self
,
rootdir
,
workdir
,
selectors
,
exclude_selectors
,
annotate
,
def
__init__
(
self
,
rootdir
,
workdir
,
selectors
,
exclude_selectors
,
annotate
,
cleanup_workdir
,
cleanup_sharedlibs
,
with_pyregr
,
cython_only
,
cleanup_workdir
,
cleanup_sharedlibs
,
with_pyregr
,
cython_only
,
languages
,
test_bugs
):
languages
,
test_bugs
,
fork
):
self
.
rootdir
=
rootdir
self
.
rootdir
=
rootdir
self
.
workdir
=
workdir
self
.
workdir
=
workdir
self
.
selectors
=
selectors
self
.
selectors
=
selectors
...
@@ -111,6 +112,7 @@ class TestBuilder(object):
...
@@ -111,6 +112,7 @@ class TestBuilder(object):
self
.
cython_only
=
cython_only
self
.
cython_only
=
cython_only
self
.
languages
=
languages
self
.
languages
=
languages
self
.
test_bugs
=
test_bugs
self
.
test_bugs
=
test_bugs
self
.
fork
=
fork
def
build_suite
(
self
):
def
build_suite
(
self
):
suite
=
unittest
.
TestSuite
()
suite
=
unittest
.
TestSuite
()
...
@@ -192,12 +194,13 @@ class TestBuilder(object):
...
@@ -192,12 +194,13 @@ class TestBuilder(object):
annotate
=
self
.
annotate
,
annotate
=
self
.
annotate
,
cleanup_workdir
=
self
.
cleanup_workdir
,
cleanup_workdir
=
self
.
cleanup_workdir
,
cleanup_sharedlibs
=
self
.
cleanup_sharedlibs
,
cleanup_sharedlibs
=
self
.
cleanup_sharedlibs
,
cython_only
=
self
.
cython_only
)
cython_only
=
self
.
cython_only
,
fork
=
self
.
fork
)
class
CythonCompileTestCase
(
unittest
.
TestCase
):
class
CythonCompileTestCase
(
unittest
.
TestCase
):
def
__init__
(
self
,
directory
,
workdir
,
module
,
language
=
'c'
,
def
__init__
(
self
,
directory
,
workdir
,
module
,
language
=
'c'
,
expect_errors
=
False
,
annotate
=
False
,
cleanup_workdir
=
True
,
expect_errors
=
False
,
annotate
=
False
,
cleanup_workdir
=
True
,
cleanup_sharedlibs
=
True
,
cython_only
=
False
):
cleanup_sharedlibs
=
True
,
cython_only
=
False
,
fork
=
True
):
self
.
directory
=
directory
self
.
directory
=
directory
self
.
workdir
=
workdir
self
.
workdir
=
workdir
self
.
module
=
module
self
.
module
=
module
...
@@ -207,6 +210,7 @@ class CythonCompileTestCase(unittest.TestCase):
...
@@ -207,6 +210,7 @@ class CythonCompileTestCase(unittest.TestCase):
self
.
cleanup_workdir
=
cleanup_workdir
self
.
cleanup_workdir
=
cleanup_workdir
self
.
cleanup_sharedlibs
=
cleanup_sharedlibs
self
.
cleanup_sharedlibs
=
cleanup_sharedlibs
self
.
cython_only
=
cython_only
self
.
cython_only
=
cython_only
self
.
fork
=
fork
unittest
.
TestCase
.
__init__
(
self
)
unittest
.
TestCase
.
__init__
(
self
)
def
shortDescription
(
self
):
def
shortDescription
(
self
):
...
@@ -391,8 +395,9 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -391,8 +395,9 @@ class CythonRunTestCase(CythonCompileTestCase):
pass
pass
def
run_doctests
(
self
,
module_name
,
result
):
def
run_doctests
(
self
,
module_name
,
result
):
if
sys
.
version_info
[
0
]
>=
3
or
not
hasattr
(
os
,
'fork'
):
if
sys
.
version_info
[
0
]
>=
3
or
not
hasattr
(
os
,
'fork'
)
or
not
self
.
fork
:
doctest
.
DocTestSuite
(
module_name
).
run
(
result
)
doctest
.
DocTestSuite
(
module_name
).
run
(
result
)
gc
.
collect
()
return
return
# fork to make sure we do not keep the tested module loaded
# fork to make sure we do not keep the tested module loaded
...
@@ -407,11 +412,13 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -407,11 +412,13 @@ class CythonRunTestCase(CythonCompileTestCase):
partial_result
=
PartialTestResult
(
result
)
partial_result
=
PartialTestResult
(
result
)
tests
=
doctest
.
DocTestSuite
(
module_name
)
tests
=
doctest
.
DocTestSuite
(
module_name
)
tests
.
run
(
partial_result
)
tests
.
run
(
partial_result
)
gc
.
collect
()
except
Exception
:
except
Exception
:
if
tests
is
None
:
if
tests
is
None
:
# importing failed, try to fake a test class
# importing failed, try to fake a test class
tests
=
_FakeClass
(
tests
=
_FakeClass
(
failureException
=
None
,
failureException
=
None
,
shortDescription
=
self
.
shortDescription
,
**
{
module_name
:
None
})
**
{
module_name
:
None
})
partial_result
.
addError
(
tests
,
sys
.
exc_info
())
partial_result
.
addError
(
tests
,
sys
.
exc_info
())
result_code
=
1
result_code
=
1
...
@@ -421,9 +428,13 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -421,9 +428,13 @@ class CythonRunTestCase(CythonCompileTestCase):
except
:
pass
except
:
pass
os
.
_exit
(
result_code
)
os
.
_exit
(
result_code
)
cid
,
result_code
=
os
.
waitpid
(
child_id
,
0
)
if
result_code
in
(
0
,
1
):
input
=
os
.
fdopen
(
input
,
'rb'
)
input
=
os
.
fdopen
(
input
,
'rb'
)
try
:
PartialTestResult
.
join_results
(
result
,
pickle
.
load
(
input
))
PartialTestResult
.
join_results
(
result
,
pickle
.
load
(
input
))
cid
,
result_code
=
os
.
waitpid
(
child_id
,
0
)
finally
:
input
.
close
()
if
result_code
:
if
result_code
:
raise
Exception
(
"Tests in module '%s' exited with status %d"
%
raise
Exception
(
"Tests in module '%s' exited with status %d"
%
(
module_name
,
result_code
>>
8
))
(
module_name
,
result_code
>>
8
))
...
@@ -663,6 +674,9 @@ if __name__ == '__main__':
...
@@ -663,6 +674,9 @@ if __name__ == '__main__':
parser
.
add_option
(
"--no-refnanny"
,
dest
=
"with_refnanny"
,
parser
.
add_option
(
"--no-refnanny"
,
dest
=
"with_refnanny"
,
action
=
"store_false"
,
default
=
True
,
action
=
"store_false"
,
default
=
True
,
help
=
"do not regression test reference counting"
)
help
=
"do not regression test reference counting"
)
parser
.
add_option
(
"--no-fork"
,
dest
=
"fork"
,
action
=
"store_false"
,
default
=
True
,
help
=
"do not fork to run tests"
)
parser
.
add_option
(
"--sys-pyregr"
,
dest
=
"system_pyregr"
,
parser
.
add_option
(
"--sys-pyregr"
,
dest
=
"system_pyregr"
,
action
=
"store_true"
,
default
=
False
,
action
=
"store_true"
,
default
=
False
,
help
=
"run the regression tests of the CPython installation"
)
help
=
"run the regression tests of the CPython installation"
)
...
@@ -814,14 +828,16 @@ if __name__ == '__main__':
...
@@ -814,14 +828,16 @@ if __name__ == '__main__':
filetests
=
TestBuilder
(
ROOTDIR
,
WORKDIR
,
selectors
,
exclude_selectors
,
filetests
=
TestBuilder
(
ROOTDIR
,
WORKDIR
,
selectors
,
exclude_selectors
,
options
.
annotate_source
,
options
.
cleanup_workdir
,
options
.
annotate_source
,
options
.
cleanup_workdir
,
options
.
cleanup_sharedlibs
,
options
.
pyregr
,
options
.
cleanup_sharedlibs
,
options
.
pyregr
,
options
.
cython_only
,
languages
,
test_bugs
)
options
.
cython_only
,
languages
,
test_bugs
,
options
.
fork
)
test_suite
.
addTest
(
filetests
.
build_suite
())
test_suite
.
addTest
(
filetests
.
build_suite
())
if
options
.
system_pyregr
and
languages
:
if
options
.
system_pyregr
and
languages
:
filetests
=
TestBuilder
(
ROOTDIR
,
WORKDIR
,
selectors
,
exclude_selectors
,
filetests
=
TestBuilder
(
ROOTDIR
,
WORKDIR
,
selectors
,
exclude_selectors
,
options
.
annotate_source
,
options
.
cleanup_workdir
,
options
.
annotate_source
,
options
.
cleanup_workdir
,
options
.
cleanup_sharedlibs
,
True
,
options
.
cleanup_sharedlibs
,
True
,
options
.
cython_only
,
languages
,
test_bugs
)
options
.
cython_only
,
languages
,
test_bugs
,
options
.
fork
)
test_suite
.
addTest
(
test_suite
.
addTest
(
filetests
.
handle_directory
(
filetests
.
handle_directory
(
os
.
path
.
join
(
sys
.
prefix
,
'lib'
,
'python'
+
sys
.
version
[:
3
],
'test'
),
os
.
path
.
join
(
sys
.
prefix
,
'lib'
,
'python'
+
sys
.
version
[:
3
],
'test'
),
...
...
tests/bugs.txt
View file @
416e3293
...
@@ -5,5 +5,4 @@ methodmangling_T5
...
@@ -5,5 +5,4 @@ methodmangling_T5
class_attribute_init_values_T18
class_attribute_init_values_T18
numpy_ValueError_T172
numpy_ValueError_T172
unsignedbehaviour_T184
unsignedbehaviour_T184
bad_c_struct_T252
missing_baseclass_in_predecl_T262
missing_baseclass_in_predecl_T262
tests/compile/bufaccess_noassignT444.pyx
0 → 100644
View file @
416e3293
def
test
():
cdef
object
[
int
]
not_assigned_to
not_assigned_to
[
2
]
=
3
tests/compile/cpp_exceptions.h
deleted
100644 → 0
View file @
ae714eac
extern
int
generic_error
(
void
);
extern
int
specified_error
(
void
);
extern
int
dynamic_error
(
void
);
tests/compile/cpp_exceptions_T265.pyx
deleted
100644 → 0
View file @
ae714eac
cdef
void
raise_py_error
():
pass
cdef
extern
from
"cpp_exceptions.h"
:
cdef
int
generic_error
()
except
+
cdef
int
specified_error
()
except
+
MemoryError
cdef
int
dynamic_error
()
except
+
raise_py_error
def
test_it
():
generic_error
()
specified_error
()
dynamic_error
()
tests/run/bad_c_struct_T252.pyx
View file @
416e3293
cdef
cf
(
default
=
None
):
cdef
cf
(
default
=
None
):
return
default
return
default
cpdef
cpf
(
default
=
None
):
cpdef
cpf
(
default
=
100
):
"""
"""
>>> cpf()
>>> cpf()
None
100
>>> cpf(1)
>>> cpf(1)
1
1
>>> cpf(default=2)
>>> cpf(default=2)
...
@@ -13,10 +13,10 @@ cpdef cpf(default=None):
...
@@ -13,10 +13,10 @@ cpdef cpf(default=None):
default
=
cf
(
default
)
default
=
cf
(
default
)
return
default
return
default
def
pf
(
default
=
None
):
def
pf
(
default
=
100
):
"""
"""
>>> pf()
>>> pf()
None
100
>>> pf(1)
>>> pf(1)
1
1
>>> pf(default=2)
>>> pf(default=2)
...
...
tests/run/cdivision_CEP_516.pyx
View file @
416e3293
...
@@ -31,12 +31,16 @@ True
...
@@ -31,12 +31,16 @@ True
True
True
>>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
>>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
True
"""
>>> def simple_warn(msg, *args): print(msg)
import
warnings
>>> import warnings
orig_showwarning
=
warnings
.
showwarning
>>> warnings.showwarning = simple_warn
true_py_functions
=
{}
exec
"def simple_warn(msg, *args): print(msg)"
in
true_py_functions
simple_warn
=
true_py_functions
[
'simple_warn'
]
del
true_py_functions
"""
def
_all
(
seq
):
def
_all
(
seq
):
for
x
in
seq
:
for
x
in
seq
:
...
@@ -100,9 +104,11 @@ def test_cdiv_cmod(short a, short b):
...
@@ -100,9 +104,11 @@ def test_cdiv_cmod(short a, short b):
@
cython
.
cdivision_warnings
(
True
)
@
cython
.
cdivision_warnings
(
True
)
def
mod_int_c_warn
(
int
a
,
int
b
):
def
mod_int_c_warn
(
int
a
,
int
b
):
"""
"""
>>> warnings.showwarning = simple_warn
>>> mod_int_c_warn(-17, 10)
>>> mod_int_c_warn(-17, 10)
division with oppositely signed operands, C and Python semantics differ
division with oppositely signed operands, C and Python semantics differ
-7
-7
>>> warnings.showwarning = orig_showwarning
"""
"""
return
a
%
b
return
a
%
b
...
@@ -110,9 +116,11 @@ def mod_int_c_warn(int a, int b):
...
@@ -110,9 +116,11 @@ def mod_int_c_warn(int a, int b):
@
cython
.
cdivision_warnings
(
True
)
@
cython
.
cdivision_warnings
(
True
)
def
div_int_c_warn
(
int
a
,
int
b
):
def
div_int_c_warn
(
int
a
,
int
b
):
"""
"""
>>> warnings.showwarning = simple_warn
>>> div_int_c_warn(-17, 10)
>>> div_int_c_warn(-17, 10)
division with oppositely signed operands, C and Python semantics differ
division with oppositely signed operands, C and Python semantics differ
-1
-1
>>> warnings.showwarning = orig_showwarning
"""
"""
return
a
//
b
return
a
//
b
...
@@ -120,12 +128,14 @@ def div_int_c_warn(int a, int b):
...
@@ -120,12 +128,14 @@ def div_int_c_warn(int a, int b):
@
cython
.
cdivision_warnings
(
True
)
@
cython
.
cdivision_warnings
(
True
)
def
complex_expression
(
int
a
,
int
b
,
int
c
,
int
d
):
def
complex_expression
(
int
a
,
int
b
,
int
c
,
int
d
):
"""
"""
>>> warnings.showwarning = simple_warn
>>> complex_expression(-150, 20, 19, -7)
>>> complex_expression(-150, 20, 19, -7)
verbose_call(20)
verbose_call(20)
division with oppositely signed operands, C and Python semantics differ
division with oppositely signed operands, C and Python semantics differ
verbose_call(19)
verbose_call(19)
division with oppositely signed operands, C and Python semantics differ
division with oppositely signed operands, C and Python semantics differ
-2
-2
>>> warnings.showwarning = orig_showwarning
"""
"""
return
(
a
//
verbose_call
(
b
))
%
(
verbose_call
(
c
)
//
d
)
return
(
a
//
verbose_call
(
b
))
%
(
verbose_call
(
c
)
//
d
)
...
...
tests/run/complex_int_T446.pyx
0 → 100644
View file @
416e3293
import
cython
def
test_arith
(
int
complex
a
,
int
complex
b
):
"""
>>> test_arith(4, 2)
((-4+0j), (6+0j), (2+0j), (8+0j), (2+0j))
>>> test_arith(6+9j, 3j)
((-6-9j), (6+12j), (6+6j), (-27+18j), (3-2j))
>>> test_arith(29+11j, 5+7j)
((-29-11j), (34+18j), (24+4j), (68+258j), (3-2j))
"""
return
-
a
,
a
+
b
,
a
-
b
,
a
*
b
,
a
/
b
@
cython
.
cdivision
(
False
)
def
test_div_by_zero
(
long
complex
z
):
"""
>>> test_div_by_zero(4j)
-25j
>>> test_div_by_zero(0)
Traceback (most recent call last):
...
ZeroDivisionError: float division
"""
return
100
/
z
def
test_coercion
(
int
a
,
long
b
,
int
complex
c
):
"""
>>> test_coercion(1, -2, 3-3j)
(1+0j)
(-2+0j)
(3-3j)
(5-6j)
"""
cdef
double
complex
z
z
=
a
;
print
z
z
=
b
;
print
z
z
=
c
;
print
z
return
z
+
a
+
b
+
c
def
test_conjugate
(
long
complex
z
):
"""
>>> test_conjugate(2+3j)
(2-3j)
"""
return
z
.
conjugate
()
\ No newline at end of file
tests/run/complex_numbers_T305.pyx
View file @
416e3293
#cdef extern from "complex.h":
# pass
cimport
cython
cimport
cython
def
test_object_conversion
(
o
):
def
test_object_conversion
(
o
):
...
@@ -23,21 +20,20 @@ def test_arithmetic(double complex z, double complex w):
...
@@ -23,21 +20,20 @@ def test_arithmetic(double complex z, double complex w):
((6+12j), (-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j))
((6+12j), (-6-12j), (6+15j), (6+9j), (-36+18j), (4-2j))
>>> test_arithmetic(5-10j, 3+4j)
>>> test_arithmetic(5-10j, 3+4j)
((5-10j), (-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j))
((5-10j), (-5+10j), (8-6j), (2-14j), (55-10j), (-1-2j))
## XXX this is not working
## >>> test_div_by_zero(4j)
## -0.25j
## >>> test_div_by_zero(0)
## Traceback (most recent call last):
## ...
## ZeroDivisionError: float division
"""
"""
return
+
z
,
-
z
,
z
+
w
,
z
-
w
,
z
*
w
,
z
/
w
return
+
z
,
-
z
,
z
+
w
,
z
-
w
,
z
*
w
,
z
/
w
## XXX this is not working
@
cython
.
cdivision
(
False
)
## @cython.cdivision(False)
def
test_div_by_zero
(
double
complex
z
):
## def test_div_by_zero(double complex z):
"""
## return 1/z
>>> test_div_by_zero(4j)
-0.25j
>>> test_div_by_zero(0)
Traceback (most recent call last):
...
ZeroDivisionError: float division
"""
return
1
/
z
def
test_coercion
(
int
a
,
float
b
,
double
c
,
float
complex
d
,
double
complex
e
):
def
test_coercion
(
int
a
,
float
b
,
double
c
,
float
complex
d
,
double
complex
e
):
"""
"""
...
@@ -127,13 +123,43 @@ def test_conjugate_double(double complex z):
...
@@ -127,13 +123,43 @@ def test_conjugate_double(double complex z):
ctypedef
double
complex
cdouble
ctypedef
double
complex
cdouble
def
test_conjugate_typedef
(
cdouble
z
):
def
test_conjugate_typedef
(
cdouble
z
):
"""
>>> test_conjugate_typedef(2+3j)
(2-3j)
"""
return
z
.
conjugate
()
return
z
.
conjugate
()
## cdef extern from "complex_numbers_T305.h":
## ctypedef double double_really_float "myfloat"
## ctypedef float float_really_double "mydouble"
## ctypedef float real_float "myfloat"
## ctypedef double real_double "mydouble"
## def test_conjugate_nosizeassumptions(double_really_float x,
## float_really_double y,
## real_float z, real_double w):
## """
## >>> test_conjugate_nosizeassumptions(1, 1, 1, 1)
## (-1j, -1j, -1j, -1j)
## >>> ["%.2f" % x.imag for x in test_conjugate_nosizeassumptions(2e300, 2e300, 2e300, 2e300)]
## ['-inf', '-2e+300', '-inf', '-2e+300']
## """
## cdef double complex I = 1j
## return ((x*I).conjugate(), (y*I).conjugate(), (z*I).conjugate(), (w*I).conjugate())
ctypedef
double
mydouble
ctypedef
double
mydouble
def
test_coerce_typedef_multiply
(
mydouble
x
,
double
complex
z
):
def
test_coerce_typedef_multiply
(
mydouble
x
,
double
complex
z
):
"""
"""
>>> test_coerce_typedef_multiply(3, 1j)
>>> test_coerce_typedef_multiply(3, 1+1j)
(3j)
(3+3j)
"""
return
x
*
z
ctypedef
int
myint
def
test_coerce_typedef_multiply_int
(
myint
x
,
double
complex
z
):
"""
>>> test_coerce_typedef_multiply_int(3, 1+1j)
(3+3j)
"""
"""
return
x
*
z
return
x
*
z
...
...
tests/run/cpp_exceptions.pyx
View file @
416e3293
cdef
int
raise_py_error
()
except
*
:
cdef
int
raise_py_error
()
except
*
:
raise
TypeError
(
"custom"
)
raise
TypeError
(
"custom"
)
cdef
extern
from
"cpp_exceptions_helper.
cpp
"
:
cdef
extern
from
"cpp_exceptions_helper.
h
"
:
cdef
int
raise_int_raw
"raise_int"
(
bint
fire
)
except
+
cdef
int
raise_int_raw
"raise_int"
(
bint
fire
)
except
+
cdef
int
raise_int_value
"raise_int"
(
bint
fire
)
except
+
ValueError
cdef
int
raise_int_value
"raise_int"
(
bint
fire
)
except
+
ValueError
cdef
int
raise_int_custom
"raise_int"
(
bint
fire
)
except
+
raise_py_error
cdef
int
raise_int_custom
"raise_int"
(
bint
fire
)
except
+
raise_py_error
...
...
tests/run/cpp_exceptions_helper.
cpp
→
tests/run/cpp_exceptions_helper.
h
View file @
416e3293
File moved
tests/run/forfrom.pyx
View file @
416e3293
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u" u'"
,
u" '"
).
replace
(
u' u"'
,
u' "'
)
def
for_else
():
def
for_else
():
"""
"""
>>> for_else()
>>> for_else()
30
30
>>> print(
u'*'.join(int_comp()
) )
>>> print(
int_comp(
) )
00*01*02
00*01*02
"""
"""
cdef
int
i
,
j
=
0
,
k
=
2
cdef
int
i
,
j
=
0
,
k
=
2
...
@@ -18,5 +15,5 @@ def for_else():
...
@@ -18,5 +15,5 @@ def for_else():
def
int_comp
():
def
int_comp
():
cdef
int
i
cdef
int
i
return
tuple
([
u"%02d"
%
i
return
u'*'
.
join
(
tuple
([
u"%02d"
%
i
for
i
from
0
<=
i
<
3
]
)
for
i
from
0
<=
i
<
3
])
)
tests/run/index.pyx
View file @
416e3293
__doc__
=
u"""
>>> index_object(100, 100)
Traceback (most recent call last):
...
TypeError: 'int' object is unsubscriptable
"""
import
sys
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u'is unsubscriptable'
,
u'is not subscriptable'
)
__doc__
=
__doc__
.
replace
(
u'is unsubscriptable'
,
u'is not subscriptable'
)
elif
sys
.
version_info
<
(
2
,
5
):
elif
sys
.
version_info
<
(
2
,
5
):
__doc__
=
__doc__
.
replace
(
u"'int' object is unsubscriptable"
,
u'unsubscriptable object'
)
__doc__
=
__doc__
.
replace
(
u"'int' object is unsubscriptable"
,
u'unsubscriptable object'
)
def
index_tuple
(
tuple
t
,
int
i
):
def
index_tuple
(
tuple
t
,
int
i
):
"""
"""
>>> index_tuple((1,1,2,3,5), 0)
>>> index_tuple((1,1,2,3,5), 0)
...
@@ -52,10 +60,6 @@ def index_object(object o, int i):
...
@@ -52,10 +60,6 @@ def index_object(object o, int i):
Traceback (most recent call last):
Traceback (most recent call last):
...
...
IndexError: string index out of range
IndexError: string index out of range
>>> index_object(100, 100)
Traceback (most recent call last):
...
TypeError: 'int' object is unsubscriptable
"""
"""
return
o
[
i
]
return
o
[
i
]
...
...
tests/run/int_literals.pyx
View file @
416e3293
__doc__
=
u"""
>>> c_longs()
(1, 1L, -1L, 18446744073709551615L)
>>> py_longs()
(1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L)
"""
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u'L'
,
u''
)
import
sys
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u'L'
,
u''
)
__doc__
=
__doc__
.
replace
(
u'L'
,
u''
)
def
c_longs
():
def
c_longs
():
"""
>>> c_longs()
(1, 1L, -1L, 18446744073709551615L)
"""
cdef
long
a
=
1L
cdef
long
a
=
1L
cdef
unsigned
long
ua
=
1
UL
cdef
unsigned
long
ua
=
1
UL
cdef
long
long
aa
=
0xFFFFFFFFFFFFFFFF
LL
cdef
long
long
aa
=
0xFFFFFFFFFFFFFFFF
LL
...
@@ -16,8 +24,4 @@ def c_longs():
...
@@ -16,8 +24,4 @@ def c_longs():
return
a
,
ua
,
aa
,
uaa
return
a
,
ua
,
aa
,
uaa
def
py_longs
():
def
py_longs
():
"""
>>> py_longs()
(1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L)
"""
return
1
,
1L
,
100000000000000000000000000000000
,
-
100000000000000000000000000000000
return
1
,
1L
,
100000000000000000000000000000000
,
-
100000000000000000000000000000000
tests/run/ishimoto2.pyx
View file @
416e3293
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u" u'"
,
u" '"
)
class
C
:
class
C
:
"""
"""
>>> C().xxx(5)
>>> C().xxx(5)
5
5
>>> C().xxx()
>>> C().xxx()
u
'a b'
'a b'
>>> C().xxx(42)
>>> C().xxx(42)
42
42
>>> C().xxx()
>>> C().xxx()
u
'a b'
'a b'
"""
"""
def
xxx
(
self
,
p
=
u
"a b"
):
def
xxx
(
self
,
p
=
"a b"
):
return
p
return
p
tests/run/list_pop.pyx
0 → 100644
View file @
416e3293
cimport
cython
class
A
:
def
pop
(
self
,
*
args
):
print
args
return
None
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
simple_pop
(
L
):
"""
>>> L = range(10)
>>> simple_pop(L)
9
>>> simple_pop(L)
8
>>> L
[0, 1, 2, 3, 4, 5, 6, 7]
>>> while L:
... _ = simple_pop(L)
>>> L
[]
>>> simple_pop(L)
Traceback (most recent call last):
...
IndexError: pop from empty list
>>> simple_pop(A())
()
"""
return
L
.
pop
()
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
index_pop
(
L
,
int
i
):
"""
>>> L = range(10)
>>> index_pop(L, 2)
2
>>> index_pop(L, -2)
8
>>> L
[0, 1, 3, 4, 5, 6, 7, 9]
>>> index_pop(L, 100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> index_pop(L, -100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> while L:
... _ = index_pop(L, 0)
>>> L
[]
>>> index_pop(L, 0)
Traceback (most recent call last):
...
IndexError: pop from empty list
>>> index_pop(A(), 3)
(3,)
"""
return
L
.
pop
(
i
)
@
cython
.
test_fail_if_path_exists
(
'//PythonCapiCallNode'
)
def
crazy_pop
(
L
):
"""
>>> crazy_pop(range(10))
Traceback (most recent call last):
...
TypeError: pop() takes at most 1 argument (3 given)
>>> crazy_pop(A())
(1, 2, 3)
"""
return
L
.
pop
(
1
,
2
,
3
)
tests/run/modbody.pyx
View file @
416e3293
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u" u'"
,
u" '"
)
def
f
():
def
f
():
"""
"""
>>> f()
>>> f()
>>> g
>>> g
42
42
>>> x
>>> x
== 'spam'
u'spam'
True
>>> y
>>> y
== 'eggs'
u'eggs'
True
>>> z
>>> z
== 'spameggs'
u'spameggs'
True
"""
"""
pass
pass
...
...
tests/run/new_style_exceptions.pyx
View file @
416e3293
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u"u'"
,
u"'"
)
import
sys
,
types
import
sys
,
types
def
test
(
obj
):
def
test
(
obj
):
"""
"""
>>> test(Exception(
u
'hi'))
>>> test(Exception('hi'))
Raising: Exception(
u
'hi',)
Raising: Exception('hi',)
Caught: Exception(
u
'hi',)
Caught: Exception('hi',)
"""
"""
print
u"Raising: %s%r"
%
(
obj
.
__class__
.
__name__
,
obj
.
args
)
print
u"Raising: %s%r"
%
(
obj
.
__class__
.
__name__
,
obj
.
args
)
try
:
try
:
...
...
tests/run/profile_test.pyx
View file @
416e3293
...
@@ -20,7 +20,10 @@ __doc__ = u"""
...
@@ -20,7 +20,10 @@ __doc__ = u"""
KeyError: 'f_noprof'
KeyError: 'f_noprof'
>>> short_stats['f_raise']
>>> short_stats['f_raise']
100
100
>>> os.unlink(statsfile)
>>> try:
... os.unlink(statsfile)
... except:
... pass
"""
"""
import
sys
import
sys
...
...
tests/run/r_bowden1.pyx
View file @
416e3293
__doc__
=
u"""
>>> f(100)
101L
>>> g(3000000000)
3000000001L
"""
import
sys
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u"L"
,
u""
)
__doc__
=
__doc__
.
replace
(
u"L"
,
u""
)
def
f
(
x
):
def
f
(
x
):
"""
>>> f(100)
101L
"""
cdef
unsigned
long
long
ull
cdef
unsigned
long
long
ull
ull
=
x
ull
=
x
return
ull
+
1
return
ull
+
1
def
g
(
unsigned
long
x
):
def
g
(
unsigned
long
x
):
"""
>>> g(3000000000)
3000000001L
"""
return
x
+
1
return
x
+
1
tests/run/tp_new.pyx
0 → 100644
View file @
416e3293
cimport
cython
cdef
class
MyType
:
def
__cinit__
(
self
):
print
"CINIT"
def
__init__
(
self
):
print
"INIT"
cdef
class
MySubType
(
MyType
):
def
__cinit__
(
self
):
print
"CINIT(SUB)"
def
__init__
(
self
):
print
"INIT"
class
MyClass
(
object
):
def
__cinit__
(
self
):
print
"CINIT"
def
__init__
(
self
):
print
"INIT"
class
MyTypeSubClass
(
MyType
):
def
__cinit__
(
self
):
# not called: Python class!
print
"CINIT(PYSUB)"
def
__init__
(
self
):
print
"INIT"
# only this can be safely optimised:
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new
():
"""
>>> isinstance(make_new(), MyType)
CINIT
True
"""
m
=
MyType
.
__new__
(
MyType
)
return
m
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new_typed_target
():
"""
>>> isinstance(make_new_typed_target(), MyType)
CINIT
True
"""
cdef
MyType
m
m
=
MyType
.
__new__
(
MyType
)
return
m
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new_builtin
():
"""
>>> isinstance(make_new_builtin(), tuple)
True
"""
m
=
dict
.
__new__
(
dict
)
m
=
list
.
__new__
(
list
)
m
=
tuple
.
__new__
(
tuple
)
return
m
@
cython
.
test_assert_path_exists
(
'//PythonCapiCallNode'
)
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/AttributeNode'
)
def
make_new_none
(
type
t
=
None
):
"""
>>> isinstance(make_new_none(), MyType)
Traceback (most recent call last):
TypeError: object.__new__(X): X is not a type object (NoneType)
"""
m
=
t
.
__new__
(
t
)
return
m
# these cannot:
@
cython
.
test_assert_path_exists
(
'//SimpleCallNode/AttributeNode'
)
@
cython
.
test_fail_if_path_exists
(
'//PythonCapiCallNode'
)
def
make_new_pyclass
():
"""
>>> isinstance(make_new_pyclass(), MyTypeSubClass)
CINIT
True
"""
m
=
MyClass
.
__new__
(
MyClass
)
m
=
MyTypeSubClass
.
__new__
(
MyTypeSubClass
)
return
m
@
cython
.
test_assert_path_exists
(
'//SimpleCallNode/AttributeNode'
)
@
cython
.
test_fail_if_path_exists
(
'//PythonCapiCallNode'
)
def
make_new_args
(
type
t1
=
None
,
type
t2
=
None
):
"""
>>> isinstance(make_new_args(), MyType)
CINIT
True
>>> isinstance(make_new_args(MyType), MyType)
CINIT
True
>>> isinstance(make_new_args(MyType, MyType), MyType)
CINIT
True
>>> isinstance(make_new_args(MyType, MySubType), MySubType)
Traceback (most recent call last):
TypeError: tp_new.MyType.__new__(tp_new.MySubType) is not safe, use tp_new.MySubType.__new__()
>>> isinstance(make_new_args(MySubType, MyType), MyType)
Traceback (most recent call last):
TypeError: tp_new.MySubType.__new__(tp_new.MyType): tp_new.MyType is not a subtype of tp_new.MySubType
"""
if
t1
is
None
:
t1
=
MyType
if
t2
is
None
:
t2
=
MyType
m
=
t1
.
__new__
(
t2
)
return
m
@
cython
.
test_assert_path_exists
(
'//SimpleCallNode/AttributeNode'
)
@
cython
.
test_fail_if_path_exists
(
'//PythonCapiCallNode'
)
def
make_new_none_typed
(
tuple
t
=
None
):
"""
>>> isinstance(make_new_none(), MyType)
Traceback (most recent call last):
TypeError: object.__new__(X): X is not a type object (NoneType)
"""
m
=
t
.
__new__
(
t
)
return
m
@
cython
.
test_assert_path_exists
(
'//SimpleCallNode/AttributeNode'
)
@
cython
.
test_fail_if_path_exists
(
'//PythonCapiCallNode'
)
def
make_new_untyped
(
t
):
"""
>>> make_new_untyped(None)
Traceback (most recent call last):
TypeError: object.__new__(X): X is not a type object (NoneType)
"""
m
=
t
.
__new__
(
t
)
return
m
tests/run/typedfieldbug_T303.pyx
View file @
416e3293
__doc__
=
"""
>>> readonly()
Traceback (most recent call last):
...
TypeError: readonly attribute
"""
import
sys
import
sys
if
sys
.
version_info
[
0
]
>=
3
:
if
sys
.
version_info
[
0
]
>=
3
:
__doc__
=
__doc__
.
replace
(
u'TypeError:'
,
u'AttributeError:'
)
__doc__
=
__doc__
.
replace
(
u'TypeError:'
,
u'AttributeError:'
)
...
@@ -53,11 +60,5 @@ def longdouble_access():
...
@@ -53,11 +60,5 @@ def longdouble_access():
def
readonly
():
def
readonly
():
"""
>>> readonly()
Traceback (most recent call last):
...
TypeError: readonly attribute
"""
c
=
MyClass
()
c
=
MyClass
()
c
.
actual_double
=
3
c
.
actual_double
=
3
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