@@ -20,6 +20,11 @@ static PyObject * record_new_items_iter(PyObject *);
2020static ApgRecordObject * free_list [ApgRecord_MAXSAVESIZE ];
2121static int numfree [ApgRecord_MAXSAVESIZE ];
2222
23+ static PyObject * record_reconstruct_obj ;
24+ static PyObject * record_desc_reconstruct_obj ;
25+
26+ static PyMethodDef record_desc_methods [];
27+
2328static size_t MAX_RECORD_SIZE = (
2429 ((size_t )PY_SSIZE_T_MAX - sizeof (ApgRecordObject ) - sizeof (PyObject * ))
2530 / sizeof (PyObject * )
@@ -575,14 +580,14 @@ record_repr(ApgRecordObject *v)
575580
576581
577582static PyObject *
578- record_values (PyObject * o , PyObject * args )
583+ record_values (PyObject * o , PyObject * Py_UNUSED ( unused ) )
579584{
580585 return record_iter (o );
581586}
582587
583588
584589static PyObject *
585- record_keys (PyObject * o , PyObject * args )
590+ record_keys (PyObject * o , PyObject * Py_UNUSED ( unused ) )
586591{
587592 if (!ApgRecord_Check (o )) {
588593 PyErr_BadInternalCall ();
@@ -594,7 +599,7 @@ record_keys(PyObject *o, PyObject *args)
594599
595600
596601static PyObject *
597- record_items (PyObject * o , PyObject * args )
602+ record_items (PyObject * o , PyObject * Py_UNUSED ( unused ) )
598603{
599604 if (!ApgRecord_Check (o )) {
600605 PyErr_BadInternalCall ();
@@ -657,12 +662,71 @@ static PyMappingMethods record_as_mapping = {
657662 0 /* mp_ass_subscript */
658663};
659664
665+ static PyMethodDef record_methods [];
666+
667+ static PyObject *
668+ record_reduce (ApgRecordObject * o , PyObject * Py_UNUSED (unused ))
669+ {
670+ PyObject * value = PyTuple_New (2 );
671+ if (value == NULL ) {
672+ return NULL ;
673+ }
674+ Py_ssize_t len = Py_SIZE (o );
675+ PyObject * state = PyTuple_New (1 + len );
676+ if (state == NULL ) {
677+ Py_DECREF (value );
678+ return NULL ;
679+ }
680+ PyTuple_SET_ITEM (value , 0 , record_reconstruct_obj );
681+ Py_INCREF (record_reconstruct_obj );
682+ PyTuple_SET_ITEM (value , 1 , state );
683+ PyTuple_SET_ITEM (state , 0 , (PyObject * )o -> desc );
684+ Py_INCREF (o -> desc );
685+ for (Py_ssize_t i = 0 ; i < len ; i ++ ) {
686+ PyObject * item = ApgRecord_GET_ITEM (o , i );
687+ PyTuple_SET_ITEM (state , i + 1 , item );
688+ Py_INCREF (item );
689+ }
690+ return value ;
691+ }
692+
693+ static PyObject *
694+ record_reconstruct (PyObject * Py_UNUSED (unused ), PyObject * args )
695+ {
696+ if (!PyTuple_CheckExact (args )) {
697+ return NULL ;
698+ }
699+ Py_ssize_t len = PyTuple_GET_SIZE (args );
700+ if (len < 2 ) {
701+ return NULL ;
702+ }
703+ len -- ;
704+ ApgRecordDescObject * desc = (ApgRecordDescObject * )PyTuple_GET_ITEM (args , 0 );
705+ if (!ApgRecordDesc_CheckExact (desc )) {
706+ return NULL ;
707+ }
708+ if (PyObject_Length (desc -> mapping ) != len ) {
709+ return NULL ;
710+ }
711+ PyObject * record = ApgRecord_New (& ApgRecord_Type , (PyObject * )desc , len );
712+ if (record == NULL ) {
713+ return NULL ;
714+ }
715+ for (Py_ssize_t i = 0 ; i < len ; i ++ ) {
716+ PyObject * item = PyTuple_GET_ITEM (args , i + 1 );
717+ ApgRecord_SET_ITEM (record , i , item );
718+ Py_INCREF (item );
719+ }
720+ return record ;
721+ }
660722
661723static PyMethodDef record_methods [] = {
662724 {"values" , (PyCFunction )record_values , METH_NOARGS },
663725 {"keys" , (PyCFunction )record_keys , METH_NOARGS },
664726 {"items" , (PyCFunction )record_items , METH_NOARGS },
665727 {"get" , (PyCFunction )record_get , METH_VARARGS },
728+ {"__reduce__" , (PyCFunction )record_reduce , METH_NOARGS },
729+ {"__reconstruct__" , (PyCFunction )record_reconstruct , METH_VARARGS | METH_STATIC },
666730 {NULL , NULL } /* sentinel */
667731};
668732
@@ -942,7 +1006,7 @@ record_new_items_iter(PyObject *seq)
9421006}
9431007
9441008
945- PyTypeObject *
1009+ PyObject *
9461010ApgRecord_InitTypes (void )
9471011{
9481012 if (PyType_Ready (& ApgRecord_Type ) < 0 ) {
@@ -961,7 +1025,22 @@ ApgRecord_InitTypes(void)
9611025 return NULL ;
9621026 }
9631027
964- return & ApgRecord_Type ;
1028+ record_reconstruct_obj = PyCFunction_New (
1029+ & record_methods [5 ], (PyObject * )& ApgRecord_Type
1030+ );
1031+ record_desc_reconstruct_obj = PyCFunction_New (
1032+ & record_desc_methods [1 ], (PyObject * )& ApgRecordDesc_Type
1033+ );
1034+
1035+ PyObject * types = PyTuple_New (2 );
1036+ if (types == NULL ) {
1037+ return NULL ;
1038+ }
1039+ PyTuple_SET_ITEM (types , 0 , (PyObject * )& ApgRecord_Type );
1040+ Py_INCREF (& ApgRecord_Type );
1041+ PyTuple_SET_ITEM (types , 1 , (PyObject * )& ApgRecordDesc_Type );
1042+ Py_INCREF (& ApgRecordDesc_Type );
1043+ return types ;
9651044}
9661045
9671046
@@ -987,15 +1066,54 @@ record_desc_traverse(ApgRecordDescObject *o, visitproc visit, void *arg)
9871066}
9881067
9891068
1069+ static PyObject * record_desc_reduce (ApgRecordDescObject * o , PyObject * Py_UNUSED (unused ))
1070+ {
1071+ PyObject * value = PyTuple_New (2 );
1072+ if (value == NULL ) {
1073+ return NULL ;
1074+ }
1075+ PyObject * state = PyTuple_New (2 );
1076+ if (state == NULL ) {
1077+ Py_DECREF (value );
1078+ return NULL ;
1079+ }
1080+ PyTuple_SET_ITEM (value , 0 , record_desc_reconstruct_obj );
1081+ Py_INCREF (record_desc_reconstruct_obj );
1082+ PyTuple_SET_ITEM (value , 1 , state );
1083+ PyTuple_SET_ITEM (state , 0 , o -> mapping );
1084+ Py_INCREF (o -> mapping );
1085+ PyTuple_SET_ITEM (state , 1 , o -> keys );
1086+ Py_INCREF (o -> keys );
1087+ return value ;
1088+ }
1089+
1090+
1091+ static PyObject * record_desc_reconstruct (PyObject * Py_UNUSED (unused ), PyObject * args )
1092+ {
1093+ if (PyTuple_GET_SIZE (args ) != 2 ) {
1094+ return NULL ;
1095+ }
1096+ return ApgRecordDesc_New (PyTuple_GET_ITEM (args , 0 ), PyTuple_GET_ITEM (args , 1 ));
1097+ }
1098+
1099+
1100+ static PyMethodDef record_desc_methods [] = {
1101+ {"__reduce__" , (PyCFunction )record_desc_reduce , METH_NOARGS },
1102+ {"__reconstruct__" , (PyCFunction )record_desc_reconstruct , METH_VARARGS | METH_STATIC },
1103+ {NULL , NULL } /* sentinel */
1104+ };
1105+
1106+
9901107PyTypeObject ApgRecordDesc_Type = {
9911108 PyVarObject_HEAD_INIT (NULL , 0 )
992- .tp_name = "RecordDescriptor" ,
1109+ .tp_name = "asyncpg.protocol.protocol. RecordDescriptor" ,
9931110 .tp_basicsize = sizeof (ApgRecordDescObject ),
9941111 .tp_dealloc = (destructor )record_desc_dealloc ,
9951112 .tp_getattro = PyObject_GenericGetAttr ,
9961113 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC ,
9971114 .tp_traverse = (traverseproc )record_desc_traverse ,
9981115 .tp_iter = PyObject_SelfIter ,
1116+ .tp_methods = record_desc_methods ,
9991117};
10001118
10011119
0 commit comments