Skip to content

Commit e1f99a9

Browse files
Merge branch 'main' of https://github.com/python/cpython
2 parents ad83f10 + ae53da5 commit e1f99a9

35 files changed

Lines changed: 529 additions & 237 deletions

Doc/c-api/long.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,8 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
453453
454454
Otherwise, returns the number of bytes required to store the value.
455455
If this is equal to or less than *n_bytes*, the entire value was copied.
456-
All *n_bytes* of the buffer are written: large buffers are padded with
457-
zeroes.
456+
All *n_bytes* of the buffer are written: remaining bytes filled by
457+
copies of the sign bit.
458458
459459
If the returned value is greater than *n_bytes*, the value was
460460
truncated: as many of the lowest bits of the value as could fit are written,

Doc/c-api/memory.rst

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,39 @@ The following type-oriented macros are provided for convenience. Note that
293293
294294
Same as :c:func:`PyMem_Free`.
295295
296-
In addition, the following macro sets are provided for calling the Python memory
297-
allocator directly, without involving the C API functions listed above. However,
298-
note that their use does not preserve binary compatibility across Python
299-
versions and is therefore deprecated in extension modules.
300-
301-
* ``PyMem_MALLOC(size)``
302-
* ``PyMem_NEW(type, size)``
303-
* ``PyMem_REALLOC(ptr, size)``
304-
* ``PyMem_RESIZE(ptr, type, size)``
305-
* ``PyMem_FREE(ptr)``
306-
* ``PyMem_DEL(ptr)``
296+
297+
Deprecated aliases
298+
------------------
299+
300+
These are :term:`soft deprecated` aliases to existing functions and macros.
301+
They exist solely for backwards compatibility.
302+
303+
.. list-table::
304+
:widths: auto
305+
:header-rows: 1
306+
307+
* * Deprecated alias
308+
* Corresponding function or macro
309+
* * .. c:macro:: PyMem_MALLOC(size)
310+
* :c:func:`PyMem_Malloc`
311+
* * .. c:macro:: PyMem_NEW(type, size)
312+
* :c:macro:`PyMem_New`
313+
* * .. c:macro:: PyMem_REALLOC(ptr, size)
314+
* :c:func:`PyMem_Realloc`
315+
* * .. c:macro:: PyMem_RESIZE(ptr, type, size)
316+
* :c:macro:`PyMem_Resize`
317+
* * .. c:macro:: PyMem_FREE(ptr)
318+
* :c:func:`PyMem_Free`
319+
* * .. c:macro:: PyMem_DEL(ptr)
320+
* :c:func:`PyMem_Free`
321+
322+
.. versionchanged:: 3.4
323+
324+
The macros are now aliases of the corresponding functions and macros.
325+
Previously, their behavior was the same, but their use did not necessarily
326+
preserve binary compatibility across Python versions.
327+
328+
.. deprecated:: 2.0
307329
308330
309331
.. _objectinterface:

Doc/library/select.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ linearly scanned again. :c:func:`!select` is *O*\ (*highest file descriptor*), w
478478

479479
.. versionchanged:: 3.15
480480
Accepts any real number as *timeout*, not only integer or float.
481+
If ``ppoll()`` function is available, *timeout* has a resolution
482+
of ``1`` ns (``1e-6`` ms) instead of ``1`` ms.
481483

482484

483485
.. _kqueue-objects:

