Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ“š Document pre-commit hook for pyupgrade #1065

Merged
merged 7 commits into from
Nov 12, 2021
Merged
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Features
- Command-line interface with Click_
- Static type-checking with mypy_
- Runtime type-checking with Typeguard_
- Automated Python syntax upgrades with pyupgrade_
- Security audit with Bandit_ and Safety_
- Check documentation examples with xdoctest_
- Generate API documentation with autodoc_ and napoleon_
Expand Down Expand Up @@ -118,6 +119,7 @@ The template supports Python 3.7, 3.8, 3.9, and 3.10.
.. _napoleon: https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html
.. _pre-commit: https://pre-commit.com/
.. _pytest: https://docs.pytest.org/en/latest/
.. _pyupgrade: https://github.com/asottile/pyupgrade
.. _sphinx-click: https://sphinx-click.readthedocs.io/
.. _xdoctest: https://github.com/Erotemic/xdoctest
.. _GitHub Labeler: https://github.com/marketplace/actions/github-labeler
Expand Down
27 changes: 22 additions & 5 deletions docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -744,20 +744,22 @@ See the table below for an overview of the dependencies of generated projects:
click_ Composable command line interface toolkit
coverage__ Code coverage measurement for Python
darglint_ A utility for ensuring Google-style docstrings stay up to date with the source code.
flake8_ The modular source code checker: pep8 pyflakes and co
flake8_ the modular source code checker: pep8 pyflakes and co
flake8-bandit_ Automated security testing with bandit and flake8.
flake8-bugbear_ A plugin for flake8 finding likely bugs and design problems in your program.
flake8-docstrings_ Extension for flake8 which uses pydocstyle to check docstrings
flake8-rst-docstrings_ Python docstring reStructuredText (RST) validator
mypy_ Optional static typing for Python
pep8-naming_ Check PEP-8 naming conventions, plugin for flake8
pre-commit_ A framework for managing and maintaining multi-language pre-commit hooks
pre-commit_ A framework for managing and maintaining multi-language pre-commit hooks.
pre-commit-hooks_ Some out-of-the-box hooks for pre-commit.
pytest_ Simple powerful testing with Python
pygments_ Pygments is a syntax highlighting package written in Python.
pytest_ pytest: simple powerful testing with Python
pyupgrade_ A tool to automatically upgrade syntax for newer versions.
reorder-python-imports_ Tool for reordering python imports
safety_ Checks installed dependencies for known vulnerabilities
safety_ Checks installed dependencies for known vulnerabilities.
sphinx_ Python documentation generator
sphinx-autobuild_ Watch a Sphinx directory and rebuild the documentation when a change is detected
sphinx-autobuild_ Rebuild Sphinx documentation on changes, with live-reload in the browser.
sphinx-click_ Sphinx extension that automatically documents click applications
sphinx-rtd-theme_ Read the Docs theme for Sphinx
typeguard_ Run-time type checker for Python
Expand Down Expand Up @@ -1651,6 +1653,7 @@ The |HPC| comes with a pre-commit configuration consisting of the following hook
`black <Black_>`__ Run the Black_ code formatter
`flake8 <Flake8_>`__ Run the Flake8_ linter
`prettier <Prettier_>`__ Run the Prettier_ code formatter
pyupgrade_ Upgrade syntax to newer versions of Python
check-added-large-files_ Prevent giant files from being committed
check-toml_ Validate TOML_ files
check-yaml_ Validate YAML_ files
Expand Down Expand Up @@ -1703,6 +1706,20 @@ and moves them after normal imports.
Any duplicate imports are removed.


The pyupgrade hook
------------------

pyupgrade_ upgrades your source code
to newer versions of the Python language and standard library.
The tool analyzes the `abstract syntax tree`__ of the modules in your project,
replacing deprecated or legacy usages with modern idioms.

The minimum supported Python version is declared in the relevant section of ``.pre-commit-config.yaml``.
You should change this setting whenever you drop support for an old version of Python.

__ https://docs.python.org/3/library/ast.html


Hooks from pre-commit-hooks
---------------------------

Expand Down
7 changes: 7 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,10 @@ def linkcheck(session: Session) -> None:
session.install("-r", "docs/requirements.txt")

session.run("sphinx-build", *args)


@nox.session(name="dependencies-table")
def dependencies_table(session: Session) -> None:
"""Print the dependencies table."""
session.install("tomli")
session.run("python", "tools/dependencies-table.py", external=True)
77 changes: 77 additions & 0 deletions tools/dependencies-table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import re
from pathlib import Path

import tomli


PROJECT = Path("{{cookiecutter.project_name}}")
JINJA_PATTERN = re.compile(r"{%.*%}")
JINJA_PATTERN2 = re.compile(r"{{[^{]*}}")
LINE_FORMAT = " {name:{width}} {description}"
CANONICALIZE_PATTERN = re.compile(r"[-_.]+")
DESCRIPTION_PATTERN = re.compile(r"\. .*")


def canonicalize_name(name: str) -> str:
# From ``packaging.utils.canonicalize_name`` (PEP 503)
return CANONICALIZE_PATTERN.sub("-", name).lower()


def truncate_description(description: str) -> str:
"""Truncate the description to the first sentence."""
return DESCRIPTION_PATTERN.sub(".", description)


def format_dependency(dependency: str) -> str:
"""Format the dependency for the table."""
return "coverage__" if dependency == "coverage" else f"{dependency}_"


def main() -> None:
"""Print restructuredText table of dependencies."""
path = PROJECT / "pyproject.toml"
text = path.read_text()
text = JINJA_PATTERN.sub("", text)
text = JINJA_PATTERN2.sub("x", text)
data = tomli.loads(text)

dependencies = {
canonicalize_name(dependency)
for section in ["dependencies", "dev-dependencies"]
for dependency in data["tool"]["poetry"][section].keys()
if dependency != "python"
}

path = PROJECT / "poetry.lock"
text = path.read_text()
data = tomli.loads(text)

descriptions = {
canonicalize_name(package["name"]): truncate_description(package["description"])
for package in data["package"]
if package["name"] in dependencies
}

table = {
format_dependency(dependency): descriptions[dependency]
for dependency in sorted(dependencies)
}

width = max(len(name) for name in table)
width2 = max(len(description) for description in table.values())
separator = LINE_FORMAT.format(
name="=" * width, width=width, description="=" * width2
)

print(separator)

for name, description in table.items():
line = LINE_FORMAT.format(name=name, width=width, description=description)

print(line)

print(separator)


if __name__ == "__main__":
main()