version_check.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import os
  2. import re
  3. import runpy
  4. import subprocess
  5. import sys
  6. import docutils.nodes
  7. import docutils.parsers.rst
  8. import docutils.utils
  9. import docutils.frontend
  10. def parse_rst(text: str) -> docutils.nodes.document:
  11. parser = docutils.parsers.rst.Parser()
  12. components = (docutils.parsers.rst.Parser,)
  13. settings = docutils.frontend.OptionParser(
  14. components=components
  15. ).get_default_values()
  16. document = docutils.utils.new_document("<rst-doc>", settings=settings)
  17. parser.parse(text, document)
  18. return document
  19. class SectionVisitor(docutils.nodes.NodeVisitor):
  20. def __init__(self, *args, **kwargs):
  21. super().__init__(*args, **kwargs)
  22. self.sectiontitles_found = []
  23. def visit_section(self, node: docutils.nodes.section) -> None:
  24. """Called for "section" nodes."""
  25. title = node[0]
  26. assert isinstance(title, docutils.nodes.title)
  27. self.sectiontitles_found.append(title.astext())
  28. def unknown_visit(self, node: docutils.nodes.Node) -> None:
  29. """Called for all other node types."""
  30. pass
  31. def get_sphinxchangelog_version(rootdir):
  32. with open(os.path.join(rootdir, "docs", "changelog.rst"), mode="r") as f:
  33. doc = parse_rst(f.read())
  34. visitor = SectionVisitor(doc)
  35. doc.walk(visitor)
  36. unique_sectiontitles = set(visitor.sectiontitles_found)
  37. assert len(visitor.sectiontitles_found) == len(unique_sectiontitles)
  38. assert visitor.sectiontitles_found[0] == "Changelog"
  39. changelog_pattern = re.compile(r"^Version (\S+)((?: \(unreleased\)))?$")
  40. matchobj = changelog_pattern(visitor.sectiontitles_found[1])
  41. assert matchobj
  42. version = matchobj.group(1)
  43. version_unreleased = matchobj.group(2)
  44. matchobj = changelog_pattern(visitor.sectiontitles_found[2])
  45. assert matchobj
  46. release = matchobj.group(1)
  47. release_unreleased = matchobj.group(2)
  48. if version_unreleased:
  49. assert release_unreleased
  50. return version, release
  51. def get_sphinxconfpy_version(rootdir):
  52. """Get version from Sphinx' conf.py."""
  53. sphinx_conf = runpy.run_path(os.path.join(rootdir, "docs", "conf.py"))
  54. version, sep, bugfix = sphinx_conf["release"].rpartition(".")
  55. assert sep == "."
  56. assert bugfix
  57. assert version == sphinx_conf["version"]
  58. return sphinx_conf["version"], sphinx_conf["release"]
  59. def get_setuppy_version(rootdir):
  60. """Get version from setup.py."""
  61. setupfile = os.path.join(rootdir, "setup.py")
  62. cmd = (sys.executable, setupfile, "--version")
  63. release = subprocess.check_output(cmd, text=True).rstrip("\n")
  64. version = release.rpartition(".")[0]
  65. return version, release
  66. def main():
  67. rootdir = os.path.join(os.path.dirname(__file__), "..")
  68. setuppy_version, setuppy_release = get_setuppy_version(rootdir)
  69. confpy_version, confpy_release = get_setuppy_version(rootdir)
  70. changelog_version, changelog_release = get_setuppy_version(rootdir)
  71. version_head = "Version"
  72. version_width = max(
  73. [
  74. len(version_head),
  75. len(setuppy_version),
  76. len(confpy_version),
  77. len(changelog_version),
  78. ]
  79. )
  80. release_head = "Release"
  81. release_width = max(
  82. [
  83. len(release_head),
  84. len(setuppy_release),
  85. len(confpy_release),
  86. len(changelog_release),
  87. ]
  88. )
  89. print(
  90. f"File {version_head} {release_head}\n"
  91. f"------------------------------- {'-' * version_width}"
  92. f" {'-' * release_width}\n"
  93. f"setup.py {setuppy_version:>{version_width}}"
  94. f" {setuppy_release:>{release_width}}\n"
  95. f"docs/conf.py {confpy_version:>{version_width}}"
  96. f" {confpy_release:>{release_width}}\n"
  97. f"docs/changelog.rst {changelog_version:>{version_width}}"
  98. f" {changelog_release:>{release_width}}\n"
  99. )
  100. assert setuppy_version == confpy_version
  101. assert setuppy_version == changelog_version
  102. assert setuppy_release == confpy_release
  103. assert setuppy_release == changelog_release
  104. if __name__ == "__main__":
  105. main()