chore: import upstream snapshot with attribution
fuzz / fuzz (3.11) (push) Failing after 1s
fuzz / fuzz (3.12) (push) Failing after 1s
build and publish / sdist + pure wheel (push) Failing after 0s
diff-shades / analysis / base / ${{ matrix.mode }} (push) Has been skipped
docs / docs (ubuntu-latest) (push) Failing after 2s
fuzz / fuzz (3.10) (push) Failing after 1s
fuzz / fuzz (3.14) (push) Failing after 0s
lint and format / lint (push) Failing after 1s
diff-shades / configure (push) Failing after 1s
docker / build (linux/amd64) (push) Has been skipped
diff-shades / analysis / target / ${{ matrix.mode }} (push) Has been skipped
fuzz / fuzz (3.13) (push) Failing after 0s
build and publish / generate wheels matrix (push) Failing after 0s
test release tool / test-release-tool (ubuntu-latest, 3.13) (push) Failing after 1s
build and publish / mypyc wheels ${{ matrix.only }} (push) Has been skipped
test / test (ubuntu-latest, 3.10) (push) Failing after 0s
test / test (ubuntu-latest, 3.11) (push) Failing after 1s
test / test (ubuntu-latest, 3.13) (push) Failing after 0s
test / test (ubuntu-latest, pypy3.11-v7.3.22) (push) Failing after 1s
test / test (ubuntu-latest, 3.15) (push) Failing after 1s
test release tool / test-release-tool (ubuntu-latest, 3.15) (push) Failing after 0s
zizmor / zizmor (push) Failing after 0s
test release tool / test-release-tool (ubuntu-latest, 3.12) (push) Failing after 4s
test release tool / test-release-tool (ubuntu-latest, 3.14) (push) Failing after 3s
test / uvloop (ubuntu-latest) (push) Failing after 1s
test / test (ubuntu-latest, 3.14) (push) Failing after 1s
test / test (ubuntu-latest, 3.12.10) (push) Failing after 5s
docker / build (linux/arm64) (push) Has been cancelled
docker / push (push) Has been cancelled
docs / docs (windows-latest) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.14) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.15) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.12) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.13) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.14) (push) Has been cancelled
test release tool / test-release-tool (macOS-latest, 3.15) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.12) (push) Has been cancelled
test release tool / test-release-tool (windows-latest, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.11) (push) Has been cancelled
test / test (macOS-latest, 3.12.10) (push) Has been cancelled
test / test (macOS-latest, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.14) (push) Has been cancelled
test / test (macOS-latest, 3.15) (push) Has been cancelled
test / test (macOS-latest, pypy3.11-v7.3.22) (push) Has been cancelled
test / test (windows-11-arm, 3.11) (push) Has been cancelled
test / test (windows-11-arm, 3.12.10) (push) Has been cancelled
test / test (windows-11-arm, 3.13) (push) Has been cancelled
test / test (macOS-latest, 3.10) (push) Has been cancelled
test / coveralls-finish (push) Has been cancelled
test / uvloop (macOS-latest) (push) Has been cancelled
test / uvloop (windows-11-arm) (push) Has been cancelled
test / uvloop (windows-latest) (push) Has been cancelled
test / test (windows-11-arm, 3.14) (push) Has been cancelled
test / test (windows-11-arm, 3.15) (push) Has been cancelled
test / test (windows-latest, 3.10) (push) Has been cancelled
test / test (windows-latest, 3.11) (push) Has been cancelled
test / test (windows-latest, 3.12.10) (push) Has been cancelled
test / test (windows-latest, 3.13) (push) Has been cancelled
test / test (windows-latest, 3.14) (push) Has been cancelled
test / test (windows-latest, 3.15) (push) Has been cancelled
test / test (windows-latest, pypy3.11-v7.3.22) (push) Has been cancelled
diff-shades / compare / ${{ matrix.mode }} (push) Has been cancelled
fuzz / create-issue (push) Has been cancelled
build and publish / publish-mypyc (push) Has been cancelled
build and publish / publish-hatch (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:07:39 +08:00
commit d0aab9212a
460 changed files with 145411 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
# Treat each other well
Everyone participating in the _Black_ project, and in particular in the issue tracker,
pull requests, and social media activity, is expected to treat other people with respect
and more generally to follow the guidelines articulated in the
[Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/).
At the same time, humor is encouraged. In fact, basic familiarity with Monty Python's
Flying Circus is expected. We are not savages.
And if you _really_ need to slap somebody, do it with a fish while dancing.
+64
View File
@@ -0,0 +1,64 @@
---
name: Bug report
about: Create a report to help us improve Black's quality
title: ""
labels: "T: bug"
assignees: ""
---
<!--
Please make sure that the bug is not already fixed either in newer versions or the
current development version. To confirm this, you have three options:
1. Update Black's version if a newer release exists: `pip install -U black`
2. Install the latest `main` branch directly:
`pip install "black @ git+https://github.com/psf/black.git"`
3. Or run _Black_ from source on your machine:
- create a new virtualenv (make sure it's the same Python version);
- clone this repository;
- run `pip install -e .[d]`;
- run `pip install --group tests`
- make sure it's sane by running `python -m pytest -n auto`; and
- run `black` like you did last time.
-->
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
<!--
Minimal steps to reproduce the behavior with source code and Black's configuration.
-->
For example, take this code:
```python
this = "code"
```
And run it with these arguments:
```sh
$ black file.py --target-version py310
```
The resulting error is:
> cannot format file.py: INTERNAL ERROR: ...
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Environment**
<!-- Please complete the following information: -->
- Black's version: <!-- e.g. [main] -->
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] -->
**Additional context**
<!-- Add any other context about the problem here. -->
+11
View File
@@ -0,0 +1,11 @@
# See also: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
# This is the default and blank issues are useful so let's keep 'em.
blank_issues_enabled: true
contact_links:
- name: Chat on Python Discord
url: https://discord.gg/RtVdv86PrH
about: >-
User support, questions, and other lightweight requests can be handled via the
#black-formatter text channel we have on Python Discord.
+27
View File
@@ -0,0 +1,27 @@
---
name: Documentation
about: Report a problem with or suggest something for the documentation
title: ""
labels: "T: documentation"
assignees: ""
---
**Is this related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is.
e.g. I'm always frustrated when [...] / I wished that [...] -->
**Describe the solution you'd like**
<!-- A clear and concise description of what you want to
happen or see changed. -->
**Describe alternatives you've considered**
<!-- A clear and concise description of any
alternative solutions or features you've considered. -->
**Additional context**
<!-- Add any other context or screenshots about the issue
here. -->
+27
View File
@@ -0,0 +1,27 @@
---
name: Feature request
about: Suggest an idea for this project
title: ""
labels: "T: enhancement"
assignees: ""
---
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is.
e.g. I'm always frustrated when [...] -->
**Describe the solution you'd like**
<!-- A clear and concise description of what you want to
happen. -->
**Describe alternatives you've considered**
<!-- A clear and concise description of any
alternative solutions or features you've considered. -->
**Additional context**
<!-- Add any other context or screenshots about the feature request
here. -->
+38
View File
@@ -0,0 +1,38 @@
---
name: Code style issue
about: Help us improve the Black code style
title: ""
labels: "T: style"
assignees: ""
---
**Describe the style change**
<!-- A clear and concise description of how the style can be
improved. -->
**Examples in the current _Black_ style**
<!-- Think of some short code snippets that show
how the current _Black_ style is not great: -->
```python
def f():
"""This code should be formatted as per the current Black style"""
pass
```
**Desired style**
<!-- How do you think _Black_ should format the above snippets: -->
```python
def f(
):
"""This code can be formatted however you suggest!"""
pass
```
**Additional context**
<!-- Add any other context about the problem here. -->
+42
View File
@@ -0,0 +1,42 @@
<!-- Hello! Thanks for submitting a PR. To help make things go a bit smoother
we would appreciate that you go through this template. -->
### Description
<!-- Good things to put here include: reasoning for the change (please link
any relevant issues!), any noteworthy (or hacky) choices to be aware of,
or what the problem resolved here looked like ... we won't mind a ranty
story :) -->
### Checklist - did you ...
<!-- If any of the following items aren't relevant for your contribution,
please still tick them so we know you've gone through the checklist.
- Please familiarize yourself with Black's stability policy, linked
below. Code style changes are only allowed under the `--preview` flag
until maintainers move them to stable in the next calendar year.
- All user-facing changes should get a changelog entry. If this isn't
user-facing, signal to us that this should get the magical label to
silence the check.
- Tests are required for all bugfixes and new features.
- Documentation changes are necessary for most formatting changes and
other enhancements. -->
- [ ] Implement any code style changes under the `--preview` style, following the stability policy?
- [ ] Add an entry in `CHANGES.md` if necessary?
- [ ] Add / update tests if necessary?
- [ ] Add new / update outdated documentation?
<!-- Just as a reminder, everyone in all psf/black spaces, including PRs, must
follow the PSF Code of Conduct (link below).
Finally, thanks once again for your time and effort. If you have any
feedback regarding your experience contributing here, please let us know!
Helpful links:
- PSF COC: https://www.python.org/psf/conduct/
- Contributing docs: https://black.readthedocs.io/en/latest/contributing/index.html
- Chat on Python Discord: https://discord.gg/RtVdv86PrH
- Stability policy: https://black.readthedocs.io/en/stable/the_black_code_style/index.html -->
+21
View File
@@ -0,0 +1,21 @@
# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
# Workflow files in .github/workflows will be checked
directory: "/"
labels: ["ci: skip news", "C: dependencies", "C: maintenance"]
schedule:
interval: daily
cooldown:
default-days: 7
- package-ecosystem: "pip"
directory: "/"
labels: ["ci: skip news", "C: dependencies"]
schedule:
interval: daily
cooldown:
default-days: 7
+25
View File
@@ -0,0 +1,25 @@
name: changelog
on:
pull_request:
types: [opened, synchronize, labeled, unlabeled, reopened]
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Grep CHANGES.md for PR number
if: >
contains(github.event.pull_request.labels.*.name, 'ci: skip news') != true
run: |
grep -Pz "\((\n\s*)?#${{ github.event.pull_request.number }}(\n\s*)?\)" CHANGES.md || \
(echo "Please add '(#${{ github.event.pull_request.number }})' change line to CHANGES.md (or if appropriate, ask a maintainer to add the 'ci: skip news' label)" && \
exit 1)
+240
View File
@@ -0,0 +1,240 @@
name: diff-shades
on:
push:
branches: [main]
paths:
- src/**
- pyproject.toml
- scripts/diff_shades_gha_helper.py
- .github/workflows/diff_shades.yml
- .github/workflows/diff_shades_comment.yml
pull_request:
paths:
- src/**
- pyproject.toml
- scripts/diff_shades_gha_helper.py
- .github/workflows/diff_shades.yml
- .github/workflows/diff_shades_comment.yml
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
env:
HATCH_BUILD_HOOKS_ENABLE: "1"
# Clang is less picky with the C code it's given than gcc (and may generate faster
# binaries too).
CC: clang-18
permissions: {}
jobs:
configure:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-config.outputs.matrix }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group diff-shades --group diff-shades-comment
- name: Calculate run configuration & metadata
id: set-config
env:
GITHUB_TOKEN: ${{ github.token }}
run: python scripts/diff_shades_gha_helper.py config
analysis-base:
name: analysis / base / ${{ matrix.mode }}
needs: configure
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.configure.outputs.matrix) }}
steps:
- name: Checkout this repository (full clone)
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# The baseline revision could be rather old so a full clone is ideal.
fetch-depth: 0
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group diff-shades
- name: Configure git
run: |
git config user.name "diff-shades-gha"
git config user.email "diff-shades-gha@example.com"
- name: Attempt to use cached baseline analysis
id: baseline-cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ matrix.baseline-analysis }}
key: ${{ matrix.baseline-cache-key }}
- name: Build and install baseline revision
if: steps.baseline-cache.outputs.cache-hit != 'true'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
${{ matrix.baseline-setup-cmd }}
python -m pip install .
- name: Analyze baseline revision
if: steps.baseline-cache.outputs.cache-hit != 'true'
run:
diff-shades analyze ${{ matrix.baseline-analysis }} --work-dir projects-cache/
--force-${{ matrix.style }}-style -v
- name: Upload baseline analysis
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.baseline-analysis }}
path: ${{ matrix.baseline-analysis }}
analysis-target:
name: analysis / target / ${{ matrix.mode }}
needs: configure
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.configure.outputs.matrix) }}
steps:
- name: Checkout this repository (full clone)
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# The baseline revision could be rather old so a full clone is ideal.
fetch-depth: 0
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group diff-shades
- name: Configure git
run: |
git config user.name "diff-shades-gha"
git config user.email "diff-shades-gha@example.com"
- name: Build and install target revision
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
${{ matrix.target-setup-cmd }}
python -m pip install .
# Pull it from previous runs - we're NOT trying to get it from this run
# (but it wouldn't cause problems if we theoretically did)
- name: Attempt to find baseline analysis
id: baseline-cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ matrix.baseline-analysis }}
key: ${{ matrix.baseline-cache-key }}
- name: Analyze target revision (with repeated projects)
if: steps.baseline-cache.outputs.cache-hit == 'true'
run: |
diff-shades analyze ${{ matrix.target-analysis }} --work-dir projects-cache/ \
--force-${{ matrix.style }}-style -v \
--repeat-projects-from ${{ matrix.baseline-analysis }}
- name: Analyze target revision (without repeated projects)
if: steps.baseline-cache.outputs.cache-hit != 'true'
run:
diff-shades analyze ${{ matrix.target-analysis }} --work-dir projects-cache/
--force-${{ matrix.style }}-style -v
- name: Upload target analysis
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.target-analysis }}
path: ${{ matrix.target-analysis }}
- name: Check for failed files for target revision
run: diff-shades show-failed --check --show-log ${{ matrix.target-analysis }}
compare:
name: compare / ${{ matrix.mode }}
needs: ["configure", "analysis-base", "analysis-target"]
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.configure.outputs.matrix) }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
merge-multiple: true
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group diff-shades --group diff-shades-comment
- name: Generate HTML diff report
run: |
diff-shades --dump-html diff.html \
compare --diff ${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
- name: Upload diff report
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.style }}-diff.html
path: diff.html
- name: Generate summary file (PR only)
if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
python scripts/diff_shades_gha_helper.py comment-body \
${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }} \
${{ matrix.style }} ${{ matrix.mode }}
- name: Upload summary file (PR only)
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: .${{ matrix.style }}.pr-comment.md
path: .${{ matrix.style }}.pr-comment.md
include-hidden-files: true
- name: Verify zero changes (PR only)
if: matrix.mode == 'assert-no-changes'
run: |
diff-shades compare --check \
${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }} || \
(echo "Please verify you didn't change the stable code style unintentionally!" \
&& exit 1)
+123
View File
@@ -0,0 +1,123 @@
name: diff-shades comment
on:
workflow_run:
workflows: [diff-shades]
types: [completed]
permissions: {}
jobs:
comment:
runs-on: ubuntu-latest
# We want to comment even if there were failed files or the stable style changed
# That would cause the main workflow to "fail"
if:
github.event.workflow_run.event == 'pull_request' &&
contains(fromJSON('["success", "failure"]'), github.event.workflow_run.conclusion)
permissions:
pull-requests: write # Needed to comment on PR
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
id: artifacts
with:
merge-multiple: true
pattern: ".*.pr-comment.md"
path: ${{ runner.temp }}/diff-shades-artifacts
github-token: ${{ github.token }}
run-id: ${{ github.event.workflow_run.id }}
- name: Validate downloaded comment artifacts
id: comment-artifacts
shell: bash
run: |
set -euo pipefail
artifact_dir="${RUNNER_TEMP}/diff-shades-artifacts"
preview_artifact="${artifact_dir}/.preview.pr-comment.md"
stable_artifact="${artifact_dir}/.stable.pr-comment.md"
if [ ! -d "$artifact_dir" ]; then
echo "::error::Artifact directory does not exist: ${artifact_dir}"
exit 1
fi
while IFS= read -r -d '' entry; do
if [ "$(dirname "$entry")" != "$artifact_dir" ]; then
echo "::error::Unexpected nested artifact path: ${entry}"
exit 1
fi
case "$(basename "$entry")" in
.preview.pr-comment.md|.stable.pr-comment.md) ;;
*)
echo "::error::Unexpected artifact path: ${entry}"
exit 1
;;
esac
if [ ! -f "$entry" ] || [ -L "$entry" ]; then
echo "::error::Artifact must be a regular file: ${entry}"
exit 1
fi
done < <(find "$artifact_dir" -mindepth 1 -print0)
for artifact in "$preview_artifact" "$stable_artifact"; do
if [ ! -f "$artifact" ] || [ -L "$artifact" ]; then
echo "::error::Missing expected artifact file: ${artifact}"
exit 1
fi
done
{
echo "preview=${preview_artifact}"
echo "stable=${stable_artifact}"
} >> "$GITHUB_OUTPUT"
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group diff-shades-comment
- name: Get PR number
id: pr
run:
echo pr=$(gh pr list --search $sha --json number --jq ".[0].number") >>
"$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ github.token }}
sha: ${{ github.event.workflow_run.head_sha }}
- name: Get details from initial workflow run
id: metadata
run: |
python scripts/diff_shades_gha_helper.py comment-details \
"$pr" "$run_id" "$preview_artifact" "$stable_artifact"
env:
GITHUB_TOKEN: ${{ github.token }}
pr: ${{ steps.pr.outputs.pr }}
run_id: ${{ github.event.workflow_run.id }}
preview_artifact: ${{ steps.comment-artifacts.outputs.preview }}
stable_artifact: ${{ steps.comment-artifacts.outputs.stable }}
- name: Try to find pre-existing PR comment
id: find-comment
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
with:
issue-number: ${{ steps.pr.outputs.pr }}
comment-author: "github-actions[bot]"
body-includes: "diff-shades"
- name: Create or update PR comment
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ steps.pr.outputs.pr }}
body: ${{ steps.metadata.outputs.comment-body }}
edit-mode: replace
+123
View File
@@ -0,0 +1,123 @@
name: docker
on:
push:
branches:
- "main"
release:
types: [published]
permissions:
contents: read
env:
REGISTRY: pyfound/black
jobs:
build:
if: github.repository == 'psf/black'
runs-on: ${{ matrix.runner }}
name: build (${{ matrix.platform }})
strategy:
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Login to DockerHub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Prepare
id: prepare
run: echo "platform=${platform//\//-}" >> $GITHUB_OUTPUT
env:
platform: ${{ matrix.platform }}
- name: Build and push
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
platforms: ${{ matrix.platform }}
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
tags: ${{ env.REGISTRY }}
cache-from: type=gha,scope=${{ steps.prepare.outputs.platform }}
cache-to: type=gha,scope=${{ steps.prepare.outputs.platform }},mode=max
- name: Export digest
run: |
mkdir -p digests
touch "digests/${digest#sha256:}"
env:
digest: ${{ steps.build.outputs.digest }}
- name: Upload digest
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: digests-${{ steps.prepare.outputs.platform }}
path: digests/*
if-no-files-found: error
push:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: digests
pattern: digests-*
merge-multiple: true
- name: Login to DockerHub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Create manifest list and push
run: |
TAGS="-t $REGISTRY:latest"
if [[ "$EVENT_NAME" == "release" ]]; then
TAGS="$TAGS -t $REGISTRY:$(git describe --candidates=0 --tags)"
if [[ "$PRERELEASE" == "true" ]]; then
TAGS="$TAGS -t $REGISTRY:latest_prerelease"
else
TAGS="$TAGS -t $REGISTRY:latest_release"
fi
else
TAGS="$TAGS -t $REGISTRY:latest_non_release"
fi
cd digests
docker buildx imagetools create $TAGS $(printf "$REGISTRY@sha256:%s " *)
env:
EVENT_NAME: ${{ github.event_name }}
PRERELEASE: ${{ github.event.release.prerelease }}
- name: Inspect image
run: docker buildx imagetools inspect $REGISTRY:latest
+41
View File
@@ -0,0 +1,41 @@
name: docs
on:
push:
paths: ["docs/**", "src/**", "pyproject.toml", ".github/workflows/docs.yml"]
pull_request:
paths: ["docs/**", "src/**", "pyproject.toml", ".github/workflows/docs.yml"]
permissions:
contents: read
jobs:
docs:
# We want to run on external PRs, but not on our own internal PRs as they'll be run
# by the push to the branch. Without this if check, checks are duplicated since
# internal PRs match both the push and pull_request events.
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
github.repository
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: -e .[d] --group docs
- name: Build documentation
run: sphinx-build -a -b html -W --keep-going docs/ docs/_build
+109
View File
@@ -0,0 +1,109 @@
name: fuzz
on:
push:
branches: main
pull_request:
paths:
- .github/workflows/fuzz.yml
- scripts/fuzz.py
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
jobs:
fuzz:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# TODO: add 3.15; relies on libcst which doesn't support 3.15 yet
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
pip-version: "25.3"
pip-install: --group tox
- name: Run fuzz tests
id: fuzz
run: tox -e fuzz --result-json $python_ver
env:
python_ver: ${{ matrix.python-version }}
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure() && steps.fuzz.outcome == 'failure'
with:
name: ${{ matrix.python-version }}
path: ${{ matrix.python-version }}
create-issue:
runs-on: ubuntu-latest
needs: fuzz
if:
github.repository == 'psf/black' && github.event_name != 'pull_request' &&
failure()
permissions:
issues: write # Needed to create issue
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
merge-multiple: true
path: ./output
- name: Generate issue data
run: |
output=issue-body.html
touch $output
for FILE in ./output/*; do
echo "**Python $(basename $FILE)**" >> $output
echo -e "\`\`\`py" >> $output
echo -e "# stdout:" >> $output
echo -e "$(jq .testenvs.fuzz.test[-1].output $FILE -r)\n" >> $output
echo -e "# stderr:" >> $output
echo -e "$(jq .testenvs.fuzz.test[-1].err $FILE -r)" >> $output
echo -e "\`\`\`\n" >> $output
done
- name: Get existing issue
id: issue
run: |
echo "ISSUE=$( gh issue list \
-A github-actions[bot] -l 'ci: fuzz error' \
--json number -q .[0].number \
-R $REPO )" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
- name: Create new issue
if: steps.issue.outputs.ISSUE == ''
run: >
gh issue create -t "Fuzz test failure" -F issue-body.html -l "ci: fuzz error"
-R $REPO
env:
GITHUB_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
- name: Edit existing issue
if: steps.issue.outputs.ISSUE != ''
run: gh issue edit $ISSUE -F issue-body.html -R $REPO
env:
GITHUB_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
ISSUE: ${{ steps.issue.outputs.ISSUE }}
+46
View File
@@ -0,0 +1,46 @@
name: lint and format
on: [push, pull_request]
permissions: {}
jobs:
lint:
# We want to run on external PRs, but not on our own internal PRs as they'll be run
# by the push to the branch. Without this if check, checks are duplicated since
# internal PRs match both the push and pull_request events.
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
github.repository
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Assert PR target is main
if: github.event_name == 'pull_request' && github.repository == 'psf/black'
run: |
if [ "$GITHUB_BASE_REF" != "main" ]; then
echo "::error::PR targeting '$GITHUB_BASE_REF', please refile targeting 'main'." && exit 1
fi
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: -e . --group tox
- name: Run pre-commit hooks
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
- name: Format ourselves
run: tox -e run_self
- name: Regenerate schema
run: |
tox -e generate_schema
git diff --exit-code
+66
View File
@@ -0,0 +1,66 @@
name: post release
on:
release:
types: published
permissions: {}
jobs:
update-stable:
runs-on: ubuntu-latest
if: github.event.release.prerelease != 'true'
permissions:
contents: write # Needed to push to stable
steps:
- name: Checkout stable branch
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: stable
fetch-depth: 0
persist-credentials: true # needed for `git push` below
- name: Update stable branch to release tag & push
run: |
git reset --hard "${TAG_NAME}"
git push
env:
TAG_NAME: ${{ github.event.release.tag_name }}
new-changelog:
runs-on: ubuntu-latest
if: github.event.release.prerelease != 'true'
permissions:
contents: write # Needed to push to new branch
pull-requests: write # Needed to create PR
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: main
fetch-tags: true
persist-credentials: true # Needed for git-auto-commit-action
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
- run: python scripts/release.py -a
- uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0
with:
commit_message: Add new changelog
branch: ci/new-changelog
create_branch: true
- name: Create PR
run: |
gh pr create \
-t "Add new changelog" -b "" \
-l "ci: skip news" -l "C: maintenance" \
-a $USER
env:
GITHUB_TOKEN: ${{ github.token }}
USER: ${{ github.event.release.author.login }}
+77
View File
@@ -0,0 +1,77 @@
name: publish binaries
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
required: true
type: string
permissions: {}
jobs:
publish:
name: publish (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
pathsep: ";"
asset_name: black_windows.exe
executable_mime: "application/vnd.microsoft.portable-executable"
strip: false
- os: windows-11-arm
pathsep: ";"
asset_name: black_windows-arm.exe
executable_mime: "application/vnd.microsoft.portable-executable"
strip: false
- os: ubuntu-latest
pathsep: ":"
asset_name: black_linux
executable_mime: "application/x-executable"
strip: true
- os: ubuntu-24.04-arm
pathsep: ":"
asset_name: black_linux-arm
executable_mime: "application/x-executable"
strip: true
- os: macos-latest
pathsep: ":"
asset_name: black_macos
executable_mime: "application/x-mach-binary"
strip: false
permissions:
contents: write # Needed to upload to release
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: .[colorama] --group pyinstaller
- name: Build executable with PyInstaller
run:
python -m PyInstaller -F ${{ matrix.strip && '--strip' || '' }} --name ${{
matrix.asset_name }} --add-data 'src/blib2to3${{ matrix.pathsep }}blib2to3'
src/black/__main__.py
- name: Quickly test executable
run: |
./dist/${{ matrix.asset_name }} --version
./dist/${{ matrix.asset_name }} src --verbose
- run: gh release upload "$tag" dist/${{ matrix.asset_name }}
shell: bash
env:
GH_TOKEN: ${{ github.token }}
tag: ${{ inputs.tag || github.event.release.tag_name }}
+160
View File
@@ -0,0 +1,160 @@
name: build and publish
on:
release:
types: published
pull_request:
push:
branches: main
permissions: {}
env:
PROJECT: https://pypi.org/p/black
jobs:
configure:
name: generate wheels matrix
runs-on: ubuntu-latest
outputs:
include: ${{ steps.set-matrix.outputs.include }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group cibw
- name: generate matrix
if: |
github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'ci: build all wheels')
run: |
{
cibuildwheel --print-build-identifiers --platform linux \
| pyp 'json.dumps({"only": x, "os": "ubuntu-latest"})' \
&& cibuildwheel --print-build-identifiers --platform macos \
| pyp 'json.dumps({"only": x, "os": "macos-latest"})' \
&& cibuildwheel --print-build-identifiers --platform windows \
| pyp 'json.dumps({"only": x, "os": "windows-latest"})' \
&& cibuildwheel --print-build-identifiers --platform windows --archs ARM64 \
| pyp 'json.dumps({"only": x, "os": "windows-11-arm"})'
} | pyp 'json.dumps(list(map(json.loads, lines)))' > /tmp/matrix
env:
CIBW_ARCHS_LINUX: x86_64
CIBW_ARCHS_MACOS: x86_64 arm64
CIBW_ARCHS_WINDOWS: AMD64
- name: generate matrix (PR)
if: |
github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'ci: build all wheels')
run: |
{
CIBW_BUILD="cp310-*" cibuildwheel --print-build-identifiers --platform linux | pyp 'json.dumps({"only": x, "os": "ubuntu-latest"})'
CIBW_BUILD="cp314-*" cibuildwheel --print-build-identifiers --platform windows | pyp 'json.dumps({"only": x, "os": "windows-latest"})'
} | pyp 'json.dumps(list(map(json.loads, lines)))' > /tmp/matrix
env:
CIBW_ARCHS_LINUX: x86_64
- id: set-matrix
run: echo "include=$(cat /tmp/matrix)" | tee -a $GITHUB_OUTPUT
mypyc:
name: mypyc wheels ${{ matrix.only }}
needs: configure
runs-on: ${{ matrix.os }}
strategy:
matrix:
include: ${{ fromJson(needs.configure.outputs.include) }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group cibw
- name: Run cibuildwheel
run: cibuildwheel . --only ${{ matrix.only }}
- name: Upload wheels as workflow artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.only }}-mypyc-wheels
path: wheelhouse/
hatch:
name: sdist + pure wheel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: --group hatch
- name: Build wheel and source distributions
run: python -m hatch build
- name: Store the distribution packages
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sdist-and-pure-wheel
path: dist/
publish-mypyc:
if: github.event_name == 'release'
needs: mypyc
runs-on: ubuntu-latest
environment:
name: release
url: ${{ env.PROJECT }}
permissions:
id-token: write # Required for PyPI trusted publishing
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: "*-mypyc-wheels"
path: wheelhouse/
merge-multiple: true
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
packages-dir: wheelhouse/
verbose: true
publish-hatch:
if: github.event_name == 'release'
needs: hatch
runs-on: ubuntu-latest
environment:
name: release
url: ${{ env.PROJECT }}
permissions:
id-token: write # Required for PyPI trusted publishing
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: sdist-and-pure-wheel
path: dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
verbose: true
+59
View File
@@ -0,0 +1,59 @@
name: test release tool
on:
push:
paths:
- .github/workflows/release_tests.yml
- scripts/release.py
- scripts/release_tests.py
pull_request:
paths:
- .github/workflows/release_tests.yml
- scripts/release.py
- scripts/release_tests.py
permissions: {}
jobs:
test-release-tool:
# We want to run on external PRs, but not on our own internal PRs as they'll be run
# by the push to the branch. Without this if check, checks are duplicated since
# internal PRs match both the push and pull_request events.
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
github.repository
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.12", "3.13", "3.14", "3.15"]
os: [macOS-latest, ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# Give us all history, branches and tags
fetch-depth: 0
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
pip-version: "25.3"
pip-install: --group coverage
- name: Print Python Version
run: python --version --version && which python
- name: Print Pip Version
run: pip --version && which pip
- name: Print Git Version
run: git --version && which git
- name: Run unit tests via coverage + print report
run: |
coverage run scripts/release_tests.py
coverage report --show-missing
+124
View File
@@ -0,0 +1,124 @@
name: test
on:
push:
paths:
- .github/workflows/test.yml
- src/**
- tests/**
- tox.ini
- pyproject.toml
pull_request:
paths:
- .github/workflows/test.yml
- src/**
- tests/**
- tox.ini
- pyproject.toml
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
test:
# We want to run on external PRs, but not on our own internal PRs as they'll be run
# by the push to the branch. Without this if check, checks are duplicated since
# internal PRs match both the push and pull_request events.
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
github.repository
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version:
["3.10", "3.11", "3.12.10", "3.13", "3.14", "3.15", "pypy3.11-v7.3.22"]
os: [ubuntu-latest, macOS-latest, windows-latest, windows-11-arm]
exclude:
# setup-python only supports CPython 3.11+ on arm64 windows
- os: windows-11-arm
python-version: "3.10"
- os: windows-11-arm
python-version: "pypy3.11-v7.3.22"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
pip-version: "25.3"
pip-install: --group tox
- name: Unit tests
if: "!startsWith(matrix.python-version, 'pypy')"
run:
tox -e ci-py$(echo ${{ matrix.python-version }} | tr -d '.') -- -v --color=yes
- name: Unit tests (pypy)
if: "startsWith(matrix.python-version, 'pypy')"
run: tox -e ci-pypy3 -- -v --color=yes
- name: Upload coverage to Coveralls
# Upload coverage if we are on the main repository and
# we're running on Linux (this action only supports Linux)
if:
github.repository == 'psf/black' && matrix.os == 'ubuntu-latest' &&
!startsWith(matrix.python-version, 'pypy')
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
flag-name: py${{ matrix.python-version }}-${{ matrix.os }}
debug: true
coveralls-finish:
needs: test
if: github.repository == 'psf/black'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Send finished signal to Coveralls
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
with:
parallel-finished: true
debug: true
uvloop:
if:
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
github.repository
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest, windows-11-arm]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
pip-version: "25.3"
pip-install: -e .[uvloop]
- name: Format ourselves
run: python -m black --check .
+25
View File
@@ -0,0 +1,25 @@
name: zizmor
on:
push:
branches: ["main"]
paths: ["**.yml"]
pull_request:
paths: ["**.yml"]
permissions: {}
jobs:
zizmor:
name: zizmor
runs-on: ubuntu-latest
permissions:
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Run zizmor
uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7
+8
View File
@@ -0,0 +1,8 @@
rules:
dangerous-triggers:
ignore:
# The diff-shades comment workflow intentionally runs after the unprivileged
# diff-shades workflow so it can publish the generated PR comment. It must
# treat artifacts as untrusted and only read validated files from an isolated
# artifact directory.
- diff_shades_comment.yml