10000 Merge branch 'main' into remove-load-attr-method-with-dict · python/cpython@e112966 · GitHub
[go: up one dir, main page]

Skip to content

Commit e112966

Browse files
authored
Merge branch 'main' into remove-load-attr-method-with-dict
2 parents b63534d + 105e373 commit e112966

File tree

15 files changed

+48
-35
lines changed

15 files changed

+48
-35
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Python/traceback.c @iritkatriel
6363
# bytecode.
6464
**/*import*.c @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw
6565
**/*import*.py @brettcannon @encukou @ericsnowcurrently @ncoghlan @warsaw
66-
**/*importlib/resources/* @jaraco @warsaw @brettcannon @FFY00
66+
**/*importlib/resources/* @jaraco @warsaw @FFY00
6767
**/importlib/metadata/* @jaraco @warsaw
6868

6969
# Dates and times
@@ -152,8 +152,5 @@ Lib/ast.py @isidentical
152152
/Mac/ @python/macos-team
153153
**/*osx_support* @python/macos-team
154154

155-
# pathlib
156-
**/*pathlib* @brettcannon
157-
158155
# zipfile.Path
159156
**/*zipfile/*_path.py @jaraco

Doc/library/locale.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,9 @@ The :mod:`locale` module defines the following exception and functions:
496496
system, like those returned by :func:`os.strerror` might be affected by this
497497
category.
498498

499+
This value may not be available on operating systems not conforming to the
500+
POSIX standard, most notably Windows.
501+
499502

500503
.. data:: LC_NUMERIC
501504

Include/cpython/code.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ typedef struct {
8787
int co_nlocalsplus; /* number of local + cell + free variables */ \
8888
int co_framesize; /* Size of frame in words */ \
8989
int co_nlocals; /* number of local variables */ \
90-
int co_nplaincellvars; /* number of non-arg cell variables */ \
9190
int co_ncellvars; /* total number of cell variables */ \
9291
int co_nfreevars; /* number of free variables */ \
9392
uint32_t co_version; /* version number */ \
@@ -157,6 +156,11 @@ static inline Py_ssize_t PyCode_GetNumFree(PyCodeObject *op) {
157156
return op->co_nfreevars;
158157
}
159158

159+
static inline int PyCode_GetFirstFree(PyCodeObject *op) {
160+
assert(PyCode_Check(op));
161+
return op->co_nlocalsplus - op->co_nfreevars;
162+
}
163+
160164
#define _PyCode_CODE(CO) _Py_RVALUE((_Py_CODEUNIT *)(CO)->co_code_adaptive)
161165
#define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT))
162166

Lib/test/test_unittest/testmock/testmock.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,22 @@ def test_mock_unsafe(self):
16521652
m.aseert_foo_call()
16531653
m.assrt_foo_call()
16541654

1655+
# gh-100739
1656+
def test_mock_safe_with_spec(self):
1657+
class Foo(object):
1658+
def assert_bar(self):
1659+
pass
1660+
1661+
def assertSome(self):
1662+
pass
1663+
1664+
m = Mock(spec=Foo)
1665+
m.assert_bar()
1666+
m.assertSome()
1667+
1668+
m.assert_bar.assert_called_once()
1669+
m.assertSome.assert_called_once()
1670+
16551671
#Issue21262
16561672
def test_assert_not_called(self):
16571673
m = Mock()

