-
Notifications
You must be signed in to change notification settings - Fork 139
Open
Description
Hi,
I stumbled across this since we use graalpy on the pydantic test suite, where we interact with Python's C API through Rust. If going through that the order of an OrderedDict
is not respected (it is for a dict though). Here are the steps to reproduce:
dict_printer.c
:
#include <Python.h>
static PyObject* print_dict(PyObject* self, PyObject* args) {
PyObject* dict;
if (!PyArg_ParseTuple(args, "O", &dict)) {
return NULL;
}
PyObject* mapping = PyObject_GetIter(PyMapping_Items(dict));
if (mapping == NULL) {
PyErr_SetString(PyExc_TypeError, "Object is not a valid mapping");
return NULL;
}
PyObject* item;
printf("Mapping contents:\n");
while ((item = PyIter_Next(mapping)) != NULL) {
PyObject* key = PyTuple_GetItem(item, 0);
PyObject* value = PyTuple_GetItem(item, 1);
PyObject* key_str = PyObject_Str(key);
PyObject* value_str = PyObject_Str(value);
const char* key_cstr = PyUnicode_AsUTF8(key_str);
const char* value_cstr = PyUnicode_AsUTF8(value_str);
printf(" %s: %s\n", key_cstr, value_cstr);
Py_DECREF(key_str);
Py_DECREF(value_str);
Py_DECREF(item);
}
Py_DECREF(mapping);
if (PyErr_Occurred()) {
return NULL;
}
Py_RETURN_NONE;
}
static PyMethodDef DictPrinterMethods[] = {
{"print_dict", print_dict, METH_VARARGS, "Print all elements of a dictionary/mapping"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef dictprintermodule = {
PyModuleDef_HEAD_INIT,
"dict_printer",
"A module to print dictionary/mapping elements",
-1,
DictPrinterMethods
};
PyMODINIT_FUNC PyInit_dict_printer(void) {
return PyModule_Create(&dictprintermodule);
}
setup.py
from setuptools import setup, Extension
module = Extension('dict_printer',
sources=['dict_printer.c'])
setup(name='dict_printer',
version='1.0',
description='C extension to print dictionary/mapping elements',
ext_modules=[module])
Then run python setup.py build_ext --inplace
and execute
from collections import OrderedDict
import dict_printer
my_dict = OrderedDict({'a': 1, 'b': 2, 'c': 3})
my_dict.move_to_end('a')
dict_printer.print_dict(my_dict)
print(my_dict)
This outputs with graalpy:
Mapping contents:
a: 1
b: 2
c: 3
OrderedDict({'b': 2, 'c': 3, 'a': 1})
using CPython:
Mapping contents:
b: 2
c: 3
a: 1
OrderedDict([('b', 2), ('c', 3), ('a', 1)])
Thanks.
Metadata
Metadata
Assignees
Labels
No labels