diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index cf979205ff2cee..e0122986e9ba3a 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -2435,19 +2435,6 @@ types. Using :func:`super` (and the ``__class__`` :term:`closure variable`) in methods of ``NamedTuple`` subclasses is unsupported and causes a :class:`TypeError`. - .. deprecated-removed:: 3.13 3.15 - The undocumented keyword argument syntax for creating NamedTuple classes - (``NT = NamedTuple("NT", x=int)``) is deprecated, and will be disallowed - in 3.15. Use the class-based syntax or the functional syntax instead. - - .. deprecated-removed:: 3.13 3.15 - When using the functional syntax to create a NamedTuple class, failing to - pass a value to the 'fields' parameter (``NT = NamedTuple("NT")``) is - deprecated. Passing ``None`` to the 'fields' parameter - (``NT = NamedTuple("NT", None)``) is also deprecated. Both will be - disallowed in Python 3.15. To create a NamedTuple class with 0 fields, - use ``class NT(NamedTuple): pass`` or ``NT = NamedTuple("NT", [])``. - .. class:: NewType(name, tp) Helper class to create low-overhead :ref:`distinct types `. @@ -2823,13 +2810,6 @@ types. .. versionchanged:: 3.13 Support for the :data:`ReadOnly` qualifier was added. - .. deprecated-removed:: 3.13 3.15 - When using the functional syntax to create a TypedDict class, failing to - pass a value to the 'fields' parameter (``TD = TypedDict("TD")``) is - deprecated. Passing ``None`` to the 'fields' parameter - (``TD = TypedDict("TD", None)``) is also deprecated. Both will be - disallowed in Python 3.15. To create a TypedDict class with 0 fields, - use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``. Protocols --------- diff --git a/Include/internal/pycore_bytesobject.h b/Include/internal/pycore_bytesobject.h index 6c6e2ed21e3761..c7bc53b6073770 100644 --- a/Include/internal/pycore_bytesobject.h +++ b/Include/internal/pycore_bytesobject.h @@ -73,6 +73,26 @@ struct PyBytesWriter { // Export for '_testcapi' shared extension PyAPI_FUNC(PyBytesWriter*) _PyBytesWriter_CreateByteArray(Py_ssize_t size); +static inline Py_ssize_t +_PyBytesWriter_GetSize(PyBytesWriter *writer) +{ + return writer->size; +} + +static inline char* +_PyBytesWriter_GetData(PyBytesWriter *writer) +{ + if (writer->obj == NULL) { + return writer->small_buffer; + } + else if (writer->use_bytearray) { + return PyByteArray_AS_STRING(writer->obj); + } + else { + return PyBytes_AS_STRING(writer->obj); + } +} + #ifdef __cplusplus } #endif diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 91d20cb9afa7ba..de8ab26db1e966 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3480,15 +3480,7 @@ _PyBytes_Repeat(char* dest, Py_ssize_t len_dest, static inline char* byteswriter_data(PyBytesWriter *writer) { - if (writer->obj == NULL) { - return writer->small_buffer; - } - else if (writer->use_bytearray) { - return PyByteArray_AS_STRING(writer->obj); - } - else { - return PyBytes_AS_STRING(writer->obj); - } + return _PyBytesWriter_GetData(writer); } @@ -3710,7 +3702,7 @@ PyBytesWriter_GetData(PyBytesWriter *writer) Py_ssize_t PyBytesWriter_GetSize(PyBytesWriter *writer) { - return writer->size; + return _PyBytesWriter_GetSize(writer); } diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5799d92211aa97..9c00e22ea24bd0 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7988,7 +7988,7 @@ encode_code_page_flags(UINT code_page, const char *errors) * an OSError and returns -1 on other error. */ static int -encode_code_page_strict(UINT code_page, PyObject **outbytes, +encode_code_page_strict(UINT code_page, PyBytesWriter **writer, PyObject *unicode, Py_ssize_t offset, int len, const char* errors) { @@ -8034,25 +8034,21 @@ encode_code_page_strict(UINT code_page, PyObject **outbytes, goto done; } - if (*outbytes == NULL) { + if (*writer == NULL) { /* Create string object */ - *outbytes = PyBytes_FromStringAndSize(NULL, outsize); - if (*outbytes == NULL) { + *writer = PyBytesWriter_Create(outsize); + if (*writer == NULL) { goto done; } - out = PyBytes_AS_STRING(*outbytes); + out = PyBytesWriter_GetData(*writer); } else { /* Extend string object */ - const Py_ssize_t n = PyBytes_Size(*outbytes); - if (outsize > PY_SSIZE_T_MAX - n) { - PyErr_NoMemory(); - goto done; - } - if (_PyBytes_Resize(outbytes, n + outsize) < 0) { + Py_ssize_t n = PyBytesWriter_GetSize(*writer); + if (PyBytesWriter_Grow(*writer, outsize) < 0) { goto done; } - out = PyBytes_AS_STRING(*outbytes) + n; + out = (char*)PyBytesWriter_GetData(*writer) + n; } /* Do the conversion */ @@ -8089,7 +8085,7 @@ encode_code_page_strict(UINT code_page, PyObject **outbytes, * -1 on other error. */ static int -encode_code_page_errors(UINT code_page, PyObject **outbytes, +encode_code_page_errors(UINT code_page, PyBytesWriter **writer, PyObject *unicode, Py_ssize_t unicode_offset, Py_ssize_t insize, const char* errors) { @@ -8108,7 +8104,7 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes, PyObject *exc = NULL; PyObject *encoding_obj = NULL; const char *encoding; - Py_ssize_t newpos, newoutsize; + Py_ssize_t newpos; PyObject *rep; int ret = -1; @@ -8141,23 +8137,21 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes, } outsize = insize * Py_ARRAY_LENGTH(buffer); - if (*outbytes == NULL) { + if (*writer == NULL) { /* Create string object */ - *outbytes = PyBytes_FromStringAndSize(NULL, outsize); - if (*outbytes == NULL) + *writer = PyBytesWriter_Create(outsize); + if (*writer == NULL) { goto error; - out = PyBytes_AS_STRING(*outbytes); + } + out = PyBytesWriter_GetData(*writer); } else { /* Extend string object */ - Py_ssize_t n = PyBytes_Size(*outbytes); - if (n > PY_SSIZE_T_MAX - outsize) { - PyErr_NoMemory(); + Py_ssize_t n = PyBytesWriter_GetSize(*writer); + if (PyBytesWriter_Grow(*writer, outsize) < 0) { goto error; } - if (_PyBytes_Resize(outbytes, n + outsize) < 0) - goto error; - out = PyBytes_AS_STRING(*outbytes) + n; + out = (char*)PyBytesWriter_GetData(*writer) + n; } /* Encode the string character per character */ @@ -8206,13 +8200,11 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes, outsize = PyBytes_GET_SIZE(rep); morebytes += outsize; if (morebytes > 0) { - Py_ssize_t offset = out - PyBytes_AS_STRING(*outbytes); - newoutsize = PyBytes_GET_SIZE(*outbytes) + morebytes; - if (_PyBytes_Resize(outbytes, newoutsize) < 0) { + out = PyBytesWriter_GrowAndUpdatePointer(*writer, morebytes, out); + if (out == NULL) { Py_DECREF(rep); goto error; } - out = PyBytes_AS_STRING(*outbytes) + offset; } memcpy(out, PyBytes_AS_STRING(rep), outsize); out += outsize; @@ -8225,13 +8217,11 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes, outsize = PyUnicode_GET_LENGTH(rep); morebytes += outsize; if (morebytes > 0) { - Py_ssize_t offset = out - PyBytes_AS_STRING(*outbytes); - newoutsize = PyBytes_GET_SIZE(*outbytes) + morebytes; - if (_PyBytes_Resize(outbytes, newoutsize) < 0) { + out = PyBytesWriter_GrowAndUpdatePointer(*writer, morebytes, out); + if (out == NULL) { Py_DECREF(rep); goto error; } - out = PyBytes_AS_STRING(*outbytes) + offset; } kind = PyUnicode_KIND(rep); data = PyUnicode_DATA(rep); @@ -8254,10 +8244,11 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes, } /* write a NUL byte */ *out = 0; - outsize = out - PyBytes_AS_STRING(*outbytes); - assert(outsize <= PyBytes_GET_SIZE(*outbytes)); - if (_PyBytes_Resize(outbytes, outsize) < 0) + outsize = out - (char*)PyBytesWriter_GetData(*writer); + assert(outsize <= PyBytesWriter_GetSize(*writer)); + if (PyBytesWriter_Resize(*writer, outsize) < 0) { goto error; + } ret = 0; error: @@ -8267,13 +8258,14 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes, return ret; } -static PyObject * -encode_code_page(int code_page, - PyObject *unicode, - const char *errors) + +PyObject * +PyUnicode_EncodeCodePage(int code_page, + PyObject *unicode, + const char *errors) { Py_ssize_t len; - PyObject *outbytes = NULL; + PyBytesWriter *writer = NULL; Py_ssize_t offset; int chunk_len, ret, done; @@ -8307,15 +8299,15 @@ encode_code_page(int code_page, done = 1; } - ret = encode_code_page_strict(code_page, &outbytes, + ret = encode_code_page_strict(code_page, &writer, unicode, offset, chunk_len, errors); if (ret == -2) - ret = encode_code_page_errors(code_page, &outbytes, + ret = encode_code_page_errors(code_page, &writer, unicode, offset, chunk_len, errors); if (ret < 0) { - Py_XDECREF(outbytes); + PyBytesWriter_Discard(writer); return NULL; } @@ -8323,16 +8315,9 @@ encode_code_page(int code_page, len -= chunk_len; } while (!done); - return outbytes; + return PyBytesWriter_Finish(writer); } -PyObject * -PyUnicode_EncodeCodePage(int code_page, - PyObject *unicode, - const char *errors) -{ - return encode_code_page(code_page, unicode, errors); -} PyObject * PyUnicode_AsMBCSString(PyObject *unicode) @@ -8842,15 +8827,13 @@ charmapencode_lookup(Py_UCS4 c, PyObject *mapping, unsigned char *replace) } static int -charmapencode_resize(PyObject **outobj, Py_ssize_t *outpos, Py_ssize_t requiredsize) +charmapencode_resize(PyBytesWriter *writer, Py_ssize_t *outpos, Py_ssize_t requiredsize) { - Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); + Py_ssize_t outsize = PyBytesWriter_GetSize(writer); /* exponentially overallocate to minimize reallocations */ - if (requiredsize < 2*outsize) - requiredsize = 2*outsize; - if (_PyBytes_Resize(outobj, requiredsize)) - return -1; - return 0; + if (requiredsize < 2 * outsize) + requiredsize = 2 * outsize; + return PyBytesWriter_Resize(writer, requiredsize); } typedef enum charmapencode_result { @@ -8864,12 +8847,12 @@ typedef enum charmapencode_result { reallocation error occurred. The caller must decref the result */ static charmapencode_result charmapencode_output(Py_UCS4 c, PyObject *mapping, - PyObject **outobj, Py_ssize_t *outpos) + PyBytesWriter *writer, Py_ssize_t *outpos) { PyObject *rep; unsigned char replace; char *outstart; - Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); + Py_ssize_t outsize = _PyBytesWriter_GetSize(writer); if (Py_IS_TYPE(mapping, &EncodingMapType)) { int res = encoding_map_lookup(c, mapping); @@ -8877,9 +8860,9 @@ charmapencode_output(Py_UCS4 c, PyObject *mapping, if (res == -1) return enc_FAILED; if (outsize outsize) /* Make room for all additional bytes. */ - if (charmapencode_resize(res, respos, requiredsize)) { + if (charmapencode_resize(writer, respos, requiredsize)) { Py_DECREF(repunicode); return -1; } - memcpy(PyBytes_AsString(*res) + *respos, + memcpy((char*)PyBytesWriter_GetData(writer) + *respos, PyBytes_AsString(repunicode), repsize); *respos += repsize; *inpos = newpos; @@ -9045,7 +9028,7 @@ charmap_encoding_error( kind = PyUnicode_KIND(repunicode); for (index = 0; index < repsize; index++) { Py_UCS4 repch = PyUnicode_READ(kind, data, index); - x = charmapencode_output(repch, mapping, res, respos); + x = charmapencode_output(repch, mapping, writer, respos); if (x==enc_EXCEPTION) { Py_DECREF(repunicode); return -1; @@ -9067,65 +9050,64 @@ _PyUnicode_EncodeCharmap(PyObject *unicode, PyObject *mapping, const char *errors) { - /* output object */ - PyObject *res = NULL; - /* current input position */ - Py_ssize_t inpos = 0; - Py_ssize_t size; - /* current output position */ - Py_ssize_t respos = 0; - PyObject *error_handler_obj = NULL; - PyObject *exc = NULL; - _Py_error_handler error_handler = _Py_ERROR_UNKNOWN; - const void *data; - int kind; - - size = PyUnicode_GET_LENGTH(unicode); - data = PyUnicode_DATA(unicode); - kind = PyUnicode_KIND(unicode); - /* Default to Latin-1 */ - if (mapping == NULL) + if (mapping == NULL) { return unicode_encode_ucs1(unicode, errors, 256); + } + Py_ssize_t size = PyUnicode_GET_LENGTH(unicode); + if (size == 0) { + return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); + } + const void *data = PyUnicode_DATA(unicode); + int kind = PyUnicode_KIND(unicode); + + PyObject *error_handler_obj = NULL; + PyObject *exc = NULL; + + /* output object */ + PyBytesWriter *writer; /* allocate enough for a simple encoding without replacements, if we need more, we'll resize */ - res = PyBytes_FromStringAndSize(NULL, size); - if (res == NULL) + writer = PyBytesWriter_Create(size); + if (writer == NULL) { goto onError; - if (size == 0) - return res; + } + + /* current input position */ + Py_ssize_t inpos = 0; + /* current output position */ + Py_ssize_t respos = 0; + _Py_error_handler error_handler = _Py_ERROR_UNKNOWN; while (inpos adjust input position */ ++inpos; + } } - /* Resize if we allocated to much */ - if (resposc_stack_hard_limit = ((uintptr_t)low) + guarantee + _PyOS_STACK_MARGIN_BYTES; _tstate->c_stack_soft_limit = _tstate->c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES; +#elif defined(__APPLE__) + pthread_t this_thread = pthread_self(); + void *stack_addr = pthread_get_stackaddr_np(this_thread); // top of the stack + size_t stack_size = pthread_get_stacksize_np(this_thread); + _tstate->c_stack_top = (uintptr_t)stack_addr; + _tstate->c_stack_hard_limit = _tstate->c_stack_top - stack_size; + _tstate->c_stack_soft_limit = _tstate->c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES; #else uintptr_t here_addr = _Py_get_machine_stack_pointer(); /// XXX musl supports HAVE_PTHRED_GETATTR_NP, but the resulting stack size