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:
Guido van Rossum 2019-03-13 13:00:46 -07:00 committed by Miss Islington (bot)
parent 8b5bdda5b4
commit 10f8ce6688
6 changed files with 142 additions and 60 deletions

32
Python/Python-ast.c generated
View file

@ -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;
}

View file

@ -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);
}