[Python-checkins] r83195 - in python/branches/py3k: Lib/ctypes/__init__.py Lib/ctypes/test/test_buffers.py Lib/ctypes/test/test_bytes.py Lib/ctypes/test/test_parameters.py Lib/ctypes/test/test_unicode.py Misc/NEWS Modules/_ctypes/_ctypes.c Modules/_ctypes/callproc.c Modules/_ctypes/cfield.c
victor.stinner
python-checkins at python.org
Wed Jul 28 02:15:04 CEST 2010
Author: victor.stinner
Date: Wed Jul 28 02:15:03 2010
New Revision: 83195
Log:
Issue #8966: ctypes: Remove implicit bytes-unicode conversion
Modified:
python/branches/py3k/Lib/ctypes/__init__.py
python/branches/py3k/Lib/ctypes/test/test_buffers.py
python/branches/py3k/Lib/ctypes/test/test_bytes.py
python/branches/py3k/Lib/ctypes/test/test_parameters.py
python/branches/py3k/Lib/ctypes/test/test_unicode.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Modules/_ctypes/_ctypes.c
python/branches/py3k/Modules/_ctypes/callproc.c
python/branches/py3k/Modules/_ctypes/cfield.c
Modified: python/branches/py3k/Lib/ctypes/__init__.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/__init__.py (original)
+++ python/branches/py3k/Lib/ctypes/__init__.py Wed Jul 28 02:15:03 2010
@@ -259,41 +259,31 @@
from _ctypes import POINTER, pointer, _pointer_type_cache
-try:
- from _ctypes import set_conversion_mode
-except ImportError:
- pass
-else:
- if _os.name in ("nt", "ce"):
- set_conversion_mode("mbcs", "strict")
- else:
- set_conversion_mode("ascii", "strict")
-
- class c_wchar_p(_SimpleCData):
- _type_ = "Z"
+class c_wchar_p(_SimpleCData):
+ _type_ = "Z"
- class c_wchar(_SimpleCData):
- _type_ = "u"
+class c_wchar(_SimpleCData):
+ _type_ = "u"
- POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
+POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
- def create_unicode_buffer(init, size=None):
- """create_unicode_buffer(aString) -> character array
- create_unicode_buffer(anInteger) -> character array
- create_unicode_buffer(aString, anInteger) -> character array
- """
- if isinstance(init, (str, bytes)):
- if size is None:
- size = len(init)+1
- buftype = c_wchar * size
- buf = buftype()
- buf.value = init
- return buf
- elif isinstance(init, int):
- buftype = c_wchar * init
- buf = buftype()
- return buf
- raise TypeError(init)
+def create_unicode_buffer(init, size=None):
+ """create_unicode_buffer(aString) -> character array
+ create_unicode_buffer(anInteger) -> character array
+ create_unicode_buffer(aString, anInteger) -> character array
+ """
+ if isinstance(init, (str, bytes)):
+ if size is None:
+ size = len(init)+1
+ buftype = c_wchar * size
+ buf = buftype()
+ buf.value = init
+ return buf
+ elif isinstance(init, int):
+ buftype = c_wchar * init
+ buf = buftype()
+ return buf
+ raise TypeError(init)
POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param
Modified: python/branches/py3k/Lib/ctypes/test/test_buffers.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/test/test_buffers.py (original)
+++ python/branches/py3k/Lib/ctypes/test/test_buffers.py Wed Jul 28 02:15:03 2010
@@ -20,18 +20,6 @@
self.assertEqual(b[::2], b"ac")
self.assertEqual(b[::5], b"a")
- def test_string_conversion(self):
- b = create_string_buffer("abc")
- self.assertEqual(len(b), 4) # trailing nul char
- self.assertEqual(sizeof(b), 4 * sizeof(c_char))
- self.assertTrue(type(b[0]) is bytes)
- self.assertEqual(b[0], b"a")
- self.assertEqual(b[:], b"abc\0")
- self.assertEqual(b[::], b"abc\0")
- self.assertEqual(b[::-1], b"\0cba")
- self.assertEqual(b[::2], b"ac")
- self.assertEqual(b[::5], b"a")
-
try:
c_wchar
except NameError:
Modified: python/branches/py3k/Lib/ctypes/test/test_bytes.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/test/test_bytes.py (original)
+++ python/branches/py3k/Lib/ctypes/test/test_bytes.py Wed Jul 28 02:15:03 2010
@@ -17,18 +17,15 @@
(c_wchar * 3)("a", "b", "c")
def test_c_char_p(self):
- c_char_p("foo bar")
c_char_p(b"foo bar")
def test_c_wchar_p(self):
c_wchar_p("foo bar")
- c_wchar_p(b"foo bar")
def test_struct(self):
class X(Structure):
_fields_ = [("a", c_char * 3)]
- X("abc")
x = X(b"abc")
self.assertEqual(x.a, b"abc")
self.assertEqual(type(x.a), bytes)
@@ -37,7 +34,6 @@
class X(Structure):
_fields_ = [("a", c_wchar * 3)]
- X(b"abc")
x = X("abc")
self.assertEqual(x.a, "abc")
self.assertEqual(type(x.a), str)
Modified: python/branches/py3k/Lib/ctypes/test/test_parameters.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/test/test_parameters.py (original)
+++ python/branches/py3k/Lib/ctypes/test/test_parameters.py Wed Jul 28 02:15:03 2010
@@ -57,8 +57,8 @@
self.assertTrue(c_char_p.from_param(s)._obj is s)
# new in 0.9.1: convert (encode) unicode to ascii
- self.assertEqual(c_char_p.from_param("123")._obj, b"123")
- self.assertRaises(UnicodeEncodeError, c_char_p.from_param, "123\377")
+ self.assertEqual(c_char_p.from_param(b"123")._obj, b"123")
+ self.assertRaises(TypeError, c_char_p.from_param, "123\377")
self.assertRaises(TypeError, c_char_p.from_param, 42)
# calling c_char_p.from_param with a c_char_p instance
@@ -80,7 +80,7 @@
# new in 0.9.1: convert (decode) ascii to unicode
self.assertEqual(c_wchar_p.from_param("123")._obj, "123")
- self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, b"123\377")
+ self.assertRaises(TypeError, c_wchar_p.from_param, b"123\377")
pa = c_wchar_p.from_param(c_wchar_p("123"))
self.assertEqual(type(pa), c_wchar_p)
Modified: python/branches/py3k/Lib/ctypes/test/test_unicode.py
==============================================================================
--- python/branches/py3k/Lib/ctypes/test/test_unicode.py (original)
+++ python/branches/py3k/Lib/ctypes/test/test_unicode.py Wed Jul 28 02:15:03 2010
@@ -7,122 +7,53 @@
pass
else:
import _ctypes_test
- dll = ctypes.CDLL(_ctypes_test.__file__)
- wcslen = dll.my_wcslen
- wcslen.argtypes = [ctypes.c_wchar_p]
-
class UnicodeTestCase(unittest.TestCase):
- def setUp(self):
- self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
+ def test_wcslen(self):
+ dll = ctypes.CDLL(_ctypes_test.__file__)
+ wcslen = dll.my_wcslen
+ wcslen.argtypes = [ctypes.c_wchar_p]
- def tearDown(self):
- ctypes.set_conversion_mode(*self.prev_conv_mode)
-
- def test_ascii_strict(self):
- ctypes.set_conversion_mode("ascii", "strict")
- # no conversions take place with unicode arguments
self.assertEqual(wcslen("abc"), 3)
self.assertEqual(wcslen("ab\u2070"), 3)
- # string args are converted
- self.assertEqual(wcslen("abc"), 3)
self.assertRaises(ctypes.ArgumentError, wcslen, b"ab\xe4")
- def test_ascii_replace(self):
- ctypes.set_conversion_mode("ascii", "replace")
- self.assertEqual(wcslen("abc"), 3)
- self.assertEqual(wcslen("ab\u2070"), 3)
- self.assertEqual(wcslen("abc"), 3)
- self.assertEqual(wcslen("ab\xe4"), 3)
-
- def test_ascii_ignore(self):
- ctypes.set_conversion_mode("ascii", "ignore")
- self.assertEqual(wcslen("abc"), 3)
- self.assertEqual(wcslen("ab\u2070"), 3)
- # ignore error mode skips non-ascii characters
- self.assertEqual(wcslen("abc"), 3)
- self.assertEqual(wcslen(b"\xe4\xf6\xfc\xdf"), 0)
-
- def test_latin1_strict(self):
- ctypes.set_conversion_mode("latin-1", "strict")
- self.assertEqual(wcslen("abc"), 3)
- self.assertEqual(wcslen("ab\u2070"), 3)
- self.assertEqual(wcslen("abc"), 3)
- self.assertEqual(wcslen("\xe4\xf6\xfc\xdf"), 4)
-
def test_buffers(self):
- ctypes.set_conversion_mode("ascii", "strict")
buf = ctypes.create_unicode_buffer("abc")
self.assertEqual(len(buf), 3+1)
- ctypes.set_conversion_mode("ascii", "replace")
- buf = ctypes.create_unicode_buffer(b"ab\xe4\xf6\xfc")
- self.assertEqual(buf[:], "ab\uFFFD\uFFFD\uFFFD\0")
- self.assertEqual(buf[::], "ab\uFFFD\uFFFD\uFFFD\0")
- self.assertEqual(buf[::-1], "\0\uFFFD\uFFFD\uFFFDba")
- self.assertEqual(buf[::2], "a\uFFFD\uFFFD")
+ buf = ctypes.create_unicode_buffer("ab\xe4\xf6\xfc")
+ self.assertEqual(buf[:], "ab\xe4\xf6\xfc\0")
+ self.assertEqual(buf[::], "ab\xe4\xf6\xfc\0")
+ self.assertEqual(buf[::-1], '\x00\xfc\xf6\xe4ba')
+ self.assertEqual(buf[::2], 'a\xe4\xfc')
self.assertEqual(buf[6:5:-1], "")
- ctypes.set_conversion_mode("ascii", "ignore")
- buf = ctypes.create_unicode_buffer(b"ab\xe4\xf6\xfc")
- # is that correct? not sure. But with 'ignore', you get what you pay for..
- self.assertEqual(buf[:], "ab\0\0\0\0")
- self.assertEqual(buf[::], "ab\0\0\0\0")
- self.assertEqual(buf[::-1], "\0\0\0\0ba")
- self.assertEqual(buf[::2], "a\0\0")
- self.assertEqual(buf[6:5:-1], "")
-
- import _ctypes_test
func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p
class StringTestCase(UnicodeTestCase):
def setUp(self):
- self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
func.argtypes = [ctypes.c_char_p]
func.restype = ctypes.c_char_p
def tearDown(self):
- ctypes.set_conversion_mode(*self.prev_conv_mode)
func.argtypes = None
func.restype = ctypes.c_int
- def test_ascii_replace(self):
- ctypes.set_conversion_mode("ascii", "strict")
- self.assertEqual(func("abc"), "abc")
- self.assertEqual(func("abc"), "abc")
- self.assertRaises(ctypes.ArgumentError, func, "ab\xe4")
-
- def test_ascii_ignore(self):
- ctypes.set_conversion_mode("ascii", "ignore")
- self.assertEqual(func("abc"), b"abc")
- self.assertEqual(func("abc"), b"abc")
- self.assertEqual(func("\xe4\xf6\xfc\xdf"), b"")
-
- def test_ascii_replace(self):
- ctypes.set_conversion_mode("ascii", "replace")
- self.assertEqual(func("abc"), b"abc")
- self.assertEqual(func("abc"), b"abc")
- self.assertEqual(func("\xe4\xf6\xfc\xdf"), b"????")
+ def test_func(self):
+ self.assertEqual(func(b"abc\xe4"), b"abc\xe4")
def test_buffers(self):
- ctypes.set_conversion_mode("ascii", "strict")
- buf = ctypes.create_string_buffer("abc")
+ buf = ctypes.create_string_buffer(b"abc")
self.assertEqual(len(buf), 3+1)
- ctypes.set_conversion_mode("ascii", "replace")
- buf = ctypes.create_string_buffer("ab\xe4\xf6\xfc")
- self.assertEqual(buf[:], b"ab???\0")
- self.assertEqual(buf[::], b"ab???\0")
- self.assertEqual(buf[::-1], b"\0???ba")
- self.assertEqual(buf[::2], b"a??")
+ buf = ctypes.create_string_buffer(b"ab\xe4\xf6\xfc")
+ self.assertEqual(buf[:], b"ab\xe4\xf6\xfc\0")
+ self.assertEqual(buf[::], b"ab\xe4\xf6\xfc\0")
+ self.assertEqual(buf[::-1], b'\x00\xfc\xf6\xe4ba')
+ self.assertEqual(buf[::2], b'a\xe4\xfc')
self.assertEqual(buf[6:5:-1], b"")
- ctypes.set_conversion_mode("ascii", "ignore")
- buf = ctypes.create_string_buffer("ab\xe4\xf6\xfc")
- # is that correct? not sure. But with 'ignore', you get what you pay for..
- self.assertEqual(buf[:], b"ab\0\0\0\0")
- self.assertEqual(buf[::], b"ab\0\0\0\0")
- self.assertEqual(buf[::-1], b"\0\0\0\0ba")
if __name__ == '__main__':
unittest.main()
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Wed Jul 28 02:15:03 2010
@@ -473,6 +473,8 @@
Library
-------
+- Issue #8966: ctypes: Remove implicit bytes-unicode conversion.
+
- Issue #9378: python -m pickle <pickle file> will now load and
display the first object in the pickle file.
Modified: python/branches/py3k/Modules/_ctypes/_ctypes.c
==============================================================================
--- python/branches/py3k/Modules/_ctypes/_ctypes.c (original)
+++ python/branches/py3k/Modules/_ctypes/_ctypes.c Wed Jul 28 02:15:03 2010
@@ -132,8 +132,6 @@
/* a callable object used for unpickling */
static PyObject *_unpickle;
-char *_ctypes_conversion_encoding = NULL;
-char *_ctypes_conversion_errors = NULL;
/****************************************************************/
@@ -1090,13 +1088,7 @@
return -1;
}
- if (PyUnicode_Check(value)) {
- value = PyUnicode_AsEncodedString(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (!value)
- return -1;
- } else if (!PyBytes_Check(value)) {
+ if (!PyBytes_Check(value)) {
PyErr_Format(PyExc_TypeError,
"str/bytes expected instead of %s instance",
Py_TYPE(value)->tp_name);
@@ -1150,13 +1142,7 @@
"can't delete attribute");
return -1;
}
- if (PyBytes_Check(value)) {
- value = PyUnicode_FromEncodedObject(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (!value)
- return -1;
- } else if (!PyUnicode_Check(value)) {
+ if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"unicode string expected instead of %s instance",
Py_TYPE(value)->tp_name);
@@ -1510,7 +1496,7 @@
Py_INCREF(Py_None);
return Py_None;
}
- if (PyBytes_Check(value) || PyUnicode_Check(value)) {
+ if (PyBytes_Check(value)) {
PyCArgObject *parg;
struct fielddesc *fd = _ctypes_get_fielddesc("z");
Modified: python/branches/py3k/Modules/_ctypes/callproc.c
==============================================================================
--- python/branches/py3k/Modules/_ctypes/callproc.c (original)
+++ python/branches/py3k/Modules/_ctypes/callproc.c Wed Jul 28 02:15:03 2010
@@ -1641,37 +1641,6 @@
return arg;
}
-#ifdef CTYPES_UNICODE
-
-static char set_conversion_mode_doc[] =
-"set_conversion_mode(encoding, errors) -> (previous-encoding, previous-errors)\n\
-\n\
-Set the encoding and error handling ctypes uses when converting\n\
-between unicode and strings. Returns the previous values.\n";
-
-static PyObject *
-set_conversion_mode(PyObject *self, PyObject *args)
-{
- char *coding, *mode;
- PyObject *result;
-
- if (!PyArg_ParseTuple(args, "zs:set_conversion_mode", &coding, &mode))
- return NULL;
- result = Py_BuildValue("(zz)", _ctypes_conversion_encoding, _ctypes_conversion_errors);
- if (coding) {
- PyMem_Free(_ctypes_conversion_encoding);
- _ctypes_conversion_encoding = PyMem_Malloc(strlen(coding) + 1);
- strcpy(_ctypes_conversion_encoding, coding);
- } else {
- _ctypes_conversion_encoding = NULL;
- }
- PyMem_Free(_ctypes_conversion_errors);
- _ctypes_conversion_errors = PyMem_Malloc(strlen(mode) + 1);
- strcpy(_ctypes_conversion_errors, mode);
- return result;
-}
-#endif
-
static PyObject *
resize(PyObject *self, PyObject *args)
{
@@ -1852,9 +1821,6 @@
{"_unpickle", unpickle, METH_VARARGS },
{"buffer_info", buffer_info, METH_O, "Return buffer interface information"},
{"resize", resize, METH_VARARGS, "Resize the memory buffer of a ctypes instance"},
-#ifdef CTYPES_UNICODE
- {"set_conversion_mode", set_conversion_mode, METH_VARARGS, set_conversion_mode_doc},
-#endif
#ifdef MS_WIN32
{"get_last_error", get_last_error, METH_NOARGS},
{"set_last_error", set_last_error, METH_VARARGS},
Modified: python/branches/py3k/Modules/_ctypes/cfield.c
==============================================================================
--- python/branches/py3k/Modules/_ctypes/cfield.c (original)
+++ python/branches/py3k/Modules/_ctypes/cfield.c Wed Jul 28 02:15:03 2010
@@ -1168,20 +1168,6 @@
static PyObject *
c_set(void *ptr, PyObject *value, Py_ssize_t size)
{
- if (PyUnicode_Check(value)) {
- value = PyUnicode_AsEncodedString(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (value == NULL)
- return NULL;
- if (PyBytes_GET_SIZE(value) != 1) {
- Py_DECREF(value);
- goto error;
- }
- *(char *)ptr = PyBytes_AS_STRING(value)[0];
- Py_DECREF(value);
- _RET(value);
- }
if (PyBytes_Check(value) && PyBytes_GET_SIZE(value) == 1) {
*(char *)ptr = PyBytes_AS_STRING(value)[0];
_RET(value);
@@ -1217,13 +1203,7 @@
u_set(void *ptr, PyObject *value, Py_ssize_t size)
{
Py_ssize_t len;
- if (PyBytes_Check(value)) {
- value = PyUnicode_FromEncodedObject(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (!value)
- return NULL;
- } else if (!PyUnicode_Check(value)) {
+ if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"unicode string expected instead of %s instance",
value->ob_type->tp_name);
@@ -1292,13 +1272,7 @@
/* It's easier to calculate in characters than in bytes */
length /= sizeof(wchar_t);
- if (PyBytes_Check(value)) {
- value = PyUnicode_FromEncodedObject(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (!value)
- return NULL;
- } else if (!PyUnicode_Check(value)) {
+ if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"unicode string expected instead of %s instance",
value->ob_type->tp_name);
@@ -1342,14 +1316,7 @@
char *data;
Py_ssize_t size;
- if (PyUnicode_Check(value)) {
- value = PyUnicode_AsEncodedString(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (value == NULL)
- return NULL;
- assert(PyBytes_Check(value));
- } else if(PyBytes_Check(value)) {
+ if(PyBytes_Check(value)) {
Py_INCREF(value);
} else {
PyErr_Format(PyExc_TypeError,
@@ -1393,14 +1360,6 @@
*(char **)ptr = PyBytes_AsString(value);
Py_INCREF(value);
return value;
- } else if (PyUnicode_Check(value)) {
- PyObject *str = PyUnicode_AsEncodedString(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (str == NULL)
- return NULL;
- *(char **)ptr = PyBytes_AS_STRING(str);
- return str;
} else if (PyLong_Check(value)) {
#if SIZEOF_VOID_P == SIZEOF_LONG_LONG
*(char **)ptr = (char *)PyLong_AsUnsignedLongLongMask(value);
@@ -1454,13 +1413,7 @@
Py_INCREF(Py_None);
return Py_None;
}
- if (PyBytes_Check(value)) {
- value = PyUnicode_FromEncodedObject(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (!value)
- return NULL;
- } else if (!PyUnicode_Check(value)) {
+ if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"unicode string or integer address expected instead of %s instance",
value->ob_type->tp_name);
@@ -1540,12 +1493,6 @@
/* convert value into a PyUnicodeObject or NULL */
if (Py_None == value) {
value = NULL;
- } else if (PyBytes_Check(value)) {
- value = PyUnicode_FromEncodedObject(value,
- _ctypes_conversion_encoding,
- _ctypes_conversion_errors);
- if (!value)
- return NULL;
} else if (PyUnicode_Check(value)) {
Py_INCREF(value); /* for the descref below */
} else {
More information about the Python-checkins
mailing list