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.
3 * Copyright (C) 2006 Collabora Ltd.
5 * Licensed under the Academic Free License version 2.1
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.
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.
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
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))
85 "dbus.UTF8String",
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;
158 return (DBusPyStrBase_Type.tp_new)(cls, args, kwargs);
161 PyTypeObject DBusPyObjectPath_Type = {
162 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
164 "dbus.ObjectPath",
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;
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;
250 if (PyInt_AS_LONG(variantness) < 0) {
251 PyErr_SetString(PyExc_ValueError,
252 "variant_level must be non-negative");
253 return NULL;
256 self = (PyUnicode_Type.tp_new)(cls, args, NULL);
257 if (self) {
258 PyObject_GenericSetAttr(self, dbus_py_variant_level_const, variantness);
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);
281 else {
282 my_repr = PyString_FromFormat("%s(%s)", self->ob_type->tp_name,
283 PyString_AS_STRING(parent_repr));
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))
293 "dbus.String",
294 INT_MAX, /* placeholder */
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: */