selectors.py 1.1 KB

12345678910111213141516171819202122232425262728293031323334
  1. import logging
  2. import re
  3. import dataclasses
  4. from .common import ALLOWED_NAMES, ALLOWED_GLOBALS
  5. from structures.common import BaseMeasurement
  6. logger = logging.getLogger(__name__)
  7. @dataclasses.dataclass(frozen=True)
  8. class Selection(BaseMeasurement):
  9. value: str
  10. series: str
  11. class ComplexSelector():
  12. def __init__(self, parent, selector) -> None:
  13. self._selector = selector
  14. self._compiled = compile(selector, "<string>", "eval")
  15. # Validate allowed names
  16. for name in self._compiled.co_names:
  17. if name not in ALLOWED_NAMES:
  18. raise NameError(f"The use of '{name}' is not allowed in '{selector}'")
  19. def execute(self, values):
  20. for measurement in values:
  21. try:
  22. value = eval(self._compiled, {"__builtins__": ALLOWED_GLOBALS}, measurement.__dict__)
  23. yield Selection(
  24. timestamp = measurement.timestamp,
  25. series = re.match(r"[\w_\.\-\(\)]+", self._selector).group(0),
  26. source = "selection",
  27. value=value
  28. )
  29. except Exception as e:
  30. logger.error(f"Error while evaluating selector '{self._selector}': {e}")