Skip to content

Commit 4d9c542

Browse files
authored
Merge branch 'main' into note
2 parents 31d4202 + c3cd3d1 commit 4d9c542

File tree

8 files changed

+126
-25
lines changed

8 files changed

+126
-25
lines changed

Doc/library/gc.rst

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,17 @@ The :mod:`gc` module provides the following functions:
206206

207207
.. function:: freeze()
208208

209-
Freeze all the objects tracked by gc - move them to a permanent generation
210-
and ignore all the future collections. This can be used before a POSIX
211-
fork() call to make the gc copy-on-write friendly or to speed up collection.
212-
Also collection before a POSIX fork() call may free pages for future
213-
allocation which can cause copy-on-write too so it's advised to disable gc
214-
in parent process and freeze before fork and enable gc in child process.
209+
Freeze all the objects tracked by the garbage collector; move them to a
210+
permanent generation and ignore them in all the future collections.
211+
212+
If a process will ``fork()`` without ``exec()``, avoiding unnecessary
213+
copy-on-write in child processes will maximize memory sharing and reduce
214+
overall memory usage. This requires both avoiding creation of freed "holes"
215+
in memory pages in the parent process and ensuring that GC collections in
216+
child processes won't touch the ``gc_refs`` counter of long-lived objects
217+
originating in the parent process. To accomplish both, call ``gc.disable()``
218+
early in the parent process, ``gc.freeze()`` right before ``fork()``, and
219+
``gc.enable()`` early in child processes.
215220

216221
.. versionadded:: 3.7
217222

Doc/library/typing.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ to this is that a list of types can be used to substitute a :class:`ParamSpec`::
423423
>>> class Z(Generic[T, P]): ...
424424
...
425425
>>> Z[int, [dict, float]]
426-
__main__.Z[int, (<class 'dict'>, <class 'float'>)]
426+
__main__.Z[int, [dict, float]]
427427

428428

429429
Furthermore, a generic with only one parameter specification variable will accept
@@ -434,9 +434,9 @@ to the former, so the following are equivalent::
434434
>>> class X(Generic[P]): ...
435435
...
436436
>>> X[int, str]
437-
__main__.X[(<class 'int'>, <class 'str'>)]
437+
__main__.X[[int, str]]
438438
>>> X[[int, str]]
439-
__main__.X[(<class 'int'>, <class 'str'>)]
439+
__main__.X[[int, str]]
440440

441441
Do note that generics with :class:`ParamSpec` may not have correct
442442
``__parameters__`` after substitution in some cases because they

Lib/test/test_typing.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,14 @@ def test_accepts_single_type(self):
855855
(*tuple[int],)
856856
Unpack[Tuple[int]]
857857

858+
def test_dir(self):
859+
dir_items = set(dir(Unpack[Tuple[int]]))
860+
for required_item in [
861+
'__args__', '__parameters__', '__origin__',
862+
]:
863+
with self.subTest(required_item=required_item):
864+
self.assertIn(required_item, dir_items)
865+
858866
def test_rejects_multiple_types(self):
859867
with self.assertRaises(TypeError):
860868
Unpack[Tuple[int], Tuple[str]]
@@ -1699,6 +1707,14 @@ def test_repr(self):
16991707
u = Optional[str]
17001708
self.assertEqual(repr(u), 'typing.Optional[str]')
17011709

1710+
def test_dir(self):
1711+
dir_items = set(dir(Union[str, int]))
1712+
for required_item in [
1713+
'__args__', '__parameters__', '__origin__',
1714+
]:
1715+
with self.subTest(required_item=required_item):
1716+
self.assertIn(required_item, dir_items)
1717+
17021718
def test_cannot_subclass(self):
17031719
with self.assertRaisesRegex(TypeError,
17041720
r'Cannot subclass typing\.Union'):
@@ -1839,6 +1855,15 @@ def test_eq_hash(self):
18391855
self.assertNotEqual(C, Callable[..., int])
18401856
self.assertNotEqual(C, Callable)
18411857

