functions: revert the function init order to make pylint happy again. See #217
[pygobject.git] / gi / pygenum.c
blob69f1cd70c0495968f3e19c356ac1f36b965220e3
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * pygtk- Python bindings for the GTK toolkit.
3 * Copyright (C) 1998-2003 James Henstridge
4 * Copyright (C) 2004 Johan Dahlin
6 * pygenum.c: GEnum wrapper
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 #include <config.h>
24 #include "pygi-python-compat.h"
25 #include "pygi-type.h"
26 #include "pygi-util.h"
27 #include "pygi-type.h"
28 #include "pygi-basictype.h"
29 #include "pygenum.h"
30 #include "pygboxed.h"
32 GQuark pygenum_class_key;
34 PYGLIB_DEFINE_TYPE("gobject.GEnum", PyGEnum_Type, PyGEnum);
36 static PyObject *
37 pyg_enum_val_new(PyObject* subclass, GType gtype, PyObject *intval)
39 PyObject *args, *item;
40 args = Py_BuildValue("(O)", intval);
41 item = (&PYGLIB_PyLong_Type)->tp_new((PyTypeObject*)subclass, args, NULL);
42 Py_DECREF(args);
43 if (!item)
44 return NULL;
45 ((PyGEnum*)item)->gtype = gtype;
47 return item;
50 static PyObject *
51 pyg_enum_richcompare(PyGEnum *self, PyObject *other, int op)
53 static char warning[256];
55 if (!PYGLIB_PyLong_Check(other)) {
56 Py_INCREF(Py_NotImplemented);
57 return Py_NotImplemented;
60 if (PyObject_TypeCheck(other, &PyGEnum_Type) && ((PyGEnum*)other)->gtype != self->gtype) {
61 g_snprintf(warning, sizeof(warning), "comparing different enum types: %s and %s",
62 g_type_name(self->gtype), g_type_name(((PyGEnum*)other)->gtype));
63 if (PyErr_Warn(PyExc_Warning, warning))
64 return NULL;
67 return pyg_integer_richcompare((PyObject *)self, other, op);
70 static PyObject *
71 pyg_enum_repr(PyGEnum *self)
73 PyObject *module;
74 GEnumClass *enum_class;
75 const char *value;
76 guint index;
77 char *namespace, *module_str;
78 static char tmp[256];
79 long l;
81 module = PyObject_GetAttrString ((PyObject *)self, "__module__");
82 if (module == NULL)
83 return NULL;
85 if (!PYGLIB_PyUnicode_Check (module)) {
86 Py_DECREF (module);
87 return NULL;
90 enum_class = g_type_class_ref(self->gtype);
91 g_assert(G_IS_ENUM_CLASS(enum_class));
93 l = PYGLIB_PyLong_AS_LONG(self);
94 for (index = 0; index < enum_class->n_values; index++)
95 if (l == enum_class->values[index].value)
96 break;
98 module_str = PYGLIB_PyUnicode_AsString (module);
99 namespace = g_strrstr (module_str, ".");
100 if (namespace == NULL) {
101 namespace = module_str;
102 } else {
103 namespace += 1;
106 value = enum_class->values[index].value_name;
107 if (value)
108 sprintf(tmp, "<enum %s of type %s.%s>", value,
109 namespace, Py_TYPE (self)->tp_name);
110 else
111 sprintf(tmp, "<enum %ld of type %s.%s>", PYGLIB_PyLong_AS_LONG(self),
112 namespace, Py_TYPE (self)->tp_name);
113 Py_DECREF (module);
114 g_type_class_unref(enum_class);
116 return PYGLIB_PyUnicode_FromString(tmp);
119 static PyObject *
120 pyg_enum_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
122 static char *kwlist[] = { "value", NULL };
123 long value;
124 PyObject *pytc, *values, *ret, *intvalue;
125 GType gtype;
126 GEnumClass *eclass;
128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "l", kwlist, &value))
129 return NULL;
131 pytc = PyObject_GetAttrString((PyObject *)type, "__gtype__");
132 if (!pytc)
133 return NULL;
135 if (!PyObject_TypeCheck(pytc, &PyGTypeWrapper_Type)) {
136 Py_DECREF(pytc);
137 PyErr_SetString(PyExc_TypeError,
138 "__gtype__ attribute not a typecode");
139 return NULL;
142 gtype = pyg_type_from_object(pytc);
143 Py_DECREF(pytc);
145 eclass = G_ENUM_CLASS(g_type_class_ref(gtype));
147 /* A check that 0 < value < eclass->n_values was here but got
148 * removed: enumeration values do not need to be consequitive,
149 * e.g. GtkPathPriorityType values are not.
152 values = PyObject_GetAttrString((PyObject *)type, "__enum_values__");
153 if (!values) {
154 g_type_class_unref(eclass);
155 return NULL;
158 /* Note that size of __enum_values__ dictionary can easily be less
159 * than 'n_values'. This happens if some values of the enum are
160 * numerically equal, e.g. gtk.ANCHOR_N == gtk.ANCHOR_NORTH.
161 * Johan said that "In retrospect, using a dictionary to store the
162 * values might not have been that good", but we need to keep
163 * backward compatibility.
165 if (!PyDict_Check(values) || (gsize)PyDict_Size(values) > eclass->n_values) {
166 PyErr_SetString(PyExc_TypeError, "__enum_values__ badly formed");
167 Py_DECREF(values);
168 g_type_class_unref(eclass);
169 return NULL;
172 g_type_class_unref(eclass);
174 intvalue = PYGLIB_PyLong_FromLong(value);
175 ret = PyDict_GetItem(values, intvalue);
176 Py_DECREF(intvalue);
177 Py_DECREF(values);
178 if (ret)
179 Py_INCREF(ret);
180 else
181 PyErr_Format(PyExc_ValueError, "invalid enum value: %ld", value);
183 return ret;
186 PyObject*
187 pyg_enum_from_gtype (GType gtype, int value)
189 PyObject *pyclass, *values, *retval, *intvalue;
191 g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
193 /* Get a wrapper class by:
194 * 1. check for one attached to the gtype
195 * 2. lookup one in a typelib
196 * 3. creating a new one
198 pyclass = (PyObject*)g_type_get_qdata(gtype, pygenum_class_key);
199 if (!pyclass)
200 pyclass = pygi_type_import_by_g_type(gtype);
201 if (!pyclass)
202 pyclass = pyg_enum_add(NULL, g_type_name(gtype), NULL, gtype);
203 if (!pyclass)
204 return PYGLIB_PyLong_FromLong(value);
206 values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
207 "__enum_values__");
208 intvalue = PYGLIB_PyLong_FromLong(value);
209 retval = PyDict_GetItem(values, intvalue);
210 if (retval) {
211 Py_INCREF(retval);
213 else {
214 PyErr_Clear();
215 retval = pyg_enum_val_new(pyclass, gtype, intvalue);
217 Py_DECREF(intvalue);
219 return retval;
223 * pyg_enum_add
224 * Dynamically create a class derived from PyGEnum based on the given GType.
226 PyObject *
227 pyg_enum_add (PyObject * module,
228 const char * typename,
229 const char * strip_prefix,
230 GType gtype)
232 PyGILState_STATE state;
233 PyObject *instance_dict, *stub, *values, *o;
234 GEnumClass *eclass;
235 guint i;
237 g_return_val_if_fail(typename != NULL, NULL);
238 if (!g_type_is_a (gtype, G_TYPE_ENUM)) {
239 PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as enum when in fact it is of type '%s'",
240 g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype)));
241 return NULL;
244 state = PyGILState_Ensure();
246 /* Create a new type derived from GEnum. This is the same as:
247 * >>> stub = type(typename, (GEnum,), {})
249 instance_dict = PyDict_New();
250 stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
251 typename, (PyObject *)&PyGEnum_Type,
252 instance_dict);
253 Py_DECREF(instance_dict);
254 if (!stub) {
255 PyErr_SetString(PyExc_RuntimeError, "can't create const");
256 PyGILState_Release(state);
257 return NULL;
260 ((PyTypeObject *)stub)->tp_flags &= ~Py_TPFLAGS_BASETYPE;
262 if (module)
263 PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
264 "__module__",
265 PYGLIB_PyUnicode_FromString(PyModule_GetName(module)));
267 g_type_set_qdata(gtype, pygenum_class_key, stub);
269 o = pyg_type_wrapper_new(gtype);
270 PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict, "__gtype__", o);
271 Py_DECREF(o);
273 if (module) {
274 /* Add it to the module name space */
275 PyModule_AddObject(module, (char*)typename, stub);
276 Py_INCREF(stub);
279 /* Register enum values */
280 eclass = G_ENUM_CLASS(g_type_class_ref(gtype));
282 values = PyDict_New();
283 for (i = 0; i < eclass->n_values; i++) {
284 PyObject *item, *intval;
286 intval = PYGLIB_PyLong_FromLong(eclass->values[i].value);
287 item = pyg_enum_val_new(stub, gtype, intval);
288 PyDict_SetItem(values, intval, item);
289 Py_DECREF(intval);
291 if (module) {
292 char *prefix;
294 prefix = g_strdup(pyg_constant_strip_prefix(eclass->values[i].value_name, strip_prefix));
295 PyModule_AddObject(module, prefix, item);
296 g_free(prefix);
298 Py_INCREF(item);
302 PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
303 "__enum_values__", values);
304 Py_DECREF(values);
306 g_type_class_unref(eclass);
308 PyGILState_Release(state);
309 return stub;
312 static PyObject *
313 pyg_enum_reduce(PyObject *self, PyObject *args)
315 if (!PyArg_ParseTuple(args, ":GEnum.__reduce__"))
316 return NULL;
318 return Py_BuildValue("(O(i)O)", Py_TYPE(self), PYGLIB_PyLong_AsLong(self),
319 PyObject_GetAttrString(self, "__dict__"));
322 static PyObject *
323 pyg_enum_get_value_name(PyGEnum *self, void *closure)
325 GEnumClass *enum_class;
326 GEnumValue *enum_value;
327 PyObject *retval;
328 gint intvalue;
330 if (!pygi_gint_from_py ((PyObject*) self, &intvalue))
331 return NULL;
333 enum_class = g_type_class_ref(self->gtype);
334 g_assert(G_IS_ENUM_CLASS(enum_class));
336 enum_value = g_enum_get_value(enum_class, intvalue);
338 retval = pygi_utf8_to_py (enum_value->value_name);
339 g_type_class_unref(enum_class);
341 return retval;
344 static PyObject *
345 pyg_enum_get_value_nick(PyGEnum *self, void *closure)
347 GEnumClass *enum_class;
348 GEnumValue *enum_value;
349 PyObject *retval;
350 gint intvalue;
352 if (!pygi_gint_from_py ((PyObject*) self, &intvalue))
353 return NULL;
355 enum_class = g_type_class_ref(self->gtype);
356 g_assert(G_IS_ENUM_CLASS(enum_class));
358 enum_value = g_enum_get_value(enum_class, intvalue);
360 retval = pygi_utf8_to_py (enum_value->value_nick);
362 g_type_class_unref(enum_class);
364 return retval;
368 static PyMethodDef pyg_enum_methods[] = {
369 { "__reduce__", (PyCFunction)pyg_enum_reduce, METH_VARARGS },
370 { NULL, NULL, 0 }
373 static PyGetSetDef pyg_enum_getsets[] = {
374 { "value_name", (getter)pyg_enum_get_value_name, (setter)0 },
375 { "value_nick", (getter)pyg_enum_get_value_nick, (setter)0 },
376 { NULL, 0, 0 }
380 * Returns 0 on success, or -1 and sets an exception.
383 pygi_enum_register_types(PyObject *d)
385 pygenum_class_key = g_quark_from_static_string("PyGEnum::class");
387 PyGEnum_Type.tp_base = &PYGLIB_PyLong_Type;
388 PyGEnum_Type.tp_new = pyg_enum_new;
389 PyGEnum_Type.tp_hash = PYGLIB_PyLong_Type.tp_hash;
390 PyGEnum_Type.tp_repr = (reprfunc)pyg_enum_repr;
391 PyGEnum_Type.tp_str = (reprfunc)pyg_enum_repr;
392 PyGEnum_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
393 PyGEnum_Type.tp_richcompare = (richcmpfunc)pyg_enum_richcompare;
394 PyGEnum_Type.tp_methods = pyg_enum_methods;
395 PyGEnum_Type.tp_getset = pyg_enum_getsets;
396 PYGOBJECT_REGISTER_GTYPE(d, PyGEnum_Type, "GEnum", G_TYPE_ENUM);
398 return 0;