From fd407b692b815bcf15c1e70ddaa239ccf8fc43cf Mon Sep 17 00:00:00 2001 From: Hubert Deng Date: Tue, 17 Sep 2024 13:03:57 -0700 Subject: [PATCH] restructure modules for packaging --- {src => devservices}/__init__.py | 0 {src => devservices}/commands/__init__.py | 0 .../commands/list_dependencies.py | 2 +- .../commands/list_services.py | 4 +-- {src => devservices}/commands/logs.py | 10 +++--- {src => devservices}/commands/start.py | 12 +++---- {src => devservices}/commands/status.py | 13 ++++--- {src => devservices}/commands/stop.py | 12 +++---- .../configs/service_config.py | 10 +++--- {src => devservices}/constants.py | 0 {src => devservices}/exceptions.py | 0 {src => devservices}/main.py | 13 +++---- {src => devservices}/utils/__init__.py | 0 {src => devservices}/utils/console.py | 0 {src => devservices}/utils/devenv.py | 0 {src => devservices}/utils/docker_compose.py | 2 +- {src => devservices}/utils/services.py | 16 ++++----- pyproject.toml | 9 +++-- tests/commands/test_start.py | 10 +++--- tests/commands/test_stop.py | 10 +++--- tests/configs/test_service_config.py | 36 +++++++++---------- 21 files changed, 79 insertions(+), 80 deletions(-) rename {src => devservices}/__init__.py (100%) rename {src => devservices}/commands/__init__.py (100%) rename {src => devservices}/commands/list_dependencies.py (94%) rename {src => devservices}/commands/list_services.py (87%) rename {src => devservices}/commands/logs.py (81%) rename {src => devservices}/commands/start.py (79%) rename {src => devservices}/commands/status.py (90%) rename {src => devservices}/commands/stop.py (79%) rename {src => devservices}/configs/service_config.py (91%) rename {src => devservices}/constants.py (100%) rename {src => devservices}/exceptions.py (100%) rename {src => devservices}/main.py (83%) rename {src => devservices}/utils/__init__.py (100%) rename {src => devservices}/utils/console.py (100%) rename {src => devservices}/utils/devenv.py (100%) rename {src => devservices}/utils/docker_compose.py (90%) rename {src => devservices}/utils/services.py (74%) diff --git a/src/__init__.py b/devservices/__init__.py similarity index 100% rename from src/__init__.py rename to devservices/__init__.py diff --git a/src/commands/__init__.py b/devservices/commands/__init__.py similarity index 100% rename from src/commands/__init__.py rename to devservices/commands/__init__.py diff --git a/src/commands/list_dependencies.py b/devservices/commands/list_dependencies.py similarity index 94% rename from src/commands/list_dependencies.py rename to devservices/commands/list_dependencies.py index f8394e20..b6a15102 100644 --- a/src/commands/list_dependencies.py +++ b/devservices/commands/list_dependencies.py @@ -4,7 +4,7 @@ from argparse import ArgumentParser from argparse import Namespace -from utils.services import find_matching_service +from devservices.utils.services import find_matching_service def add_parser(subparsers: _SubParsersAction[ArgumentParser]) -> None: diff --git a/src/commands/list_services.py b/devservices/commands/list_services.py similarity index 87% rename from src/commands/list_services.py rename to devservices/commands/list_services.py index 261e2b99..88044fbe 100644 --- a/src/commands/list_services.py +++ b/devservices/commands/list_services.py @@ -4,8 +4,8 @@ from argparse import ArgumentParser from argparse import Namespace -from utils.devenv import get_coderoot -from utils.services import get_local_services +from devservices.utils.devenv import get_coderoot +from devservices.utils.services import get_local_services def add_parser(subparsers: _SubParsersAction[ArgumentParser]) -> None: diff --git a/src/commands/logs.py b/devservices/commands/logs.py similarity index 81% rename from src/commands/logs.py rename to devservices/commands/logs.py index e31d8b86..f75425f1 100644 --- a/src/commands/logs.py +++ b/devservices/commands/logs.py @@ -6,11 +6,11 @@ from argparse import ArgumentParser from argparse import Namespace -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME -from exceptions import DockerComposeError -from utils.docker_compose import run_docker_compose_command -from utils.services import find_matching_service +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME +from devservices.exceptions import DockerComposeError +from devservices.utils.docker_compose import run_docker_compose_command +from devservices.utils.services import find_matching_service def add_parser(subparsers: _SubParsersAction[ArgumentParser]) -> None: diff --git a/src/commands/start.py b/devservices/commands/start.py similarity index 79% rename from src/commands/start.py rename to devservices/commands/start.py index bd871ebf..6d1c88e2 100644 --- a/src/commands/start.py +++ b/devservices/commands/start.py @@ -5,12 +5,12 @@ from argparse import ArgumentParser from argparse import Namespace -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME -from exceptions import DockerComposeError -from utils.console import Status -from utils.docker_compose import run_docker_compose_command -from utils.services import find_matching_service +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME +from devservices.exceptions import DockerComposeError +from devservices.utils.console import Status +from devservices.utils.docker_compose import run_docker_compose_command +from devservices.utils.services import find_matching_service def add_parser(subparsers: _SubParsersAction[ArgumentParser]) -> None: diff --git a/src/commands/status.py b/devservices/commands/status.py similarity index 90% rename from src/commands/status.py rename to devservices/commands/status.py index a216800f..06199ffc 100644 --- a/src/commands/status.py +++ b/devservices/commands/status.py @@ -7,11 +7,11 @@ from argparse import ArgumentParser from argparse import Namespace -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME -from exceptions import DockerComposeError -from utils.docker_compose import run_docker_compose_command -from utils.services import find_matching_service +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME +from devservices.exceptions import DockerComposeError +from devservices.utils.docker_compose import run_docker_compose_command +from devservices.utils.services import find_matching_service LINE_LENGTH = 40 @@ -70,11 +70,10 @@ def status(args: Namespace) -> None: modes = service.config.modes # TODO: allow custom modes to be used mode_to_view = "default" - mode_dependencies = modes[mode_to_view] + mode_dependencies = " ".join(modes[mode_to_view]) service_config_file_path = os.path.join( service.repo_path, DEVSERVICES_DIR_NAME, DOCKER_COMPOSE_FILE_NAME ) - mode_dependencies = " ".join(modes[mode_to_view]) try: status_json = run_docker_compose_command( f"-f {service_config_file_path} ps {mode_dependencies} --format json" diff --git a/src/commands/stop.py b/devservices/commands/stop.py similarity index 79% rename from src/commands/stop.py rename to devservices/commands/stop.py index 045dac20..e66d74bd 100644 --- a/src/commands/stop.py +++ b/devservices/commands/stop.py @@ -5,12 +5,12 @@ from argparse import ArgumentParser from argparse import Namespace -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME -from exceptions import DockerComposeError -from utils.console import Status -from utils.docker_compose import run_docker_compose_command -from utils.services import find_matching_service +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME +from devservices.exceptions import DockerComposeError +from devservices.utils.console import Status +from devservices.utils.docker_compose import run_docker_compose_command +from devservices.utils.services import find_matching_service def add_parser(subparsers: _SubParsersAction[ArgumentParser]) -> None: diff --git a/src/configs/service_config.py b/devservices/configs/service_config.py similarity index 91% rename from src/configs/service_config.py rename to devservices/configs/service_config.py index 82348c6e..70a6fc10 100644 --- a/src/configs/service_config.py +++ b/devservices/configs/service_config.py @@ -4,12 +4,12 @@ from dataclasses import dataclass import yaml -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME -from exceptions import ConfigNotFoundError -from exceptions import ConfigParseError -from exceptions import ConfigValidationError +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME +from devservices.exceptions import ConfigNotFoundError +from devservices.exceptions import ConfigParseError +from devservices.exceptions import ConfigValidationError VALID_VERSIONS = [0.1] diff --git a/src/constants.py b/devservices/constants.py similarity index 100% rename from src/constants.py rename to devservices/constants.py diff --git a/src/exceptions.py b/devservices/exceptions.py similarity index 100% rename from src/exceptions.py rename to devservices/exceptions.py diff --git a/src/main.py b/devservices/main.py similarity index 83% rename from src/main.py rename to devservices/main.py index 42261bed..4892c896 100644 --- a/src/main.py +++ b/devservices/main.py @@ -4,14 +4,15 @@ import atexit import sentry_sdk -from commands import list_dependencies -from commands import list_services -from commands import logs -from commands import start -from commands import status -from commands import stop from sentry_sdk.integrations.argv import ArgvIntegration +from devservices.commands import list_dependencies +from devservices.commands import list_services +from devservices.commands import logs +from devservices.commands import start +from devservices.commands import status +from devservices.commands import stop + sentry_sdk.init( dsn="https://56470da7302c16e83141f62f88e46449@o1.ingest.us.sentry.io/4507946704961536", traces_sample_rate=1.0, diff --git a/src/utils/__init__.py b/devservices/utils/__init__.py similarity index 100% rename from src/utils/__init__.py rename to devservices/utils/__init__.py diff --git a/src/utils/console.py b/devservices/utils/console.py similarity index 100% rename from src/utils/console.py rename to devservices/utils/console.py diff --git a/src/utils/devenv.py b/devservices/utils/devenv.py similarity index 100% rename from src/utils/devenv.py rename to devservices/utils/devenv.py diff --git a/src/utils/docker_compose.py b/devservices/utils/docker_compose.py similarity index 90% rename from src/utils/docker_compose.py rename to devservices/utils/docker_compose.py index 14902d6a..f409d3ff 100644 --- a/src/utils/docker_compose.py +++ b/devservices/utils/docker_compose.py @@ -2,7 +2,7 @@ import subprocess -from exceptions import DockerComposeError +from devservices.exceptions import DockerComposeError def run_docker_compose_command(command: str) -> subprocess.CompletedProcess[str]: diff --git a/src/utils/services.py b/devservices/utils/services.py similarity index 74% rename from src/utils/services.py rename to devservices/utils/services.py index 193f7443..34f4e6cf 100644 --- a/src/utils/services.py +++ b/devservices/utils/services.py @@ -3,12 +3,12 @@ import os from dataclasses import dataclass -from configs.service_config import ServiceConfig -from exceptions import ConfigNotFoundError -from exceptions import ConfigParseError -from exceptions import ConfigValidationError -from exceptions import ServiceNotFoundError -from utils.devenv import get_coderoot +from devservices.configs.service_config import ServiceConfig +from devservices.exceptions import ConfigNotFoundError +from devservices.exceptions import ConfigParseError +from devservices.exceptions import ConfigValidationError +from devservices.exceptions import ServiceNotFoundError +from devservices.utils.devenv import get_coderoot @dataclass @@ -20,7 +20,7 @@ class Service: def get_local_services(coderoot: str) -> list[Service]: """Get a list of services in the coderoot.""" - from configs.service_config import load_service_config_from_file + from devservices.configs.service_config import load_service_config_from_file services = [] for repo in os.listdir(coderoot): @@ -43,7 +43,7 @@ def get_local_services(coderoot: str) -> list[Service]: def find_matching_service(service_name: str | None = None) -> Service: """Find a service with the given name.""" if service_name is None: - from configs.service_config import load_service_config_from_file + from devservices.configs.service_config import load_service_config_from_file repo_path = os.getcwd() service_config = load_service_config_from_file(repo_path) diff --git a/pyproject.toml b/pyproject.toml index 19f2ea0c..4f25c127 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,12 +22,11 @@ dev = [ ] [project.scripts] -devservices = "main:main" +devservices = "devservices.main:main" + +[tool.setuptools.packages] +find = {} -[tool.setuptools] -package-dir = {"" = "src"} -packages = {find = {where = ["src"]}} -include-package-data = true [tool.mypy] python_version = "3.12" diff --git a/tests/commands/test_start.py b/tests/commands/test_start.py index 81966a68..47caff6e 100644 --- a/tests/commands/test_start.py +++ b/tests/commands/test_start.py @@ -7,14 +7,14 @@ from unittest import mock import pytest -from commands.start import start -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME +from devservices.commands.start import start +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME from tests.testutils import create_config_file -@mock.patch("utils.docker_compose.subprocess.run") +@mock.patch("devservices.utils.docker_compose.subprocess.run") def test_start_simple(mock_run: mock.Mock, tmp_path: Path) -> None: config = { "x-sentry-service-config": { @@ -56,7 +56,7 @@ def test_start_simple(mock_run: mock.Mock, tmp_path: Path) -> None: ) -@mock.patch("utils.docker_compose.subprocess.run") +@mock.patch("devservices.utils.docker_compose.subprocess.run") def test_start_error( mock_run: mock.Mock, capsys: pytest.CaptureFixture[str], tmp_path: Path ) -> None: diff --git a/tests/commands/test_stop.py b/tests/commands/test_stop.py index 14fbd641..423e93e9 100644 --- a/tests/commands/test_stop.py +++ b/tests/commands/test_stop.py @@ -7,14 +7,14 @@ from unittest import mock import pytest -from commands.stop import stop -from constants import DEVSERVICES_DIR_NAME -from constants import DOCKER_COMPOSE_FILE_NAME +from devservices.commands.stop import stop +from devservices.constants import DEVSERVICES_DIR_NAME +from devservices.constants import DOCKER_COMPOSE_FILE_NAME from tests.testutils import create_config_file -@mock.patch("utils.docker_compose.subprocess.run") +@mock.patch("devservices.utils.docker_compose.subprocess.run") def test_stop_simple(mock_run: mock.Mock, tmp_path: Path) -> None: config = { "x-sentry-service-config": { @@ -56,7 +56,7 @@ def test_stop_simple(mock_run: mock.Mock, tmp_path: Path) -> None: ) -@mock.patch("utils.docker_compose.subprocess.run") +@mock.patch("devservices.utils.docker_compose.subprocess.run") def test_stop_error( mock_run: mock.Mock, capsys: pytest.CaptureFixture[str], tmp_path: Path ) -> None: diff --git a/tests/configs/test_service_config.py b/tests/configs/test_service_config.py index cf200b59..47d0615c 100644 --- a/tests/configs/test_service_config.py +++ b/tests/configs/test_service_config.py @@ -4,11 +4,11 @@ from pathlib import Path import pytest -from configs.service_config import load_service_config_from_file -from exceptions import ConfigNotFoundError -from exceptions import ConfigParseError -from exceptions import ConfigValidationError +from devservices.configs.service_config import load_service_config_from_file +from devservices.exceptions import ConfigNotFoundError +from devservices.exceptions import ConfigParseError +from devservices.exceptions import ConfigValidationError from tests.testutils import create_config_file @@ -64,7 +64,7 @@ def test_load_service_config_from_file( } create_config_file(tmp_path, config) - service_config = load_service_config_from_file(tmp_path) + service_config = load_service_config_from_file(str(tmp_path)) assert asdict(service_config) == { "version": 0.1, "service_name": service_name, @@ -86,7 +86,7 @@ def test_load_service_config_from_file_no_dependencies(tmp_path: Path) -> None: } create_config_file(tmp_path, config) - service_config = load_service_config_from_file(tmp_path) + service_config = load_service_config_from_file(str(tmp_path)) assert asdict(service_config) == { "version": 0.1, "service_name": "example-service", @@ -97,7 +97,7 @@ def test_load_service_config_from_file_no_dependencies(tmp_path: Path) -> None: def test_load_service_config_from_file_missing_config(tmp_path: Path) -> None: with pytest.raises(ConfigNotFoundError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert ( str(e.value) == f"Config file not found in directory: {tmp_path / 'devservices' / 'docker-compose.yml'}" @@ -118,7 +118,7 @@ def test_load_service_config_from_file_invalid_version(tmp_path: Path) -> None: create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Invalid version '0.2' in service config" @@ -134,7 +134,7 @@ def test_load_service_config_from_file_missing_version(tmp_path: Path) -> None: create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Version is required in service config" @@ -151,7 +151,7 @@ def test_load_service_config_from_file_missing_service_name(tmp_path: Path) -> N create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Service name is required in service config" @@ -169,7 +169,7 @@ def test_load_service_config_from_file_invalid_dependency(tmp_path: Path) -> Non create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert ( str(e.value) == "Service 'unknown-dependency' in mode 'default' is not defined in dependencies" @@ -190,7 +190,7 @@ def test_load_service_config_from_file_missing_default_mode(tmp_path: Path) -> N create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Default mode is required in service config" @@ -207,7 +207,7 @@ def test_load_service_config_from_file_no_modes(tmp_path: Path) -> None: create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Default mode is required in service config" @@ -228,7 +228,7 @@ def test_load_service_config_from_file_invalid_dependencies(tmp_path: Path) -> N create_config_file(tmp_path, config) with pytest.raises(ConfigParseError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert ( str(e.value) == "Error parsing service dependencies: Dependency.__init__() got an unexpected keyword argument 'unknown'" @@ -252,7 +252,7 @@ def test_load_service_config_from_file_invalid_modes(tmp_path: Path) -> None: create_config_file(tmp_path, config) with pytest.raises(ConfigValidationError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Services in mode 'custom' must be a list" @@ -272,7 +272,7 @@ def test_load_service_config_from_file_no_x_sentry_service_config( create_config_file(tmp_path, config) with pytest.raises(ConfigParseError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert str(e.value) == "Config file does not contain 'x-sentry-service-config' key" @@ -292,7 +292,7 @@ def test_load_service_config_from_file_invalid_yaml(tmp_path: Path) -> None: f.write(config) with pytest.raises(ConfigParseError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert ( str(e.value) == f"Error parsing config file: mapping values are not allowed here\n in \"{tmp_path / 'devservices' / 'docker-compose.yml'}\", line 2, column 12" @@ -316,7 +316,7 @@ def test_load_service_config_from_file_invalid_yaml_tag(tmp_path: Path) -> None: f.write(config) with pytest.raises(ConfigParseError) as e: - load_service_config_from_file(tmp_path) + load_service_config_from_file(str(tmp_path)) assert ( str(e.value) == f"Error parsing config file: could not determine a constructor for the tag 'tag:yaml.org,2002:invalid_tag'\n in \"{tmp_path / 'devservices' / 'docker-compose.yml'}\", line 7, column 19"