ssot-views 0.2.4__tar.gz

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.
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: ssot-views
3
+ Version: 0.2.4
4
+ Summary: Derived projections, reports, and graph exports for SSOT.
5
+ Author-email: Jacob Stewart <jacob@swarmauri.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/groupsum/ssot-registry
8
+ Project-URL: Repository, https://github.com/groupsum/ssot-registry
9
+ Project-URL: Issues, https://github.com/groupsum/ssot-registry/issues
10
+ Keywords: ssot,views,reports,graph,projections
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: <3.14,>=3.10
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: ssot-contracts==0.2.4
25
+ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
26
+
27
+ # ssot-views
28
+
29
+ Derived SSOT projections:
30
+
31
+ - validation and certification reports
32
+ - graph exports
33
+ - future shared view metadata
@@ -0,0 +1,7 @@
1
+ # ssot-views
2
+
3
+ Derived SSOT projections:
4
+
5
+ - validation and certification reports
6
+ - graph exports
7
+ - future shared view metadata
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ssot-views"
7
+ version = "0.2.4"
8
+ description = "Derived projections, reports, and graph exports for SSOT."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10,<3.14"
11
+ license = "Apache-2.0"
12
+ authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
13
+ dependencies = [
14
+ "ssot-contracts==0.2.4",
15
+ "tomli>=2.0.1; python_version < '3.11'",
16
+ ]
17
+ keywords = ["ssot", "views", "reports", "graph", "projections"]
18
+ classifiers = [
19
+ "Development Status :: 3 - Alpha",
20
+ "Intended Audience :: Developers",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Scientific/Engineering :: Information Analysis",
29
+ "Topic :: Software Development :: Libraries :: Python Modules",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/groupsum/ssot-registry"
34
+ Repository = "https://github.com/groupsum/ssot-registry"
35
+ Issues = "https://github.com/groupsum/ssot-registry/issues"
36
+
37
+ [tool.setuptools]
38
+ package-dir = {"" = "src"}
39
+
40
+ [tool.setuptools.packages.find]
41
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ from .graph import build_graph_dot, build_graph_json
2
+ from .reports import build_certification_report, build_summary, build_validation_report
3
+
4
+ __all__ = [
5
+ "build_certification_report",
6
+ "build_graph_dot",
7
+ "build_graph_json",
8
+ "build_summary",
9
+ "build_validation_report",
10
+ ]
@@ -0,0 +1,11 @@
1
+ from .export_json import build_graph_json
2
+ from .export_dot import build_graph_dot
3
+
4
+ __all__ = [
5
+ "build_graph_json",
6
+ "build_graph_dot",
7
+ ]
8
+ from .export_dot import build_graph_dot
9
+ from .export_json import build_graph_json
10
+
11
+ __all__ = ["build_graph_dot", "build_graph_json"]
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from .export_json import build_graph_json
4
+
5
+
6
+ def _dot_escape(value: str) -> str:
7
+ return value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n").replace("\r", "")
8
+
9
+
10
+ def build_graph_dot(registry: dict[str, object]) -> str:
11
+ graph = build_graph_json(registry)
12
+ lines = ["digraph ssot_registry {"]
13
+ for node in graph["nodes"]:
14
+ node_id = _dot_escape(node["id"])
15
+ label = _dot_escape(f'{node["id"]}\\n({node["kind"]})')
16
+ lines.append(f' "{node_id}" [label="{label}"];')
17
+ for edge in graph["edges"]:
18
+ edge_from = _dot_escape(edge["from"])
19
+ edge_to = _dot_escape(edge["to"])
20
+ edge_type = _dot_escape(edge["type"])
21
+ lines.append(f' "{edge_from}" -> "{edge_to}" [label="{edge_type}"];')
22
+ lines.append("}")
23
+ return "\n".join(lines) + "\n"
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ from ssot_contracts.generated.python.enums import GRAPH_NODE_KIND
4
+
5
+
6
+ def build_graph_json(registry: dict[str, object]) -> dict[str, object]:
7
+ nodes: list[dict[str, str]] = []
8
+ edges: list[dict[str, str]] = []
9
+
10
+ for section, kind in GRAPH_NODE_KIND.items():
11
+ for row in registry.get(section, []):
12
+ nodes.append({"id": row["id"], "kind": kind})
13
+
14
+ for boundary in registry.get("boundaries", []):
15
+ for feature_id in boundary.get("feature_ids", []):
16
+ edges.append({"type": "SCOPES", "from": boundary["id"], "to": feature_id})
17
+ for profile_id in boundary.get("profile_ids", []):
18
+ edges.append({"type": "SCOPES_PROFILE", "from": boundary["id"], "to": profile_id})
19
+
20
+ for profile in registry.get("profiles", []):
21
+ for feature_id in profile.get("feature_ids", []):
22
+ edges.append({"type": "BUNDLES", "from": profile["id"], "to": feature_id})
23
+ for nested_profile_id in profile.get("profile_ids", []):
24
+ edges.append({"type": "COMPOSES", "from": profile["id"], "to": nested_profile_id})
25
+
26
+ for release in registry.get("releases", []):
27
+ edges.append({"type": "USES_BOUNDARY", "from": release["id"], "to": release["boundary_id"]})
28
+ for claim_id in release.get("claim_ids", []):
29
+ edges.append({"type": "PUBLISHES", "from": release["id"], "to": claim_id})
30
+ for evidence_id in release.get("evidence_ids", []):
31
+ edges.append({"type": "INCLUDES", "from": release["id"], "to": evidence_id})
32
+
33
+ for feature in registry.get("features", []):
34
+ for required_feature_id in feature.get("requires", []):
35
+ edges.append({"type": "REQUIRES", "from": feature["id"], "to": required_feature_id})
36
+ for test_id in feature.get("test_ids", []):
37
+ edges.append({"type": "COVERED_BY", "from": feature["id"], "to": test_id})
38
+
39
+ for claim in registry.get("claims", []):
40
+ for feature_id in claim.get("feature_ids", []):
41
+ edges.append({"type": "ASSERTS", "from": claim["id"], "to": feature_id})
42
+ for test_id in claim.get("test_ids", []):
43
+ edges.append({"type": "VERIFIES", "from": test_id, "to": claim["id"]})
44
+ for evidence_id in claim.get("evidence_ids", []):
45
+ edges.append({"type": "SUPPORTS", "from": evidence_id, "to": claim["id"]})
46
+
47
+ for test in registry.get("tests", []):
48
+ for evidence_id in test.get("evidence_ids", []):
49
+ edges.append({"type": "DERIVES_FROM", "from": evidence_id, "to": test["id"]})
50
+
51
+ for issue in registry.get("issues", []):
52
+ for section_key in ("feature_ids", "claim_ids", "test_ids", "evidence_ids", "risk_ids"):
53
+ for target_id in issue.get(section_key, []):
54
+ edges.append({"type": "AFFECTS", "from": issue["id"], "to": target_id})
55
+
56
+ for risk in registry.get("risks", []):
57
+ for section_key in ("feature_ids", "claim_ids", "test_ids", "evidence_ids", "issue_ids"):
58
+ for target_id in risk.get(section_key, []):
59
+ edges.append({"type": "AFFECTS", "from": risk["id"], "to": target_id})
60
+
61
+ return {
62
+ "nodes": nodes,
63
+ "edges": edges,
64
+ }
@@ -0,0 +1,14 @@
1
+ from .validation_report import build_validation_report
2
+ from .certification_report import build_certification_report
3
+ from .summary import build_summary
4
+
5
+ __all__ = [
6
+ "build_validation_report",
7
+ "build_certification_report",
8
+ "build_summary",
9
+ ]
10
+ from .certification_report import build_certification_report
11
+ from .summary import build_summary
12
+ from .validation_report import build_validation_report
13
+
14
+ __all__ = ["build_certification_report", "build_summary", "build_validation_report"]
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ from .summary import build_summary
4
+
5
+
6
+ def build_certification_report(
7
+ registry: dict[str, object],
8
+ registry_path: str,
9
+ release_report: dict[str, object],
10
+ ) -> dict[str, object]:
11
+ boundary = release_report.get("boundary", {})
12
+ return {
13
+ "passed": bool(release_report.get("passed")),
14
+ "registry_path": registry_path,
15
+ "release": release_report,
16
+ "boundary_scope": {
17
+ "boundary_id": boundary.get("id"),
18
+ "profile_ids": boundary.get("profile_ids", []),
19
+ "feature_ids": boundary.get("feature_ids", []),
20
+ },
21
+ "summary": build_summary(registry),
22
+ }
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ def build_summary(registry: dict[str, object]) -> dict[str, object]:
4
+ profile_status = {"passing": 0, "failing": 0, "draft": 0}
5
+ profiles = registry.get("profiles", [])
6
+ if not isinstance(profiles, list):
7
+ profiles = []
8
+ for profile in profiles:
9
+ if not isinstance(profile, dict):
10
+ continue
11
+ if profile.get("status") == "draft":
12
+ profile_status["draft"] += 1
13
+ else:
14
+ profile_status["passing"] += 1
15
+ return {
16
+ "counts": {
17
+ "features": len(registry.get("features", [])),
18
+ "profiles": len(registry.get("profiles", [])),
19
+ "tests": len(registry.get("tests", [])),
20
+ "claims": len(registry.get("claims", [])),
21
+ "evidence": len(registry.get("evidence", [])),
22
+ "issues": len(registry.get("issues", [])),
23
+ "risks": len(registry.get("risks", [])),
24
+ "boundaries": len(registry.get("boundaries", [])),
25
+ "releases": len(registry.get("releases", [])),
26
+ "adrs": len(registry.get("adrs", [])),
27
+ "specs": len(registry.get("specs", [])),
28
+ },
29
+ "profile_status": profile_status,
30
+ }
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from .summary import build_summary
4
+
5
+
6
+ def build_validation_report(
7
+ registry: dict[str, object],
8
+ registry_path: str,
9
+ failures: list[str],
10
+ warnings: list[str],
11
+ ) -> dict[str, object]:
12
+ return {
13
+ "passed": not failures,
14
+ "registry_path": registry_path,
15
+ "failures": failures,
16
+ "warnings": warnings,
17
+ "summary": build_summary(registry),
18
+ }
@@ -0,0 +1,33 @@
1
+ Metadata-Version: 2.4
2
+ Name: ssot-views
3
+ Version: 0.2.4
4
+ Summary: Derived projections, reports, and graph exports for SSOT.
5
+ Author-email: Jacob Stewart <jacob@swarmauri.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/groupsum/ssot-registry
8
+ Project-URL: Repository, https://github.com/groupsum/ssot-registry
9
+ Project-URL: Issues, https://github.com/groupsum/ssot-registry/issues
10
+ Keywords: ssot,views,reports,graph,projections
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: <3.14,>=3.10
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: ssot-contracts==0.2.4
25
+ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
26
+
27
+ # ssot-views
28
+
29
+ Derived SSOT projections:
30
+
31
+ - validation and certification reports
32
+ - graph exports
33
+ - future shared view metadata
@@ -0,0 +1,15 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/ssot_views/__init__.py
4
+ src/ssot_views.egg-info/PKG-INFO
5
+ src/ssot_views.egg-info/SOURCES.txt
6
+ src/ssot_views.egg-info/dependency_links.txt
7
+ src/ssot_views.egg-info/requires.txt
8
+ src/ssot_views.egg-info/top_level.txt
9
+ src/ssot_views/graph/__init__.py
10
+ src/ssot_views/graph/export_dot.py
11
+ src/ssot_views/graph/export_json.py
12
+ src/ssot_views/reports/__init__.py
13
+ src/ssot_views/reports/certification_report.py
14
+ src/ssot_views/reports/summary.py
15
+ src/ssot_views/reports/validation_report.py
@@ -0,0 +1,4 @@
1
+ ssot-contracts==0.2.4
2
+
3
+ [:python_version < "3.11"]
4
+ tomli>=2.0.1
@@ -0,0 +1 @@
1
+ ssot_views