feat: integrated with typer
This commit is contained in:
parent
5fe565d8aa
commit
7cfede725d
13 changed files with 162 additions and 14 deletions
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
@ -2,9 +2,9 @@ name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [ main, dev ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main ]
|
branches: [ main, dev ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
@ -91,4 +91,4 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
pip install pytest
|
pip install pytest
|
||||||
pip install pytest-cov
|
pip install pytest-cov
|
||||||
python tests/test_validate_input_file.py tests/validate_input_file.py tests/in/docker-compose.yaml
|
pytest
|
||||||
|
|
2
compose_viz/__init__.py
Normal file
2
compose_viz/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
__app_name__ = "compose_viz"
|
||||||
|
__version__ = "0.1.0"
|
9
compose_viz/__main__.py
Normal file
9
compose_viz/__main__.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from compose_viz import cli, __app_name__
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
cli.app(prog_name=__app_name__)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
59
compose_viz/cli.py
Normal file
59
compose_viz/cli.py
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
from ast import parse
|
||||||
|
from enum import Enum
|
||||||
|
import typer
|
||||||
|
from typing import Optional
|
||||||
|
from compose_viz import __app_name__, __version__
|
||||||
|
from compose_viz.compose import Compose
|
||||||
|
from compose_viz.parser import Parser
|
||||||
|
|
||||||
|
|
||||||
|
class VisualizationFormats(str, Enum):
|
||||||
|
png = "PNG"
|
||||||
|
dot = "DOT"
|
||||||
|
|
||||||
|
|
||||||
|
app = typer.Typer(
|
||||||
|
invoke_without_command=True,
|
||||||
|
no_args_is_help=True,
|
||||||
|
subcommand_metavar="",
|
||||||
|
add_completion=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _version_callback(value: bool) -> None:
|
||||||
|
if value:
|
||||||
|
typer.echo(f"{__app_name__} {__version__}")
|
||||||
|
raise typer.Exit()
|
||||||
|
|
||||||
|
|
||||||
|
@app.callback()
|
||||||
|
def compose_viz(
|
||||||
|
input_path: str,
|
||||||
|
output_path: Optional[str] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--output_path",
|
||||||
|
"-o",
|
||||||
|
help="Output path for the generated visualization.",
|
||||||
|
),
|
||||||
|
format: VisualizationFormats = typer.Option(
|
||||||
|
"PNG",
|
||||||
|
"--format",
|
||||||
|
"-m",
|
||||||
|
help="Output format for the generated visualization.",
|
||||||
|
),
|
||||||
|
_: Optional[bool] = typer.Option(
|
||||||
|
None,
|
||||||
|
"--version",
|
||||||
|
"-v",
|
||||||
|
help="Show the version of compose_viz.",
|
||||||
|
callback=_version_callback,
|
||||||
|
is_eager=True,
|
||||||
|
)
|
||||||
|
) -> None:
|
||||||
|
parser = Parser()
|
||||||
|
compose = parser.parse(input_path)
|
||||||
|
|
||||||
|
if compose:
|
||||||
|
typer.echo(f"Successfully parsed {input_path}")
|
||||||
|
|
||||||
|
raise typer.Exit()
|
10
compose_viz/compose.py
Normal file
10
compose_viz/compose.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from typing import List
|
||||||
|
from compose_viz.service import Service
|
||||||
|
|
||||||
|
|
||||||
|
class Compose:
|
||||||
|
def __init__(self, services: List[Service]) -> None:
|
||||||
|
self.services = services
|
||||||
|
|
||||||
|
def extract_networks(self) -> List[str]:
|
||||||
|
raise NotImplementedError
|
10
compose_viz/parser.py
Normal file
10
compose_viz/parser.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from compose_viz.compose import Compose
|
||||||
|
|
||||||
|
|
||||||
|
class Parser:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def parse(self, file_path: str) -> Compose:
|
||||||
|
# validate input file using `docker-compose config -q sys.argv[1]` first
|
||||||
|
raise NotImplementedError
|
13
compose_viz/service.py
Normal file
13
compose_viz/service.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
class Service:
|
||||||
|
def __init__(self, name: str, image: str, ports: List[str] = [], networks: List[str] = [], volumes: List[str] = [], depends_on: List[str] = [], links: List[str] = [], extends: List[str] = []) -> None:
|
||||||
|
self.name = name
|
||||||
|
self.image = image
|
||||||
|
self.ports = ports
|
||||||
|
self.networks = networks
|
||||||
|
self.volumes = volumes
|
||||||
|
self.depends_on = depends_on
|
||||||
|
self.links = links
|
||||||
|
self.extends = extends
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
14
tests/test_cli.py
Normal file
14
tests/test_cli.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import pytest
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
from compose_viz import cli
|
||||||
|
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
|
||||||
|
|
||||||
|
def test_cli():
|
||||||
|
input_path = "tests/in/000001.yaml"
|
||||||
|
result = runner.invoke(cli.app, [input_path])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert f"Successfully parsed {input_path}\n" in result.stdout
|
29
tests/test_parse_file.py
Normal file
29
tests/test_parse_file.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
from compose_viz.parser import Parser
|
||||||
|
from compose_viz.compose import Compose
|
||||||
|
from compose_viz.service import Service
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_file():
|
||||||
|
expected: Compose = Compose([
|
||||||
|
Service(
|
||||||
|
name='frontend',
|
||||||
|
image='awesome/webapp',
|
||||||
|
networks=['front-tier', 'back-tier'],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name='monitoring',
|
||||||
|
image='awesome/monitoring',
|
||||||
|
networks=['admin'],
|
||||||
|
),
|
||||||
|
Service(
|
||||||
|
name='backend',
|
||||||
|
image='awesome/backend',
|
||||||
|
networks=['back-tier', 'admin'],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
|
||||||
|
parser = Parser()
|
||||||
|
actual = parser.parse('tests/in/000001.yaml')
|
||||||
|
|
||||||
|
assert actual == expected
|
|
@ -1,5 +0,0 @@
|
||||||
import sys
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
pytest.main([sys.argv[1]])
|
|
13
tests/test_version.py
Normal file
13
tests/test_version.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import pytest
|
||||||
|
from typer.testing import CliRunner
|
||||||
|
from compose_viz import cli, __app_name__, __version__
|
||||||
|
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
|
||||||
|
|
||||||
|
def test_version():
|
||||||
|
result = runner.invoke(cli.app, ["--version"])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert f"{__app_name__} {__version__}\n" in result.stdout
|
|
@ -1,6 +0,0 @@
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
def test_validate_input_file():
|
|
||||||
process = os.system("docker-compose -f " + sys.argv[2] + " config -q")
|
|
||||||
assert process == 0
|
|
Loading…
Reference in a new issue