functions: revert the function init order to make pylint happy again. See #217
[pygobject.git] / gi / pygflags.c
blob01e8a55ef2f4b19e3d109387bfc52a97442b11d2
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 * pygflags.c: GFlags 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-type.h"
25 #include "pygi-util.h"
26 #include "pygi-type.h"
27 #include "pygflags.h"
28 #include "pygboxed.h"
30 GQuark pygflags_class_key;
32 PYGLIB_DEFINE_TYPE("gobject.GFlags", PyGFlags_Type, PyGFlags);
34 static PyObject *
35 pyg_flags_val_new(PyObject* subclass, GType gtype, PyObject *intval)
37 PyObject *args, *item;
38 args = Py_BuildValue("(O)", intval);
39 g_assert(PyObject_IsSubclass(subclass, (PyObject*) &PyGFlags_Type));
40 item = PYGLIB_PyLong_Type.tp_new((PyTypeObject*)subclass, args, NULL);
41 Py_DECREF(args);
42 if (!item)
43 return NULL;
44 ((PyGFlags*)item)->gtype = gtype;
46 return item;
49 static PyObject *
50 pyg_flags_richcompare(PyGFlags *self, PyObject *other, int op)
52 static char warning[256];
54 if (!PYGLIB_PyLong_Check(other)) {
55 Py_INCREF(Py_NotImplemented);
56 return Py_NotImplemented;
59 if (PyObject_TypeCheck(other, &PyGFlags_Type) && ((PyGFlags*)other)->gtype != self->gtype) {
60 g_snprintf(warning, sizeof(warning), "comparing different flags types: %s and %s",
61 g_type_name(self->gtype), g_type_name(((PyGFlags*)other)->gtype));
62 if (PyErr_Warn(PyExc_Warning, warning))
63 return NULL;
66 return pyg_integer_richcompare((PyObject *)self, other, op);
69 static char *
70 generate_repr(GType gtype, guint value)
72 GFlagsClass *flags_class;
73 char *retval = NULL, *tmp;
74 guint i;
76 flags_class = g_type_class_ref(gtype);
77 g_assert(G_IS_FLAGS_CLASS(flags_class));
79 for (i = 0; i < flags_class->n_values; i++) {
80 /* Some types (eg GstElementState in GStreamer 0.8) has flags with 0 values,
81 * we're just ignore them for now otherwise they'll always show up
83 if (flags_class->values[i].value == 0)
84 continue;
86 if ((value & flags_class->values[i].value) == flags_class->values[i].value) {
87 if (retval) {
88 tmp = g_strdup_printf("%s | %s", retval, flags_class->values[i].value_name);
89 g_free(retval);
90 retval = tmp;
91 } else {
92 retval = g_strdup_printf("%s", flags_class->values[i].value_name);
97 g_type_class_unref(flags_class);
99 return retval;
102 static PyObject *
103 pyg_flags_repr(PyGFlags *self)
105 char *tmp, *retval, *module_str, *namespace;
106 PyObject *pyretval, *module;
108 tmp = generate_repr(self->gtype, (guint)PYGLIB_PyLong_AsUnsignedLong(self));
110 module = PyObject_GetAttrString ((PyObject *)self, "__module__");
111 if (module == NULL)
112 return NULL;
114 if (!PYGLIB_PyUnicode_Check (module)) {
115 Py_DECREF (module);
116 return NULL;
119 module_str = PYGLIB_PyUnicode_AsString (module);
120 namespace = g_strrstr (module_str, ".");
121 if (namespace == NULL) {
122 namespace = module_str;
123 } else {
124 namespace += 1;
127 if (tmp)
128 retval = g_strdup_printf("<flags %s of type %s.%s>", tmp,
129 namespace, Py_TYPE (self)->tp_name);
130 else
131 retval = g_strdup_printf("<flags %ld of type %s.%s>",
132 PYGLIB_PyLong_AsUnsignedLong (self),
133 namespace, Py_TYPE (self)->tp_name);
134 g_free(tmp);
135 Py_DECREF (module);
137 pyretval = PYGLIB_PyUnicode_FromString(retval);
138 g_free(retval);
140 return pyretval;
143 static PyObject *
144 pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
146 static char *kwlist[] = { "value", NULL };
147 gulong value;
148 PyObject *pytc, *values, *ret, *pyint;
149 GType gtype;
150 GFlagsClass *eclass;
152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "k", kwlist, &value))
153 return NULL;
155 pytc = PyObject_GetAttrString((PyObject *)type, "__gtype__");
156 if (!pytc)
157 return NULL;
159 if (!PyObject_TypeCheck(pytc, &PyGTypeWrapper_Type)) {
160 Py_DECREF(pytc);
161 PyErr_SetString(PyExc_TypeError,
162 "__gtype__ attribute not a typecode");
163 return NULL;
166 gtype = pyg_type_from_object(pytc);
167 Py_DECREF(pytc);
169 eclass = G_FLAGS_CLASS(g_type_class_ref(gtype));
171 values = PyObject_GetAttrString((PyObject *)type, "__flags_values__");
172 if (!values) {
173 g_type_class_unref(eclass);
174 return NULL;
177 if (!PyDict_Check(values)) {
178 PyErr_SetString(PyExc_TypeError, "__flags_values__ badly formed");
179 Py_DECREF(values);
180 g_type_class_unref(eclass);
181 return NULL;
184 g_type_class_unref(eclass);
186 pyint = PYGLIB_PyLong_FromUnsignedLong(value);
187 ret = PyDict_GetItem(values, pyint);
188 if (!ret) {
189 PyErr_Clear();
191 ret = pyg_flags_val_new((PyObject *)type, gtype, pyint);
192 g_assert(ret != NULL);
193 } else {
194 Py_INCREF(ret);
197 Py_DECREF(pyint);
198 Py_DECREF(values);
200 return ret;
203 PyObject*
204 pyg_flags_from_gtype (GType gtype, guint value)
206 PyObject *pyclass, *values, *retval, *pyint;
208 if (PyErr_Occurred())
209 return PYGLIB_PyLong_FromUnsignedLong(0);
211 g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
213 /* Get a wrapper class by:
214 * 1. check for one attached to the gtype
215 * 2. lookup one in a typelib
216 * 3. creating a new one
218 pyclass = (PyObject*)g_type_get_qdata(gtype, pygflags_class_key);
219 if (!pyclass)
220 pyclass = pygi_type_import_by_g_type(gtype);
221 if (!pyclass)
222 pyclass = pyg_flags_add(NULL, g_type_name(gtype), NULL, gtype);
223 if (!pyclass)
224 return PYGLIB_PyLong_FromUnsignedLong(value);
226 values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
227 "__flags_values__");
228 pyint = PYGLIB_PyLong_FromUnsignedLong(value);
229 retval = PyDict_GetItem(values, pyint);
230 if (!retval) {
231 PyErr_Clear();
233 retval = pyg_flags_val_new(pyclass, gtype, pyint);
234 g_assert(retval != NULL);
235 } else {
236 Py_INCREF(retval);
238 Py_DECREF(pyint);
240 return retval;
244 * pyg_flags_add
245 * Dynamically create a class derived from PyGFlags based on the given GType.
247 PyObject *
248 pyg_flags_add (PyObject * module,
249 const char * typename,
250 const char * strip_prefix,
251 GType gtype)
253 PyGILState_STATE state;
254 PyObject *instance_dict, *stub, *values, *o;
255 GFlagsClass *eclass;
256 guint i;
258 g_return_val_if_fail(typename != NULL, NULL);
259 if (!g_type_is_a(gtype, G_TYPE_FLAGS)) {
260 g_warning("Trying to register gtype '%s' as flags when in fact it is of type '%s'",
261 g_type_name(gtype), g_type_name(G_TYPE_FUNDAMENTAL(gtype)));
262 return NULL;
265 state = PyGILState_Ensure();
267 /* Create a new type derived from GFlags. This is the same as:
268 * >>> stub = type(typename, (GFlags,), {})
270 instance_dict = PyDict_New();
271 stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
272 typename, (PyObject *)&PyGFlags_Type,
273 instance_dict);
274 Py_DECREF(instance_dict);
275 if (!stub) {
276 PyErr_SetString(PyExc_RuntimeError, "can't create GFlags subtype");
277 PyGILState_Release(state);
278 return NULL;
281 ((PyTypeObject *)stub)->tp_flags &= ~Py_TPFLAGS_BASETYPE;
283 if (module) {
284 PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
285 "__module__",
286 PYGLIB_PyUnicode_FromString(PyModule_GetName(module)));
288 /* Add it to the module name space */
289 PyModule_AddObject(module, (char*)typename, stub);
290 Py_INCREF(stub);
292 g_type_set_qdata(gtype, pygflags_class_key, stub);
294 o = pyg_type_wrapper_new(gtype);
295 PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict, "__gtype__", o);
296 Py_DECREF(o);
298 /* Register flag values */
299 eclass = G_FLAGS_CLASS(g_type_class_ref(gtype));
301 values = PyDict_New();
302 for (i = 0; i < eclass->n_values; i++) {
303 PyObject *item, *intval;
305 intval = PYGLIB_PyLong_FromUnsignedLong(eclass->values[i].value);
306 g_assert(PyErr_Occurred() == NULL);
307 item = pyg_flags_val_new(stub, gtype, intval);
308 PyDict_SetItem(values, intval, item);
309 Py_DECREF(intval);
311 if (module) {
312 char *prefix;
314 prefix = g_strdup(pyg_constant_strip_prefix(eclass->values[i].value_name, strip_prefix));
315 Py_INCREF(item);
316 PyModule_AddObject(module, prefix, item);
317 g_free(prefix);
319 Py_DECREF(item);
322 PyDict_SetItemString(((PyTypeObject *)stub)->tp_dict,
323 "__flags_values__", values);
324 Py_DECREF(values);
326 g_type_class_unref(eclass);
328 PyGILState_Release(state);
330 return stub;
333 static PyObject *
334 pyg_flags_and(PyGFlags *a, PyGFlags *b)
336 if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
337 return PYGLIB_PyLong_Type.tp_as_number->nb_and((PyObject*)a,
338 (PyObject*)b);
340 return pyg_flags_from_gtype(a->gtype,
341 (guint)(PYGLIB_PyLong_AsUnsignedLong(a) & PYGLIB_PyLong_AsUnsignedLong(b)));
344 static PyObject *
345 pyg_flags_or(PyGFlags *a, PyGFlags *b)
347 if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
348 return PYGLIB_PyLong_Type.tp_as_number->nb_or((PyObject*)a,
349 (PyObject*)b);
351 return pyg_flags_from_gtype(a->gtype, (guint)(PYGLIB_PyLong_AsUnsignedLong(a) | PYGLIB_PyLong_AsUnsignedLong(b)));
354 static PyObject *
355 pyg_flags_xor(PyGFlags *a, PyGFlags *b)
357 if (!PyGFlags_Check(a) || !PyGFlags_Check(b))
358 return PYGLIB_PyLong_Type.tp_as_number->nb_xor((PyObject*)a,
359 (PyObject*)b);
361 return pyg_flags_from_gtype(a->gtype,
362 (guint)(PYGLIB_PyLong_AsUnsignedLong(a) ^ PYGLIB_PyLong_AsUnsignedLong(b)));
366 static PyObject *
367 pyg_flags_warn (PyObject *self, PyObject *args)
369 if (PyErr_Warn(PyExc_Warning, "unsupported arithmetic operation for flags type"))
370 return NULL;
372 Py_INCREF(Py_None);
373 return Py_None;
376 static PyObject *
377 pyg_flags_get_first_value_name(PyGFlags *self, void *closure)
379 GFlagsClass *flags_class;
380 GFlagsValue *flags_value;
381 PyObject *retval;
383 flags_class = g_type_class_ref(self->gtype);
384 g_assert(G_IS_FLAGS_CLASS(flags_class));
385 flags_value = g_flags_get_first_value(flags_class, (guint)PYGLIB_PyLong_AsUnsignedLong(self));
386 if (flags_value)
387 retval = PYGLIB_PyUnicode_FromString(flags_value->value_name);
388 else {
389 retval = Py_None;
390 Py_INCREF(Py_None);
392 g_type_class_unref(flags_class);
394 return retval;
397 static PyObject *
398 pyg_flags_get_first_value_nick(PyGFlags *self, void *closure)
400 GFlagsClass *flags_class;
401 GFlagsValue *flags_value;
402 PyObject *retval;
404 flags_class = g_type_class_ref(self->gtype);
405 g_assert(G_IS_FLAGS_CLASS(flags_class));
407 flags_value = g_flags_get_first_value(flags_class, (guint)PYGLIB_PyLong_AsUnsignedLong(self));
408 if (flags_value)
409 retval = PYGLIB_PyUnicode_FromString(flags_value->value_nick);
410 else {
411 retval = Py_None;
412 Py_INCREF(Py_None);
414 g_type_class_unref(flags_class);
416 return retval;
419 static PyObject *
420 pyg_flags_get_value_names(PyGFlags *self, void *closure)
422 GFlagsClass *flags_class;
423 PyObject *retval;
424 guint i;
426 flags_class = g_type_class_ref(self->gtype);
427 g_assert(G_IS_FLAGS_CLASS(flags_class));
429 retval = PyList_New(0);
430 for (i = 0; i < flags_class->n_values; i++) {
431 PyObject *value_name;
433 if ((PYGLIB_PyLong_AsUnsignedLong (self) & flags_class->values[i].value) == flags_class->values[i].value) {
434 value_name = PYGLIB_PyUnicode_FromString (flags_class->values[i].value_name);
435 PyList_Append (retval, value_name);
436 Py_DECREF (value_name);
440 g_type_class_unref(flags_class);
442 return retval;
445 static PyObject *
446 pyg_flags_get_value_nicks(PyGFlags *self, void *closure)
448 GFlagsClass *flags_class;
449 PyObject *retval;
450 guint i;
452 flags_class = g_type_class_ref(self->gtype);
453 g_assert(G_IS_FLAGS_CLASS(flags_class));
455 retval = PyList_New(0);
456 for (i = 0; i < flags_class->n_values; i++)
457 if ((PYGLIB_PyLong_AsUnsignedLong(self) & flags_class->values[i].value) == flags_class->values[i].value) {
458 PyObject *py_nick = PYGLIB_PyUnicode_FromString(flags_class->values[i].value_nick);
459 PyList_Append(retval, py_nick);
460 Py_DECREF (py_nick);
463 g_type_class_unref(flags_class);
465 return retval;
468 static PyGetSetDef pyg_flags_getsets[] = {
469 { "first_value_name", (getter)pyg_flags_get_first_value_name, (setter)0 },
470 { "first_value_nick", (getter)pyg_flags_get_first_value_nick, (setter)0 },
471 { "value_names", (getter)pyg_flags_get_value_names, (setter)0 },
472 { "value_nicks", (getter)pyg_flags_get_value_nicks, (setter)0 },
473 { NULL, 0, 0 }
476 static PyNumberMethods pyg_flags_as_number = {
477 (binaryfunc)pyg_flags_warn, /* nb_add */
478 (binaryfunc)pyg_flags_warn, /* nb_subtract */
479 (binaryfunc)pyg_flags_warn, /* nb_multiply */
480 (binaryfunc)pyg_flags_warn, /* nb_divide */
481 (binaryfunc)pyg_flags_warn, /* nb_remainder */
482 #if PY_VERSION_HEX < 0x03000000
483 (binaryfunc)pyg_flags_warn, /* nb_divmod */
484 #endif
485 (ternaryfunc)pyg_flags_warn, /* nb_power */
486 0, /* nb_negative */
487 0, /* nb_positive */
488 0, /* nb_absolute */
489 0, /* nb_nonzero */
490 0, /* nb_invert */
491 0, /* nb_lshift */
492 0, /* nb_rshift */
493 (binaryfunc)pyg_flags_and, /* nb_and */
494 (binaryfunc)pyg_flags_xor, /* nb_xor */
495 (binaryfunc)pyg_flags_or, /* nb_or */
499 * Returns 0 on success, or -1 and sets an exception.
502 pygi_flags_register_types(PyObject *d)
504 pygflags_class_key = g_quark_from_static_string("PyGFlags::class");
506 PyGFlags_Type.tp_base = &PYGLIB_PyLong_Type;
507 PyGFlags_Type.tp_new = pyg_flags_new;
508 PyGFlags_Type.tp_hash = PYGLIB_PyLong_Type.tp_hash;
509 PyGFlags_Type.tp_repr = (reprfunc)pyg_flags_repr;
510 PyGFlags_Type.tp_as_number = &pyg_flags_as_number;
511 PyGFlags_Type.tp_str = (reprfunc)pyg_flags_repr;
512 PyGFlags_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
513 PyGFlags_Type.tp_richcompare = (richcmpfunc)pyg_flags_richcompare;
514 PyGFlags_Type.tp_getset = pyg_flags_getsets;
515 PYGOBJECT_REGISTER_GTYPE(d, PyGFlags_Type, "GFlags", G_TYPE_FLAGS);
517 return 0;