aboutsummaryrefslogtreecommitdiff
path: root/Python/symtable.c
diff options
context:
space:
mode:
authorBatuhan Taskaya <isidentical@gmail.com>2021-05-03 10:43:00 +0300
committerGitHub <noreply@github.com>2021-05-03 10:43:00 +0300
commitad106c68eb00f5e4af2f937107baff6141948cee (patch)
treee3b3b5aa1e2f62015da34efd1a46b4faef378ab1 /Python/symtable.c
parent37ebdf0a866457ce825d0ff6e498a10938895760 (diff)
downloadcpython3-ad106c68eb00f5e4af2f937107baff6141948cee.tar.gz
bpo-42725: Render annotations effectless on symbol table with PEP 563 (GH-25583)
Diffstat (limited to 'Python/symtable.c')
-rw-r--r--Python/symtable.c101
1 files changed, 91 insertions, 10 deletions
diff --git a/Python/symtable.c b/Python/symtable.c
index e620f1ecc1..62bd1e2ec4 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1,6 +1,6 @@
#include "Python.h"
#include "pycore_ast.h" // identifier, stmt_ty
-#include "pycore_compile.h" // _Py_Mangle()
+#include "pycore_compile.h" // _Py_Mangle(), _PyFuture_FromAST()
#include "pycore_parser.h" // _PyParser_ASTFromString()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_symtable.h" // PySTEntryObject
@@ -45,6 +45,10 @@
#define NAMED_EXPR_COMP_ITER_EXPR \
"assignment expression cannot be used in a comprehension iterable expression"
+#define ANNOTATION_NOT_ALLOWED \
+"'%s' can not be used within an annotation"
+
+
static PySTEntryObject *
ste_new(struct symtable *st, identifier name, _Py_block_ty block,
void *key, int lineno, int col_offset,
@@ -209,17 +213,19 @@ static int symtable_visit_alias(struct symtable *st, alias_ty);
static int symtable_visit_comprehension(struct symtable *st, comprehension_ty);
static int symtable_visit_keyword(struct symtable *st, keyword_ty);
static int symtable_visit_params(struct symtable *st, asdl_arg_seq *args);
+static int symtable_visit_annotation(struct symtable *st, expr_ty annotation);
static int symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args);
static int symtable_implicit_arg(struct symtable *st, int pos);
-static int symtable_visit_annotations(struct symtable *st, arguments_ty, expr_ty);
+static int symtable_visit_annotations(struct symtable *st, stmt_ty, arguments_ty, expr_ty);
static int symtable_visit_withitem(struct symtable *st, withitem_ty item);
static int symtable_visit_match_case(struct symtable *st, match_case_ty m);
static int symtable_visit_pattern(struct symtable *st, pattern_ty s);
+static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty);
static identifier top = NULL, lambda = NULL, genexpr = NULL,
listcomp = NULL, setcomp = NULL, dictcomp = NULL,
- __class__ = NULL;
+ __class__ = NULL, _annotation = NULL;
#define GET_IDENTIFIER(VAR) \
((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR)))
@@ -987,8 +993,17 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
/* The entry is owned by the stack. Borrow it for st_cur. */
Py_DECREF(ste);
st->st_cur = ste;
+
+ /* Annotation blocks shouldn't have any affect on the symbol table since in
+ * the compilation stage, they will all be transformed to strings. They are
+ * only created if future 'annotations' feature is activated. */
+ if (block == AnnotationBlock) {
+ return 1;
+ }
+
if (block == ModuleBlock)
st->st_global = st->st_cur->ste_symbols;
+
if (prev) {
if (PyList_Append(prev->ste_children, (PyObject *)ste) < 0) {
return 0;
@@ -1190,7 +1205,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
if (s->v.FunctionDef.args->kw_defaults)
VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults);
- if (!symtable_visit_annotations(st, s->v.FunctionDef.args,
+ if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
s->v.FunctionDef.returns))
VISIT_QUIT(st, 0);
if (s->v.FunctionDef.decorator_list)
@@ -1273,7 +1288,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
else {
VISIT(st, expr, s->v.AnnAssign.target);
}
- VISIT(st, expr, s->v.AnnAssign.annotation);
+ if (!symtable_visit_annotation(st, s->v.AnnAssign.annotation)) {
+ VISIT_QUIT(st, 0);
+ }
+
if (s->v.AnnAssign.value) {
VISIT(st, expr, s->v.AnnAssign.value);
}
@@ -1422,7 +1440,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (s->v.AsyncFunctionDef.args->kw_defaults)
VISIT_SEQ_WITH_NULL(st, expr,
s->v.AsyncFunctionDef.args->kw_defaults);
- if (!symtable_visit_annotations(st, s->v.AsyncFunctionDef.args,
+ if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
s->v.AsyncFunctionDef.returns))
VISIT_QUIT(st, 0);
if (s->v.AsyncFunctionDef.decorator_list)
@@ -1564,6 +1582,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
}
switch (e->kind) {
case NamedExpr_kind:
+ if (!symtable_raise_if_annotation_block(st, "named expression", e)) {
+ VISIT_QUIT(st, 0);
+ }
if(!symtable_handle_namedexpr(st, e))
VISIT_QUIT(st, 0);
break;
@@ -1624,15 +1645,24 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
VISIT_QUIT(st, 0);
break;
case Yield_kind:
+ if (!symtable_raise_if_annotation_block(st, "yield expression", e)) {
+ VISIT_QUIT(st, 0);
+ }
if (e->v.Yield.value)
VISIT(st, expr, e->v.Yield.value);
st->st_cur->ste_generator = 1;
break;
case YieldFrom_kind:
+ if (!symtable_raise_if_annotation_block(st, "yield expression", e)) {
+ VISIT_QUIT(st, 0);
+ }
VISIT(st, expr, e->v.YieldFrom.value);
st->st_cur->ste_generator = 1;
break;
case Await_kind:
+ if (!symtable_raise_if_annotation_block(st, "await expression", e)) {
+ VISIT_QUIT(st, 0);
+ }
VISIT(st, expr, e->v.Await.value);
st->st_cur->ste_coroutine = 1;
break;
@@ -1781,6 +1811,24 @@ symtable_visit_params(struct symtable *st, asdl_arg_seq *args)
}
static int
+symtable_visit_annotation(struct symtable *st, expr_ty annotation)
+{
+ int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;
+ if (future_annotations &&
+ !symtable_enter_block(st, GET_IDENTIFIER(_annotation), AnnotationBlock,
+ (void *)annotation, annotation->lineno,
+ annotation->col_offset, annotation->end_lineno,
+ annotation->end_col_offset)) {
+ VISIT_QUIT(st, 0);
+ }
+ VISIT(st, expr, annotation);
+ if (future_annotations && !symtable_exit_block(st)) {
+ VISIT_QUIT(st, 0);
+ }
+ return 1;
+}
+
+static int
symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args)
{
int i;
@@ -1798,8 +1846,15 @@ symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args)
}
static int
-symtable_visit_annotations(struct symtable *st, arguments_ty a, expr_ty returns)
+symtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ty returns)
{
+ int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;
+ if (future_annotations &&
+ !symtable_enter_block(st, GET_IDENTIFIER(_annotation), AnnotationBlock,
+ (void *)o, o->lineno, o->col_offset, o->end_lineno,
+ o->end_col_offset)) {
+ VISIT_QUIT(st, 0);
+ }
if (a->posonlyargs && !symtable_visit_argannotations(st, a->posonlyargs))
return 0;
if (a->args && !symtable_visit_argannotations(st, a->args))
@@ -1810,8 +1865,12 @@ symtable_visit_annotations(struct symtable *st, arguments_ty a, expr_ty returns)
VISIT(st, expr, a->kwarg->annotation);
if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))
return 0;
- if (returns)
- VISIT(st, expr, returns);
+ if (future_annotations && !symtable_exit_block(st)) {
+ VISIT_QUIT(st, 0);
+ }
+ if (returns && !symtable_visit_annotation(st, returns)) {
+ VISIT_QUIT(st, 0);
+ }
return 1;
}
@@ -2033,6 +2092,21 @@ symtable_visit_dictcomp(struct symtable *st, expr_ty e)
e->v.DictComp.value);
}
+static int
+symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_ty e)
+{
+ if (st->st_cur->ste_type != AnnotationBlock) {
+ return 1;
+ }
+
+ PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);
+ PyErr_RangedSyntaxLocationObject(st->st_filename,
+ e->lineno,
+ e->col_offset + 1,
+ e->end_lineno,
+ e->end_col_offset + 1);
+ return 0;
+}
struct symtable *
_Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
@@ -2051,7 +2125,14 @@ _Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
_PyArena_Free(arena);
return NULL;
}
- st = _PySymtable_Build(mod, filename, 0);
+ PyFutureFeatures *future = _PyFuture_FromAST(mod, filename);
+ if (future == NULL) {
+ _PyArena_Free(arena);
+ return NULL;
+ }
+ future->ff_features |= flags->cf_flags;
+ st = _PySymtable_Build(mod, filename, future);
+ PyObject_Free((void *)future);
_PyArena_Free(arena);
return st;
}