Source code for action0.celery_sched.formats
"""
The file formats a schedule can be written in, and how the loaders tell them apart.
A schedule means the same whatever its format — the entries have the same
keys and values — so the format only decides which parser turns the text into
data. By default a file's suffix decides: ``.yaml`` and ``.yml`` are YAML,
``.toml`` is TOML. A stream is judged by its ``name`` (which files opened with
:py:func:`open` have); anything else needs an explicit ``format``.
TOML is read with the standard library's :py:mod:`tomllib`. YAML needs
PyYAML, which comes with the ``yaml`` extra
(``pip install "action0-celery-sched[yaml]"``); it is imported only once a
YAML source is actually read, so TOML-only installs never need it.
"""
from collections.abc import Callable
from enum import StrEnum
from pathlib import PurePath
from typing import Any
from typing import Literal
from typing import TypeAlias
from action0.celery_sched.toml_loader import load_toml
#: a :py:class:`Format`, or its value as a plain string
FormatLike: TypeAlias = Format | Literal["yaml", "toml"]
#: the file suffixes each format is recognised by (compared case-insensitively)
SUFFIXES: dict[str, Format] = {
".yaml": Format.YAML,
".yml": Format.YAML,
".toml": Format.TOML,
}
[docs]
def parse_text(text: str, format: Format) -> Any:
"""
Parse schedule text in the given format.
>>> parse_text("[Poll]\\ntask = 'myapp.tasks.poll'", Format.TOML)
{'Poll': {'task': 'myapp.tasks.poll'}}
:param text: the document
:param format: its format
:returns: the parsed document, as plain Python data
:raises DefinitionError: if the text is malformed
:raises ImportError: for YAML, if PyYAML (the ``yaml`` extra) is not installed
"""
return parser_for(format)(text)
[docs]
def parser_for(format: Format) -> Callable[[str], Any]:
"""
Get the parser of a format, importing the YAML one on first use.
The loaders call this *before* reading a source, so a missing PyYAML is
reported without any I/O, like a format that can't be told.
>>> parser_for(Format.TOML).__name__
'load_toml'
:param format: the format
:returns: a function turning text in that format into plain Python data
:raises ImportError: for YAML, if PyYAML (the ``yaml`` extra) is not installed
"""
if format is Format.TOML:
return load_toml
try:
from action0.celery_sched.yaml_loader import load_yaml
except ImportError as error:
if error.name != "yaml": # a real bug, not the missing extra
raise
raise ImportError(
"YAML schedules need PyYAML: pip install 'action0-celery-sched[yaml]'"
) from error
return load_yaml
def _choices() -> str:
"""The format values, for error messages."""
return ", ".join(repr(choice.value) for choice in Format)