Skip to content

Commit e9a1e9a

Browse files
committed
add more tests, remove defensive code
1 parent c7daa03 commit e9a1e9a

11 files changed

Lines changed: 88 additions & 12 deletions

File tree

Include/internal/pycore_interp_structs.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,13 @@ struct _py_func_state {
525525
/****** type state *********/
526526

527527
/* For now we hard-code this to a value for which we are confident
528-
all the static builtin types will fit (for all builds). */
529-
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 203
528+
all the static builtin types will fit (for all builds).
529+
If you add a new static type to the standard library, you may have to
530+
update one of these numbers.
531+
*/
532+
#define _Py_NUM_MANAGED_PREINITIALIZED_TYPES 120
533+
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES \
534+
(_Py_NUM_MANAGED_PREINITIALIZED_TYPES + 83)
530535
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10
531536
#define _Py_MAX_MANAGED_STATIC_TYPES \
532537
(_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES)

InternalDocs/parser.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,13 @@ directory on the CPython repository and manually call the parser generator by ex
819819
$ python -m pegen python <PATH TO YOUR GRAMMAR FILE>
820820
```
821821

822+
> [!CAUTION]
823+
> Python's grammar (the `Grammar/python.gram` file) is written for the
824+
> C backend. To experiment, you will need to write a grammar
825+
> without C-specific parts like actions and the trailer.
826+
> See [#133560](https://github.com/python/cpython/issues/133560)
827+
> and [#96424](https://github.com/python/cpython/issues/96424) for more information.
828+
822829
This will generate a file called `parse.py` in the same directory that you
823830
can use to parse some input:
824831

Lib/pdb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ def get_default_backend():
376376

377377
def _pyrepl_available():
378378
"""return whether pdb should use _pyrepl for input"""
379-
if not os.getenv("PYTHON_BASIC_REPL"):
379+
if os.getenv("PYTHON_BASIC_REPL"):
380380
CAN_USE_PYREPL = False
381381
else:
382382
try:

Lib/test/test_capi/test_opt.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4819,6 +4819,46 @@ def f(n):
48194819
# Every element must be False: the set is empty after discard()
48204820
self.assertTrue(all(r is False for r in res))
48214821

4822+
def _check_to_bool_recorded_type(self, inner, value, guard_op):
4823+
"""Recorded-type path: a value whose static type is unknown but whose
4824+
runtime type is recorded should emit `guard_op` + _TO_BOOL_SIZED."""
4825+
self.assertEqual(inner(value), TIER2_THRESHOLD)
4826+
ex_inner = get_first_executor(inner)
4827+
self.assertIsNotNone(ex_inner)
4828+
uops = get_opnames(ex_inner)
4829+
self.assertIn(guard_op, uops)
4830+
self.assertIn("_TO_BOOL_SIZED", uops)
4831+
self.assertNotIn("_TO_BOOL", uops)
4832+
4833+
def test_to_bool_bytes(self):
4834+
def inner(v):
4835+
cnt = 0
4836+
for _ in range(TIER2_THRESHOLD):
4837+
if v:
4838+
cnt += 1
4839+
return cnt
4840+
self._check_to_bool_recorded_type(inner, b"hello", "_GUARD_TOS_BYTES")
4841+
4842+
def test_to_bool_bytearray(self):
4843+
def inner(v):
4844+
cnt = 0
4845+
for _ in range(TIER2_THRESHOLD):
4846+
if v:
4847+
cnt += 1
4848+
return cnt
4849+
self._check_to_bool_recorded_type(
4850+
inner, bytearray(b"hello"), "_GUARD_TOS_BYTEARRAY")
4851+
4852+
def test_to_bool_frozenset(self):
4853+
def inner(v):
4854+
cnt = 0
4855+
for _ in range(TIER2_THRESHOLD):
4856+
if v:
4857+
cnt += 1
4858+
return cnt
4859+
self._check_to_bool_recorded_type(
4860+
inner, frozenset({1, 2, 3}), "_GUARD_TOS_FROZENSET")
4861+
48224862
def test_attr_promotion_failure(self):
48234863
# We're not testing for any specific uops here, just
48244864
# testing it doesn't crash.

Lib/test/test_pdb.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4753,6 +4753,16 @@ def foo(self):
47534753
stdout, stderr = self.run_pdb_script(script, commands)
47544754
self.assertIn("The specified object 'C.foo' is not a function", stdout)
47554755

4756+
def test_pyrepl_available(self):
4757+
with patch.dict(os.environ, {"PYTHON_BASIC_REPL": "1"}):
4758+
self.assertFalse(pdb._pyrepl_available())
4759+
4760+
with patch.dict(os.environ, {}, clear=True):
4761+
mod = types.ModuleType("_pyrepl.main")
4762+
mod.CAN_USE_PYREPL = True
4763+
with patch.dict("sys.modules", {"_pyrepl.main": mod}):
4764+
self.assertTrue(pdb._pyrepl_available())
4765+
47564766

47574767
class ChecklineTests(unittest.TestCase):
47584768
def setUp(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Block Apple Clang from being used to build the JIT as it ships without
2+
required LLVM tools.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix inverted :envvar:`PYTHON_BASIC_REPL` environment check in
2+
``pdb._pyrepl_available``.

Objects/object.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2526,7 +2526,7 @@ extern PyTypeObject _PyMemoryIter_Type;
25262526
extern PyTypeObject _PyPositionsIterator;
25272527
extern PyTypeObject _Py_GenericAliasIterType;
25282528

2529-
static PyTypeObject* static_types[] = {
2529+
static PyTypeObject* static_types[_Py_NUM_MANAGED_PREINITIALIZED_TYPES] = {
25302530
// The two most important base types: must be initialized first and
25312531
// deallocated last.
25322532
&PyBaseObject_Type,
@@ -2644,6 +2644,9 @@ static PyTypeObject* static_types[] = {
26442644
&_PyUnion_Type,
26452645
#ifdef _Py_TIER2
26462646
&_PyUOpExecutor_Type,
2647+
#else
2648+
// The array should have the same size on all builds; see gh-149139
2649+
NULL,
26472650
#endif
26482651
&_PyWeakref_CallableProxyType,
26492652
&_PyWeakref_ProxyType,
@@ -2668,6 +2671,9 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
26682671
// All other static types (unless initialized elsewhere)
26692672
for (size_t i=0; i < Py_ARRAY_LENGTH(static_types); i++) {
26702673
PyTypeObject *type = static_types[i];
2674+
if (type == NULL) {
2675+
continue;
2676+
}
26712677
if (_PyStaticType_InitBuiltin(interp, type) < 0) {
26722678
return _PyStatus_ERR("Can't initialize builtin type");
26732679
}
@@ -2708,6 +2714,9 @@ _PyTypes_FiniTypes(PyInterpreterState *interp)
27082714
// their base classes.
27092715
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_types)-1; i>=0; i--) {
27102716
PyTypeObject *type = static_types[i];
2717+
if (type == NULL) {
2718+
continue;
2719+
}
27112720
_PyStaticType_FiniBuiltin(interp, type);
27122721
}
27132722
}

Python/optimizer_bytecodes.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -714,11 +714,10 @@ dummy_func(void) {
714714
REPLACE_OP(this_instr, _TO_BOOL_SIZED, 0, size_offset);
715715
}
716716
}
717-
else if (emitted_guard) {
718-
// Defensive: we emitted a guard but didn't compute a
719-
// size_offset (shouldn't happen with the table above).
720-
// Ensure the original _TO_BOOL still reaches output.
721-
ADD_OP(_TO_BOOL, 0, 0);
717+
else {
718+
// Every type that sets emitted_guard above is also in the
719+
// size_offset table, so we never reach here with a guard.
720+
assert(!emitted_guard);
722721
}
723722
res = sym_new_truthiness(ctx, value, true);
724723
}

Python/optimizer_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)