DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
Status
Motivation
What problem does it solve? / Why is it needed?
This AIP is a scoped-down, modified part of bigger initiative, which aims to establish extendable DAG parsing controls within Airflow. We’ve strategically divided it into 2 independent parts to better manage complexity: while this AIP focuses on the implementation of the DAG importer interface, the subsequent AIP covers the overarching architectural framework for parsing controls with addition of interactive DAG processor (AIP-116). This modular approach allows us to implement the core importer mechanism faster and independently of the broader architectural updates.
The primary motivation for this AIP is:
- Many organizations are building customized workflow orchestration solutions on top of Airflow, often preferring different formats(Java, or YAML) to define their DAGs. Currently, these solutions require significant workarounds because Airflow is primarily designed to parse DAGs exclusively from Python files, even when the underlying generation process is a simple, standardized transformation.
- While AIP-72 successfully decoupled task definitions from Python, DAG structural definitions remain strictly bound to the Python language. This limitation is increasingly relevant as industry adoption of non-Python DAG generation tools (such as DAG Factory/Orchestration Pipelines and serverless configurations like AWS MWAA) grows. Allowing these alternative formats to be first-class citizens in Apache Airflow would:
- Eliminate the need for complex, brittle hacks to support external DAG definitions.
- Enable native support for diverse DAG generation sources.
- Align Airflow’s architecture with modern, multi-format workflow requirements.
Benefits
Implementing the DAG importer interface introduces several key operational, scaling, and architectural benefits like:
Elimination of python "bridge" code and CI complexity
Today, using declarative formats (like YAML via
dag-factoryor custom JSON schemas) requires maintaining a Python "bridge" file to load configs because Airflow's DAG processor only recognizes.pyfiles. As deployments scale, a single Python bridge file suffers from performance bottlenecks. To scale further, teams are forced to either complicate their CI/CD pipelines to dynamically generate 1-to-1 Python files for every declarative config or devise complex custom sharding schemas. The DAG importer eliminates this entire operational layer, allowing data teams to focus strictly on their configuration files without worrying about underlying DAG processor orchestration quirks.
Airflow-native optimizations for declarative DAGs
Instead of treating declarative formats as secondary citizens that must pass through an intermediary script, alternative formats become first-class entities. Declarative files (such as individual YAML trees) will be ingested natively, allowing them to potentially benefit from the core DAG processor's internal caching, parallelization, and scheduling optimizations without the performance overhead or translation friction of a homegrown generator framework.
Foundation for multi-language DAG authoring (AIP-108 Alignment)
AIP-85 directly unblocks multi-language authoring by providing the exact structural interface required to extract DAG definitions from non-Python languages. This creates a clean separation of concerns: an implementation of AIP-85's AbstractDagImporter (e.g., a JavaDagImporter) handles the discovery and parsing of the DAG structure, which then allows components from AIP-108 (like a JavaCoordinator) to natively hook in and manage the actual task execution.
- Note: It is important to clarify that AIP-85 and AIP-108 operate at different levels of the Airflow lifecycle to achieve multi-language support. While AIP-108 focuses on the task execution phase via the Task SDK’s Language Coordinator Layer, this AIP (AIP-85) focuses strictly on the DAG authoring and parsing phase.
Standardized UI visibility ("Code" Tab)
The improvement cleanly delegates the responsibility of source-text retrieval to the specific importer itself. Whether a user is inspecting a native YAML tree configuration or a non-Python code file managed by an external language SDK, the Airflow Web UI can reliably fetch and display the accurate source definitions without relying on brittle workarounds like overriding
dag.fileloc.
Considerations
What change do you propose to make?
The high-level architecture centers on a modular registry-based approach, decoupling DAG discovery from parsing. This enables support for diverse DAG formats beyond Python files, such as YAML or serialized formats, by delegating parsing to specialized, pluggable importer implementations. The architecture for the proposal entails the following flow:
The design of the solution consists of three integral changes:
- Airflow SDK
- Airflow Configuration
- Airflow Custom Importers
Proposal for Airflow SDK changes
Introduce extensible architecture centered around three primary entities within the Airflow SDK: DagDefinition, AbstractDagImporter and DagImporterRegistry.
DagDefinition
Instead of operating directly on file paths, importers will interact with a rich DagDefinition object. This abstraction natively supports non-filesystem sources (like ZIP contents or binaries) and separates I/O operations from logical extraction.
class DagDefinition:
@property
def freshness_token(self) -> str: ...
def read_bytes(self) -> bytes: ...
def read_text(self, encoding="utf-8") -> str: ...
def as_file(self) -> ContextManager[pathlib.Path]: ...
def __repr__(self) -> str: ...
- freshness_token(): Replaces hard-wired mtime checks with an opaque, generalized token, giving different source types the flexibility to implement their own update-detection logic
- read_bytes(): Read and return the content of the named resource as bytes.
- read_text(encoding: str): Read and return the content of the named resource as str.
- as_file(): Returns a context manager that yields a
pathlib.Pathpointing to an existing filesystem object. For file-based definitions, it returns the backing file. For non-filesystem files, it creates a temporary file, yields its path, and cleans it up on exit, preserving backward compatibility for importers that rely heavily on filesystem paths. - __repr__(): Provides the string representation used by import error and warning objects to properly point the user to the correct location.
AbstractDagImporter
This is the base interface responsible for the discovery, validation, and construction of DAG objects. It serves as an adapter layer that decouples the DAG definition source from the Airflow runtime. Importers are designed to be stateless or trivially constructible, ensuring they do not introduce complexity when managed across IPC boundaries in Airflow’s multi-process environment.
Proposed Interface
class AbstractDagImporter: @property def supported_extensions(self) -> list[str]: ... def import_file(self, definition: DagDefinition, *, bundle_path: str, bundle_name: str, safe_mode: bool) -> DagImportResult: ... def can_handle(self, definition: DagDefinition) -> bool: ... def list_dag_files(self, dir: str, safe_mode: bool) -> Iterator[DagDefinition]: ... def get_source_code(self, definition: DagDefinition) -> DagSourceCode: ...
- supported_extensions: A class attribute that defines the file extensions this importer can parse.
- import_file(): A method that parses the target DAG definition and returns a DagImportResult containing parsed DAGs, import errors, and warnings.
- can_handle(): A method that determines if the importer is suitable for a given DAG definition.
- list_dag_files(): A method that traverses the directory to yield compatible DAG definitions for further processing.
- get_source_code(): A method that retrieves the raw source code and its language identifier for the specified DAG definition (this will allow the Web UI to render the native definition in the Code tab).
class DagSource: source_code: str language: str
The DagImportResult dataclass will standardize output across different formats:
class DagImportResult: definition: DagDefinition dags: list[DAG] errors: list[DagImportError] skipped_definitions: list[DagDefinition] warnings: list[DagImportWarning] dependencies: list[DagDefinition]
- definition: DagDefinition object representing the source that was parsed. The DAG processor can use definition.__repr__() to log or display its location.
- dags: list of executable DAG objects successfully parsed from the given file path.
- errors: list of fatal parsing issues for the given file path. This should be used strictly for issues that prevent DAG construction entirely (e.g., invalid syntax or missing mandatory fields). The DAG processor will persist these to be surfaced prominently in the Airflow UI.
- warnings: list of non-fatal issues for the given file path, such as the use of deprecated fields. To support frontend UI translation and avoid storing hardcoded user-facing messages directly in the database, custom importers will emit structured DagImportWarning objects.
- Note: currently, the
warning_typeis enum field that supports only specific predefined types. To support custom warning types, theDagImportWarningmodel has to be adjusted to accept namespaced string field forwarning_typefield (e.g., "yaml:deprecated_field"), alongside a dictionary of context variables.
- Note: currently, the
- skipped_definitions: list of DAG definitions that show a clear intent of being a DAG but are ultimately unparsable due to different reasons.
- Guidance: To prevent flooding the Airflow UI with useless noise, importers must exercise discretion. Completely unrelated definitions should be silently ignored. Definitions appended here will be surfaced in the Airflow UI to give users visibility and prevent hard-to-debug "silent skipping" scenarios.
- dependencies: auxiliary dependencies to monitor for dependency changes and prevent staleness.
- Note: the DAG Processor will extract the
freshness_tokenfrom each of these objects and cache them. During its parsing loop, the DAG Processor will monitor these dependencies; if any token changes, it will automatically trigger a re-parse of the primary definition to prevent stale DAGs.
- Note: the DAG Processor will extract the
DagImporterRegistry
The DagImporterRegistry acts as a centralized service locator and orchestrator and the entire resolution and discovery process is desidned to be fully agnostic to the local filesystem. It maintains a 1:1 mapping between DAG Bundles and their configured importers. When the DagBag attempts to discover DAGs, it queries this registry to identify the correct importer for a given DAG definition.
Proposed Interface
class DagImporterRegistry:
@property
def supported_extensions(self) -> list[str]: ...
def register(self, importer: AbstractDagImporter, extensions: list[str]) -> None: ...
def get_importer(self, definition: DagDefinition) -> AbstractDagImporter | None: ...
def can_handle(self, definition: DagDefinition) -> bool: ...
def supported_extensions(self) -> list[str]: ...
def list_dag_files(self, bundle: BaseDagBundle, safe_mode: bool) -> Iterator[DagDefinition]: ...
- supported_extensions: A class attribute that defines the extensions for which there is a registered AbstractDagImporter.
- register(): A method that registers the DAG importer to handle the specific extensions.
- get_importer(): A method that gets the registered importer for the DAG definition.
- can_handle(): A method that checks if there is a registered importer that can handle this DAG definition.
- list_dag_files(): A method that lists the DAG definitions in the DAG bundle via registered DAG importers.
DagBag backwards compatibility
To maintain strict backward compatibility across the Airflow, particularly for thousands of existing unit tests and internal utilities that instantiate DagBag, the DagImporterRegistry will be integrated using an optional dependency injection pattern. The DagBag.__init__ method accepts an optional importer_registry argument. When omitted, the constructor automatically falls back to invoking the global, default-initialized DagImporterRegistry singleton instance, which arrives pre-loaded with the PythonDagImporter, ensuring that legacy tests and standard Python-based DAG environments parse exactly as they did in legacy versions, requiring zero code modifications from end-users or provider developers.
def __new__(cls) -> DagImporterRegistry:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._importers = {}
cls._instance._register_default_importers()
return cls._instance
def _register_default_importers(self) -> None:
from airflow.sdk.importers.python_importer import PythonDagImporter
self.register(PythonDagImporter())
Implemented foundation [as of Jan 2026]
The foundation for the above entities / changes was laid in the following PR.
The foundational elements of this proposal have already been merged into the main branch in the following PR. The following components are currently implemented:
- core: AbstractDagImporter base interface;
- core: DagImporterRegistry for centralized service location;
- core: native PythonDagImporter.
Archive importers (specifically ZipImporter)
Currently, the existing PythonDagImporter owns both the .py and .zip extensions. This design has two critical limitations:
- Python DAG parsing and ZIP archive extraction logic are tightly coupled inside a single importer.
- Users cannot package non-Python DAG formats (like YAML DAGs or custom domain-specific language DAGs) within a .zip archive. The current system is locked into assuming that any .zip file exclusively contains Python modules.
To solve these limitations, we propose introducing a generic composite ZipImporter (and a wider pattern for nested/hierarchical importers). The ZipImporter acts purely as a router: it is responsible only for traversing the .zip archive and delegating the discovery and parsing of the files inside to specialized, configurable "internal" importers (format specified in Airflow Configuration changes below).
Proposed design:
With the introduction of the DagDefinition abstraction, the ZipImporter does not need to rely on default brute-force "extraction-to-temp-dir" flow. Instead, it will utilize a native, lazy-loading interface.
- When the DAG Processor encounters a
.ziparchive, the DagImporterRegistry routes the archive's DagDefinition to the ZipImporter. - The ZipImporter reads the ZIP table of contents directly. To protect against resource depletion, it only processes internal files whose suffixes match the keys in the configured internal_importers dictionary.
- For each valid internal file, the ZipImporter constructs a new, nested DagDefinition object representing that specific ZIP entry. This nested definition implements a
__repr__()that natively formats the archive location (e.g.,my_archive.zip:dags/dag_1.java). - The ZipImporter selects the correct internal importer (e.g., invoking PythonDagImporter for
.pyfiles and JavaDagImporter for.javaor.jarfiles) and passes the nested DagDefinition to the internal importer'simport_file()method.- Lazy extraction: If the internal importer requires access to a physical file on disk (like the PythonDagImporter does), it calls
definition.as_filesystem_path()on the nested definition. The nested DagDefinition handles securely extracting that specific file to a temporary location, yields thepathlib.Path, and cleans it up upon exiting the context manager. - Cross-imports: To support standard Python cross-imports within the ZIP archive (e.g., a
dag.pyimporting ahelpers.pycontained in the same ZIP), the ZipImporter temporarily injects the ZIP archive itself into sys.path.
- Lazy extraction: If the internal importer requires access to a physical file on disk (like the PythonDagImporter does), it calls
- The ZipImporter aggregates the DagImportResult objects from all internal importer runs. Because the nested DagDefinition objects manage their own state and string representations, user-facing error logs, warnings, and source code retrieval inherently remain readable without needing the ZipImporter to manually translate file paths post-parse.
- As a cleanup step, any sys.path entries injected for the archive are removed.
Proposal for Airflow Configuration changes
This section defines the mapping between DAG bundles and their corresponding importer logic. The configuration can be part of [dag_processor]dag_bundle_config_list, for example:
[
{
"name": "dags-folder",
"classpath": "airflow.dag_processing.bundles.local.LocalDagBundle",
"kwargs" {}
"importers": {
"py": {
"classpath": "airflow.sdk.importers.python_importer.PythonDagImporter"
},
"zip": {
"classpath": "airflow.sdk.importers.archive_importer.ZipImporter"
"kwargs": {
"internal_importers": {
"py": {
"classpath": "airflow.sdk.importers.python_importer.PythonDagImporter"
}
}
}
}
}
]
Defining this mapping within the bundle configuration allows Airflow to maintain strict isolation between different sources/bundles. This structure ensures that parsing logic is coupled with the bundle's lifecycle, simplifying dependency management and reducing the risk of configuration being applied across diverse environments.
Design considerations:
- Resolution order: Importers are resolved based on file extension matching. If multiple importers support the same extension, the importer will be overridden, and, based on the current implementation, will log a warning. The priority for importers with the same extensions is
Bundle Explicit Mapping>Global Configuration>Default Importers (e.g., PythonDagImporter). - Composition: The archive importer pattern (as shown above) demonstrates how importers can be nested. This recursive resolution allows for complex bundle structures (e.g., an archive containing multiple DAG definition types).
Proposal for Custom Importers
Airflow's configuration will be extended to support custom DAG importers. This allows users to author and register custom DAG parsers natively. For this purpose, the Airflow will dynamically resolve custom importers directly from the Airflow configuration using import_string().
The technical implementation involves two steps: defining the custom importer interface and configuring the class path.
Defining a custom importer interface
Users or developers must create a class that inherits from AbstractDagImporter and implements its core interface. The custom importer dictates how files are read, translated into Airflow DAG objects, and returned via the standardized DagImportResult dataclass. Structure:
from airflow.sdk.importers.base import AbstractDagImporter, DagImportResult class NewDagImporter(AbstractDagImporter): supported_extensions: list[str] = [".extension1", ".extension2"] def can_handle(self, definition: DagDefinition) -> bool: ... def import_file( self, definition: DagDefinition, *, bundle_path: str, bundle_name: str, safe_mode: bool ) -> DagImportResult: ...
Configuring the Importer via Airflow Configuration
Custom importers are registered directly in the Airflow configuration file (or via environment variables). Airflow will dynamically instantiate the configured class path at runtime.
[dag_processor] dag_importer_configs = [ "custom.importers.NewDagImporter", "another_folder.importers.CustomYamlImporter" ]
When the DAG processor initializes, it loops through the specified class paths, imports them using import_string, and registers them to handle incoming bundle files based on their can_handle logic.
Considerations
Performance
To validate that the architecture introduces no latency regressions, and to quantify the expected performance gains of native declarative parsing, the following dimensions and scenarios will be measured as part of the performance tests:
- Number of DAG files
- Number of DAGs in single file
- Number of accesses to other parse-time parameters
Given that the initialization of the DagBag with DagImporterRegistry and loading of importer classes, some small performance regression is anticipated. At the same time alternative parsers will provide the performance improvement in themselves (e.g. by avoiding unnecessary parsing) which can overweight any anticipated regression.
Comparative benchmarking: direct performance comparison measuring the time and resource overhead to parse N declarative DAGs (e.g., YAML) natively via a custom importer, versus parsing the same N DAGs using legacy Python generator patterns (such as DAG Factory).
What defines this AIP as "done"?
This AIP will be considered “done” when the PR with necessary well-documented solution is created and the language-specific custom DAG importers can be registered.
Overall, the deliverables for this AIP include:
AbstractDagImporterinterface: A new pluggable, public interface allowing custom plugins to transform alternative bundle content into executable Airflow DAG objects.base version implemented; may be changed based on functional needs
PythonDagImporter: A native implementation migrating legacyDagBagprocessing logic into this new architecture, ensuring standard Python files continue to parse cleanly.- base version implemented; may be changed based on functional needs
Bundle & Processor integration: Extension of the Airflow 3 Bundle interface to dynamically map and instantiate designated importers per bundle, and full integration within the DAG processor.
UI Source retrieval & Syntax highlighting: Core API support for methods like
get_source_code()and language hinting. The UI will be updated to display the native format and apply the correct syntax highlighting in the 'Code' tab.- UI visibility for parsing metadata: The Airflow UI will be updated to consume and display the extended metadata provided by
DagImportResult. This implementation includes adding UI components (such as banners or dedicated views) to surface:- Skipped files: Giving users visibility into files rejected by the importer's
safe_modeheuristic. - Warnings: The existing
dag_warningtable mechanism will be extended to support custom importer warnings. This requires relaxing theDagWarningTypecolumn from a strict databaseEnumto a standardstringcolumn to support namespaced warning types (e.g., "yaml:unrecognized_key"). Additionally, the table will need to store the warningcontext(e.g., {"field_name": "field_value"})to enable dynamic i18n translation of these messages in the frontend. - Errors: Continuing to display critical parsing failures accurately.
- Skipped files: Giving users visibility into files rejected by the importer's
Out of Scope
- DAG reconciliation
The logic determining how and when a DAG record is purged from the system (for example, if its underlying definition is deleted from the bundle) is explicitly out of scope for the importer contract. Determining whether a DAG record should be removed belongs entirely to the DAG bundle lifecycle management and the DAG Processor. Importers remain strictly focused on discovery and translation.
Known limitations
- Code tab permissions for multi-DAG files: It is a common pattern to define multiple DAGs in a single file. Currently, the Airflow Code tab only renders the file if the user has
CODElevel permissions for every DAG defined within it. Solving this RBAC granularity issue is deferred to future work, as this limitation is inherited from how Airflow currently handles multi-DAG Python files.

14 Comments
Michal Modras
Aug 04, 2024Overall looks good to me - fits with other major AIPs in Airflow 3.0 (e.g. AIP-72) and brings the value of better DAG processing management.
Jedidiah Cunningham
Aug 07, 2024Overall LGTM. Matches what I was imagining for this topic, and I don't see any conflicts (at this point at least
).
Jarek Potiuk
Aug 11, 2024I like the way it is defined - and agree with Michal Modras and Jedidiah Cunningham . Also the idea of making some refactorings in DagBag and related code in Airflow 3 without yet full implementation of this AIP is a good idea.
Maybe I'd add one more use case - this should be also stepping stone for the long term "workflow-in-workflow" cases (like Cosmosfor DBT and Databricks workflow support we have in a limited way)) - at least the first part of it where external workflwos can be mapped (i.e bundle-parsed) into Airflow DAG. The next steps would be to add "null" tasks and a way to interact with the workflow running elsewhere, but this one wil be a good prerequisite to have.
Kaxil Naik
Dec 30, 2025Igor Kholopov What timelines are you targeting to land this?
Vikram Koka
Jun 05, 2026What are the actual deliverables of this AIP (in it's revised form)?
Is this purely an internal code refactor with no immediate user facing benefits?
I ask because this refactored AIP also refers to an already merged PR 60127
If this for performance reasons - mentioned above, but not yet precisely defined with respect to before / after.
Are there any user facing benefits as a result of this AIP?
Dilnaz Amanzholova
Jun 08, 2026Overall, the deliverables for this AIP include:
AbstractDagImporterInterface: A new pluggable, public interface allowing providers or custom plugins to transform alternative bundle content into executable Airflow DAG objects.base version implemented; may be changed based on functional needs
LocalPythonImporter: A native implementation migrating legacyDagBagprocessing logic into this new architecture, ensuring standard Python files continue to parse cleanly.Bundle & Processor Integration: Extension of the Airflow 3 Bundle interface to dynamically map and instantiate designated importers per bundle, and full integration within the core DAG processor.
UI Source Retrieval: Core support for methods like
get_source_codeso that the Web UI can naturally display non-Python source formats in the "Code" tab.The AIP brings several benefits:
Jens Scheffler
Jun 05, 2026I think the technical description fits nicely into the current Java SDK and Go SDK plans and this abstraction layber could be used as a common ground also to hook these into.
Important also not only the interfaces in the AIP described but also the data structure in which an imported Dag is represented in order allowing the scheduler to work and the UI to render the view. This would need to include providing the "source code" to be displayed in "Code" tab - an improvemnt in this case could be that compared to todays dag-factory where the Py code of the factory stub is displayed that such importer could provide the YAML tree instead.
Dilnaz Amanzholova
Jun 08, 2026You are right, the importer should allow to display the true source code - whether it is YAML or Java - instead of current python wrapper with no context.
Tzu-ping Chung
Aug 05, 2026A few thoughts that I’m not sure if they fit specifically anywhere inline. I think the AIP is good. Two of the following points are on detailed interface design that does not change the overall goal, and the other is more about clarifying what is still missing (aside from execution-time) after the AIP.
Decouple source acquisition from parsing
We should split I/O (how to get an importable source) from logical extraction (how to get DAGs from a file). Specifically, Instead of operating on file paths, we should introduce a rich object similar to Python’s file object or pathlib.Path. Something like:
The function
list_dag_filesshould be modified to return a list of this type (or a subclass) instead (or maybe an iterator/generator). This allows us to support things that are not file-based. I believe it would have an instant improvement on ZIP file handling; instead of a string that fakes a path, we can more natively represent ZIP contents.Importer functions that currently receive a path (in str) can be changed to receive an object of this type instead. If we want, we can still build a FileDagImporter that implements common logic for file-based importers to subclass instead.
Generalize the freshness declaration beyond file mtimes
Similar to the previous point. Instead of hard-wiring the logic to checking mtime in the dag processor, we can implement an opaque property on
DagDefinitionto emit a more general token to check whether the definition has updated. We can use mtime (and maybe file size, hash, etc.) for plain file-based definitions, but other kinds of definitions can implement a better logic.Keep reconciliation out of the importer contract
The AIP does not currently go into how a DAG record is purged from the system if the definition is deleted from the bundle. If this is not intentionally omitted, we should also include a section to outline the plan there. Specifically, following the logic above, I think we should separate the concerns. The logic of whether a DAG record should be removed belongs to the DAG bundle, not the importer. We likely need some extra interface to make it work correctly with non-filesystem-definitions, but this is probably out of AIP-85’s scope.
Dilnaz Amanzholova
Aug 05, 2026Hi Tzu-ping,
Thanks for the suggestions! The separation you suggested seems like a very good way to support easy parsing of non-filesystem files. As you pointed out, abstracting the I/O operations into a DagDefinition object will provide an instant improvement on ZIP file handling(and other possible binary file formats), allowing us to natively represent contents instead of relying on string manipulations that fake a path.
I just want to add one thing to your proposed
DagDefinitioninterface: I think we should also include a relative_path() (or path) property/method alongside read_bytes() and read_text().PythonDagImporterand underlying Python modules all work heavily with file Path objects. Moving toDagDefinitionwithout path access would require re-writing a lot of that core logic (IIUC).Overall, having the path, text, and bytes available will give importers a choice of three different sources for importing a file. WDYT?
Regarding generalizing the freshness check - I agree. Replacing
mtimechecks with a generalized token (like a hash, size, ormtime) in theDagDefinitionmakes it more flexible and customizable. I can leave the default time check as it is, while the importer functions can re-write the default logic.Aobut the reconciliation, it was not intentional, but I can add a section of out-of-scope features that are not part of this AIP.
Overall, let me know what you think about the proposal about the relative path, and once we reach the consensus - I will update the content of AIP accordingly.
Tzu-ping Chung
Aug 06, 2026I think that makes sense. One the flexibility and compatibility points, we can borrow the idea from
importlib.resources.as_file, something likeA relative path can always be calculated from a pathlib.Path object and a known bundle root when it makes sense.
For errors and warnings, I think implementing a proper
__repr__would be better.For clarity, I think these can all be figured out during implementation instead. As long as we have an idea about the importer interface, nothing in this thread blocks voting on the AIP.
Dilnaz Amanzholova
Aug 06, 2026Hey Tzu-ping,
Thank you for the suggestion! I have added the section for the DagDefinition and modified the DAG importer methods accordingly. PTAL
Tzu-ping Chung
Aug 09, 2026I see there are some stale signatures and type names etc. It’s probably worthwhile to go through the document from top to bottom to clean those out. The ZipImporter section can probably also be rewritten since there’s now a more native interface it fits into.
We’ll also need some additional changes in DagImporterRegistry to make it fully agnostic to files (maybe build it directly from DagBundle objects instead of the paths they contain?) and call DagImporter’s
list_dag_fileswith a container object (a “directory” of DagDefinitions). Otherwise I think this is all very nice.Dilnaz Amanzholova
yesterday at 03:38 PMHey Tzu-ping,
I updated the doc and went through to modify the stale definitions. PTAL and let me know if the document is clearer now.