julee 0.1.5__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.
Files changed (105) hide show
  1. julee/docs/sphinx_hcd/__init__.py +146 -13
  2. julee/docs/sphinx_hcd/domain/__init__.py +5 -0
  3. julee/docs/sphinx_hcd/domain/models/__init__.py +32 -0
  4. julee/docs/sphinx_hcd/domain/models/accelerator.py +152 -0
  5. julee/docs/sphinx_hcd/domain/models/app.py +151 -0
  6. julee/docs/sphinx_hcd/domain/models/code_info.py +121 -0
  7. julee/docs/sphinx_hcd/domain/models/epic.py +79 -0
  8. julee/docs/sphinx_hcd/domain/models/integration.py +230 -0
  9. julee/docs/sphinx_hcd/domain/models/journey.py +222 -0
  10. julee/docs/sphinx_hcd/domain/models/persona.py +106 -0
  11. julee/docs/sphinx_hcd/domain/models/story.py +128 -0
  12. julee/docs/sphinx_hcd/domain/repositories/__init__.py +25 -0
  13. julee/docs/sphinx_hcd/domain/repositories/accelerator.py +98 -0
  14. julee/docs/sphinx_hcd/domain/repositories/app.py +57 -0
  15. julee/docs/sphinx_hcd/domain/repositories/base.py +89 -0
  16. julee/docs/sphinx_hcd/domain/repositories/code_info.py +69 -0
  17. julee/docs/sphinx_hcd/domain/repositories/epic.py +62 -0
  18. julee/docs/sphinx_hcd/domain/repositories/integration.py +79 -0
  19. julee/docs/sphinx_hcd/domain/repositories/journey.py +106 -0
  20. julee/docs/sphinx_hcd/domain/repositories/story.py +68 -0
  21. julee/docs/sphinx_hcd/domain/use_cases/__init__.py +64 -0
  22. julee/docs/sphinx_hcd/domain/use_cases/derive_personas.py +166 -0
  23. julee/docs/sphinx_hcd/domain/use_cases/resolve_accelerator_references.py +236 -0
  24. julee/docs/sphinx_hcd/domain/use_cases/resolve_app_references.py +144 -0
  25. julee/docs/sphinx_hcd/domain/use_cases/resolve_story_references.py +121 -0
  26. julee/docs/sphinx_hcd/parsers/__init__.py +48 -0
  27. julee/docs/sphinx_hcd/parsers/ast.py +150 -0
  28. julee/docs/sphinx_hcd/parsers/gherkin.py +155 -0
  29. julee/docs/sphinx_hcd/parsers/yaml.py +184 -0
  30. julee/docs/sphinx_hcd/repositories/__init__.py +4 -0
  31. julee/docs/sphinx_hcd/repositories/memory/__init__.py +25 -0
  32. julee/docs/sphinx_hcd/repositories/memory/accelerator.py +86 -0
  33. julee/docs/sphinx_hcd/repositories/memory/app.py +45 -0
  34. julee/docs/sphinx_hcd/repositories/memory/base.py +106 -0
  35. julee/docs/sphinx_hcd/repositories/memory/code_info.py +59 -0
  36. julee/docs/sphinx_hcd/repositories/memory/epic.py +54 -0
  37. julee/docs/sphinx_hcd/repositories/memory/integration.py +70 -0
  38. julee/docs/sphinx_hcd/repositories/memory/journey.py +96 -0
  39. julee/docs/sphinx_hcd/repositories/memory/story.py +63 -0
  40. julee/docs/sphinx_hcd/sphinx/__init__.py +28 -0
  41. julee/docs/sphinx_hcd/sphinx/adapters.py +116 -0
  42. julee/docs/sphinx_hcd/sphinx/context.py +163 -0
  43. julee/docs/sphinx_hcd/sphinx/directives/__init__.py +160 -0
  44. julee/docs/sphinx_hcd/sphinx/directives/accelerator.py +576 -0
  45. julee/docs/sphinx_hcd/sphinx/directives/app.py +349 -0
  46. julee/docs/sphinx_hcd/sphinx/directives/base.py +211 -0
  47. julee/docs/sphinx_hcd/sphinx/directives/epic.py +434 -0
  48. julee/docs/sphinx_hcd/sphinx/directives/integration.py +220 -0
  49. julee/docs/sphinx_hcd/sphinx/directives/journey.py +642 -0
  50. julee/docs/sphinx_hcd/sphinx/directives/persona.py +345 -0
  51. julee/docs/sphinx_hcd/sphinx/directives/story.py +575 -0
  52. julee/docs/sphinx_hcd/sphinx/event_handlers/__init__.py +16 -0
  53. julee/docs/sphinx_hcd/sphinx/event_handlers/builder_inited.py +31 -0
  54. julee/docs/sphinx_hcd/sphinx/event_handlers/doctree_read.py +27 -0
  55. julee/docs/sphinx_hcd/sphinx/event_handlers/doctree_resolved.py +43 -0
  56. julee/docs/sphinx_hcd/sphinx/event_handlers/env_purge_doc.py +42 -0
  57. julee/docs/sphinx_hcd/sphinx/initialization.py +139 -0
  58. julee/docs/sphinx_hcd/tests/__init__.py +9 -0
  59. julee/docs/sphinx_hcd/tests/conftest.py +6 -0
  60. julee/docs/sphinx_hcd/tests/domain/__init__.py +1 -0
  61. julee/docs/sphinx_hcd/tests/domain/models/__init__.py +1 -0
  62. julee/docs/sphinx_hcd/tests/domain/models/test_accelerator.py +266 -0
  63. julee/docs/sphinx_hcd/tests/domain/models/test_app.py +258 -0
  64. julee/docs/sphinx_hcd/tests/domain/models/test_code_info.py +231 -0
  65. julee/docs/sphinx_hcd/tests/domain/models/test_epic.py +163 -0
  66. julee/docs/sphinx_hcd/tests/domain/models/test_integration.py +327 -0
  67. julee/docs/sphinx_hcd/tests/domain/models/test_journey.py +249 -0
  68. julee/docs/sphinx_hcd/tests/domain/models/test_persona.py +172 -0
  69. julee/docs/sphinx_hcd/tests/domain/models/test_story.py +216 -0
  70. julee/docs/sphinx_hcd/tests/domain/use_cases/__init__.py +1 -0
  71. julee/docs/sphinx_hcd/tests/domain/use_cases/test_derive_personas.py +314 -0
  72. julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_accelerator_references.py +476 -0
  73. julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_app_references.py +265 -0
  74. julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_story_references.py +229 -0
  75. julee/docs/sphinx_hcd/tests/integration/__init__.py +1 -0
  76. julee/docs/sphinx_hcd/tests/parsers/__init__.py +1 -0
  77. julee/docs/sphinx_hcd/tests/parsers/test_ast.py +298 -0
  78. julee/docs/sphinx_hcd/tests/parsers/test_gherkin.py +282 -0
  79. julee/docs/sphinx_hcd/tests/parsers/test_yaml.py +496 -0
  80. julee/docs/sphinx_hcd/tests/repositories/__init__.py +1 -0
  81. julee/docs/sphinx_hcd/tests/repositories/test_accelerator.py +298 -0
  82. julee/docs/sphinx_hcd/tests/repositories/test_app.py +218 -0
  83. julee/docs/sphinx_hcd/tests/repositories/test_base.py +151 -0
  84. julee/docs/sphinx_hcd/tests/repositories/test_code_info.py +253 -0
  85. julee/docs/sphinx_hcd/tests/repositories/test_epic.py +237 -0
  86. julee/docs/sphinx_hcd/tests/repositories/test_integration.py +268 -0
  87. julee/docs/sphinx_hcd/tests/repositories/test_journey.py +294 -0
  88. julee/docs/sphinx_hcd/tests/repositories/test_story.py +236 -0
  89. julee/docs/sphinx_hcd/tests/sphinx/__init__.py +1 -0
  90. julee/docs/sphinx_hcd/tests/sphinx/directives/__init__.py +1 -0
  91. julee/docs/sphinx_hcd/tests/sphinx/directives/test_base.py +160 -0
  92. julee/docs/sphinx_hcd/tests/sphinx/test_adapters.py +176 -0
  93. julee/docs/sphinx_hcd/tests/sphinx/test_context.py +257 -0
  94. {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/METADATA +2 -1
  95. {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/RECORD +98 -13
  96. julee/docs/sphinx_hcd/accelerators.py +0 -1175
  97. julee/docs/sphinx_hcd/apps.py +0 -518
  98. julee/docs/sphinx_hcd/epics.py +0 -453
  99. julee/docs/sphinx_hcd/integrations.py +0 -310
  100. julee/docs/sphinx_hcd/journeys.py +0 -797
  101. julee/docs/sphinx_hcd/personas.py +0 -457
  102. julee/docs/sphinx_hcd/stories.py +0 -960
  103. {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/WHEEL +0 -0
  104. {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/licenses/LICENSE +0 -0
  105. {julee-0.1.5.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
- }