mirror of
https://github.com/python/cpython.git
synced 2025-08-31 22:18:28 +00:00
bpo-36280: Add Constant.kind field (GH-12295)
The value is a string for string and byte literals, None otherwise. It is 'u' for u"..." literals, 'b' for b"..." literals, '' for "..." literals. The 'r' (raw) prefix is ignored. Does not apply to f-strings. This appears sufficient to make mypy capable of using the stdlib ast module instead of typed_ast (assuming a mypy patch I'm working on). WIP: I need to make the tests pass. @ilevkivskyi @serhiy-storchaka https://bugs.python.org/issue36280
This commit is contained in:
parent
8b5bdda5b4
commit
10f8ce6688
6 changed files with 142 additions and 60 deletions
32
Python/Python-ast.c
generated
32
Python/Python-ast.c
generated
|
@ -324,8 +324,10 @@ static char *JoinedStr_fields[]={
|
|||
"values",
|
||||
};
|
||||
static PyTypeObject *Constant_type;
|
||||
_Py_IDENTIFIER(kind);
|
||||
static char *Constant_fields[]={
|
||||
"value",
|
||||
"kind",
|
||||
};
|
||||
static PyTypeObject *Attribute_type;
|
||||
_Py_IDENTIFIER(attr);
|
||||
|
@ -950,7 +952,7 @@ static int init_types(void)
|
|||
if (!FormattedValue_type) return 0;
|
||||
JoinedStr_type = make_type("JoinedStr", expr_type, JoinedStr_fields, 1);
|
||||
if (!JoinedStr_type) return 0;
|
||||
Constant_type = make_type("Constant", expr_type, Constant_fields, 1);
|
||||
Constant_type = make_type("Constant", expr_type, Constant_fields, 2);
|
||||
if (!Constant_type) return 0;
|
||||
Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3);
|
||||
if (!Attribute_type) return 0;
|
||||
|
@ -2287,8 +2289,8 @@ JoinedStr(asdl_seq * values, int lineno, int col_offset, int end_lineno, int
|
|||
}
|
||||
|
||||
expr_ty
|
||||
Constant(constant value, int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena)
|
||||
Constant(constant value, string kind, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena)
|
||||
{
|
||||
expr_ty p;
|
||||
if (!value) {
|
||||
|
@ -2301,6 +2303,7 @@ Constant(constant value, int lineno, int col_offset, int end_lineno, int
|
|||
return NULL;
|
||||
p->kind = Constant_kind;
|
||||
p->v.Constant.value = value;
|
||||
p->v.Constant.kind = kind;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
p->end_lineno = end_lineno;
|
||||
|
@ -3507,6 +3510,11 @@ ast2obj_expr(void* _o)
|
|||
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_string(o->v.Constant.kind);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_kind, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case Attribute_kind:
|
||||
result = PyType_GenericNew(Attribute_type, NULL, NULL);
|
||||
|
@ -7224,6 +7232,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
|
|||
}
|
||||
if (isinstance) {
|
||||
constant value;
|
||||
string kind;
|
||||
|
||||
if (_PyObject_LookupAttrId(obj, &PyId_value, &tmp) < 0) {
|
||||
return 1;
|
||||
|
@ -7238,8 +7247,21 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
|
|||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
}
|
||||
*out = Constant(value, lineno, col_offset, end_lineno, end_col_offset,
|
||||
arena);
|
||||
if (_PyObject_LookupAttrId(obj, &PyId_kind, &tmp) < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (tmp == NULL || tmp == Py_None) {
|
||||
Py_CLEAR(tmp);
|
||||
kind = NULL;
|
||||
}
|
||||
else {
|
||||
int res;
|
||||
res = obj2ast_string(tmp, &kind, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
}
|
||||
*out = Constant(value, kind, lineno, col_offset, end_lineno,
|
||||
end_col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
|
|
53
Python/ast.c
53
Python/ast.c
|
@ -2313,13 +2313,13 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
size_t len = strlen(s);
|
||||
if (len >= 4 && len <= 5) {
|
||||
if (!strcmp(s, "None"))
|
||||
return Constant(Py_None, LINENO(n), n->n_col_offset,
|
||||
return Constant(Py_None, NULL, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
if (!strcmp(s, "True"))
|
||||
return Constant(Py_True, LINENO(n), n->n_col_offset,
|
||||
return Constant(Py_True, NULL, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
if (!strcmp(s, "False"))
|
||||
return Constant(Py_False, LINENO(n), n->n_col_offset,
|
||||
return Constant(Py_False, NULL, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
}
|
||||
name = new_identifier(s, c);
|
||||
|
@ -2374,11 +2374,11 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
Py_DECREF(pynum);
|
||||
return NULL;
|
||||
}
|
||||
return Constant(pynum, LINENO(n), n->n_col_offset,
|
||||
return Constant(pynum, NULL, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
}
|
||||
case ELLIPSIS: /* Ellipsis */
|
||||
return Constant(Py_Ellipsis, LINENO(n), n->n_col_offset,
|
||||
return Constant(Py_Ellipsis, NULL, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
case LPAR: /* some parenthesized expressions */
|
||||
ch = CHILD(n, 1);
|
||||
|
@ -5388,18 +5388,57 @@ FstringParser_Dealloc(FstringParser *state)
|
|||
ExprList_Dealloc(&state->expr_list);
|
||||
}
|
||||
|
||||
/* Constants for the following */
|
||||
static PyObject *u_kind;
|
||||
|
||||
/* Compute 'kind' field for string Constant (either 'u' or None) */
|
||||
static PyObject *
|
||||
make_kind(struct compiling *c, const node *n)
|
||||
{
|
||||
char *s = NULL;
|
||||
PyObject *kind = NULL;
|
||||
|
||||
/* Find the first string literal, if any */
|
||||
while (TYPE(n) != STRING) {
|
||||
if (NCH(n) == 0)
|
||||
return NULL;
|
||||
n = CHILD(n, 0);
|
||||
}
|
||||
REQ(n, STRING);
|
||||
|
||||
/* If it starts with 'u', return a PyUnicode "u" string */
|
||||
s = STR(n);
|
||||
if (s && *s == 'u') {
|
||||
if (!u_kind) {
|
||||
u_kind = PyUnicode_InternFromString("u");
|
||||
if (!u_kind)
|
||||
return NULL;
|
||||
}
|
||||
kind = u_kind;
|
||||
if (PyArena_AddPyObject(c->c_arena, kind) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(kind);
|
||||
}
|
||||
return kind;
|
||||
}
|
||||
|
||||
/* Make a Constant node, but decref the PyUnicode object being added. */
|
||||
static expr_ty
|
||||
make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
|
||||
{
|
||||
PyObject *s = *str;
|
||||
PyObject *kind = NULL;
|
||||
*str = NULL;
|
||||
assert(PyUnicode_CheckExact(s));
|
||||
if (PyArena_AddPyObject(c->c_arena, s) < 0) {
|
||||
Py_DECREF(s);
|
||||
return NULL;
|
||||
}
|
||||
return Constant(s, LINENO(n), n->n_col_offset,
|
||||
kind = make_kind(c, n);
|
||||
if (kind == NULL && PyErr_Occurred())
|
||||
return NULL;
|
||||
return Constant(s, kind, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
|
@ -5774,7 +5813,7 @@ parsestrplus(struct compiling *c, const node *n)
|
|||
/* Just return the bytes object and we're done. */
|
||||
if (PyArena_AddPyObject(c->c_arena, bytes_str) < 0)
|
||||
goto error;
|
||||
return Constant(bytes_str, LINENO(n), n->n_col_offset,
|
||||
return Constant(bytes_str, NULL, LINENO(n), n->n_col_offset,
|
||||
n->n_end_lineno, n->n_end_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue