Skip to content

Commit 54095f0

Browse files
committed
Merge branch 'main' into nestedcomps
* main: pythongh-74690: Don't set special protocol attributes on non-protocol subclasses of protocols (python#104622) pythongh-104623: Update Windows installer to use SQLite 3.42.0 (python#104625) pythongh-104050: Add more type annotations to Argument Clinic (python#104628) pythongh-104629: Don't skip test_clinic if _testclinic is missing (python#104630) pythongh-104549: Set __module__ on TypeAliasType (python#104550) pythongh-104050: Improve some typing around `default`s and sentinel values (python#104626) pythongh-104146: Remove unused vars from Argument Clinic (python#104627) pythongh-104615: don't make unsafe swaps in apply_static_swaps (python#104620) pythonGH-104484: Add case_sensitive argument to `pathlib.PurePath.match()` (pythonGH-104565) pythonGH-96803: Document and test new unstable internal frame API functions (pythonGH-104211) pythonGH-104580: Don't cache eval breaker in interpreter (pythonGH-104581)
2 parents 96f17a8 + f7835fc commit 54095f0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+669
-372
lines changed

Doc/c-api/frame.rst

+35
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,38 @@ See also :ref:`Reflection <reflection>`.
130130
.. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)
131131
132132
Return the line number that *frame* is currently executing.
133+
134+
135+
136+
Internal Frames
137+
---------------
138+
139+
Unless using :pep:`523`, you will not need this.
140+
141+
.. c:struct:: _PyInterpreterFrame
142+
143+
The interpreter's internal frame representation.
144+
145+
.. versionadded:: 3.11
146+
147+
.. c:function:: PyObject* PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
148+
149+
Return a :term:`strong reference` to the code object for the frame.
150+
151+
.. versionadded:: 3.12
152+
153+
154+
.. c:function:: int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame);
155+
156+
Return the byte offset into the last executed instruction.
157+
158+
.. versionadded:: 3.12
159+
160+
161+
.. c:function:: int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame);
162+
163+
Return the currently executing line number, or -1 if there is no line number.
164+
165+
.. versionadded:: 3.12
166+
167+

Doc/library/pathlib.rst

+6-1
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ Pure paths provide the following methods and properties:
546546
PureWindowsPath('c:/Program Files')
547547

548548

549-
.. method:: PurePath.match(pattern)
549+
.. method:: PurePath.match(pattern, *, case_sensitive=None)
550550

551551
Match this path against the provided glob-style pattern. Return ``True``
552552
if matching is successful, ``False`` otherwise.
@@ -576,6 +576,11 @@ Pure paths provide the following methods and properties:
576576
>>> PureWindowsPath('b.py').match('*.PY')
577577
True
578578

579+
Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
580+
581+
.. versionadded:: 3.12
582+
The *case_sensitive* argument.
583+
579584

580585
.. method:: PurePath.relative_to(other, walk_up=False)
581586

Doc/whatsnew/3.12.rst

