E52B ref(sdk/python): migrate python code analysis from runtime to ast-based by eunomie · Pull Request #11655 · dagger/dagger · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@eunomie
Copy link
Member
@eunomie eunomie commented Jan 9, 2026

The Python SDK's code analysis has been migrated from runtime-based to AST-based analysis. This allows types to be available before dependencies are fetched, enabling static analysis without executing user code.

Files Created

File Purpose
sdk/python/src/dagger/mod/_ir.py Immutable dataclasses for intermediate representation (TypeAnnotation, ParameterIR, FunctionIR, FieldIR, EnumMemberIR, ObjectTypeIR, ModuleIR)
sdk/python/src/dagger/mod/_ast_visitor.py Core AST parsing with DaggerModuleVisitor class that extracts decorated types without executing code
sdk/python/src/dagger/mod/_ast_resolver.py TypeResolver and IRToTypeDefConverter classes to convert IR to Dagger TypeDefs
sdk/python/src/dagger/mod/_analyzer.py Main entry points: PythonModuleAnalyzer, analyze_package(), analyze_source()
sdk/python/tests/mod/test_ast_analyzer.py 38 comprehensive tests covering all components

Files Modified

File Changes
sdk/python/src/dagger/mod/cli.py Added analyze parameter to app(), analyze_standalone() function for CLI, analyze_and_register() async function
sdk/python/src/dagger/mod/_module.py Added use_ast parameter to register(), _typedefs_from_ast() method
sdk/python/ruff.toml Added per-file ignores for AST complexity rules

Key Features

  1. Static Analysis: Parses Python source using ast module without importing/executing code
  2. Full Decorator Support: @object_type, @function, @field, @enum_type, @interface, @check
  3. Metadata Extraction: Handles Annotated[] with Doc, Name, DefaultPath, Ignore, Deprecated
  4. Name Conversion: Automatic snake_case → camelCase, trailing underscore normalization
  5. Type Resolution: Maps Python types to Dagger TypeDef (builtins, Dagger core types, module types)
  6. Constructor Support: Default constructors from dataclass fields, explicit constructors via name=""
  7. Package Analysis: Supports single files and full package directories with recursive scanning

Usage

# Programmatic API
from dagger.mod._analyzer import analyze_package, analyze_source

# Analyze a package directory
module_ir = analyze_package(Path("./src"), main_object="MyModule")

# Analyze source code string
module_ir = analyze_source(source_code, "test.py")

# CLI standalone analysis
python -m dagger --analyze  # Uses DAGGER_SOURCE_DIR env var

# Integration with Module.register()
await mod.register(use_ast=True)

Architecture

The implementation follows a clean separation of concerns:

Source Code → AST Visitor → IR Dataclasses → TypeDef Converter → Dagger API

This allows the parsing and type resolution to be tested independently and makes future extensions straightforward.

The Python SDK's code analysis has been migrated from runtime-based to AST-based analysis. This allows types to be available before dependencies are fetched, enabling static analysis without executing user code.

Files Created

| File                                       | Purpose                                                                                                                                        |
|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|
| sdk/python/src/dagger/mod/_ir.py           | Immutable dataclasses for intermediate representation (TypeAnnotation, ParameterIR, FunctionIR, FieldIR, EnumMemberIR, ObjectTypeIR, ModuleIR) |
| sdk/python/src/dagger/mod/_ast_visitor.py  | Core AST parsing with DaggerModuleVisitor class that extracts decorated types without executing code                                           |
| sdk/python/src/dagger/mod/_ast_resolver.py | TypeResolver and IRToTypeDefConverter classes to convert IR to Dagger TypeDefs                                                                 |
| sdk/python/src/dagger/mod/_analyzer.py     | Main entry points: PythonModuleAnalyzer, analyze_package(), analyze_source()                                                                   |
| sdk/python/tests/mod/test_ast_analyzer.py  | 38 comprehensive tests covering all components                                                                                                 |

Files Modified

| File                                 | Changes                                                                                                        |
|-----
B03E
---------------------------------|----------------------------------------------------------------------------------------------------------------|
| sdk/python/src/dagger/mod/cli.py     | Added analyze parameter to app(), analyze_standalone() function for CLI, analyze_and_register() async function |
| sdk/python/src/dagger/mod/_module.py | Added use_ast parameter to register(), _typedefs_from_ast() method                                             |
| sdk/python/ruff.toml                 | Added per-file ignores for AST complexity rules                                                                |

Key Features

1. Static Analysis: Parses Python source using ast module without importing/executing code
2. Full Decorator Support: @object_type, @function, @field, @enum_type, @interface, @check
3. Metadata Extraction: Handles Annotated[] with Doc, Name, DefaultPath, Ignore, Deprecated
4. Name Conversion: Automatic snake_case → camelCase, trailing underscore normalization
5. Type Resolution: Maps Python types to Dagger TypeDef (builtins, Dagger core types, module types)
6. Constructor Support: Default constructors from dataclass fields, explicit constructors via name=""
7. Package Analysis: Supports single files and full package directories with recursive scanning

Usage

    # Programmatic API
    from dagger.mod._analyzer import analyze_package, analyze_source

    # Analyze a package directory
    module_ir = analyze_package(Path("./src"), main_object="MyModule")

    # Analyze source code string
    module_ir = analyze_source(source_code, "test.py")

    # CLI standalone analysis
    python -m dagger --analyze  # Uses DAGGER_SOURCE_DIR env var

    # Integration with Module.register()
    await mod.register(use_ast=True)

Architecture

The implementation follows a clean separation of concerns:

Source Code → AST Visitor → IR Dataclasses → TypeDef Converter → Dagger API

This allows the parsing and type resolution to be tested independently and makes future extensions straightforward.

Signed-off-by: Yves Brissaud <yves.brissaud@gmail.com>
@grouville grouville self-requested a review January 9, 2026 20:43
@github-actions
Copy link
Contributor

This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0