From 344d70e611b4e9f1122c8bada0c4a1cb7b0e5bcd Mon Sep 17 00:00:00 2001 From: Nick Crews Date: Fri, 29 Mar 2024 12:50:49 -0800 Subject: [PATCH] dev: swap black to ruff, drop pre-commit now that ruff has formatting capabilities, we can drop one more dependency. Also, the version of black and ruff in the pre-commit config was out of sync from the version pinned in pdm.lock. That is bad. So just drop pre-commit, and run stuff manually, there are only a few commands. But I can't remove it entirely, since pre-commit.ci is enabled on all jazzband repos and I can't turn it off. So there needs to be some content in there, so I added some of the generic builtin ones. I had to adjust a few of the example docstrings so that ruff wouldn't autoformat away the needed leading indentation. I was lazy and just added a bunch of `# noqa: E721` for the `type(match.value) == str` checks that should be isinstance() checks, because when I tried isinstance, some tests failed. The current method isn't that egregious. --- .github/workflows/test.yml | 18 +- .gitignore | 1 - .pre-commit-config.yaml | 31 +- CHANGELOG.md | 4 + README.md | 12 +- docopt/__init__.py | 13 +- examples/arguments_example.py | 3 +- examples/calculator_example.py | 3 +- examples/config_file_example.py | 6 +- examples/counted_example.py | 3 +- examples/git/git.py | 2 +- examples/git/git_add.py | 6 +- examples/git/git_branch.py | 3 +- examples/git/git_checkout.py | 6 +- examples/git/git_clone.py | 6 +- examples/git/git_commit.py | 6 +- examples/git/git_push.py | 6 +- examples/git/git_remote.py | 3 +- examples/interactive_example.py | 0 examples/naval_fate.py | 3 +- examples/odd_even_example.py | 3 +- examples/options_example.py | 3 +- examples/options_shortcut_example.py | 3 +- examples/quick_example.py | 6 +- examples/validation_example.py | 6 +- pdm.lock | 739 ++++++++++++++------------- pyproject.toml | 5 +- 27 files changed, 482 insertions(+), 418 deletions(-) mode change 100644 => 100755 examples/arguments_example.py mode change 100644 => 100755 examples/calculator_example.py mode change 100644 => 100755 examples/config_file_example.py mode change 100644 => 100755 examples/counted_example.py mode change 100644 => 100755 examples/git/git_add.py mode change 100644 => 100755 examples/git/git_branch.py mode change 100644 => 100755 examples/git/git_checkout.py mode change 100644 => 100755 examples/git/git_clone.py mode change 100644 => 100755 examples/git/git_commit.py mode change 100644 => 100755 examples/git/git_push.py mode change 100644 => 100755 examples/git/git_remote.py mode change 100644 => 100755 examples/interactive_example.py mode change 100644 => 100755 examples/naval_fate.py mode change 100644 => 100755 examples/odd_even_example.py mode change 100644 => 100755 examples/options_example.py mode change 100644 => 100755 examples/options_shortcut_example.py mode change 100644 => 100755 examples/quick_example.py mode change 100644 => 100755 examples/validation_example.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0871583..e97f546 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,19 @@ on: - "*" jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up PDM + uses: pdm-project/setup-pdm@v2 + - name: Install dependencies + run: pdm sync -d -G dev + - name: Check formatting + run: pdm run ruff format --check . + - name: Lint + run: pdm run ruff check . + test: runs-on: ubuntu-latest strategy: @@ -25,11 +38,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: | - pdm sync -d -G dev + run: pdm sync -d -G dev - # Linting is taken care of by pre-commit - # in a different github action - name: Run tests run: | pdm run -v pytest --cov-report term-missing --cov-report xml --cov=docopt --mypy diff --git a/.gitignore b/.gitignore index 3bb5fb7..66d6ae8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ .* !.github !.gitignore -!.pre-commit-config.yaml *.py[co] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f722fbd..fd46d13 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,26 @@ repos: - - repo: https://github.com/psf/black - rev: 23.3.0 +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 hooks: - - id: black - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.0.270 - hooks: - - id: ruff + - id: check-added-large-files # prevents giant files from being committed. + - id: check-ast # simply checks whether the files parse as valid python. + - id: check-byte-order-marker # forbids files which have a utf-8 byte-order marker. + - id: check-case-conflict # checks for files that would conflict in case-insensitive filesystems. + - id: check-executables-have-shebangs # ensures that (non-binary) executables have a shebang. + - id: check-json # checks json files for parseable syntax. + - id: check-shebang-scripts-are-executable # ensures that (non-binary) files with a shebang are executable. + - id: pretty-format-json # sets a standard for formatting json files. + - id: check-merge-conflict # checks for files that contain merge conflict strings. + - id: check-symlinks # checks for symlinks which do not point to anything. + - id: check-toml # checks toml files for parseable syntax. + - id: check-vcs-permalinks # ensures that links to vcs websites are permalinks. + - id: check-xml # checks xml files for parseable syntax. + - id: check-yaml # checks yaml files for parseable syntax. + - id: debug-statements # checks for debugger imports and py37+ `breakpoint()` calls in python source. + - id: destroyed-symlinks # detects symlinks which are changed to regular files with a content of a path which that symlink was pointing to. + - id: detect-private-key # detects the presence of private keys. + - id: end-of-file-fixer # ensures that a file is either empty, or ends with one newline. + - id: fix-byte-order-marker # removes utf-8 byte order marker. + - id: mixed-line-ending # replaces or checks mixed line ending. + - id: sort-simple-yaml # sorts simple yaml files which consist only of top-level keys, preserving comments and blocks. + - id: trailing-whitespace # trims trailing whitespace. diff --git a/CHANGELOG.md b/CHANGELOG.md index 4301bd0..13c2115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## UNRELEASED +### Changed + +- Switched from black to ruff for formatting. Dropped use of pre-commit. + ## Version 0.9.0: ### Changed diff --git a/README.md b/README.md index d7c84a9..7777914 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![codecov](https://codecov.io/gh/jazzband/docopt-ng/branch/master/graph/badge.svg)](https://codecov.io/gh/jazzband/docopt-ng) [![image](https://img.shields.io/pypi/v/docopt-ng.svg)](https://pypi.python.org/pypi/docopt-ng) [![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) **docopt-ng** is a fork of the [original docopt](https://github.com/docopt/docopt), now maintained by the [jazzband](https://jazzband.co/) project. Now with maintenance, typehints, and complete test coverage! @@ -322,14 +322,14 @@ To setup your dev environment, fork this repo and clone it locally. We use [pdm](https://pdm.fming.dev/latest/#installation) to manage the project, so install that first. -Then install dev requirements and the package itself as editable, then -install the pre-commit hooks: +Then create a virtual env, install dev requirements and the package itself as editable, +then install the pre-commit hooks: - pdm sync -d -G dev + pdm sync --dev --group dev pdm run pre-commit install Useful testing, linting, and formatting commands: pdm run pytest - pdm run black . - pdm run ruff . + pdm run ruff check . + pdm run ruff format . diff --git a/docopt/__init__.py b/docopt/__init__.py index 237bd70..b13ff73 100644 --- a/docopt/__init__.py +++ b/docopt/__init__.py @@ -21,6 +21,7 @@ * Copyright (c) 2019 itdaniher, itdaniher@gmail.com """ + from __future__ import annotations import re @@ -181,21 +182,21 @@ def match( return False, left, collected left_ = left[:pos] + left[(pos + 1) :] same_name = [a for a in collected if a.name == self.name] - if type(self.value) == int and len(same_name) > 0: + if type(self.value) == int and len(same_name) > 0: # noqa: E721 if isinstance(same_name[0].value, int): same_name[0].value += 1 return True, left_, collected - if type(self.value) == int and not same_name: + if type(self.value) == int and not same_name: # noqa: E721 match.value = 1 return True, left_, collected + [match] - if same_name and type(self.value) == list: - if type(match.value) == str: + if same_name and type(self.value) == list: # noqa: E721 + if type(match.value) == str: # noqa: E721 increment = [match.value] if same_name[0].value is not None and increment is not None: if isinstance(same_name[0].value, type(increment)): same_name[0].value += increment return True, left_, collected - elif not same_name and type(self.value) == list: + elif not same_name and type(self.value) == list: # noqa: E721 if isinstance(match.value, str): match.value = [match.value] return True, left_, collected + [match] @@ -238,7 +239,7 @@ def fix_repeating_arguments(self) -> _BranchPattern: if type(e) is _Argument or type(e) is _Option and e.argcount: if e.value is None: e.value = [] - elif type(e.value) is not list: + elif type(e.value) is not list: # noqa: E721 e.value = cast(str, e.value) e.value = e.value.split() if type(e) is _Command or type(e) is _Option and e.argcount == 0: diff --git a/examples/arguments_example.py b/examples/arguments_example.py old mode 100644 new mode 100755 index 2471726..aff1e68 --- a/examples/arguments_example.py +++ b/examples/arguments_example.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """Usage: arguments_example.py [-vqrh] [FILE] ... arguments_example.py (--left | --right) CORRECTION FILE @@ -15,8 +16,8 @@ -r make report --left use left-hand side --right use right-hand side - """ + from docopt import docopt if __name__ == "__main__": diff --git a/examples/calculator_example.py b/examples/calculator_example.py old mode 100644 new mode 100755 index 9a3574b..fd3ea73 --- a/examples/calculator_example.py +++ b/examples/calculator_example.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """Not a serious example. Usage: @@ -12,8 +13,8 @@ Options: -h, --help - """ + from docopt import docopt if __name__ == "__main__": diff --git a/examples/config_file_example.py b/examples/config_file_example.py old mode 100644 new mode 100755 index 5df30c1..938a420 --- a/examples/config_file_example.py +++ b/examples/config_file_example.py @@ -1,9 +1,11 @@ -"""Usage: +#!/usr/bin/env python3 +""" +Usage: quick_example.py tcp [] [--force] [--timeout=] quick_example.py serial [--baud=] [--timeout=] quick_example.py -h | --help | --version - """ + from docopt import docopt diff --git a/examples/counted_example.py b/examples/counted_example.py old mode 100644 new mode 100755 index b384857..ca46bb2 --- a/examples/counted_example.py +++ b/examples/counted_example.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """Usage: counted_example.py --help counted_example.py -v... counted_example.py go [go] @@ -8,8 +9,8 @@ counted_example.py go go counted_example.py --path ./here --path ./there counted_example.py this.txt that.txt - """ + from docopt import docopt print(docopt(__doc__)) diff --git a/examples/git/git.py b/examples/git/git.py index 1d2ce70..e548c0d 100755 --- a/examples/git/git.py +++ b/examples/git/git.py @@ -21,8 +21,8 @@ remote Manage set of tracked repositories See 'git help ' for more information on a specific command. - """ + from subprocess import call from docopt import docopt diff --git a/examples/git/git_add.py b/examples/git/git_add.py old mode 100644 new mode 100755 index 1e255b9..b578dd1 --- a/examples/git/git_add.py +++ b/examples/git/git_add.py @@ -1,4 +1,6 @@ -"""usage: git add [options] [--] [...] +#!/usr/bin/env python3 +""" +usage: git add [options] [--] [...] -h, --help -n, --dry-run dry run @@ -14,8 +16,8 @@ --refresh don't add, only refresh the index --ignore-errors just skip files which cannot be added because of errors --ignore-missing check if - even missing - files are ignored in dry run - """ + from docopt import docopt if __name__ == "__main__": diff --git a/examples/git/git_branch.py b/examples/git/git_branch.py old mode 100644 new mode 100755 index 86b8e41..db1dbe1 --- a/examples/git/git_branch.py +++ b/examples/git/git_branch.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 """ usage: git branch [options] [-r | -a] [--merged= | --no-merged=] git branch [options] [-l] [-f] [] @@ -24,8 +25,8 @@ -f, --force force creation (when already exists) --no-merged= print only not merged branches --merged= print only merged branches - """ + from docopt import docopt if __name__ == "__main__": diff --git a/examples/git/git_checkout.py b/examples/git/git_checkout.py old mode 100644 new mode 100755 index 9ac09cf..4e6c399 --- a/examples/git/git_checkout.py +++ b/examples/git/git_checkout.py @@ -1,4 +1,6 @@ -"""usage: git checkout [options] +#!/usr/bin/env python3 +""" +usage: git checkout [options] git checkout [options] -- ... -q, --quiet suppress progress reporting @@ -14,8 +16,8 @@ -m, --merge perform a 3-way merge with the new branch --conflict