Include/internal/pycore_flowgraph.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ int _PyCfg_OptimizeCodeUnit(struct _PyCfgBuilder *g, PyObject *consts, PyObject
2727
struct _PyCfgBuilder* _PyCfg_FromInstructionSequence(_PyInstructionSequence *seq);
2828
int _PyCfg_ToInstructionSequence(struct _PyCfgBuilder *g, _PyInstructionSequence *seq);
2929
int _PyCfg_OptimizedCfgToInstructionSequence(struct _PyCfgBuilder *g, _PyCompile_CodeUnitMetadata *umd,
30-
int code_flags, int *stackdepth, int *nlocalsplus,
30+
int *stackdepth, int *nlocalsplus,
3131
_PyInstructionSequence *seq);
3232

3333
PyCodeObject *

Include/internal/pycore_instruction_sequence.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ int _PyInstructionSequence_SetAnnotationsCode(_PyInstructionSequence *seq,
7373
_PyInstructionSequence *annotations);
7474
int _PyInstructionSequence_AddNested(_PyInstructionSequence *seq, _PyInstructionSequence *nested);
7575
void PyInstructionSequence_Fini(_PyInstructionSequence *seq);
76+
_PyInstruction _PyInstructionSequence_GetInstruction(_PyInstructionSequence *seq, int pos);
7677

7778
extern PyTypeObject _PyInstructionSequence_Type;
7879
#define _PyInstructionSequence_Check(v) Py_IS_TYPE((v), &_PyInstructionSequence_Type)

Include/internal/pycore_magic_number.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ Known values:
290290
Python 3.15a4 3657 (Add BINARY_OP_SUBSCR_USTR_INT)
291291
Python 3.15a4 3658 (Optimize bytecode for list/set called on genexp)
292292
Python 3.15a4 3659 (Add CALL_FUNCTION_EX specialization)
293+
Python 3.15a4 3660 (Change generator preamble code)
293294
294295
295296
Python 3.16 will start with 3700
@@ -303,7 +304,7 @@ PC/launcher.c must also be updated.
303304
304305
*/
305306

306-
#define PYC_MAGIC_NUMBER 3659
307+
#define PYC_MAGIC_NUMBER 3660
307308
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
308309
(little-endian) and then appending b'\r\n'. */
309310
#define PYC_MAGIC_NUMBER_TOKEN \

Lib/_pyio.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -952,20 +952,21 @@ def write(self, b):
952952
if isinstance(b, str):
953953
raise TypeError("can't write str to binary stream")
954954
with memoryview(b) as view:
955-
n = view.nbytes # Size of any bytes-like object
956955
if self.closed:
957956
raise ValueError("write to closed file")
958-
if n == 0:
959-
return 0
960957

961-
with self._lock:
962-
pos = self._pos
963-
if pos > len(self._buffer):
964-
# Pad buffer to pos with null bytes.
965-
self._buffer.resize(pos)
966-
self._buffer[pos:pos + n] = b
967-
self._pos += n
968-
return n
958+
n = view.nbytes # Size of any bytes-like object
959+
if n == 0:
960+
return 0
961+
962+
with self._lock:
963+
pos = self._pos
964+
if pos > len(self._buffer):
965+
# Pad buffer to pos with null bytes.
966+
self._buffer.resize(pos)
967+
self._buffer[pos:pos + n] = view
968+
self._pos += n
969+
return n
969970

970971
def seek(self, pos, whence=0):
971972
if self.closed:

Lib/test/datetimetester.py

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,24 +2706,20 @@ def utcfromtimestamp(*args, **kwargs):
27062706
self.assertEqual(zero.second, 0)
27072707
self.assertEqual(zero.microsecond, 0)
27082708
one = fts(1e-6)
2709-
try:
2710-
minus_one = fts(-1e-6)
2711-
except OSError:
2712-
# localtime(-1) and gmtime(-1) is not supported on Windows
2713-
pass
2714-
else:
2715-
self.assertEqual(minus_one.second, 59)
2716-
self.assertEqual(minus_one.microsecond, 999999)
2717-
2718-
t = fts(-1e-8)
2719-
self.assertEqual(t, zero)
2720-
t = fts(-9e-7)
2721-
self.assertEqual(t, minus_one)
2722-
t = fts(-1e-7)
2723-
self.assertEqual(t, zero)
2724-
t = fts(-1/2**7)
2725-
self.assertEqual(t.second, 59)
2726-
self.assertEqual(t.microsecond, 992188)
2709+
minus_one = fts(-1e-6)
2710+
2711+
self.assertEqual(minus_one.second, 59)
2712+
self.assertEqual(minus_one.microsecond, 999999)
2713+
2714+
t = fts(-1e-8)
2715+
self.assertEqual(t, zero)
2716+
t = fts(-9e-7)
2717+
self.assertEqual(t, minus_one)
2718+
t = fts(-1e-7)
2719+
self.assertEqual(t, zero)
2720+
t = fts(-1/2**7)
2721+
self.assertEqual(t.second, 59)
2722+
self.assertEqual(t.microsecond, 992188)
27272723

27282724
t = fts(1e-7)
27292725
self.assertEqual(t, zero)
@@ -2752,22 +2748,18 @@ def utcfromtimestamp(*args, **kwargs):
27522748
self.assertEqual(zero.second, 0)
27532749
self.assertEqual(zero.microsecond, 0)
27542750
one = fts(D('0.000_001'))
2755-
try:
2756-
minus_one = fts(D('-0.000_001'))
2757-
except OSError:
2758-
# localtime(-1) and gmtime(-1) is not supported on Windows
2759-
pass
2760-
else:
2761-
self.assertEqual(minus_one.second, 59)
2762-
self.assertEqual(minus_one.microsecond, 999_999)
2751+
minus_one = fts(D('-0.000_001'))
2752+
2753+
self.assertEqual(minus_one.second, 59)
2754+
self.assertEqual(minus_one.microsecond, 999_999)
27632755

2764-
t = fts(D('-0.000_000_1'))
2765-
self.assertEqual(t, zero)
2766-
t = fts(D('-0.000_000_9'))
2767-
self.assertEqual(t, minus_one)
2768-
t = fts(D(-1)/2**7)
2769-
self.assertEqual(t.second, 59)
2770-
self.assertEqual(t.microsecond, 992188)
2756+
t = fts(D('-0.000_000_1'))
2757+
self.assertEqual(t, zero)
2758+
t = fts(D('-0.000_000_9'))
2759+
self.assertEqual(t, minus_one)
2760+
t = fts(D(-1)/2**7)
2761+
self.assertEqual(t.second, 59)
2762+
self.assertEqual(t.microsecond, 992188)
27712763

27722764
t = fts(D('0.000_000_1'))
27732765
self.assertEqual(t, zero)
@@ -2803,22 +2795,18 @@ def utcfromtimestamp(*args, **kwargs):
28032795
self.assertEqual(zero.second, 0)
28042796
self.assertEqual(zero.microsecond, 0)
28052797
one = fts(F(1, 1_000_000))
2806-
try:
2807-
minus_one = fts(F(-1, 1_000_000))
2808-
except OSError:
2809-
# localtime(-1) and gmtime(-1) is not supported on Windows
2810-
pass
2811-
else:
2812-
self.assertEqual(minus_one.second, 59)
2813-
self.assertEqual(minus_one.microsecond, 999_999)
2798+
minus_one = fts(F(-1, 1_000_000))
28142799

2815-
t = fts(F(-1, 10_000_000))
2816-
self.assertEqual(t, zero)
2817-
t = fts(F(-9, 10_000_000))
2818-
self.assertEqual(t, minus_one)
2819-
t = fts(F(-1, 2**7))
2820-
self.assertEqual(t.second, 59)
2821-
self.assertEqual(t.microsecond, 992188)
2800+
self.assertEqual(minus_one.second, 59)
2801+
self.assertEqual(minus_one.microsecond, 999_999)
2802+
2803+
t = fts(F(-1, 10_000_000))
2804+
self.assertEqual(t, zero)
2805+
t = fts(F(-9, 10_000_000))
2806+
self.assertEqual(t, minus_one)
2807+
t = fts(F(-1, 2**7))
2808+
self.assertEqual(t.second, 59)
2809+
self.assertEqual(t.microsecond, 992188)
28222810

28232811
t = fts(F(1, 10_000_000))
28242812
self.assertEqual(t, zero)
@@ -2860,6 +2848,7 @@ def test_timestamp_limits(self):
28602848
# If that assumption changes, this value can change as well
28612849
self.assertEqual(max_ts, 253402300799.0)
28622850

2851+
@unittest.skipIf(sys.platform == "win32", "Windows doesn't support min timestamp")
28632852
def test_fromtimestamp_limits(self):
28642853
try:
28652854
self.theclass.fromtimestamp(-2**32 - 1)
@@ -2899,6 +2888,7 @@ def test_fromtimestamp_limits(self):
28992888
# OverflowError, especially on 32-bit platforms.
29002889
self.theclass.fromtimestamp(ts)
29012890

2891+
@unittest.skipIf(sys.platform == "win32", "Windows doesn't support min timestamp")
29022892
def test_utcfromtimestamp_limits(self):
29032893
with self.assertWarns(DeprecationWarning):
29042894
try:
@@ -2960,13 +2950,11 @@ def test_insane_utcfromtimestamp(self):
29602950
self.assertRaises(OverflowError, self.theclass.utcfromtimestamp,
29612951
insane)
29622952

2963-
@unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
29642953
def test_negative_float_fromtimestamp(self):
29652954
# The result is tz-dependent; at least test that this doesn't
29662955
# fail (like it did before bug 1646728 was fixed).
29672956
self.theclass.fromtimestamp(-1.05)
29682957

2969-
@unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
29702958
def test_negative_float_utcfromtimestamp(self):
29712959
with self.assertWarns(DeprecationWarning):
29722960
d = self.theclass.utcfromtimestamp(-1.05)

Lib/test/test_compile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ def return_genexp():
12981298
x
12991299
in
13001300
y)
1301-
genexp_lines = [0, 4, 2, 0, 4]
1301+
genexp_lines = [4, 0, 4, 2, 0, 4]
13021302

