Skip to content

Commit

Permalink
Pin the linters used (ruff, pyright, pylint) to specific versions (te…
Browse files Browse the repository at this point in the history
…ktronix#131)

* ci: Pinned the linters used (ruff, pyright, pylint) to specific versions to remove failures that can occur when a new version is released that introduces a new linting rule or breaks an existing one. Also added a script that can be used to easily update all pinned dependencies in the pyproject.toml and .pre-commit-config.yaml files.

* docs: Update changelog with entry about pinning linters.
  • Loading branch information
nfelt14 authored and qthompso committed Feb 16, 2024
1 parent b9c17dc commit 8b2edf8
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 22 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ repos:
hooks:
- id: commitizen
stages: [commit-msg]
- repo: https://github.com/asottile/blacken-docs
- repo: https://github.com/adamchainz/blacken-docs
rev: 1.16.0
hooks:
- id: blacken-docs
files: \.(rst|md|markdown|tex)$
- repo: https://github.com/lyz-code/yamlfix/
- repo: https://github.com/lyz-code/yamlfix
rev: 1.16.0
hooks:
- id: yamlfix
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ Things to be included in the next release go here.

### Changed

- Switched to ruff's formatter instead of black's formatter for python code
- Updated the version of `python-semantic-release` that is used to avoid needing to store a copy of the previous changelog in the repo
- Switched to ruff's formatter instead of black's formatter for python code.
- Updated the version of `python-semantic-release` that is used to avoid needing to store a copy of the previous changelog in the repo.
- Pinned the linters (ruff, pyright, pylint, docformatter) to specific versions to reduce failures when updates are released that add new rules or break existing rules.

______________________________________________________________________

Expand Down
6 changes: 1 addition & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,7 @@ source .venv/bin/activate
````
```console
python -m poetry self update
python -m poetry update
pre-commit autoupdate
python scripts/update_development_dependencies.py
```
## Pull Request Guidelines
Expand Down
2 changes: 1 addition & 1 deletion docs/troubleshooting/contributions.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ source .venv/bin/activate
.venv\Scripts\activate.bat

# Update installed dependencies
python -m poetry update
python scripts/update_development_dependencies.py

# Re-run original, failing command
```
Expand Down
14 changes: 10 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ zeroconf = ">=0.54.0"
[tool.poetry.group.dev.dependencies]
coverage = {extras = ["toml"], version = ">=7.2.2"}
coverage-conditional-plugin = ">=0.9.0"
docformatter = {extras = ["tomli"], version = ">=1.6.5,<1.7.1"} # upper bound is due to https://github.com/PyCQA/docformatter/issues/174
docformatter = {extras = ["tomli"], version = "==1.7.0"} # can't update due to https://github.com/PyCQA/docformatter/issues/174
flask = ">=2.2.2"
graphviz = ">=0.20.1"
http-server-mock = ">=1.7"
Expand All @@ -107,16 +107,17 @@ myst-parser = ">=0.19.1"
pip = ">=22.0"
poetry = ">=1.5.1"
pre-commit = ">=2.20.0"
pylint = {extras = ["spelling"], version = ">=3.0"}
pyright = ">=1.1.334"
pre-commit-update = ">=0.1.3"
pylint = {extras = ["spelling"], version = "3.0.3"} # Update this by running scripts/update_development_dependencies.py
pyright = "1.1.348" # Update this by running scripts/update_development_dependencies.py
pyroma = ">=4.2"
pytest = ">=7.1.2"
pytest-cov = ">=3.0.0"
pytest-html = ">=4.0"
pytest-order = ">=1.0.1"
pytest-profiling = ">=1.7.0"
python-semantic-release = ">=8.5.1"
ruff = ">=0.1.7"
ruff = "0.1.14" # Update this by running scripts/update_development_dependencies.py
safety = ">=2.1.1"
sphinx-autoapi = ">=2.0.0"
sphinx-copybutton = ">=0.5.1"
Expand All @@ -133,6 +134,7 @@ types-pyyaml = ">=6.0"
types-requests = ">=2.28.8"
urllib3 = ">=1.26.14"
wheel = ">=0.37.1"
yamlfix = ">=1.16.0"

[tool.poetry.scripts]
list-visa-resources = "tm_devices:print_available_visa_devices"
Expand All @@ -141,6 +143,10 @@ list-visa-resources = "tm_devices:print_available_visa_devices"
"Bug Tracker" = "https://github.com/tektronix/tm_devices/issues"
"Changelog" = "https://github.com/tektronix/tm_devices/blob/main/CHANGELOG.md"

[tool.pre-commit-update]
keep = ["docformatter"]
verbose = true

[tool.pylint.basic]
good-names = ["_"]

Expand Down
29 changes: 21 additions & 8 deletions scripts/pypi_latest_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,41 @@ def parse_arguments() -> argparse.Namespace:
return parser.parse_args()


def main() -> None:
def get_latest_version(package_name: str, index: str) -> str:
"""Get the latest version of the provided package.
Args:
package_name: The name of the package to get the latest version of.
index: The index to check for the package, one of (pypi|test.pypi).
Returns:
A string containing the latest version of the package from the given index.
Raises:
SystemExit: Indicates there were no versions for the package.
"""
args = parse_arguments()
package = args.package
index = args.index

# This code mirrors code found in src/tm_devices/helpers/functions.py.
# This code mirrors code found in src/tm_devices/helpers/functions.py,
# in the check_for_update() function.
# If this code is updated, the helper function should be updated too.
url = f"https://{index}.org/pypi/{package}/json"
url = f"https://{index}.org/pypi/{package_name}/json"
try:
response = requests.get(url, timeout=10)
releases = json.loads(response.text)["releases"]
version_list = sorted(releases, key=Version.parse, reverse=True)
latest_version = version_list[0]
except (IndexError, json.decoder.JSONDecodeError) as error:
msg = f"There were no versions found for the {package} package."
msg = f"There were no versions found for the {package_name} package."
raise SystemExit(msg) from error

return latest_version


def main() -> None:
"""Get the latest version of the provided package."""
args = parse_arguments()
package = args.package
index = args.index
latest_version = get_latest_version(package, index)
print(latest_version)


Expand Down
67 changes: 67 additions & 0 deletions scripts/update_development_dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Update the development dependencies.
This script will update the development dependencies that are pinned in the pyproject.toml and .pre-
commit-config.yaml files.
"""
import shlex
import subprocess
import sys
import warnings

from pathlib import Path
from typing import List

from yamlfix import fix_files # pyright: ignore

from pypi_latest_version import get_latest_version

# NOTE: When docformatter is uncommented from this list, be sure to
# remove the 'keep' key from the '[tool.pre-commit-update]' section in ``pyproject.toml``.
DEPENDENCIES_TO_UPDATE = (
# FUTURE # "docformatter[tomli]", # can't update due to https://github.com/PyCQA/docformatter/issues/174
"pylint[spelling]",
"pyright",
"ruff",
)


def _run_cmd_in_subprocess(command: str) -> None:
"""Run the given command in a subprocess.
Args:
command: The command string to send.
"""
command = command.replace("\\", "/")
print(f"\nExecuting command: {command}")
subprocess.check_call(shlex.split(command)) # noqa: S603


def main() -> None:
"""Run the script to update the development dependencies."""
script_location = Path(__file__)
python_executable = sys.executable
latest_dependency_versions: List[str] = []

# Get the latest versions for each of the dependencies to update
for dependency in DEPENDENCIES_TO_UPDATE:
latest_dep_version = get_latest_version(dependency.split("[", maxsplit=1)[0], "pypi")
latest_dependency_versions.append(dependency + f"=={latest_dep_version}")

# Update dependencies in pyproject.toml using poetry
dependencies = " ".join(f'"{x}"' for x in latest_dependency_versions)
_run_cmd_in_subprocess(f"{python_executable} -m poetry add --group=dev {dependencies}")

# Run poetry update
_run_cmd_in_subprocess(f"{python_executable} -m poetry update")

# Update pre-commit config file
_run_cmd_in_subprocess(python_executable.rsplit("python", maxsplit=1)[-0] + "pre-commit-update")

# Fix the formatting of the pre-commit config file
with warnings.catch_warnings():
warnings.simplefilter("ignore", UserWarning)
fix_files([f"{script_location.parent.parent}/.pre-commit-config.yaml"])


if __name__ == "__main__":
main()

0 comments on commit 8b2edf8

Please sign in to comment.