djangoplay-cli 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.4
2
+ Name: djangoplay-cli
3
+ Version: 1.0.0
4
+ Summary: CLI tools for DjangoPlay developers. 'djangoplay-cli' provides a lightweight command-line interface for developers working on the 'DjangoPlay ecosystem'.
5
+ Requires-Python: >=3.11
6
+ License-File: LICENSE
7
+ Requires-Dist: typer>=0.9
8
+ Requires-Dist: rich>=13
9
+ Requires-Dist: pyyaml>=6.0
10
+ Dynamic: license-file
@@ -0,0 +1,29 @@
1
+ djangoplay_cli-1.0.0.dist-info/licenses/LICENSE,sha256=GLJEF-NBZTCkIR0TUMpun47uhcMBy3xFLAT3bhSt5hA,1091
2
+ dplay/__init__.py,sha256=GUmte5vPzPopdUowmGLKJcGSzQJelYiKwEx293xyQEg,123
3
+ dplay/cli.py,sha256=6CMNJk7yDy4YmW3Cu9yk-166mbKuOTDdsJb8rpHtIeg,2725
4
+ dplay/commands/__init__.py,sha256=uzPlh23O3s_Ej9r0QLr-ePJvp4BrS0Pnsv0UA3gZOxo,316
5
+ dplay/commands/dev/__init__.py,sha256=Avwl4U1Nkyejc5dd-a5lC1uNGc3L1IB6FXtE8MIfYGs,718
6
+ dplay/commands/dev/down.py,sha256=1r2VKDgJ1YTAngnktub6xlnhBdt7I7p9w77ibdNL74k,416
7
+ dplay/commands/dev/http.py,sha256=bkTHtmGIwzAZa67oYLL7EyVbfPw9BpCZ_o2x8qG9ibA,961
8
+ dplay/commands/dev/logs.py,sha256=t29RgZ6-6qRlemnzy23dnZsdJXhY_YJMWUKuKwpPXiA,292
9
+ dplay/commands/dev/ssl.py,sha256=LgZJmInwfZ5-7iqhR981qNAcTQxLe7xuxwhFwXhjxvs,1056
10
+ dplay/commands/dev/up.py,sha256=xsBakFQ5YsJQ7rvw-TKY86NZKYW_uYhuvWe5LQnb3tk,547
11
+ dplay/commands/dev/worker.py,sha256=cnoLGvdTT5ftdpwoi7eJ9y4xW5IaIAMkKzawS4TcXwg,546
12
+ dplay/commands/system/__init__.py,sha256=N6giylwo5seyiv0AC_yvEohrOayrdPXV2wzaphAumA0,42
13
+ dplay/commands/system/doctor.py,sha256=kL-unHtdvfvR9LIohCR9ddQ0hNa65F3_8d7SJ-EKxyM,699
14
+ dplay/commands/system/reset.py,sha256=8nb_lkB3aBjUGLBf9tV1w126FXMJF0CvmnzQVeiOT7A,779
15
+ dplay/core/__init__.py,sha256=vWXi1-Ij3kTYUwN1XU0ag9FVOzo91PyNy5sAO65fCIg,277
16
+ dplay/core/config_loader.py,sha256=qHqyRBX5W-vKvqAqhFIsdaDoaD73m9v45U_LNLmZ-Iw,1247
17
+ dplay/core/process_manager.py,sha256=T_ufAOkXnDnAMo_uG6QS9ti-19lQzao3qTprJL81Qb0,886
18
+ dplay/core/repo_detector.py,sha256=TFRZ_m-8mouTLU7VSyHzlGOKAKFNqqzgCaN1WR-ZAe4,890
19
+ dplay/environment/__init__.py,sha256=TkR95dCBFa2qkJtgoNj6SCI1-l-qXy0tRRBO-8jftHs,307
20
+ dplay/environment/diagnostics.py,sha256=ROdmnAp0-in8br8I49l72t9GZYlSIhkezRDZhHXR--o,2089
21
+ dplay/environment/venv_detector.py,sha256=2CzOh35KipDOHLwdonbQG67IbX1MNxvBhtLQtED2OoY,526
22
+ dplay/utils/__init__.py,sha256=GrLowM1HNEFoMsBNlyk6cFugmllsamloS6R0ytwoLXg,191
23
+ dplay/utils/dev_startup.py,sha256=DyjQ7-bt6fgItq5L6aXgWuPYt2BED--ZCKz_41Iiq94,1576
24
+ dplay/utils/subprocess_utils.py,sha256=96rzSMQz4GmZvQinM46EAvtVdfQQExYnojgh6O3GnTE,68
25
+ djangoplay_cli-1.0.0.dist-info/METADATA,sha256=mGbQ3N2dfKmox-xgLEJ5BEN-5pVPtbkMIVxkGagBSqA,366
26
+ djangoplay_cli-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
27
+ djangoplay_cli-1.0.0.dist-info/entry_points.txt,sha256=ECAidkbZn6XuAeH0yxrB8S326pRBGpMj9EGV46Bilok,41
28
+ djangoplay_cli-1.0.0.dist-info/top_level.txt,sha256=IC9uHIzHrULkJq7PH4tRaKIBybQwng00VbDa509v0is,6
29
+ djangoplay_cli-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ dplay = dplay.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 binaryfleet chandrashekhar-bhosale
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ dplay
dplay/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ """
2
+ DjangoPlay CLI package.
3
+
4
+ This package provides developer tooling used by the
5
+ DjangoPlay ecosystem.
6
+
7
+ Version: 1.0.0
8
+ """
dplay/cli.py ADDED
@@ -0,0 +1,99 @@
1
+ """
2
+ CLI entrypoint for djangoplay-cli.
3
+
4
+ This module defines the root CLI application and registers
5
+ all command groups.
6
+ """
7
+
8
+ from importlib.metadata import version
9
+
10
+ import typer
11
+
12
+ from dplay.commands.dev.down import down_command
13
+ from dplay.commands.dev.http import http_command
14
+ from dplay.commands.dev.logs import logs_command
15
+ from dplay.commands.dev.ssl import ssl_command
16
+ from dplay.commands.dev.up import up_command
17
+ from dplay.commands.dev.worker import worker_command
18
+ from dplay.commands.system.doctor import doctor_command
19
+ from dplay.commands.system.reset import reset_command
20
+
21
+ app = typer.Typer(help="DjangoPlay CLI")
22
+
23
+
24
+ # ------------------------------------------------------------------
25
+ # EXTENSIBLE METADATA
26
+ # ------------------------------------------------------------------
27
+
28
+
29
+ def get_cli_version() -> str:
30
+ """
31
+ Retrieve CLI version from installed package metadata.
32
+ """
33
+
34
+ try:
35
+ return version("djangoplay-cli")
36
+ except Exception:
37
+ return "unknown"
38
+
39
+
40
+ # ------------------------------------------------------------------
41
+ # DEV COMMAND GROUP
42
+ # ------------------------------------------------------------------
43
+
44
+ dev_app = typer.Typer(help="Development commands")
45
+
46
+ dev_app.command("http")(http_command)
47
+ dev_app.command("ssl")(ssl_command)
48
+ dev_app.command("worker")(worker_command)
49
+ dev_app.command("up")(up_command)
50
+ dev_app.command("down")(down_command)
51
+
52
+ app.add_typer(dev_app, name="dev")
53
+
54
+ # ------------------------------------------------------------------
55
+ # SYSTEM COMMAND GROUP
56
+ # ------------------------------------------------------------------
57
+
58
+ system_app = typer.Typer(help="System environment commands")
59
+
60
+ system_app.command("doctor")(doctor_command)
61
+ system_app.command("reset")(reset_command)
62
+
63
+ app.add_typer(system_app, name="system")
64
+
65
+ # ------------------------------------------------------------------
66
+ # LOG COMMAND
67
+ # ------------------------------------------------------------------
68
+
69
+ app.command("logs")(logs_command)
70
+
71
+ # -------------------------------------------------------------
72
+ # GLOBAL OPTIONS
73
+ # ------------------------------------------------------------------
74
+
75
+
76
+ @app.callback(invoke_without_command=True)
77
+ def callback(
78
+ ctx: typer.Context,
79
+ version_flag: bool = typer.Option(None, "--version", "-v", is_eager=True),
80
+ ):
81
+ """
82
+ CLI entrypoint used by the console script.
83
+
84
+ This wrapper ensures compatibility with Python packaging
85
+ and avoids exposing the Typer object directly and handles
86
+ global CLI option such as --version.
87
+ """
88
+
89
+ if version_flag:
90
+ typer.echo(get_cli_version())
91
+ raise typer.Exit()
92
+
93
+ if ctx.invoked_subcommand is None:
94
+ typer.echo(ctx.get_help())
95
+ raise typer.Exit()
96
+
97
+
98
+ def main():
99
+ app()
@@ -0,0 +1,15 @@
1
+ """
2
+ CLI command packages for djangoplay-cli.
3
+
4
+ This module groups all user-facing CLI commands exposed
5
+ through the `dplay` command-line interface.
6
+
7
+ Submodules implement command groups such as:
8
+
9
+ - dev
10
+ - env (future)
11
+ - repo (future)
12
+
13
+ The command structure follows the Typer CLI architecture
14
+ defined in `dplay.cli`.
15
+ """
@@ -0,0 +1,25 @@
1
+ """
2
+ Development command group for djangoplay-cli.
3
+
4
+ This package contains CLI commands responsible for managing
5
+ the local DjangoPlay development environment.
6
+
7
+ Available commands include:
8
+
9
+ - dev http → start Django development server (HTTP)
10
+ - dev ssl → start Django development server (HTTPS)
11
+ - dev worker → start Celery worker
12
+ - dev up → start full development environment
13
+ - dev down → stop development environment
14
+ - dev logs → display development logs
15
+
16
+ The commands in this package coordinate services such as:
17
+
18
+ - Django development server
19
+ - Celery worker and beat
20
+ - Redis
21
+ - PostgreSQL
22
+
23
+ These commands are registered under the `dplay dev` command
24
+ group defined in `dplay.cli`.
25
+ """
@@ -0,0 +1,20 @@
1
+ """
2
+ Stop development environment.
3
+ """
4
+
5
+ from dplay.core.process_manager import stop_celery
6
+
7
+
8
+ # ------------------------------------------------------------------
9
+ # EXTENSIBLE METADATA
10
+ # ------------------------------------------------------------------
11
+ def down_command():
12
+ """
13
+ Stop all development services.
14
+ """
15
+
16
+ print("Stopping DjangoPlay services")
17
+
18
+ stop_celery()
19
+
20
+ print("Services stopped")
@@ -0,0 +1,42 @@
1
+ """
2
+ HTTP development server command.
3
+ """
4
+
5
+ import subprocess
6
+
7
+ from dplay.core.repo_detector import ensure_repo
8
+ from dplay.environment.venv_detector import ensure_venv
9
+ from dplay.utils.dev_startup import print_environment, restart_celery
10
+
11
+
12
+ # ------------------------------------------------------------------
13
+ # EXTENSIBLE METADATA
14
+ # ------------------------------------------------------------------
15
+ def http_command():
16
+ """
17
+ Start DjangoPlay HTTP development server.
18
+
19
+ Starts:
20
+ - Celery worker
21
+ - Celery beat
22
+ - Django development server
23
+ """
24
+
25
+ repo_path = ensure_repo()
26
+ python_exec = ensure_venv()
27
+
28
+ print_environment(repo_path, python_exec)
29
+
30
+ restart_celery()
31
+
32
+ print("✔ Django server starting\n")
33
+
34
+ print("Server URL:")
35
+ print("http://localhost:3333\n")
36
+
37
+ print("Press CTRL+C to stop the server.\n")
38
+
39
+ subprocess.run(
40
+ ["python", "manage.py", "runserver", "localhost:3333"],
41
+ check=True,
42
+ )
@@ -0,0 +1,14 @@
1
+ """
2
+ CLI log command.
3
+ """
4
+
5
+
6
+ # ------------------------------------------------------------------
7
+ # EXTENSIBLE METADATA
8
+ # ------------------------------------------------------------------
9
+ def logs_command():
10
+ """
11
+ Display development logs.
12
+ """
13
+
14
+ print("Logs feature coming soon")
@@ -0,0 +1,43 @@
1
+ """
2
+ HTTPS development server command.
3
+ """
4
+
5
+ import subprocess
6
+
7
+ from dplay.core.repo_detector import ensure_repo
8
+ from dplay.environment.venv_detector import ensure_venv
9
+ from dplay.utils.dev_startup import print_environment, restart_celery
10
+
11
+
12
+ # ------------------------------------------------------------------
13
+ # EXTENSIBLE METADATA
14
+ # ------------------------------------------------------------------
15
+ def ssl_command():
16
+ """
17
+ Start DjangoPlay HTTPS development server.
18
+
19
+ Uses runserver_plus when available.
20
+ """
21
+
22
+ repo_path = ensure_repo()
23
+ python_exec = ensure_venv()
24
+
25
+ print_environment(repo_path, python_exec)
26
+
27
+ restart_celery()
28
+
29
+ print("✔ Django HTTPS server starting\n")
30
+
31
+ print("Server URL:")
32
+ print("https://localhost:9999\n")
33
+
34
+ try:
35
+ subprocess.run(
36
+ ["python", "manage.py", "runserver_plus", "localhost:9999"],
37
+ check=True,
38
+ )
39
+ except Exception:
40
+ subprocess.run(
41
+ ["python", "manage.py", "runserver", "localhost:9999"],
42
+ check=True,
43
+ )
@@ -0,0 +1,24 @@
1
+ """
2
+ Start full development environment.
3
+ """
4
+
5
+ import subprocess
6
+
7
+ from dplay.core.process_manager import start_celery
8
+
9
+
10
+ # ------------------------------------------------------------------
11
+ # EXTENSIBLE METADATA
12
+ # ------------------------------------------------------------------
13
+ def up_command():
14
+ """
15
+ Start Redis, Celery and Django services.
16
+ """
17
+
18
+ print("Starting DjangoPlay development environment\n")
19
+
20
+ start_celery()
21
+
22
+ subprocess.Popen(["python", "manage.py", "runserver", "localhost:3333"])
23
+
24
+ print("Environment is up")
@@ -0,0 +1,25 @@
1
+ """
2
+ Celery worker command.
3
+ """
4
+
5
+ import subprocess
6
+
7
+ from dplay.core.repo_detector import ensure_repo
8
+ from dplay.environment.venv_detector import ensure_venv
9
+
10
+
11
+ # ------------------------------------------------------------------
12
+ # EXTENSIBLE METADATA
13
+ # ------------------------------------------------------------------
14
+ def worker_command():
15
+ """
16
+ Start Celery worker and beat services.
17
+ """
18
+
19
+ ensure_repo()
20
+ ensure_venv()
21
+
22
+ subprocess.run(
23
+ ["celery", "-A", "paystream", "worker", "-l", "info"],
24
+ check=True,
25
+ )
@@ -0,0 +1,3 @@
1
+ """
2
+ DjangoPlay CLI Health Diagnostics
3
+ """
@@ -0,0 +1,31 @@
1
+ """
2
+ Environment diagnostics command.
3
+ """
4
+
5
+ from dplay.core.repo_detector import ensure_repo
6
+ from dplay.environment.diagnostics import run_diagnostics
7
+ from dplay.environment.venv_detector import ensure_venv
8
+
9
+
10
+ # ------------------------------------------------------------------
11
+ # EXTENSIBLE METADATA
12
+ # ------------------------------------------------------------------
13
+ def doctor_command():
14
+ """
15
+ Run environment diagnostics.
16
+ """
17
+
18
+ ensure_repo()
19
+ ensure_venv()
20
+
21
+ print("\nEnvironment Diagnostics\n")
22
+
23
+ results = run_diagnostics()
24
+
25
+ for ok, message in results:
26
+ if ok:
27
+ print(f"✔ {message}")
28
+ else:
29
+ print(f"✖ {message}")
30
+
31
+ print("")
@@ -0,0 +1,37 @@
1
+ """
2
+ Environment reset command.
3
+ """
4
+
5
+ import subprocess
6
+
7
+
8
+ # ------------------------------------------------------------------
9
+ # EXTENSIBLE METADATA
10
+ # ------------------------------------------------------------------
11
+ def reset_command():
12
+ """
13
+ Reset development environment.
14
+ """
15
+
16
+ print("\nResetting development environment\n")
17
+
18
+ subprocess.run(
19
+ 'pkill -9 -f "celery.*paystream" 2>/dev/null || true',
20
+ shell=True,
21
+ )
22
+
23
+ subprocess.run(
24
+ 'pkill -9 -f "celery.*beat" 2>/dev/null || true',
25
+ shell=True,
26
+ )
27
+
28
+ print("✔ Celery processes stopped")
29
+
30
+ subprocess.run(
31
+ "redis-cli flushall",
32
+ shell=True,
33
+ stdout=subprocess.DEVNULL,
34
+ stderr=subprocess.DEVNULL,
35
+ )
36
+
37
+ print("✔ Redis flushed\n")
dplay/core/__init__.py ADDED
@@ -0,0 +1,12 @@
1
+ """
2
+ Core infrastructure utilities for djangoplay-cli.
3
+
4
+ This package contains low-level helpers responsible for:
5
+
6
+ - repository detection
7
+ - process management (future)
8
+ - configuration loading (future)
9
+
10
+ Core modules should remain lightweight and reusable
11
+ across CLI commands.
12
+ """
@@ -0,0 +1,53 @@
1
+ """
2
+ Configuration loader for DjangoPlay CLI.
3
+
4
+ Loads configuration from ~/.dplay/config.yaml
5
+ and secrets from ~/.dplay/.secrets
6
+ """
7
+
8
+ import os
9
+ from pathlib import Path
10
+
11
+ import yaml
12
+
13
+ CONFIG_DIR = Path.home() / ".dplay"
14
+ CONFIG_FILE = CONFIG_DIR / "config.yaml"
15
+ SECRETS_FILE = CONFIG_DIR / ".secrets"
16
+
17
+
18
+ # ------------------------------------------------------------------
19
+ # EXTENSIBLE METADATA
20
+ # ------------------------------------------------------------------
21
+ def load_config():
22
+ """
23
+ Load YAML configuration file.
24
+ """
25
+
26
+ if not CONFIG_FILE.exists():
27
+ raise RuntimeError("Missing configuration file ~/.dplay/config.yaml")
28
+
29
+ with open(CONFIG_FILE) as f:
30
+ return yaml.safe_load(f)
31
+
32
+
33
+ # ------------------------------------------------------------------
34
+ # EXTENSIBLE METADATA
35
+ # ------------------------------------------------------------------
36
+ def load_secrets():
37
+ """
38
+ Load secrets into environment variables.
39
+ """
40
+
41
+ if not SECRETS_FILE.exists():
42
+ return
43
+
44
+ with open(SECRETS_FILE) as f:
45
+ for line in f:
46
+ line = line.strip()
47
+
48
+ if not line or line.startswith("#"):
49
+ continue
50
+
51
+ key, value = line.split("=", 1)
52
+
53
+ os.environ[key] = value
@@ -0,0 +1,37 @@
1
+ """
2
+ Process management utilities.
3
+ """
4
+
5
+ import subprocess
6
+
7
+
8
+ # ------------------------------------------------------------------
9
+ # EXTENSIBLE METADATA
10
+ # ------------------------------------------------------------------
11
+ def start_celery():
12
+ """
13
+ Start celery worker and beat.
14
+ """
15
+
16
+ subprocess.Popen(["celery", "-A", "paystream", "worker", "-l", "info"])
17
+
18
+ subprocess.Popen(["celery", "-A", "paystream", "beat", "-l", "info"])
19
+
20
+
21
+ # ------------------------------------------------------------------
22
+ # EXTENSIBLE METADATA
23
+ # ------------------------------------------------------------------
24
+ def stop_celery():
25
+ """
26
+ Stop running celery workers.
27
+ """
28
+
29
+ subprocess.run(
30
+ 'pkill -9 -f "celery.*paystream" 2>/dev/null || true',
31
+ shell=True,
32
+ )
33
+
34
+ subprocess.run(
35
+ 'pkill -9 -f "celery.*beat" 2>/dev/null || true',
36
+ shell=True,
37
+ )
@@ -0,0 +1,40 @@
1
+ """
2
+ Repository detection utilities.
3
+ """
4
+
5
+ import subprocess
6
+ import sys
7
+
8
+
9
+ # ------------------------------------------------------------------
10
+ # EXTENSIBLE METADATA
11
+ # ------------------------------------------------------------------
12
+ def ensure_repo():
13
+ """
14
+ Ensure command runs inside DjangoPlay repository.
15
+
16
+ Returns
17
+ -------
18
+ str
19
+ Repository root path.
20
+ """
21
+
22
+ try:
23
+ result = subprocess.check_output(
24
+ ["git", "rev-parse", "--show-toplevel"],
25
+ stderr=subprocess.DEVNULL,
26
+ )
27
+
28
+ repo_path = result.decode().strip()
29
+
30
+ if "djangoplay" not in repo_path.lower():
31
+ raise RuntimeError
32
+
33
+ return repo_path
34
+
35
+ except Exception:
36
+ print(
37
+ "Error: DjangoPlay repository not detected.\n"
38
+ "Run this command inside the DjangoPlay project directory."
39
+ )
40
+ sys.exit(1)
@@ -0,0 +1,15 @@
1
+ """
2
+ Environment validation utilities.
3
+
4
+ Modules in this package verify the runtime environment
5
+ required to execute DjangoPlay development commands.
6
+
7
+ Current responsibilities include:
8
+
9
+ - Python virtual environment validation
10
+
11
+ Future responsibilities may include:
12
+
13
+ - dependency checks
14
+ - system diagnostics
15
+ """
@@ -0,0 +1,79 @@
1
+ """
2
+ Environment diagnostics utilities.
3
+ """
4
+
5
+ import shutil
6
+ import socket
7
+ import sys
8
+
9
+
10
+ # ------------------------------------------------------------------
11
+ # EXTENSIBLE METADATA
12
+ # ------------------------------------------------------------------
13
+ def check_python():
14
+ """Verify Python version."""
15
+
16
+ version = sys.version_info
17
+ if version.major >= 3 and version.minor >= 11:
18
+ return True, "Python version OK"
19
+ return False, "Python >=3.11 required"
20
+
21
+
22
+ # ------------------------------------------------------------------
23
+ # EXTENSIBLE METADATA
24
+ # ------------------------------------------------------------------
25
+ def check_redis():
26
+ """Check Redis availability."""
27
+
28
+ try:
29
+ sock = socket.create_connection(("127.0.0.1", 6379), timeout=1)
30
+ sock.close()
31
+ return True, "Redis reachable"
32
+ except Exception:
33
+ return False, "Redis not reachable"
34
+
35
+
36
+ # ------------------------------------------------------------------
37
+ # EXTENSIBLE METADATA
38
+ # ------------------------------------------------------------------
39
+ def check_postgres():
40
+ """Check Postgres availability."""
41
+
42
+ try:
43
+ sock = socket.create_connection(("127.0.0.1", 5432), timeout=1)
44
+ sock.close()
45
+ return True, "Postgres reachable"
46
+ except Exception:
47
+ return False, "Postgres not reachable"
48
+
49
+
50
+ # ------------------------------------------------------------------
51
+ # EXTENSIBLE METADATA
52
+ # ------------------------------------------------------------------
53
+ def check_celery():
54
+ """Check Celery availability."""
55
+
56
+ if shutil.which("celery"):
57
+ return True, "Celery available"
58
+ return False, "Celery not installed"
59
+
60
+
61
+ # ------------------------------------------------------------------
62
+ # EXTENSIBLE METADATA
63
+ # ------------------------------------------------------------------
64
+ def run_diagnostics():
65
+ """Run all environment checks."""
66
+
67
+ checks = [
68
+ check_python,
69
+ check_redis,
70
+ check_postgres,
71
+ check_celery,
72
+ ]
73
+
74
+ results = []
75
+
76
+ for check in checks:
77
+ results.append(check())
78
+
79
+ return results
@@ -0,0 +1,26 @@
1
+ """
2
+ Virtual environment detection utilities.
3
+ """
4
+
5
+ import os
6
+ import sys
7
+
8
+
9
+ # ------------------------------------------------------------------
10
+ # EXTENSIBLE METADATA
11
+ # ------------------------------------------------------------------
12
+ def ensure_venv():
13
+ """
14
+ Ensure Python virtual environment is active.
15
+
16
+ Returns
17
+ -------
18
+ str
19
+ Python executable path.
20
+ """
21
+
22
+ if "VIRTUAL_ENV" not in os.environ:
23
+ print("Error: Virtual environment not active.")
24
+ sys.exit(1)
25
+
26
+ return sys.executable
@@ -0,0 +1,9 @@
1
+ """
2
+ Utility helpers used across the CLI implementation.
3
+
4
+ These modules provide reusable functionality such as:
5
+
6
+ - development startup helpers
7
+ - subprocess wrappers
8
+ - future CLI utilities
9
+ """
@@ -0,0 +1,66 @@
1
+ """
2
+ Development startup helpers.
3
+
4
+ Shared utilities used by development commands such as:
5
+
6
+ - dev http
7
+ - dev ssl
8
+ """
9
+
10
+ import subprocess
11
+
12
+
13
+ # ------------------------------------------------------------------
14
+ # EXTENSIBLE METADATA
15
+ # ------------------------------------------------------------------
16
+ def print_environment(repo_path: str, python_exec: str):
17
+ """
18
+ Print CLI environment summary.
19
+ """
20
+
21
+ print("\nDjangoPlay CLI\n")
22
+
23
+ print(f"Repository: {repo_path}")
24
+ print(f"Python: {python_exec}")
25
+ print("Environment: development\n")
26
+
27
+
28
+ # ------------------------------------------------------------------
29
+ # EXTENSIBLE METADATA
30
+ # ------------------------------------------------------------------
31
+ def restart_celery():
32
+ """
33
+ Stop existing celery processes and start fresh ones.
34
+ """
35
+
36
+ print("Stopping existing Celery workers...")
37
+
38
+ subprocess.run(
39
+ 'pkill -9 -f "celery.*paystream" 2>/dev/null || true',
40
+ shell=True,
41
+ )
42
+
43
+ subprocess.run(
44
+ 'pkill -9 -f "celery.*beat" 2>/dev/null || true',
45
+ shell=True,
46
+ )
47
+
48
+ print("✔ Existing Celery processes cleared\n")
49
+
50
+ print("Starting services...\n")
51
+
52
+ subprocess.Popen(
53
+ ["celery", "-A", "paystream", "worker", "-l", "info"],
54
+ stdout=subprocess.DEVNULL,
55
+ stderr=subprocess.DEVNULL,
56
+ )
57
+
58
+ print("✔ Celery worker started")
59
+
60
+ subprocess.Popen(
61
+ ["celery", "-A", "paystream", "beat", "-l", "info"],
62
+ stdout=subprocess.DEVNULL,
63
+ stderr=subprocess.DEVNULL,
64
+ )
65
+
66
+ print("✔ Celery beat started\n")
@@ -0,0 +1,5 @@
1
+ """
2
+ Subprocess helper utilities.
3
+
4
+ Reserved for future releases.
5
+ """