path-link 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ from pathlib import Path
2
+ from dataclasses import dataclass, field
3
+
4
+ # This file is auto-generated by ptool-serena. Do not edit manually.
5
+ # Run `ptool gen-static` or `just regen` to regenerate.
6
+
7
+ @dataclass(frozen=True)
8
+ class ProjectPathsStatic:
9
+ """A static, auto-generated dataclass for project paths."""
10
+
11
+ root: Path = field(default_factory=Path.home)
12
+ base_dir: Path = field(default_factory=Path.cwd)
13
+ config_dir: Path = field(default_factory=lambda: Path.cwd() / "config")
14
+ data_dir: Path = field(default_factory=lambda: Path.cwd() / "data")
@@ -0,0 +1,94 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
3
+ from enum import Enum, auto
4
+ from typing import Protocol, TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from .model import _ProjectPathsBase
8
+
9
+
10
+ class Severity(Enum):
11
+ """Defines the severity level of a validation finding."""
12
+
13
+ INFO = auto()
14
+ WARNING = auto()
15
+ ERROR = auto()
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class Finding:
20
+ """Represents a single, structured validation issue."""
21
+
22
+ severity: Severity
23
+ code: str
24
+ message: str
25
+ field: str | None = None
26
+ path: str | None = None
27
+
28
+
29
+ @dataclass
30
+ class ValidationResult:
31
+ """Aggregates findings from a validation run."""
32
+
33
+ findings: list[Finding] = field(default_factory=list)
34
+
35
+ def add(self, *items: Finding) -> None:
36
+ """Adds one or more findings to the result."""
37
+ self.findings.extend(items)
38
+
39
+ def ok(self) -> bool:
40
+ """Returns True if there are no findings with ERROR severity."""
41
+ return not any(f.severity is Severity.ERROR for f in self.findings)
42
+
43
+ def errors(self) -> list[Finding]:
44
+ """Returns a list of all findings with ERROR severity."""
45
+ return [f for f in self.findings if f.severity is Severity.ERROR]
46
+
47
+ def warnings(self) -> list[Finding]:
48
+ """Returns a list of all findings with WARNING severity."""
49
+ return [f for f in self.findings if f.severity is Severity.WARNING]
50
+
51
+
52
+ class PathValidator(Protocol):
53
+ """
54
+ A protocol that all validator classes must implement.
55
+ """
56
+
57
+ def validate(self, p: "_ProjectPathsBase") -> ValidationResult: ...
58
+
59
+
60
+ @dataclass
61
+ class CompositeValidator:
62
+ """Combines multiple validators and runs them in sequence."""
63
+
64
+ parts: list[PathValidator]
65
+
66
+ def validate(self, p: "_ProjectPathsBase") -> ValidationResult:
67
+ out = ValidationResult()
68
+ for v in self.parts:
69
+ r = v.validate(p)
70
+ out.add(*r.findings)
71
+ return out
72
+
73
+
74
+ class PathValidationError(Exception):
75
+ """Custom exception raised for validation failures."""
76
+
77
+ def __init__(self, result: ValidationResult):
78
+ errors = [f for f in result.findings if f.severity is Severity.ERROR]
79
+ lines = [
80
+ f"- [{f.severity.name}] {f.code} {f.field or ''} -> {f.path or ''}: {f.message}"
81
+ for f in (errors or result.findings)
82
+ ]
83
+ super().__init__("\n".join(lines))
84
+ self.result = result
85
+
86
+
87
+ def validate_or_raise(p: "_ProjectPathsBase", v: PathValidator) -> ValidationResult:
88
+ """
89
+ A helper function that runs a validator and raises an exception on failure.
90
+ """
91
+ res = v.validate(p)
92
+ if not res.ok():
93
+ raise PathValidationError(res)
94
+ return res