Source code for palsparserpy.structs

"""
The values :func:`palsparserpy.parse_and_expand_pals` hands back: the problems
found while expanding a lattice, and the five views of the lattice itself.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple

from .node import YAMLNode

__all__ = [
    "ProblemSeverity", "ProblemOrigin", "Problem", "Lattices",
    "NodeCorrespondence",
    "PROBLEM_ERROR", "PROBLEM_WARNING",
    "PROBLEM_INPUT", "PROBLEM_UNSUPPORTED", "PROBLEM_UNSPECIFIED",
]


[docs] class ProblemSeverity(IntEnum): """Whether a problem leaves the expanded trees trustworthy. - ``ERROR`` -- the document is wrong here and expansion could not work around it. Do not trust the affected part of the trees. - ``WARNING`` -- expansion produced a usable result; something was assumed or skipped, but the trees are still sound. Mirrors ``enum problem_severity`` in PALSParserCpp.h. """ ERROR = 0 WARNING = 1
[docs] class ProblemOrigin(IntEnum): """Who has to act on a problem. - ``INPUT`` -- the document is wrong; the lattice author can fix it. - ``UNSUPPORTED`` -- valid PALS that PALSParserCpp does not implement yet. Editing the lattice will not clear it. - ``UNSPECIFIED`` -- the PALS standard does not define the case, so nothing was invented. Neither the author nor the library is in the wrong. Mirrors ``enum problem_origin`` in PALSParserCpp.h. """ INPUT = 0 UNSUPPORTED = 1 UNSPECIFIED = 2
# The C spellings, so that a problem list can be filtered without reaching # through the enum class. PROBLEM_ERROR = ProblemSeverity.ERROR PROBLEM_WARNING = ProblemSeverity.WARNING PROBLEM_INPUT = ProblemOrigin.INPUT PROBLEM_UNSUPPORTED = ProblemOrigin.UNSUPPORTED PROBLEM_UNSPECIFIED = ProblemOrigin.UNSPECIFIED
[docs] @dataclass(frozen=True) class Problem: """One problem found while reading or expanding a document. - ``message`` -- human-readable description, always present. - ``path`` -- the logical spot it was found at, such as ``"q1>ApertureP.shape"``. Empty when the problem is not tied to one place. This is a location within the document, not a file name or a line number; ``message`` already names the file where the file is the point. - ``severity`` -- a :class:`ProblemSeverity`: can the trees still be trusted? - ``origin`` -- a :class:`ProblemOrigin`: whose problem is it? Only a ``PROBLEM_INPUT`` can be cleared by editing the lattice, which is what makes the last field worth reading: a tool that fails on any problem at all will fail on lattices whose author has nothing left to fix. """ message: str path: str severity: ProblemSeverity origin: ProblemOrigin def __str__(self): out = "ERROR" if self.severity is ProblemSeverity.ERROR else "WARNING" if self.origin is ProblemOrigin.UNSUPPORTED: out += " (unsupported)" elif self.origin is ProblemOrigin.UNSPECIFIED: out += " (unspecified by PALS)" if self.path: out += f" at {self.path}" return f"{out}: {self.message}"
[docs] @dataclass(frozen=True) class Lattices: """Five representations of a lattice, each as a root :class:`YAMLNode`, plus the list of problems found while expanding it. ``expanded`` and ``full_expanded`` are the same expanded lattice holding the same values; ``full_expanded`` additionally carries every parameter the bookkeeper computed, while ``expanded`` keeps only what the author wrote. See :func:`palsparserpy.parse_and_expand_pals` for what each view holds. ``problems`` is a list of :class:`Problem` -- one entry per problem encountered during expansion (undefined lattice, dangling element/line references, undefined ``inherit``/``repeat``/``Fork`` targets, misspelled names, and expressions that could not be evaluated). It is empty when expansion was clean. Filter it on ``severity`` or ``origin`` to decide what is worth acting on:: lat = parse_and_expand_pals("ex.pals.yaml", problems="none") mine = [p for p in lat.problems if p.origin is PROBLEM_INPUT] """ original: YAMLNode combined: YAMLNode expanded: YAMLNode full_expanded: YAMLNode adjunct: YAMLNode problems: List[Problem] = field(default_factory=list)
[docs] class NodeCorrespondence(NamedTuple): """The nodes one logical entity maps to in each of the four derivation-chain trees, grouped by tree. ``expanded`` takes no part -- it is a pruned copy of ``full_expanded``, not a step in the chain. A field is empty when a tree has no corresponding node. """ original: List[YAMLNode] combined: List[YAMLNode] full_expanded: List[YAMLNode] adjunct: List[YAMLNode]