idasit/dbus_fast/validators.py
bparodi@lezzo.org 41c244e903 first commit
2024-12-14 14:55:37 +01:00

199 lines
5.1 KiB
Python

import re
from functools import lru_cache
from .errors import (
InvalidBusNameError,
InvalidInterfaceNameError,
InvalidMemberNameError,
InvalidObjectPathError,
)
_bus_name_re = re.compile(r"^[A-Za-z_-][A-Za-z0-9_-]*$")
_path_re = re.compile(r"^[A-Za-z0-9_]+$")
_element_re = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
_member_re = re.compile(r"^[A-Za-z_][A-Za-z0-9_-]*$")
@lru_cache(maxsize=32)
def is_bus_name_valid(name: str) -> bool:
"""Whether this is a valid bus name.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus
:param name: The bus name to validate.
:type name: str
:returns: Whether the name is a valid bus name.
:rtype: bool
"""
if not isinstance(name, str):
return False # type: ignore[unreachable]
if not name or len(name) > 255:
return False
if name.startswith(":"):
# a unique bus name
return True
if name.startswith("."):
return False
if name.find(".") == -1:
return False
for element in name.split("."):
if _bus_name_re.search(element) is None:
return False
return True
@lru_cache(maxsize=1024)
def is_object_path_valid(path: str) -> bool:
"""Whether this is a valid object path.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
:param path: The object path to validate.
:type path: str
:returns: Whether the object path is valid.
:rtype: bool
"""
if not isinstance(path, str):
return False # type: ignore[unreachable]
if not path:
return False
if not path.startswith("/"):
return False
if len(path) == 1:
return True
for element in path[1:].split("/"):
if _path_re.search(element) is None:
return False
return True
@lru_cache(maxsize=32)
def is_interface_name_valid(name: str) -> bool:
"""Whether this is a valid interface name.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface
:param name: The interface name to validate.
:type name: str
:returns: Whether the name is a valid interface name.
:rtype: bool
"""
if not isinstance(name, str):
return False # type: ignore[unreachable]
if not name or len(name) > 255:
return False
if name.startswith("."):
return False
if name.find(".") == -1:
return False
for element in name.split("."):
if _element_re.search(element) is None:
return False
return True
@lru_cache(maxsize=512)
def is_member_name_valid(member: str) -> bool:
"""Whether this is a valid member name.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-member
:param member: The member name to validate.
:type member: str
:returns: Whether the name is a valid member name.
:rtype: bool
"""
if not isinstance(member, str):
return False # type: ignore[unreachable]
if not member or len(member) > 255:
return False
if _member_re.search(member) is None:
return False
return True
@lru_cache(maxsize=32)
def assert_bus_name_valid(name: str) -> None:
"""Raise an error if this is not a valid bus name.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus
:param name: The bus name to validate.
:type name: str
:raises:
- :class:`InvalidBusNameError` - If this is not a valid bus name.
"""
if not is_bus_name_valid(name):
raise InvalidBusNameError(name)
@lru_cache(maxsize=1024)
def assert_object_path_valid(path: str) -> None:
"""Raise an error if this is not a valid object path.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
:param path: The object path to validate.
:type path: str
:raises:
- :class:`InvalidObjectPathError` - If this is not a valid object path.
"""
if not is_object_path_valid(path):
raise InvalidObjectPathError(path)
@lru_cache(maxsize=32)
def assert_interface_name_valid(name: str) -> None:
"""Raise an error if this is not a valid interface name.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface
:param name: The interface name to validate.
:type name: str
:raises:
- :class:`InvalidInterfaceNameError` - If this is not a valid object path.
"""
if not is_interface_name_valid(name):
raise InvalidInterfaceNameError(name)
@lru_cache(maxsize=512)
def assert_member_name_valid(member: str) -> None:
"""Raise an error if this is not a valid member name.
.. seealso:: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-member
:param member: The member name to validate.
:type member: str
:raises:
- :class:`InvalidMemberNameError` - If this is not a valid object path.
"""
if not is_member_name_valid(member):
raise InvalidMemberNameError(member)