Coverage for src/hatch_ci/version_hook.py: 0%

1 from __future__ import annotations

2

3 from typing import Any

4

5 from hatchling.version.source.plugin.interface import VersionSourceInterface

6

7 from .common import PLUGIN_NAME

8

9

10 class ValidationError(Exception):

11 pass

12

13

14 class _NO:

15 pass

16

17

18 def extract(

19 config: dict[str, str], var: str, typ: Any = _NO, fallback: Any = _NO

20) -> Any:

21 value = config.get(var, fallback)

22 if value is _NO:

23 raise ValidationError(f"cannot find variable '{var}' for plugin 'ci'")

24 try:

25 new_value = typ(value) if typ is not _NO else value

26 except Exception as exc:

27 raise ValidationError(f"cannot convert to {typ=} the {value=}") from exc

28 return new_value

29

30

31 def get_fixers(txt: str) -> dict[str, str]:

32 if not txt:

33 return {}

34 if not isinstance(txt, list):

35 raise ValidationError("fixers must be list of dicts")

36 if not all(isinstance(t, list) for t in txt):

37 raise ValidationError("fixers elements must be lists")

38 if not all(len(t) == 2 for t in txt):

39 raise ValidationError("all fixers list elements must be of length 2")

40 return dict(txt)

41

42

43 class CIVersionSource(VersionSourceInterface):

44 PLUGIN_NAME = PLUGIN_NAME

45

46 def get_version_data(self):

47 from os import getenv

48 from pathlib import Path

49

50 from hatch_ci import tools

51

52 paths = extract(self.config, "paths", typ=tools.list_of_paths, fallback=[])

53 fixers = extract(self.config, "fixers", typ=get_fixers, fallback={})

54 version_file = Path(self.root) / extract(self.config, "version-file")

55

56 if not version_file.exists():

57 raise ValidationError(

58 f"no 'version-file' key for plugin {self.PLUGIN_NAME}"

59 )

60 gdata = tools.process(

61 version_file, getenv("GITHUB_DUMP"), paths=paths, fixers=fixers

62 )

63 return {"version": gdata["version"]}