Skip to content

chore(blueprints): remove aliases#1606

Open
paul-nechifor wants to merge 1 commit intodevfrom
paul/chore/remove-blueprint-copies
Open

chore(blueprints): remove aliases#1606
paul-nechifor wants to merge 1 commit intodevfrom
paul/chore/remove-blueprint-copies

Conversation

@paul-nechifor
Copy link
Contributor

@paul-nechifor paul-nechifor commented Mar 19, 2026

Problem

Blueprint aliases are annoying because there are two ways to do the same thing.

Closes DIM-538

Solution

Removed my_moduel(). Now, you can only do MyModule.blueprint().

Breaking Changes

You can no longer import blueprint aliases. Just import the actual Module.

How to Test

Contributor License Agreement

  • I have read and approved the CLA.

@paul-nechifor paul-nechifor force-pushed the paul/chore/remove-blueprint-copies branch from f2674fe to e1293e7 Compare March 19, 2026 07:18
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 19, 2026

Greptile Summary

This PR removes ~100 lowercase_alias = ClassName.blueprint shim variables that were previously exported from module files, replacing all call sites with the canonical ClassName.blueprint(...) pattern directly. It also refactors the test_all_blueprints_generation.py scanner to auto-discover Module subclasses via AST transitive-closure analysis rather than relying on those alias assignments.

Key changes:

  • Every module file (agents, perception, navigation, hardware, manipulation, teleop, etc.) drops its foo = Foo.blueprint / __all__ boilerplate — ~5 lines removed per file across ~40 files.
  • dimos/control/coordinator.py removes control_coordinator = ControlCoordinator.blueprint and its __all__.
  • test_all_blueprints_generation.py adds _build_module_class_set (transitive closure of Module subclasses), _camel_to_snake conversion, _is_production_module_file filtering, and collision-resolution logic so modules no longer need an alias variable to be registered.
  • all_blueprints.py is regenerated: all_modules keys are now derived from class names via _camel_to_snake, causing several renames (e.g. realsense-camerareal-sense-camera, mappermap, unitree-skillsunitree-skill-container) that are breaking CLI changes.
  • pyproject.toml adds -s to addopts, disabling output capture globally — likely a debugging leftover.
  • _ends_with_blueprint_method is not updated to recognise ClassName.blueprint(...) calls, so bare .blueprint(...) assignments (all 18 coordinator_* entries in dimos/control/blueprints.py) are not detected by the scanner, which would cause test_all_blueprints_is_current to fail in CI.

Confidence Score: 2/5

  • Not safe to merge — the blueprint scanner misses the new ClassName.blueprint(...) call pattern, and a debug flag was left in pytest config.
  • The bulk of the alias-removal changes across ~100 files are mechanical and correct. However, two issues lower confidence significantly: (1) _ends_with_blueprint_method does not recognise ClassName.blueprint(...) as a blueprint-producing call, meaning all 18 coordinator_* entries in dimos/control/blueprints.py would be dropped from the auto-generated registry and test_all_blueprints_is_current would fail in CI; (2) the -s flag left in pyproject.toml will produce very noisy CI output.
  • dimos/robot/test_all_blueprints_generation.py (scanner logic) and pyproject.toml (debug flag) require attention before merging.

Important Files Changed

Filename Overview
dimos/robot/test_all_blueprints_generation.py Major refactor of blueprint scanner: replaces variable-alias detection with class-hierarchy analysis using AST transitive closure, but _ends_with_blueprint_method doesn't handle the new SomeClass.blueprint(...) call pattern, likely causing CI failures for coordinator blueprints.
pyproject.toml Adds -s (no output capture) flag to default pytest addopts — this is a debugging artifact that should be removed before merging.
dimos/control/coordinator.py Removes control_coordinator = ControlCoordinator.blueprint alias and __all__ export; callers now use ControlCoordinator.blueprint(...) directly. Clean change.
dimos/control/blueprints.py Replaces all control_coordinator(...) calls with ControlCoordinator.blueprint(...) across 14 coordinator blueprints. Mechanical and correct.
dimos/robot/all_blueprints.py Auto-generated registry updated: all_modules keys renamed to match _camel_to_snake class names (e.g. realsense-camerareal-sense-camera, mappermap). Contains several breaking CLI name changes but reflects the new auto-generation logic.
dimos/robot/unitree/go2/blueprints/agentic/_common_agentic.py Replaces aliased blueprint factories with direct class imports and .blueprint() calls across all five modules in the common agentic stack. Correct.
dimos/manipulation/blueprints.py Migrates all aliased blueprint factories to direct ClassName.blueprint(...) calls throughout the manipulation stack. Consistent with the rest of the PR.
dimos/visualization/rerun/bridge.py Removes rerun_bridge = RerunBridgeModule.blueprint alias and its associated comment. All call sites updated to RerunBridgeModule.blueprint(...) directly.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["_scan_for_blueprints(root)"] --> B["_build_module_class_set(root)\n(AST transitive closure)"]
    B --> C["known Module subclass names"]
    A --> D["Iterate Python files"]
    D --> E["_find_blueprints_in_file(file, module_classes)"]
    E --> F{"Top-level AST node?"}
    F -->|"ast.Assign"| G{"_is_autoconnect_call?\n_ends_with_blueprint_method?"}
    G -->|"Yes"| H["blueprint_vars ← var_name"]
    G -->|"No"| I["❌ SomeClass.blueprint(...)\nnot detected!"]
    F -->|"ast.ClassDef"| J{"base in module_classes?"}
    J -->|"Yes"| K["module_vars ← _camel_to_snake(class_name)"]
    H --> L["all_blueprints[cli_name] = module:var"]
    K --> M{"_is_production_module_file?"}
    M -->|"Yes"| N["all_modules[cli_name] = module_path"]
    M -->|"No"| O["Skipped"]
    L --> P{"Key collision?"}
    N --> P
    P -->|"Collision"| Q["Blueprint takes priority\ndel all_modules[key]"]
    P -->|"No collision"| R["Final registry"]
    Q --> R
Loading

Comments Outside Diff (1)

  1. dimos/robot/test_all_blueprints_generation.py, line 301-306 (link)

    P1 SomeClass.blueprint(...) call pattern is never detected as a blueprint variable

    _ends_with_blueprint_method checks if the outermost call's attribute name is in BLUEPRINT_METHODS, but "blueprint" is not in that set. As a result, top-level assignments of the form coordinator_basic = ControlCoordinator.blueprint(tick_rate=100.0, ...) (and all other coordinator_* variables in dimos/control/blueprints.py) are not picked up as blueprint variables.

    The old code detected module_alias = SomeClass.blueprint (attribute-only, no call) via the now-removed _is_blueprint_factory. With all aliases removed, the scanner has no path to detect the new direct-call pattern SomeClass.blueprint(...).

    The committed all_blueprints.py currently includes 18 coordinator-* entries (lines 19–36). If the scanner does not regenerate them, test_all_blueprints_is_current will fail in CI because the generated content won't match.

    The fix is to also recognise func.attr == "blueprint" as a valid blueprint-producing call:

Last reviewed commit: "chore(blueprints): r..."

@paul-nechifor paul-nechifor force-pushed the paul/chore/remove-blueprint-copies branch from e1293e7 to ea5c220 Compare March 19, 2026 07:25
@paul-nechifor paul-nechifor force-pushed the paul/chore/remove-blueprint-copies branch from ea5c220 to 6b8938c Compare March 19, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant