diff -r 867de88b69f0 Lib/test/test_memoryview.py --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -443,6 +443,19 @@ class ArrayMemoryviewTest(unittest.TestC m[:] = new_a self.assertEqual(a, new_a) + def test_unicode_eq(self): + a = array.array('u', 'foo') + v = memoryview(a) + w = memoryview(a) + self.assertEqual(v, w) + + def test_unicode_access(self): + a = array.array('u', 'abc') + v = memoryview(a) + self.assertEqual(v.tolist(), ['a', 'b', 'c']) + self.assertEqual(v[0], 'a') + v[0] = 'A' + self.assertEqual(a, array.array('u', 'Abc')) class BytesMemorySliceTest(unittest.TestCase, BaseMemorySliceTests, BaseBytesMemoryTests): diff -r 867de88b69f0 Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -1098,6 +1098,8 @@ get_native_fmtchar(char *result, const c case '?': size = sizeof(char); break; #endif case 'P': size = sizeof(void *); break; + case 'u': size = sizeof(Py_UCS2); break; + case 'w': size = sizeof(Py_UCS4); break; } if (size > 0 && fmt[1] == '\0') { @@ -1601,6 +1603,7 @@ unpack_single(const char *ptr, const cha double d; unsigned char uc; void *p; + int U; switch (fmt[0]) { @@ -1643,6 +1646,10 @@ unpack_single(const char *ptr, const cha /* pointer */ case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer; + /* unicode */ + case 'u': UNPACK_SINGLE(U, ptr, Py_UCS2); goto convert_unicode; + case 'w': UNPACK_SINGLE(U, ptr, Py_UCS4); goto convert_unicode; + /* default */ default: goto err_format; } @@ -1670,6 +1677,8 @@ convert_bytes: return PyBytes_FromStringAndSize(ptr, 1); convert_pointer: return PyLong_FromVoidPtr(p); +convert_unicode: + return PyUnicode_FromOrdinal(U); err_format: PyErr_Format(PyExc_NotImplementedError, "memoryview: format %s not supported", fmt); @@ -1696,6 +1705,7 @@ pack_single(char *ptr, PyObject *item, c Py_ssize_t zd; double d; void *p; + Py_UCS4 U; switch (fmt[0]) { /* signed integers */ @@ -1802,6 +1812,24 @@ pack_single(char *ptr, PyObject *item, c *ptr = PyBytes_AS_STRING(item)[0]; break; + /* str */ + case 'u': case 'w': + if (!PyUnicode_Check(item)) + return type_error_int(fmt); + if (PyUnicode_READY(item) == -1) + return NULL; + if (PyUnicode_GetLength(item) != 1) + return value_error_int(fmt); + U = PyUnicode_READ_CHAR(item, 0); + if (fmt[0] == 'u') { + if (U > 0xffff) + goto err_range; + PACK_SINGLE(ptr, U, Py_UCS2); + } + else + PACK_SINGLE(ptr, U, Py_UCS4); + break; + /* pointer */ case 'P': p = PyLong_AsVoidPtr(item); @@ -2314,6 +2342,10 @@ unpack_cmp(const char *p, const char *q, /* bytes object */ case 'c': return *p == *q; + /* unicode */ + case 'u': CMP_SINGLE(p, q, Py_UCS2); return equal; + case 'w': CMP_SINGLE(p, q, Py_UCS4); return equal; + /* pointer */ case 'P': CMP_SINGLE(p, q, void *); return equal;