Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Doc/c-api/stable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ The full API is described below for advanced use cases.
Default flags, based on current values of macros such as
:c:macro:`Py_LIMITED_API` and :c:macro:`Py_GIL_DISABLED`.

Alternately, the field can be set to to the following flags, combined
Alternately, the field can be set to the following flags, combined
by bitwise OR.
Unused bits must be set to zero.

Expand Down
2 changes: 1 addition & 1 deletion Doc/library/importlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1257,7 +1257,7 @@ find and load modules.
To accommodate this requirement, when running on iOS, extension module
binaries are *not* packaged as ``.so`` files on ``sys.path``, but as
individual standalone frameworks. To discover those frameworks, this loader
is be registered against the ``.fwork`` file extension, with a ``.fwork``
is registered against the ``.fwork`` file extension, with a ``.fwork``
file acting as a placeholder in the original location of the binary on
``sys.path``. The ``.fwork`` file contains the path of the actual binary in
the ``Frameworks`` folder, relative to the app bundle. To allow for
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5944,7 +5944,7 @@ It is written as ``None``.
The Ellipsis Object
-------------------

This object is commonly used used to indicate that something is omitted.
This object is commonly used to indicate that something is omitted.
It supports no special operations. There is exactly one ellipsis object, named
:const:`Ellipsis` (a built-in name). ``type(Ellipsis)()`` produces the
:const:`Ellipsis` singleton.
Expand Down
4 changes: 2 additions & 2 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,7 @@ concurrent.futures
.. _whatsnew314-concurrent-futures-start-method:

* On Unix platforms other than macOS, :ref:`'forkserver'
<multiprocessing-start-method-forkserver>` is now the the default :ref:`start
<multiprocessing-start-method-forkserver>` is now the default :ref:`start
method <multiprocessing-start-methods>` for
:class:`~concurrent.futures.ProcessPoolExecutor`
(replacing :ref:`'fork' <multiprocessing-start-method-fork>`).
Expand Down Expand Up @@ -1591,7 +1591,7 @@ multiprocessing
.. _whatsnew314-multiprocessing-start-method:

* On Unix platforms other than macOS, :ref:`'forkserver'
<multiprocessing-start-method-forkserver>` is now the the default :ref:`start
<multiprocessing-start-method-forkserver>` is now the default :ref:`start
method <multiprocessing-start-methods>`
(replacing :ref:`'fork' <multiprocessing-start-method-fork>`).
This change does not affect Windows or macOS, where :ref:`'spawn'
Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ Deprecated C APIs
use the :c:type:`PyBytesWriter` API instead.
(Contributed by Victor Stinner in :gh:`129813`.)

* Deprecate :c:member:`~PyComplexObject.cval` field of the the
* Deprecate :c:member:`~PyComplexObject.cval` field of the
:c:type:`PyComplexObject` type.
Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex`
to convert a Python complex number to/from the C :c:type:`Py_complex`
Expand Down
60 changes: 60 additions & 0 deletions Lib/test/test_free_threading/test_uuid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import os
import unittest

from test.support import import_helper, threading_helper
from test.support.threading_helper import run_concurrently
from uuid import SafeUUID

c_uuid = import_helper.import_module("_uuid")

NTHREADS = 10
UUID_PER_THREAD = 1000


@threading_helper.requires_working_threading()
class UUIDTests(unittest.TestCase):
@unittest.skipUnless(os.name == "posix", "POSIX only")
def test_generate_time_safe(self):
uuids = []

def worker():
local_uuids = []
for _ in range(UUID_PER_THREAD):
uuid, is_safe = c_uuid.generate_time_safe()
self.assertIs(type(uuid), bytes)
self.assertEqual(len(uuid), 16)
# Collect the UUID only if it is safe. If not, we cannot ensure
# UUID uniqueness. According to uuid_generate_time_safe() man
# page, it is theoretically possible for two concurrently
# running processes to generate the same UUID(s) if the return
# value is not 0.
if is_safe == SafeUUID.safe:
local_uuids.append(uuid)

# Merge all safe uuids
uuids.extend(local_uuids)

run_concurrently(worker_func=worker, nthreads=NTHREADS)
self.assertEqual(len(uuids), len(set(uuids)))

@unittest.skipUnless(os.name == "nt", "Windows only")
def test_UuidCreate(self):
uuids = []

def worker():
local_uuids = []
for _ in range(UUID_PER_THREAD):
uuid = c_uuid.UuidCreate()
self.assertIs(type(uuid), bytes)
self.assertEqual(len(uuid), 16)
local_uuids.append(uuid)

# Merge all uuids
uuids.extend(local_uuids)

run_concurrently(worker_func=worker, nthreads=NTHREADS)
self.assertEqual(len(uuids), len(set(uuids)))


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up parsing bytes literals concatenation by using PyBytesWriter API and
a single memory allocation (about 3x faster).
39 changes: 33 additions & 6 deletions Parser/action_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,19 +1612,46 @@ _build_concatenated_bytes(Parser *p, asdl_expr_seq *strings, int lineno,
Py_ssize_t len = asdl_seq_LEN(strings);
assert(len > 0);

PyObject* res = Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);

/* Bytes literals never get a kind, but just for consistency
since they are represented as Constant nodes, we'll mirror
the same behavior as unicode strings for determining the
kind. */
PyObject* kind = asdl_seq_GET(strings, 0)->v.Constant.kind;
PyObject *kind = asdl_seq_GET(strings, 0)->v.Constant.kind;

Py_ssize_t total = 0;
for (Py_ssize_t i = 0; i < len; i++) {
expr_ty elem = asdl_seq_GET(strings, i);
PyObject *bytes = elem->v.Constant.value;
Py_ssize_t part = PyBytes_GET_SIZE(bytes);
if (part > PY_SSIZE_T_MAX - total) {
PyErr_NoMemory();
return NULL;
}
total += part;
}

PyBytesWriter *writer = PyBytesWriter_Create(total);
if (writer == NULL) {
return NULL;
}
char *out = PyBytesWriter_GetData(writer);

for (Py_ssize_t i = 0; i < len; i++) {
expr_ty elem = asdl_seq_GET(strings, i);
PyBytes_Concat(&res, elem->v.Constant.value);
PyObject *bytes = elem->v.Constant.value;
Py_ssize_t part = PyBytes_GET_SIZE(bytes);
if (part > 0) {
memcpy(out, PyBytes_AS_STRING(bytes), part);
out += part;
}
}
if (!res || _PyArena_AddPyObject(arena, res) < 0) {
Py_XDECREF(res);

PyObject *res = PyBytesWriter_Finish(writer);
if (res == NULL) {
return NULL;
}
if (_PyArena_AddPyObject(arena, res) < 0) {
Py_DECREF(res);
return NULL;
}
return _PyAST_Constant(res, kind, lineno, col_offset, end_lineno, end_col_offset, p->arena);
Expand Down
Loading