1858+
def test_dir(self):
1859+
Callable = self.Callable
1860+
dir_items = set(dir(Callable[..., int]))
1861+
for required_item in [
1862+
'__args__', '__parameters__', '__origin__',
1863+
]:
1864+
with self.subTest(required_item=required_item):
1865+
self.assertIn(required_item, dir_items)
1866+
18421867
def test_cannot_instantiate(self):
18431868
Callable = self.Callable
18441869
with self.assertRaises(TypeError):
@@ -2151,6 +2176,14 @@ def test_repr(self):
21512176
self.assertEqual(repr(Literal[None]), "typing.Literal[None]")
21522177
self.assertEqual(repr(Literal[1, 2, 3, 3]), "typing.Literal[1, 2, 3]")
21532178

2179+
def test_dir(self):
2180+
dir_items = set(dir(Literal[1, 2, 3]))
2181+
for required_item in [
2182+
'__args__', '__parameters__', '__origin__',
2183+
]:
2184+
with self.subTest(required_item=required_item):
2185+
self.assertIn(required_item, dir_items)
2186+
21542187
def test_cannot_init(self):
21552188
with self.assertRaises(TypeError):
21562189
Literal()
@@ -7315,6 +7348,15 @@ def test_repr(self):
73157348
"typing.Annotated[typing.List[int], 4, 5]"
73167349
)
73177350

7351+
def test_dir(self):
7352+
dir_items = set(dir(Annotated[int, 4]))
7353+
for required_item in [
7354+
'__args__', '__parameters__', '__origin__',
7355+
'__metadata__',
7356+
]:
7357+
with self.subTest(required_item=required_item):
7358+
self.assertIn(required_item, dir_items)
7359+
73187360
def test_flatten(self):
73197361
A = Annotated[Annotated[int, 4], 5]
73207362
self.assertEqual(A, Annotated[int, 4, 5])
@@ -8033,6 +8075,15 @@ class MyClass: ...
80338075
c = Concatenate[MyClass, P]
80348076
self.assertNotEqual(c, Concatenate)
80358077

8078+
def test_dir(self):
8079+
P = ParamSpec('P')
8080+
dir_items = set(dir(Concatenate[int, P]))
8081+
for required_item in [
8082+
'__args__', '__parameters__', '__origin__',
8083+
]:
8084+
with self.subTest(required_item=required_item):
8085+
self.assertIn(required_item, dir_items)
8086+
80368087
def test_valid_uses(self):
80378088
P = ParamSpec('P')
80388089
T = TypeVar('T')
@@ -8310,10 +8361,18 @@ class Foo(Generic[T]):
83108361
def bar(self):
83118362
pass
83128363
baz = 3
8364+
__magic__ = 4
8365+
83138366
# The class attributes of the original class should be visible even
83148367
# in dir() of the GenericAlias. See bpo-45755.
8315-
self.assertIn('bar', dir(Foo[int]))
8316-
self.assertIn('baz', dir(Foo[int]))
8368+
dir_items = set(dir(Foo[int]))
8369+
for required_item in [
8370+
'bar', 'baz',
8371+
'__args__', '__parameters__', '__origin__',
8372+
]:
8373+
with self.subTest(required_item=required_item):
8374+
self.assertIn(required_item, dir_items)
8375+
self.assertNotIn('__magic__', dir_items)
83178376

83188377

83198378
class RevealTypeTests(BaseTestCase):

