pep723.py 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. import re
  2. from typing import Any
  3. from pip._internal.utils.compat import tomllib
  4. REGEX = r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
  5. class PEP723Exception(ValueError):
  6. """Raised to indicate a problem when parsing PEP 723 metadata from a script"""
  7. def __init__(self, msg: str) -> None:
  8. self.msg = msg
  9. def pep723_metadata(scriptfile: str) -> dict[str, Any]:
  10. with open(scriptfile) as f:
  11. script = f.read()
  12. name = "script"
  13. matches = list(
  14. filter(lambda m: m.group("type") == name, re.finditer(REGEX, script))
  15. )
  16. if len(matches) > 1:
  17. raise PEP723Exception(f"Multiple {name!r} blocks found in {scriptfile!r}")
  18. elif len(matches) == 1:
  19. content = "".join(
  20. line[2:] if line.startswith("# ") else line[1:]
  21. for line in matches[0].group("content").splitlines(keepends=True)
  22. )
  23. try:
  24. metadata = tomllib.loads(content)
  25. except Exception as exc:
  26. raise PEP723Exception(f"Failed to parse TOML in {scriptfile!r}") from exc
  27. else:
  28. raise PEP723Exception(
  29. f"File does not contain {name!r} metadata: {scriptfile!r}"
  30. )
  31. return metadata