@@ -370,9 +370,7 @@ structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
370
370
static PyObject *
371
371
structseq_replace (PyStructSequence * self , PyObject * args , PyObject * kwargs )
372
372
{
373
- PyObject * tup = NULL ;
374
- PyObject * dict = NULL ;
375
- PyObject * result ;
373
+ PyStructSequence * result = NULL ;
376
374
Py_ssize_t n_fields , n_visible_fields , n_unnamed_fields , i ;
377
375
378
376
if (!_PyArg_NoPositional ("__replace__" , args )) {
@@ -396,72 +394,43 @@ structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs)
396
394
return NULL ;
397
395
}
398
396
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 ;
402
401
}
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 ]);
406
404
}
407
405
408
406
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 );
412
411
if (!key ) {
413
- goto error ;
412
+ return NULL ;
414
413
}
415
- PyObject * ob = _PyDict_Pop (kwargs , key , self -> ob_item [i ]);
414
+ PyObject * ob = _PyDict_Pop (kwargs , key , self -> ob_item [i ]); // borrowed
416
415
Py_DECREF (key );
417
416
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 ;
432
418
}
433
- Py_DECREF (key );
419
+ Py_DECREF (result -> ob_item [i ]);
420
+ result -> ob_item [i ] = ob ;
434
421
}
422
+ // Check if there are any unexpected fields.
435
423
if (PyDict_Size (kwargs ) > 0 ) {
436
424
PyObject * names = PyDict_Keys (kwargs );
437
425
if (names ) {
438
426
PyErr_Format (PyExc_TypeError , "Got unexpected field name(s): %R" , names );
439
427
Py_DECREF (names );
440
428
}
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 ;
451
430
}
452
431
}
453
432
454
- result = structseq_new_impl (Py_TYPE (self ), tup , dict );
455
-
456
- Py_DECREF (tup );
457
- Py_DECREF (dict );
458
-
459
433
return result ;
460
-
461
- error :
462
- Py_XDECREF (tup );
463
- Py_XDECREF (dict );
464
- return NULL ;
465
434
}
466
435
467
436
static PyMethodDef structseq_methods [] = {
0 commit comments