13031303
genexp_code = return_genexp.__code__.co_consts[0]
13041304
code_lines = self.get_code_lines(genexp_code)

Lib/test/test_dict.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
from test.support import import_helper
1313

1414

15+
class CustomHash:
16+
def __init__(self, hash):
17+
self.hash = hash
18+
def __hash__(self):
19+
return self.hash
20+
def __repr__(self):
21+
return f'<CustomHash {self.hash} at {id(self):#x}>'
22+
23+
1524
class DictTest(unittest.TestCase):
1625

1726
def test_invalid_keyword_arguments(self):
@@ -1648,6 +1657,29 @@ class MyClass: pass
16481657
d[MyStr("attr1")] = 2
16491658
self.assertIsInstance(list(d)[0], MyStr)
16501659

1660+
def test_hash_collision_remove_add(self):
1661+
self.maxDiff = None
1662+
# There should be enough space, so all elements with unique hash
1663+
# will be placed in corresponding cells without collision.
1664+
n = 64
1665+
items = [(CustomHash(h), h) for h in range(n)]
1666+
# Keys with hash collision.
1667+
a = CustomHash(n)
1668+
b = CustomHash(n)
1669+
items += [(a, 'a'), (b, 'b')]
1670+
d = dict(items)
1671+
self.assertEqual(len(d), len(items), d)
1672+
del d[a]
1673+
# "a" has been replaced with a dummy.
1674+
del items[n]
1675+
self.assertEqual(len(d), len(items), d)
1676+
self.assertEqual(d, dict(items))
1677+
d[b] = 'c'
1678+
# "b" should not replace the dummy.
1679+
items[n] = (b, 'c')
1680+
self.assertEqual(len(d), len(items), d)
1681+
self.assertEqual(d, dict(items))
1682+
16511683

16521684
class CAPITest(unittest.TestCase):
16531685

0 commit comments

Comments
 (0)