Spaces:
Running
Running
import re | |
from abc import ABCMeta, abstractmethod | |
from typing import Iterator, Mapping, Optional, Pattern | |
_posix_variable: Pattern[str] = re.compile( | |
r""" | |
\$\{ | |
(?P<name>[^\}:]*) | |
(?::- | |
(?P<default>[^\}]*) | |
)? | |
\} | |
""", | |
re.VERBOSE, | |
) | |
class Atom(metaclass=ABCMeta): | |
def __ne__(self, other: object) -> bool: | |
result = self.__eq__(other) | |
if result is NotImplemented: | |
return NotImplemented | |
return not result | |
def resolve(self, env: Mapping[str, Optional[str]]) -> str: ... | |
class Literal(Atom): | |
def __init__(self, value: str) -> None: | |
self.value = value | |
def __repr__(self) -> str: | |
return f"Literal(value={self.value})" | |
def __eq__(self, other: object) -> bool: | |
if not isinstance(other, self.__class__): | |
return NotImplemented | |
return self.value == other.value | |
def __hash__(self) -> int: | |
return hash((self.__class__, self.value)) | |
def resolve(self, env: Mapping[str, Optional[str]]) -> str: | |
return self.value | |
class Variable(Atom): | |
def __init__(self, name: str, default: Optional[str]) -> None: | |
self.name = name | |
self.default = default | |
def __repr__(self) -> str: | |
return f"Variable(name={self.name}, default={self.default})" | |
def __eq__(self, other: object) -> bool: | |
if not isinstance(other, self.__class__): | |
return NotImplemented | |
return (self.name, self.default) == (other.name, other.default) | |
def __hash__(self) -> int: | |
return hash((self.__class__, self.name, self.default)) | |
def resolve(self, env: Mapping[str, Optional[str]]) -> str: | |
default = self.default if self.default is not None else "" | |
result = env.get(self.name, default) | |
return result if result is not None else "" | |
def parse_variables(value: str) -> Iterator[Atom]: | |
cursor = 0 | |
for match in _posix_variable.finditer(value): | |
(start, end) = match.span() | |
name = match["name"] | |
default = match["default"] | |
if start > cursor: | |
yield Literal(value=value[cursor:start]) | |
yield Variable(name=name, default=default) | |
cursor = end | |
length = len(value) | |
if cursor < length: | |
yield Literal(value=value[cursor:length]) | |