v0.166.0
 1from typing import TYPE_CHECKING
 2
 3if TYPE_CHECKING:
 4    from .client import ClientResponse
 5
 6__all__ = ["AppRequiredError", "RedirectCycleError", "require_app"]
 7
 8
 9class RedirectCycleError(Exception):
10    """The test client has been asked to follow a redirect loop."""
11
12    def __init__(self, message: str, last_response: ClientResponse) -> None:
13        super().__init__(message)
14        self.last_response = last_response
15
16
17class AppRequiredError(RuntimeError):
18    """A test helper that needs a Plain app was used in a run without one."""
19
20
21def require_app(helper: str) -> None:
22    """Raise `AppRequiredError` unless a Plain app is set up.
23
24    `helper` is the name to put in the message: `require_app("Client")`.
25    """
26    from plain.packages import packages_registry
27
28    if packages_registry.ready:
29        return
30
31    raise AppRequiredError(
32        f"{helper} needs a Plain app, and this run has none: there is no"
33        " `app/` directory where `plain test` was started, so the tests are"
34        " running on their own. That works for code that doesn't touch the"
35        " app — `raises`, `@cases`, `@skip`, `@tag`, `skip_test`, `patch`,"
36        " and bare `assert` all do. Anything that reads settings, routes or"
37        f" the database does not. To use {helper}, run `plain test` from the"
38        " directory that holds `app/`."
39    )