8000 Fix class scoping · python/cpython@f452eb2 · GitHub
[go: up one dir, main page]

Skip to content

Commit f452eb2

Browse files
committed
Fix class scoping
1 parent fbb1d88 commit f452eb2

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

Lib/test/test_type_annotations.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,51 @@ def func(x: undefined, /, y: undefined, *args: undefined, z: undefined, **kwargs
279279
"kwargs": 1,
280280
"return": 1,
281281
})
282+
283+
def test_async_function(self):
284+
async def func(x: undefined, /, y: undefined, *args: undefined, z: undefined, **kwargs: undefined) -> undefined:
285+
pass
286+
287+
with self.assertRaises(NameError):
288+
func.__annotations__
289+
290+
undefined = 1
291+
self.assertEqual(func.__annotations__, {
292+
"x": 1,
293+
"y": 1,
294+
"args": 1,
295+
"z": 1,
296+
"kwargs": 1,
297+
"return": 1,
298+
})
299+
300+
def test_class(self):
301+
class X:
302+
a: undefined
303+
304+
with self.assertRaises(NameError):
305+
X.__annotations__
306+
307+
undefined = 1
308+
self.assertEqual(X.__annotations__, {"a": 1})
309+
310+
def test_module(self):
311+
ns = run_code("x: undefined = 1")
312+
anno = ns["__annotate__"]
313+
with self.assertRaises(AssertionError): # TODO NotImplementedError
314+
anno(2)
315+
316+
with self.assertRaises(NameError):
317+
anno(1)
318+
319+
ns["undefined"] = 1
320+
self.assertEqual(anno(1), {"x": 1})
321+
322+
def test_class_scoping(self):
323+
class Outer:
324+
def meth(self, x: Nested): ...
325+
x: Nested
326+
class Nested: ...
327+
328+
self.assertEqual(Outer.meth.__annotations__, {"x": Outer.Nested})
329+
self.assertEqual(Outer.__annotations__, {"x": Outer.Nested})

Python/symtable.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ int
542542
_PyST_IsFunctionLike(PySTEntryObject *ste)
543543
{
544544
return ste->ste_type == FunctionBlock
545+
|| ste->ste_type == AnnotationBlock
545546
|| ste->ste_type == TypeVarBoundBlock
546547
|| ste->ste_type == TypeAliasBlock
547548
|| ste->ste_type == TypeParamBlock;
@@ -2478,12 +2479,20 @@ symtable_visit_annotation(struct symtable *st, expr_ty annotation,
24782479
}
24792480
else {
24802481
if (st->st_cur->ste_annotation_block == NULL) {
2482+
_Py_block_ty current_type = st->st_cur->ste_type;
24812483
if (!symtable_enter_block(st, parent_ste->ste_name, AnnotationBlock,
24822484
key, LOCATION(annotation))) {
24832485
VISIT_QUIT(st, 0);
24842486
}
24852487
parent_ste->ste_annotation_block =
24862488
(struct _symtable_entry *)Py_NewRef(st->st_cur);
2489+
if (current_type == ClassBlock) {
2490+
st->st_cur->ste_can_see_class_scope = 1;
2491+
if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(annotation))) {
2492+
return 0;
2493+
}
2494+
}
2495+
24872496
_Py_DECLARE_STR(format, ".format");
24882497
// We need to insert code that reads this "parameter" to the function.
24892498
if (!symtable_add_def(st, &_Py_STR(format), DEF_PARAM,
@@ -2531,10 +2540,17 @@ static int
25312540
symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ty returns,
25322541
struct _symtable_entry *function_ste)
25332542
{
2543+
_Py_block_ty current_type = st->st_cur->ste_type;
25342544
if (!symtable_enter_block(st, function_ste->ste_name, AnnotationBlock,
25352545
(void *)a, LOCATION(o))) {
25362546
VISIT_QUIT(st, 0);
25372547
}
2548+
if (current_type == ClassBlock) {
2549+
st->st_cur->ste_can_see_class_scope = 1;
2550+
if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(o))) {
2551+
return 0;
2552+
}
2553+
}
25382554
_Py_DECLARE_STR(format, ".format");
25392555
// We need to insert code that reads this "parameter" to the function.
25402556
if (!symtable_add_def(st, &_Py_STR(format), DEF_PARAM, LOCATION(o))) {
@@ -2793,7 +2809,7 @@ symtable_visit_dictcomp(struct symtable *st, expr_ty e)
27932809
static int
27942810
symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_ty e)
27952811
{
2796-
enum _block_type type = st->st_cur->ste_type;
2812+
_Py_block_ty type = st->st_cur->ste_type;
27972813
if (type == AnnotationBlock)
27982814
PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
27992815
else if (type == TypeVarBoundBlock)

0 commit comments

Comments
 (0)
0