8000 Keep field defaults inside of _field_defaults and recreate the mutabl… · python/cpython@5d033a1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5d033a1

Browse files
committed
Keep field defaults inside of _field_defaults and recreate the mutable ones
1 parent 43fe55a commit 5d033a1

File tree

4 files changed

+278
-307
lines changed

4 files changed

+278
-307
lines changed

Lib/ast.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,6 @@ def _convert(node):
102102
return _convert_signed_num(node)
103103
return _convert(node_or_string)
104104

105-
@lru_cache
106-
def _field_defaults(node_type):
107-
field_defaults = {}
108-
for field, default in zip(node_type._fields, node_type._field_defaults):
109-
if default == "?":
110-
field_defaults[field] = None
111-
elif default == "*":
112-
field_defaults[field] = []
113-
else:
114-
field_defaults[field] = Ellipsis # sentinel
115-
return field_defaults
116-
117105

118106
def dump(node, annotate_fields=True, include_attributes=False, *, indent=None, omit_defaults=True):
119107
"""
@@ -142,14 +130,18 @@ def _format(node, level=0):
142130
args = []
143131
allsimple = True
144132
keywords = annotate_fields
145-
field_defaults = _field_defaults(cls)
133+
field_defaults = cls._field_defaults
146134
for name in node._fields:
147135
try:
148136
value = getattr(node, name)
149137
except AttributeError:
150138
keywords = True
151139
continue
152-
if omit_defaults and field_defaults[name] == value:
140+
if (
141+
omit_defaults
142+
and name in field_defaults
143+
and field_defaults[name] == value
144+
):
153145
keywords = True
154146
continue
155147
value, simple = _format(value, level)

Lib/test/test_ast.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ def test_field_attr_existence(self):
354354
def test_arguments(self):
355355
x = ast.FunctionDef()
356356
self.assertEqual(x._fields, ('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment'))
357-
self.assertEqual(x._field_defaults, ('', '', '*', '*', '?', '?'))
357+
self.assertEqual(x._field_defaults, {'body': [], 'decorator_list': [], 'returns': None, 'type_comment': None})
358358

359359
with self.assertRaises(AttributeError):
360360
x.name

Parser/asdl_c.py

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,8 @@ def visitProduct(self, prod, name):
614614
for f in prod.fields:
615615
self.emit('"%s",' % f.name, 1)
616616
self.emit("};", 0)
617-
self.emit("static const char * const %s_field_defaults[]={" % name, 0)
618-
for f in prod.fields:
619-
self.emit('"%s",' % f.extra, 1)
617+
self.emit("static const char %s_field_defaults[]={" % name, 0)
618+
self.emit_field_defaults(prod.fields)
620619
self.emit("};", 0)
621620

622621
def visitSum(self, sum, name):
@@ -645,11 +644,17 @@ def visitConstructor(self, cons, name):
645644
for t in cons.fields:
646645
self.emit('"%s",' % t.name, 1)
647646
self.emit("};",0)
648-
self.emit("static const char * const %s_field_defaults[]={" % cons.name, 0)
649-
for t in cons.fields:
650-
self.emit('"%s",' % t.extra, 1)
647+
self.emit("static const char %s_field_defaults[]={" % cons.name, 0)
648+
self.emit_field_defaults(cons.fields)
651649
self.emit("};",0)
652650

651+
def emit_field_defaults(self, fields):
652+
for field in fields:
653+
if field.extra:
654+
self.emit("%r," % field.extra, 1)
655+
else:
656+
self.emit("' ',", 1)
657+
653658

654659
class PyTypesVisitor(PickleVisitor):
655660

@@ -688,23 +693,6 @@ def visitModule(self, mod):
688693
return 0;
689694
}
690695
691-
static inline PyObject *
692-
find_field_default(PyObject *field_default)
693-
{
694-
if (PyUnicode_GET_LENGTH(field_default) < 1) {
695-
return NULL;
696-
}
697-
switch (PyUnicode_READ_CHAR(field_default, 0)){
698-
case '?':
699-
Py_INCREF(Py_None);
700-
return Py_None;
701-
case '*':
702-
return PyList_New(0);
703-
default:
704-
return NULL;
705-
}
706-
}
707-
708696
static int
709697
ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
710698
{
@@ -752,25 +740,21 @@ def visitModule(self, mod):
752740
goto cleanup;
753741
}
754742
}
755-
PyObject *field, *raw_field_default, *field_default;
743+
PyObject *field, *field_default;
756744
for (i = 0; i < numfields; i++) {
757745
field = PySequence_GetItem(fields, i);
758746
if (!field) {
759747
res = -1;
760748
goto cleanup;
761749
}
762750
int attr_present = PyObject_HasAttr(self, field);
751+
field_default = PyDict_GetItem(field_defaults, field);
763752
Py_DECREF(field);
764-
if (!attr_present) {
765-
raw_field_default = PySequence_GetItem(field_defaults, i);
766-
if (!raw_field_default) {
767-
res = -1;
768-
goto cleanup;
769-
}
770-
field_default = find_field_default(raw_field_default);
771-
Py_DECREF(raw_field_default);
772-
if (!field_default) {
773-
continue;
753+
if (!attr_present && field_default) {
754+
if (PyList_Check(field_default)) {
755+
field_default = PyList_New(0);
756+
} else {
757+
Py_INCREF(field_default);
774758
}
775759
res = PyObject_SetAttr(self, field, field_default);
776760
Py_DECREF(field_default);
@@ -843,7 +827,7 @@ def visitModule(self, mod):
843827
const char *type,
844828
PyObject* base,
845829
const char* const* fields,
846-
const char* const* field_defaults,
830+
const char* field_defaults,
847831
Py_ssize_t num_fields,
848832
const char *doc
849833
)
@@ -856,21 +840,29 @@ def visitModule(self, mod):
856840
if (!fnames) {
857841
goto exit;
858842
}
859-
fdefaults = PyTuple_New(num_fields);
843+
fdefaults = PyDict_New();
860844
if (!fdefaults) {
861845
goto exit;
862846
}
847+
PyObject *field, *field_default;
863848
for (i = 0; i < num_fields; i++) {
864-
PyObject *field = PyUnicode_InternFromString(fields[i]);
849+
field = PyUnicode_InternFromString(fields[i]);
865850
if (!field) {
866851
goto exit;
867852
}
868853
PyTuple_SET_ITEM(fnames, i, field);
869-
PyObject *field_default = PyUnicode_InternFromString(field_defaults[i]);
870-
if (!field_default) {
871-
goto exit;
854+
if (field_defaults[i] == '?') {
855+
field_default = Py_None;
856+
Py_INCREF(field_default);
857+
} else if (field_defaults[i] == '*') {
858+
field_default = PyList_New(0);
859+
if (!field_default) {
860+
goto exit;
861+
}
862+
} else {
863+
continue;
872864
}
873-
PyTuple_SET_ITEM(fdefaults, i, field_default);
865+
PyDict_SetItem(fdefaults, field, field_default);
874866
}
875867
result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){OOOOOOOs}",
876868
type, base,

0 commit comments

Comments
 (0)
0