@@ -656,12 +656,68 @@ static int frozendict_update_common(PyObject* self,
656656 return result ;
657657}
658658
659+ /* Forward */
660+ static PyObject * frozendictkeys_new (PyObject * , PyObject * );
661+ static PyObject * frozendictitems_new (PyObject * , PyObject * );
662+ static PyObject * frozendictvalues_new (PyObject * , PyObject * );
663+
664+ #define MINUSONE_HASH ((Py_hash_t) -1)
665+
666+ static Py_hash_t frozendict_hash (PyObject * self ) {
667+ PyFrozenDictObject * frozen_self = (PyFrozenDictObject * ) self ;
668+ Py_hash_t hash ;
669+
670+ if (frozen_self -> ma_hash_calculated ) {
671+ hash = frozen_self -> ma_hash ;
672+
673+ if (hash == MINUSONE_HASH ) {
674+ PyErr_SetObject (PyExc_TypeError , Py_None );
675+ }
676+ }
677+ else {
678+ PyObject * frozen_items_tmp = frozendictitems_new (self , NULL );
679+ int save_hash = 1 ;
680+
681+ if (frozen_items_tmp == NULL ) {
682+ hash = MINUSONE_HASH ;
683+ save_hash = 0 ;
684+ }
685+ else {
686+ PyObject * frozen_items = PyFrozenSet_New (frozen_items_tmp );
687+
688+ if (frozen_items == NULL ) {
689+ PyObject * err = PyErr_Occurred ();
690+
691+ if (err == NULL || ! PyErr_GivenExceptionMatches (err , PyExc_TypeError )) {
692+ save_hash = 0 ;
693+ }
694+
695+ hash = MINUSONE_HASH ;
696+ }
697+ else {
698+ hash = PyFrozenSet_Type .tp_hash (frozen_items );
699+ }
700+ }
701+
702+ if (save_hash ) {
703+ frozen_self -> ma_hash = hash ;
704+ frozen_self -> ma_hash_calculated = 1 ;
705+ }
706+ }
707+
708+ return hash ;
709+ }
710+
659711static PyObject * frozendict_copy (PyObject * o , PyObject * Py_UNUSED (ignored )) {
660712 if (PyAnyFrozenDict_CheckExact (o )) {
661713 Py_INCREF (o );
662714 return o ;
663715 }
664716
717+ if (! PyAnyFrozenDict_Check (o )) {
718+ Py_RETURN_NOTIMPLEMENTED ;
719+ }
720+
665721 PyObject * args = PyTuple_New (1 );
666722
667723 if (args == NULL ) {
@@ -676,6 +732,110 @@ static PyObject* frozendict_copy(PyObject* o, PyObject* Py_UNUSED(ignored)) {
676732 return PyObject_Call ((PyObject * ) type , args , NULL );
677733}
678734
735+ PyObject * frozendict_deepcopy (PyObject * self , PyObject * memo ) {
736+ if (PyAnyFrozenDict_CheckExact (self )) {
737+ frozendict_hash (self );
738+
739+ if (PyErr_Occurred ()) {
740+ PyErr_Clear ();
741+ }
742+ else {
743+ Py_INCREF (self );
744+ return self ;
745+ }
746+ }
747+
748+ if (! PyAnyFrozenDict_Check (self )) {
749+ Py_RETURN_NOTIMPLEMENTED ;
750+ }
751+
752+ PyObject * d = PyDict_New ();
753+
754+ if (d == NULL ) {
755+ return NULL ;
756+ }
757+
758+ PyObject * copy_module_name = NULL ;
759+ PyObject * copy_module = NULL ;
760+ PyObject * deepcopy_fun = NULL ;
761+ PyObject * deep_args = NULL ;
762+ PyObject * deep_d = NULL ;
763+ PyObject * args = NULL ;
764+ PyObject * res = NULL ;
765+ int decref_d = 1 ;
766+ int decref_deep_d = 1 ;
767+
768+ if (PyDict_Merge (d , self , 1 )) {
769+ goto end ;
770+ }
771+
772+ copy_module_name = PyUnicode_FromString ("copy" );
773+
774+ if (copy_module_name == NULL ) {
775+ goto end ;
776+ }
777+
778+ copy_module = PyImport_Import (copy_module_name );
779+
780+ if (copy_module == NULL ) {
781+ goto end ;
782+ }
783+
784+ deepcopy_fun = PyObject_GetAttrString (copy_module , "deepcopy" );
785+
786+ if (deepcopy_fun == NULL ) {
787+ goto end ;
788+ }
789+
790+ deep_args = PyTuple_New (2 );
791+
792+ if (deep_args == NULL ) {
793+ goto end ;
794+ }
795+
796+ PyTuple_SET_ITEM (deep_args , 0 , d );
797+ decref_d = 0 ;
798+
799+ Py_INCREF (memo );
800+ PyTuple_SET_ITEM (deep_args , 1 , memo );
801+
802+ deep_d = PyObject_CallObject (deepcopy_fun , deep_args );
803+
804+ if (deep_d == NULL ) {
805+ goto end ;
806+ }
807+
808+ args = PyTuple_New (1 );
809+
810+ if (args == NULL ) {
811+ goto end ;
812+ }
813+
814+ PyTuple_SET_ITEM (args , 0 , deep_d );
815+ decref_deep_d = 0 ;
816+
817+ PyTypeObject * type = Py_TYPE (self );
818+
819+ res = PyObject_Call ((PyObject * ) type , args , NULL );
820+
821+ end :
822+ Py_XDECREF (args );
823+ Py_XDECREF (deep_args );
824+ Py_XDECREF (deepcopy_fun );
825+ Py_XDECREF (copy_module );
826+ Py_XDECREF (copy_module_name );
827+
828+ if (decref_d ) {
829+ Py_DECREF (d );
830+ }
831+
832+ if (decref_deep_d ) {
833+ Py_DECREF (deep_d );
834+ }
835+
836+ return res ;
837+ }
838+
679839static int frozendict_equal (PyDictObject * a , PyDictObject * b ) {
680840 if (a == b ) {
681841 return 1 ;
@@ -741,11 +901,6 @@ static Py_ssize_t dict_get_index(PyDictObject *self, PyObject *key) {
741901 return (self -> ma_keys -> dk_lookup ) (self , key , hash , & val , NULL );
742902}
743903
744- /* Forward */
745- static PyObject * frozendictkeys_new (PyObject * , PyObject * );
746- static PyObject * frozendictitems_new (PyObject * , PyObject * );
747- static PyObject * frozendictvalues_new (PyObject * , PyObject * );
748-
749904static PyObject *
750905frozendict_reduce (PyFrozenDictObject * mp , PyObject * Py_UNUSED (ignored ))
751906{
@@ -755,7 +910,10 @@ frozendict_reduce(PyFrozenDictObject* mp, PyObject *Py_UNUSED(ignored))
755910 return NULL ;
756911 }
757912
758- PyDict_Merge (d , (PyObject * )mp , 1 );
913+ if (PyDict_Merge (d , (PyObject * )mp , 1 )) {
914+ Py_DECREF (d );
915+ return NULL ;
916+ }
759917
760918 return Py_BuildValue ("O(N)" , Py_TYPE (mp ), d );
761919}
@@ -946,6 +1104,10 @@ static PyMethodDef frozendict_mapp_methods[] = {
9461104 {"fromkeys" , (PyCFunction )frozendict_fromkeys , METH_VARARGS |METH_CLASS , dict_fromkeys__doc__ },
9471105 {"copy" , (PyCFunction )frozendict_copy , METH_NOARGS ,
9481106 copy__doc__ },
1107+ {"__copy__" , (PyCFunction )frozendict_copy , METH_NOARGS ,
1108+ "Returns a copy of the object." },
1109+ {"__deepcopy__" , (PyCFunction )frozendict_deepcopy , METH_O ,
1110+ "Returns a deepcopy of the object." },
9491111 DICT___REVERSED___METHODDEF
9501112 {"__reduce__" , (PyCFunction )(void (* )(void ))frozendict_reduce , METH_NOARGS ,
9511113 "" },
@@ -980,6 +1142,10 @@ static PyMethodDef coold_mapp_methods[] = {
9801142 {"fromkeys" , (PyCFunction )frozendict_fromkeys , METH_VARARGS |METH_CLASS , dict_fromkeys__doc__ },
9811143 {"copy" , (PyCFunction )frozendict_copy , METH_NOARGS ,
9821144 copy__doc__ },
1145+ {"__copy__" , (PyCFunction )frozendict_copy , METH_NOARGS ,
1146+ "Returns a copy of the object." },
1147+ {"__deepcopy__" , (PyCFunction )frozendict_deepcopy , METH_O ,
1148+ "Returns a deepcopy of the object." },
9831149 DICT___REVERSED___METHODDEF
9841150 {"__reduce__" , (PyCFunction )(void (* )(void ))frozendict_reduce , METH_NOARGS ,
9851151 "" },
@@ -1102,43 +1268,6 @@ static PyObject* frozendict_new(PyTypeObject* type, PyObject* args, PyObject* kw
11021268 return _frozendict_new (type , args , kwds , 1 );
11031269}
11041270
1105- #define MINUSONE_HASH ((Py_hash_t) -1)
1106-
1107- static Py_hash_t frozendict_hash (PyObject * self ) {
1108- PyFrozenDictObject * frozen_self = (PyFrozenDictObject * ) self ;
1109- Py_hash_t hash ;
1110-
1111- if (frozen_self -> ma_hash_calculated ) {
1112- hash = frozen_self -> ma_hash ;
1113-
1114- if (hash == MINUSONE_HASH ) {
1115- PyErr_SetObject (PyExc_TypeError , Py_None );
1116- }
1117- }
1118- else {
1119- PyObject * frozen_items_tmp = frozendictitems_new (self , NULL );
1120-
1121- if (frozen_items_tmp == NULL ) {
1122- hash = MINUSONE_HASH ;
1123- }
1124- else {
1125- PyObject * frozen_items = PyFrozenSet_New (frozen_items_tmp );
1126-
1127- if (frozen_items == NULL ) {
1128- hash = MINUSONE_HASH ;
1129- }
1130- else {
1131- hash = PyFrozenSet_Type .tp_hash (frozen_items );
1132- }
1133- }
1134-
1135- frozen_self -> ma_hash = hash ;
1136- frozen_self -> ma_hash_calculated = 1 ;
1137- }
1138-
1139- return hash ;
1140- }
1141-
11421271static PyObject * frozendict_or (PyObject * self , PyObject * other ) {
11431272 if (! PyAnyFrozenDict_Check (self ) || ! PyAnyDict_Check (other )) {
11441273 Py_RETURN_NOTIMPLEMENTED ;
@@ -1431,6 +1560,7 @@ static PyObject* frozendictiter_iternextitem(dictiterobject* di) {
14311560 assert (key != NULL );
14321561 assert (val != NULL );
14331562 di -> di_pos ++ ;
1563+ di -> len -- ;
14341564 Py_INCREF (key );
14351565 Py_INCREF (val );
14361566
0 commit comments