Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 26eedbc

Browse files
committed
Refactor implementation with copy and replacement
1 parent 7abaf64 commit 26eedbc

File tree

1 file changed

+18
-49
lines changed

1 file changed

+18
-49
lines changed

Objects/structseq.c

Lines changed: 18 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,7 @@ structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
370370
static PyObject *
371371
structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs)
372372
{
373-
PyObject *tup = NULL;
374-
PyObject *dict = NULL;
375-
PyObject *result;
373+
PyStructSequence *result = NULL;
376374
Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields, i;
377375

378376
if (!_PyArg_NoPositional("__replace__", args)) {
@@ -396,72 +394,43 @@ structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs)
396394
return NULL;
397395
}
398396

399-
tup = _PyTuple_FromArray(self->ob_item, n_visible_fields);
400-
if (!tup) {
401-
goto error;
397+
// Create an identical instance.
398+
result = (PyStructSequence *)PyStructSequence_New(Py_TYPE(self));
399+
if (result == NULL) {
400+
return NULL;
402401
}
403-
dict = PyDict_New();
404-
if (!dict) {
405-
goto error;
402+
for (i = 0; i < n_fields; ++i) {
403+
result->ob_item[i] = Py_NewRef(self->ob_item[i]);
406404
}
407405

408406
if (kwargs != NULL) {
409-
for (i = 0; i < n_visible_fields; i++) {
410-
const char *name = Py_TYPE(self)->tp_members[i].name;
411-
PyObject *key = PyUnicode_FromString(name);
407+
// We do not support types with unnamed fields, so we can iterate over
408+
// i >= n_visible_fields case without slicing with (i - n_unnamed_fields).
409+
for (i = 0; i < n_fields; i++) {
410+
PyObject *key = PyUnicode_FromString(Py_TYPE(self)->tp_members[i].name);
412411
if (!key) {
413-
goto error;
412+
return NULL;
414413
}
415-
PyObject *ob = _PyDict_Pop(kwargs, key, self->ob_item[i]);
414+
PyObject *ob = _PyDict_Pop(kwargs, key, self->ob_item[i]); // borrowed
416415
Py_DECREF(key);
417416
if (!ob) {
418-
goto error;
419-
}
420-
PyTuple_SetItem(tup, i, ob);
421-
}
422-
for (i = n_visible_fields; i < n_fields; i++) {
423-
const char *name = Py_TYPE(self)->tp_members[i - n_unnamed_fields].name;
424-
PyObject *key = PyUnicode_FromString(name);
425-
if (!key) {
426-
goto error;
427-
}
428-
PyObject *ob = _PyDict_Pop(kwargs, key, self->ob_item[i]);
429-
if (!ob || PyDict_SetItem(dict, key, ob) < 0) {
430-
Py_DECREF(key);
431-
goto error;
417+
return NULL;
432418
}
433-
Py_DECREF(key);
419+
Py_DECREF(result->ob_item[i]);
420+
result->ob_item[i] = ob;
434421
}
422+
// Check if there are any unexpected fields.
435423
if (PyDict_Size(kwargs) > 0) {
436424
PyObject *names = PyDict_Keys(kwargs);
437425
if (names) {
438426
PyErr_Format(PyExc_TypeError, "Got unexpected field name(s): %R", names);
439427
Py_DECREF(names);
440428
}
441-
goto error;
442-
}
443-
}
444-
else
445-
{
446-
for (i = n_visible_fields; i < n_fields; i++) {
447-
const char *name = Py_TYPE(self)->tp_members[i - n_unnamed_fields].name;
448-
if (PyDict_SetItemString(dict, name, self->ob_item[i]) < 0) {
449-
goto error;
450-
}
429+
return NULL;
451430
}
452431
}
453432

454-
result = structseq_new_impl(Py_TYPE(self), tup, dict);
455-
456-
Py_DECREF(tup);
457-
Py_DECREF(dict);
458-
459433
return result;
460-
461-
error:
462-
Py_XDECREF(tup);
463-
Py_XDECREF(dict);
464-
return NULL;
465434
}
466435

467436
static PyMethodDef structseq_methods[] = {

0 commit comments

Comments
 (0)