Skip to content

Commit 9d47b00

Browse files
committed
Added name validation functions to low-level API
Requires libsystemd version higher or equal than 246
1 parent b1f28a6 commit 9d47b00

File tree

3 files changed

+161
-2
lines changed

3 files changed

+161
-2
lines changed

src/sdbus/sd_bus_internals.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,22 @@ def add_exception_mapping(exc: Exception, /) -> None:
242242
... # We want to be able to generate docs without module
243243

244244

245+
def is_interface_name_valid(string_to_check: str, /) -> bool:
246+
raise NotImplementedError(__STUB_ERROR)
247+
248+
249+
def is_service_name_valid(string_to_check: str, /) -> bool:
250+
raise NotImplementedError(__STUB_ERROR)
251+
252+
253+
def is_member_name_valid(string_to_check: str, /) -> bool:
254+
raise NotImplementedError(__STUB_ERROR)
255+
256+
257+
def is_object_path_valid(string_to_check: str, /) -> bool:
258+
raise NotImplementedError(__STUB_ERROR)
259+
260+
245261
class SdBusBaseError(Exception):
246262
...
247263

src/sdbus/sd_bus_internals_funcs.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,98 @@ static PyObject* add_exception_mapping(PyObject* Py_UNUSED(self), PyObject* args
156156
Py_RETURN_NONE;
157157
}
158158

