Skip to content

Commit 1fc24f4

Browse files
committed
Change format of co_annotations to single tuple of string
1 parent 5e03c3e commit 1fc24f4

File tree

6 files changed

+57
-37
lines changed

6 files changed

+57
-37
lines changed

Include/cpython/code.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct PyCodeObject {
2727
PyObject *co_code; /* instruction opcodes */
2828
PyObject *co_consts; /* list (constants used) */
2929
PyObject *co_names; /* list of strings (names used) */
30-
PyObject *co_annotations; /* tuple of pairs (annotations name and value) */
30+
PyObject *co_annotations; /* tuple of strings (annotations names and values) */
3131
PyObject *co_varnames; /* tuple of strings (local variable names) */
3232
PyObject *co_freevars; /* tuple of strings (free variable names) */
3333
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Add ``co_annotations`` field to ``PyCodeObject`` in order to compute
2-
all annotations at compilation time. Patch provided by Yurii Karabas.
2+
annotations at compilation time. Patch provided by Yurii Karabas.

Objects/codeobject.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ PyCode_NewWithAnnotations(int argcount, int posonlyargcount, int kwonlyargcount,
137137
cellvars == NULL || !PyTuple_Check(cellvars) ||
138138
name == NULL || !PyUnicode_Check(name) ||
139139
filename == NULL || !PyUnicode_Check(filename) ||
140-
linetable == NULL || !PyBytes_Check(linetable)) {
140+
linetable == NULL || !PyBytes_Check(linetable) ||
141+
annotations == NULL || !(annotations == Py_None || PyTuple_Check(annotations))) {
141142
PyErr_BadInternalCall();
142143
return NULL;
143144
}
@@ -165,7 +166,7 @@ PyCode_NewWithAnnotations(int argcount, int posonlyargcount, int kwonlyargcount,
165166
if (intern_string_constants(consts, NULL) < 0) {
166167
return NULL;
167168
}
168-
if (annotations != Py_None && intern_string_constants(annotations, NULL) < 0) {
169+
if (annotations != Py_None && intern_strings(annotations) < 0) {
169170
return NULL;
170171
}
171172

@@ -231,6 +232,13 @@ PyCode_NewWithAnnotations(int argcount, int posonlyargcount, int kwonlyargcount,
231232
cell2arg = NULL;
232233
}
233234
}
235+
236+
/* Check if annotation len is even */
237+
if (annotations != Py_None && PyTuple_GET_SIZE(annotations) % 2){
238+
PyErr_SetString(PyExc_ValueError, "code: annotations len is odd");
239+
return NULL;
240+
}
241+
234242
co = PyObject_New(PyCodeObject, &PyCode_Type);
235243
if (co == NULL) {
236244
if (cell2arg)
@@ -388,7 +396,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
388396
funcname_ob, /* name */
389397
firstlineno, /* firstlineno */
390398
emptystring, /* linetable */
391-
nulltuple /* annotations */
399+
Py_None /* annotations */
392400
);
393401

394402
failed:
@@ -580,6 +588,7 @@ code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount,
580588
PyObject *ourvarnames = NULL;
581589
PyObject *ourfreevars = NULL;
582590
PyObject *ourcellvars = NULL;
591+
PyObject *ourannotations = NULL;
583592

584593
if (PySys_Audit("code.__new__", "OOOiiiiii",
585594
code, filename, name, argcount, posonlyargcount,
@@ -632,23 +641,27 @@ code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount,
632641
ourcellvars = PyTuple_New(0);
633642
if (ourcellvars == NULL)
634643
goto cleanup;
635-
if (annotations == NULL)
636-
goto cleanup;
637644
if (annotations && annotations != Py_None && !PyTuple_Check(annotations)) {
638645
PyErr_SetString(
639646
PyExc_ValueError,
640647
"code: annotations must be tuple or None");
641648
goto cleanup;
642649
}
643-
650+
if (annotations && annotations != Py_None)
651+
ourannotations = validate_and_copy_tuple(annotations);
652+
else
653+
ourannotations = Py_None;
654+
if (ourannotations == NULL)
655+
goto cleanup;
644656

645657
co = (PyObject *)PyCode_NewWithAnnotations(argcount, posonlyargcount,
646658
kwonlyargcount,
647659
nlocals, stacksize, flags,
648660
code, consts, ournames,
649661
ourvarnames, ourfreevars,
650662
ourcellvars, filename,
651-
name, firstlineno, linetable, annotations);
663+
name, firstlineno, linetable,
664+
ourannotations);
652665
cleanup:
653666
Py_XDECREF(ournames);
654667
Py_XDECREF(ourvarnames);

Objects/funcobject.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,22 @@ func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored))
425425
return NULL;
426426

427427
PyObject *annotations = ((PyCodeObject*) op->func_code )->co_annotations;
428-
if (annotations != Py_None && PyDict_MergeFromSeq2(op->func_annotations, annotations, 1))
429-
return NULL;
428+
if (annotations != Py_None) {
429+
assert(PyTuple_Size(annotations) % 2 == 0);
430+
431+
Py_ssize_t i;
432+
int err;
433+
for (i = 0; i < PyTuple_Size(annotations); i += 2) {
434+
err = PyDict_SetItem(op->func_annotations,
435+
PyTuple_GET_ITEM(annotations, i),
436+
PyTuple_GET_ITEM(annotations, i + 1));
437+
438+
if (err < 0) {
439+
Py_DECREF(op->func_annotations);
440+
return NULL;
441+
}
442+
}
443+
}
430444
}
431445
Py_INCREF(op->func_annotations);
432446
return op->func_annotations;

