Python · 1491 bytes Raw Blame History
1 """Typed errors for `dlm.directives` path resolution + expansion.
2
3 `DirectiveError` is the package-wide base. Callers can catch it to
4 cover every directive failure in one handler (the CLI reporter does
5 this). Concrete subclasses carry enough context for the error message
6 to point at the offending directive in the frontmatter.
7 """
8
9 from __future__ import annotations
10
11 from pathlib import Path
12
13
14 class DirectiveError(Exception):
15 """Base for every `dlm.directives` failure."""
16
17
18 class DirectivePolicyError(DirectiveError):
19 """A directive's resolved path escapes the strict-policy root.
20
21 Only raised when `training.sources_policy == "strict"`. Under
22 permissive policy we only log a warning for symlink escapes and
23 proceed — users opted into that mode by explicitly choosing it.
24 """
25
26 def __init__(self, resolved: Path, root: Path) -> None:
27 self.resolved = resolved
28 self.root = root
29 super().__init__(
30 f"directive path {resolved!s} escapes strict-policy root {root!s}; "
31 "either move the path under the .dlm's parent directory or "
32 "set `training.sources_policy: permissive` to allow external paths"
33 )
34
35
36 class DirectivePathError(DirectiveError):
37 """A directive points at a path that doesn't exist or isn't readable."""
38
39 def __init__(self, path: Path, reason: str) -> None:
40 self.path = path
41 self.reason = reason
42 super().__init__(f"directive path {path!s}: {reason}")