phlo-postgres 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/PKG-INFO +1 -1
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/pyproject.toml +1 -1
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/__init__.py +1 -1
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/cli.py +25 -8
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres.egg-info/PKG-INFO +1 -1
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/tests/test_postgres_cli.py +32 -6
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/README.md +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/setup.cfg +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/authorization.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/cli_plugin.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/exporter_service.yaml +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/plugin.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/publish_target.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/resource.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/service.yaml +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/settings.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres/volume_setup.yaml +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres.egg-info/SOURCES.txt +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres.egg-info/dependency_links.txt +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres.egg-info/entry_points.txt +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres.egg-info/requires.txt +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/src/phlo_postgres.egg-info/top_level.txt +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/tests/test_authorization.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/tests/test_integration_postgres.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/tests/test_postgres_plugin.py +0 -0
- {phlo_postgres-0.3.0 → phlo_postgres-0.3.1}/tests/test_resource.py +0 -0
|
@@ -24,12 +24,19 @@ from subprocess import TimeoutExpired
|
|
|
24
24
|
import click
|
|
25
25
|
|
|
26
26
|
from phlo.cli.commands.services.utils import (
|
|
27
|
-
|
|
27
|
+
ensure_compose_project,
|
|
28
28
|
require_container_backend as _require_selected_container_backend,
|
|
29
29
|
)
|
|
30
30
|
from phlo.cli.infrastructure.command import CommandError, run_command
|
|
31
31
|
from phlo.cli.infrastructure.compose import compose_base_cmd
|
|
32
32
|
from phlo.cli.infrastructure.utils import get_project_name
|
|
33
|
+
from phlo.cli.output import (
|
|
34
|
+
command_failed_error,
|
|
35
|
+
empty_file_error,
|
|
36
|
+
exclusive_options_error,
|
|
37
|
+
file_read_error,
|
|
38
|
+
)
|
|
39
|
+
from phlo.cli.output import missing_query_error
|
|
33
40
|
from phlo_postgres.settings import get_settings
|
|
34
41
|
|
|
35
42
|
|
|
@@ -56,18 +63,18 @@ def _read_sql(*, query: str | None, file: Path | None) -> str:
|
|
|
56
63
|
|
|
57
64
|
"""
|
|
58
65
|
if query and file:
|
|
59
|
-
raise
|
|
66
|
+
raise exclusive_options_error("an inline query", "--file")
|
|
60
67
|
if file is not None:
|
|
61
68
|
try:
|
|
62
69
|
sql = file.read_text(encoding="utf-8")
|
|
63
70
|
except OSError as exc:
|
|
64
|
-
raise
|
|
71
|
+
raise file_read_error(file) from exc
|
|
65
72
|
if sql.strip():
|
|
66
73
|
return sql
|
|
67
|
-
raise
|
|
74
|
+
raise empty_file_error(file)
|
|
68
75
|
if query and query.strip():
|
|
69
76
|
return query
|
|
70
|
-
raise
|
|
77
|
+
raise missing_query_error(command_hint='phlo postgres query "SELECT 1"')
|
|
71
78
|
|
|
72
79
|
|
|
73
80
|
def _require_container_backend() -> None:
|
|
@@ -93,7 +100,7 @@ def _postgres_exec_base(*, tty: bool) -> list[str]:
|
|
|
93
100
|
>>> # Returns: ['docker', 'compose', '-p', 'phlo', '-f', '...', 'exec', '-t', 'postgres']
|
|
94
101
|
|
|
95
102
|
"""
|
|
96
|
-
phlo_dir =
|
|
103
|
+
phlo_dir = ensure_compose_project()
|
|
97
104
|
project_name = get_project_name()
|
|
98
105
|
cmd = compose_base_cmd(phlo_dir=phlo_dir, project_name=project_name)
|
|
99
106
|
cmd.append("exec")
|
|
@@ -244,7 +251,12 @@ def postgres_query(
|
|
|
244
251
|
)
|
|
245
252
|
except CommandError as exc:
|
|
246
253
|
stderr = exc.stderr.strip()
|
|
247
|
-
raise
|
|
254
|
+
raise command_failed_error(
|
|
255
|
+
"psql",
|
|
256
|
+
exit_code=exc.returncode,
|
|
257
|
+
details=[stderr] if stderr else ["PostgreSQL did not complete the query."],
|
|
258
|
+
run="phlo services status postgres",
|
|
259
|
+
) from exc
|
|
248
260
|
except TimeoutExpired as exc:
|
|
249
261
|
raise click.ClickException(f"Query timed out after {timeout_seconds} seconds.") from exc
|
|
250
262
|
|
|
@@ -302,7 +314,12 @@ def postgres_dump(
|
|
|
302
314
|
)
|
|
303
315
|
except CommandError as exc:
|
|
304
316
|
stderr = exc.stderr.strip()
|
|
305
|
-
raise
|
|
317
|
+
raise command_failed_error(
|
|
318
|
+
"pg_dump",
|
|
319
|
+
exit_code=exc.returncode,
|
|
320
|
+
details=[stderr] if stderr else ["PostgreSQL did not create the dump."],
|
|
321
|
+
run="phlo services status postgres",
|
|
322
|
+
) from exc
|
|
306
323
|
except TimeoutExpired as exc:
|
|
307
324
|
raise click.ClickException(f"Dump timed out after {timeout_seconds} seconds.") from exc
|
|
308
325
|
|
|
@@ -42,7 +42,9 @@ def test_postgres_query_runs_psql(monkeypatch) -> None:
|
|
|
42
42
|
]
|
|
43
43
|
return CompletedProcess(cmd, 0, stdout="1\n", stderr="")
|
|
44
44
|
|
|
45
|
-
monkeypatch.setattr(
|
|
45
|
+
monkeypatch.setattr(
|
|
46
|
+
"phlo_postgres.cli.ensure_compose_project", lambda: Path("/tmp/project/.phlo")
|
|
47
|
+
)
|
|
46
48
|
monkeypatch.setattr("phlo_postgres.cli.get_project_name", lambda: "demo")
|
|
47
49
|
monkeypatch.setattr(
|
|
48
50
|
"phlo_postgres.cli.compose_base_cmd",
|
|
@@ -56,6 +58,20 @@ def test_postgres_query_runs_psql(monkeypatch) -> None:
|
|
|
56
58
|
assert result.output == "1\n"
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
def test_postgres_query_requires_initialized_services(monkeypatch, tmp_path) -> None:
|
|
62
|
+
phlo_dir = tmp_path / ".phlo"
|
|
63
|
+
phlo_dir.mkdir()
|
|
64
|
+
monkeypatch.chdir(tmp_path)
|
|
65
|
+
|
|
66
|
+
result = CliRunner().invoke(postgres_group, ["query", "SELECT 1"])
|
|
67
|
+
|
|
68
|
+
assert result.exit_code != 0
|
|
69
|
+
assert "Error: Phlo services have not been initialized" in result.output
|
|
70
|
+
assert "Missing: .phlo/docker-compose.yml" in result.output
|
|
71
|
+
assert "Run: phlo services init" in result.output
|
|
72
|
+
assert "couldn't find env file" not in result.output
|
|
73
|
+
|
|
74
|
+
|
|
59
75
|
def test_postgres_dump_writes_gzip_file(monkeypatch, tmp_path) -> None:
|
|
60
76
|
output_file = tmp_path / "backup.sql.gz"
|
|
61
77
|
|
|
@@ -65,7 +81,9 @@ def test_postgres_dump_writes_gzip_file(monkeypatch, tmp_path) -> None:
|
|
|
65
81
|
assert cmd[-4:] == ["pg_dump", "-U", "phlo", "phlo"]
|
|
66
82
|
return CompletedProcess(cmd, 0, stdout="CREATE TABLE test ();", stderr="")
|
|
67
83
|
|
|
68
|
-
monkeypatch.setattr(
|
|
84
|
+
monkeypatch.setattr(
|
|
85
|
+
"phlo_postgres.cli.ensure_compose_project", lambda: Path("/tmp/project/.phlo")
|
|
86
|
+
)
|
|
69
87
|
monkeypatch.setattr("phlo_postgres.cli.get_project_name", lambda: "demo")
|
|
70
88
|
monkeypatch.setattr(
|
|
71
89
|
"phlo_postgres.cli.compose_base_cmd",
|
|
@@ -86,7 +104,9 @@ def test_postgres_restore_reads_file(monkeypatch, tmp_path) -> None:
|
|
|
86
104
|
input_file.write_text("SELECT 1;", encoding="utf-8")
|
|
87
105
|
captured: list[tuple[list[str], str]] = []
|
|
88
106
|
|
|
89
|
-
monkeypatch.setattr(
|
|
107
|
+
monkeypatch.setattr(
|
|
108
|
+
"phlo_postgres.cli.ensure_compose_project", lambda: Path("/tmp/project/.phlo")
|
|
109
|
+
)
|
|
90
110
|
monkeypatch.setattr("phlo_postgres.cli.get_project_name", lambda: "demo")
|
|
91
111
|
monkeypatch.setattr(
|
|
92
112
|
"phlo_postgres.cli.compose_base_cmd",
|
|
@@ -136,7 +156,9 @@ def test_postgres_vacuum_runs_vacuumdb(monkeypatch) -> None:
|
|
|
136
156
|
assert cmd[-5:] == ["vacuumdb", "-U", "phlo", "-z", "phlo"]
|
|
137
157
|
return CompletedProcess(cmd, 0, stdout="VACUUM\n", stderr="")
|
|
138
158
|
|
|
139
|
-
monkeypatch.setattr(
|
|
159
|
+
monkeypatch.setattr(
|
|
160
|
+
"phlo_postgres.cli.ensure_compose_project", lambda: Path("/tmp/project/.phlo")
|
|
161
|
+
)
|
|
140
162
|
monkeypatch.setattr("phlo_postgres.cli.get_project_name", lambda: "demo")
|
|
141
163
|
monkeypatch.setattr(
|
|
142
164
|
"phlo_postgres.cli.compose_base_cmd",
|
|
@@ -153,7 +175,9 @@ def test_postgres_vacuum_runs_vacuumdb(monkeypatch) -> None:
|
|
|
153
175
|
def test_postgres_shell_passthrough(monkeypatch) -> None:
|
|
154
176
|
captured: list[list[str]] = []
|
|
155
177
|
|
|
156
|
-
monkeypatch.setattr(
|
|
178
|
+
monkeypatch.setattr(
|
|
179
|
+
"phlo_postgres.cli.ensure_compose_project", lambda: Path("/tmp/project/.phlo")
|
|
180
|
+
)
|
|
157
181
|
monkeypatch.setattr("phlo_postgres.cli.get_project_name", lambda: "demo")
|
|
158
182
|
monkeypatch.setattr(
|
|
159
183
|
"phlo_postgres.cli.compose_base_cmd",
|
|
@@ -197,7 +221,9 @@ def test_postgres_query_timeout(monkeypatch) -> None:
|
|
|
197
221
|
return CompletedProcess(cmd, 0, stdout="", stderr="")
|
|
198
222
|
raise TimeoutExpired(cmd=cmd, timeout=30)
|
|
199
223
|
|
|
200
|
-
monkeypatch.setattr(
|
|
224
|
+
monkeypatch.setattr(
|
|
225
|
+
"phlo_postgres.cli.ensure_compose_project", lambda: Path("/tmp/project/.phlo")
|
|
226
|
+
)
|
|
201
227
|
monkeypatch.setattr("phlo_postgres.cli.get_project_name", lambda: "demo")
|
|
202
228
|
monkeypatch.setattr(
|
|
203
229
|
"phlo_postgres.cli.compose_base_cmd",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|