Update NEWS, README for 0.80.0
[dbus-python-phuang.git] / _dbus_bindings / string.c
blobf655600430c91fc73e66a56d50d4278fbe9af5d8
1 /* Simple D-Bus types: ObjectPath and other string types.
2  *
3  * Copyright (C) 2006 Collabora Ltd.
4  *
5  * Licensed under the Academic Free License version 2.1
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
25 #include "types-internal.h"
27 /* UTF-8 string representation ====================================== */
29 PyDoc_STRVAR(UTF8String_tp_doc,
30 "A string represented using UTF-8 - a subtype of `str`.\n"
31 "\n"
32 "All strings on D-Bus are required to be valid Unicode; in the \"wire\n"
33 "protocol\" they're transported as UTF-8.\n"
34 "\n"
35 "By default, when byte arrays are converted from D-Bus to Python, they\n"
36 "come out as a `dbus.String`, which is a subtype of `unicode`.\n"
37 "If you prefer to get UTF-8 strings (as instances of this class) or you\n"
38 "want to avoid the conversion overhead of going from UTF-8 to Python's\n"
39 "internal Unicode representation, you can pass the ``utf8_strings=True``\n"
40 "keyword argument to any of these methods:\n"
41 "\n"
42 "* any D-Bus method proxy, or ``connect_to_signal``, on the objects returned\n"
43 "  by `Bus.get_object`\n"
44 "* any D-Bus method on a `dbus.Interface`\n"
45 "* `dbus.Interface.connect_to_signal`\n"
46 "* `Bus.add_signal_receiver`\n"
47 "\n"
48 "\n"
49 "Constructor::\n"
50 "\n"
51 "    dbus.UTF8String(value: str or unicode[, variant_level: int]) -> UTF8String\n"
52 "\n"
53 "If value is a str object it must be valid UTF-8.\n"
54 "\n"
55 "variant_level must be non-negative; the default is 0.\n"
56 "\n"
57 ":IVariables:\n"
58 "  `variant_level` : int\n"
59 "    Indicates how many nested Variant containers this object\n"
60 "    is contained in: if a message's wire format has a variant containing a\n"
61 "    variant containing a string, this is represented in Python by a\n"
62 "    String or UTF8String with variant_level==2.\n"
63 ":Since: 0.80 (in older versions, use dbus.String)\n"
66 static PyObject *
67 UTF8String_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
69     const char *str = NULL;
70     long variantness = 0;
71     static char *argnames[] = {"value", "variant_level", NULL};
72     PyObject *unicode;
74     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|l:__new__", argnames,
75                                      &str, &variantness)) return NULL;
76     unicode = PyUnicode_DecodeUTF8(str, strlen(str), NULL);
77     if (!unicode) return NULL;
78     Py_DECREF(unicode);
79     return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
82 PyTypeObject DBusPyUTF8String_Type = {
83     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
84     0,
85     "dbus.UTF8String",
86     0,
87     0,
88     0,                                      /* tp_dealloc */
89     0,                                      /* tp_print */
90     0,                                      /* tp_getattr */
91     0,                                      /* tp_setattr */
92     0,                                      /* tp_compare */
93     0,                                      /* tp_repr */
94     0,                                      /* tp_as_number */
95     0,                                      /* tp_as_sequence */
96     0,                                      /* tp_as_mapping */
97     0,                                      /* tp_hash */
98     0,                                      /* tp_call */
99     0,                                      /* tp_str */
100     0,                                      /* tp_getattro */
101     0,                                      /* tp_setattro */
102     0,                                      /* tp_as_buffer */
103     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
104     UTF8String_tp_doc,                      /* tp_doc */
105     0,                                      /* tp_traverse */
106     0,                                      /* tp_clear */
107     0,                                      /* tp_richcompare */
108     0,                                      /* tp_weaklistoffset */
109     0,                                      /* tp_iter */
110     0,                                      /* tp_iternext */
111     0,                                      /* tp_methods */
112     0,                                      /* tp_members */
113     0,                                      /* tp_getset */
114     DEFERRED_ADDRESS(&DBusPyStrBase_Type),   /* tp_base */
115     0,                                      /* tp_dict */
116     0,                                      /* tp_descr_get */
117     0,                                      /* tp_descr_set */
118     0,                                      /* tp_dictoffset */
119     0,                                      /* tp_init */
120     0,                                      /* tp_alloc */
121     UTF8String_tp_new,                      /* tp_new */
124 /* Object path ====================================================== */
126 PyDoc_STRVAR(ObjectPath_tp_doc,
127 "A D-Bus object path, such as '/com/example/MyApp/Documents/abc'.\n"
128 "\n"
129 "ObjectPath is a subtype of str, and object-paths behave like strings.\n"
130 "\n"
131 "Constructor::\n"
132 "\n"
133 "    dbus.ObjectPath(path: str, variant_level: int) -> ObjectPath\n"
134 "\n"
135 "path must be an ASCII string following the syntax of object paths.\n"
136 "variant_level must be non-negative; the default is 0.\n"
137 "\n"
138 ":IVariables:\n"
139 "  `variant_level` : int\n"
140 "    Indicates how many nested Variant containers this object\n"
141 "    is contained in: if a message's wire format has a variant containing a\n"
142 "    variant containing an object path, this is represented in Python by an\n"
143 "    ObjectPath with variant_level==2.\n"
146 static PyObject *
147 ObjectPath_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
149     const char *str = NULL;
150     long variantness = 0;
151     static char *argnames[] = {"object_path", "variant_level", NULL};
153     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|l:__new__", argnames,
154                                      &str, &variantness)) return NULL;
155     if (!dbus_py_validate_object_path(str)) {
156         return NULL;
157     }
158     return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
161 PyTypeObject DBusPyObjectPath_Type = {
162     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
163     0,
164     "dbus.ObjectPath",
165     0,
166     0,
167     0,                                      /* tp_dealloc */
168     0,                                      /* tp_print */
169     0,                                      /* tp_getattr */
170     0,                                      /* tp_setattr */
171     0,                                      /* tp_compare */
172     0,                                      /* tp_repr */
173     0,                                      /* tp_as_number */
174     0,                                      /* tp_as_sequence */
175     0,                                      /* tp_as_mapping */
176     0,                                      /* tp_hash */
177     0,                                      /* tp_call */
178     0,                                      /* tp_str */
179     0,                                      /* tp_getattro */
180     0,                                      /* tp_setattro */
181     0,                                      /* tp_as_buffer */
182     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
183     ObjectPath_tp_doc,                      /* tp_doc */
184     0,                                      /* tp_traverse */
185     0,                                      /* tp_clear */
186     0,                                      /* tp_richcompare */
187     0,                                      /* tp_weaklistoffset */
188     0,                                      /* tp_iter */
189     0,                                      /* tp_iternext */
190     0,                                      /* tp_methods */
191     0,                                      /* tp_members */
192     0,                                      /* tp_getset */
193     DEFERRED_ADDRESS(&DBusPyStrBase_Type),   /* tp_base */
194     0,                                      /* tp_dict */
195     0,                                      /* tp_descr_get */
196     0,                                      /* tp_descr_set */
197     0,                                      /* tp_dictoffset */
198     0,                                      /* tp_init */
199     0,                                      /* tp_alloc */
200     ObjectPath_tp_new,                      /* tp_new */
203 /* Unicode string representation ==================================== */
205 PyDoc_STRVAR(String_tp_doc,
206 "A string represented using Unicode - a subtype of `unicode`.\n"
207 "\n"
208 "All strings on D-Bus are required to be valid Unicode; in the \"wire\n"
209 "protocol\" they're transported as UTF-8.\n"
210 "\n"
211 "By default, when strings are converted from D-Bus to Python, they\n"
212 "come out as this class. If you prefer to get UTF-8 strings (as instances\n"
213 "of a subtype of `str`) or you want to avoid the conversion overhead of\n"
214 "going from UTF-8 to Python's internal Unicode representation, see the\n"
215 "documentation for `dbus.UTF8String`.\n"
216 "\n"
217 "Constructor::\n"
218 "\n"
219 "    String(value: str or unicode[, variant_level: int]) -> String\n"
220 "\n"
221 "variant_level must be non-negative; the default is 0.\n"
222 "\n"
223 ":IVariables:\n"
224 "  `variant_level` : int\n"
225 "    Indicates how many nested Variant containers this object\n"
226 "    is contained in: if a message's wire format has a variant containing a\n"
227 "    variant containing a string, this is represented in Python by a\n"
228 "    String or UTF8String with variant_level==2.\n"
231 static PyObject *
232 String_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
234     PyObject *self;
235     PyObject *variantness = NULL;
236     static char *argnames[] = {"variant_level", NULL};
238     if (PyTuple_Size(args) > 1) {
239         PyErr_SetString(PyExc_TypeError,
240                         "__new__ takes at most one positional parameter");
241         return NULL;
242     }
243     if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs,
244                                      "|O!:__new__", argnames,
245                                      &PyInt_Type, &variantness)) return NULL;
246     if (!variantness) {
247         variantness = PyInt_FromLong(0);
248         if (!variantness) return NULL;
249     }
250     if (PyInt_AS_LONG(variantness) < 0) {
251         PyErr_SetString(PyExc_ValueError,
252                         "variant_level must be non-negative");
253         return NULL;
254     }
256     self = (PyUnicode_Type.tp_new)(cls, args, NULL);
257     if (self) {
258         PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness);
259     }
260     return self;
263 static PyObject *
264 String_tp_repr(PyObject *self)
266     PyObject *parent_repr = (PyUnicode_Type.tp_repr)(self);
267     PyObject *vl_obj;
268     PyObject *my_repr;
269     long variant_level;
271     if (!parent_repr) return NULL;
272     vl_obj = PyObject_GetAttr(self, dbus_py_variant_level_const);
273     if (!vl_obj) return NULL;
274     variant_level = PyInt_AsLong(vl_obj);
275     if (variant_level > 0) {
276         my_repr = PyString_FromFormat("%s(%s, variant_level=%ld)",
277                                       self->ob_type->tp_name,
278                                       PyString_AS_STRING(parent_repr),
279                                       variant_level);
280     }
281     else {
282         my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
283                                       PyString_AS_STRING(parent_repr));
284     }
285     /* whether my_repr is NULL or not: */
286     Py_DECREF(parent_repr);
287     return my_repr;
290 PyTypeObject DBusPyString_Type = {
291     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
292     0,
293     "dbus.String",
294     INT_MAX, /* placeholder */
295     0,
296     0,                                      /* tp_dealloc */
297     0,                                      /* tp_print */
298     0,                                      /* tp_getattr */
299     0,                                      /* tp_setattr */
300     0,                                      /* tp_compare */
301     String_tp_repr,                         /* tp_repr */
302     0,                                      /* tp_as_number */
303     0,                                      /* tp_as_sequence */
304     0,                                      /* tp_as_mapping */
305     0,                                      /* tp_hash */
306     0,                                      /* tp_call */
307     0,                                      /* tp_str */
308     PyObject_GenericGetAttr,                /* tp_getattro */
309     dbus_py_immutable_setattro,                /* tp_setattro */
310     0,                                      /* tp_as_buffer */
311     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
312     String_tp_doc,                          /* tp_doc */
313     0,                                      /* tp_traverse */
314     0,                                      /* tp_clear */
315     0,                                      /* tp_richcompare */
316     0,                                      /* tp_weaklistoffset */
317     0,                                      /* tp_iter */
318     0,                                      /* tp_iternext */
319     0,                                      /* tp_methods */
320     0,                                      /* tp_members */
321     0,                                      /* tp_getset */
322     DEFERRED_ADDRESS(&PyUnicode_Type),      /* tp_base */
323     0,                                      /* tp_dict */
324     0,                                      /* tp_descr_get */
325     0,                                      /* tp_descr_set */
326     -sizeof(void *),                        /* tp_dictoffset */
327     0,                                      /* tp_init */
328     0,                                      /* tp_alloc */
329     String_tp_new,                          /* tp_new */
332 dbus_bool_t
333 dbus_py_init_string_types(void)
335     DBusPyString_Type.tp_basicsize = PyUnicode_Type.tp_basicsize
336                                      + 2*sizeof(PyObject *) - 1;
337     DBusPyString_Type.tp_basicsize /= sizeof(PyObject *);
338     DBusPyString_Type.tp_basicsize *= sizeof(PyObject *);
339     DBusPyString_Type.tp_base = &PyUnicode_Type;
340     if (PyType_Ready(&DBusPyString_Type) < 0) return 0;
341     DBusPyString_Type.tp_print = NULL;
343     DBusPyUTF8String_Type.tp_basicsize = PyUnicode_Type.tp_basicsize
344                                   + 2*sizeof(PyObject *) - 1;
345     DBusPyUTF8String_Type.tp_basicsize /= sizeof(PyObject *);
346     DBusPyUTF8String_Type.tp_basicsize *= sizeof(PyObject *);
347     DBusPyUTF8String_Type.tp_base = &DBusPyStrBase_Type;
348     if (PyType_Ready(&DBusPyUTF8String_Type) < 0) return 0;
349     DBusPyUTF8String_Type.tp_print = NULL;
351     DBusPyObjectPath_Type.tp_base = &DBusPyStrBase_Type;
352     if (PyType_Ready(&DBusPyObjectPath_Type) < 0) return 0;
353     DBusPyObjectPath_Type.tp_print = NULL;
355     DBusPyBoolean_Type.tp_base = &DBusPyIntBase_Type;
356     if (PyType_Ready(&DBusPyBoolean_Type) < 0) return 0;
357     DBusPyBoolean_Type.tp_print = NULL;
359     return 1;
362 dbus_bool_t
363 dbus_py_insert_string_types(PyObject *this_module)
365     Py_INCREF(&DBusPyObjectPath_Type);
366     Py_INCREF(&DBusPyUTF8String_Type);
367     Py_INCREF(&DBusPyString_Type);
368     if (PyModule_AddObject(this_module, "ObjectPath",
369                            (PyObject *)&DBusPyObjectPath_Type) < 0) return 0;
370     if (PyModule_AddObject(this_module, "UTF8String",
371                            (PyObject *)&DBusPyUTF8String_Type) < 0) return 0;
372     if (PyModule_AddObject(this_module, "String",
373                            (PyObject *)&DBusPyString_Type) < 0) return 0;
375     return 1;
378 /* vim:set ft=c cino< sw=4 sts=4 et: */