Skip to content

Commit 8f25789

Browse files
authoredNov 12, 2021
πŸ“š Document pre-commit hook for pyupgrade (#1065)
* ✨ [tools] Add tool for generating dependencies table in User Guide * πŸ‘· [nox] Add session `dependencies-table` * πŸ“š [docs] Update dependency table in User Guide * πŸ“š [README] Add pyupgrade to feature list * πŸ“š [docs] Add pyupgrade to the list of pre-commit hooks * πŸ“š [docs] Add documentation section for pyupgrade to User Guide * πŸ“š [docs] Drop a word
1 parent 9fc1bcf commit 8f25789

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed
 

β€ŽREADME.rst

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ Features
8181
- Command-line interface with Click_
8282
- Static type-checking with mypy_
8383
- Runtime type-checking with Typeguard_
84+
- Automated Python syntax upgrades with pyupgrade_
8485
- Security audit with Bandit_ and Safety_
8586
- Check documentation examples with xdoctest_
8687
- Generate API documentation with autodoc_ and napoleon_
@@ -118,6 +119,7 @@ The template supports Python 3.7, 3.8, 3.9, and 3.10.
118119
.. _napoleon: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html
119120
.. _pre-commit: https://pre-commit.com/
120121
.. _pytest: https://docs.pytest.org/en/latest/
122+
.. _pyupgrade: https://github.com/asottile/pyupgrade
121123
.. _sphinx-click: https://sphinx-click.readthedocs.io/
122124
.. _xdoctest: https://github.com/Erotemic/xdoctest
123125
.. _GitHub Labeler: https://github.com/marketplace/actions/github-labeler

β€Ždocs/guide.rst

+22-5
Original file line numberDiff line numberDiff line change
@@ -730,20 +730,22 @@ See the table below for an overview of the dependencies of generated projects:
730730
click_ Composable command line interface toolkit
731731
coverage__ Code coverage measurement for Python
732732
darglint_ A utility for ensuring Google-style docstrings stay up to date with the source code.
733-
flake8_ The modular source code checker: pep8 pyflakes and co
733+
flake8_ the modular source code checker: pep8 pyflakes and co
734734
flake8-bandit_ Automated security testing with bandit and flake8.
735735
flake8-bugbear_ A plugin for flake8 finding likely bugs and design problems in your program.
736736
flake8-docstrings_ Extension for flake8 which uses pydocstyle to check docstrings
737737
flake8-rst-docstrings_ Python docstring reStructuredText (RST) validator
738738
mypy_ Optional static typing for Python
739739
pep8-naming_ Check PEP-8 naming conventions, plugin for flake8
740-
pre-commit_ A framework for managing and maintaining multi-language pre-commit hooks
740+
pre-commit_ A framework for managing and maintaining multi-language pre-commit hooks.
741741
pre-commit-hooks_ Some out-of-the-box hooks for pre-commit.
742-
pytest_ Simple powerful testing with Python
742+
pygments_ Pygments is a syntax highlighting package written in Python.
743+
pytest_ pytest: simple powerful testing with Python
744+
pyupgrade_ A tool to automatically upgrade syntax for newer versions.
743745
reorder-python-imports_ Tool for reordering python imports
744-
safety_ Checks installed dependencies for known vulnerabilities
746+
safety_ Checks installed dependencies for known vulnerabilities.
745747
sphinx_ Python documentation generator
746-
sphinx-autobuild_ Watch a Sphinx directory and rebuild the documentation when a change is detected
748+
sphinx-autobuild_ Rebuild Sphinx documentation on changes, with live-reload in the browser.
747749
sphinx-click_ Sphinx extension that automatically documents click applications
748750
sphinx-rtd-theme_ Read the Docs theme for Sphinx
749751
typeguard_ Run-time type checker for Python
@@ -1635,6 +1637,7 @@ The |HPC| comes with a pre-commit configuration consisting of the following hook
16351637
`black <Black_>`__ Run the Black_ code formatter
16361638
`flake8 <Flake8_>`__ Run the Flake8_ linter
16371639
`prettier <Prettier_>`__ Run the Prettier_ code formatter
1640+
pyupgrade_ Upgrade syntax to newer versions of Python
16381641
check-added-large-files_ Prevent giant files from being committed
16391642
check-toml_ Validate TOML_ files
16401643
check-yaml_ Validate YAML_ files
@@ -1687,6 +1690,20 @@ and moves them after normal imports.
16871690
Any duplicate imports are removed.
16881691

16891692

1693+
The pyupgrade hook
1694+
------------------
1695+
1696+
pyupgrade_ upgrades your source code
1697+
to newer versions of the Python language and standard library.
1698+
The tool analyzes the `abstract syntax tree`__ of the modules in your project,
1699+
replacing deprecated or legacy usages with modern idioms.
1700+
1701+
The minimum supported Python version is declared in the relevant section of ``.pre-commit-config.yaml``.
1702+
You should change this setting whenever you drop support for an old version of Python.
1703+
1704+
__ https://docs.python.org/3/library/ast.html
1705+
1706+
16901707
Hooks from pre-commit-hooks
16911708
---------------------------
16921709

β€Žnoxfile.py

+7
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,10 @@ def linkcheck(session: Session) -> None:
6868
session.install("-r", "docs/requirements.txt")
6969

7070
session.run("sphinx-build", *args)
71+
72+
73+
@nox.session(name="dependencies-table")
74+
def dependencies_table(session: Session) -> None:
75+
"""Print the dependencies table."""
76+
session.install("tomli")
77+
session.run("python", "tools/dependencies-table.py", external=True)

β€Žtools/dependencies-table.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import re
2+
from pathlib import Path
3+
4+
import tomli
5+
6+
7+
PROJECT = Path("{{cookiecutter.project_name}}")
8+
JINJA_PATTERN = re.compile(r"{%.*%}")
9+
JINJA_PATTERN2 = re.compile(r"{{[^{]*}}")
10+
LINE_FORMAT = " {name:{width}} {description}"
11+
CANONICALIZE_PATTERN = re.compile(r"[-_.]+")
12+
DESCRIPTION_PATTERN = re.compile(r"\. .*")
13+
14+
15+
def canonicalize_name(name: str) -> str:
16+
# From ``packaging.utils.canonicalize_name`` (PEP 503)
17+
return CANONICALIZE_PATTERN.sub("-", name).lower()
18+
19+
20+
def truncate_description(description: str) -> str:
21+
"""Truncate the description to the first sentence."""
22+
return DESCRIPTION_PATTERN.sub(".", description)
23+
24+
25+
def format_dependency(dependency: str) -> str:
26+
"""Format the dependency for the table."""
27+
return "coverage__" if dependency == "coverage" else f"{dependency}_"
28+
29+
30+
def main() -> None:
31+
"""Print restructuredText table of dependencies."""
32+
path = PROJECT / "pyproject.toml"
33+
text = path.read_text()
34+
text = JINJA_PATTERN.sub("", text)
35+
text = JINJA_PATTERN2.sub("x", text)
36+
data = tomli.loads(text)
37+
38+
dependencies = {
39+
canonicalize_name(dependency)
40+
for section in ["dependencies", "dev-dependencies"]
41+
for dependency in data["tool"]["poetry"][section].keys()
42+
if dependency != "python"
43+
}
44+
45+
path = PROJECT / "poetry.lock"
46+
text = path.read_text()
47+
data = tomli.loads(text)
48+
49+
descriptions = {
50+
canonicalize_name(package["name"]): truncate_description(package["description"])
51+
for package in data["package"]
52+
if package["name"] in dependencies
53+
}
54+
55+
table = {
56+
format_dependency(dependency): descriptions[dependency]
57+
for dependency in sorted(dependencies)
58+
}
59+
60+
width = max(len(name) for name in table)
61+
width2 = max(len(description) for description in table.values())
62+
separator = LINE_FORMAT.format(
63+
name="=" * width, width=width, description="=" * width2
64+
)
65+
66+
print(separator)
67+
68+
for name, description in table.items():
69+
line = LINE_FORMAT.format(name=name, width=width, description=description)
70+
71+
print(line)
72+
73+
print(separator)
74+
75+
76+
if __name__ == "__main__":
77+
main()

0 commit comments

Comments
 (0)
Please sign in to comment.