self.assertEqual(dct, frozendict(x=1, y=2))
self.assertIs(type(dct), frozendict)
+ # PyFrozenDict_New(frozendict) returns the same object unmodified
+ fd = frozendict(a=1, b=2, c=3)
+ fd2 = frozendict_new(fd)
+ self.assertIs(fd2, fd)
+
+ fd = FrozenDictSubclass(a=1, b=2, c=3)
+ fd2 = frozendict_new(fd)
+ self.assertIsNot(fd2, fd)
+ self.assertEqual(fd2, fd)
+
# PyFrozenDict_New(NULL) creates an empty dictionary
dct = frozendict_new(NULL)
self.assertEqual(dct, frozendict())
return NULL;
}
- PyObject *self;
- if (Py_Is((PyTypeObject*)type, &PyFrozenDict_Type)
- || PyType_IsSubtype((PyTypeObject*)type, &PyFrozenDict_Type))
- {
- self = frozendict_new(_PyType_CAST(type), NULL, NULL);
+ PyObject *self = dict_new(_PyType_CAST(type), NULL, NULL);
+ if (self == NULL) {
+ return NULL;
}
- else {
- self = dict_new(_PyType_CAST(type), NULL, NULL);
+ if (nargs == 1) {
+ if (dict_update_arg(self, args[0]) < 0) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ args++;
}
+ if (kwnames != NULL) {
+ for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwnames); i++) {
+ PyObject *key = PyTuple_GET_ITEM(kwnames, i); // borrowed
+ if (PyDict_SetItem(self, key, args[i]) < 0) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+ }
+ return self;
+}
+
+static PyObject *
+frozendict_vectorcall(PyObject *type, PyObject * const*args,
+ size_t nargsf, PyObject *kwnames)
+{
+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
+ if (!_PyArg_CheckPositional("frozendict", nargs, 0, 1)) {
+ return NULL;
+ }
+
+ if (nargs == 1 && kwnames == NULL
+ && PyFrozenDict_CheckExact(args[0])
+ && Py_Is((PyTypeObject*)type, &PyFrozenDict_Type))
+ {
+ // frozendict(frozendict) returns the same object unmodified
+ return Py_NewRef(args[0]);
+ }
+
+ PyObject *self = frozendict_new(_PyType_CAST(type), NULL, NULL);
if (self == NULL) {
return NULL;
}
PyFrozenDict_New(PyObject *iterable)
{
if (iterable != NULL) {
+ if (PyFrozenDict_CheckExact(iterable)) {
+ // PyFrozenDict_New(frozendict) returns the same object unmodified
+ return Py_NewRef(iterable);
+ }
+
PyObject *args = PyTuple_Pack(1, iterable);
if (args == NULL) {
return NULL;
.tp_alloc = _PyType_AllocNoTrack,
.tp_new = frozendict_new,
.tp_free = PyObject_GC_Del,
- .tp_vectorcall = dict_vectorcall,
+ .tp_vectorcall = frozendict_vectorcall,
.tp_version_tag = _Py_TYPE_VERSION_FROZENDICT,
};