commit 0b01c783a6bb8a7466c04f8c37435b21c1024cdc
parent 72cab7551735d3f2d73af8d1cf596c381467a1e6
Author: Alex Hochheiden <ahochheiden@mozilla.com>
Date: Wed, 7 Jan 2026 00:29:59 +0000
Bug 2006716 - Remove `black` linter r=ahal,linter-reviewers
It will be replaced with `ruff-format` in a subsequent commit.
Differential Revision: https://phabricator.services.mozilla.com/D276898
Diffstat:
11 files changed, 2 insertions(+), 244 deletions(-)
diff --git a/pyproject.toml b/pyproject.toml
@@ -20,7 +20,7 @@ lint.ignore = [
"PLC0206", # dict-index-missing-items
"PLC0415", # `import` should be at the top-level of a file
- # These are handled by black.
+ # These are handled by ruff format.
"E1", "E4", "E5", "W2", "W5",
]
builtins = ["gdb"]
diff --git a/python/sites/lint.txt b/python/sites/lint.txt
@@ -2,7 +2,6 @@ requires-python:>=3.9
# We need sphinx to avoid some rstcheck errors and warnings
pypi:Sphinx==7.1.2
pypi:alabaster==0.7.13
-pypi:black==24.8.0
pypi:codespell==2.4.0
pypi:dataclasses==0.6
pypi:distlib==0.3.7
diff --git a/python/sites/python-test.txt b/python/sites/python-test.txt
@@ -4,7 +4,6 @@ pypi:Flask==2.1.3
# We need sphinx to avoid some rstcheck errors and warnings
pypi:Sphinx==7.1.2
pypi:alabaster==0.7.13
-pypi:black==24.8.0
pypi:codespell==2.4.0
pypi:dataclasses==0.6
pypi:docutils==0.18.1
diff --git a/taskcluster/kinds/source-test/mozlint.yml b/taskcluster/kinds/source-test/mozlint.yml
@@ -398,22 +398,6 @@ mscom-init:
- '**/*.rs'
- 'tools/lint/mscom-init.yml'
-py-black:
- description: black run over the gecko codebase
- treeherder:
- symbol: py(black)
- run:
- mach: lint -v -l black -f treeherder -f json:/builds/worker/mozlint.json .
- when:
- files-changed:
- # The list of extensions should match tools/lint/black.yml
- - '**/*.py'
- - '**/moz.build'
- - '**/*.configure'
- - '**/*.mozbuild'
- - 'pyproject.toml'
- - 'tools/lint/black.yml'
-
py-ruff:
description: Run ruff over the gecko codebase
treeherder:
diff --git a/tools/lint/black.yml b/tools/lint/black.yml
@@ -1,18 +0,0 @@
----
-black:
- description: Reformat python
- exclude:
- - gfx/harfbuzz/src/meson.build
- - '**/*.mako.py'
- - python/mozbuild/mozbuild/test/frontend/data/reader-error-syntax/moz.build
- - testing/mozharness/configs/test/test_malformed.py
- - testing/web-platform/tests
- extensions:
- - build
- - configure
- - mozbuild
- - py
- support-files:
- - 'tools/lint/python/**'
- type: external
- payload: python.black:lint
diff --git a/tools/lint/mach_commands.py b/tools/lint/mach_commands.py
@@ -25,7 +25,7 @@ if os.path.exists(thunderbird_excludes):
GLOBAL_EXCLUDES = ["**/node_modules", "tools/lint/test/files", ".hg", ".git"]
-VALID_FORMATTERS = {"black", "clang-format", "eslint", "rustfmt", "stylelint"}
+VALID_FORMATTERS = {"clang-format", "eslint", "rustfmt", "stylelint"}
VALID_ANDROID_FORMATTERS = {"android-format"}
# Code-review bot must index issues from the whole codebase when pushing
diff --git a/tools/lint/python/black.py b/tools/lint/python/black.py
@@ -1,144 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import os
-import platform
-import re
-import signal
-import subprocess
-import sys
-
-from mozlint import result
-from mozlint.pathutils import expand_exclusions
-
-here = os.path.abspath(os.path.dirname(__file__))
-
-
-def default_bindir():
- # We use sys.prefix to find executables as that gets modified with
- # virtualenv's activate_this.py, whereas sys.executable doesn't.
- if platform.system() == "Windows":
- return os.path.join(sys.prefix, "Scripts")
- else:
- return os.path.join(sys.prefix, "bin")
-
-
-def get_black_version(binary):
- """
- Returns found binary's version
- """
- try:
- output = subprocess.check_output(
- [binary, "--version"],
- stderr=subprocess.STDOUT,
- universal_newlines=True,
- )
- except subprocess.CalledProcessError as e:
- output = e.output
- try:
- # Accept `black.EXE, version ...` on Windows.
- # for old version of black, the output is
- # black, version 21.4b2
- # From black 21.11b1, the output is like
- # black, 21.11b1 (compiled: no)
- return re.match(r"black.*,( version)? (\S+)", output)[2]
- except TypeError as e:
- print(f"Could not parse the version '{output}'")
- print(f"Error: {e}")
-
-
-def parse_issues(config, output, paths, *, log):
- would_reformat = re.compile("^would reformat (.*)$", re.I)
- reformatted = re.compile("^reformatted (.*)$", re.I)
- cannot_reformat = re.compile("^error: cannot format (.*?): (.*)$", re.I)
- results = []
- for l in output.split(b"\n"):
- line = l.decode("utf-8").rstrip("\r\n")
- if line.startswith("All done!") or line.startswith("Oh no!"):
- break
-
- match = would_reformat.match(line)
- if match:
- res = {"path": match.group(1), "level": "error"}
- results.append(result.from_config(config, **res))
- continue
-
- match = reformatted.match(line)
- if match:
- res = {"path": match.group(1), "level": "warning", "message": "reformatted"}
- results.append(result.from_config(config, **res))
- continue
-
- match = cannot_reformat.match(line)
- if match:
- res = {"path": match.group(1), "level": "error", "message": match.group(2)}
- results.append(result.from_config(config, **res))
- continue
-
- log.debug(f"Unhandled line: {line}")
- return results
-
-
-def run_process(config, cmd):
- orig = signal.signal(signal.SIGINT, signal.SIG_IGN)
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- signal.signal(signal.SIGINT, orig)
- try:
- output, _ = proc.communicate()
- proc.wait()
- except KeyboardInterrupt:
- proc.kill()
-
- return output
-
-
-def run_black(config, paths, fix=None, *, log, virtualenv_bin_path):
- fixed = 0
- binary = os.path.join(virtualenv_bin_path or default_bindir(), "black")
-
- log.debug(f"Black version {get_black_version(binary)}")
-
- cmd_args = [binary]
- if not fix:
- cmd_args.append("--check")
-
- if platform.system() == "Windows":
- MAX_PATHS_PER_JOB = (
- 50 # set a max size to prevent command lines that are too long on Windows
- )
- chunked_paths = [
- paths[i : i + MAX_PATHS_PER_JOB]
- for i in range(0, len(paths), MAX_PATHS_PER_JOB)
- ]
- else:
- chunked_paths = [paths]
-
- all_output = []
-
- for paths_chunk in chunked_paths:
- base_command = cmd_args + paths_chunk
- log.debug("Command: {}".format(" ".join(base_command)))
- output = parse_issues(
- config, run_process(config, base_command), paths_chunk, log=log
- )
- all_output.extend(output)
-
- # black returns an issue for fixed files as well
- for eachIssue in output:
- if eachIssue.message == "reformatted":
- fixed += 1
-
- return {"results": all_output, "fixed": fixed}
-
-
-def lint(paths, config, fix=None, **lintargs):
- files = list(expand_exclusions(paths, config, lintargs["root"]))
-
- return run_black(
- config,
- files,
- fix=fix,
- log=lintargs["log"],
- virtualenv_bin_path=lintargs.get("virtualenv_bin_path"),
- )
diff --git a/tools/lint/test/files/black/bad.py b/tools/lint/test/files/black/bad.py
@@ -1,6 +0,0 @@
-# Any copyright is dedicated to the Public Domain.
-# http://creativecommons.org/publicdomain/zero/1.0/
-
-print (
- "test"
- )
diff --git a/tools/lint/test/files/black/invalid.py b/tools/lint/test/files/black/invalid.py
@@ -1,4 +0,0 @@
-# Any copyright is dedicated to the Public Domain.
-# http://creativecommons.org/publicdomain/zero/1.0/
-
-print(
diff --git a/tools/lint/test/python.toml b/tools/lint/test/python.toml
@@ -3,8 +3,6 @@ subsuite = "mozlint"
["test_android_format.py"]
-["test_black.py"]
-
["test_cargo-audit.py"]
# testing it on linux is enough
skip-if = [
diff --git a/tools/lint/test/test_black.py b/tools/lint/test/test_black.py
@@ -1,50 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import mozunit
-
-LINTER = "black"
-fixed = 0
-
-
-def test_lint_fix(lint, create_temp_file):
- contents = """def is_unique(
- s
- ):
- s = list(s
- )
- s.sort()
-
-
- for i in range(len(s) - 1):
- if s[i] == s[i + 1]:
- return 0
- else:
- return 1
-
-
-if __name__ == "__main__":
- print(
- is_unique(input())
- ) """
-
- path = create_temp_file(contents, "bad.py")
- lint([path], fix=True)
- assert fixed == 1
-
-
-def test_lint_black(lint, paths):
- results = lint(paths())
- assert len(results) == 2
-
- assert results[0].level == "error"
- assert results[0].relpath == "bad.py"
-
- assert "EOF" in results[1].message
- assert results[1].level == "error"
- assert results[1].relpath == "invalid.py"
-
-
-if __name__ == "__main__":
- mozunit.main()