Coverage for tsfpga/tools/sphinx_doc.py: 0%
59 statements
« prev ^ index » next coverage.py v6.4, created at 2022-05-28 04:01 +0000
« prev ^ index » next coverage.py v6.4, created at 2022-05-28 04:01 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project.
5# https://tsfpga.com
6# https://gitlab.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
8# A set of methods for building sphinx docs. Should be reusable between projects.
9# --------------------------------------------------------------------------------------------------
11from datetime import datetime
12from subprocess import check_call
13import sys
15from git import Repo
16from packaging.version import parse
18from tsfpga.system_utils import read_file
21def generate_release_notes(repo_root, release_notes_directory, project_name):
22 """
23 Generate release notes in RST format based on a directory full of release note files.
24 Will match each file to a git tag.
26 Arguments:
27 repo_root (pathlib.Path): Git commands will be executed here.
28 release_notes_directory (pathlib.Path): Location of release notes files.
29 project_name (str): Name of project will be used for the gitlab link.
31 Return:
32 str: RST code with release notes.
33 """
34 rst = ""
36 for release, previous_release_git_tag in _get_release_notes_files(
37 repo_root=repo_root, release_notes_directory=release_notes_directory
38 ):
39 heading = f"{release.version} ({release.date})"
40 rst += heading + "\n"
41 rst += "-" * len(heading) + "\n"
42 rst += "\n"
43 if previous_release_git_tag is not None:
44 diff_url = (
45 f"https://gitlab.com/tsfpga/{project_name}/-/compare/"
46 f"{previous_release_git_tag}...{release.git_tag}"
47 )
48 rst += f"`Changes since previous release <{diff_url}>`__\n"
49 rst += "\n"
50 rst += read_file(release.release_notes_file)
51 rst += "\n"
53 return rst
56def _get_release_notes_files(repo_root, release_notes_directory):
57 """
58 Iterate the release notes.
59 """
60 unreleased_notes_file = release_notes_directory / "unreleased.rst"
62 release_notes = []
64 # Get all versioned release notes files and sort them in order newest -> oldest
65 for release_notes_file in release_notes_directory.glob("*.rst"):
66 if not release_notes_file == unreleased_notes_file:
67 release_notes.append(release_notes_file)
69 # Sort by parsing the version number in the file name. Newest to oldest.
70 def sort_key(path):
71 return parse(path.stem)
73 release_notes.sort(key=sort_key, reverse=True)
75 # The "Unreleased" shall be first
76 release_notes.insert(0, unreleased_notes_file)
78 repo = Repo(repo_root)
79 releases = [
80 Release(repo=repo, release_notes_file=release_notes_file)
81 for release_notes_file in release_notes
82 ]
84 for idx, release in enumerate(releases):
85 if idx == len(releases) - 1:
86 previous_release_git_tag = None
87 else:
88 previous_release_git_tag = releases[idx + 1].git_tag
90 yield release, previous_release_git_tag
93class Release:
94 """
95 Used to represent a release.
96 """
98 def __init__(self, repo, release_notes_file):
99 self.release_notes_file = release_notes_file
101 version = release_notes_file.stem
102 if version == "unreleased":
103 self.version = "Unreleased"
104 self.git_tag = "master"
105 self.date = "YYYY-MM-DD"
106 else:
107 self.version = version
108 self.git_tag = "v" + self.version
109 self.date = self.get_git_date_from_tag(repo=repo, tag=self.git_tag)
111 @staticmethod
112 def get_git_date_from_tag(repo, tag):
113 """
114 Get a formatted date string, gathered from git log based on tag name.
115 """
116 timestamp = repo.tag(f"refs/tags/{tag}").commit.committed_date
117 time = datetime.fromtimestamp(timestamp)
118 return f"{time.day} {time:%B} {time.year}".lower()
121def build_sphinx(build_path, output_path):
122 """
123 Execute sphinx on command line to build HTML documentation.
125 Arguments:
126 build_path (pathlib.Path): The location that contains ``conf.py`` and ``index.rst``.
127 output_path (pathlib.Path): Where to place the generated HTML.
128 """
129 cmd = [
130 sys.executable,
131 "-m",
132 "sphinx",
133 # Enable nitpicky mode
134 "-n",
135 # Turn errors into warnings
136 "-W",
137 # Show full traceback upon error
138 "-T",
139 str(build_path),
140 str(output_path),
141 ]
142 check_call(cmd, cwd=build_path)
144 index_html = output_path / "index.html"
145 assert index_html.exists(), index_html
146 print(f"Open with:\nfirefox {index_html} &")