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
3171ec18
Commit
3171ec18
authored
Apr 27, 2010
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support casting '<bytes>int_val' and coercing integers to bytes on assignment
parent
31f2903e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
207 additions
and
7 deletions
+207
-7
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+53
-7
tests/run/bytes_char_coercion.pyx
tests/run/bytes_char_coercion.pyx
+154
-0
No files found.
Cython/Compiler/ExprNodes.py
View file @
3171ec18
...
...
@@ -554,7 +554,10 @@ class ExprNode(Node):
if
dst_type
.
is_pyobject
:
if
not
src
.
type
.
is_pyobject
:
src
=
CoerceToPyTypeNode
(
src
,
env
)
if
dst_type
is
bytes_type
and
src
.
type
.
is_int
:
src
=
CoerceIntToBytesNode
(
src
,
env
)
else
:
src
=
CoerceToPyTypeNode
(
src
,
env
)
if
not
src
.
type
.
subtype_of
(
dst_type
):
if
not
isinstance
(
src
,
NoneNode
):
src
=
PyTypeTestNode
(
src
,
dst_type
,
env
)
...
...
@@ -4555,7 +4558,12 @@ class TypecastNode(ExprNode):
if
from_py
and
not
to_py
and
self
.
operand
.
is_ephemeral
()
and
not
self
.
type
.
is_numeric
:
error
(
self
.
pos
,
"Casting temporary Python object to non-numeric non-Python type"
)
if
to_py
and
not
from_py
:
if
self
.
operand
.
type
.
can_coerce_to_pyobject
(
env
):
if
self
.
type
is
bytes_type
and
self
.
operand
.
type
.
is_int
:
# FIXME: the type cast node isn't needed in this case
# and can be dropped once analyse_types() can return a
# different node
self
.
operand
=
CoerceIntToBytesNode
(
self
.
operand
,
env
)
elif
self
.
operand
.
type
.
can_coerce_to_pyobject
(
env
):
self
.
result_ctype
=
py_object_type
self
.
operand
=
self
.
operand
.
coerce_to_pyobject
(
env
)
else
:
...
...
@@ -5614,10 +5622,8 @@ class CmpNode(object):
def
is_c_string_contains
(
self
):
return
self
.
operator
in
(
'in'
,
'not_in'
)
and
\
((
self
.
operand1
.
type
in
(
PyrexTypes
.
c_char_type
,
PyrexTypes
.
c_uchar_type
)
and
self
.
operand2
.
type
in
(
PyrexTypes
.
c_char_ptr_type
,
PyrexTypes
.
c_uchar_ptr_type
,
bytes_type
))
or
((
self
.
operand1
.
type
.
is_int
and
(
self
.
operand2
.
type
.
is_string
or
self
.
operand2
.
type
is
bytes_type
))
or
(
self
.
operand1
.
type
is
PyrexTypes
.
c_py_unicode_type
and
self
.
operand2
.
type
is
unicode_type
))
...
...
@@ -6181,7 +6187,7 @@ class CoerceToPyTypeNode(CoercionNode):
CoercionNode
.
__init__
(
self
,
arg
)
if
not
arg
.
type
.
create_to_py_utility_code
(
env
):
error
(
arg
.
pos
,
"Cannot convert '%s' to Python object"
%
arg
.
type
)
"Cannot convert '%s' to Python object"
%
arg
.
type
)
if
type
is
not
py_object_type
:
self
.
type
=
py_object_type
elif
arg
.
type
.
is_string
:
...
...
@@ -6217,6 +6223,46 @@ class CoerceToPyTypeNode(CoercionNode):
code
.
put_gotref
(
self
.
py_result
())
class
CoerceIntToBytesNode
(
CoerceToPyTypeNode
):
# This node is used to convert a C int type to a Python bytes
# object.
is_temp
=
1
def
__init__
(
self
,
arg
,
env
):
arg
=
arg
.
coerce_to_simple
(
env
)
CoercionNode
.
__init__
(
self
,
arg
)
self
.
type
=
Builtin
.
bytes_type
def
generate_result_code
(
self
,
code
):
arg
=
self
.
arg
arg_result
=
arg
.
result
()
if
arg
.
type
not
in
(
PyrexTypes
.
c_char_type
,
PyrexTypes
.
c_uchar_type
,
PyrexTypes
.
c_schar_type
):
if
arg
.
type
.
signed
:
code
.
putln
(
"if ((%s < 0) || (%s > 255)) {"
%
(
arg_result
,
arg_result
))
else
:
code
.
putln
(
"if (%s > 255) {"
%
arg_result
)
code
.
putln
(
'PyErr_Format(PyExc_OverflowError, '
'"value too large to pack into a byte"); %s'
%
(
code
.
error_goto
(
self
.
pos
)))
code
.
putln
(
'}'
)
temp
=
None
if
arg
.
type
is
not
PyrexTypes
.
c_char_type
:
temp
=
code
.
funcstate
.
allocate_temp
(
PyrexTypes
.
c_char_type
,
manage_ref
=
False
)
code
.
putln
(
"%s = (char)%s;"
%
(
temp
,
arg_result
))
arg_result
=
temp
code
.
putln
(
'%s = PyBytes_FromStringAndSize(&%s, 1); %s'
%
(
self
.
result
(),
arg_result
,
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
if
temp
is
not
None
:
code
.
funcstate
.
release_temp
(
temp
)
code
.
put_gotref
(
self
.
py_result
())
class
CoerceFromPyTypeNode
(
CoercionNode
):
# This node is used to convert a Python object
# to a C data type.
...
...
tests/run/bytes_char_coercion.pyx
0 → 100644
View file @
3171ec18
cimport
cython
def
coerce_char_default
(
char
c
):
"""
Default char -> int coercion
>>> coerce_char_default(ord('A')) == ord('A')
True
"""
return
c
def
coerce_uchar_default
(
unsigned
char
c
):
"""
Default char -> int coercion
>>> coerce_uchar_default(ord('A')) == ord('A')
True
"""
return
c
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_char_bytes_cast
(
char
c
):
"""
Explicit char -> bytes coercion
>>> coerce_char_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
"""
return
<
bytes
>
c
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_uchar_bytes_cast
(
unsigned
char
c
):
"""
Explicit uchar -> bytes coercion
>>> coerce_uchar_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uchar_bytes_cast(ord('
\
\
xff'))
>>> b == '
\
\
xff' or b == '
\
\
xff'.encode('ISO-8859-1') # Py2 or Py3
True
"""
return
<
bytes
>
c
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_int_bytes_cast
(
int
c
):
"""
Explicit int -> bytes coercion
>>> coerce_int_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
>>> coerce_int_bytes_cast(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
>>> coerce_int_bytes_cast(ord('A') - 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
return
<
bytes
>
c
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_uint_bytes_cast
(
unsigned
int
c
):
"""
Explicit uint -> bytes coercion
>>> coerce_uint_bytes_cast(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uint_bytes_cast(ord('
\
\
xff'))
>>> b == '
\
\
xff' or b == '
\
\
xff'.encode('ISO-8859-1') # Py2 or Py3
True
>>> coerce_uint_bytes_cast(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
return
<
bytes
>
c
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_char_bytes_assign
(
char
c
):
"""
Implicit char -> bytes coercion in assignments
>>> coerce_char_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
"""
cdef
bytes
s
=
c
return
s
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_uchar_bytes_assign
(
unsigned
char
c
):
"""
Implicit uchar -> bytes coercion in assignments
>>> coerce_uchar_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uchar_bytes_assign(ord('
\
\
xff'))
>>> b == '
\
\
xff' or b == '
\
\
xff'.encode('ISO-8859-1') # Py2 or Py3
True
"""
cdef
bytes
s
=
c
return
s
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_int_bytes_assign
(
int
c
):
"""
Implicit int -> bytes coercion in assignments
>>> coerce_int_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
>>> coerce_int_bytes_assign(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
>>> coerce_int_bytes_assign(ord('A') - 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
cdef
bytes
s
=
c
return
s
@
cython
.
test_assert_path_exists
(
"//CoerceIntToBytesNode"
)
@
cython
.
test_fail_if_path_exists
(
"//CoerceToPyTypeNode"
)
def
coerce_uint_bytes_assign
(
unsigned
int
c
):
"""
Implicit uint -> bytes coercion in assignments
>>> coerce_uint_bytes_assign(ord('A')) == 'A'.encode('ASCII')
True
>>> b = coerce_uint_bytes_assign(ord('
\
\
xff'))
>>> b == '
\
\
xff' or b == '
\
\
xff'.encode('ISO-8859-1') # Py2 or Py3
True
>>> coerce_uint_bytes_assign(ord('A') + 0x100)
Traceback (most recent call last):
OverflowError: value too large to pack into a byte
"""
cdef
bytes
s
=
c
return
s
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