Python/ceval.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,20 +3059,25 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
30593059
Py_DECREF(ann_dict);
30603060
}
30613061
}
3062-
if (ann_dict && f->f_code->co_annotations != Py_None) {
3063-
if (PyDict_CheckExact(ann_dict)) {
3064-
if (PyDict_MergeFromSeq2(ann_dict, f->f_code->co_annotations, 1))
3065-
goto error;
3066-
} else {
3067-
Py_ssize_t i;
3068-
PyObject *annotations = f->f_code->co_annotations;
3062+
if (ann_dict != NULL && f->f_code->co_annotations != Py_None) {
3063+
PyObject* annotations = f->f_code->co_annotations;
3064+
int (*set_item)(PyObject *, PyObject *, PyObject *);
30693065

3070-
for (i = 0; i < PyTuple_Size(annotations); i++) {
3071-
PyObject* pair = PyTuple_GET_ITEM(annotations, i);
3066+
if (PyDict_CheckExact(ann_dict))
3067+
set_item = &PyDict_SetItem;
3068+
else
3069+
set_item = &PyObject_SetItem;
30723070

3073-
if (PyObject_SetItem(ann_dict, PyTuple_GET_ITEM(pair, 0), PyTuple_GET_ITEM(pair, 1)))
3074-
goto error;
3075-
}
3071+
assert(PyTuple_Size(annotations) % 2 == 0);
3072+
3073+
Py_ssize_t i;
3074+
for (i = 0; i < PyTuple_Size(annotations); i += 2) {
3075+
err = set_item(ann_dict,
3076+
PyTuple_GET_ITEM(annotations, i),
3077+
PyTuple_GET_ITEM(annotations, i + 1));
3078+
3079+
if (err < 0)
3080+
goto error;
30763081
}
30773082
}
30783083
DISPATCH();

Python/compile.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,37 +2029,26 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_arg_seq *kwonlyargs,
20292029
return 0;
20302030
}
20312031

2032-
static int
2033-
compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
2034-
{
2035-
ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation));
2036-
return 1;
2037-
}
2038-
20392032
static int
20402033
compiler_add_annotation(struct compiler *c, PyObject* mangled,
20412034
expr_ty annotation, PyObject *annotations) {
2042-
PyObject *pair;
20432035
PyObject *value;
20442036

20452037
value = _PyAST_ExprAsUnicode(annotation);
20462038
if (value == NULL)
20472039
return 0;
20482040

2049-
pair = PyTuple_Pack(2, mangled, value);
2050-
if (pair == NULL) {
2041+
if (PyList_Append(annotations, mangled) < 0) {
20512042
Py_DECREF(value);
20522043
return 0;
20532044
}
20542045

2055-
if (PyList_Append(annotations, pair) < 0) {
2046+
if (PyList_Append(annotations, value) < 0) {
20562047
Py_DECREF(value);
2057-
Py_DECREF(pair);
20582048
return 0;
20592049
}
20602050

20612051
Py_DECREF(value);
2062-
Py_DECREF(pair);
20632052
return 1;
20642053
}
20652054

@@ -2246,7 +2235,6 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
22462235
asdl_expr_seq* decos;
22472236
asdl_stmt_seq *body;
22482237
Py_ssize_t i, funcflags;
2249-
int annotations;
22502238
int scope_type;
22512239
int firstlineno;
22522240

0 commit comments

Comments
 (0)