Reference: KeyPaths¶
Dracon uses KeyPaths internally to reference specific locations within a nested configuration structure during composition and interpolation. Understanding KeyPaths is essential for using features like value references (@), merge targets (@), include sub-key targeting (@), and deferred paths.
Syntax¶
KeyPaths use dot (.) notation as the primary separator, with special characters for root, parent navigation, and pattern matching:
- Segment Separator (
.): Separates keys in mappings or indices in sequences. - Example:
database.host,users.0.name - Absolute Root (
/): When used only at the beginning of a path, it indicates the path starts from the absolute root of the configuration document being processed. It is not used as a separator between segments. - Example:
/app/name(Incorrect! Or rather, probably not what you meant: it's strictly equivalent to/name),/app.name(Correct),/services.0.port(Correct) - Parent (
..): Navigates one level up in the hierarchy. Can be chained (...for two levels up, etc.). These are often resolved during path simplification (e.g.,a.b..cbecomesa.c). - Example:
config.database..timeout(accessestimeoutsibling ofdatabase) - Current (
.): Represents the current level. Often used implicitly for relative paths in interpolation, e.g.,${@.sibling}refers to a sibling key. A leading.like.!include .sibling_filewould typically be resolved relative to the current node's location context (often the parent directory). - Escaping (
\.,\/): Use a backslash (\) to escape literal dots (.) or slashes (/) if they appear within a key name itself. This is necessary to distinguish them from separators or the root indicator. - Example:
section\.with\.dots.value,a.path\/segment.key(References keys named "section.with.dots" and "path/segment" respectively). - Wildcards (for Matching Only): Used primarily in patterns like
deferred_pathsinDraconLoaderor potentially custom logic. Not used for direct value retrieval via@. *: Matches any single segment name/index (e.g.,a.*.cmatchesa.b.c).**: Matches zero or more consecutive segments (e.g.,a.**.dmatchesa.d,a.b.d, anda.b.c.d).- Partial segment matching with
*is also supported within patterns (e.g.,a.b*.cmatchesa.b.canda.bcd.c).
Separator is . not /
Remember that / denotes the absolute root. All subsequent levels in the path must be separated by dots (.). a/b/c will actually simplify to /c ; when what you probably meant was a.b.c.
Usage in Dracon¶
KeyPaths are the standard way to target nodes in various Dracon features:
-
Value References (
@in${...}) and Node Copies (&):${@/path.from.root}: Absolute KeyPath, starting from the root of the ENTIRE constructed configuration document.${@.sibling_key}: Relative KeyPath (sibling).${@..parent.key}: Relative KeyPath (navigating up).${&/key.subkey}: Absolute KeyPath, starting from the root of the CURRENT configuration graph being processed.- Example:
${@/database.host},${@.name},${@..config.timeout},${&/defaults.timeout * 2}(copies the current value ofdefaults.timeoutand multiplies it by 2). - See Interpolation Syntax.
-
Merge Targets (
<<...@target_path:):target_pathis a relative KeyPath from the mapping containing the merge key.- Example:
<<{+<}@database: *db_defaults(merges into thedatabasekey). - See Merge Key Syntax.
-
Deferred Paths (
DraconLoader(deferred_paths=...)):- List of absolute KeyPath patterns (supporting
*,**) identifying nodes to defer automatically. - Example:
['/services.*.connection', '/external_apis/**'] - See Deferred Execution Guide.
- List of absolute KeyPath patterns (supporting
-
Include Sub-key Targeting (
!include source@target_path):target_pathis a KeyPath within thesourcedocument.- Example:
!include file:settings.yaml@database.host(loads only the host value). - See Include Syntax.
Internal Representation & Simplification¶
While you typically interact with KeyPaths as strings, Dracon internally parses them into a list of segments and special tokens (like ROOT, UP). It performs simplification before using them for lookups or matching, resolving . and .. segments where possible (e.g., a.b..c simplifies to a.c, /a/b simplifies to /b). You generally don't need to worry about this unless debugging complex path issues.