159+
#ifndef Py_LIMITED_API
160+
static PyObject* is_interface_name_valid(PyObject* Py_UNUSED(self), PyObject* const* args, Py_ssize_t nargs) {
161+
SD_BUS_PY_CHECK_ARGS_NUMBER(1);
162+
SD_BUS_PY_CHECK_ARG_CHECK_FUNC(0, PyUnicode_Check);
163+
164+
const char* string_to_check = SD_BUS_PY_UNICODE_AS_CHAR_PTR(args[0]);
165+
#else
166+
static PyObject* is_interface_name_valid(PyObject* Py_UNUSED(self), PyObject* args) {
167+
const char* string_to_check = NULL;
168+
CALL_PYTHON_BOOL_CHECK(PyArg_ParseTuple(args, "s", &string_to_check, NULL));
169+
#endif
170+
#ifdef LIBSYSTEMD_NO_VALIDATION_FUNCS
171+
PyErr_SetString(PyExc_NotImplementedError, "libsystemd < 246 does not support validation functions");
172+
return NULL;
173+
#else
174+
if (sd_bus_interface_name_is_valid(string_to_check)) {
175+
Py_RETURN_TRUE;
176+
} else {
177+
Py_RETURN_FALSE;
178+
}
179+
#endif
180+
}
181+
182+
#ifndef Py_LIMITED_API
183+
static PyObject* is_service_name_valid(PyObject* Py_UNUSED(self), PyObject* const* args, Py_ssize_t nargs) {
184+
SD_BUS_PY_CHECK_ARGS_NUMBER(1);
185+
SD_BUS_PY_CHECK_ARG_CHECK_FUNC(0, PyUnicode_Check);
186+
187+
const char* string_to_check = SD_BUS_PY_UNICODE_AS_CHAR_PTR(args[0]);
188+
#else
189+
static PyObject* is_service_name_valid(PyObject* Py_UNUSED(self), PyObject* args) {
190+
const char* string_to_check = NULL;
191+
CALL_PYTHON_BOOL_CHECK(PyArg_ParseTuple(args, "s", &string_to_check, NULL));
192+
#endif
193+
#ifdef LIBSYSTEMD_NO_VALIDATION_FUNCS
194+
PyErr_SetString(PyExc_NotImplementedError, "libsystemd < 246 does not support validation functions");
195+
return NULL;
196+
#else
197+
if (sd_bus_service_name_is_valid(string_to_check)) {
198+
Py_RETURN_TRUE;
199+
} else {
200+
Py_RETURN_FALSE;
201+
}
202+
#endif
203+
}
204+
205+
#ifndef Py_LIMITED_API
206+
static PyObject* is_member_name_valid(PyObject* Py_UNUSED(self), PyObject* const* args, Py_ssize_t nargs) {
207+
SD_BUS_PY_CHECK_ARGS_NUMBER(1);
208+
SD_BUS_PY_CHECK_ARG_CHECK_FUNC(0, PyUnicode_Check);
209+
210+
const char* string_to_check = SD_BUS_PY_UNICODE_AS_CHAR_PTR(args[0]);
211+
#else
212+
static PyObject* is_member_name_valid(PyObject* Py_UNUSED(self), PyObject* args) {
213+
const char* string_to_check = NULL;
214+
CALL_PYTHON_BOOL_CHECK(PyArg_ParseTuple(args, "s", &string_to_check, NULL));
215+
#endif
216+
#ifdef LIBSYSTEMD_NO_VALIDATION_FUNCS
217+
PyErr_SetString(PyExc_NotImplementedError, "libsystemd < 246 does not support validation functions");
218+
return NULL;
219+
#else
220+
if (sd_bus_member_name_is_valid(string_to_check)) {
221+
Py_RETURN_TRUE;
222+
} else {
223+
Py_RETURN_FALSE;
224+
}
225+
#endif
226+
}
227+
228+
#ifndef Py_LIMITED_API
229+
static PyObject* is_object_path_valid(PyObject* Py_UNUSED(self), PyObject* const* args, Py_ssize_t nargs) {
230+
SD_BUS_PY_CHECK_ARGS_NUMBER(1);
231+
SD_BUS_PY_CHECK_ARG_CHECK_FUNC(0, PyUnicode_Check);
232+
233+
const char* string_to_check = SD_BUS_PY_UNICODE_AS_CHAR_PTR(args[0]);
234+
#else
235+
static PyObject* is_object_path_valid(PyObject* Py_UNUSED(self), PyObject* args) {
236+
const char* string_to_check = NULL;
237+
CALL_PYTHON_BOOL_CHECK(PyArg_ParseTuple(args, "s", &string_to_check, NULL));
238+
#endif
239+
#ifdef LIBSYSTEMD_NO_VALIDATION_FUNCS
240+
PyErr_SetString(PyExc_NotImplementedError, "libsystemd < 246 does not support validation functions");
241+
return NULL;
242+
#else
243+
if (sd_bus_object_path_is_valid(string_to_check)) {
244+
Py_RETURN_TRUE;
245+
} else {
246+
Py_RETURN_FALSE;
247+
}
248+
#endif
249+
}
250+
159251
PyMethodDef SdBusPyInternal_methods[] = {
160252
{"sd_bus_open", (PyCFunction)sd_bus_py_open, METH_NOARGS,
161253
"Open dbus connection. Session bus running as user or system bus as "
@@ -168,5 +260,9 @@ PyMethodDef SdBusPyInternal_methods[] = {
168260
{"encode_object_path", (SD_BUS_PY_FUNC_TYPE)encode_object_path, SD_BUS_PY_METH, "Encode object path with object path prefix and arbitrary string"},
169261
{"decode_object_path", (SD_BUS_PY_FUNC_TYPE)decode_object_path, SD_BUS_PY_METH, "Decode object path with object path prefix and arbitrary string"},
170262
{"add_exception_mapping", (SD_BUS_PY_FUNC_TYPE)add_exception_mapping, SD_BUS_PY_METH, "Add exception to the mapping of dbus error names"},
263+
{"is_interface_name_valid", (SD_BUS_PY_FUNC_TYPE)is_interface_name_valid, SD_BUS_PY_METH, "Is the string valid interface name?"},
264+
{"is_service_name_valid", (SD_BUS_PY_FUNC_TYPE)is_service_name_valid, SD_BUS_PY_METH, "Is the string valid service name?"},
265+
{"is_member_name_valid", (SD_BUS_PY_FUNC_TYPE)is_member_name_valid, SD_BUS_PY_METH, "Is the string valid member name?"},
266+
{"is_object_path_valid", (SD_BUS_PY_FUNC_TYPE)is_object_path_valid, SD_BUS_PY_METH, "Is the string valid object path?"},
171267
{NULL, NULL, 0, NULL},
172268
};

test/test_low_level_api.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,63 @@
1919
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2020
from __future__ import annotations
2121

22-
from unittest import main
22+
from unittest import SkipTest, main
2323

24-
from sdbus.sd_bus_internals import SdBus
24+
from sdbus.sd_bus_internals import (
25+
SdBus,
26+
is_interface_name_valid,
27+
is_member_name_valid,
28+
is_object_path_valid,
29+
is_service_name_valid,
30+
)
2531
from sdbus.unittest import IsolatedDbusTestCase
2632

2733

2834
class TestDbusTypes(IsolatedDbusTestCase):
2935
def test_init_bus(self) -> None:
3036
SdBus()
3137

38+
def test_validation_funcs(self) -> None:
39+
try:
40+
self.assertTrue(
41+
is_interface_name_valid('org.example.test')
42+
)
43+
44+
self.assertFalse(
45+
is_interface_name_valid('Not very valid 😀')
46+
)
47+
48+
self.assertTrue(
49+
is_service_name_valid('org.example.test')
50+
)
51+
52+
self.assertFalse(
53+
is_service_name_valid('Not very valid 😀')
54+
)
55+
56+
self.assertTrue(
57+
is_member_name_valid('GetSomething')
58+
)
59+
60+
self.assertFalse(
61+
is_member_name_valid('no.dots.in.member.names')
62+
)
63+
64+
self.assertTrue(
65+
is_object_path_valid('/test')
66+
)
67+
68+
self.assertFalse(
69+
is_object_path_valid('no.dots.in.object.paths')
70+
)
71+
except NotImplementedError:
72+
raise SkipTest(
73+
(
74+
"Validation funcs not implemented. "
75+
"Probably too old libsystemd. (< 246)"
76+
)
77+
)
78+
3279

3380
if __name__ == "__main__":
3481
main()

0 commit comments

Comments
 (0)