From 2a0b25fca5f6d4bef7edd4d618e420559209e8ec Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 21 Feb 2022 00:22:59 +0100 Subject: Translate enumerations before PyGObject using internal definitions when needed. --- plugins/pychrysalide/helpers.c | 104 +++++++++++++++++++++++++++++++++++++++-- plugins/pychrysalide/helpers.h | 54 +++++++++++++++------ 2 files changed, 139 insertions(+), 19 deletions(-) diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c index 92a5db9..320e40a 100644 --- a/plugins/pychrysalide/helpers.c +++ b/plugins/pychrysalide/helpers.c @@ -1440,15 +1440,15 @@ int convert_to_gdk_rgba(PyObject *arg, void *dst) * * * Description : Officialise un groupe de constantes avec sémentique. * * * -* Retour : true en cas de succès de l'opération, false sinon. * +* Retour : Groupe de constantes mis en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc) +PyObject *_attach_constants_group(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc) { - bool result; /* Bilan à retourner */ + PyObject *result; /* Instance à retourner */ PyObject *enum_mod; /* Module Python enum */ PyObject *class; /* Classe "Enum*" */ PyObject *str_obj; /* Conversion en Python */ @@ -1462,7 +1462,7 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons PyObject *features; /* Module à recompléter */ PyObject *features_dict; /* Dictionnaire à compléter */ - result = false; + result = NULL; /* Recherche de la classe Python */ @@ -1539,7 +1539,8 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons ret = PyDict_SetItemString(features_dict, name, new); if (ret != 0) goto register_1_error; - result = true; + result = new; + Py_INCREF(result); /* Sortie propre */ @@ -1570,6 +1571,99 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons } +/****************************************************************************** +* * +* Paramètres : owner = désignation du propriétaire du dictionnaire visé. * +* dict = dictionnaire dont le contenu est à compléter. * +* flags = indique le type d'énumération ciblée. * +* name = désignation humaine du groupe à constituer. * +* values = noms et valeurs associées. * +* doc = documentation à associer au groupe. * +* gtype = énumération GLib à lier. * +* * +* Description : Officialise un groupe de constantes avec lien GLib. * +* * +* Retour : Groupe de constantes mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyObject *_attach_constants_group_with_pyg_enum(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc, GType gtype) +{ + PyObject *result; /* Instance à retourner */ + PyObject *values_set; /* Zone pour nouvelles valeurs */ + int ret; /* Bilan d'une insertion */ + PyObject *new; /* Nouvelle instance en place */ + PyObject *values_src; /* Source de nouvelles valeurs */ + PyObject *values_dest; /* Destination des valeurs */ + + static GQuark pygenum_class_key = 0; /* Clef d'accès au marquage */ + + result = NULL; + + /** + * Le seul intérêt d'un tel enregistrement en bonne et due forme est de + * permettre une impression, via str() ou repr(), de l'énumération + * transcrite en GLib via g_enum_register_static() et potentiellement + * convertie de façon brusque par _pygi_argument_to_object(), lors d'une + * émission de signal par exemple. + * + * La satisfaction de la fonction pyg_enum_from_gtype() est ainsi recherchée. + * Tous les éléments sont normalement mis en place à partir de la fonction + * pyg_enum_add(). + */ + + /* Préparation du réceptacle */ + + values_set = PyDict_New(); + + ret = PyDict_SetItemString(values, "__enum_values__", values_set); + + Py_DECREF(values_set); + + if (ret != 0) goto exit; + + /* Création */ + + new = _attach_constants_group(owner, dict, flags, name, values, doc); + if (new == NULL) goto exit; + + /* Actualisation des valeurs */ + + values_src = PyDict_GetItemString(((PyTypeObject *)new)->tp_dict, "_value2member_map_"); + if (values_src == NULL) goto exit_without_src; + + values_dest = PyDict_GetItemString(((PyTypeObject *)new)->tp_dict, "__enum_values__"); + if (values_dest == NULL) goto exit_without_dest; + + assert(values_dest == values_set); + + ret = PyDict_Merge(values_dest, values_src, true); + + if (ret == 0) + { + result = new; + Py_INCREF(result); + + if (pygenum_class_key == 0) + pygenum_class_key = g_quark_from_static_string("PyGEnum::class"); + + g_type_set_qdata(gtype, pygenum_class_key, result); + + } + + exit_without_dest: + exit_without_src: + + Py_DECREF(new); + + exit: + + return result; + +} + /****************************************************************************** * * diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h index 931be95..0ef8adc 100644 --- a/plugins/pychrysalide/helpers.h +++ b/plugins/pychrysalide/helpers.h @@ -308,20 +308,46 @@ int convert_to_gdk_rgba(PyObject *, void *); }) /* Officialise un groupe de constantes avec sémentique. */ -bool _attach_constants_group(const char *, PyObject *, bool, const char *, PyObject *, const char *); - -#define attach_constants_group_to_type(type, flags, name, values, doc) \ - _attach_constants_group(type->tp_name, type->tp_dict, flags, name, values, doc) - -#define attach_constants_group_to_module(mod, flags, name, values, doc) \ - ({ \ - bool __result; \ - const char *__owner; \ - PyObject *__dict; \ - __owner = PyModule_GetName(mod); \ - __dict = PyModule_GetDict(mod); \ - __result = _attach_constants_group(__owner, __dict, flags, name, values, doc); \ - __result; \ +PyObject *_attach_constants_group(const char *, PyObject *, bool, const char *, PyObject *, const char *); + +#define attach_constants_group_to_type(type, flags, name, values, doc) \ + ({ \ + bool __result; \ + PyObject *__new; \ + __new = _attach_constants_group(type->tp_name, type->tp_dict, flags, name, values, \ + doc); \ + __result = (__new != NULL); \ + Py_XDECREF(__new); \ + __result; \ + }) + +#define attach_constants_group_to_module(mod, flags, name, values, doc) \ + ({ \ + bool __result; \ + const char *__owner; \ + PyObject *__dict; \ + PyObject *__new; \ + __owner = PyModule_GetName(mod); \ + __dict = PyModule_GetDict(mod); \ + __new = _attach_constants_group(__owner, __dict, flags, name, values, doc); \ + __result = (__new != NULL); \ + Py_XDECREF(__new); \ + __result; \ + }) + +/* Officialise un groupe de constantes avec lien GLib. */ +PyObject *_attach_constants_group_with_pyg_enum(const char *, PyObject *, bool, const char *, PyObject *, const char *, GType); + + +#define attach_constants_group_to_type_with_pyg_enum(type, flags, name, values, doc, gtype) \ + ({ \ + bool __result; \ + PyObject *__new; \ + __new = _attach_constants_group_with_pyg_enum(type->tp_name, type->tp_dict, flags, \ + name, values, doc, gtype); \ + __result = (__new != NULL); \ + Py_XDECREF(__new); \ + __result; \ }) /* Traduit une valeur constante C en équivalent Python. */ -- cgit v0.11.2-87-g4458