Skip to content

Rule Module

datajoint_file_validator.rule.Rule dataclass

A single rule for a fileset.

Source code in datajoint_file_validator/rule.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@dataclass
class Rule:
    """A single rule for a fileset."""

    id: Optional[str]
    description: Optional[str]
    constraints: List[Constraint] = field(default_factory=list)
    query: Query = field(default_factory=GlobQuery)

    def __post_init__(self):
        if not self.id:
            self.id = generate_id(self)

    def __hash__(self):
        return hash((self.id, self.query, tuple(self.constraints)))

    def validate(self, snapshot: Snapshot) -> Dict[str, ValidationResult]:
        filtered_snapshot: Snapshot = self.query.filter(snapshot)
        results = list(
            map(
                lambda constraint: constraint.validate(filtered_snapshot),
                self.constraints,
            )
        )
        return {
            constraint.name: result
            for constraint, result in zip(self.constraints, results)
        }

    @staticmethod
    def compile_query(raw: Any) -> "Query":
        if isinstance(raw, dict):
            try:
                return CompositeQuery.from_dict(raw)
            except InvalidQueryError as e:
                raise InvalidRuleError(f"Error parsing query: {e}") from e
        elif not isinstance(raw, str):
            raise InvalidRuleError(f"Query must be a string, not '{type(raw)}'")
        return GlobQuery(path=raw)

    @staticmethod
    def compile_constraint(
        name: str, val: Any, constraint_map=CONSTRAINT_MAP
    ) -> "Constraint":
        if name not in constraint_map:
            raise InvalidRuleError(f"Unknown constraint: '{name}'")
        try:
            return constraint_map[name](val)
        except Exception as e:
            raise InvalidRuleError(f"Error parsing constraint '{name}': {e}") from e

    @classmethod
    def from_dict(cls, d: Dict) -> "Rule":
        """Load a rule from a dictionary."""
        rest = {k: v for k, v in d.items() if k not in ("id", "description", "query")}
        try:
            self_ = cls(
                id=d.get("id"),
                description=d.get("description"),
                query=cls.compile_query(d.get("query", config.default_query)),
                constraints=[
                    cls.compile_constraint(name, val) for name, val in rest.items()
                ],
            )
        except InvalidRuleError as e:
            raise InvalidRuleError(f"Error parsing rule '{id}': {e}") from e
        return self_

from_dict(d) classmethod

Load a rule from a dictionary.

Source code in datajoint_file_validator/rule.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@classmethod
def from_dict(cls, d: Dict) -> "Rule":
    """Load a rule from a dictionary."""
    rest = {k: v for k, v in d.items() if k not in ("id", "description", "query")}
    try:
        self_ = cls(
            id=d.get("id"),
            description=d.get("description"),
            query=cls.compile_query(d.get("query", config.default_query)),
            constraints=[
                cls.compile_constraint(name, val) for name, val in rest.items()
            ],
        )
    except InvalidRuleError as e:
        raise InvalidRuleError(f"Error parsing rule '{id}': {e}") from e
    return self_