1 2 3 4 5 6 7 8 9 10 11 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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
"""
pint.delegates.txt_defparser.group
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Definitions for parsing Group and their related objects
Notices that some of the checks are done within the
format agnostic parent definition class.
See each one for a slighly longer description of the
syntax.
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import annotations
import re
import typing as ty
from dataclasses import dataclass
import flexparser as fp
from ...facets.group import definitions
from ..base_defparser import PintParsedStatement
from . import block, common, plain
@dataclass(frozen=True)
class BeginGroup(PintParsedStatement):
"""Being of a group directive.
@group <name> [using <group 1>, ..., <group N>]
"""
#: Regex to match the header parts of a definition.
_header_re = re.compile(r"@group\s+(?P<name>\w+)\s*(using\s(?P<used_groups>.*))*")
name: str
using_group_names: ty.Tuple[str, ...]
@classmethod
def from_string(cls, s: str) -> fp.NullableParsedResult[BeginGroup]:
if not s.startswith("@group"):
return None
r = cls._header_re.search(s)
if r is None:
return common.DefinitionSyntaxError(f"Invalid Group header syntax: '{s}'")
name = r.groupdict()["name"].strip()
groups = r.groupdict()["used_groups"]
if groups:
parent_group_names = tuple(a.strip() for a in groups.split(","))
else:
parent_group_names = ()
return cls(name, parent_group_names)
@dataclass(frozen=True)
class GroupDefinition(
block.DirectiveBlock[
definitions.GroupDefinition,
BeginGroup,
ty.Union[
plain.CommentDefinition,
plain.UnitDefinition,
],
]
):
"""Definition of a group.
@group <name> [using <group 1>, ..., <group N>]
<definition 1>
...
<definition N>
@end
See UnitDefinition and Comment for more parsing related information.
Example::
@group AvoirdupoisUS using Avoirdupois
US_hundredweight = hundredweight = US_cwt
US_ton = ton
US_force_ton = force_ton = _ = US_ton_force
@end
"""
def derive_definition(self) -> definitions.GroupDefinition:
return definitions.GroupDefinition(
self.name, self.using_group_names, self.definitions
)
@property
def name(self) -> str:
assert isinstance(self.opening, BeginGroup)
return self.opening.name
@property
def using_group_names(self) -> tuple[str, ...]:
assert isinstance(self.opening, BeginGroup)
return self.opening.using_group_names
@property
def definitions(self) -> tuple[plain.UnitDefinition, ...]:
return tuple(el for el in self.body if isinstance(el, plain.UnitDefinition))
|