200 lines
5.1 KiB
Python
200 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)
|