diff options
| author | Christoph Schlosser <christoph@linux.com> | 2025-08-24 17:10:11 +0200 |
|---|---|---|
| committer | Christoph Schlosser <christoph@linux.com> | 2025-08-24 17:10:11 +0200 |
| commit | 9bd3fd1bce788dce610ad7276ce1f1634019c380 (patch) | |
| tree | 59898b74445bf4a9e751b4b7bec46f85a7ad43d8 | |
| parent | 66dfe0e665ebeb0dce1ff290b77245e4a9fadd88 (diff) | |
| download | git2hugo-9bd3fd1bce788dce610ad7276ce1f1634019c380.tar.gz | |
g2h: Add unit tests and restructure class layout
Instead of having a large generator class use individual pages
| -rw-r--r-- | g2h/__init__.py | 0 | ||||
| -rw-r--r-- | g2h/cli.py | 8 | ||||
| -rw-r--r-- | g2h/gen.py | 49 | ||||
| -rw-r--r-- | g2h/log_page.py | 43 | ||||
| -rw-r--r-- | g2h/overview_page.py | 15 | ||||
| -rw-r--r-- | g2h/page.py | 18 | ||||
| -rw-r--r-- | g2h/page_factory.py | 13 | ||||
| -rw-r--r-- | mise.toml | 4 | ||||
| -rw-r--r-- | requirements.txt | 1 | ||||
| -rw-r--r-- | test_repo/git.tgz | bin | 16230 -> 16230 bytes | |||
| -rw-r--r-- | tests/__init__.py | 0 | ||||
| -rw-r--r-- | tests/log_test.py | 189 | ||||
| -rw-r--r-- | tests/overview_test.py | 8 | ||||
| -rw-r--r-- | tests/page_test.py | 19 |
14 files changed, 314 insertions, 53 deletions
diff --git a/g2h/__init__.py b/g2h/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/g2h/__init__.py @@ -2,7 +2,7 @@ import argparse import os from .git import Git -from .gen import Generator +from .page_factory import PageFactory def parse_args(): parser = argparse.ArgumentParser( @@ -25,9 +25,9 @@ def main(): project_name = args.name if args.name is not None else os.path.basename(args.repo_path) tags = git.get_tags() - gen = Generator(args.out_dir) - gen.render_overview(project_name, branches, tags) - gen.render_log(project_name, commits, branches, tags) + factory = PageFactory(args.out_dir, project_name) + factory.new_overview(branches, tags).render() + factory.new_log(commits, branches, tags).render() if __name__ == '__main__': main() diff --git a/g2h/gen.py b/g2h/gen.py deleted file mode 100644 index 9591d87..0000000 --- a/g2h/gen.py +++ /dev/null @@ -1,49 +0,0 @@ -from jinja2 import Environment, FileSystemLoader -import os - -def ref_names_for_commit(refs, commit_sha): - ref_names = [] - for ref in refs: - if ref.commit.hexsha == commit_sha: - ref_names.append(ref.name) - - return ref_names - -class Generator: - def __init__(self, output_dir): - self.output_dir = output_dir - template_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'templates')) - self.templates = Environment(loader=FileSystemLoader(template_dir)) - - def _render(self, template, context, out_path): - template = self.templates.get_template(template) - content = template.render(context) - out_file = os.path.join(self.output_dir, out_path) - os.makedirs(os.path.dirname(out_file), exist_ok=True) - with open(out_file, 'w', encoding='utf-8') as f: - f.write(content) - - def render_log(self, name, commits, branches, tags): - commits_context = [] - for commit in commits: - refs = ref_names_for_commit(branches, commit.hexsha) + ref_names_for_commit(tags, commit.hexsha) - commit_context = { - 'committed_datetime': commit.committed_datetime, - 'refs': refs, - 'summary': commit.summary - } - commits_context.append(commit_context) - - context = { - 'commits': commits_context, - 'title': name + ': Log' - } - self._render('log.md', context, 'l.md') - - def render_overview(self, name, branches, tags): - context = { - 'branches': branches, - 'tags': tags, - 'title': name - } - self._render('overview.md', context, '_index.md') diff --git a/g2h/log_page.py b/g2h/log_page.py new file mode 100644 index 0000000..684a758 --- /dev/null +++ b/g2h/log_page.py @@ -0,0 +1,43 @@ +import os + +from .page import Page + +def ref_names_for_commit(refs, commit_sha): + ref_names = [] + if refs is None: + return ref_names + for ref in refs: + if ref.commit.hexsha == commit_sha: + ref_names.append(ref.name) + + return ref_names + +class LogPage(Page): + def __init__(self, out_dir, name, commits, branches, tags): + super(LogPage, self).__init__('log.md', out_dir, 'l.md', name) + self.commits = commits + self.branches = branches + self.tags = tags + + def _commits_with_refs(self): + commits_context = [] + for commit in self.commits: + refs = ref_names_for_commit(self.branches, commit.hexsha) + ref_names_for_commit(self.tags, commit.hexsha) + commit_context = { + 'committed_datetime': commit.committed_datetime, + 'refs': refs, + 'summary': commit.summary + } + commits_context.append(commit_context) + return commits_context + + def context(self): + commits_context = [] + if self.commits is not None: + commits_context = self._commits_with_refs() + + return { + 'commits': commits_context, + 'title': self.name + ': Log' + } + diff --git a/g2h/overview_page.py b/g2h/overview_page.py new file mode 100644 index 0000000..1693b9a --- /dev/null +++ b/g2h/overview_page.py @@ -0,0 +1,15 @@ +from .page import Page + +class OverviewPage(Page): + def __init__(self, out_dir, name, branches, tags): + super(OverviewPage, self).__init__('overview.md', out_dir, '_index.md', name) + self.branches = branches + self.tags = tags + + def context(self): + return { + 'branches': self.branches, + 'tags': self.tags, + 'title': self.name + } + diff --git a/g2h/page.py b/g2h/page.py new file mode 100644 index 0000000..44f97ee --- /dev/null +++ b/g2h/page.py @@ -0,0 +1,18 @@ +from jinja2 import Environment, FileSystemLoader +import os + +class Page: + def __init__(self, template_file, out_dir, out_file, name): + self.out_file_path = os.path.join(out_dir, out_file) + self.name = name + template_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'templates')) + self.template = Environment(loader=FileSystemLoader(template_dir)).get_template(template_file) + + def context(self): + raise NotImplementedError("Must override context") + + def render(self): + content = self.template.render(self.context()) + os.makedirs(os.path.dirname(self.out_file_path), exist_ok=True) + with open(self.out_file_path, 'w', encoding='utf-8') as f: + f.write(content) diff --git a/g2h/page_factory.py b/g2h/page_factory.py new file mode 100644 index 0000000..dae9675 --- /dev/null +++ b/g2h/page_factory.py @@ -0,0 +1,13 @@ +from .overview_page import OverviewPage +from .log_page import LogPage + +class PageFactory: + def __init__(self, out_dir, name): + self.out_dir = out_dir + self.name = name + + def new_overview(self, branches, tags): + return OverviewPage(self.out_dir, self.name, branches, tags) + + def new_log(self, commits, branches, tags): + return LogPage(self.out_dir, self.name, commits, branches, tags) @@ -11,6 +11,10 @@ description = "Run g2h with the test repo" alias = "r" run = "rm -rf ./test_out && python3 -m g2h.cli test_repo test_out --name 'Test repo'" +[tasks.test] +alias = "t" +run = "pytest" + [tasks.commit] run = [ 'tar czf test_repo/git.tgz -C test_repo .git', diff --git a/requirements.txt b/requirements.txt index a04e815..65a012c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ GitPython==3.1.45 Jinja2==3.1.6 +pytest==8.4.1 diff --git a/test_repo/git.tgz b/test_repo/git.tgz Binary files differindex 8506102..16afa55 100644 --- a/test_repo/git.tgz +++ b/test_repo/git.tgz diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/__init__.py diff --git a/tests/log_test.py b/tests/log_test.py new file mode 100644 index 0000000..1efe3bd --- /dev/null +++ b/tests/log_test.py @@ -0,0 +1,189 @@ +from g2h.log_page import LogPage +from unittest.mock import MagicMock + +def test_init(): + page = LogPage('test/log', 'log test', None, None, None) + assert(page.name == 'log test') + assert(page.out_file_path == 'test/log/l.md') + assert(page.template.name == 'log.md') + +def test_context_no_commits(): + page = LogPage('test/log', 'log test', None, None, None) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == []) + +def test_context_no_branches_and_tags(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + page = LogPage('test/log', 'log test', [commit], None, None) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': [], 'summary': 'mock commit'}]) + +def test_context_matching_branch_no_tags(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + branch = MagicMock() + branch.commit.hexsha = commit.hexsha + branch.name = 'mock branch' + page = LogPage('test/log', 'log test', [commit], [branch], None) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': ['mock branch'], 'summary': 'mock commit'}]) + +def test_context_unmatching_branch_no_tags(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + branch = MagicMock() + branch.commit.hexsha = 4321 + branch.name = 'mock branch' + page = LogPage('test/log', 'log test', [commit], [branch], None) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': [], 'summary': 'mock commit'}]) + +def test_context_no_branch_matching_tag(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + tag = MagicMock() + tag.commit.hexsha = commit.hexsha + tag.name = 'mock tag' + page = LogPage('test/log', 'log test', [commit], None, [tag]) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': ['mock tag'], 'summary': 'mock commit'}]) + +def test_context_no_branch_no_matching_tag(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + tag = MagicMock() + tag.commit.hexsha = 4321 + tag.name = 'mock tag' + page = LogPage('test/log', 'log test', [commit], None, [tag]) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': [], 'summary': 'mock commit'}]) + +def test_context_no_matching_branch_no_matching_tag(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + branch = MagicMock() + branch.commit.hexsha = 321 + branch.name = 'mock branch' + tag = MagicMock() + tag.commit.hexsha = 4321 + tag.name = 'mock tag' + page = LogPage('test/log', 'log test', [commit], [branch], [tag]) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': [], 'summary': 'mock commit'}]) + +def test_context_matching_branch_matching_tag(): + commit = MagicMock() + commit.summary = 'mock commit' + commit.hexsha = 1234; + commit.committed_datetime = 0 + branch = MagicMock() + branch.commit.hexsha = commit.hexsha + branch.name = 'mock branch' + tag = MagicMock() + tag.commit.hexsha = commit.hexsha + tag.name = 'mock tag' + page = LogPage('test/log', 'log test', [commit], [branch], [tag]) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [{'committed_datetime': 0, 'refs': ['mock branch', 'mock tag'], 'summary': 'mock commit'}]) + +def test_multiple_commits(): + commit1 = MagicMock() + commit1.summary = 'mock commit 1' + commit1.hexsha = 1; + commit1.committed_datetime = 0 + commit2 = MagicMock() + commit2.summary = 'mock commit 2' + commit2.hexsha = 2; + commit2.committed_datetime = 1 + page = LogPage('test/log', 'log test', [commit1, commit2], None, None) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [ + {'committed_datetime': 0, 'refs': [], 'summary': 'mock commit 1'}, + {'committed_datetime': 1, 'refs': [], 'summary': 'mock commit 2'} + ]) + +def test_multiple_commits_branch(): + commit1 = MagicMock() + commit1.summary = 'mock commit 1' + commit1.hexsha = 1; + commit1.committed_datetime = 0 + commit2 = MagicMock() + commit2.summary = 'mock commit 2' + commit2.hexsha = 2; + commit2.committed_datetime = 1 + branch = MagicMock() + branch.commit.hexsha = 1 + branch.name = 'mock branch' + page = LogPage('test/log', 'log test', [commit1, commit2], [branch], None) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [ + {'committed_datetime': 0, 'refs': ['mock branch'], 'summary': 'mock commit 1'}, + {'committed_datetime': 1, 'refs': [], 'summary': 'mock commit 2'} + ]) + +def test_multiple_commits_tag(): + commit1 = MagicMock() + commit1.summary = 'mock commit 1' + commit1.hexsha = 1; + commit1.committed_datetime = 0 + commit2 = MagicMock() + commit2.summary = 'mock commit 2' + commit2.hexsha = 2; + commit2.committed_datetime = 1 + tag = MagicMock() + tag.commit.hexsha = 1 + tag.name = 'mock tag' + page = LogPage('test/log', 'log test', [commit1, commit2], None, [tag]) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [ + {'committed_datetime': 0, 'refs': ['mock tag'], 'summary': 'mock commit 1'}, + {'committed_datetime': 1, 'refs': [], 'summary': 'mock commit 2'} + ]) + +def test_multiple_commits_branch_and_tag(): + commit1 = MagicMock() + commit1.summary = 'mock commit 1' + commit1.hexsha = 1; + commit1.committed_datetime = 0 + commit2 = MagicMock() + commit2.summary = 'mock commit 2' + commit2.hexsha = 2; + commit2.committed_datetime = 1 + branch = MagicMock() + branch.commit.hexsha = 1 + branch.name = 'mock branch' + tag = MagicMock() + tag.commit.hexsha = 2 + tag.name = 'mock tag' + page = LogPage('test/log', 'log test', [commit1, commit2], [branch], [tag]) + context = page.context() + assert(context['title'] == 'log test: Log') + assert(context['commits'] == [ + {'committed_datetime': 0, 'refs': ['mock branch'], 'summary': 'mock commit 1'}, + {'committed_datetime': 1, 'refs': ['mock tag'], 'summary': 'mock commit 2'} + ]) + diff --git a/tests/overview_test.py b/tests/overview_test.py new file mode 100644 index 0000000..fa51858 --- /dev/null +++ b/tests/overview_test.py @@ -0,0 +1,8 @@ +from g2h.overview_page import OverviewPage + +def test_init(): + page = OverviewPage('test/overview', 'overview test', 'test branch', 'test tag') + context = page.context() + assert(context['title'] == 'overview test') + assert(context['branches'] == 'test branch') + assert(context['tags'] == 'test tag') diff --git a/tests/page_test.py b/tests/page_test.py new file mode 100644 index 0000000..1008a8d --- /dev/null +++ b/tests/page_test.py @@ -0,0 +1,19 @@ +from g2h.page import Page +from jinja2.exceptions import TemplateNotFound +import pytest + +def test_init(): + page = Page('overview.md', 'dir', 'file', 'name') + assert(page.name == 'name') + assert(page.out_file_path == 'dir/file') + assert(page.template.name == 'overview.md') + +def test_wrong_template(): + with pytest.raises(TemplateNotFound): + Page('not existant.md', 'dir', 'file', 'name') + +def test_no_context(): + page = Page('overview.md', 'dir', 'file', 'name') + with pytest.raises(NotImplementedError): + page.context() + |