julee 0.1.4__py3-none-any.whl → 0.1.6__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.
- julee/__init__.py +1 -1
- julee/api/tests/routers/test_assembly_specifications.py +2 -0
- julee/api/tests/routers/test_documents.py +2 -0
- julee/api/tests/routers/test_knowledge_service_configs.py +2 -0
- julee/api/tests/routers/test_knowledge_service_queries.py +2 -0
- julee/api/tests/routers/test_system.py +2 -0
- julee/api/tests/routers/test_workflows.py +2 -0
- julee/api/tests/test_app.py +2 -0
- julee/api/tests/test_dependencies.py +2 -0
- julee/api/tests/test_requests.py +2 -0
- julee/contrib/polling/__init__.py +22 -19
- julee/contrib/polling/apps/__init__.py +17 -0
- julee/contrib/polling/apps/worker/__init__.py +17 -0
- julee/contrib/polling/apps/worker/pipelines.py +288 -0
- julee/contrib/polling/domain/__init__.py +7 -9
- julee/contrib/polling/domain/models/__init__.py +6 -7
- julee/contrib/polling/domain/models/polling_config.py +18 -1
- julee/contrib/polling/domain/services/__init__.py +6 -5
- julee/contrib/polling/domain/services/poller.py +1 -1
- julee/contrib/polling/infrastructure/__init__.py +9 -8
- julee/contrib/polling/infrastructure/services/__init__.py +6 -5
- julee/contrib/polling/infrastructure/services/polling/__init__.py +6 -5
- julee/contrib/polling/infrastructure/services/polling/http/__init__.py +6 -5
- julee/contrib/polling/infrastructure/services/polling/http/http_poller_service.py +5 -2
- julee/contrib/polling/infrastructure/temporal/__init__.py +12 -12
- julee/contrib/polling/infrastructure/temporal/activities.py +1 -1
- julee/contrib/polling/infrastructure/temporal/manager.py +291 -0
- julee/contrib/polling/infrastructure/temporal/proxies.py +1 -1
- julee/contrib/polling/tests/unit/apps/worker/test_pipelines.py +580 -0
- julee/contrib/polling/tests/unit/infrastructure/services/polling/http/test_http_poller_service.py +40 -2
- julee/contrib/polling/tests/unit/infrastructure/temporal/__init__.py +7 -0
- julee/contrib/polling/tests/unit/infrastructure/temporal/test_manager.py +475 -0
- julee/docs/sphinx_hcd/__init__.py +146 -13
- julee/docs/sphinx_hcd/domain/__init__.py +5 -0
- julee/docs/sphinx_hcd/domain/models/__init__.py +32 -0
- julee/docs/sphinx_hcd/domain/models/accelerator.py +152 -0
- julee/docs/sphinx_hcd/domain/models/app.py +151 -0
- julee/docs/sphinx_hcd/domain/models/code_info.py +121 -0
- julee/docs/sphinx_hcd/domain/models/epic.py +79 -0
- julee/docs/sphinx_hcd/domain/models/integration.py +230 -0
- julee/docs/sphinx_hcd/domain/models/journey.py +222 -0
- julee/docs/sphinx_hcd/domain/models/persona.py +106 -0
- julee/docs/sphinx_hcd/domain/models/story.py +128 -0
- julee/docs/sphinx_hcd/domain/repositories/__init__.py +25 -0
- julee/docs/sphinx_hcd/domain/repositories/accelerator.py +98 -0
- julee/docs/sphinx_hcd/domain/repositories/app.py +57 -0
- julee/docs/sphinx_hcd/domain/repositories/base.py +89 -0
- julee/docs/sphinx_hcd/domain/repositories/code_info.py +69 -0
- julee/docs/sphinx_hcd/domain/repositories/epic.py +62 -0
- julee/docs/sphinx_hcd/domain/repositories/integration.py +79 -0
- julee/docs/sphinx_hcd/domain/repositories/journey.py +106 -0
- julee/docs/sphinx_hcd/domain/repositories/story.py +68 -0
- julee/docs/sphinx_hcd/domain/use_cases/__init__.py +64 -0
- julee/docs/sphinx_hcd/domain/use_cases/derive_personas.py +166 -0
- julee/docs/sphinx_hcd/domain/use_cases/resolve_accelerator_references.py +236 -0
- julee/docs/sphinx_hcd/domain/use_cases/resolve_app_references.py +144 -0
- julee/docs/sphinx_hcd/domain/use_cases/resolve_story_references.py +121 -0
- julee/docs/sphinx_hcd/parsers/__init__.py +48 -0
- julee/docs/sphinx_hcd/parsers/ast.py +150 -0
- julee/docs/sphinx_hcd/parsers/gherkin.py +155 -0
- julee/docs/sphinx_hcd/parsers/yaml.py +184 -0
- julee/docs/sphinx_hcd/repositories/__init__.py +4 -0
- julee/docs/sphinx_hcd/repositories/memory/__init__.py +25 -0
- julee/docs/sphinx_hcd/repositories/memory/accelerator.py +86 -0
- julee/docs/sphinx_hcd/repositories/memory/app.py +45 -0
- julee/docs/sphinx_hcd/repositories/memory/base.py +106 -0
- julee/docs/sphinx_hcd/repositories/memory/code_info.py +59 -0
- julee/docs/sphinx_hcd/repositories/memory/epic.py +54 -0
- julee/docs/sphinx_hcd/repositories/memory/integration.py +70 -0
- julee/docs/sphinx_hcd/repositories/memory/journey.py +96 -0
- julee/docs/sphinx_hcd/repositories/memory/story.py +63 -0
- julee/docs/sphinx_hcd/sphinx/__init__.py +28 -0
- julee/docs/sphinx_hcd/sphinx/adapters.py +116 -0
- julee/docs/sphinx_hcd/sphinx/context.py +163 -0
- julee/docs/sphinx_hcd/sphinx/directives/__init__.py +160 -0
- julee/docs/sphinx_hcd/sphinx/directives/accelerator.py +576 -0
- julee/docs/sphinx_hcd/sphinx/directives/app.py +349 -0
- julee/docs/sphinx_hcd/sphinx/directives/base.py +211 -0
- julee/docs/sphinx_hcd/sphinx/directives/epic.py +434 -0
- julee/docs/sphinx_hcd/sphinx/directives/integration.py +220 -0
- julee/docs/sphinx_hcd/sphinx/directives/journey.py +642 -0
- julee/docs/sphinx_hcd/sphinx/directives/persona.py +345 -0
- julee/docs/sphinx_hcd/sphinx/directives/story.py +575 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/__init__.py +16 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/builder_inited.py +31 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/doctree_read.py +27 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/doctree_resolved.py +43 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/env_purge_doc.py +42 -0
- julee/docs/sphinx_hcd/sphinx/initialization.py +139 -0
- julee/docs/sphinx_hcd/tests/__init__.py +9 -0
- julee/docs/sphinx_hcd/tests/conftest.py +6 -0
- julee/docs/sphinx_hcd/tests/domain/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/domain/models/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_accelerator.py +266 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_app.py +258 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_code_info.py +231 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_epic.py +163 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_integration.py +327 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_journey.py +249 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_persona.py +172 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_story.py +216 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_derive_personas.py +314 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_accelerator_references.py +476 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_app_references.py +265 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_story_references.py +229 -0
- julee/docs/sphinx_hcd/tests/integration/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/parsers/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/parsers/test_ast.py +298 -0
- julee/docs/sphinx_hcd/tests/parsers/test_gherkin.py +282 -0
- julee/docs/sphinx_hcd/tests/parsers/test_yaml.py +496 -0
- julee/docs/sphinx_hcd/tests/repositories/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/repositories/test_accelerator.py +298 -0
- julee/docs/sphinx_hcd/tests/repositories/test_app.py +218 -0
- julee/docs/sphinx_hcd/tests/repositories/test_base.py +151 -0
- julee/docs/sphinx_hcd/tests/repositories/test_code_info.py +253 -0
- julee/docs/sphinx_hcd/tests/repositories/test_epic.py +237 -0
- julee/docs/sphinx_hcd/tests/repositories/test_integration.py +268 -0
- julee/docs/sphinx_hcd/tests/repositories/test_journey.py +294 -0
- julee/docs/sphinx_hcd/tests/repositories/test_story.py +236 -0
- julee/docs/sphinx_hcd/tests/sphinx/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/sphinx/directives/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/sphinx/directives/test_base.py +160 -0
- julee/docs/sphinx_hcd/tests/sphinx/test_adapters.py +176 -0
- julee/docs/sphinx_hcd/tests/sphinx/test_context.py +257 -0
- julee/domain/models/assembly/tests/test_assembly.py +2 -0
- julee/domain/models/assembly_specification/tests/test_assembly_specification.py +2 -0
- julee/domain/models/assembly_specification/tests/test_knowledge_service_query.py +2 -0
- julee/domain/models/custom_fields/tests/test_custom_fields.py +2 -0
- julee/domain/models/document/tests/test_document.py +2 -0
- julee/domain/models/policy/tests/test_document_policy_validation.py +2 -0
- julee/domain/models/policy/tests/test_policy.py +2 -0
- julee/domain/use_cases/tests/test_extract_assemble_data.py +2 -0
- julee/domain/use_cases/tests/test_initialize_system_data.py +2 -0
- julee/domain/use_cases/tests/test_validate_document.py +2 -0
- julee/maintenance/release.py +10 -5
- julee/repositories/memory/tests/test_document.py +2 -0
- julee/repositories/memory/tests/test_document_policy_validation.py +2 -0
- julee/repositories/memory/tests/test_policy.py +2 -0
- julee/repositories/minio/tests/test_assembly.py +2 -0
- julee/repositories/minio/tests/test_assembly_specification.py +2 -0
- julee/repositories/minio/tests/test_client_protocol.py +3 -0
- julee/repositories/minio/tests/test_document.py +2 -0
- julee/repositories/minio/tests/test_document_policy_validation.py +2 -0
- julee/repositories/minio/tests/test_knowledge_service_config.py +2 -0
- julee/repositories/minio/tests/test_knowledge_service_query.py +2 -0
- julee/repositories/minio/tests/test_policy.py +2 -0
- julee/services/knowledge_service/anthropic/tests/test_knowledge_service.py +2 -0
- julee/services/knowledge_service/memory/test_knowledge_service.py +2 -0
- julee/services/knowledge_service/test_factory.py +2 -0
- julee/util/tests/test_decorators.py +2 -0
- julee-0.1.6.dist-info/METADATA +104 -0
- julee-0.1.6.dist-info/RECORD +288 -0
- julee/docs/sphinx_hcd/accelerators.py +0 -1175
- julee/docs/sphinx_hcd/apps.py +0 -518
- julee/docs/sphinx_hcd/epics.py +0 -453
- julee/docs/sphinx_hcd/integrations.py +0 -310
- julee/docs/sphinx_hcd/journeys.py +0 -797
- julee/docs/sphinx_hcd/personas.py +0 -457
- julee/docs/sphinx_hcd/stories.py +0 -960
- julee-0.1.4.dist-info/METADATA +0 -197
- julee-0.1.4.dist-info/RECORD +0 -196
- {julee-0.1.4.dist-info → julee-0.1.6.dist-info}/WHEEL +0 -0
- {julee-0.1.4.dist-info → julee-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {julee-0.1.4.dist-info → julee-0.1.6.dist-info}/top_level.txt +0 -0
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
"""Sphinx extension for integrations.
|
|
2
|
-
|
|
3
|
-
Scans integration manifests for definitions and provides directives to render
|
|
4
|
-
integration information with external dependencies.
|
|
5
|
-
|
|
6
|
-
Provides directives:
|
|
7
|
-
- define-integration: Render integration info from YAML
|
|
8
|
-
- integration-index: Generate index with architecture diagram
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
|
|
13
|
-
import yaml
|
|
14
|
-
from docutils import nodes
|
|
15
|
-
from sphinx.util import logging
|
|
16
|
-
from sphinx.util.docutils import SphinxDirective
|
|
17
|
-
|
|
18
|
-
from .config import get_config
|
|
19
|
-
|
|
20
|
-
logger = logging.getLogger(__name__)
|
|
21
|
-
|
|
22
|
-
# Global registry populated at build init
|
|
23
|
-
_integration_registry: dict = {}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def get_integration_registry() -> dict:
|
|
27
|
-
"""Get the integration registry."""
|
|
28
|
-
return _integration_registry
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def get_documented_integrations(env) -> set:
|
|
32
|
-
"""Get documented integrations set from env, creating if needed."""
|
|
33
|
-
if not hasattr(env, "documented_integrations"):
|
|
34
|
-
env.documented_integrations = set()
|
|
35
|
-
return env.documented_integrations
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def scan_integration_manifests(app):
|
|
39
|
-
"""Scan integration manifests and build the registry."""
|
|
40
|
-
global _integration_registry
|
|
41
|
-
_integration_registry = {}
|
|
42
|
-
|
|
43
|
-
config = get_config()
|
|
44
|
-
integrations_dir = config.get_path("integration_manifests")
|
|
45
|
-
|
|
46
|
-
if not integrations_dir.exists():
|
|
47
|
-
logger.info(
|
|
48
|
-
f"Integrations directory not found at {integrations_dir} - no integration manifests to index"
|
|
49
|
-
)
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
for int_dir in integrations_dir.iterdir():
|
|
53
|
-
if not int_dir.is_dir() or int_dir.name.startswith("_"):
|
|
54
|
-
continue
|
|
55
|
-
|
|
56
|
-
manifest_path = int_dir / "integration.yaml"
|
|
57
|
-
if not manifest_path.exists():
|
|
58
|
-
continue
|
|
59
|
-
|
|
60
|
-
module_name = int_dir.name
|
|
61
|
-
|
|
62
|
-
try:
|
|
63
|
-
with open(manifest_path) as f:
|
|
64
|
-
manifest = yaml.safe_load(f)
|
|
65
|
-
except Exception as e:
|
|
66
|
-
logger.warning(f"Could not read {manifest_path}: {e}")
|
|
67
|
-
continue
|
|
68
|
-
|
|
69
|
-
slug = manifest.get("slug", module_name.replace("_", "-"))
|
|
70
|
-
_integration_registry[slug] = {
|
|
71
|
-
"slug": slug,
|
|
72
|
-
"module": module_name,
|
|
73
|
-
"name": manifest.get("name", slug.replace("-", " ").title()),
|
|
74
|
-
"description": manifest.get("description", "").strip(),
|
|
75
|
-
"direction": manifest.get("direction", "bidirectional"),
|
|
76
|
-
"depends_on": manifest.get("depends_on", []),
|
|
77
|
-
"manifest_path": str(manifest_path),
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
logger.info(f"Indexed {len(_integration_registry)} integrations from manifests")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def validate_integrations(app, env):
|
|
84
|
-
"""Validate integration coverage after all documents are read."""
|
|
85
|
-
documented = get_documented_integrations(env)
|
|
86
|
-
|
|
87
|
-
# Check for integrations without documentation
|
|
88
|
-
for slug in _integration_registry:
|
|
89
|
-
if slug not in documented:
|
|
90
|
-
logger.warning(
|
|
91
|
-
f"Integration '{slug}' has no docs page. "
|
|
92
|
-
f"Create integrations/{slug}.rst with '.. define-integration:: {slug}'"
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
# Check for documented integrations without manifests
|
|
96
|
-
for slug in documented:
|
|
97
|
-
if slug not in _integration_registry:
|
|
98
|
-
logger.warning(
|
|
99
|
-
f"Integration '{slug}' documented but has no manifest. "
|
|
100
|
-
f"Create integration.yaml in the appropriate directory"
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
class DefineIntegrationDirective(SphinxDirective):
|
|
105
|
-
"""Render integration info from YAML manifest.
|
|
106
|
-
|
|
107
|
-
Usage::
|
|
108
|
-
|
|
109
|
-
.. define-integration:: pilot-data-collection
|
|
110
|
-
"""
|
|
111
|
-
|
|
112
|
-
required_arguments = 1
|
|
113
|
-
|
|
114
|
-
def run(self):
|
|
115
|
-
slug = self.arguments[0]
|
|
116
|
-
get_documented_integrations(self.env).add(slug)
|
|
117
|
-
|
|
118
|
-
node = DefineIntegrationPlaceholder()
|
|
119
|
-
node["integration_slug"] = slug
|
|
120
|
-
return [node]
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
class DefineIntegrationPlaceholder(nodes.General, nodes.Element):
|
|
124
|
-
"""Placeholder node for define-integration, replaced at doctree-resolved."""
|
|
125
|
-
|
|
126
|
-
pass
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class IntegrationIndexDirective(SphinxDirective):
|
|
130
|
-
"""Generate integration index with architecture diagram.
|
|
131
|
-
|
|
132
|
-
Usage::
|
|
133
|
-
|
|
134
|
-
.. integration-index::
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
def run(self):
|
|
138
|
-
return [IntegrationIndexPlaceholder()]
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
class IntegrationIndexPlaceholder(nodes.General, nodes.Element):
|
|
142
|
-
"""Placeholder node for integration-index, replaced at doctree-resolved."""
|
|
143
|
-
|
|
144
|
-
pass
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def build_integration_content(slug, docname):
|
|
148
|
-
"""Build content nodes for an integration page."""
|
|
149
|
-
from sphinx.addnodes import seealso
|
|
150
|
-
|
|
151
|
-
if slug not in _integration_registry:
|
|
152
|
-
para = nodes.paragraph()
|
|
153
|
-
para += nodes.problematic(text=f"Integration '{slug}' not found")
|
|
154
|
-
return [para]
|
|
155
|
-
|
|
156
|
-
data = _integration_registry[slug]
|
|
157
|
-
result_nodes = []
|
|
158
|
-
|
|
159
|
-
# Description
|
|
160
|
-
if data["description"]:
|
|
161
|
-
desc_para = nodes.paragraph()
|
|
162
|
-
desc_para += nodes.Text(data["description"])
|
|
163
|
-
result_nodes.append(desc_para)
|
|
164
|
-
|
|
165
|
-
# Seealso with metadata
|
|
166
|
-
seealso_node = seealso()
|
|
167
|
-
|
|
168
|
-
# Direction
|
|
169
|
-
direction_labels = {
|
|
170
|
-
"inbound": "Inbound (data source)",
|
|
171
|
-
"outbound": "Outbound (data sink)",
|
|
172
|
-
"bidirectional": "Bidirectional",
|
|
173
|
-
}
|
|
174
|
-
dir_para = nodes.paragraph()
|
|
175
|
-
dir_para += nodes.strong(text="Direction: ")
|
|
176
|
-
dir_para += nodes.Text(direction_labels.get(data["direction"], data["direction"]))
|
|
177
|
-
seealso_node += dir_para
|
|
178
|
-
|
|
179
|
-
# Module
|
|
180
|
-
mod_para = nodes.paragraph()
|
|
181
|
-
mod_para += nodes.strong(text="Module: ")
|
|
182
|
-
mod_para += nodes.literal(text=f"integrations.{data['module']}")
|
|
183
|
-
seealso_node += mod_para
|
|
184
|
-
|
|
185
|
-
# External dependencies
|
|
186
|
-
if data["depends_on"]:
|
|
187
|
-
deps_para = nodes.paragraph()
|
|
188
|
-
deps_para += nodes.strong(text="Depends On: ")
|
|
189
|
-
for i, dep in enumerate(data["depends_on"]):
|
|
190
|
-
if dep.get("url"):
|
|
191
|
-
ref = nodes.reference("", "", refuri=dep["url"])
|
|
192
|
-
ref += nodes.Text(dep["name"])
|
|
193
|
-
deps_para += ref
|
|
194
|
-
else:
|
|
195
|
-
deps_para += nodes.Text(dep["name"])
|
|
196
|
-
if i < len(data["depends_on"]) - 1:
|
|
197
|
-
deps_para += nodes.Text(", ")
|
|
198
|
-
seealso_node += deps_para
|
|
199
|
-
|
|
200
|
-
result_nodes.append(seealso_node)
|
|
201
|
-
return result_nodes
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def build_integration_index(docname):
|
|
205
|
-
"""Build integration index with architecture diagram."""
|
|
206
|
-
from sphinxcontrib.plantuml import plantuml
|
|
207
|
-
|
|
208
|
-
result_nodes = []
|
|
209
|
-
|
|
210
|
-
if not _integration_registry:
|
|
211
|
-
para = nodes.paragraph()
|
|
212
|
-
para += nodes.emphasis(text="No integrations defined")
|
|
213
|
-
return [para]
|
|
214
|
-
|
|
215
|
-
# Build PlantUML diagram
|
|
216
|
-
lines = [
|
|
217
|
-
"@startuml",
|
|
218
|
-
"skinparam componentStyle rectangle",
|
|
219
|
-
"skinparam defaultTextAlignment center",
|
|
220
|
-
"skinparam component {",
|
|
221
|
-
" BackgroundColor<<integration>> LightBlue",
|
|
222
|
-
" BackgroundColor<<external>> LightYellow",
|
|
223
|
-
" BackgroundColor<<core>> LightGreen",
|
|
224
|
-
"}",
|
|
225
|
-
"",
|
|
226
|
-
'title "Integration Architecture"',
|
|
227
|
-
"",
|
|
228
|
-
"' Core system",
|
|
229
|
-
'component "Julee\\nSolution" as core <<core>>',
|
|
230
|
-
"",
|
|
231
|
-
"' Integrations and their external dependencies",
|
|
232
|
-
]
|
|
233
|
-
|
|
234
|
-
for slug, data in sorted(_integration_registry.items()):
|
|
235
|
-
int_id = slug.replace("-", "_")
|
|
236
|
-
lines.append(f'component "{data["name"]}" as {int_id} <<integration>>')
|
|
237
|
-
|
|
238
|
-
for dep in data.get("depends_on", []):
|
|
239
|
-
dep_id = dep["name"].lower().replace(" ", "_").replace("-", "_")
|
|
240
|
-
dep_label = dep["name"]
|
|
241
|
-
if dep.get("description"):
|
|
242
|
-
dep_label += f"\\n({dep['description']})"
|
|
243
|
-
lines.append(f'component "{dep_label}" as {dep_id} <<external>>')
|
|
244
|
-
|
|
245
|
-
lines.append("")
|
|
246
|
-
lines.append("' Relationships")
|
|
247
|
-
|
|
248
|
-
for slug, data in sorted(_integration_registry.items()):
|
|
249
|
-
int_id = slug.replace("-", "_")
|
|
250
|
-
direction = data.get("direction", "bidirectional")
|
|
251
|
-
|
|
252
|
-
# Core to/from integration
|
|
253
|
-
if direction == "inbound":
|
|
254
|
-
lines.append(f"{int_id} --> core")
|
|
255
|
-
elif direction == "outbound":
|
|
256
|
-
lines.append(f"core --> {int_id}")
|
|
257
|
-
else:
|
|
258
|
-
lines.append(f"core <--> {int_id}")
|
|
259
|
-
|
|
260
|
-
# Integration to external dependencies
|
|
261
|
-
for dep in data.get("depends_on", []):
|
|
262
|
-
dep_id = dep["name"].lower().replace(" ", "_").replace("-", "_")
|
|
263
|
-
if direction == "inbound":
|
|
264
|
-
lines.append(f"{dep_id} --> {int_id}")
|
|
265
|
-
elif direction == "outbound":
|
|
266
|
-
lines.append(f"{int_id} --> {dep_id}")
|
|
267
|
-
else:
|
|
268
|
-
lines.append(f"{int_id} <--> {dep_id}")
|
|
269
|
-
|
|
270
|
-
lines.append("")
|
|
271
|
-
lines.append("@enduml")
|
|
272
|
-
|
|
273
|
-
puml_source = "\n".join(lines)
|
|
274
|
-
node = plantuml(puml_source)
|
|
275
|
-
node["uml"] = puml_source
|
|
276
|
-
node["incdir"] = os.path.dirname(docname)
|
|
277
|
-
node["filename"] = os.path.basename(docname) + ".rst"
|
|
278
|
-
result_nodes.append(node)
|
|
279
|
-
|
|
280
|
-
return result_nodes
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
def process_integration_placeholders(app, doctree, docname):
|
|
284
|
-
"""Replace integration placeholders after all documents are read."""
|
|
285
|
-
for node in doctree.traverse(DefineIntegrationPlaceholder):
|
|
286
|
-
slug = node["integration_slug"]
|
|
287
|
-
content = build_integration_content(slug, docname)
|
|
288
|
-
node.replace_self(content)
|
|
289
|
-
|
|
290
|
-
for node in doctree.traverse(IntegrationIndexPlaceholder):
|
|
291
|
-
content = build_integration_index(docname)
|
|
292
|
-
node.replace_self(content)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
def setup(app):
|
|
296
|
-
app.connect("builder-inited", scan_integration_manifests)
|
|
297
|
-
app.connect("env-check-consistency", validate_integrations)
|
|
298
|
-
app.connect("doctree-resolved", process_integration_placeholders)
|
|
299
|
-
|
|
300
|
-
app.add_directive("define-integration", DefineIntegrationDirective)
|
|
301
|
-
app.add_directive("integration-index", IntegrationIndexDirective)
|
|
302
|
-
|
|
303
|
-
app.add_node(DefineIntegrationPlaceholder)
|
|
304
|
-
app.add_node(IntegrationIndexPlaceholder)
|
|
305
|
-
|
|
306
|
-
return {
|
|
307
|
-
"version": "1.0",
|
|
308
|
-
"parallel_read_safe": False,
|
|
309
|
-
"parallel_write_safe": True,
|
|
310
|
-
}
|