Lib/typing.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,6 +2154,8 @@ class _AnnotatedAlias(_NotIterable, _GenericAlias, _root=True):
21542154
with extra annotations. The alias behaves like a normal typing alias,
21552155
instantiating is the same as instantiating the underlying type, binding
21562156
it to types is also the same.
2157+
2158+
The metadata itself is stored in a '__metadata__' attribute as a tuple.
21572159
"""
21582160
def __init__(self, origin, metadata):
21592161
if isinstance(origin, _AnnotatedAlias):
@@ -2209,6 +2211,10 @@ class Annotated:
22092211
Details:
22102212
22112213
- It's an error to call `Annotated` with less than two arguments.
2214+
- Access the metadata via the ``__metadata__`` attribute::
2215+
2216+
Annotated[int, '$'].__metadata__ == ('$',)
2217+
22122218
- Nested Annotated are flattened::
22132219
22142220
Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3]

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,7 @@ Jason Lowe
11151115
Tony Lownds
11161116
Ray Loyzaga
11171117
Kang-Hao (Kenny) Lu
1118+
Raymond Lu
11181119
Lukas Lueg
11191120
Loren Luke
11201121
Fredrik Lundh

PC/msvcrtmodule.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,11 @@ PyMODINIT_FUNC
609609
PyInit_msvcrt(void)
610610
{
611611
int st;
612-
PyObject *d, *version;
613612
PyObject *m = PyModule_Create(&msvcrtmodule);
614-
if (m == NULL)
613+
if (m == NULL) {
615614
return NULL;
616-
d = PyModule_GetDict(m);
615+
}
616+
PyObject *d = PyModule_GetDict(m); // Borrowed ref.
617617

618618
/* constants for the locking() function's mode argument */
619619
insertint(d, "LK_LOCK", _LK_LOCK);
@@ -644,30 +644,47 @@ PyInit_msvcrt(void)
644644
#ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN
645645
st = PyModule_AddStringConstant(m, "VC_ASSEMBLY_PUBLICKEYTOKEN",
646646
_VC_ASSEMBLY_PUBLICKEYTOKEN);
647-
if (st < 0) return NULL;
647+
if (st < 0) {
648+
goto error;
649+
}
648650
#endif
649651
#ifdef _CRT_ASSEMBLY_VERSION
650652
st = PyModule_AddStringConstant(m, "CRT_ASSEMBLY_VERSION",
651653
_CRT_ASSEMBLY_VERSION);
652-
if (st < 0) return NULL;
654+
if (st < 0) {
655+
goto error;
656+
}
653657
#endif
654658
#ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX
655659
st = PyModule_AddStringConstant(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX",
656660
__LIBRARIES_ASSEMBLY_NAME_PREFIX);
657-
if (st < 0) return NULL;
661+
if (st < 0) {
662+
goto error;
663+
}
658664
#endif
659665

660666
/* constants for the 2010 crt versions */
661667
#if defined(_VC_CRT_MAJOR_VERSION) && defined (_VC_CRT_MINOR_VERSION) && defined(_VC_CRT_BUILD_VERSION) && defined(_VC_CRT_RBUILD_VERSION)
662-
version = PyUnicode_FromFormat("%d.%d.%d.%d", _VC_CRT_MAJOR_VERSION,
663-
_VC_CRT_MINOR_VERSION,
664-
_VC_CRT_BUILD_VERSION,
665-
_VC_CRT_RBUILD_VERSION);
666-
st = PyModule_AddObject(m, "CRT_ASSEMBLY_VERSION", version);
667-
if (st < 0) return NULL;
668+
PyObject *version = PyUnicode_FromFormat("%d.%d.%d.%d",
669+
_VC_CRT_MAJOR_VERSION,
670+
_VC_CRT_MINOR_VERSION,
671+
_VC_CRT_BUILD_VERSION,
672+
_VC_CRT_RBUILD_VERSION);
673+
if (version == NULL) {
674+
goto error;
675+
}
676+
st = PyModule_AddObjectRef(m, "CRT_ASSEMBLY_VERSION", version);
677+
Py_DECREF(version);
678+
if (st < 0) {
679+
goto error;
680+
}
668681
#endif
669682
/* make compiler warning quiet if st is unused */
670683
(void)st;
671684

672685
return m;
686+
687+
error:
688+
Py_DECREF(m);
689+
return NULL;
673690
}

Tools/c-analyzer/cpython/_parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def clean_lines(text):
4747
'''
4848

4949
# XXX Handle these.
50+
# Tab separated:
5051
EXCLUDED = clean_lines('''
5152
# @begin=conf@
5253

Tools/patchcheck/patchcheck.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,24 @@ def report_modified_files(file_paths):
170170
return "\n".join(lines)
171171

172172

173+
#: Python files that have tabs by design:
174+
_PYTHON_FILES_WITH_TABS = frozenset({
175+
'Tools/c-analyzer/cpython/_parser.py',
176+
})
177+
178+
173179
@status("Fixing Python file whitespace", info=report_modified_files)
174180
def normalize_whitespace(file_paths):
175181
"""Make sure that the whitespace for .py files have been normalized."""
176182
reindent.makebackup = False # No need to create backups.
177-
fixed = [path for path in file_paths if path.endswith('.py') and
178-
reindent.check(os.path.join(SRCDIR, path))]
183+
fixed = [
184+
path for path in file_paths
185+
if (
186+
path.endswith('.py')
187+
and path not in _PYTHON_FILES_WITH_TABS
188+
and reindent.check(os.path.join(SRCDIR, path))
189+
)
190+
]
179191
return fixed
180192

181193

0 commit comments

Comments
 (0)