Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mypyc/lib-rt/CPy.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ CPyTagged CPyBytes_GetItem(PyObject *o, CPyTagged index);
PyObject *CPyBytes_Concat(PyObject *a, PyObject *b);
PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter);
CPyTagged CPyBytes_Ord(PyObject *obj);
PyObject *CPy_DecodeUtf8(PyObject *bytes_obj, const char *errors);


int CPyBytes_Compare(PyObject *left, PyObject *right);
Expand Down
13 changes: 13 additions & 0 deletions mypyc/lib-rt/bytes_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,16 @@ CPyTagged CPyBytes_Ord(PyObject *obj) {
PyErr_SetString(PyExc_TypeError, "ord() expects a character");
return CPY_INT_TAG;
}


PyObject *CPy_DecodeUtf8(PyObject *bytes_obj, const char *errors) {
if (!PyBytes_Check(bytes_obj)) {
PyErr_SetString(PyExc_TypeError, "expected bytes object");
return NULL;
}

char *data = PyBytes_AS_STRING(bytes_obj);
Py_ssize_t size = PyBytes_GET_SIZE(bytes_obj);

return PyUnicode_DecodeUTF8(data, size, errors);
}
8 changes: 8 additions & 0 deletions mypyc/primitives/bytes_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,11 @@
c_function_name="CPyBytes_Ord",
error_kind=ERR_MAGIC,
)

method_op(
name="decode",
arg_types=[bytes_rprimitive, bytes_rprimitive],
return_type=str_rprimitive,
c_function_name="CPy_DecodeUtf8",
error_kind=ERR_MAGIC,
)
12 changes: 12 additions & 0 deletions mypyc/test-data/irbuild-bytes.test
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,15 @@ L0:
r10 = CPyBytes_Build(2, var, r9)
b4 = r10
return 1

[case testDecodeUtf8]
def f(b: bytes) -> str:
return b.decode("utf-8")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's silly to have a parameter when we only support "utf-8". It doesn't look like you have a fallback either but I don't really know mypyc.

[out]
def f(b):
b :: bytes
r0, r1 :: str
L0:
r0 = 'utf-8'
r1 = CPy_Decode(b, r0, 0)
return r1
26 changes: 26 additions & 0 deletions mypyc/test-data/run-bytes.test
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,29 @@ class A:
def test_bytes_dunder() -> None:
assert b'%b' % A() == b'aaa'
assert b'%s' % A() == b'aaa'

[case testDecodeUtf8]
from typing import Any
from testutil import assertRaises
from a import bytes_subclass

def test_decode_utf8() -> None:
assert b'hello'.decode('utf-8') == 'hello'
assert b''.decode('utf-8') == ''

x: bytes = bytearray(b'hello')
assert x.decode('utf-8') == 'hello'
assert type(x.decode('utf-8')) == str

y: Any = bytes_subclass()
assert y.decode('utf-8') == 'spook'

n: Any = 123
with assertRaises(AttributeError):
n.decode('utf-8')


[file a.py]
class bytes_subclass(bytes):
def decode(self, encoding='utf-8'):
return 'spook'