Instruction Tags¶
All instruction tags recognized during composition. Tags are processed on YAML mapping keys and removed from the final tree (unless noted otherwise).
Processing Order¶
!set_default/!define?-- soft variable definitions!define-- hard variable definitions!each-- loop expansion!if-- conditional inclusion
After all instructions:
!require-- checked for unsatisfied requirements!assert-- evaluated in a separate pass
!include, !deferred, !noconstruct, and !unset are handled by the composition pipeline directly, not by the instruction registry.
!define¶
Define a variable and add it to the context of sibling and descendant nodes. The definition node is removed from the tree.
The value can be:
- A scalar (string, number, bool)
- An interpolation expression (
${...}) -- evaluated at composition time - A mapping or sequence -- constructed immediately
- A
!fncallable -- stored as aDraconCallable - A
!pipepipeline -- stored as aDraconPipe - A tagged mapping (e.g.
!MyModel) -- lazily constructed asLazyConstructable
Variable names must be valid Python identifiers.
!define:type¶
Coerce the value to a specific type after evaluation.
Supported types: int, float, str, bool, list, dict.
!set_default / !define?¶
Soft definition. Sets the variable only if it does not already exist in the context. Values from !define or CLI ++ override soft defaults.
Also supports typed coercion: !set_default:int, !define?:float, etc.
!require¶
Declares that a variable must be provided by some outer scope (a !define, a !set_default, CLI ++, or programmatic context). Checked after all instructions have run.
If the variable is not satisfied by end of composition, raises CompositionError with the hint message. Removed from the tree (pure validation).
!assert¶
Validate an invariant on the composed tree. Evaluated after all other instructions.
The key must be an interpolation expression that evaluates to a truthy/falsy value. If falsy, raises CompositionError with the message. Removed from the tree.
!if¶
Conditional inclusion. The key is an expression evaluated for truthiness.
Shorthand form¶
Include the content if the condition is true, otherwise remove the node entirely:
Then/else form¶
If the else key is absent and the condition is false, the node is removed.
The condition value can be a plain scalar (true/false/0/1) or an interpolation.
!each¶
Loop expansion. Duplicates the template body for each item in a list-like expression.
The variable (name in this example) is available in ${...} expressions inside the template.
Sequence value (generates list items)¶
When all keys in a mapping are !each instructions with sequence values, they are expanded and spliced into the parent sequence.
Key expression¶
The key must be an interpolation expression that evaluates to an iterable. Plain scalars are not valid.
Nested instructions¶
!each can contain other instructions (!define, !if, etc.) in its body. They are expanded per-iteration.
!fn¶
Define a callable YAML template. Three forms:
File reference¶
Loads the file as a template. Each call deepcopies the template, injects kwargs as context, and runs composition + construction.
Inline mapping¶
!define greeting: !fn
!require name: "name is required"
!set_default greeting: "Hello"
message: "${greeting}, ${name}!"
The !fn tag goes on the value node, not as a separate key. The mapping body becomes the template. Use !require for mandatory parameters and !set_default for optional ones.
Expression lambda¶
The value is an interpolation expression. Parameters come from the caller's kwargs.
Return marker (!fn :)¶
Inside a mapping template body, tagging a key with !fn marks it as the return value. The callable returns only that value instead of the whole mapping.
!define compute: !fn
!require x: "input"
intermediate: ${x * 2}
!fn : ${intermediate + 1}
# compute(x=5) returns 11, not the whole mapping
Invocation¶
Callables defined by !fn are invoked via ${fn_name(key=value)} in expressions or programmatically as regular Python callables.
!fn:path (Partial Application)¶
Creates a DraconPartial -- a partial application of a Python callable with pre-filled kwargs.
The dotted path is resolved as a Python import. The mapping body provides default kwargs. At call time, runtime kwargs override the defaults.
If the path has no dots, it is looked up in the current context instead of imported.
!pipe¶
Function composition. Chains a sequence of callables where each stage's output feeds into the next.
!define pipeline: !pipe
- load_data
- clean_data:
remove_nulls: true
- ${custom_transform}
- !fn:mymodule.save
path: output.csv
Stage types¶
- Bare name: resolved from context
- Name with kwargs:
name: {kwargs}-- pre-fills kwargs for that stage - Interpolation:
${expr}-- resolved at definition time - Tagged node:
!fn:path {kwargs}-- constructed via the loader
Value threading¶
- If a stage returns a mapping, it is unpacked as
**kwargsinto the next stage - If a stage returns a non-mapping, it is passed as the single unfilled
!requireparameter of the next stage
Nested DraconPipe instances are flattened automatically.
!include¶
Include content from an external source. See Include Schemes for the full list of schemes.
database: !include file:db.yaml
settings: !include pkg:mypackage:defaults.yaml
api_key: !include env:API_KEY
Selector¶
Append @keypath to extract a subtree:
Internal references¶
- Absolute path:
!include /some.path-- reference within the current document - Relative path:
!include .siblingor!include ..parent.key - Anchor:
!include anchor_nameor!include anchor_name.sub.key
!include?¶
Optional include. If the source is not found (e.g. missing file), the node is silently removed instead of raising FileNotFoundError.
!deferred¶
Pause composition at this node. The subtree is wrapped in a DeferredNode and not processed further until explicitly composed/constructed at runtime.
Extended syntax¶
!deferred:Type¶
Specify the target type for construction:
!deferred::query_params¶
Query-string style parameters:
clear_ctx=true-- clear the inherited context before constructingreroot=true-- re-root the composition at this node
!deferred::query:Type¶
Combine query params and a type:
!noconstruct¶
When used as a tag on a mapping key, !noconstruct causes the entire key-value pair to be skipped during construction. The pair does not appear in the constructed output at all.
!unset¶
Mark a key for deletion during merge processing. Used to remove inherited keys.
After merges are processed, any key with !unset as its value is deleted from the parent mapping.
Custom Instructions¶
Register your own instruction tags:
from dracon import register_instruction, Instruction
class MyInstruction(Instruction):
@staticmethod
def match(value):
if value == '!mytag':
return MyInstruction()
return None
def process(self, comp_res, path, loader):
# modify comp_res and return it
return comp_res
register_instruction('!mytag', MyInstruction)