Coverage for tests / test_git.py: 100.00%

45 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-11 11:48 +0100

1"""Tests for creating a griffe Module from specific commits in a git repository.""" 

2 

3from __future__ import annotations 

4 

5import shutil 

6from subprocess import run 

7from typing import TYPE_CHECKING 

8 

9import pytest 

10 

11from griffe import Module, check, load_git 

12from tests import FIXTURES_DIR 

13 

14if TYPE_CHECKING: 

15 from pathlib import Path 

16 

17 from pytest_gitconfig import GitConfig 

18 

19REPO_NAME = "my-repo" 

20REPO_SOURCE = FIXTURES_DIR / "_repo" 

21MODULE_NAME = "my_module" 

22 

23 

24def _copy_contents(src: Path, dst: Path) -> None: 

25 """Copy *contents* of src into dst. 

26 

27 Parameters: 

28 src: the folder whose contents will be copied to dst 

29 dst: the destination folder 

30 """ 

31 dst.mkdir(exist_ok=True, parents=True) 

32 for src_path in src.iterdir(): 

33 dst_path = dst / src_path.name 

34 if src_path.is_dir(): 

35 _copy_contents(src_path, dst_path) 

36 else: 

37 shutil.copy(src_path, dst_path) 

38 

39 

40@pytest.fixture 

41def git_repo(tmp_path: Path, gitconfig: GitConfig) -> Path: # noqa: ARG001 

42 """Fixture that creates a git repo with multiple tagged versions. 

43 

44 For each directory in `tests/test_git/_repo/` 

45 

46 - the contents of the directory will be copied into the temporary repo 

47 - all files will be added and commited 

48 - the commit will be tagged with the name of the directory 

49 

50 To add to these tests (i.e. to simulate change over time), either modify one of 

51 the files in the existing `v0.1.0`, `v0.2.0` folders, or continue adding new 

52 version folders following the same pattern. 

53 

54 Parameters: 

55 tmp_path: temporary directory fixture 

56 

57 Returns: 

58 Path: path to temporary repo. 

59 """ 

60 repo_path = tmp_path / REPO_NAME 

61 repo_path.mkdir() 

62 run(["git", "-C", str(repo_path), "init"], check=True) 

63 for tagdir in REPO_SOURCE.iterdir(): 

64 ver = tagdir.name 

65 _copy_contents(tagdir, repo_path) 

66 run(["git", "-C", str(repo_path), "add", "."], check=True) 

67 run(["git", "-C", str(repo_path), "commit", "-m", f"feat: {ver} stuff"], check=True) 

68 run(["git", "-C", str(repo_path), "tag", ver], check=True) 

69 return repo_path 

70 

71 

72def test_load_git(git_repo: Path) -> None: 

73 """Test that we can load modules from different commits from a git repo. 

74 

75 Parameters: 

76 git_repo: temporary git repo 

77 """ 

78 v1 = load_git(MODULE_NAME, ref="v0.1.0", repo=git_repo) 

79 v2 = load_git(MODULE_NAME, ref="v0.2.0", repo=git_repo) 

80 assert isinstance(v1, Module) 

81 assert isinstance(v2, Module) 

82 assert v1.attributes["__version__"].value == "'0.1.0'" 

83 assert v2.attributes["__version__"].value == "'0.2.0'" 

84 

85 

86def test_load_git_errors(git_repo: Path) -> None: 

87 """Test that we get informative errors for various invalid inputs. 

88 

89 Parameters: 

90 git_repo: temporary git repo 

91 """ 

92 with pytest.raises(OSError, match="Not a git repository"): 

93 load_git(MODULE_NAME, ref="v0.2.0", repo="not-a-repo") 

94 

95 with pytest.raises(RuntimeError, match="Could not create git worktree"): 

96 load_git(MODULE_NAME, ref="invalid-tag", repo=git_repo) 

97 

98 with pytest.raises(ImportError, match="ModuleNotFoundError: No module named 'not_a_real_module'"): 

99 load_git("not_a_real_module", ref="v0.2.0", repo=git_repo) 

100 

101 

102def test_git_failures(tmp_path: Path) -> None: 

103 """Test failures to use Git.""" 

104 assert check(tmp_path) == 2