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
4a761906
Commit
4a761906
authored
Jul 25, 2015
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make code usages of Python "long" compatible with Py2/Py3
parent
958593e9
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
83 additions
and
49 deletions
+83
-49
Cython/Build/Dependencies.py
Cython/Build/Dependencies.py
+5
-3
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+23
-14
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+8
-3
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+17
-11
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+6
-3
Cython/Compiler/Visitor.py
Cython/Compiler/Visitor.py
+10
-1
Cython/Debugger/libcython.py
Cython/Debugger/libcython.py
+1
-1
Cython/Debugger/libpython.py
Cython/Debugger/libpython.py
+12
-12
Cython/Shadow.py
Cython/Shadow.py
+1
-1
No files found.
Cython/Build/Dependencies.py
View file @
4a761906
...
...
@@ -163,7 +163,7 @@ distutils_settings = {
'language'
:
transitive_str
,
}
@
cython
.
locals
(
start
=
long
,
end
=
long
)
@
cython
.
locals
(
start
=
cython
.
Py_ssize_t
,
end
=
cython
.
Py_ssize_t
)
def
line_iter
(
source
):
if
isinstance
(
source
,
basestring
):
start
=
0
...
...
@@ -254,8 +254,10 @@ class DistutilsInfo(object):
value
=
getattr
(
extension
,
key
)
+
list
(
value
)
setattr
(
extension
,
key
,
value
)
@
cython
.
locals
(
start
=
long
,
q
=
long
,
single_q
=
long
,
double_q
=
long
,
hash_mark
=
long
,
end
=
long
,
k
=
long
,
counter
=
long
,
quote_len
=
long
)
@
cython
.
locals
(
start
=
cython
.
Py_ssize_t
,
q
=
cython
.
Py_ssize_t
,
single_q
=
cython
.
Py_ssize_t
,
double_q
=
cython
.
Py_ssize_t
,
hash_mark
=
cython
.
Py_ssize_t
,
end
=
cython
.
Py_ssize_t
,
k
=
cython
.
Py_ssize_t
,
counter
=
cython
.
Py_ssize_t
,
quote_len
=
cython
.
Py_ssize_t
)
def
strip_string_literals
(
code
,
prefix
=
'__Pyx_L'
):
"""
Normalizes every string literal to be of the form '__Pyx_Lxxx',
...
...
Cython/Compiler/ExprNodes.py
View file @
4a761906
...
...
@@ -13,10 +13,11 @@ cython.declare(error=object, warning=object, warn_once=object, InternalError=obj
unicode_type
=
object
,
str_type
=
object
,
bytes_type
=
object
,
type_type
=
object
,
Builtin
=
object
,
Symtab
=
object
,
Utils
=
object
,
find_coercion_error
=
object
,
debug_disposal_code
=
object
,
debug_temp_alloc
=
object
,
debug_coercion
=
object
,
bytearray_type
=
object
,
slice_type
=
object
)
bytearray_type
=
object
,
slice_type
=
object
,
_py_int_types
=
object
)
import
os.path
import
sys
import
copy
import
os.path
import
operator
from
.Errors
import
error
,
warning
,
warn_once
,
InternalError
,
CompileError
...
...
@@ -52,6 +53,12 @@ except ImportError:
bytes
=
str
# Python 2
if
sys
.
version_info
[
0
]
>=
3
:
_py_int_types
=
int
else
:
_py_int_types
=
(
int
,
long
)
class
NotConstant
(
object
):
_obj
=
None
...
...
@@ -123,8 +130,9 @@ def check_negative_indices(*nodes):
Used to find (potential) bugs inside of "wraparound=False" sections.
"""
for
node
in
nodes
:
if
(
node
is
None
or
not
isinstance
(
node
.
constant_result
,
(
int
,
float
,
long
))):
if
node
is
None
or
(
not
isinstance
(
node
.
constant_result
,
_py_int_types
)
and
not
isinstance
(
node
.
constant_result
,
float
)):
continue
if
node
.
constant_result
<
0
:
warning
(
node
.
pos
,
...
...
@@ -2466,7 +2474,7 @@ class IteratorNode(ExprNode):
item_count
=
len
(
self
.
sequence
.
args
)
if
self
.
sequence
.
mult_factor
is
None
:
final_size
=
item_count
elif
isinstance
(
self
.
sequence
.
mult_factor
.
constant_result
,
(
int
,
long
)
):
elif
isinstance
(
self
.
sequence
.
mult_factor
.
constant_result
,
_py_int_types
):
final_size
=
item_count
*
self
.
sequence
.
mult_factor
.
constant_result
code
.
putln
(
"if (%s >= %s) break;"
%
(
self
.
counter_cname
,
final_size
))
if
self
.
reversed
:
...
...
@@ -3609,7 +3617,7 @@ class IndexNode(ExprNode):
wraparound
=
(
bool
(
code
.
globalstate
.
directives
[
'wraparound'
])
and
self
.
original_index_type
.
signed
and
not
(
isinstance
(
self
.
index
.
constant_result
,
(
int
,
long
)
)
not
(
isinstance
(
self
.
index
.
constant_result
,
_py_int_types
)
and
self
.
index
.
constant_result
>=
0
))
boundscheck
=
bool
(
code
.
globalstate
.
directives
[
'boundscheck'
])
return
", %s, %d, %s, %d, %d, %d"
%
(
...
...
@@ -4336,7 +4344,7 @@ class SliceIndexNode(ExprNode):
start
=
'%s + %d'
%
(
self
.
base
.
type
.
size
,
start
)
else
:
start
+=
total_length
if
isinstance
(
slice_size
,
(
int
,
long
)
):
if
isinstance
(
slice_size
,
_py_int_types
):
slice_size
-=
start
else
:
slice_size
=
'%s - (%s)'
%
(
slice_size
,
start
)
...
...
@@ -4351,7 +4359,7 @@ class SliceIndexNode(ExprNode):
except
ValueError
:
int_target_size
=
None
else
:
compile_time_check
=
isinstance
(
slice_size
,
(
int
,
long
)
)
compile_time_check
=
isinstance
(
slice_size
,
_py_int_types
)
if
compile_time_check
and
slice_size
<
0
:
if
int_target_size
>
0
:
...
...
@@ -6443,8 +6451,8 @@ class SequenceNode(ExprNode):
mult_factor
=
self
.
mult_factor
if
mult_factor
.
type
.
is_int
:
c_mult
=
mult_factor
.
result
()
if
isinstance
(
mult_factor
.
constant_result
,
(
int
,
long
))
\
and
mult_factor
.
constant_result
>
0
:
if
(
isinstance
(
mult_factor
.
constant_result
,
_py_int_types
)
and
mult_factor
.
constant_result
>
0
)
:
size_factor
=
' * %s'
%
mult_factor
.
constant_result
elif
mult_factor
.
type
.
signed
:
size_factor
=
' * ((%s<0) ? 0:%s)'
%
(
c_mult
,
c_mult
)
...
...
@@ -6870,7 +6878,8 @@ class TupleNode(SequenceNode):
if
not
all
(
child
.
is_literal
for
child
in
node
.
args
):
return
node
if
not
node
.
mult_factor
or
(
node
.
mult_factor
.
is_literal
and
isinstance
(
node
.
mult_factor
.
constant_result
,
(
int
,
long
))):
node
.
mult_factor
.
is_literal
and
isinstance
(
node
.
mult_factor
.
constant_result
,
_py_int_types
)):
node
.
is_temp
=
False
node
.
is_literal
=
True
else
:
...
...
@@ -7002,7 +7011,7 @@ class ListNode(SequenceNode):
elif
(
dst_type
.
is_array
or
dst_type
.
is_ptr
)
and
dst_type
.
base_type
is
not
PyrexTypes
.
c_void_type
:
array_length
=
len
(
self
.
args
)
if
self
.
mult_factor
:
if
isinstance
(
self
.
mult_factor
.
constant_result
,
(
int
,
long
)
):
if
isinstance
(
self
.
mult_factor
.
constant_result
,
_py_int_types
):
if
self
.
mult_factor
.
constant_result
<=
0
:
error
(
self
.
pos
,
"Cannot coerce non-positively multiplied list to '%s'"
%
dst_type
)
else
:
...
...
@@ -10230,7 +10239,7 @@ class DivNode(NumBinopNode):
func
=
compile_time_binary_operators
[
self
.
operator
]
if
self
.
operator
==
'/'
and
self
.
truedivision
is
None
:
# => true div for floats, floor div for integers
if
isinstance
(
op1
,
(
int
,
long
))
and
isinstance
(
op2
,
(
int
,
long
)
):
if
isinstance
(
op1
,
_py_int_types
)
and
isinstance
(
op2
,
_py_int_types
):
func
=
compile_time_binary_operators
[
'//'
]
return
func
...
...
@@ -10515,7 +10524,7 @@ class PowNode(NumBinopNode):
def
py_operation_function
(
self
,
code
):
if
(
self
.
type
.
is_pyobject
and
self
.
operand1
.
constant_result
==
2
and
isinstance
(
self
.
operand1
.
constant_result
,
(
int
,
long
)
)
and
isinstance
(
self
.
operand1
.
constant_result
,
_py_int_types
)
and
self
.
operand2
.
type
is
py_object_type
):
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
'PyNumberPow2'
,
'Optimize.c'
))
if
self
.
inplace
:
...
...
Cython/Compiler/Nodes.py
View file @
4a761906
...
...
@@ -10,11 +10,16 @@ cython.declare(sys=object, os=object, copy=object,
py_object_type
=
object
,
ModuleScope
=
object
,
LocalScope
=
object
,
ClosureScope
=
object
,
StructOrUnionScope
=
object
,
PyClassScope
=
object
,
CppClassScope
=
object
,
UtilityCode
=
object
,
EncodedString
=
object
,
absolute_path_length
=
cython
.
Py_ssize_t
,
error_type
=
object
)
absolute_path_length
=
cython
.
Py_ssize_t
,
error_type
=
object
,
_py_int_types
=
object
)
import
sys
,
os
,
copy
from
itertools
import
chain
if
sys
.
version_info
[
0
]
>=
3
:
_py_int_types
=
int
else
:
_py_int_types
=
(
int
,
long
)
from
.
import
Builtin
from
.Errors
import
error
,
warning
,
InternalError
,
CompileError
from
.
import
Naming
...
...
@@ -4951,7 +4956,7 @@ class SingleAssignmentNode(AssignmentNode):
if
node
.
type
.
is_array
and
node
.
type
.
size
:
stop_node
=
ExprNodes
.
IntNode
(
self
.
pos
,
value
=
str
(
node
.
type
.
size
),
constant_result
=
(
node
.
type
.
size
if
isinstance
(
node
.
type
.
size
,
(
int
,
long
)
)
constant_result
=
(
node
.
type
.
size
if
isinstance
(
node
.
type
.
size
,
_py_int_types
)
else
ExprNodes
.
constant_value_not_set
))
else
:
error
(
self
.
pos
,
"C array iteration requires known end index"
)
...
...
@@ -4977,7 +4982,7 @@ class SingleAssignmentNode(AssignmentNode):
elif
node
.
type
.
is_array
:
slice_size
=
node
.
type
.
size
if
not
isinstance
(
slice_size
,
(
int
,
long
)
):
if
not
isinstance
(
slice_size
,
_py_int_types
):
return
# might still work when coercing to Python
else
:
return
...
...
Cython/Compiler/Optimize.py
View file @
4a761906
from
__future__
import
absolute_import
import
sys
import
copy
import
codecs
from
.
import
TypeSlots
from
.ExprNodes
import
not_a_constant
import
cython
cython
.
declare
(
UtilityCode
=
object
,
EncodedString
=
object
,
BytesLiteral
=
object
,
Nodes
=
object
,
ExprNodes
=
object
,
PyrexTypes
=
object
,
Builtin
=
object
,
UtilNodes
=
object
)
UtilNodes
=
object
,
_py_int_types
=
object
)
if
sys
.
version_info
[
0
]
>=
3
:
_py_int_types
=
int
else
:
_py_int_types
=
(
int
,
long
)
from
.
import
Nodes
from
.
import
ExprNodes
...
...
@@ -20,9 +29,6 @@ from .StringEncoding import EncodedString, BytesLiteral
from
.Errors
import
error
from
.ParseTreeTransforms
import
SkipDeclarations
import
copy
import
codecs
try
:
from
__builtin__
import
reduce
except
ImportError
:
...
...
@@ -444,7 +450,7 @@ class IterationTransform(Visitor.EnvTransform):
stop
=
filter_none_node
(
index
.
stop
)
step
=
filter_none_node
(
index
.
step
)
if
step
:
if
not
isinstance
(
step
.
constant_result
,
(
int
,
long
)
)
\
if
not
isinstance
(
step
.
constant_result
,
_py_int_types
)
\
or
step
.
constant_result
==
0
\
or
step
.
constant_result
>
0
and
not
stop
\
or
step
.
constant_result
<
0
and
not
start
:
...
...
@@ -683,7 +689,7 @@ class IterationTransform(Visitor.EnvTransform):
else
:
step
=
args
[
2
]
step_pos
=
step
.
pos
if
not
isinstance
(
step
.
constant_result
,
(
int
,
long
)
):
if
not
isinstance
(
step
.
constant_result
,
_py_int_types
):
# cannot determine step direction
return
node
step_value
=
step
.
constant_result
...
...
@@ -708,8 +714,8 @@ class IterationTransform(Visitor.EnvTransform):
bound1
,
bound2
=
bound2
,
bound1
abs_step
=
abs
(
step_value
)
if
abs_step
!=
1
:
if
(
isinstance
(
bound1
.
constant_result
,
(
int
,
long
)
)
and
isinstance
(
bound2
.
constant_result
,
(
int
,
long
)
)):
if
(
isinstance
(
bound1
.
constant_result
,
_py_int_types
)
and
isinstance
(
bound2
.
constant_result
,
_py_int_types
)):
# calculate final bounds now
if
step_value
<
0
:
begin_value
=
bound2
.
constant_result
...
...
@@ -3852,12 +3858,12 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
def
_calculate_constant_seq
(
self
,
node
,
sequence_node
,
factor
):
if
factor
.
constant_result
!=
1
and
sequence_node
.
args
:
if
isinstance
(
factor
.
constant_result
,
(
int
,
long
)
)
and
factor
.
constant_result
<=
0
:
if
isinstance
(
factor
.
constant_result
,
_py_int_types
)
and
factor
.
constant_result
<=
0
:
del
sequence_node
.
args
[:]
sequence_node
.
mult_factor
=
None
elif
sequence_node
.
mult_factor
is
not
None
:
if
(
isinstance
(
factor
.
constant_result
,
(
int
,
long
)
)
and
isinstance
(
sequence_node
.
mult_factor
.
constant_result
,
(
int
,
long
)
)):
if
(
isinstance
(
factor
.
constant_result
,
_py_int_types
)
and
isinstance
(
sequence_node
.
mult_factor
.
constant_result
,
_py_int_types
)):
value
=
sequence_node
.
mult_factor
.
constant_result
*
factor
.
constant_result
sequence_node
.
mult_factor
=
ExprNodes
.
IntNode
(
sequence_node
.
mult_factor
.
pos
,
...
...
Cython/Compiler/Parsing.py
View file @
4a761906
...
...
@@ -13,9 +13,10 @@ cython.declare(Nodes=object, ExprNodes=object, EncodedString=object,
Future
=
object
,
Options
=
object
,
error
=
object
,
warning
=
object
,
Builtin
=
object
,
ModuleNode
=
object
,
Utils
=
object
,
re
=
object
,
_unicode
=
object
,
_bytes
=
object
,
partial
=
object
,
reduce
=
object
)
partial
=
object
,
reduce
=
object
,
_IS_PY3
=
cython
.
bint
)
import
re
import
sys
from
unicodedata
import
lookup
as
lookup_unicodechar
from
functools
import
partial
,
reduce
...
...
@@ -31,6 +32,8 @@ from .. import Utils
from
.
import
Future
from
.
import
Options
_IS_PY3
=
sys
.
version_info
[
0
]
>=
3
class
Ctx
(
object
):
# Parsing context
...
...
@@ -759,8 +762,6 @@ def wrap_compile_time_constant(pos, value):
return
ExprNodes
.
BoolNode
(
pos
,
value
=
value
)
elif
isinstance
(
value
,
int
):
return
ExprNodes
.
IntNode
(
pos
,
value
=
rep
)
elif
isinstance
(
value
,
long
):
return
ExprNodes
.
IntNode
(
pos
,
value
=
rep
,
longness
=
"L"
)
elif
isinstance
(
value
,
float
):
return
ExprNodes
.
FloatNode
(
pos
,
value
=
rep
)
elif
isinstance
(
value
,
_unicode
):
...
...
@@ -775,6 +776,8 @@ def wrap_compile_time_constant(pos, value):
else
:
# error already reported
return
None
elif
not
_IS_PY3
and
isinstance
(
value
,
long
):
return
ExprNodes
.
IntNode
(
pos
,
value
=
rep
,
longness
=
"L"
)
error
(
pos
,
"Invalid type for compile-time constant: %r (type %s)"
%
(
value
,
value
.
__class__
.
__name__
))
return
None
...
...
Cython/Compiler/Visitor.py
View file @
4a761906
...
...
@@ -6,6 +6,7 @@
from
__future__
import
absolute_import
import
sys
import
inspect
from
.
import
TypeSlots
...
...
@@ -19,6 +20,14 @@ from . import Future
import
cython
cython
.
declare
(
_PRINTABLE
=
tuple
)
if
sys
.
version_info
>=
3
:
_PRINTABLE
=
(
bytes
,
str
,
int
,
float
)
else
:
_PRINTABLE
=
(
str
,
unicode
,
long
,
int
,
float
)
class
TreeVisitor
(
object
):
"""
Base class for writing visitors for a Cython tree, contains utilities for
...
...
@@ -94,7 +103,7 @@ class TreeVisitor(object):
continue
elif
isinstance
(
value
,
list
):
value
=
u'[...]/%d'
%
len
(
value
)
elif
not
isinstance
(
value
,
(
str
,
unicode
,
long
,
int
,
float
)
):
elif
not
isinstance
(
value
,
_PRINTABLE
):
continue
else
:
value
=
repr
(
value
)
...
...
Cython/Debugger/libcython.py
View file @
4a761906
...
...
@@ -405,7 +405,7 @@ class CythonBase(object):
# Closed over free variable
if
cur_lineno
>
cython_func
.
lineno
:
if
cyvar
.
type
==
PythonObject
:
return
long
(
gdb
.
parse_and_eval
(
cyvar
.
cname
))
return
int
(
gdb
.
parse_and_eval
(
cyvar
.
cname
))
return
True
return
False
...
...
Cython/Debugger/libpython.py
View file @
4a761906
...
...
@@ -269,7 +269,7 @@ class PyObjectPtr(object):
return
PyTypeObjectPtr
(
self
.
field
(
'ob_type'
))
def
is_null
(
self
):
return
0
==
long
(
self
.
_gdbval
)
return
0
==
int
(
self
.
_gdbval
)
def
is_optimized_out
(
self
):
'''
...
...
@@ -330,7 +330,7 @@ class PyObjectPtr(object):
return
'<%s at remote 0x%x>'
%
(
self
.
tp_name
,
self
.
address
)
return
FakeRepr
(
self
.
safe_tp_name
(),
long
(
self
.
_gdbval
))
int
(
self
.
_gdbval
))
def
write_repr
(
self
,
out
,
visited
):
'''
...
...
@@ -432,7 +432,7 @@ class PyObjectPtr(object):
return
gdb
.
lookup_type
(
cls
.
_typename
).
pointer
()
def
as_address
(
self
):
return
long
(
self
.
_gdbval
)
return
int
(
self
.
_gdbval
)
class
PyVarObjectPtr
(
PyObjectPtr
):
...
...
@@ -553,7 +553,7 @@ class PyTypeObjectPtr(PyObjectPtr):
tp_name
=
self
.
safe_tp_name
()
# New-style class:
return
InstanceProxy
(
tp_name
,
attr_dict
,
long
(
self
.
_gdbval
))
return
InstanceProxy
(
tp_name
,
attr_dict
,
int
(
self
.
_gdbval
))
def
write_repr
(
self
,
out
,
visited
):
# Guard against infinite loops:
...
...
@@ -751,7 +751,7 @@ class PyInstanceObjectPtr(PyObjectPtr):
in_dict
=
self
.
pyop_field
(
'in_dict'
).
proxyval
(
visited
)
# Old-style class:
return
InstanceProxy
(
cl_name
,
in_dict
,
long
(
self
.
_gdbval
))
return
InstanceProxy
(
cl_name
,
in_dict
,
int
(
self
.
_gdbval
))
def
write_repr
(
self
,
out
,
visited
):
# Guard against infinite loops:
...
...
@@ -836,9 +836,9 @@ class PyLongObjectPtr(PyObjectPtr):
#define PyLong_SHIFT 30
#define PyLong_SHIFT 15
'''
ob_size
=
long
(
self
.
field
(
'ob_size'
))
ob_size
=
int
(
self
.
field
(
'ob_size'
))
if
ob_size
==
0
:
return
long
(
0
)
return
int
(
0
)
ob_digit
=
self
.
field
(
'ob_digit'
)
...
...
@@ -971,7 +971,7 @@ class PyFrameObjectPtr(PyObjectPtr):
if
self
.
is_optimized_out
():
return
None
f_trace
=
self
.
field
(
'f_trace'
)
if
long
(
f_trace
)
!=
0
:
if
int
(
f_trace
)
!=
0
:
# we have a non-NULL f_trace:
return
self
.
f_lineno
else
:
...
...
@@ -1203,7 +1203,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
# From unicodeobject.h:
# Py_ssize_t length; /* Length of raw Unicode data in buffer */
# Py_UNICODE *str; /* Raw Unicode buffer */
field_length
=
long
(
self
.
field
(
'length'
))
field_length
=
int
(
self
.
field
(
'length'
))
field_str
=
self
.
field
(
'str'
)
# Gather a list of ints from the Py_UNICODE array; these are either
...
...
@@ -2321,11 +2321,11 @@ def _pointervalue(gdbval):
"""
# don'
t
convert
with
int
()
as
it
will
raise
a
RuntimeError
if
gdbval
.
address
is
not
None
:
return
long
(
gdbval
.
address
)
return
int
(
gdbval
.
address
)
else
:
# the address attribute is None sometimes, in which case we can
# still convert the pointer to an int
return
long
(
gdbval
)
return
int
(
gdbval
)
def
pointervalue
(
gdbval
):
...
...
@@ -2517,7 +2517,7 @@ class FixGdbCommand(gdb.Command):
warnings
.
filterwarnings
(
'ignore'
,
r'.*'
,
RuntimeWarning
,
re
.
escape
(
__name__
))
try
:
long
(
gdb
.
parse_and_eval
(
"(void *) 0"
))
==
0
int
(
gdb
.
parse_and_eval
(
"(void *) 0"
))
==
0
except
RuntimeError
:
pass
# warnings.resetwarnings()
...
...
Cython/Shadow.py
View file @
4a761906
...
...
@@ -344,7 +344,7 @@ def _specialized_from_args(signatures, args, kwargs):
py_int
=
typedef
(
int
,
"int"
)
try
:
py_long
=
typedef
(
long
,
"long"
)
except
NameError
:
# Py3
except
NameError
:
# Py3
py_long
=
typedef
(
int
,
"long"
)
py_float
=
typedef
(
float
,
"float"
)
py_complex
=
typedef
(
complex
,
"double complex"
)
...
...
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