Coverage for archdocs/mapping.py: 100%
45 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-18 22:03 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-18 22:03 +0000
1import dataclasses
2import enum
3import pathlib
4import types
5import typing
7from archdocs import diagram_model
8from archdocs.features.app_servers import parser as app_servers_parser
9from archdocs.features.app_servers import renderer as app_servers_renderer
10from archdocs.features.http_api import parser as http_api_parser
11from archdocs.features.http_api import renderer as http_api_renderer
12from archdocs.features.http_clients import parser as http_clients_parser
13from archdocs.features.http_clients import renderer as http_clients_renderer
14from archdocs.features.kubernetes import manifest_files as kubernetes_manifest_files
15from archdocs.features.kubernetes import parser as kubernetes_parser
16from archdocs.features.kubernetes import renderer as kubernetes_renderer
17from archdocs.features.messaging_queue import parser as messaging_queue_parser
18from archdocs.features.messaging_queue import renderer as messaging_queue_renderer
19from archdocs.features.redis import parser as redis_parser
20from archdocs.features.redis import renderer as redis_renderer
21from archdocs.features.sqlalchemy import parser as sqlalchemy_parser
22from archdocs.features.sqlalchemy import renderer as sqlalchemy_renderer
23from archdocs.features.task_queues import parser as task_queues_parser
24from archdocs.features.task_queues import renderer as task_queues_renderer
27# The type variable is the registry's safety net: an entry pairing one feature's parser with
28# another feature's renderer — the realistic slip when a new feature is copied from a neighbour —
29# fails right here under mypy instead of failing at runtime on somebody's diagram.
30@typing.final
31@dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
32class _FeatureFunctions[ParsedFeaturesT]:
33 parse_source: typing.Callable[[str], ParsedFeaturesT]
34 render_edges: typing.Callable[
35 [diagram_model.DiagramNode, ParsedFeaturesT],
36 tuple[diagram_model.DiagramEdge, ...],
37 ]
40@typing.final
41class AllCurrentFeatures(enum.Enum):
42 fastapi_litestar = 1
43 faststream = 2
44 sqlalchemy = 3
45 redis_cache = 4
46 http_clients = 5
47 task_queues = 6
48 app_servers = 7
51type _FeatureRegistry = types.MappingProxyType[AllCurrentFeatures, _FeatureFunctions[typing.Any]]
53MAPPING_OF_PARSERS_AND_RENDERERS: typing.Final[_FeatureRegistry] = types.MappingProxyType(
54 {
55 AllCurrentFeatures.fastapi_litestar: _FeatureFunctions(
56 parse_source=http_api_parser.find_fastapi_and_litestar_features,
57 render_edges=http_api_renderer.render_http_api_features,
58 ),
59 AllCurrentFeatures.faststream: _FeatureFunctions(
60 parse_source=messaging_queue_parser.find_faststream_features,
61 render_edges=messaging_queue_renderer.render_messaging_queue_features,
62 ),
63 AllCurrentFeatures.sqlalchemy: _FeatureFunctions(
64 parse_source=sqlalchemy_parser.find_sqlalchemy_features,
65 render_edges=sqlalchemy_renderer.render_sqlalchemy_features,
66 ),
67 AllCurrentFeatures.redis_cache: _FeatureFunctions(
68 parse_source=redis_parser.find_redis_features,
69 render_edges=redis_renderer.render_redis_features,
70 ),
71 AllCurrentFeatures.http_clients: _FeatureFunctions(
72 parse_source=http_clients_parser.find_http_client_features,
73 render_edges=http_clients_renderer.render_http_client_features,
74 ),
75 AllCurrentFeatures.task_queues: _FeatureFunctions(
76 parse_source=task_queues_parser.find_task_queue_features,
77 render_edges=task_queues_renderer.render_task_queue_features,
78 ),
79 AllCurrentFeatures.app_servers: _FeatureFunctions(
80 parse_source=app_servers_parser.find_application_server_features,
81 render_edges=app_servers_renderer.render_application_server_features,
82 ),
83 },
84)
87@typing.final
88@dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
89class ManifestFeatureFunctions[ParsedManifestsT]:
90 read_source: typing.Callable[[pathlib.Path, str | pathlib.Path | None], str]
91 parse_manifests: typing.Callable[[str], ParsedManifestsT]
92 render_edges: typing.Callable[
93 [diagram_model.DiagramNode, ParsedManifestsT],
94 tuple[diagram_model.DiagramEdge, ...],
95 ]
96 render_node_annotations: typing.Callable[[ParsedManifestsT], tuple[str, ...]]
99@typing.final
100class AllCurrentManifestFeatures(enum.Enum):
101 kubernetes = 1
104type _ManifestRegistry = types.MappingProxyType[AllCurrentManifestFeatures, ManifestFeatureFunctions[typing.Any]]
106MAPPING_OF_MANIFEST_PARSERS_AND_RENDERERS: typing.Final[_ManifestRegistry] = types.MappingProxyType(
107 {
108 AllCurrentManifestFeatures.kubernetes: ManifestFeatureFunctions(
109 read_source=kubernetes_manifest_files.read_kubernetes_manifests,
110 parse_manifests=kubernetes_parser.find_kubernetes_features,
111 render_edges=kubernetes_renderer.render_kubernetes_features,
112 render_node_annotations=kubernetes_renderer.render_kubernetes_node_annotations,
113 ),
114 },
115)