+3
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,9 @@ pathlib
395395
* Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`.
396396
(Contributed by Charles Machalow in :gh:`99547`.)
397397

398+
* Add *case_sensitive* optional parameter to :meth:`pathlib.Path.glob`,
399+
:meth:`pathlib.Path.rglob` and :meth:`pathlib.PurePath.match` for matching
400+
the path's case sensitivity, allowing for more precise control over the matching process.
398401

399402
dis
400403
---

Include/cpython/frameobject.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
3535

3636
/* Returns the code object of the frame (strong reference).
3737
* Does not raise an exception. */
38-
PyAPI_FUNC(PyCodeObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
38+
PyAPI_FUNC(PyObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
3939

4040
/* Returns a byte ofsset into the last executed instruction.
4141
* Does not raise an exception. */

Include/internal/pycore_ceval_state.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,14 @@ struct _pending_calls {
8181
};
8282

8383
struct _ceval_state {
84-
int recursion_limit;
85-
struct _gil_runtime_state *gil;
86-
int own_gil;
8784
/* This single variable consolidates all requests to break out of
8885
the fast path in the eval loop. */
8986
_Py_atomic_int eval_breaker;
9087
/* Request for dropping the GIL */
9188
_Py_atomic_int gil_drop_request;
89+
int recursion_limit;
90+
struct _gil_runtime_state *gil;
91+
int own_gil;
9292
/* The GC is ready to be executed */
9393
_Py_atomic_int gc_scheduled;
9494
struct _pending_calls pending;

Include/internal/pycore_compile.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ PyAPI_FUNC(PyObject*) _PyCompile_CodeGen(
105105

106106
PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg(
107107
PyObject *instructions,
108-
PyObject *consts);
108+
PyObject *consts,
109+
int nlocals);
109110

110111
PyAPI_FUNC(PyCodeObject*)
111112
_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,

Include/internal/pycore_global_objects.h

-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ struct _Py_interp_cached_objects {
7575
PyTypeObject *paramspec_type;
7676
PyTypeObject *paramspecargs_type;
7777
PyTypeObject *paramspeckwargs_type;
78-
PyTypeObject *typealias_type;
7978
};
8079

8180
#define _Py_INTERP_STATIC_OBJECT(interp, NAME) \

Include/internal/pycore_global_objects_fini_generated.h

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

+1
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ struct _Py_global_strings {
559559
STRUCT_FOR_ID(newline)
560560
STRUCT_FOR_ID(newlines)
561561
STRUCT_FOR_ID(next)
562+
STRUCT_FOR_ID(nlocals)
562563
STRUCT_FOR_ID(node_depth)
563564
STRUCT_FOR_ID(node_offset)
564565
STRUCT_FOR_ID(ns)

Include/internal/pycore_interp.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct _Py_long_state {
4848
*/
4949
struct _is {
5050

51+
struct _ceval_state ceval;
5152
PyInterpreterState *next;
5253

5354
uint64_t monitoring_version;
@@ -92,7 +93,6 @@ struct _is {
9293

9394
struct _obmalloc_state obmalloc;
9495

95-
struct _ceval_state ceval;
9696
struct _gc_runtime_state gc;
9797

9898
struct _import_state imports;

Include/internal/pycore_runtime_init_generated.h

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_typevarobject.h

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ extern PyObject *_Py_subscript_generic(PyThreadState *, PyObject *);
1616
extern int _Py_initialize_generic(PyInterpreterState *);
1717
extern void _Py_clear_generic_types(PyInterpreterState *);
1818

19+
extern PyTypeObject _PyTypeAlias_Type;
20+
1921
#ifdef __cplusplus
2022
}
2123
#endif

Include/internal/pycore_unicodeobject_generated.h

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/pathlib.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ def _make_selector(pattern_parts, flavour, case_sensitive):
8686
return cls(pat, child_parts, flavour, case_sensitive)
8787

8888

89+
@functools.lru_cache(maxsize=256)
90+
def _compile_pattern(pat, case_sensitive):
91+
flags = re.NOFLAG if case_sensitive else re.IGNORECASE
92+
return re.compile(fnmatch.translate(pat), flags).match
93+
94+
8995
class _Selector:
9096
"""A selector matches a specific glob pattern part against the children
9197
of a given path."""
@@ -133,8 +139,7 @@ def __init__(self, pat, child_parts, flavour, case_sensitive):
133139
if case_sensitive is None:
134140
# TODO: evaluate case-sensitivity of each directory in _select_from()
135141
case_sensitive = _is_case_sensitive(flavour)
136-
flags = re.NOFLAG if case_sensitive else re.IGNORECASE
137-
self.match = re.compile(fnmatch.translate(pat), flags=flags).fullmatch
142+
self.match = _compile_pattern(pat, case_sensitive)
138143

139144
def _select_from(self, parent_path, scandir):
140145
try:
@@ -680,22 +685,25 @@ def is_reserved(self):
680685
name = self._tail[-1].partition('.')[0].partition(':')[0].rstrip(' ')
681686
return name.upper() in _WIN_RESERVED_NAMES
682687

683-
def match(self, path_pattern):
688+
def match(self, path_pattern, *, case_sensitive=None):
684689
"""
685690
Return True if this path matches the given pattern.
686691
"""
692+
if case_sensitive is None:
693+
case_sensitive = _is_case_sensitive(self._flavour)
687694
pat = self.with_segments(path_pattern)
688695
if not pat.parts:
689696
raise ValueError("empty pattern")
690-
pat_parts = pat._parts_normcase
691-
parts = self._parts_normcase
697+
pat_parts = pat.parts
698+
parts = self.parts
692699
if pat.drive or pat.root:
693700
if len(pat_parts) != len(parts):
694701
return False
695702
elif len(pat_parts) > len(parts):
696703
return False
697704
for part, pat in zip(reversed(parts), reversed(pat_parts)):
698-
if not fnmatch.fnmatchcase(part, pat):
705+
match = _compile_pattern(pat, case_sensitive)
706+
if not match(part):
699707
return False
700708
return True
701709

Lib/test/mod_generics_cache.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Module for testing the behavior of generics across different modules."""
22

3-
from typing import TypeVar, Generic, Optional
3+
from typing import TypeVar, Generic, Optional, TypeAliasType
44

55
default_a: Optional['A'] = None
66
default_b: Optional['B'] = None
@@ -19,3 +19,6 @@ class A(Generic[T]):
1919
my_inner_a1: 'B.A'
2020
my_inner_a2: A
2121
my_outer_a: 'A' # unless somebody calls get_type_hints with localns=B.__dict__
22+
23+
type Alias = int
24+
OldStyle = TypeAliasType("OldStyle", int)

Lib/test/support/bytecode_helper.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ def generate_code(self, ast):
130130

131131
class CfgOptimizationTestCase(CompilationStepTestCase):
132132

133-
def get_optimized(self, insts, consts):
133+
def get_optimized(self, insts, consts, nlocals=0):
134134
insts = self.normalize_insts(insts)
135135
insts = self.complete_insts_info(insts)
136-
insts = optimize_cfg(insts, consts)
136+
insts = optimize_cfg(insts, consts, nlocals)
137137
return insts, consts
138138

139139
class AssemblerTestCase(CompilationStepTestCase):

Lib/test/test_capi/test_misc.py

+24
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,30 @@ class Subclass(BaseException, self.module.StateAccessType):
17441744
self.assertIs(Subclass().get_defining_module(), self.module)
17451745

17461746

1747+
class TestInternalFrameApi(unittest.TestCase):
1748+
1749+
@staticmethod
1750+
def func():
1751+
return sys._getframe()
1752+
1753+
def test_code(self):
1754+
frame = self.func()
1755+
code = _testinternalcapi.iframe_getcode(frame)
1756+
self.assertIs(code, self.func.__code__)
1757+
1758+
def test_lasti(self):
1759+
frame = self.func()
1760+
lasti = _testinternalcapi.iframe_getlasti(frame)
1761+
self.assertGreater(lasti, 0)
1762+
self.assertLess(lasti, len(self.func.__code__.co_code))
1763+
1764+
def test_line(self):
1765+
frame = self.func()
1766+
line = _testinternalcapi.iframe_getline(frame)
1767+
firstline = self.func.__code__.co_firstlineno
1768+
self.assertEqual(line, firstline + 2)
1769+
1770+
17471771
SUFFICIENT_TO_DEOPT_AND_SPECIALIZE = 100
17481772

17491773
class Test_Pep523API(unittest.TestCase):

Lib/test/test_clinic.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -868,9 +868,12 @@ def test_external(self):
868868
self.assertEqual(new_mtime_ns, old_mtime_ns)
869869

870870

871-
ac_tester = import_helper.import_module('_testclinic')
872-
871+
try:
872+
import _testclinic as ac_tester
873+
except ImportError:
874+
ac_tester = None
873875

876+
@unittest.skipIf(ac_tester is None, "_testclinic is missing")
874877
class ClinicFunctionalTest(unittest.TestCase):
875878
locals().update((name, getattr(ac_tester, name))
876879
for name in dir(ac_tester) if name.startswith('test_'))

Lib/test/test_compile.py

+18
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,24 @@ def foo(param, lambda_exp):
11681168
""")
11691169
compile(code, "<test>", "exec")
11701170

1171+
def test_apply_static_swaps(self):
1172+
def f(x, y):
1173+
a, a = x, y
1174+
return a
1175+
self.assertEqual(f("x", "y"), "y")
1176+
1177+
def test_apply_static_swaps_2(self):
1178+
def f(x, y, z):
1179+
a, b, a = x, y, z
1180+
return a
1181+
self.assertEqual(f("x", "y", "z"), "z")
1182+
1183+
def test_apply_static_swaps_3(self):
1184+
def f(x, y, z):
1185+
a, a, b = x, y, z
1186+
return a
1187+
self.assertEqual(f("x", "y", "z"), "y")
1188+
11711189

11721190
@requires_debug_ranges()
11731191
class TestSourcePositions(unittest.TestCase):

Lib/test/test_listcomps.py

+6
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,12 @@ def test_nested_listcomp_in_lambda(self):
510510
"""
511511
self._check_in_scopes(code, {"z": 1, "out": [(3, 2, 1)]})
512512

513+
def test_assign_to_comp_iter_var_in_outer_function(self):
514+
code = """
515+
a = [1 for a in [0]]
516+
"""
517+
self._check_in_scopes(code, {"a": [1]}, scopes=["function"])
518+
513519

514520
__test__ = {'doctests' : doctests}
515521

Lib/test/test_pathlib.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,11 @@ def test_match_common(self):
312312
# Multi-part glob-style pattern.
313313
self.assertFalse(P('/a/b/c.py').match('/**/*.py'))
314314
self.assertTrue(P('/a/b/c.py').match('/a/**/*.py'))
315+
# Case-sensitive flag
316+
self.assertFalse(P('A.py').match('a.PY', case_sensitive=True))
317+
self.assertTrue(P('A.py').match('a.PY', case_sensitive=False))
318+
self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True))
319+
self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False))
315320

316321
def test_ordering_common(self):
317322
# Ordering is tuple-alike.
@@ -916,7 +921,7 @@ def test_as_uri(self):
916921
self.assertEqual(P('//some/share/a/b%#c\xe9').as_uri(),
917922
'file://some/share/a/b%25%23c%C3%A9')
918923

919-
def test_match_common(self):
924+
def test_match(self):
920925
P = self.cls
921926
# Absolute patterns.
922927
self.assertTrue(P('c:/b.py').match('*:/*.py'))

Lib/test/test_peepholer.py

+17-3
Original file line numberDiff line numberDiff line change
@@ -971,13 +971,14 @@ def trace(frame, event, arg):
971971
self.assertNotInBytecode(f, "LOAD_FAST_CHECK")
972972

973973

974-
class DirectiCfgOptimizerTests(CfgOptimizationTestCase):
974+
class DirectCfgOptimizerTests(CfgOptimizationTestCase):
975975

976976
def cfg_optimization_test(self, insts, expected_insts,
977-
consts=None, expected_consts=None):
977+
consts=None, expected_consts=None,
978+
nlocals=0):
978979
if expected_consts is None:
979980
expected_consts = consts
980-
opt_insts, opt_consts = self.get_optimized(insts, consts)
981+
opt_insts, opt_consts = self.get_optimized(insts, consts, nlocals)
981982
expected_insts = self.normalize_insts(expected_insts)
982983
self.assertInstructionsMatch(opt_insts, expected_insts)
983984
self.assertEqual(opt_consts, expected_consts)
@@ -1058,6 +1059,19 @@ def test_conditional_jump_backward_const_condition(self):
10581059
]
10591060
self.cfg_optimization_test(insts, expected_insts, consts=list(range(5)))
10601061

1062+
def test_no_unsafe_static_swap(self):
1063+
# We can't change order of two stores to the same location
1064+
insts = [
1065+
('LOAD_CONST', 0, 1),
1066+
('LOAD_CONST', 1, 2),
1067+
('LOAD_CONST', 2, 3),
1068+
('SWAP', 3, 4),
1069+
('STORE_FAST', 1, 4),
1070+
('STORE_FAST', 1, 4),
1071+
('POP_TOP', 0, 4),
1072+
('RETURN_VALUE', 5)
1073+
]
1074+
self.cfg_optimization_test(insts, insts, consts=list(range(3)), nlocals=1)
10611075

10621076
if __name__ == "__main__":
10631077
unittest.main()

0 commit comments

Comments
 (0)