# Build dependency graph
graph = build_dependency_graph()
print(f"Found {len(graph.modules)} modules with {len(graph.dependencies)} dependencies")Found 7 modules with 19 dependencies
Represents a dependency between modules
Dependency graph for a project
Extract project-internal imports from an import statement
Analyze a module’s imports to find project-internal dependencies
Build a dependency graph for all modules in a project
Generate a Mermaid.js dependency diagram from a dependency graph
Generate a dependency matrix showing which modules depend on which
Let’s test the dependency analysis on our project:
Found 7 modules with 19 dependencies
api_docs depends on:
- parsers: *
- dependencies: *
- tree: *
- core: *
cli depends on:
- parsers: *
- tree: *
- api_docs: *
- dependencies: *
dependencies depends on:
- dependencies: ModuleDependency
- parsers: *
- parsers: ModuleInfo
- dependencies: generate_mermaid_diagram
- core: *
- dependencies: DependencyGraph
generators depends on:
- tree: *
- core: *
parsers depends on:
- tree: extract_notebook_info
- core: *
tree depends on:
- core: *
# Test with a sample graph that includes reserved keywords
from cjm_nbdev_overview.dependencies import DependencyGraph, ModuleDependency, generate_mermaid_diagram
from cjm_nbdev_overview.parsers import ModuleInfo
from pathlib import Path
# Create test graph with reserved keywords
test_graph = DependencyGraph()
# Add modules including ones with reserved keywords
modules_data = [
("colors", "Colors"),
("core", "Core"),
("examples", "Practical Usage Examples"),
("layout", "Layout"),
("modern", "Modern"),
("style", "Style"), # This should trigger the reserved keyword handling
("types", "Type Definitions"),
("validation", "Validation"),
("variants", "Variants")
]
for name, title in modules_data:
module = ModuleInfo(
path=Path(f"nbs/{name}.ipynb"),
name=name,
title=title,
description=None,
functions=[],
classes=[],
variables=[],
imports=[]
)
test_graph.add_module(module)
# Add some test dependencies
test_dependencies = [
("colors", "validation"),
("colors", "types"),
("core", "types"),
("core", "validation"),
("examples", "validation"),
("examples", "variants"),
("examples", "core"),
("examples", "modern"),
("examples", "colors"),
("examples", "layout"),
("examples", "style"), # This should work with escaped style
("layout", "core"),
("layout", "types"),
("layout", "validation"),
("modern", "core"),
("style", "core"), # This should work with escaped style
("style", "types"), # This should work with escaped style
("style", "colors"), # This should work with escaped style
("style", "validation"),# This should work with escaped style
("variants", "core")
]
for source, target in test_dependencies:
dep = ModuleDependency(source=source, target=target, import_type="from", imported_names=["*"])
test_graph.add_dependency(dep)
# Generate diagram that should now work without parse errors
print("## Test Diagram with Reserved Keywords Handled\n")
print(generate_mermaid_diagram(test_graph, direction="LR"))## Test Diagram with Reserved Keywords Handled
```mermaid
graph LR
colors[colors<br/>Colors]
core[core<br/>Core]
examples[examples<br/>Practical Usage Examples]
layout[layout<br/>Layout]
modern[modern<br/>Modern]
style_mod[style<br/>Style]
types[types<br/>Type Definitions]
validation[validation<br/>Validation]
variants[variants<br/>Variants]
colors --> validation
colors --> types
core --> types
core --> validation
examples --> validation
examples --> variants
examples --> core
examples --> modern
examples --> colors
examples --> layout
examples --> style_mod
layout --> core
layout --> types
layout --> validation
modern --> core
style_mod --> core
style_mod --> types
style_mod --> colors
style_mod --> validation
variants --> core
```
# Test nested module imports
test_imports = [
"from cjm_fasthtml_daisyui.core.base import DaisyComponent, DaisySize",
"from cjm_fasthtml_daisyui.core.colors import SemanticColor",
"from cjm_fasthtml_daisyui.core.behaviors import InteractiveMixin, FormControlMixin",
"from cjm_fasthtml_daisyui.core.modifiers import StyleType, HasStyles",
"from cjm_fasthtml_daisyui.core.htmx import HTMXComponent, HTMXAttrs",
"from cjm_fasthtml_daisyui.core import *"
]
print("Testing nested module import extraction:")
print("-" * 50)
for import_str in test_imports:
dep = extract_project_imports(import_str, "cjm_fasthtml_daisyui")
if dep:
print(f"Import: {import_str}")
print(f" Target module: {dep.target}")
print(f" Imported names: {', '.join(dep.imported_names)}")
print()Testing nested module import extraction:
--------------------------------------------------
Import: from cjm_fasthtml_daisyui.core.base import DaisyComponent, DaisySize
Target module: core.base
Imported names: DaisyComponent, DaisySize
Import: from cjm_fasthtml_daisyui.core.colors import SemanticColor
Target module: core.colors
Imported names: SemanticColor
Import: from cjm_fasthtml_daisyui.core.behaviors import InteractiveMixin, FormControlMixin
Target module: core.behaviors
Imported names: InteractiveMixin, FormControlMixin
Import: from cjm_fasthtml_daisyui.core.modifiers import StyleType, HasStyles
Target module: core.modifiers
Imported names: StyleType, HasStyles
Import: from cjm_fasthtml_daisyui.core.htmx import HTMXComponent, HTMXAttrs
Target module: core.htmx
Imported names: HTMXComponent, HTMXAttrs
Import: from cjm_fasthtml_daisyui.core import *
Target module: core
Imported names: *
# Test with a graph that simulates the nested module structure from the bug report
nested_test_graph = DependencyGraph()
# Add nested modules like in the bug report
nested_modules = [
("actions.button", "Button"),
("core.animation", "Animation & Transitions"),
("core.base", "Core Base Classes"),
("core.behaviors", "Behavior States"),
("core.colors", "Colors"),
("core.config", "Configuration"),
("core.factory", "Component Factory"),
("core.htmx", "HTMX Integration"),
("core.modifiers", "Style Modifiers"),
("core.parts", "Component Parts"),
("core.placement", "Placement & Direction"),
("core.resources", "Resources"),
("core.testing", "Testing"),
("core.validation", "Validation"),
("core.variants", "Variant System")
]
for name, title in nested_modules:
module = ModuleInfo(
path=Path(f"nbs/{name.replace('.', '/')}.ipynb"),
name=name,
title=title,
description=None,
functions=[],
classes=[],
variables=[],
imports=[]
)
nested_test_graph.add_module(module)
# Add dependencies from actions.button to various core modules
dependencies_to_add = [
("actions.button", "core.base", ["DaisyComponent", "DaisySize"]),
("actions.button", "core.colors", ["SemanticColor"]),
("actions.button", "core.behaviors", ["InteractiveMixin", "FormControlMixin"]),
("actions.button", "core.modifiers", ["StyleType", "HasStyles"]),
("actions.button", "core.htmx", ["HTMXComponent", "HTMXAttrs"]),
# Self-dependencies within core
("core.base", "core.colors", ["*"]),
("core.factory", "core.base", ["*"]),
("core.htmx", "core.base", ["*"]),
("core.testing", "core.validation", ["*"]),
("core.validation", "core.config", ["*"])
]
for source, target, imported in dependencies_to_add:
dep = ModuleDependency(source=source, target=target, import_type="from", imported_names=imported)
nested_test_graph.add_dependency(dep)
# Generate the corrected diagram
print("## Fixed Mermaid Diagram with Nested Modules\n")
print(generate_mermaid_diagram(nested_test_graph, direction="LR"))
print(f"\n*{len(nested_test_graph.dependencies)} cross-module dependencies detected*")## Fixed Mermaid Diagram with Nested Modules
```mermaid
graph LR
actions_button[actions.button<br/>Button]
core_animation[core.animation<br/>Animation & Transitions]
core_base[core.base<br/>Core Base Classes]
core_behaviors[core.behaviors<br/>Behavior States]
core_colors[core.colors<br/>Colors]
core_config[core.config<br/>Configuration]
core_factory[core.factory<br/>Component Factory]
core_htmx[core.htmx<br/>HTMX Integration]
core_modifiers[core.modifiers<br/>Style Modifiers]
core_parts[core.parts<br/>Component Parts]
core_placement[core.placement<br/>Placement & Direction]
core_resources[core.resources<br/>Resources]
core_testing[core.testing<br/>Testing]
core_validation[core.validation<br/>Validation]
core_variants[core.variants<br/>Variant System]
actions_button --> core_base
actions_button --> core_colors
actions_button --> core_behaviors
actions_button --> core_modifiers
actions_button --> core_htmx
core_base --> core_colors
core_factory --> core_base
core_htmx --> core_base
core_testing --> core_validation
core_validation --> core_config
```
*10 cross-module dependencies detected*
## Dependency Matrix
| Module | api_docs | cli | core | dependencies | generators | parsers | tree |
|--------|----|----|----|----|----|----|----|
| api_docs | | | ✓ | ✓ | | ✓ | ✓ |
| cli | ✓ | | | ✓ | | ✓ | ✓ |
| core | | | | | | | |
| dependencies | | | ✓ | ✓ | | ✓ | |
| generators | | | ✓ | | | | ✓ |
| parsers | | | ✓ | | | | ✓ |
| tree | | | ✓ | | | | |