1from importlib.util import find_spec
2from pathlib import Path
3
4from .dotenv import load_dotenv_files
5from .utils import has_pyproject_toml
6
7
8def setup() -> None:
9 # Make sure our clis are registered
10 # since this isn't an installed app
11 from .cli import cli # noqa
12 from .precommit import cli # noqa
13 from .contribute import cli # noqa
14 from .services import auto_start_services
15
16 has_postgres = find_spec("plain.postgres") is not None
17
18 # `plain db` manages Postgres databases, so it only exists when
19 # plain.postgres is installed.
20 if has_postgres:
21 from .db import cli # noqa
22
23 load_dotenv_files()
24
25 # Resolve a database URL before services start, so DB-dependent services
26 # inherit it. No-op when the user configured their own or when managed
27 # Postgres is off; skipped entirely when plain.postgres isn't installed.
28 if has_postgres:
29 _ensure_managed_postgres()
30
31 # Auto-start dev services for commands that need the runtime
32 auto_start_services()
33
34
35def _ensure_managed_postgres() -> None:
36 # Located by walking up from the working directory: this runs before
37 # settings are configured, so `APP_PATH` isn't available yet. `plain db`
38 # walks up from the app instead and must land in the same place — see
39 # `find_project_root`.
40 from .state import find_project_root
41
42 project_root = find_project_root(Path.cwd())
43 if not has_pyproject_toml(project_root):
44 return
45
46 from .postgres.resolve import ensure_postgres
47
48 try:
49 ensure_postgres(project_root)
50 except Exception as e:
51 # A database problem should surface when something actually needs the
52 # database, with that command's own error — not as a failure of every
53 # command that merely passed through setup().
54 import click
55
56 click.secho(f"Managed Postgres unavailable: {e}", fg="yellow", err=True)