Skip to content

v0.0.18

New: NamespaceFragment

Composable fragments group related nodes, DAG factories, and cached callables under a shared nsref prefix. Two patterns are supported:

  • Class fragment — subclass NamespaceFragment, decorate methods with @nsnode, @dag_factory, @require_cache. Constructor args come from init: in the YAML config. Example: SleepFragment(NamespaceFragment).
  • Module fragment — a plain Python module with decorated top-level functions. Discovered via ModuleRef and registered with the same decorators. Example: transforms.py with @nsnode double, @dag_factory double_dag.

Fragment entries use type: fragment in namespace YAML config with gref, nsref, optional init (constructor kwargs), and per-node configs (triggers, cache settings).

Supporting decorators

  • @nsnode(tags=...) — marks a method/function for automatic discovery and registration as a NamespaceNode.
  • @dag_factory — marks a method that returns a Dag instance.
  • @require_cache(ttl=..., db=...) — marks a callable for cache-backed execution via lythonic.compose.cached.

Fragment registration

Namespace.from_dict discriminates type: fragment entries, instantiates the class or imports the module, discovers decorated members, and registers them with auto-prefixed nsrefs.

New: DagContext.ns_call / ns_acall

Call registered namespace nodes from within DAG-participating callables.

  • ns_call(nsref, *args, **kwargs) — sync dispatch. Raises TypeError if the target is async (use ns_acall instead).
  • ns_acall(nsref, *args, **kwargs) — async dispatch. Handles async targets directly, @inline sync targets on the event loop, and regular sync targets via loop.run_in_executor.

DagContext now carries a namespace field (excluded from serialization), set by DagRunner._call_node.

New: Trigger shorthand

TriggerConfig accepts a bare cron string (e.g., "*/13 * * * * *") and expands it to {type: "poll", schedule: "..."}. Trigger names auto-derive from the node's nsref leaf when omitted.

New: --verbose flag for CLI

Main model includes a verbose: bool field. When --verbose is passed, ActionTree._run_args prints the full traceback on error instead of just the message.

Changed

  • EngineConfig.namespace changed from list[NsNodeConfig] to list[dict[str, Any]] so fragment-specific fields pass through to Namespace.from_dict without Pydantic stripping them.
  • GlobalRef now accepts bound methods (ismethod added to the callable check).
  • Namespace.get_as_dag sets parent_namespace on ad-hoc single-node DAGs, so callables using DagContext.namespace work correctly.

Fixes

  • Cache DDL for zero-arg functionsgenerate_cache_table_ddl produced PRIMARY KEY () for parameterless functions. Fixed: conditional PRIMARY KEY in DDL, empty WHERE in lookup, DELETE-before-INSERT in upsert.
  • Node failure tracebacksDagRunner.run() now captures traceback.format_exc(), logs it via logging.error, and stores the full traceback in node_executions.error.
  • Silent ad-hoc DAG failuresget_as_dag() created DAGs without parent_namespace, causing "DagContext has no namespace" errors for callables using ns_call.