@@ -62,6 +62,51 @@ static PyTypeObject* PyWindowsPath_Type;
6262static PyTypeObject* PyStructTime_Type;
6363static PyTypeObject* PyUUID_Type;
6464
65+ /* *
66+ * Try to set the key type of the sorted dictionary. It should not already be
67+ * set. The provided argument should not be a null pointer.
68+ *
69+ * @param key_type Key type.
70+ *
71+ * @return `true` if successful, else `false`.
72+ */
73+ bool SortedDictType::try_set_key_type (PyObject* key_type)
74+ {
75+ static PyTypeObject* allowed_key_types[] = {
76+ &PyBool_Type,
77+ &PyBytes_Type,
78+ &PyFloat_Type,
79+ &PyLong_Type,
80+ &PyUnicode_Type,
81+ // The following types are not built-in.
82+ PyDate_Type = import_python_type (" datetime" , " date" ),
83+ PyTimeDelta_Type = import_python_type (" datetime" , " timedelta" ),
84+ PyDecimal_Type = import_python_type (" decimal" , " Decimal" ),
85+ PyFraction_Type = import_python_type (" fractions" , " Fraction" ),
86+ PyIPv4Address_Type = import_python_type (" ipaddress" , " IPv4Address" ),
87+ PyIPv4Interface_Type = import_python_type (" ipaddress" , " IPv4Interface" ),
88+ PyIPv4Network_Type = import_python_type (" ipaddress" , " IPv4Network" ),
89+ PyIPv6Address_Type = import_python_type (" ipaddress" , " IPv6Address" ),
90+ PyIPv6Interface_Type = import_python_type (" ipaddress" , " IPv6Interface" ),
91+ PyIPv6Network_Type = import_python_type (" ipaddress" , " IPv6Network" ),
92+ PyPosixPath_Type = import_python_type (" pathlib" , " PosixPath" ),
93+ PyPurePosixPath_Type = import_python_type (" pathlib" , " PurePosixPath" ),
94+ PyPureWindowsPath_Type = import_python_type (" pathlib" , " PureWindowsPath" ),
95+ PyWindowsPath_Type = import_python_type (" pathlib" , " WindowsPath" ),
96+ PyStructTime_Type = import_python_type (" time" , " struct_time" ),
97+ PyUUID_Type = import_python_type (" uuid" , " UUID" ),
98+ };
99+ for (PyTypeObject* allowed_key_type : allowed_key_types)
100+ {
101+ if (allowed_key_type != nullptr && Py_Is (key_type, reinterpret_cast <PyObject*>(allowed_key_type)))
102+ {
103+ this ->key_type = allowed_key_type;
104+ return true ;
105+ }
106+ }
107+ return false ;
108+ }
109+
65110/* *
66111 * Check whether the given key can be inserted into this sorted dictionary. For
67112 * instance, NaN cannot be compared with other floating-point numbers, so it
@@ -125,8 +170,10 @@ bool SortedDictType::are_key_type_and_key_value_pair_good(PyObject* key, PyObjec
125170 }
126171
127172 // The first key-value pair is being inserted.
128- if (this ->set_key_type (reinterpret_cast <PyObject*>(Py_TYPE (key)), key) == -1 )
173+ PyObject* key_type = reinterpret_cast <PyObject*>(Py_TYPE (key));
174+ if (!this ->try_set_key_type (key_type))
129175 {
176+ PyErr_Format (PyExc_TypeError, " got key %R of unsupported type %R" , key, key_type);
130177 return false ;
131178 }
132179 key_type_set_here = true ;
@@ -637,7 +684,7 @@ PyObject* SortedDictType::get_key_type(void)
637684 return Py_NewRef (this ->key_type ); // 🆕
638685}
639686
640- int SortedDictType::set_key_type (PyObject* key_type, PyObject* key )
687+ int SortedDictType::set_key_type (PyObject* key_type)
641688{
642689 if (key_type == nullptr )
643690 {
@@ -655,51 +702,12 @@ int SortedDictType::set_key_type(PyObject* key_type, PyObject* key)
655702 return -1 ;
656703 }
657704
658- static PyTypeObject* allowed_key_types[] = {
659- &PyBool_Type,
660- &PyBytes_Type,
661- &PyFloat_Type,
662- &PyLong_Type,
663- &PyUnicode_Type,
664- // The following types are not built-in.
665- PyDate_Type = import_python_type (" datetime" , " date" ),
666- PyTimeDelta_Type = import_python_type (" datetime" , " timedelta" ),
667- PyDecimal_Type = import_python_type (" decimal" , " Decimal" ),
668- PyFraction_Type = import_python_type (" fractions" , " Fraction" ),
669- PyIPv4Address_Type = import_python_type (" ipaddress" , " IPv4Address" ),
670- PyIPv4Interface_Type = import_python_type (" ipaddress" , " IPv4Interface" ),
671- PyIPv4Network_Type = import_python_type (" ipaddress" , " IPv4Network" ),
672- PyIPv6Address_Type = import_python_type (" ipaddress" , " IPv6Address" ),
673- PyIPv6Interface_Type = import_python_type (" ipaddress" , " IPv6Interface" ),
674- PyIPv6Network_Type = import_python_type (" ipaddress" , " IPv6Network" ),
675- PyPosixPath_Type = import_python_type (" pathlib" , " PosixPath" ),
676- PyPurePosixPath_Type = import_python_type (" pathlib" , " PurePosixPath" ),
677- PyPureWindowsPath_Type = import_python_type (" pathlib" , " PureWindowsPath" ),
678- PyWindowsPath_Type = import_python_type (" pathlib" , " WindowsPath" ),
679- PyStructTime_Type = import_python_type (" time" , " struct_time" ),
680- PyUUID_Type = import_python_type (" uuid" , " UUID" ),
681- };
682- for (PyTypeObject* allowed_key_type : allowed_key_types)
705+ if (!this ->try_set_key_type (key_type))
683706 {
684- if (allowed_key_type != nullptr && Py_Is (key_type, reinterpret_cast <PyObject*>(allowed_key_type)))
685- {
686- this ->key_type = allowed_key_type;
687- return 0 ;
688- }
689- }
690-
691- if (key != nullptr )
692- {
693- // The user supplied a key of the wrong type.
694- PyErr_Format (PyExc_TypeError, " got key %R of unsupported type %R" , key, key_type);
695- }
696- else
697- {
698- // The user supplied a wrong value (which should have been a supported
699- // type).
700707 PyErr_Format (PyExc_ValueError, " got %R, want a supported key type" , key_type);
708+ return -1 ;
701709 }
702- return - 1 ;
710+ return 0 ;
703711}
704712
705713int SortedDictType::init (PyObject* args, PyObject* kwargs)
0 commit comments