Coverage for tests/test_git.py: 100.00%

47 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-15 16:47 +0200

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 

17REPO_NAME = "my-repo" 

18REPO_SOURCE = FIXTURES_DIR / "_repo" 

19MODULE_NAME = "my_module" 

20 

21 

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

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

24 

25 Parameters: 

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

27 dst: the destination folder 

28 """ 

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

30 for src_path in src.iterdir(): 

31 dst_path = dst / src_path.name 

32 if src_path.is_dir(): 

33 _copy_contents(src_path, dst_path) 

34 else: 

35 shutil.copy(src_path, dst_path) 

36 

37 

38@pytest.fixture 

39def git_repo(tmp_path: Path) -> Path: 

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

41 

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

43 

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

45 - all files will be added and commited 

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

47 

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

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

50 version folders following the same pattern. 

51 

52 Parameters: 

53 tmp_path: temporary directory fixture 

54 

55 Returns: 

56 Path: path to temporary repo. 

57 """ 

58 repo_path = tmp_path / REPO_NAME 

59 repo_path.mkdir() 

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

61 run(["git", "-C", str(repo_path), "config", "user.name", "Name"], check=True) 

62 run(["git", "-C", str(repo_path), "config", "user.email", "my@email.com"], 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 worktre"): 

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