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

Dev 2 #14

Merged
merged 3 commits into from
Jun 24, 2024
Merged
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
/_trials

# ignore outs folder
/_outputs
/_outputs*

# ignore python cache folders
*__pycache__

# ignore test files for now
_test_files
_test_files*
test_cli.py

## PYTHON
Expand Down
30 changes: 17 additions & 13 deletions client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
@dataclass
class FileFormat:
input_path: str
output_path: str


# Façade
Expand All @@ -35,9 +34,7 @@ def _compose_and_draw(self, pygraph: AGraph, flow: TokenSequence):

return diagram

def _compose_and_draw_inner(
self, pygraph: AGraph, flow: TokenSequence, name: str
):
def _compose_and_draw_inner(self, pygraph: AGraph, flow: TokenSequence, name: str):
pygraph.add_subgraph(
name=name, label=name, cluster=True, labelloc="t", fontcolor="blue"
)
Expand All @@ -46,18 +43,23 @@ def _compose_and_draw_inner(
returned = self._compose_and_draw(pygraph=sg, flow=flow)
return returned

def draw_epc(self, file_format: list[FileFormat]):
def _draw_architectural_connections(self, pygraph: AGraph, diagram: TokenSequence):
diagram.architecture.draw_connections(pygraph=pygraph)

def draw_epc(self, out_path: str, file_format: list[FileFormat]):
cluster = Cluster()
cluster.extract_flows(
file_name_list=[file.input_path for file in file_format]
)
cluster.extract_flows(file_name_list=[file.input_path for file in file_format])

main_flows = [flow.tokens for flow in cluster._main_flows]
ARCHG = AGraph(directed=True, compound=True)
for index, main_flow in enumerate(main_flows):
G = AGraph(directed=True, compound=True)
current_main_process = self._compose_and_draw(
pygraph=G, flow=main_flow
current_main_process = self._compose_and_draw(pygraph=G, flow=main_flow)

current_main_process.architecture.draw_architectural(
ARCHG, cluster._main_flows[index].name
)

inner_flows = [
flow
for flow in cluster._inner_flows
Expand All @@ -68,11 +70,13 @@ def draw_epc(self, file_format: list[FileFormat]):
pygraph=G, flow=inner_flow.tokens, name=inner_flow.name
)

file = file_format[index]
G.layout()
G.draw(
f"./_outputs/{cluster._main_flows[index].name}.png",
f"./{out_path}/{cluster._main_flows[index].name}.png",
prog="dot",
)

log.info(msg=f"{file.output_path} - Done.")
ARCHG.layout()
ARCHG.draw(f"./{out_path}/architecture.png", prog="dot")

log.info(msg="Done.")
10 changes: 1 addition & 9 deletions clusterer.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ def _find_main_flows(self, token: str, index: int, flows: Flows):
if ClusterKeywords.MAIN_CLUSTER in token:
flow = deepcopy(Flow())
flow.name = (
re.search(
rf"(?<={ClusterKeywords.MAIN_CLUSTER})(.*?)$", token
)[0]
re.search(rf"(?<={ClusterKeywords.MAIN_CLUSTER})(.*?)$", token)[0]
.lstrip()
.rstrip()
)
Expand Down Expand Up @@ -90,9 +88,3 @@ def extract_flows(self, file_name_list: list[str]):
indexes_processed = self._find_main_flows(
str(token_raw), index, main_flows
)

if indexes_processed:
start_index = main_flows.processed_indexes["start_index"]
end_index = main_flows.processed_indexes["end_index"] + 1

del parsed[start_index:end_index]
16 changes: 16 additions & 0 deletions compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from settings.language import (
NODE_KEYWORDS,
SYMBOLS,
ArchitecturalKeywords,
ClusterKeywords,
ContextKeywords,
Keywords,
Expand Down Expand Up @@ -52,6 +53,16 @@ def _split_flow(self, token: str):

return flows

def _handle_subscriptions(self, token: str, diagram: EpcDiagram) -> EpcNode:
if ArchitecturalKeywords.SUBSCRIBES in token:
raw_action = self._get_after(token, ArchitecturalKeywords.SUBSCRIBES)
subscriptions = list(
map(lambda x: x.lstrip().rstrip(), raw_action.split(","))
)

for subscription in subscriptions:
diagram.architecture.subscribe(subscription)

def _handle_activity(self, token: str, diagram: EpcDiagram) -> EpcNode:
if Keywords.ACTIVITY in token:
raw_action = self._get_after(token, Keywords.ACTIVITY)
Expand All @@ -76,6 +87,10 @@ def _handle_event(self, token: str, diagram: EpcDiagram) -> EpcNode:
raw_action = self._get_after(token, Keywords.EVENT)
diagram.push(EventNode(description=raw_action))

if ArchitecturalKeywords.PUBLISHES in token:
raw_action = self._get_after(token, ArchitecturalKeywords.PUBLISHES)
diagram.architecture.publish(raw_action)

def _handle_inner_flow(self, token: str, diagram: EpcDiagram) -> EpcNode:
if ClusterKeywords.INNER_FLOW in token:
raw_name = self._get_after(token, ClusterKeywords.INNER_FLOW)
Expand All @@ -84,6 +99,7 @@ def _handle_inner_flow(self, token: str, diagram: EpcDiagram) -> EpcNode:

def _handle_flow(self, token: str, diagram: EpcDiagram):
self._handle_inner_flow(token=token, diagram=diagram)
self._handle_subscriptions(token=token, diagram=diagram)

flows = self._split_flow(token=token)
for flow in flows:
Expand Down
76 changes: 74 additions & 2 deletions doctree.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,70 @@
import pygraphviz as pgv


class ArchitectureManager:
_subscribes: list[str]
_publishes: list[str]

def __init__(self, name: str) -> None:
self._subscribes = []
self._publishes = []

def subscribe(self, subscribe: str):
self._subscribes.append(subscribe)

def publish(self, publish: str):
self._publishes.append(publish)

def draw_architectural(self, pygraph: pgv.AGraph, diagram_name: str):
for subscribe in self._subscribes:
pygraph.add_node(
diagram_name,
color="palegoldenrod",
shape="polygon",
fontcolor="black",
style="filled",
fontsize=16,
width=4,
group="1",
)
pygraph.add_node(
subscribe,
color="darkred",
shape="octagon",
fontcolor="white",
style="filled",
width=1.0,
height=0.6,
fixedsize=False,
group="1",
)
pygraph.add_edge(subscribe, diagram_name)

for publish in self._publishes:
pygraph.add_node(
diagram_name,
color="palegoldenrod",
shape="polygon",
fontcolor="black",
style="filled",
fontsize=16,
width=4,
group="1",
)
pygraph.add_node(
publish,
color="darkred",
shape="octagon",
fontcolor="white",
style="filled",
width=1.0,
height=0.6,
fixedsize=False,
group="1",
)
pygraph.add_edge(diagram_name, publish)


class EpcNode(ABC):
_description: str
_start: str
Expand Down Expand Up @@ -53,7 +117,9 @@ def draw_line(self, pygraph: pgv.AGraph, end_id: str = None):
name=self._description + self._database,
)
db_id = self.add_db_node(
pygraph=graph, description=self._database, group=self._description
pygraph=graph,
description=self._database,
group=self._description,
)
graph.add_edge(self._description, db_id)

Expand Down Expand Up @@ -187,7 +253,10 @@ class IfNode(EpcNode):
branches: list[EpcNode]

def __init__(
self, description: str, next: Self | None = None, branches: list[EpcNode] = []
self,
description: str,
next: Self | None = None,
branches: list[EpcNode] = [],
) -> None:
super().__init__(description, next)
self.branches = branches
Expand Down Expand Up @@ -230,13 +299,16 @@ class EpcDiagram:
tail: EpcNode
inner_flow_names: list[str]
length: int
name: str
architecture: ArchitectureManager

def __init__(self, name: str = "EPC") -> None:
self.name = name
self.head = None
self.tail = None
self.length = 0
self.inner_flow_names = []
self.architecture = ArchitectureManager(name)

def add(self, node: EpcNode):
self.head = node
Expand Down
51 changes: 51 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os
from typing import Optional

import typer

from client import DocupytClient, FileFormat

app = typer.Typer()

client = DocupytClient()


def get_filepaths(directory):
"""
This function will generate the file names in a directory
tree by walking the tree either top-down or bottom-up. For each
directory in the tree rooted at directory top (including top itself),
it yields a 3-tuple (dirpath, dirnames, filenames).
"""
file_paths = []

for root, directories, files in os.walk(directory):
for filename in files:
filepath = os.path.join(root, filename)
file_paths.append(filepath)

return file_paths


@app.command()
def docupyt(path: Optional[str] = None, out_path: Optional[str] = "_outputs"):
if not path:
raise ValueError("Path is required")

if not os.path.exists(out_path):
os.mkdir(out_path)

formats = []

for filepath in get_filepaths(path):
formats.append(
FileFormat(
input_path=filepath,
)
)

client.draw_epc(out_path=out_path, file_format=formats)


if __name__ == "__main__":
app()
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# main
code-tokenize==0.2.0
typer==0.12.3
# test
pytest-cov==4.1.0
pytest==7.4.3
Expand Down
6 changes: 6 additions & 0 deletions settings/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class ClusterKeywords(StringEnum):
END_MAIN_CLUSTER = "end-diagram-main:"


class ArchitecturalKeywords(StringEnum):
SUBSCRIBES = "subscribes:"
PUBLISHES = "publishes:"


NODE_KEYWORDS = [
Keywords.ACTIVITY,
Keywords.EVENT,
Expand All @@ -45,4 +50,5 @@ class ClusterKeywords(StringEnum):
ContextKeywords.DATABASE,
ContextKeywords.API_CALL_OUT,
ContextKeywords.API_CALL_IN,
ArchitecturalKeywords.PUBLISHES,
]
16 changes: 16 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from setuptools import find_packages, setup

setup(
name="docupyt",
version="0.1.1",
author="Eyup Fatih Ersoy",
author_email="eyupfatih.ersoy@hotmail.com",
description="Docupyt",
packages=find_packages(""),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires=">=3.6",
)
Loading