Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for docs directive #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions pystructurizr/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
help='The view file to generate.')
@click.option('--as-json', is_flag=True, default=False,
help='Dumps the generated code and the imported modules as a json object')
def dump(view, as_json):
diagram_code, imported_modules = generate_diagram_code_in_child_process(view)
@click.option(
"--directives", help="Flag to add extra directives (i.e. !docs) or omit",
is_flag=True, default=False)
def dump(view, as_json, directives: bool):
diagram_code, imported_modules = generate_diagram_code_in_child_process(view, directives)
if as_json:
print(json.dumps({
"code": diagram_code,
Expand All @@ -40,7 +43,7 @@ def dev(view):

async def async_behavior():
print("Generating diagram...")
diagram_code, imported_modules = generate_diagram_code_in_child_process(view)
diagram_code, imported_modules = generate_diagram_code_in_child_process(view, False)
await generate_svg(diagram_code, tmp_folder)
return imported_modules

Expand All @@ -66,7 +69,7 @@ async def observe_loop():
def build(view, gcs_credentials, bucket_name, object_name):
async def async_behavior():
# Generate diagram
diagram_code, _ = generate_diagram_code_in_child_process(view)
diagram_code, _ = generate_diagram_code_in_child_process(view, False)
tmp_folder = ensure_tmp_folder_exists()

# Generate SVG
Expand Down
7 changes: 5 additions & 2 deletions pystructurizr/cli_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
import httpx


def generate_diagram_code_in_child_process(view: str) -> tuple[dict, list[str]]:
def generate_diagram_code_in_child_process(view: str, directives: bool) -> tuple[dict, list[str]]:
def run_child_process():
# Run a separate Python script as a child process
output = subprocess.check_output([sys.executable, "-m", "pystructurizr.generator", "dump", "--view", view])
executable = [sys.executable, "-m", "pystructurizr.generator", "dump", "--view", view]
if directives:
executable.append("--directives")
output = subprocess.check_output(executable)
return output.decode().strip()

# Run the child process and capture its output
Expand Down
26 changes: 20 additions & 6 deletions pystructurizr/dsl.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import keyword
import re
from enum import Enum
from typing import Dict, List, Optional
from typing import Dict, List, Optional, Literal


# pylint: disable=too-few-public-methods
Expand Down Expand Up @@ -35,10 +35,15 @@ def make_identifier(name: str) -> str:


class Dumper:
def __init__(self):
def __init__(self, with_directives: bool = True):
self.with_directives = with_directives
self.level = 0
self.lines = []

def add_directive(self, type: Literal['!docs', '!adrs'], value: str) -> None:
if self.with_directives:
self.add(f"{type} {value}")

def add(self, txt: str) -> None:
self.lines.append(f'{" " * self.level}{txt}')

Expand Down Expand Up @@ -106,9 +111,10 @@ def dump_relationships(self, dumper: Dumper) -> None:


class Container(Element):
def __init__(self, name: str, description: Optional[str]=None, technology: Optional[str]=None, tags: Optional[List[str]]=None):
def __init__(self, name: str, description: Optional[str]=None, technology: Optional[str]=None, tags: Optional[List[str]]=None, docs: str = None):
super().__init__(name, description, technology, tags)
self.elements = []
self.docs = docs

def __enter__(self):
return self
Expand Down Expand Up @@ -137,6 +143,8 @@ def Group(self, *args, **kwargs) -> "Group":
def dump(self, dumper: Dumper) -> None:
dumper.add(f'{self.instname} = Container "{self.name}" "{self.description}" {{')
dumper.indent()
if self.docs:
dumper.add_directive("!docs", f"{self.docs}")
if self.technology:
dumper.add(f'technology "{self.technology}"')
if self.tags:
Expand All @@ -154,9 +162,10 @@ def dump_relationships(self, dumper: Dumper) -> None:


class SoftwareSystem(Element):
def __init__(self, name: str, description: Optional[str]=None, technology: Optional[str]=None, tags: Optional[List[str]]=None):
def __init__(self, name: str, description: Optional[str]=None, technology: Optional[str]=None, tags: Optional[List[str]]=None, docs: str = None):
super().__init__(name, description, technology, tags)
self.elements = []
self.docs = docs

def __enter__(self):
return self
Expand Down Expand Up @@ -185,6 +194,8 @@ def Group(self, *args, **kwargs) -> "Group":
def dump(self, dumper: Dumper) -> None:
dumper.add(f'{self.instname} = SoftwareSystem "{self.name}" "{self.description}" {{')
dumper.indent()
if self.docs:
dumper.add_directive("!docs", f"{self.docs}")
if self.technology:
dumper.add(f'technology "{self.technology}"')
if self.tags:
Expand Down Expand Up @@ -382,7 +393,7 @@ def dump(self, dumper: Dumper) -> None:


class Workspace:
def __init__(self):
def __init__(self, docs: str = None):
self.models = []
self.views = []
self.styles = []
Expand Down Expand Up @@ -416,16 +427,19 @@ def __init__(self):
"shape": "Cylinder"
}
)
self.docs = docs

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
pass

def dump(self, dumper: Dumper = Dumper()) -> None:
def dump(self, dumper: Dumper = Dumper()) -> str:
dumper.add('workspace {')
dumper.indent()
if self.docs:
dumper.add_directive("!docs", f"{self.docs}")

dumper.add('model {')
dumper.indent()
Expand Down
10 changes: 8 additions & 2 deletions pystructurizr/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@

import click

from pystructurizr.dsl import Dumper


@click.command()
@click.option('--view', prompt='Your view file (e.g. example.componentview)',
help='The view file to generate.')
def dump(view: str):
@click.option(
"--directives", help="Flag to add extra directives (i.e. !docs) or omit",
is_flag=True, default=False)
def dump(view: str, directives: bool):
try:
initial_modules = set(sys.modules.keys())
module = importlib.import_module(view)
imported_modules = set(sys.modules.keys()) - initial_modules
code = module.workspace.dump()
dumper = Dumper(with_directives=directives)
code = module.workspace.dump(dumper=dumper)
print(json.dumps({
"code": code,
"imported_modules": list(imported_modules)
Expand Down