fastapi-voyager 0.4.4__tar.gz → 0.4.5__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.
Files changed (42) hide show
  1. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/PKG-INFO +1 -1
  2. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/module.py +20 -0
  3. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/version.py +1 -1
  4. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/test_module.py +36 -10
  5. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/.gitignore +0 -0
  6. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/LICENSE +0 -0
  7. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/README.md +0 -0
  8. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/pyproject.toml +0 -0
  9. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/__init__.py +0 -0
  10. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/cli.py +0 -0
  11. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/filter.py +0 -0
  12. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/graph.py +0 -0
  13. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/server.py +0 -0
  14. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/type.py +0 -0
  15. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/type_helper.py +0 -0
  16. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/component/route-code-display.js +0 -0
  17. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/component/schema-code-display.js +0 -0
  18. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/component/schema-field-filter.js +0 -0
  19. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/graph-ui.js +0 -0
  20. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/graphviz.svg.css +0 -0
  21. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/graphviz.svg.js +0 -0
  22. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/android-chrome-192x192.png +0 -0
  23. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/android-chrome-512x512.png +0 -0
  24. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/apple-touch-icon.png +0 -0
  25. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/favicon-16x16.png +0 -0
  26. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/favicon-32x32.png +0 -0
  27. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/favicon.ico +0 -0
  28. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/icon/site.webmanifest +0 -0
  29. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/index.html +0 -0
  30. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/quasar.min.css +0 -0
  31. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/quasar.min.js +0 -0
  32. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/src/fastapi_voyager/web/vue-main.js +0 -0
  33. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/__init__.py +0 -0
  34. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/demo.py +0 -0
  35. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/demo_anno.py +0 -0
  36. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/service/__init__.py +0 -0
  37. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/service/schema.py +0 -0
  38. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/test_analysis.py +0 -0
  39. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/test_import.py +0 -0
  40. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/tests/test_type_helper.py +0 -0
  41. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/uv.lock +0 -0
  42. {fastapi_voyager-0.4.4 → fastapi_voyager-0.4.5}/voyager.jpg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-voyager
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: Visualize FastAPI application's routing tree and dependencies
5
5
  Project-URL: Homepage, https://github.com/allmonday/fastapi-voyager
6
6
  Project-URL: Source, https://github.com/allmonday/fastapi-voyager
@@ -41,4 +41,24 @@ def build_module_tree(schema_nodes: list[SchemaNode]) -> list[ModuleNode]:
41
41
  result = list(top_modules.values())
42
42
  if root_level_nodes:
43
43
  result.append(ModuleNode(name="__root__", fullname="__root__", schema_nodes=root_level_nodes, modules=[]))
44
+
45
+ # Collapse pass: if a module has exactly one child module and no schema_nodes,
46
+ # merge it upward (A + B -> A.B). Repeat until fixed point.
47
+ def collapse(node: ModuleNode):
48
+ # Collapse chains at current node
49
+ while len(node.modules) == 1 and len(node.schema_nodes) == 0:
50
+ child = node.modules[0]
51
+ # Merge child's identity into current node
52
+ node.name = f"{node.name}.{child.name}"
53
+ # Prefer child's fullname which already reflects full path
54
+ node.fullname = child.fullname
55
+ node.schema_nodes = child.schema_nodes
56
+ node.modules = child.modules
57
+ # Recurse into children
58
+ for m in node.modules:
59
+ collapse(m)
60
+
61
+ for top in result:
62
+ collapse(top)
63
+
44
64
  return result
@@ -1,2 +1,2 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.4.4"
2
+ __version__ = "0.4.5"
@@ -50,16 +50,11 @@ def test_build_module_tree_basic():
50
50
  assert [sn.name for sn in other.schema_nodes] == ["C"]
51
51
  assert other.modules == []
52
52
 
53
- # x.y.z level
54
- x = _find_top(top_modules, "x")
53
+ # x.y.z chain should collapse to a single module named "x.y.z"
54
+ x = _find_top(top_modules, "x.y.z")
55
55
  assert x is not None
56
- assert x.schema_nodes == []
57
- y = _find_child(x, "y")
58
- assert y is not None
59
- z = _find_child(y, "z")
60
- assert z is not None
61
- assert [sn.name for sn in z.schema_nodes] == ["D"]
62
- assert z.modules == []
56
+ assert [sn.name for sn in x.schema_nodes] == ["D"]
57
+ assert x.modules == []
63
58
 
64
59
 
65
60
  def test_build_module_tree_empty_input():
@@ -82,4 +77,35 @@ def test_build_module_tree_root_level_nodes():
82
77
  assert root is not None
83
78
  assert sorted(sn.name for sn in root.schema_nodes) == ["Root1", "Root2"]
84
79
  pkg = _find_top(top_modules, "pkg")
85
- assert pkg is not None and [sn.name for sn in pkg.schema_nodes] == ["PkgA"]
80
+ assert pkg is not None and [sn.name for sn in pkg.schema_nodes] == ["PkgA"]
81
+
82
+
83
+ def test_collapse_single_child_empty_modules():
84
+ # Construct a deeper chain with empty intermediate modules that should collapse
85
+ schema_nodes = [
86
+ _sn("Deep", "a.b.c.d", "Deep"),
87
+ _sn("Peer", "a.b.x", "Peer"),
88
+ ]
89
+ top_modules = build_module_tree(schema_nodes)
90
+
91
+ # 'a' should have one child path 'b', but due to branching at x, only a.b collapses into a.b
92
+ # and below it, 'c.d' should collapse to 'c.d'. Final structure:
93
+ # a
94
+ # └── b
95
+ # ├── c.d (holds Deep)
96
+ # └── x (holds Peer)
97
+ a = _find_top(top_modules, "a")
98
+ assert a is not None
99
+ assert a.schema_nodes == []
100
+ # b remains as child of a
101
+ b = _find_child(a, "b")
102
+ assert b is not None
103
+ assert b.schema_nodes == []
104
+ # collapsed node under b is named "c.d"
105
+ cd = _find_child(b, "c.d")
106
+ assert cd is not None
107
+ assert [sn.name for sn in cd.schema_nodes] == ["Deep"]
108
+ # sibling x remains
109
+ x = _find_child(b, "x")
110
+ assert x is not None
111
+ assert [sn.name for sn in x.schema_nodes] == ["Peer"]
File without changes
File without changes