diff -r bff88c866886 Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c Thu Apr 09 10:27:25 2015 +0200 +++ b/Modules/_dbmmodule.c Mon Apr 13 15:59:16 2015 -0400 @@ -272,7 +272,7 @@ self: dbmobject - key: str(length=True) + key: str(types="str robuffer", length=True) default: object = None / @@ -281,7 +281,7 @@ static PyObject * dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=c2bdccaa734ad349 input=aecf5efd2f2b1a3b]*/ +/*[clinic end generated code: output=c2bdccaa734ad349 input=a0d598161224a93c]*/ { datum dbm_key, val; diff -r bff88c866886 Modules/arraymodule.c --- a/Modules/arraymodule.c Thu Apr 09 10:27:25 2015 +0200 +++ b/Modules/arraymodule.c Mon Apr 13 15:59:16 2015 -0400 @@ -1600,7 +1600,7 @@ /*[clinic input] array.array.fromstring - buffer: Py_buffer(types='str bytes bytearray buffer') + buffer: Py_buffer(types='str buffer') / Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method). @@ -1610,7 +1610,7 @@ static PyObject * array_array_fromstring_impl(arrayobject *self, Py_buffer *buffer) -/*[clinic end generated code: output=31c4baa779df84ce input=1302d94c97696b84]*/ +/*[clinic end generated code: output=31c4baa779df84ce input=3c621721b7aa7717]*/ { if (PyErr_WarnEx(PyExc_DeprecationWarning, "fromstring() is deprecated. Use frombytes() instead.", 2) != 0) diff -r bff88c866886 Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py Thu Apr 09 10:27:25 2015 +0200 +++ b/Tools/clinic/clinic.py Mon Apr 13 15:59:16 2015 -0400 @@ -2434,7 +2434,7 @@ c_ignored_default = "'\0'" def converter_init(self): - if isinstance(self.default, str) and (len(self.default) != 1): + if isinstance(self.default, bytes) and (len(self.default) != 1): fail("char_converter: illegal default value " + repr(self.default)) @@ -2477,7 +2477,7 @@ def converter_init(self, *, types='int', type=None): if types == 'str': self.format_unit = 'C' - elif types != 'int': + elif types.strip() != 'int': fail("int_converter: illegal 'types' argument") if type != None: self.type = type @@ -2569,11 +2569,20 @@ self.type = type -@add_legacy_c_converter('s#', length=True) -@add_legacy_c_converter('y', types="bytes") -@add_legacy_c_converter('y#', types="bytes", length=True) +# +# We define three string conventions for buffer types in the 'types' argument: +# 'buffer' : any object supporting the buffer interface +# 'rwbuffer': any object supporting the buffer interface, but must be writeable +# 'robuffer': any object supporting the buffer interface, but must not be writeable +# + +@add_legacy_c_converter('s#', types="str robuffer", length=True) +@add_legacy_c_converter('y', types="robuffer") +@add_legacy_c_converter('y#', types="robuffer", length=True) @add_legacy_c_converter('z', nullable=True) -@add_legacy_c_converter('z#', nullable=True, length=True) +@add_legacy_c_converter('z#', types="str robuffer", nullable=True, length=True) +# add_legacy_c_converter not supported for es, es#, et, et# +# because of their extra encoding argument class str_converter(CConverter): type = 'const char *' default_type = (str, Null, NoneType) @@ -2583,12 +2592,16 @@ length=False, nullable=False, zeroes=False): types = set(types.strip().split()) - bytes_type = {"bytes"} + bytes_type = {"bytes", "bytearray"} str_type = {"str"} - all_3_type = {"bytearray"} | bytes_type | str_type + robuffer_type = {"robuffer"} + + # ends with '#', aka 'hash', as in s# or z# + is_bytes = types == bytes_type is_str = types == str_type - is_all_3 = types == all_3_type + is_robuffer = types == robuffer_type + is_str_robuffer = types == (str_type | robuffer_type) self.length = bool(length) format_unit = None @@ -2598,34 +2611,28 @@ if is_str and not (length or zeroes or nullable): format_unit = 'es' - elif is_all_3 and not (length or zeroes or nullable): - format_unit = 'et' elif is_str and length and zeroes and not nullable: format_unit = 'es#' - elif is_all_3 and length and not (nullable or zeroes): + elif is_bytes and not (length or zeroes or nullable): + format_unit = 'et' + elif is_bytes and length and not (nullable or zeroes): format_unit = 'et#' - if format_unit.endswith('#'): - fail("Sorry: code using format unit ", repr(format_unit), "probably doesn't work properly yet.\nGive Larry your test case and he'll it.") - # TODO set pointer to NULL - # TODO add cleanup for buffer - pass - else: if zeroes: fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)") - if is_bytes and not (nullable or length): + if is_robuffer and not (nullable or length): format_unit = 'y' - elif is_bytes and length and not nullable: + elif is_robuffer and length and not nullable: format_unit = 'y#' elif is_str and not (nullable or length): format_unit = 's' - elif is_str and length and not nullable: + elif is_str_robuffer and length and not nullable: format_unit = 's#' elif is_str and nullable and not length: format_unit = 'z' - elif is_str and nullable and length: + elif is_str_robuffer and nullable and length: format_unit = 'z#' if not format_unit: @@ -2636,10 +2643,12 @@ class PyBytesObject_converter(CConverter): type = 'PyBytesObject *' format_unit = 'S' + # types = 'bytes' class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' + # types = 'bytearray' class unicode_converter(CConverter): type = 'PyObject *' @@ -2661,43 +2670,34 @@ self.length = True self.format_unit = format_unit -# -# We define three string conventions for buffer types in the 'types' argument: -# 'buffer' : any object supporting the buffer interface -# 'rwbuffer': any object supporting the buffer interface, but must be writeable -# 'robuffer': any object supporting the buffer interface, but must not be writeable -# -@add_legacy_c_converter('s*', types='str bytes bytearray buffer') -@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True) -@add_legacy_c_converter('w*', types='bytearray rwbuffer') +@add_legacy_c_converter('s*', types='str buffer') +@add_legacy_c_converter('z*', types='str buffer', nullable=True) +@add_legacy_c_converter('w*', types='rwbuffer') class Py_buffer_converter(CConverter): type = 'Py_buffer' format_unit = 'y*' impl_by_reference = True c_ignored_default = "{NULL, NULL}" - def converter_init(self, *, types='bytes bytearray buffer', nullable=False): + def converter_init(self, *, types='buffer', nullable=False): if self.default not in (unspecified, None): fail("The only legal default value for Py_buffer is None.") self.c_default = self.c_ignored_default types = set(types.strip().split()) - bytes_type = {'bytes'} - bytearray_type = {'bytearray'} buffer_type = {'buffer'} rwbuffer_type = {'rwbuffer'} robuffer_type = {'robuffer'} str_type = {'str'} - bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type format_unit = None - if types == (str_type | bytes_bytearray_buffer_type): + if types == (str_type | buffer_type): format_unit = 's*' if not nullable else 'z*' else: if nullable: fail('Py_buffer_converter: illegal combination of arguments (nullable=True)') - elif types == (bytes_bytearray_buffer_type): + elif types == buffer_type: format_unit = 'y*' - elif types == (bytearray_type | rwbuffer_type): + elif types == rwbuffer_type: format_unit = 'w*' if not format_unit: fail("Py_buffer_converter: illegal combination of arguments")