Lib/unittest/mock.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ def __getattr__(self, name):
652652
raise AttributeError("Mock object has no attribute %r" % name)
653653
elif _is_magic(name):
654654
raise AttributeError(name)
655-
if not self._mock_unsafe:
655+
if not self._mock_unsafe and (not self._mock_methods or name not in self._mock_methods):
656656
if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')):
657657
raise AttributeError(
658658
f"{name!r} is not a valid assertion. Use a spec "
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removed the co_nplaincellvars field from the code object, as it is
2+
redundant.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix ``unittest.mock.Mock`` not respecting the spec for attribute names prefixed with ``assert``.

Objects/codeobject.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,10 @@ _Py_set_localsplus_info(int offset, PyObject *name, _PyLocals_Kind kind,
247247

248248
static void
249249
get_localsplus_counts(PyObject *names, PyObject *kinds,
250-
int *pnlocals, int *pnplaincellvars, int *pncellvars,
250+
int *pnlocals, int *pncellvars,
251251
int *pnfreevars)
252252
{
253253
int nlocals = 0;
254-
int nplaincellvars = 0;
255254
int ncellvars = 0;
256255
int nfreevars = 0;
257256
Py_ssize_t nlocalsplus = PyTuple_GET_SIZE(names);
@@ -265,7 +264,6 @@ get_localsplus_counts(PyObject *names, PyObject *kinds,
265264
}
266265
else if (kind & CO_FAST_CELL) {
267266
ncellvars += 1;
268-
nplaincellvars += 1;
269267
}
270268
else if (kind & CO_FAST_FREE) {
271269
nfreevars += 1;
@@ -274,9 +272,6 @@ get_localsplus_counts(PyObject *names, PyObject *kinds,
274272
if (pnlocals != NULL) {
275273
*pnlocals = nlocals;
276274
}
277-
if (pnplaincellvars != NULL) {
278-
*pnplaincellvars = nplaincellvars;
279-
}
280275
if (pncellvars != NULL) {
281276
*pncellvars = ncellvars;
282277
}
@@ -351,7 +346,7 @@ _PyCode_Validate(struct _PyCodeConstructor *con)
351346
* here to avoid the possibility of overflow (however remote). */
352347
int nlocals;
353348
get_localsplus_counts(con->localsplusnames, con->localspluskinds,
354-
&nlocals, NULL, NULL, NULL);
349+
&nlocals, NULL, NULL);
355350
int nplainlocals = nlocals -
356351
con->argcount -
357352
con->kwonlyargcount -
@@ -371,9 +366,9 @@ static void
371366
init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
372367
{
373368
int nlocalsplus = (int)PyTuple_GET_SIZE(con->localsplusnames);
374-
int nlocals, nplaincellvars, ncellvars, nfreevars;
369+
int nlocals, ncellvars, nfreevars;
375370
get_localsplus_counts(con->localsplusnames, con->localspluskinds,
376-
&nlocals, &nplaincellvars, &ncellvars, &nfreevars);
371+
&nlocals, &ncellvars, &nfreevars);
377372

378373
co->co_filename = Py_NewRef(con->filename);
379374
co->co_name = Py_NewRef(con->name);
@@ -401,7 +396,6 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
401396
co->co_nlocalsplus = nlocalsplus;
402397
co->co_nlocals = nlocals;
403398
co->co_framesize = nlocalsplus + con->stacksize + FRAME_SPECIALS_SIZE;
404-
co->co_nplaincellvars = nplaincellvars;
405399
co->co_ncellvars = ncellvars;
406400
co->co_nfreevars = nfreevars;
407401
co->co_version = _Py_next_func_version;

Objects/frameobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
11191119

11201120
/* Free vars have not been initialized -- Do that */
11211121
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
1122-
int offset = co->co_nlocals + co->co_nplaincellvars;
1122+
int offset = PyCode_GetFirstFree(co);
11231123
for (int i = 0; i < co->co_nfreevars; ++i) {
11241124
PyObject *o = PyTuple_GET_ITEM(closure, i);
11251125
frame->localsplus[offset + i] = Py_NewRef(o);

Objects/typeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9514,7 +9514,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
95149514

95159515
// Look for __class__ in the free vars.
95169516
PyTypeObject *type = NULL;
9517-
int i = co->co_nlocals + co->co_nplaincellvars;
9517+
int i = PyCode_GetFirstFree(co);
95189518
for (; i < co->co_nlocalsplus; i++) {
95199519
assert((_PyLocals_GetKind(co->co_localspluskinds, i) & CO_FAST_FREE) != 0);
95209520
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);

Python/bytecodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1357,8 +1357,8 @@ dummy_func(
13571357
PyCodeObject *co = frame->f_code;
13581358
assert(PyFunction_Check(frame->f_funcobj));
13591359
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
1360-
int offset = co->co_nlocals + co->co_nplaincellvars;
13611360
assert(oparg == co->co_nfreevars);
1361+
int offset = co->co_nlocalsplus - oparg;
13621362
for (int i = 0; i < oparg; ++i) {
13631363
PyObject *o = PyTuple_GET_ITEM(closure, i);
13641364
frame->localsplus[offset + i] = Py_NewRef(o);

Python/ceval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3417,7 +3417,7 @@ format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)
34173417
if (_PyErr_Occurred(tstate))
34183418
return;
34193419
name = PyTuple_GET_ITEM(co->co_localsplusnames, oparg);
3420-
if (oparg < co->co_nplaincellvars + co->co_nlocals) {
3420+
if (oparg < PyCode_GetFirstFree(co)) {
34213421
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
34223422
UNBOUNDLOCAL_ERROR_MSG, name);
34233423
} else {

Python/compile.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@
131131
(opcode) == STORE_FAST__LOAD_FAST || \
132132
(opcode) == STORE_FAST__STORE_FAST)
133133

134-
#define IS_TOP_LEVEL_AWAIT(c) ( \
135-
(c->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
136-
&& (c->u->u_ste->ste_type == ModuleBlock))
134+
#define IS_TOP_LEVEL_AWAIT(C) ( \
135+
((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \
136+
&& ((C)->u->u_ste->ste_type == ModuleBlock))
137137

138138
typedef _PyCompilerSrcLocation location;
139139

@@ -479,7 +479,7 @@ struct compiler {
479479
PyArena *c_arena; /* pointer to memory allocation arena */
480480
};
481481

482-
#define CFG_BUILDER(c) (&((c)->u->u_cfg_builder))
482+
#define CFG_BUILDER(C) (&((C)->u->u_cfg_builder))
483483

484484

485485
typedef struct {
@@ -1626,7 +1626,7 @@ cfg_builder_addop_j(cfg_builder *g, location loc,
16261626

16271627
#define ADDOP_IN_SCOPE(C, LOC, OP) { \
16281628
if (cfg_builder_addop_noarg(CFG_BUILDER(C), (OP), (LOC)) < 0) { \
1629-
compiler_exit_scope(c); \
1629+
compiler_exit_scope(C); \
16301630
return -1; \
16311631
} \
16321632
}
@@ -1692,7 +1692,7 @@ cfg_builder_addop_j(cfg_builder *g, location loc,
16921692

16931693
#define VISIT_IN_SCOPE(C, TYPE, V) {\
16941694
if (compiler_visit_ ## TYPE((C), (V)) < 0) { \
1695-
compiler_exit_scope(c); \
1695+
compiler_exit_scope(C); \
16961696
return ERROR; \
16971697
} \
16981698
}
@@ -1713,7 +1713,7 @@ cfg_builder_addop_j(cfg_builder *g, location loc,
17131713
for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \
17141714
TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \
17151715
if (compiler_visit_ ## TYPE((C), elt) < 0) { \
1716-
compiler_exit_scope(c); \
1716+
compiler_exit_scope(C); \
17171717
return ERROR; \
17181718
} \
17191719
} \
@@ -2260,7 +2260,7 @@ compiler_make_closure(struct compiler *c, location loc,
22602260
qualname = co->co_name;
22612261

22622262
if (co->co_nfreevars) {
2263-
int i = co->co_nlocals + co->co_nplaincellvars;
2263+
int i = PyCode_GetFirstFree(co);
22642264
for (; i < co->co_nlocalsplus; ++i) {
22652265
/* Bypass com_addop_varname because it will generate
22662266
LOAD_DEREF but LOAD_CLOSURE is needed.

Python/generated_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/build/deepfreeze.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ def get_localsplus_counts(code: types.CodeType,
6161
names: Tuple[str, ...],
6262
kinds: bytes) -> Tuple[int, int, int, int]:
6363
nlocals = 0
64-
nplaincellvars = 0
6564
ncellvars = 0
6665
nfreevars = 0
6766
assert len(names) == len(kinds)
@@ -72,15 +71,13 @@ def get_localsplus_counts(code: types.CodeType,
7271
ncellvars += 1
7372
elif kind & CO_FAST_CELL:
7473
ncellvars += 1
75-
nplaincellvars += 1
7674
elif kind & CO_FAST_FREE:
7775
nfreevars += 1
7876
assert nlocals == len(code.co_varnames) == code.co_nlocals, \
7977
(nlocals, len(code.co_varnames), code.co_nlocals)
8078
assert ncellvars == len(code.co_cellvars)
8179
assert nfreevars == len(code.co_freevars)
82-
assert len(names) == nlocals + nplaincellvars + nfreevars
83-
return nlocals, nplaincellvars, ncellvars, nfreevars
80+
return nlocals, ncellvars, nfreevars
8481

8582

8683
PyUnicode_1BYTE_KIND = 1
243240
co_localsplusnames = self.generate(name + "_localsplusnames", localsplusnames)
244241
co_localspluskinds = self.generate(name + "_localspluskinds", localspluskinds)
245242
# Derived values
246-
nlocals, nplaincellvars, ncellvars, nfreevars = \
243+
nlocals, ncellvars, nfreevars = \
247244
get_localsplus_counts(code, localsplusnames, localspluskinds)
248245
co_code_adaptive = make_string_literal(code.co_code)
249246
self.write("static")
@@ -268,7 +265,6 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
268265
self.field(code, "co_firstlineno")
269266
self.write(f".co_nlocalsplus = {len(localsplusnames)},")
270267
self.field(code, "co_nlocals")
271-
self.write(f".co_nplaincellvars = {nplaincellvars},")
272268
self.write(f".co_ncellvars = {ncellvars},")
273269
self.write(f".co_nfreevars = {nfreevars},")
274270
self.write(f".co_version = {next_code_version},")

0 commit comments

Comments
 (0)
0