Skip to content

top: Pin black version. #749

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions .github/workflows/code_formatting.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
name: Check code formatting

# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python code formatting with black
on: [push, pull_request]

jobs:
build:
black:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- name: Install packages
run: source tools/ci.sh && ci_code_formatting_setup
- name: Run code formatting
run: source tools/ci.sh && ci_code_formatting_run
- name: Check code formatting
run: git diff --exit-code
- uses: actions/checkout@v4
- run: pip install --user black==23.7.0
Copy link
Contributor

@projectgus projectgus Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I have too much DRY brainworms, but could we add a [project.optional-dependencies] section to pyproject.toml for these versions? (I/we could also do this in a follow-up PR for this & ruff together, if that's easier.)

The main advantage is that we could then tell developers to install the linter tools from there (and Python developers will instinctively go there anyway). This means they will have matching versions in any IDE integrations, pylsp, etc and [hopefully] won't run into the situation of the pre-commit hook re-formatting (or re-linting) code that their IDE had already formatted or linted slightly differently. (This happens to me sometimes, at least!)

(AFAIK the version still needs to be duplicated in two places even then, because pre-commit maintains its own sandboxes and reads those versions from .pre-commit-config.yaml. No way around that, from what I can see.)

- run: black --diff .
2 changes: 1 addition & 1 deletion .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- run: pip install --user ruff
- run: ruff --format=github .
10 changes: 4 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
repos:
- repo: local
- repo: https://github.com/psf/black
rev: 23.7.0
hooks:
- id: codeformat
name: MicroPython codeformat.py for changed files
entry: tools/codeformat.py -v -f
language: python
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.280
rev: v0.1.0
hooks:
- id: ruff
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,7 @@ max-statements = 166

# ble multitests are evaluated with some names pre-defined
"micropython/bluetooth/aioble/multitests/*" = ["F821"]

[tool.black]
line-length = 99
fast = 1
15 changes: 0 additions & 15 deletions tools/ci.sh
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
#!/bin/bash

########################################################################################
# code formatting

function ci_code_formatting_setup {
sudo apt-add-repository --yes --update ppa:pybricks/ppa
sudo apt-get install uncrustify
pip3 install black
uncrustify --version
black --version
}

function ci_code_formatting_run {
tools/codeformat.py -v
}

########################################################################################
# build packages

Expand Down
76 changes: 4 additions & 72 deletions tools/codeformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,87 +25,19 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

# This is based on tools/codeformat.py from the main micropython/micropython
# repository but without support for .c/.h files.
# This is just a wrapper around running black, so that code formatting can be
# invoked in the same way as in the main repo.

import argparse
import glob
import itertools
import os
import re
import subprocess

# Relative to top-level repo dir.
PATHS = [
"**/*.py",
]

EXCLUSIONS = []

# Path to repo top-level dir.
TOP = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))

PY_EXTS = (".py",)


def list_files(paths, exclusions=None, prefix=""):
files = set()
for pattern in paths:
files.update(glob.glob(os.path.join(prefix, pattern), recursive=True))
for pattern in exclusions or []:
files.difference_update(glob.fnmatch.filter(files, os.path.join(prefix, pattern)))
return sorted(files)


def main():
cmd_parser = argparse.ArgumentParser(description="Auto-format Python files.")
cmd_parser.add_argument("-v", action="store_true", help="Enable verbose output")
cmd_parser.add_argument(
"-f",
action="store_true",
help="Filter files provided on the command line against the default list of files to check.",
)
cmd_parser.add_argument("files", nargs="*", help="Run on specific globs")
args = cmd_parser.parse_args()

# Expand the globs passed on the command line, or use the default globs above.
files = []
if args.files:
files = list_files(args.files)
if args.f:
# Filter against the default list of files. This is a little fiddly
# because we need to apply both the inclusion globs given in PATHS
# as well as the EXCLUSIONS, and use absolute paths
files = {os.path.abspath(f) for f in files}
all_files = set(list_files(PATHS, EXCLUSIONS, TOP))
if args.v: # In verbose mode, log any files we're skipping
for f in files - all_files:
print("Not checking: {}".format(f))
files = list(files & all_files)
else:
files = list_files(PATHS, EXCLUSIONS, TOP)

# Extract files matching a specific language.
def lang_files(exts):
for file in files:
if os.path.splitext(file)[1].lower() in exts:
yield file

# Run tool on N files at a time (to avoid making the command line too long).
def batch(cmd, files, N=200):
while True:
file_args = list(itertools.islice(files, N))
if not file_args:
break
subprocess.check_call(cmd + file_args)

# Format Python files with black.
command = ["black", "--fast", "--line-length=99"]
if args.v:
command.append("-v")
else:
command.append("-q")
batch(command, lang_files(PY_EXTS))
command = ["black", "."]
subprocess.check_call(command, cwd=TOP)


if __name__ == "__main__":
Expand Down