diff --git a/qubes/api/__init__.py b/qubes/api/__init__.py index da7516d76..e6de23308 100644 --- a/qubes/api/__init__.py +++ b/qubes/api/__init__.py @@ -240,8 +240,13 @@ def fire_event_for_filter(self, iterable, **kwargs): return apply_filters(iterable, self.fire_event_for_permission(**kwargs)) @staticmethod - def enforce(predicate): - """An assert replacement, but works even with optimisations.""" + def enforce(predicate: bool) -> None: + """If predicate is false, raise an exception to terminate handling + the request. + + This will raise :py:class:`PermissionDenied` if the predicate is false. + See the documentation of that class for details. + """ if not predicate: raise PermissionDenied() diff --git a/qubes/exc.py b/qubes/exc.py index f0b6322e3..3a198facb 100644 --- a/qubes/exc.py +++ b/qubes/exc.py @@ -264,8 +264,29 @@ def __str__(self): class ProtocolError(AssertionError): - """Raised when something is wrong with data received""" + """Raised when something is wrong with data received. + This does not provide any useful information to the client making + the request. Therefore, it should only be raised if there is a client + *programming* error, such as passing an argument to a request that does + not take an argument. It should not be used to reject requests that are + valid, but which qubesd is refusing to process. Instead, raise a + subclass of :py:class:`QubesException` with a useful error message. + + TODO: figure out when this class should be used, and when + :py:class:`PermissionDenied` should be used. + """ class PermissionDenied(Exception): - """Raised deliberately by handlers when we decide not to cooperate""" + """Raised deliberately by handlers to indicate a malformed client request. + + This does not provide any useful information to the client making + the request. Therefore, it should only be raised if there is a client + *programming* error, such as passing an argument to a request that does + not take an argument. It should not be used to reject requests that are + valid, but which qubesd is refusing to process. Instead, raise a + subclass of :py:class:`QubesException` with a useful error message. + + TODO: figure out when this class should be used, and when + :py:class:`ProtocolError` should be used. + """