tasks.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from pathlib import Path
  2. from invoke import task
  3. from jinja2 import Template
  4. system = "mocka" # Directory name of the project
  5. main_branch = "main" # The release branch on origin
  6. dev_branch = "dev" # The main development branch on origin
  7. project_template = """
  8. [build-system]
  9. requires = ["flit_core >=3.9,<4"]
  10. build-backend = "flit_core.buildapi"
  11. [project]
  12. name = "{{ system }}"
  13. authors = [
  14. {name = "Arkadiusz Michał Ryś", email = "Arkadiusz.Michal.Rys@gmail.com"},
  15. {name = "Lucas Albertins de Lima", email = "lucas.albertinsdelima@uantwerpen.be"},
  16. {name = "Rakshit Mittal", email = "rakshit.mittal@uantwerpen.be"},
  17. ]
  18. readme = "README.md"
  19. requires-python = ">={{ minimum_version }}"
  20. classifiers = [
  21. "License :: OSI Approved :: MIT License",
  22. "Programming Language :: Python :: 3",
  23. "Development Status :: 2 - Pre-Alpha",
  24. "Intended Audience :: Developers",
  25. "Natural Language :: English",
  26. ]
  27. dynamic = ["version", "description"]
  28. license = {file = "LICENSE"}
  29. keywords = ["mocka"]
  30. dependencies = [
  31. {%- for dependency in requirements.mocka %}
  32. "{{ dependency }}",
  33. {%- endfor %}
  34. ]
  35. [project.optional-dependencies]
  36. test = [
  37. {%- for dependency in requirements.test %}
  38. "{{ dependency }}",
  39. {%- endfor %}
  40. ]
  41. doc = [
  42. {%- for dependency in requirements.doc %}
  43. "{{ dependency }}",
  44. {%- endfor %}
  45. ]
  46. dev = [
  47. {%- for dependency in requirements.dev %}
  48. "{{ dependency }}",
  49. {%- endfor %}
  50. ]
  51. [project.urls]
  52. source = "https://git.rys.one/dtdesign/mocka"
  53. [project.scripts]
  54. mocka = "mocka.cli:entry_point"
  55. """
  56. @task
  57. def lint(c):
  58. """"""
  59. c.run(f"python3 -m black {system}")
  60. c.run(f"python3 -m pylint {system}")
  61. @task(name="docs")
  62. def documentation(c):
  63. """Build the documentation."""
  64. c.run("python3 -m sphinx docs docs/build/html")
  65. @task(name="preview", aliases=("rst",))
  66. def preview(c):
  67. """Show a preview of the README file."""
  68. import sys
  69. rst_view = c.run(f"restview --listen=8888 --browser --pypi-strict README.rst", asynchronous=True, out_stream=sys.stdout)
  70. print("Listening on http://localhost:8888/")
  71. rst_view.join()
  72. @task
  73. def clean(c):
  74. """Remove all artefacts."""
  75. patterns = ["build", "docs/build"]
  76. for pattern in patterns:
  77. c.run(f"rm -rf {pattern}")
  78. @task
  79. def test(c):
  80. """Run all tests under the tests directory."""
  81. c.run("python3 -m pytest")
  82. @task
  83. def coverage(c):
  84. """Run coverage from the 'tests' directory."""
  85. c.run("python3 -m coverage erase")
  86. c.run("python3 -m coverage run --source . -m unittest discover tests 'test_*' -v")
  87. c.run("python3 -m coverage report -m")
  88. c.run("python3 -m coverage html")
  89. @task
  90. def minimum(c):
  91. """Check the minimum required python version for the project."""
  92. c.run("vermin --no-parse-comments .")
  93. @task(name="migrate")
  94. def migrate_requirements(c):
  95. """Copy requirements from the requirements.txt file to pyproject.toml."""
  96. lines = Path("requirements.txt").read_text().split("\n")
  97. current = system.lower().replace("-", "_")
  98. requirements = {current: [], "test": [], "doc": [], "graphical": [], "dev": []}
  99. for line in lines:
  100. if line.startswith("#"):
  101. candidate = line[1:].lower().strip().replace(" ", "_").replace("-", "_")
  102. if candidate in requirements.keys():
  103. current = candidate
  104. continue
  105. if line.strip() == "" or ("=" in line and "#" in line):
  106. continue
  107. requirements[current].append("".join(line.split()))
  108. import vermin
  109. config = vermin.Config()
  110. source_file_paths = list(set(vermin.detect_paths([system, "tests", "docs"], config=config)))
  111. minimums, *_ = vermin.Processor().process(source_file_paths, config, config.processes())
  112. minimum_version = vermin.version_strings(list(filter(lambda ver: ver, minimums)))
  113. Path("pyproject.toml").write_text(
  114. Template(project_template[1:]).render(requirements=requirements, system=system, minimum_version=minimum_version)
  115. )
  116. @task
  117. def release(c, version):
  118. """"""
  119. if version not in ["minor", "major", "patch"]:
  120. print("Version can be either major, minor or patch.")
  121. return
  122. migrate_requirements(c)
  123. import importlib
  124. current_module = importlib.import_module(system)
  125. __version_info__ = current_module.__version_info__
  126. __version__ = current_module.__version__
  127. _major, _minor, _patch = __version_info__
  128. if version == "patch":
  129. _patch = _patch + 1
  130. elif version == "minor":
  131. _minor = _minor + 1
  132. _patch = 0
  133. elif version == "major":
  134. _major = _major + 1
  135. _minor = 0
  136. _patch = 0
  137. c.run(f"git checkout -b release-{_major}.{_minor}.{_patch} {dev_branch}")
  138. c.run(f"sed -i 's/{__version__}/{_major}.{_minor}.{_patch}/g' {system}/__init__.py")
  139. print(f"Update the readme for version {_major}.{_minor}.{_patch}.")
  140. input("Press enter when ready.")
  141. c.run(f"git add -u")
  142. c.run(f'git commit -m "Update changelog version {_major}.{_minor}.{_patch}"')
  143. c.run(f"git push --set-upstream origin release-{_major}.{_minor}.{_patch}")
  144. c.run(f"git checkout {main_branch}")
  145. c.run(f"git merge --no-ff release-{_major}.{_minor}.{_patch}")
  146. c.run(f'git tag -a {_major}.{_minor}.{_patch} -m "Release {_major}.{_minor}.{_patch}"')
  147. c.run(f"git push")
  148. c.run(f"git checkout {dev_branch}")
  149. c.run(f"git merge --no-ff release-{_major}.{_minor}.{_patch}")
  150. c.run(f"git push")
  151. c.run(f"git branch -d release-{_major}.{_minor}.{_patch}")
  152. c.run(f"git push origin --tags")