Compare commits
No commits in common. "main" and "21.8b0" have entirely different histories.
9
.coveragerc
Normal file
9
.coveragerc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[report]
|
||||||
|
omit =
|
||||||
|
src/blib2to3/*
|
||||||
|
tests/data/*
|
||||||
|
*/site-packages/*
|
||||||
|
.tox/*
|
||||||
|
|
||||||
|
[run]
|
||||||
|
relative_files = True
|
5
.flake8
5
.flake8
@ -1,8 +1,7 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
# B905 should be enabled when we drop support for 3.9
|
ignore = E203, E266, E501, W503
|
||||||
ignore = E203, E266, E501, E701, E704, W503, B905, B907
|
|
||||||
# line length is intentionally set to 80 here because black uses Bugbear
|
# line length is intentionally set to 80 here because black uses Bugbear
|
||||||
# See https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#bugbear for more details
|
# See https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#line-length for more details
|
||||||
max-line-length = 80
|
max-line-length = 80
|
||||||
max-complexity = 18
|
max-complexity = 18
|
||||||
select = B,C,E,F,W,T4,B9
|
select = B,C,E,F,W,T4,B9
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
node: $Format:%H$
|
|
||||||
node-date: $Format:%cI$
|
|
||||||
describe-name: $Format:%(describe:tags=true,match=[0-9]*)$
|
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
.git_archival.txt export-subst
|
|
||||||
*.py diff=python
|
|
61
.github/ISSUE_TEMPLATE/bug_report.md
vendored
61
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -6,61 +6,42 @@ labels: "T: bug"
|
|||||||
assignees: ""
|
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. Use the online formatter at <https://black.vercel.app/?version=main>, which will use
|
|
||||||
the latest main branch. Note that the online formatter currently runs on
|
|
||||||
an older version of Python and may not support newer syntax, such as the
|
|
||||||
extended f-string syntax added in Python 3.12.
|
|
||||||
3. Or run _Black_ 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 -r test_requirements.txt`
|
|
||||||
- make sure it's sane by running `python -m pytest`; and
|
|
||||||
- run `black` like you did last time.
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
|
|
||||||
<!-- A clear and concise description of what the bug is. -->
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
|
|
||||||
<!--
|
<!-- Steps to reproduce the behavior:
|
||||||
Minimal steps to reproduce the behavior with source code and Black's configuration.
|
|
||||||
-->
|
|
||||||
|
|
||||||
For example, take this code:
|
For example:
|
||||||
|
1. Take this file '...'
|
||||||
```python
|
1. Run _Black_ on it with these arguments '...'
|
||||||
this = "code"
|
1. See error -->
|
||||||
```
|
|
||||||
|
|
||||||
And run it with these arguments:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ black file.py --target-version py39
|
|
||||||
```
|
|
||||||
|
|
||||||
The resulting error is:
|
|
||||||
|
|
||||||
> cannot format file.py: INTERNAL ERROR: ...
|
|
||||||
|
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
|
|
||||||
<!-- A clear and concise description of what you expected to happen. -->
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
|
||||||
**Environment**
|
**Environment (please complete the following information):**
|
||||||
|
|
||||||
<!-- Please complete the following information: -->
|
- Version: <!-- e.g. [main] -->
|
||||||
|
|
||||||
- Black's version: <!-- e.g. [main] -->
|
|
||||||
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] -->
|
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] -->
|
||||||
|
|
||||||
|
**Does this bug also happen on main?**
|
||||||
|
|
||||||
|
<!-- To answer this, you have two options:
|
||||||
|
|
||||||
|
1. Use the online formatter at <https://black.vercel.app/?version=main>, which will use
|
||||||
|
the latest main branch.
|
||||||
|
1. Or run _Black_ on your machine:
|
||||||
|
- create a new virtualenv (make sure it's the same Python version);
|
||||||
|
- clone this repository;
|
||||||
|
- run `pip install -e .[d,python2]`;
|
||||||
|
- run `pip install -r test_requirements.txt`
|
||||||
|
- make sure it's sane by running `python -m pytest`; and
|
||||||
|
- run `black` like you did last time. -->
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
|
||||||
<!-- Add any other context about the problem here. -->
|
<!-- Add any other context about the problem here. -->
|
||||||
|
6
.github/ISSUE_TEMPLATE/style_issue.md
vendored
6
.github/ISSUE_TEMPLATE/style_issue.md
vendored
@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
name: Code style issue
|
name: Style issue
|
||||||
about: Help us improve the Black code style
|
about: Help us improve the Black style
|
||||||
title: ""
|
title: ""
|
||||||
labels: "T: style"
|
labels: "T: design"
|
||||||
assignees: ""
|
assignees: ""
|
||||||
---
|
---
|
||||||
|
|
||||||
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -18,7 +18,7 @@
|
|||||||
Tests are required for bugfixes and new features. Documentation changes
|
Tests are required for bugfixes and new features. Documentation changes
|
||||||
are necessary for formatting and most enhancement changes. -->
|
are necessary for formatting and most enhancement changes. -->
|
||||||
|
|
||||||
- [ ] Add an entry in `CHANGES.md` if necessary?
|
- [] Add a CHANGELOG entry if necessary?
|
||||||
- [] Add / update tests if necessary?
|
- [] Add / update tests if necessary?
|
||||||
- [] Add new / update outdated documentation?
|
- [] Add new / update outdated documentation?
|
||||||
|
|
||||||
|
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@ -1,16 +0,0 @@
|
|||||||
# 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: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
labels: ["skip news", "C: dependencies"]
|
|
||||||
|
|
||||||
- package-ecosystem: "pip"
|
|
||||||
directory: "docs/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
labels: ["skip news", "C: dependencies", "T: documentation"]
|
|
7
.github/workflows/changelog.yml
vendored
7
.github/workflows/changelog.yml
vendored
@ -4,9 +4,6 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, synchronize, labeled, unlabeled, reopened]
|
types: [opened, synchronize, labeled, unlabeled, reopened]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Changelog Entry Check
|
name: Changelog Entry Check
|
||||||
@ -14,11 +11,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Grep CHANGES.md for PR number
|
- name: Grep CHANGES.md for PR number
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'skip news') != true
|
if: contains(github.event.pull_request.labels.*.name, 'skip news') != true
|
||||||
run: |
|
run: |
|
||||||
grep -Pz "\((\n\s*)?#${{ github.event.pull_request.number }}(\n\s*)?\)" CHANGES.md || \
|
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 'skip news' label)" && \
|
(echo "Please add '(#${{ github.event.pull_request.number }})' change line to CHANGES.md" && \
|
||||||
exit 1)
|
exit 1)
|
||||||
|
155
.github/workflows/diff_shades.yml
vendored
155
.github/workflows/diff_shades.yml
vendored
@ -1,155 +0,0 @@
|
|||||||
name: diff-shades
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths: ["src/**", "pyproject.toml", ".github/workflows/*"]
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
paths: ["src/**", "pyproject.toml", ".github/workflows/*"]
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
configure:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
matrix: ${{ steps.set-config.outputs.matrix }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- name: Install diff-shades and support dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install 'click>=8.1.7' packaging urllib3
|
|
||||||
python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip
|
|
||||||
|
|
||||||
- name: Calculate run configuration & metadata
|
|
||||||
id: set-config
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
run: >
|
|
||||||
python scripts/diff_shades_gha_helper.py config ${{ github.event_name }}
|
|
||||||
${{ matrix.mode }}
|
|
||||||
|
|
||||||
analysis:
|
|
||||||
name: analysis / ${{ matrix.mode }}
|
|
||||||
needs: configure
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
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
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include: ${{ fromJson(needs.configure.outputs.matrix) }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout this repository (full clone)
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# The baseline revision could be rather old so a full clone is ideal.
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
|
|
||||||
- name: Install diff-shades and support dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip
|
|
||||||
python -m pip install 'click>=8.1.7' packaging urllib3
|
|
||||||
# After checking out old revisions, this might not exist so we'll use a copy.
|
|
||||||
cat scripts/diff_shades_gha_helper.py > helper.py
|
|
||||||
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@v4
|
|
||||||
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 -v --work-dir projects-cache/
|
|
||||||
${{ matrix.baseline-analysis }} ${{ matrix.force-flag }}
|
|
||||||
|
|
||||||
- name: Build and install target revision
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
run: >
|
|
||||||
${{ matrix.target-setup-cmd }}
|
|
||||||
&& python -m pip install .
|
|
||||||
|
|
||||||
- name: Analyze target revision
|
|
||||||
run: >
|
|
||||||
diff-shades analyze -v --work-dir projects-cache/
|
|
||||||
${{ matrix.target-analysis }} --repeat-projects-from
|
|
||||||
${{ matrix.baseline-analysis }} ${{ matrix.force-flag }}
|
|
||||||
|
|
||||||
- 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@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.mode }}-diff.html
|
|
||||||
path: diff.html
|
|
||||||
|
|
||||||
- name: Upload baseline analysis
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.baseline-analysis }}
|
|
||||||
path: ${{ matrix.baseline-analysis }}
|
|
||||||
|
|
||||||
- name: Upload target analysis
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.target-analysis }}
|
|
||||||
path: ${{ matrix.target-analysis }}
|
|
||||||
|
|
||||||
- name: Generate summary file (PR only)
|
|
||||||
if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
|
|
||||||
run: >
|
|
||||||
python helper.py comment-body ${{ matrix.baseline-analysis }}
|
|
||||||
${{ matrix.target-analysis }} ${{ matrix.baseline-sha }}
|
|
||||||
${{ matrix.target-sha }} ${{ github.event.pull_request.number }}
|
|
||||||
|
|
||||||
- name: Upload summary file (PR only)
|
|
||||||
if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: .pr-comment.json
|
|
||||||
path: .pr-comment.json
|
|
||||||
|
|
||||||
- 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)
|
|
||||||
|
|
||||||
- name: Check for failed files for target revision
|
|
||||||
# Even if the previous step failed, we should still check for failed files.
|
|
||||||
if: always()
|
|
||||||
run: >
|
|
||||||
diff-shades show-failed --check --show-log ${{ matrix.target-analysis }}
|
|
49
.github/workflows/diff_shades_comment.yml
vendored
49
.github/workflows/diff_shades_comment.yml
vendored
@ -1,49 +0,0 @@
|
|||||||
name: diff-shades-comment
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_run:
|
|
||||||
workflows: [diff-shades]
|
|
||||||
types: [completed]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
comment:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "*"
|
|
||||||
|
|
||||||
- name: Install support dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install pip --upgrade
|
|
||||||
python -m pip install click packaging urllib3
|
|
||||||
|
|
||||||
- name: Get details from initial workflow run
|
|
||||||
id: metadata
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
run: >
|
|
||||||
python scripts/diff_shades_gha_helper.py comment-details
|
|
||||||
${{github.event.workflow_run.id }}
|
|
||||||
|
|
||||||
- name: Try to find pre-existing PR comment
|
|
||||||
if: steps.metadata.outputs.needs-comment == 'true'
|
|
||||||
id: find-comment
|
|
||||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e
|
|
||||||
with:
|
|
||||||
issue-number: ${{ steps.metadata.outputs.pr-number }}
|
|
||||||
comment-author: "github-actions[bot]"
|
|
||||||
body-includes: "diff-shades"
|
|
||||||
|
|
||||||
- name: Create or update PR comment
|
|
||||||
if: steps.metadata.outputs.needs-comment == 'true'
|
|
||||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
|
|
||||||
with:
|
|
||||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
|
||||||
issue-number: ${{ steps.metadata.outputs.pr-number }}
|
|
||||||
body: ${{ steps.metadata.outputs.comment-body }}
|
|
||||||
edit-mode: replace
|
|
19
.github/workflows/doc.yml
vendored
19
.github/workflows/doc.yml
vendored
@ -1,10 +1,7 @@
|
|||||||
name: Documentation
|
name: Documentation Build
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
@ -21,20 +18,16 @@ jobs:
|
|||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up latest Python
|
- name: Set up latest Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v2
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
allow-prereleases: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install uv
|
python -m pip install --upgrade pip setuptools wheel
|
||||||
python -m uv venv
|
python -m pip install -e ".[d]"
|
||||||
python -m uv pip install -e ".[d]"
|
python -m pip install -r "docs/requirements.txt"
|
||||||
python -m uv pip install -r "docs/requirements.txt"
|
|
||||||
|
|
||||||
- name: Build documentation
|
- name: Build documentation
|
||||||
run: sphinx-build -a -b html -W --keep-going docs/ docs/_build
|
run: sphinx-build -a -b html -W --keep-going docs/ docs/_build
|
||||||
|
32
.github/workflows/docker.yml
vendored
32
.github/workflows/docker.yml
vendored
@ -5,10 +5,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: created
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
@ -16,16 +13,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
@ -36,7 +33,7 @@ jobs:
|
|||||||
latest_non_release)" >> $GITHUB_ENV
|
latest_non_release)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
@ -44,26 +41,13 @@ jobs:
|
|||||||
tags: pyfound/black:latest,pyfound/black:${{ env.GIT_TAG }}
|
tags: pyfound/black:latest,pyfound/black:${{ env.GIT_TAG }}
|
||||||
|
|
||||||
- name: Build and push latest_release tag
|
- name: Build and push latest_release tag
|
||||||
if:
|
if: ${{ github.event_name == 'release' && github.event.action == 'created' }}
|
||||||
${{ github.event_name == 'release' && github.event.action == 'published' &&
|
uses: docker/build-push-action@v2
|
||||||
!github.event.release.prerelease }}
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: pyfound/black:latest_release
|
tags: pyfound/black:latest_release
|
||||||
|
|
||||||
- name: Build and push latest_prerelease tag
|
|
||||||
if:
|
|
||||||
${{ github.event_name == 'release' && github.event.action == 'published' &&
|
|
||||||
github.event.release.prerelease }}
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: pyfound/black:latest_prerelease
|
|
||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
14
.github/workflows/fuzz.yml
vendored
14
.github/workflows/fuzz.yml
vendored
@ -2,13 +2,6 @@ name: Fuzz
|
|||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
@ -22,16 +15,15 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12.4", "3.13"]
|
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10-dev"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
allow-prereleases: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
34
.github/workflows/lint.yml
vendored
34
.github/workflows/lint.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Lint + format ourselves
|
name: Lint
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@ -14,35 +14,15 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Assert PR target is main
|
- name: Set up Python
|
||||||
if: github.event_name == 'pull_request' && github.repository == 'psf/black'
|
uses: actions/setup-python@v2
|
||||||
run: |
|
|
||||||
if [ "$GITHUB_BASE_REF" != "main" ]; then
|
|
||||||
echo "::error::PR targeting '$GITHUB_BASE_REF', please refile targeting 'main'." && exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Set up latest Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
allow-prereleases: true
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install -e '.'
|
python -m pip install -e '.[d]'
|
||||||
python -m pip install tox
|
|
||||||
|
|
||||||
- name: Run pre-commit hooks
|
- name: Lint
|
||||||
uses: pre-commit/action@v3.0.1
|
uses: pre-commit/action@v2.0.2
|
||||||
|
|
||||||
- name: Format ourselves
|
|
||||||
run: |
|
|
||||||
tox -e run_self
|
|
||||||
|
|
||||||
- name: Regenerate schema
|
|
||||||
run: |
|
|
||||||
tox -e generate_schema
|
|
||||||
git diff --exit-code
|
|
||||||
|
47
.github/workflows/primer.yml
vendored
Normal file
47
.github/workflows/primer.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: Primer
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- "docs/**"
|
||||||
|
- "*.md"
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- "docs/**"
|
||||||
|
- "*.md"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# 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.6", "3.7", "3.8", "3.9", "3.10-dev"]
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[d,jupyter]"
|
||||||
|
|
||||||
|
- name: Primer run
|
||||||
|
env:
|
||||||
|
pythonioencoding: utf-8
|
||||||
|
run: |
|
||||||
|
black-primer
|
129
.github/workflows/pypi_upload.yml
vendored
129
.github/workflows/pypi_upload.yml
vendored
@ -1,130 +1,31 @@
|
|||||||
name: Build and publish
|
name: pypi_upload
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: created
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
build:
|
||||||
name: sdist + pure wheel
|
name: PyPI Upload
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'release'
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up latest Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v2
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
allow-prereleases: true
|
|
||||||
|
|
||||||
- name: Install latest pip, build, twine
|
- name: Install latest pip, setuptools, twine + wheel
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade --disable-pip-version-check pip
|
python -m pip install --upgrade pip setuptools twine wheel
|
||||||
python -m pip install --upgrade build twine
|
|
||||||
|
|
||||||
- name: Build wheel and source distributions
|
- name: Build wheels
|
||||||
run: python -m build
|
run: |
|
||||||
|
python setup.py bdist_wheel
|
||||||
|
python setup.py sdist
|
||||||
|
|
||||||
- if: github.event_name == 'release'
|
- name: Upload to PyPI via Twine
|
||||||
name: Upload to PyPI via Twine
|
|
||||||
env:
|
env:
|
||||||
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
||||||
run: twine upload --verbose -u '__token__' dist/*
|
|
||||||
|
|
||||||
generate_wheels_matrix:
|
|
||||||
name: generate wheels matrix
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
include: ${{ steps.set-matrix.outputs.include }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# Keep cibuildwheel version in sync with below
|
|
||||||
- name: Install cibuildwheel and pypyp
|
|
||||||
run: |
|
run: |
|
||||||
pipx install cibuildwheel==2.22.0
|
twine upload --verbose -u '__token__' dist/*
|
||||||
pipx install pypyp==1.3.0
|
|
||||||
- name: generate matrix
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
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"})'
|
|
||||||
} | 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'
|
|
||||||
run: |
|
|
||||||
{
|
|
||||||
cibuildwheel --print-build-identifiers --platform linux \
|
|
||||||
| pyp 'json.dumps({"only": x, "os": "ubuntu-latest"})'
|
|
||||||
} | pyp 'json.dumps(list(map(json.loads, lines)))' > /tmp/matrix
|
|
||||||
env:
|
|
||||||
CIBW_BUILD: "cp39-* cp313-*"
|
|
||||||
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: generate_wheels_matrix
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include: ${{ fromJson(needs.generate_wheels_matrix.outputs.include) }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
# Keep cibuildwheel version in sync with above
|
|
||||||
- uses: pypa/cibuildwheel@v2.23.3
|
|
||||||
with:
|
|
||||||
only: ${{ matrix.only }}
|
|
||||||
|
|
||||||
- name: Upload wheels as workflow artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.only }}-mypyc-wheels
|
|
||||||
path: ./wheelhouse/*.whl
|
|
||||||
|
|
||||||
- if: github.event_name == 'release'
|
|
||||||
name: Upload wheels to PyPI via Twine
|
|
||||||
env:
|
|
||||||
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
|
||||||
run: pipx run twine upload --verbose -u '__token__' wheelhouse/*.whl
|
|
||||||
|
|
||||||
update-stable-branch:
|
|
||||||
name: Update stable branch
|
|
||||||
needs: [main, mypyc]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout stable branch
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: stable
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- if: github.event_name == 'release'
|
|
||||||
name: Update stable branch to release tag & push
|
|
||||||
run: |
|
|
||||||
git reset --hard ${{ github.event.release.tag_name }}
|
|
||||||
git push
|
|
||||||
|
56
.github/workflows/release_tests.yml
vendored
56
.github/workflows/release_tests.yml
vendored
@ -1,56 +0,0 @@
|
|||||||
name: Release tool CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- .github/workflows/release_tests.yml
|
|
||||||
- release.py
|
|
||||||
- release_tests.py
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/workflows/release_tests.yml
|
|
||||||
- release.py
|
|
||||||
- release_tests.py
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
# 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
|
|
||||||
|
|
||||||
name: Running python ${{ matrix.python-version }} on ${{matrix.os}}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: ["3.13"]
|
|
||||||
os: [macOS-latest, ubuntu-latest, windows-latest]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
# Give us all history, branches and tags
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
allow-prereleases: true
|
|
||||||
|
|
||||||
- name: Print Python Version
|
|
||||||
run: python --version --version && which python
|
|
||||||
|
|
||||||
- name: Print Git Version
|
|
||||||
run: git --version && which git
|
|
||||||
|
|
||||||
- name: Update pip, setuptools + wheels
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip setuptools wheel
|
|
||||||
|
|
||||||
- name: Run unit tests via coverage + print report
|
|
||||||
run: |
|
|
||||||
python -m pip install coverage
|
|
||||||
coverage run scripts/release_tests.py
|
|
||||||
coverage report --show-missing
|
|
78
.github/workflows/test.yml
vendored
78
.github/workflows/test.yml
vendored
@ -11,15 +11,8 @@ on:
|
|||||||
- "docs/**"
|
- "docs/**"
|
||||||
- "*.md"
|
- "*.md"
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
build:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# 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
|
# by the push to the branch. Without this if check, checks are duplicated since
|
||||||
# internal PRs match both the push and pull_request events.
|
# internal PRs match both the push and pull_request events.
|
||||||
@ -31,39 +24,35 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12.4", "3.13", "pypy-3.9"]
|
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10-dev"]
|
||||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
allow-prereleases: true
|
|
||||||
|
|
||||||
- name: Install tox
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install --upgrade tox
|
python -m pip install --upgrade tox
|
||||||
|
|
||||||
- name: Unit tests
|
- name: Unit tests
|
||||||
if: "!startsWith(matrix.python-version, 'pypy')"
|
run: |
|
||||||
run:
|
tox -e ci-py -- -v --color=yes
|
||||||
tox -e ci-py$(echo ${{ matrix.python-version }} | tr -d '.') -- -v --color=yes
|
|
||||||
|
|
||||||
- name: Unit tests (pypy)
|
- name: Publish coverage to Coveralls
|
||||||
if: "startsWith(matrix.python-version, 'pypy')"
|
# If pushed / is a pull request against main repo AND
|
||||||
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)
|
# we're running on Linux (this action only supports Linux)
|
||||||
if:
|
if:
|
||||||
github.repository == 'psf/black' && matrix.os == 'ubuntu-latest' &&
|
((github.event_name == 'push' && github.repository == 'psf/black') ||
|
||||||
!startsWith(matrix.python-version, 'pypy')
|
github.event.pull_request.base.repo.full_name == 'psf/black') && matrix.os ==
|
||||||
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
|
'ubuntu-latest'
|
||||||
|
|
||||||
|
uses: AndreMiras/coveralls-python-action@v20201129
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
parallel: true
|
parallel: true
|
||||||
@ -71,40 +60,17 @@ jobs:
|
|||||||
debug: true
|
debug: true
|
||||||
|
|
||||||
coveralls-finish:
|
coveralls-finish:
|
||||||
needs: main
|
needs: build
|
||||||
if: github.repository == 'psf/black'
|
# If pushed / is a pull request against main repo
|
||||||
|
if:
|
||||||
|
(github.event_name == 'push' && github.repository == 'psf/black') ||
|
||||||
|
github.event.pull_request.base.repo.full_name == 'psf/black'
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- name: Send finished signal to Coveralls
|
- name: Coveralls finished
|
||||||
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
|
uses: AndreMiras/coveralls-python-action@v20201129
|
||||||
with:
|
with:
|
||||||
parallel-finished: true
|
parallel-finished: true
|
||||||
debug: 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]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up latest Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.12.4"
|
|
||||||
|
|
||||||
- name: Install black with uvloop
|
|
||||||
run: |
|
|
||||||
python -m pip install pip --upgrade --disable-pip-version-check
|
|
||||||
python -m pip install -e ".[uvloop]"
|
|
||||||
|
|
||||||
- name: Format ourselves
|
|
||||||
run: python -m black --check src/ tests/
|
|
||||||
|
31
.github/workflows/upload_binary.yml
vendored
31
.github/workflows/upload_binary.yml
vendored
@ -1,25 +1,22 @@
|
|||||||
name: Publish executables
|
name: Upload self-contained binaries
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write # actions/upload-release-asset needs this.
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-2019, ubuntu-22.04, macos-latest]
|
os: [windows-2019, ubuntu-20.04, macos-latest]
|
||||||
include:
|
include:
|
||||||
- os: windows-2019
|
- os: windows-2019
|
||||||
pathsep: ";"
|
pathsep: ";"
|
||||||
asset_name: black_windows.exe
|
asset_name: black_windows.exe
|
||||||
executable_mime: "application/vnd.microsoft.portable-executable"
|
executable_mime: "application/vnd.microsoft.portable-executable"
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-20.04
|
||||||
pathsep: ":"
|
pathsep: ":"
|
||||||
asset_name: black_linux
|
asset_name: black_linux
|
||||||
executable_mime: "application/x-executable"
|
executable_mime: "application/x-executable"
|
||||||
@ -29,28 +26,22 @@ jobs:
|
|||||||
executable_mime: "application/x-mach-binary"
|
executable_mime: "application/x-mach-binary"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Set up latest Python
|
- name: Set up latest Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: "3.12.4"
|
python-version: "*"
|
||||||
|
|
||||||
- name: Install Black and PyInstaller
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip wheel
|
python -m pip install --upgrade pip wheel setuptools
|
||||||
python -m pip install .[colorama]
|
python -m pip install .
|
||||||
python -m pip install pyinstaller
|
python -m pip install pyinstaller
|
||||||
|
|
||||||
- name: Build executable with PyInstaller
|
- name: Build binary
|
||||||
run: >
|
|
||||||
python -m PyInstaller -F --name ${{ matrix.asset_name }} --add-data
|
|
||||||
'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
|
|
||||||
|
|
||||||
- name: Quickly test executable
|
|
||||||
run: |
|
run: |
|
||||||
./dist/${{ matrix.asset_name }} --version
|
python -m PyInstaller -F --name ${{ matrix.asset_name }} --add-data 'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
|
||||||
./dist/${{ matrix.asset_name }} src --verbose
|
|
||||||
|
|
||||||
- name: Upload binary as release asset
|
- name: Upload binary as release asset
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
|
45
.github/workflows/uvloop_test.yml
vendored
Normal file
45
.github/workflows/uvloop_test.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
name: test uvloop
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- "docs/**"
|
||||||
|
- "*.md"
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- "docs/**"
|
||||||
|
- "*.md"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# 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:
|
||||||
|
os: [ubuntu-latest, macOS-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
|
||||||
|
- name: Install latest pip
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
|
||||||
|
- name: Test uvloop Extra Install
|
||||||
|
run: |
|
||||||
|
python -m pip install -e ".[uvloop]"
|
||||||
|
|
||||||
|
- name: Primer uvloop run
|
||||||
|
run: |
|
||||||
|
black-primer
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -4,25 +4,18 @@
|
|||||||
_build
|
_build
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode
|
.vscode
|
||||||
.python-version
|
|
||||||
docs/_static/pypi.svg
|
docs/_static/pypi.svg
|
||||||
.tox
|
.tox
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
||||||
# Packaging artifacts
|
|
||||||
black.egg-info
|
black.egg-info
|
||||||
black.dist-info
|
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
pip-wheel-metadata/
|
pip-wheel-metadata/
|
||||||
.eggs
|
|
||||||
|
|
||||||
src/_black_version.py
|
src/_black_version.py
|
||||||
.idea
|
.idea
|
||||||
|
.eggs
|
||||||
.dmypy.json
|
.dmypy.json
|
||||||
*.swp
|
*.swp
|
||||||
.hypothesis/
|
.hypothesis/
|
||||||
venv/
|
venv/
|
||||||
.ipynb_checkpoints/
|
.ipynb_checkpoints/
|
||||||
node_modules/
|
|
||||||
|
@ -1,83 +1,52 @@
|
|||||||
# Note: don't use this config for your own repositories. Instead, see
|
# Note: don't use this config for your own repositories. Instead, see
|
||||||
# "Version control integration" in docs/integrations/source_version_control.md
|
# "Version control integration" in docs/integrations/source_version_control.md
|
||||||
exclude: ^(profiling/|tests/data/)
|
exclude: ^(src/blib2to3/|profiling/|tests/data/)
|
||||||
repos:
|
repos:
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
|
- id: black
|
||||||
|
name: black
|
||||||
|
language: system
|
||||||
|
entry: black
|
||||||
|
minimum_pre_commit_version: 2.9.2
|
||||||
|
require_serial: true
|
||||||
|
types_or: [python, pyi]
|
||||||
|
|
||||||
- id: check-pre-commit-rev-in-example
|
- id: check-pre-commit-rev-in-example
|
||||||
name: Check pre-commit rev in example
|
name: Check pre-commit rev in example
|
||||||
language: python
|
language: python
|
||||||
entry: python -m scripts.check_pre_commit_rev_in_example
|
entry: python -m scripts.check_pre_commit_rev_in_example
|
||||||
files: '(CHANGES\.md|source_version_control\.md)$'
|
files: '(CHANGES\.md|source_version_control\.md)$'
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
&version_check_dependencies [
|
["commonmark==0.9.1", "pyyaml==5.4.1", "beautifulsoup4==4.9.3"]
|
||||||
commonmark==0.9.1,
|
|
||||||
pyyaml==6.0.1,
|
|
||||||
beautifulsoup4==4.9.3,
|
|
||||||
]
|
|
||||||
|
|
||||||
- id: check-version-in-the-basics-example
|
- repo: https://gitlab.com/pycqa/flake8
|
||||||
name: Check black version in the basics example
|
rev: 3.9.2
|
||||||
language: python
|
|
||||||
entry: python -m scripts.check_version_in_basics_example
|
|
||||||
files: '(CHANGES\.md|the_basics\.md)$'
|
|
||||||
additional_dependencies: *version_check_dependencies
|
|
||||||
|
|
||||||
- repo: https://github.com/pycqa/isort
|
|
||||||
rev: 6.0.1
|
|
||||||
hooks:
|
|
||||||
- id: isort
|
|
||||||
|
|
||||||
- repo: https://github.com/pycqa/flake8
|
|
||||||
rev: 7.2.0
|
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies:
|
additional_dependencies: [flake8-bugbear]
|
||||||
- flake8-bugbear==24.2.6
|
|
||||||
- flake8-comprehensions
|
|
||||||
- flake8-simplify
|
|
||||||
exclude: ^src/blib2to3/
|
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v1.15.0
|
rev: v0.910
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
exclude: ^(docs/conf.py|scripts/generate_schema.py)$
|
exclude: ^docs/conf.py
|
||||||
args: []
|
additional_dependencies:
|
||||||
additional_dependencies: &mypy_deps
|
- types-dataclasses >= 0.1.3
|
||||||
- types-PyYAML
|
- types-PyYAML
|
||||||
- types-atheris
|
|
||||||
- tomli >= 0.2.6, < 2.0.0
|
- tomli >= 0.2.6, < 2.0.0
|
||||||
- click >= 8.2.0
|
- types-typed-ast >= 1.4.1
|
||||||
# Click is intentionally out-of-sync with pyproject.toml
|
- click >= 8.0.0
|
||||||
# v8.2 has breaking changes. We work around them at runtime, but we need the newer stubs.
|
|
||||||
- packaging >= 22.0
|
|
||||||
- platformdirs >= 2.1.0
|
- platformdirs >= 2.1.0
|
||||||
- pytokens >= 0.1.10
|
|
||||||
- pytest
|
|
||||||
- hypothesis
|
|
||||||
- aiohttp >= 3.7.4
|
|
||||||
- types-commonmark
|
|
||||||
- urllib3
|
|
||||||
- hypothesmith
|
|
||||||
- id: mypy
|
|
||||||
name: mypy (Python 3.10)
|
|
||||||
files: scripts/generate_schema.py
|
|
||||||
args: ["--python-version=3.10"]
|
|
||||||
additional_dependencies: *mypy_deps
|
|
||||||
|
|
||||||
- repo: https://github.com/rbubley/mirrors-prettier
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
rev: v3.5.3
|
rev: v2.3.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
types_or: [markdown, yaml, json]
|
exclude: ^Pipfile\.lock
|
||||||
exclude: \.github/workflows/diff_shades\.yml
|
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v5.0.0
|
rev: v4.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
|
|
||||||
ci:
|
|
||||||
autoupdate_schedule: quarterly
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# Note that we recommend using https://github.com/psf/black-pre-commit-mirror instead
|
|
||||||
# This will work about 2x as fast as using the hooks in this repository
|
|
||||||
- id: black
|
- id: black
|
||||||
name: black
|
name: black
|
||||||
description: "Black: The uncompromising Python code formatter"
|
description: "Black: The uncompromising Python code formatter"
|
||||||
|
@ -3,12 +3,8 @@ version: 2
|
|||||||
formats:
|
formats:
|
||||||
- htmlzip
|
- htmlzip
|
||||||
|
|
||||||
build:
|
|
||||||
os: ubuntu-22.04
|
|
||||||
tools:
|
|
||||||
python: "3.11"
|
|
||||||
|
|
||||||
python:
|
python:
|
||||||
|
version: 3.8
|
||||||
install:
|
install:
|
||||||
- requirements: docs/requirements.txt
|
- requirements: docs/requirements.txt
|
||||||
|
|
||||||
@ -16,6 +12,3 @@ python:
|
|||||||
path: .
|
path: .
|
||||||
extra_requirements:
|
extra_requirements:
|
||||||
- d
|
- d
|
||||||
|
|
||||||
sphinx:
|
|
||||||
configuration: docs/conf.py
|
|
||||||
|
26
AUTHORS.md
26
AUTHORS.md
@ -2,36 +2,27 @@
|
|||||||
|
|
||||||
Glued together by [Łukasz Langa](mailto:lukasz@langa.pl).
|
Glued together by [Łukasz Langa](mailto:lukasz@langa.pl).
|
||||||
|
|
||||||
Maintained with:
|
Maintained with [Carol Willing](mailto:carolcode@willingconsulting.com),
|
||||||
|
[Carl Meyer](mailto:carl@oddbird.net),
|
||||||
- [Carol Willing](mailto:carolcode@willingconsulting.com)
|
[Jelle Zijlstra](mailto:jelle.zijlstra@gmail.com),
|
||||||
- [Carl Meyer](mailto:carl@oddbird.net)
|
[Mika Naylor](mailto:mail@autophagy.io),
|
||||||
- [Jelle Zijlstra](mailto:jelle.zijlstra@gmail.com)
|
[Zsolt Dollenstein](mailto:zsol.zsol@gmail.com),
|
||||||
- [Mika Naylor](mailto:mail@autophagy.io)
|
[Cooper Lees](mailto:me@cooperlees.com), and Richard Si.
|
||||||
- [Zsolt Dollenstein](mailto:zsol.zsol@gmail.com)
|
|
||||||
- [Cooper Lees](mailto:me@cooperlees.com)
|
|
||||||
- [Richard Si](mailto:sichard26@gmail.com)
|
|
||||||
- [Felix Hildén](mailto:felix.hilden@gmail.com)
|
|
||||||
- [Batuhan Taskaya](mailto:batuhan@python.org)
|
|
||||||
- [Shantanu Jain](mailto:hauntsaninja@gmail.com)
|
|
||||||
|
|
||||||
Multiple contributions by:
|
Multiple contributions by:
|
||||||
|
|
||||||
- [Abdur-Rahmaan Janhangeer](mailto:arj.python@gmail.com)
|
- [Abdur-Rahmaan Janhangeer](mailto:arj.python@gmail.com)
|
||||||
- [Adam Johnson](mailto:me@adamj.eu)
|
- [Adam Johnson](mailto:me@adamj.eu)
|
||||||
- [Adam Williamson](mailto:adamw@happyassassin.net)
|
- [Adam Williamson](mailto:adamw@happyassassin.net)
|
||||||
- [Alexander Huynh](mailto:ahrex-gh-psf-black@e.sc)
|
- [Alexander Huynh](mailto:github@grande.coffee)
|
||||||
- [Alexandr Artemyev](mailto:mogost@gmail.com)
|
|
||||||
- [Alex Vandiver](mailto:github@chmrr.net)
|
- [Alex Vandiver](mailto:github@chmrr.net)
|
||||||
- [Allan Simon](mailto:allan.simon@supinfo.com)
|
- [Allan Simon](mailto:allan.simon@supinfo.com)
|
||||||
- Anders-Petter Ljungquist
|
- Anders-Petter Ljungquist
|
||||||
- [Amethyst Reese](mailto:amy@n7.gg)
|
|
||||||
- [Andrew Thorp](mailto:andrew.thorp.dev@gmail.com)
|
- [Andrew Thorp](mailto:andrew.thorp.dev@gmail.com)
|
||||||
- [Andrew Zhou](mailto:andrewfzhou@gmail.com)
|
- [Andrew Zhou](mailto:andrewfzhou@gmail.com)
|
||||||
- [Andrey](mailto:dyuuus@yandex.ru)
|
- [Andrey](mailto:dyuuus@yandex.ru)
|
||||||
- [Andy Freeland](mailto:andy@andyfreeland.net)
|
- [Andy Freeland](mailto:andy@andyfreeland.net)
|
||||||
- [Anthony Sottile](mailto:asottile@umich.edu)
|
- [Anthony Sottile](mailto:asottile@umich.edu)
|
||||||
- [Antonio Ossa Guerra](mailto:aaossa+black@uc.cl)
|
|
||||||
- [Arjaan Buijk](mailto:arjaan.buijk@gmail.com)
|
- [Arjaan Buijk](mailto:arjaan.buijk@gmail.com)
|
||||||
- [Arnav Borbornah](mailto:arnavborborah11@gmail.com)
|
- [Arnav Borbornah](mailto:arnavborborah11@gmail.com)
|
||||||
- [Artem Malyshev](mailto:proofit404@gmail.com)
|
- [Artem Malyshev](mailto:proofit404@gmail.com)
|
||||||
@ -82,7 +73,6 @@ Multiple contributions by:
|
|||||||
- [Hugo Barrera](mailto::hugo@barrera.io)
|
- [Hugo Barrera](mailto::hugo@barrera.io)
|
||||||
- Hugo van Kemenade
|
- Hugo van Kemenade
|
||||||
- [Hynek Schlawack](mailto:hs@ox.cx)
|
- [Hynek Schlawack](mailto:hs@ox.cx)
|
||||||
- [Ionite](mailto:dev@ionite.io)
|
|
||||||
- [Ivan Katanić](mailto:ivan.katanic@gmail.com)
|
- [Ivan Katanić](mailto:ivan.katanic@gmail.com)
|
||||||
- [Jakub Kadlubiec](mailto:jakub.kadlubiec@skyscanner.net)
|
- [Jakub Kadlubiec](mailto:jakub.kadlubiec@skyscanner.net)
|
||||||
- [Jakub Warczarek](mailto:jakub.warczarek@gmail.com)
|
- [Jakub Warczarek](mailto:jakub.warczarek@gmail.com)
|
||||||
@ -153,7 +143,6 @@ Multiple contributions by:
|
|||||||
- [Rishikesh Jha](mailto:rishijha424@gmail.com)
|
- [Rishikesh Jha](mailto:rishijha424@gmail.com)
|
||||||
- [Rupert Bedford](mailto:rupert@rupertb.com)
|
- [Rupert Bedford](mailto:rupert@rupertb.com)
|
||||||
- Russell Davis
|
- Russell Davis
|
||||||
- [Sagi Shadur](mailto:saroad2@gmail.com)
|
|
||||||
- [Rémi Verschelde](mailto:rverschelde@gmail.com)
|
- [Rémi Verschelde](mailto:rverschelde@gmail.com)
|
||||||
- [Sami Salonen](mailto:sakki@iki.fi)
|
- [Sami Salonen](mailto:sakki@iki.fi)
|
||||||
- [Samuel Cormier-Iijima](mailto:samuel@cormier-iijima.com)
|
- [Samuel Cormier-Iijima](mailto:samuel@cormier-iijima.com)
|
||||||
@ -181,7 +170,6 @@ Multiple contributions by:
|
|||||||
- [Tony Narlock](mailto:tony@git-pull.com)
|
- [Tony Narlock](mailto:tony@git-pull.com)
|
||||||
- [Tsuyoshi Hombashi](mailto:tsuyoshi.hombashi@gmail.com)
|
- [Tsuyoshi Hombashi](mailto:tsuyoshi.hombashi@gmail.com)
|
||||||
- [Tushar Chandra](mailto:tusharchandra2018@u.northwestern.edu)
|
- [Tushar Chandra](mailto:tusharchandra2018@u.northwestern.edu)
|
||||||
- [Tushar Sadhwani](mailto:tushar.sadhwani000@gmail.com)
|
|
||||||
- [Tzu-ping Chung](mailto:uranusjr@gmail.com)
|
- [Tzu-ping Chung](mailto:uranusjr@gmail.com)
|
||||||
- [Utsav Shah](mailto:ukshah2@illinois.edu)
|
- [Utsav Shah](mailto:ukshah2@illinois.edu)
|
||||||
- utsav-dbx
|
- utsav-dbx
|
||||||
|
1262
CHANGES.md
1262
CHANGES.md
File diff suppressed because it is too large
Load Diff
22
CITATION.cff
22
CITATION.cff
@ -1,22 +0,0 @@
|
|||||||
cff-version: 1.2.0
|
|
||||||
title: "Black: The uncompromising Python code formatter"
|
|
||||||
message: >-
|
|
||||||
If you use this software, please cite it using the metadata from this file.
|
|
||||||
type: software
|
|
||||||
authors:
|
|
||||||
- family-names: Langa
|
|
||||||
given-names: Łukasz
|
|
||||||
- name: "contributors to Black"
|
|
||||||
repository-code: "https://github.com/psf/black"
|
|
||||||
url: "https://black.readthedocs.io/en/stable/"
|
|
||||||
abstract: >-
|
|
||||||
Black is the uncompromising Python code formatter. By using it, you agree to cede
|
|
||||||
control over minutiae of hand-formatting. In return, Black gives you speed,
|
|
||||||
determinism, and freedom from pycodestyle nagging about formatting. You will save time
|
|
||||||
and mental energy for more important matters.
|
|
||||||
|
|
||||||
Blackened code looks the same regardless of the project you're reading. Formatting
|
|
||||||
becomes transparent after a while and you can focus on the content instead.
|
|
||||||
|
|
||||||
Black makes code review faster by producing the smallest diffs possible.
|
|
||||||
license: MIT
|
|
@ -1,13 +1,10 @@
|
|||||||
# Contributing to _Black_
|
# Contributing to _Black_
|
||||||
|
|
||||||
Welcome future contributor! We're happy to see you willing to make the project better.
|
Welcome! Happy to see you willing to make the project better. Have you read the entire
|
||||||
|
[user documentation](https://black.readthedocs.io/en/latest/) yet?
|
||||||
|
|
||||||
If you aren't familiar with _Black_, or are looking for documentation on something
|
Our [contributing documentation](https://black.readthedocs.org/en/latest/contributing/)
|
||||||
specific, the [user documentation](https://black.readthedocs.io/en/latest/) is the best
|
contains details on all you need to know about contributing to _Black_, the basics to
|
||||||
place to look.
|
the internals of _Black_.
|
||||||
|
|
||||||
For getting started on contributing, please read the
|
We look forward to your contributions!
|
||||||
[contributing documentation](https://black.readthedocs.org/en/latest/contributing/) for
|
|
||||||
all you need to know.
|
|
||||||
|
|
||||||
Thank you, and we look forward to your contributions!
|
|
||||||
|
28
Dockerfile
28
Dockerfile
@ -1,22 +1,14 @@
|
|||||||
FROM python:3.12-slim AS builder
|
FROM python:3-slim
|
||||||
|
|
||||||
RUN mkdir /src
|
RUN mkdir /src
|
||||||
COPY . /src/
|
COPY . /src/
|
||||||
ENV VIRTUAL_ENV=/opt/venv
|
RUN pip install --no-cache-dir --upgrade pip setuptools wheel \
|
||||||
ENV HATCH_BUILD_HOOKS_ENABLE=1
|
&& apt update && apt install -y git \
|
||||||
# Install build tools to compile black + dependencies
|
&& cd /src \
|
||||||
RUN apt update && apt install -y build-essential git python3-dev
|
&& pip install --no-cache-dir .[colorama,d] \
|
||||||
RUN python -m venv $VIRTUAL_ENV
|
&& rm -rf /src \
|
||||||
RUN python -m pip install --no-cache-dir hatch hatch-fancy-pypi-readme hatch-vcs
|
&& apt remove -y git \
|
||||||
RUN . /opt/venv/bin/activate && pip install --no-cache-dir --upgrade pip setuptools \
|
&& apt autoremove -y \
|
||||||
&& cd /src && hatch build -t wheel \
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
&& pip install --no-cache-dir dist/*-cp* \
|
|
||||||
&& pip install black[colorama,d,uvloop]
|
|
||||||
|
|
||||||
FROM python:3.12-slim
|
CMD ["black"]
|
||||||
|
|
||||||
# copy only Python packages to limit the image size
|
|
||||||
COPY --from=builder /opt/venv /opt/venv
|
|
||||||
ENV PATH="/opt/venv/bin:$PATH"
|
|
||||||
|
|
||||||
CMD ["/opt/venv/bin/black"]
|
|
||||||
|
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
prune profiling
|
54
Pipfile
Normal file
54
Pipfile
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
[[source]]
|
||||||
|
name = "pypi"
|
||||||
|
url = "https://pypi.python.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
# Testing related requirements.
|
||||||
|
coverage = ">= 5.3"
|
||||||
|
pytest = " >= 6.1.1"
|
||||||
|
pytest-mock = ">= 3.3.1"
|
||||||
|
pytest-cases = ">= 2.3.0"
|
||||||
|
pytest-xdist = ">= 2.2.1"
|
||||||
|
pytest-cov = ">= 2.11.1"
|
||||||
|
parameterized = ">= 0.7.4"
|
||||||
|
tox = "*"
|
||||||
|
|
||||||
|
# Linting related requirements.
|
||||||
|
pre-commit = ">=2.9.2"
|
||||||
|
flake8 = ">=3.9.2"
|
||||||
|
flake8-bugbear = "*"
|
||||||
|
mypy = ">=0.910"
|
||||||
|
types-dataclasses = ">=0.1.3"
|
||||||
|
types-typed-ast = ">=1.4.1"
|
||||||
|
types-PyYAML = ">=5.4.1"
|
||||||
|
|
||||||
|
# Documentation related requirements.
|
||||||
|
Sphinx = ">=4.1.2"
|
||||||
|
MyST-Parser = ">=0.15.1"
|
||||||
|
sphinxcontrib-programoutput = ">=0.17"
|
||||||
|
sphinx-copybutton = ">=0.4.0"
|
||||||
|
docutils = "==0.17.1" # not a direct dependency, see https://github.com/pypa/pipenv/issues/3865
|
||||||
|
|
||||||
|
# Packaging related requirements.
|
||||||
|
setuptools = ">=39.2.0"
|
||||||
|
setuptools-scm = "*"
|
||||||
|
twine = ">=1.11.0"
|
||||||
|
wheel = ">=0.31.1"
|
||||||
|
readme_renderer = "*"
|
||||||
|
|
||||||
|
black = {editable = true, extras = ["d", "jupyter"], path = "."}
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
aiohttp = ">=3.6.0"
|
||||||
|
aiohttp-cors = ">=0.4.0"
|
||||||
|
platformdirs= ">=2"
|
||||||
|
click = ">=8.0.0"
|
||||||
|
mypy_extensions = ">=0.4.3"
|
||||||
|
pathspec = ">=0.8.1"
|
||||||
|
regex = ">=2020.1.8"
|
||||||
|
tomli = ">=0.2.6, <2.0.0"
|
||||||
|
typed-ast = "==1.4.2"
|
||||||
|
typing_extensions = {"python_version <" = "3.10","version >=" = "3.10.0.0"}
|
||||||
|
black = {editable = true,extras = ["d"],path = "."}
|
||||||
|
dataclasses = {"python_version <" = "3.7","version >" = "0.1.3"}
|
1649
Pipfile.lock
generated
Normal file
1649
Pipfile.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
53
README.md
53
README.md
@ -1,14 +1,15 @@
|
|||||||
[](https://black.readthedocs.io/en/stable/)
|

|
||||||
|
|
||||||
<h2 align="center">The Uncompromising Code Formatter</h2>
|
<h2 align="center">The Uncompromising Code Formatter</h2>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/psf/black/actions"><img alt="Actions Status" src="https://github.com/psf/black/workflows/Test/badge.svg"></a>
|
<a href="https://github.com/psf/black/actions"><img alt="Actions Status" src="https://github.com/psf/black/workflows/Test/badge.svg"></a>
|
||||||
|
<a href="https://github.com/psf/black/actions"><img alt="Actions Status" src="https://github.com/psf/black/workflows/Primer/badge.svg"></a>
|
||||||
<a href="https://black.readthedocs.io/en/stable/?badge=stable"><img alt="Documentation Status" src="https://readthedocs.org/projects/black/badge/?version=stable"></a>
|
<a href="https://black.readthedocs.io/en/stable/?badge=stable"><img alt="Documentation Status" src="https://readthedocs.org/projects/black/badge/?version=stable"></a>
|
||||||
<a href="https://coveralls.io/github/psf/black?branch=main"><img alt="Coverage Status" src="https://coveralls.io/repos/github/psf/black/badge.svg?branch=main"></a>
|
<a href="https://coveralls.io/github/psf/black?branch=main"><img alt="Coverage Status" src="https://coveralls.io/repos/github/psf/black/badge.svg?branch=main"></a>
|
||||||
<a href="https://github.com/psf/black/blob/main/LICENSE"><img alt="License: MIT" src="https://black.readthedocs.io/en/stable/_static/license.svg"></a>
|
<a href="https://github.com/psf/black/blob/main/LICENSE"><img alt="License: MIT" src="https://black.readthedocs.io/en/stable/_static/license.svg"></a>
|
||||||
<a href="https://pypi.org/project/black/"><img alt="PyPI" src="https://img.shields.io/pypi/v/black"></a>
|
<a href="https://pypi.org/project/black/"><img alt="PyPI" src="https://img.shields.io/pypi/v/black"></a>
|
||||||
<a href="https://pepy.tech/project/black"><img alt="Downloads" src="https://static.pepy.tech/badge/black"></a>
|
<a href="https://pepy.tech/project/black"><img alt="Downloads" src="https://pepy.tech/badge/black"></a>
|
||||||
<a href="https://anaconda.org/conda-forge/black/"><img alt="conda-forge" src="https://img.shields.io/conda/dn/conda-forge/black.svg?label=conda-forge"></a>
|
<a href="https://anaconda.org/conda-forge/black/"><img alt="conda-forge" src="https://img.shields.io/conda/dn/conda-forge/black.svg?label=conda-forge"></a>
|
||||||
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
@ -38,12 +39,14 @@ Try it out now using the [Black Playground](https://black.vercel.app). Watch the
|
|||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
_Black_ can be installed by running `pip install black`. It requires Python 3.9+ to run.
|
_Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
|
||||||
If you want to format Jupyter Notebooks, install with `pip install "black[jupyter]"`.
|
run. If you want to format Python 2 code as well, install with
|
||||||
|
`pip install black[python2]`. If you want to format Jupyter Notebooks, install with
|
||||||
|
`pip install black[jupyter]`.
|
||||||
|
|
||||||
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
||||||
|
|
||||||
`pip install git+https://github.com/psf/black`
|
`pip install git+git://github.com/psf/black`
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
@ -63,13 +66,16 @@ Further information can be found in our docs:
|
|||||||
|
|
||||||
- [Usage and Configuration](https://black.readthedocs.io/en/stable/usage_and_configuration/index.html)
|
- [Usage and Configuration](https://black.readthedocs.io/en/stable/usage_and_configuration/index.html)
|
||||||
|
|
||||||
|
### NOTE: This is a beta product
|
||||||
|
|
||||||
_Black_ is already [successfully used](https://github.com/psf/black#used-by) by many
|
_Black_ is already [successfully used](https://github.com/psf/black#used-by) by many
|
||||||
projects, small and big. _Black_ has a comprehensive test suite, with efficient parallel
|
projects, small and big. Black has a comprehensive test suite, with efficient parallel
|
||||||
tests, and our own auto formatting and parallel Continuous Integration runner. Now that
|
tests, and our own auto formatting and parallel Continuous Integration runner. However,
|
||||||
we have become stable, you should not expect large formatting changes in the future.
|
_Black_ is still beta. Things will probably be wonky for a while. This is made explicit
|
||||||
Stylistic changes will mostly be responses to bug reports and support for new Python
|
by the "Beta" trove classifier, as well as by the "b" in the version number. What this
|
||||||
syntax. For more information please refer to
|
means for you is that **until the formatter becomes stable, you should expect some
|
||||||
[The Black Code Style](https://black.readthedocs.io/en/stable/the_black_code_style/index.html).
|
formatting to change in the future**. That being said, no drastic stylistic changes are
|
||||||
|
planned, mostly responses to bug reports.
|
||||||
|
|
||||||
Also, as a safety measure which slows down processing, _Black_ will check that the
|
Also, as a safety measure which slows down processing, _Black_ will check that the
|
||||||
reformatted code still produces a valid AST that is effectively equivalent to the
|
reformatted code still produces a valid AST that is effectively equivalent to the
|
||||||
@ -81,20 +87,14 @@ section for details). If you're feeling confident, use `--fast`.
|
|||||||
|
|
||||||
_Black_ is a PEP 8 compliant opinionated formatter. _Black_ reformats entire files in
|
_Black_ is a PEP 8 compliant opinionated formatter. _Black_ reformats entire files in
|
||||||
place. Style configuration options are deliberately limited and rarely added. It doesn't
|
place. Style configuration options are deliberately limited and rarely added. It doesn't
|
||||||
take previous formatting into account (see
|
take previous formatting into account (see [Pragmatism](#pragmatism) for exceptions).
|
||||||
[Pragmatism](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#pragmatism)
|
|
||||||
for exceptions).
|
|
||||||
|
|
||||||
Our documentation covers the current _Black_ code style, but planned changes to it are
|
Our documentation covers the current _Black_ code style, but planned changes to it are
|
||||||
also documented. They're both worth taking a look at:
|
also documented. They're both worth taking a look:
|
||||||
|
|
||||||
- [The _Black_ Code Style: Current style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html)
|
- [The _Black_ Code Style: Current style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html)
|
||||||
- [The _Black_ Code Style: Future style](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html)
|
- [The _Black_ Code Style: Future style](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html)
|
||||||
|
|
||||||
Changes to the _Black_ code style are bound by the Stability Policy:
|
|
||||||
|
|
||||||
- [The _Black_ Code Style: Stability Policy](https://black.readthedocs.io/en/stable/the_black_code_style/index.html#stability-policy)
|
|
||||||
|
|
||||||
Please refer to this document before submitting an issue. What seems like a bug might be
|
Please refer to this document before submitting an issue. What seems like a bug might be
|
||||||
intended behaviour.
|
intended behaviour.
|
||||||
|
|
||||||
@ -132,13 +132,12 @@ code in compliance with many other _Black_ formatted projects.
|
|||||||
## Used by
|
## Used by
|
||||||
|
|
||||||
The following notable open-source projects trust _Black_ with enforcing a consistent
|
The following notable open-source projects trust _Black_ with enforcing a consistent
|
||||||
code style: pytest, tox, Pyramid, Django, Django Channels, Hypothesis, attrs,
|
code style: pytest, tox, Pyramid, Django Channels, Hypothesis, attrs, SQLAlchemy,
|
||||||
SQLAlchemy, Poetry, PyPA applications (Warehouse, Bandersnatch, Pipenv, virtualenv),
|
Poetry, PyPA applications (Warehouse, Bandersnatch, Pipenv, virtualenv), pandas, Pillow,
|
||||||
pandas, Pillow, Twisted, LocalStack, every Datadog Agent Integration, Home Assistant,
|
Twisted, LocalStack, every Datadog Agent Integration, Home Assistant, Zulip, and many
|
||||||
Zulip, Kedro, OpenOA, FLORIS, ORBIT, WOMBAT, and many more.
|
more.
|
||||||
|
|
||||||
The following organizations use _Black_: Dropbox, KeepTruckin, Lyft, Mozilla, Quora,
|
The following organizations use _Black_: Facebook, Dropbox, Mozilla, Quora, Duolingo.
|
||||||
Duolingo, QuantumBlack, Tesla, Archer Aviation.
|
|
||||||
|
|
||||||
Are we missing anyone? Let us know.
|
Are we missing anyone? Let us know.
|
||||||
|
|
||||||
@ -165,8 +164,8 @@ Twisted and CPython:
|
|||||||
|
|
||||||
> At least the name is good.
|
> At least the name is good.
|
||||||
|
|
||||||
**Kenneth Reitz**, creator of [`requests`](https://requests.readthedocs.io/en/latest/)
|
**Kenneth Reitz**, creator of [`requests`](http://python-requests.org/) and
|
||||||
and [`pipenv`](https://readthedocs.org/projects/pipenv/):
|
[`pipenv`](https://readthedocs.org/projects/pipenv/):
|
||||||
|
|
||||||
> This vastly improves the formatting of our code. Thanks a ton!
|
> This vastly improves the formatting of our code. Thanks a ton!
|
||||||
|
|
||||||
|
11
SECURITY.md
11
SECURITY.md
@ -1,11 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Only the latest non-prerelease version is supported.
|
|
||||||
|
|
||||||
## Security contact information
|
|
||||||
|
|
||||||
To report a security vulnerability, please use the
|
|
||||||
[Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the
|
|
||||||
fix and disclosure.
|
|
56
action.yml
56
action.yml
@ -5,18 +5,13 @@ inputs:
|
|||||||
options:
|
options:
|
||||||
description:
|
description:
|
||||||
"Options passed to Black. Use `black --help` to see available options. Default:
|
"Options passed to Black. Use `black --help` to see available options. Default:
|
||||||
'--check --diff'"
|
'--check'"
|
||||||
required: false
|
required: false
|
||||||
default: "--check --diff"
|
default: "--check --diff"
|
||||||
src:
|
src:
|
||||||
description: "Source to run Black. Default: '.'"
|
description: "Source to run Black. Default: '.'"
|
||||||
required: false
|
required: false
|
||||||
default: "."
|
default: "."
|
||||||
jupyter:
|
|
||||||
description:
|
|
||||||
"Set this option to true to include Jupyter Notebook files. Default: false"
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
black_args:
|
black_args:
|
||||||
description: "[DEPRECATED] Black input arguments."
|
description: "[DEPRECATED] Black input arguments."
|
||||||
required: false
|
required: false
|
||||||
@ -27,53 +22,38 @@ inputs:
|
|||||||
description: 'Python Version specifier (PEP440) - e.g. "21.5b1"'
|
description: 'Python Version specifier (PEP440) - e.g. "21.5b1"'
|
||||||
required: false
|
required: false
|
||||||
default: ""
|
default: ""
|
||||||
use_pyproject:
|
|
||||||
description: Read Black version specifier from pyproject.toml if `true`.
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
summary:
|
|
||||||
description: "Whether to add the output to the workflow summary"
|
|
||||||
required: false
|
|
||||||
default: true
|
|
||||||
branding:
|
branding:
|
||||||
color: "black"
|
color: "black"
|
||||||
icon: "check-circle"
|
icon: "check-circle"
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: black
|
- run: |
|
||||||
run: |
|
# Exists since using github.action_path + path to main script doesn't work because bash
|
||||||
# Even when black fails, do not close the shell
|
# interprets the backslashes in github.action_path (which are used when the runner OS
|
||||||
set +e
|
# is Windows) destroying the path to the target file.
|
||||||
|
#
|
||||||
|
# Also semicolons are necessary because I can't get the newlines to work
|
||||||
|
entrypoint="import sys;
|
||||||
|
import subprocess;
|
||||||
|
from pathlib import Path;
|
||||||
|
|
||||||
|
MAIN_SCRIPT = Path(r'${{ github.action_path }}') / 'action' / 'main.py';
|
||||||
|
|
||||||
|
proc = subprocess.run([sys.executable, str(MAIN_SCRIPT)]);
|
||||||
|
sys.exit(proc.returncode)
|
||||||
|
"
|
||||||
|
|
||||||
if [ "$RUNNER_OS" == "Windows" ]; then
|
if [ "$RUNNER_OS" == "Windows" ]; then
|
||||||
runner="python"
|
echo $entrypoint | python
|
||||||
else
|
else
|
||||||
runner="python3"
|
echo $entrypoint | python3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
out=$(${runner} $GITHUB_ACTION_PATH/action/main.py)
|
|
||||||
exit_code=$?
|
|
||||||
|
|
||||||
# Display the raw output in the step
|
|
||||||
echo "${out}"
|
|
||||||
|
|
||||||
if [ "${{ inputs.summary }}" == "true" ]; then
|
|
||||||
# Display the Markdown output in the job summary
|
|
||||||
echo "\`\`\`python" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "${out}" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Exit with the exit-code returned by Black
|
|
||||||
exit ${exit_code}
|
|
||||||
env:
|
env:
|
||||||
# TODO: Remove once https://github.com/actions/runner/issues/665 is fixed.
|
# TODO: Remove once https://github.com/actions/runner/issues/665 is fixed.
|
||||||
INPUT_OPTIONS: ${{ inputs.options }}
|
INPUT_OPTIONS: ${{ inputs.options }}
|
||||||
INPUT_SRC: ${{ inputs.src }}
|
INPUT_SRC: ${{ inputs.src }}
|
||||||
INPUT_JUPYTER: ${{ inputs.jupyter }}
|
|
||||||
INPUT_BLACK_ARGS: ${{ inputs.black_args }}
|
INPUT_BLACK_ARGS: ${{ inputs.black_args }}
|
||||||
INPUT_VERSION: ${{ inputs.version }}
|
INPUT_VERSION: ${{ inputs.version }}
|
||||||
INPUT_USE_PYPROJECT: ${{ inputs.use_pyproject }}
|
|
||||||
pythonioencoding: utf-8
|
pythonioencoding: utf-8
|
||||||
shell: bash
|
shell: bash
|
||||||
|
159
action/main.py
159
action/main.py
@ -1,182 +1,39 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import PIPE, STDOUT, run
|
from subprocess import run, PIPE, STDOUT
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
|
ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
|
||||||
ENV_PATH = ACTION_PATH / ".black-env"
|
ENV_PATH = ACTION_PATH / ".black-env"
|
||||||
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
|
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
|
||||||
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
|
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
|
||||||
SRC = os.getenv("INPUT_SRC", default="")
|
SRC = os.getenv("INPUT_SRC", default="")
|
||||||
JUPYTER = os.getenv("INPUT_JUPYTER") == "true"
|
|
||||||
BLACK_ARGS = os.getenv("INPUT_BLACK_ARGS", default="")
|
BLACK_ARGS = os.getenv("INPUT_BLACK_ARGS", default="")
|
||||||
VERSION = os.getenv("INPUT_VERSION", default="")
|
VERSION = os.getenv("INPUT_VERSION", default="")
|
||||||
USE_PYPROJECT = os.getenv("INPUT_USE_PYPROJECT") == "true"
|
|
||||||
|
|
||||||
BLACK_VERSION_RE = re.compile(r"^black([^A-Z0-9._-]+.*)$", re.IGNORECASE)
|
|
||||||
EXTRAS_RE = re.compile(r"\[.*\]")
|
|
||||||
EXPORT_SUBST_FAIL_RE = re.compile(r"\$Format:.*\$")
|
|
||||||
|
|
||||||
|
|
||||||
def determine_version_specifier() -> str:
|
|
||||||
"""Determine the version of Black to install.
|
|
||||||
|
|
||||||
The version can be specified either via the `with.version` input or via the
|
|
||||||
pyproject.toml file if `with.use_pyproject` is set to `true`.
|
|
||||||
"""
|
|
||||||
if USE_PYPROJECT and VERSION:
|
|
||||||
print(
|
|
||||||
"::error::'with.version' and 'with.use_pyproject' inputs are "
|
|
||||||
"mutually exclusive.",
|
|
||||||
file=sys.stderr,
|
|
||||||
flush=True,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
if USE_PYPROJECT:
|
|
||||||
return read_version_specifier_from_pyproject()
|
|
||||||
elif VERSION and VERSION[0] in "0123456789":
|
|
||||||
return f"=={VERSION}"
|
|
||||||
else:
|
|
||||||
return VERSION
|
|
||||||
|
|
||||||
|
|
||||||
def read_version_specifier_from_pyproject() -> str:
|
|
||||||
if sys.version_info < (3, 11):
|
|
||||||
print(
|
|
||||||
"::error::'with.use_pyproject' input requires Python 3.11 or later.",
|
|
||||||
file=sys.stderr,
|
|
||||||
flush=True,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
import tomllib # type: ignore[import-not-found,unreachable]
|
|
||||||
|
|
||||||
try:
|
|
||||||
with Path("pyproject.toml").open("rb") as fp:
|
|
||||||
pyproject = tomllib.load(fp)
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(
|
|
||||||
"::error::'with.use_pyproject' input requires a pyproject.toml file.",
|
|
||||||
file=sys.stderr,
|
|
||||||
flush=True,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
version = pyproject.get("tool", {}).get("black", {}).get("required-version")
|
|
||||||
if version is not None:
|
|
||||||
return f"=={version}"
|
|
||||||
|
|
||||||
arrays = [
|
|
||||||
*pyproject.get("dependency-groups", {}).values(),
|
|
||||||
pyproject.get("project", {}).get("dependencies"),
|
|
||||||
*pyproject.get("project", {}).get("optional-dependencies", {}).values(),
|
|
||||||
]
|
|
||||||
for array in arrays:
|
|
||||||
version = find_black_version_in_array(array)
|
|
||||||
if version is not None:
|
|
||||||
break
|
|
||||||
|
|
||||||
if version is None:
|
|
||||||
print(
|
|
||||||
"::error::'black' dependency missing from pyproject.toml.",
|
|
||||||
file=sys.stderr,
|
|
||||||
flush=True,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
return version
|
|
||||||
|
|
||||||
|
|
||||||
def find_black_version_in_array(array: object) -> Union[str, None]:
|
|
||||||
if not isinstance(array, list):
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
for item in array:
|
|
||||||
# Rudimentary PEP 508 parsing.
|
|
||||||
item = item.split(";")[0]
|
|
||||||
item = EXTRAS_RE.sub("", item).strip()
|
|
||||||
if item == "black":
|
|
||||||
print(
|
|
||||||
"::error::Version specifier missing for 'black' dependency in "
|
|
||||||
"pyproject.toml.",
|
|
||||||
file=sys.stderr,
|
|
||||||
flush=True,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
elif m := BLACK_VERSION_RE.match(item):
|
|
||||||
return m.group(1).strip()
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
run([sys.executable, "-m", "venv", str(ENV_PATH)], check=True)
|
run([sys.executable, "-m", "venv", str(ENV_PATH)], check=True)
|
||||||
|
|
||||||
version_specifier = determine_version_specifier()
|
req = "black[colorama,python2]"
|
||||||
if JUPYTER:
|
if VERSION:
|
||||||
extra_deps = "[colorama,jupyter]"
|
req += f"=={VERSION}"
|
||||||
else:
|
|
||||||
extra_deps = "[colorama]"
|
|
||||||
if version_specifier:
|
|
||||||
req = f"black{extra_deps}{version_specifier}"
|
|
||||||
else:
|
|
||||||
describe_name = ""
|
|
||||||
with open(ACTION_PATH / ".git_archival.txt", encoding="utf-8") as fp:
|
|
||||||
for line in fp:
|
|
||||||
if line.startswith("describe-name: "):
|
|
||||||
describe_name = line[len("describe-name: ") :].rstrip()
|
|
||||||
break
|
|
||||||
if not describe_name:
|
|
||||||
print("::error::Failed to detect action version.", file=sys.stderr, flush=True)
|
|
||||||
sys.exit(1)
|
|
||||||
# expected format is one of:
|
|
||||||
# - 23.1.0
|
|
||||||
# - 23.1.0-51-g448bba7
|
|
||||||
# - $Format:%(describe:tags=true,match=*[0-9]*)$ (if export-subst fails)
|
|
||||||
if (
|
|
||||||
describe_name.count("-") < 2
|
|
||||||
and EXPORT_SUBST_FAIL_RE.match(describe_name) is None
|
|
||||||
):
|
|
||||||
# the action's commit matches a tag exactly, install exact version from PyPI
|
|
||||||
req = f"black{extra_deps}=={describe_name}"
|
|
||||||
else:
|
|
||||||
# the action's commit does not match any tag, install from the local git repo
|
|
||||||
req = f".{extra_deps}"
|
|
||||||
print(f"Installing {req}...", flush=True)
|
|
||||||
pip_proc = run(
|
pip_proc = run(
|
||||||
[str(ENV_BIN / "python"), "-m", "pip", "install", req],
|
[str(ENV_BIN / "python"), "-m", "pip", "install", req],
|
||||||
stdout=PIPE,
|
stdout=PIPE,
|
||||||
stderr=STDOUT,
|
stderr=STDOUT,
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
cwd=ACTION_PATH,
|
|
||||||
)
|
)
|
||||||
if pip_proc.returncode:
|
if pip_proc.returncode:
|
||||||
print(pip_proc.stdout)
|
print(pip_proc.stdout)
|
||||||
print("::error::Failed to install Black.", file=sys.stderr, flush=True)
|
print("::error::Failed to install Black.", flush=True)
|
||||||
sys.exit(pip_proc.returncode)
|
sys.exit(pip_proc.returncode)
|
||||||
|
|
||||||
|
|
||||||
base_cmd = [str(ENV_BIN / "black")]
|
base_cmd = [str(ENV_BIN / "black")]
|
||||||
if BLACK_ARGS:
|
if BLACK_ARGS:
|
||||||
# TODO: remove after a while since this is deprecated in favour of SRC + OPTIONS.
|
# TODO: remove after a while since this is deprecated in favour of SRC + OPTIONS.
|
||||||
proc = run(
|
proc = run([*base_cmd, *shlex.split(BLACK_ARGS)])
|
||||||
[*base_cmd, *shlex.split(BLACK_ARGS)],
|
|
||||||
stdout=PIPE,
|
|
||||||
stderr=STDOUT,
|
|
||||||
encoding="utf-8",
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
proc = run(
|
proc = run([*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)])
|
||||||
[*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)],
|
|
||||||
stdout=PIPE,
|
|
||||||
stderr=STDOUT,
|
|
||||||
encoding="utf-8",
|
|
||||||
)
|
|
||||||
shutil.rmtree(ENV_PATH, ignore_errors=True)
|
|
||||||
print(proc.stdout)
|
|
||||||
sys.exit(proc.returncode)
|
sys.exit(proc.returncode)
|
||||||
|
@ -3,13 +3,8 @@ import collections
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import vim
|
import vim
|
||||||
|
from distutils.util import strtobool
|
||||||
|
|
||||||
def strtobool(text):
|
|
||||||
if text.lower() in ['y', 'yes', 't', 'true', 'on', '1']:
|
|
||||||
return True
|
|
||||||
if text.lower() in ['n', 'no', 'f', 'false', 'off', '0']:
|
|
||||||
return False
|
|
||||||
raise ValueError(f"{text} is not convertible to boolean")
|
|
||||||
|
|
||||||
class Flag(collections.namedtuple("FlagBase", "name, cast")):
|
class Flag(collections.namedtuple("FlagBase", "name, cast")):
|
||||||
@property
|
@property
|
||||||
@ -29,12 +24,10 @@ FLAGS = [
|
|||||||
Flag(name="fast", cast=strtobool),
|
Flag(name="fast", cast=strtobool),
|
||||||
Flag(name="skip_string_normalization", cast=strtobool),
|
Flag(name="skip_string_normalization", cast=strtobool),
|
||||||
Flag(name="quiet", cast=strtobool),
|
Flag(name="quiet", cast=strtobool),
|
||||||
Flag(name="skip_magic_trailing_comma", cast=strtobool),
|
|
||||||
Flag(name="preview", cast=strtobool),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _get_python_binary(exec_prefix, pyver):
|
def _get_python_binary(exec_prefix):
|
||||||
try:
|
try:
|
||||||
default = vim.eval("g:pymode_python").strip()
|
default = vim.eval("g:pymode_python").strip()
|
||||||
except vim.error:
|
except vim.error:
|
||||||
@ -43,15 +36,7 @@ def _get_python_binary(exec_prefix, pyver):
|
|||||||
return default
|
return default
|
||||||
if sys.platform[:3] == "win":
|
if sys.platform[:3] == "win":
|
||||||
return exec_prefix / 'python.exe'
|
return exec_prefix / 'python.exe'
|
||||||
bin_path = exec_prefix / "bin"
|
return exec_prefix / 'bin' / 'python3'
|
||||||
exec_path = (bin_path / f"python{pyver[0]}.{pyver[1]}").resolve()
|
|
||||||
if exec_path.exists():
|
|
||||||
return exec_path
|
|
||||||
# It is possible that some environments may only have python3
|
|
||||||
exec_path = (bin_path / f"python3").resolve()
|
|
||||||
if exec_path.exists():
|
|
||||||
return exec_path
|
|
||||||
raise ValueError("python executable not found")
|
|
||||||
|
|
||||||
def _get_pip(venv_path):
|
def _get_pip(venv_path):
|
||||||
if sys.platform[:3] == "win":
|
if sys.platform[:3] == "win":
|
||||||
@ -64,19 +49,9 @@ def _get_virtualenv_site_packages(venv_path, pyver):
|
|||||||
return venv_path / 'lib' / f'python{pyver[0]}.{pyver[1]}' / 'site-packages'
|
return venv_path / 'lib' / f'python{pyver[0]}.{pyver[1]}' / 'site-packages'
|
||||||
|
|
||||||
def _initialize_black_env(upgrade=False):
|
def _initialize_black_env(upgrade=False):
|
||||||
if vim.eval("g:black_use_virtualenv ? 'true' : 'false'") == "false":
|
|
||||||
if upgrade:
|
|
||||||
print("Upgrade disabled due to g:black_use_virtualenv being disabled.")
|
|
||||||
print("Either use your system package manager (or pip) to upgrade black separately,")
|
|
||||||
print("or modify your vimrc to have 'let g:black_use_virtualenv = 1'.")
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
# Nothing needed to be done.
|
|
||||||
return True
|
|
||||||
|
|
||||||
pyver = sys.version_info[:3]
|
pyver = sys.version_info[:3]
|
||||||
if pyver < (3, 9):
|
if pyver < (3, 6, 2):
|
||||||
print("Sorry, Black requires Python 3.9+ to run.")
|
print("Sorry, Black requires Python 3.6.2+ to run.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -90,7 +65,7 @@ def _initialize_black_env(upgrade=False):
|
|||||||
_executable = sys.executable
|
_executable = sys.executable
|
||||||
_base_executable = getattr(sys, "_base_executable", _executable)
|
_base_executable = getattr(sys, "_base_executable", _executable)
|
||||||
try:
|
try:
|
||||||
executable = str(_get_python_binary(Path(sys.exec_prefix), pyver))
|
executable = str(_get_python_binary(Path(sys.exec_prefix)))
|
||||||
sys.executable = executable
|
sys.executable = executable
|
||||||
sys._base_executable = executable
|
sys._base_executable = executable
|
||||||
print(f'Creating a virtualenv in {virtualenv_path}...')
|
print(f'Creating a virtualenv in {virtualenv_path}...')
|
||||||
@ -123,49 +98,13 @@ if _initialize_black_env():
|
|||||||
import black
|
import black
|
||||||
import time
|
import time
|
||||||
|
|
||||||
def get_target_version(tv):
|
def Black():
|
||||||
if isinstance(tv, black.TargetVersion):
|
|
||||||
return tv
|
|
||||||
ret = None
|
|
||||||
try:
|
|
||||||
ret = black.TargetVersion[tv.upper()]
|
|
||||||
except KeyError:
|
|
||||||
print(f"WARNING: Target version {tv!r} not recognized by Black, using default target")
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def Black(**kwargs):
|
|
||||||
"""
|
|
||||||
kwargs allows you to override ``target_versions`` argument of
|
|
||||||
``black.FileMode``.
|
|
||||||
|
|
||||||
``target_version`` needs to be cleaned because ``black.FileMode``
|
|
||||||
expects the ``target_versions`` argument to be a set of TargetVersion enums.
|
|
||||||
|
|
||||||
Allow kwargs["target_version"] to be a string to allow
|
|
||||||
to type it more quickly.
|
|
||||||
|
|
||||||
Using also target_version instead of target_versions to remain
|
|
||||||
consistent to Black's documentation of the structure of pyproject.toml.
|
|
||||||
"""
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
configs = get_configs()
|
configs = get_configs()
|
||||||
|
|
||||||
black_kwargs = {}
|
|
||||||
if "target_version" in kwargs:
|
|
||||||
target_version = kwargs["target_version"]
|
|
||||||
|
|
||||||
if not isinstance(target_version, (list, set)):
|
|
||||||
target_version = [target_version]
|
|
||||||
target_version = set(filter(lambda x: x, map(lambda tv: get_target_version(tv), target_version)))
|
|
||||||
black_kwargs["target_versions"] = target_version
|
|
||||||
|
|
||||||
mode = black.FileMode(
|
mode = black.FileMode(
|
||||||
line_length=configs["line_length"],
|
line_length=configs["line_length"],
|
||||||
string_normalization=not configs["skip_string_normalization"],
|
string_normalization=not configs["skip_string_normalization"],
|
||||||
is_pyi=vim.current.buffer.name.endswith('.pyi'),
|
is_pyi=vim.current.buffer.name.endswith('.pyi'),
|
||||||
magic_trailing_comma=not configs["skip_magic_trailing_comma"],
|
|
||||||
preview=configs["preview"],
|
|
||||||
**black_kwargs,
|
|
||||||
)
|
)
|
||||||
quiet = configs["quiet"]
|
quiet = configs["quiet"]
|
||||||
|
|
||||||
@ -178,9 +117,9 @@ def Black(**kwargs):
|
|||||||
)
|
)
|
||||||
except black.NothingChanged:
|
except black.NothingChanged:
|
||||||
if not quiet:
|
if not quiet:
|
||||||
print(f'Black: already well formatted, good job. (took {time.time() - start:.4f}s)')
|
print(f'Already well formatted, good job. (took {time.time() - start:.4f}s)')
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(f'Black: {exc}')
|
print(exc)
|
||||||
else:
|
else:
|
||||||
current_buffer = vim.current.window.buffer
|
current_buffer = vim.current.window.buffer
|
||||||
cursors = []
|
cursors = []
|
||||||
@ -197,7 +136,7 @@ def Black(**kwargs):
|
|||||||
except vim.error:
|
except vim.error:
|
||||||
window.cursor = (len(window.buffer), 0)
|
window.cursor = (len(window.buffer), 0)
|
||||||
if not quiet:
|
if not quiet:
|
||||||
print(f'Black: reformatted in {time.time() - start:.4f}s.')
|
print(f'Reformatted in {time.time() - start:.4f}s.')
|
||||||
|
|
||||||
def get_configs():
|
def get_configs():
|
||||||
filename = vim.eval("@%")
|
filename = vim.eval("@%")
|
||||||
@ -221,17 +160,8 @@ def BlackVersion():
|
|||||||
|
|
||||||
EndPython3
|
EndPython3
|
||||||
|
|
||||||
function black#Black(...)
|
function black#Black()
|
||||||
let kwargs = {}
|
:py3 Black()
|
||||||
for arg in a:000
|
|
||||||
let arg_list = split(arg, '=')
|
|
||||||
let kwargs[arg_list[0]] = arg_list[1]
|
|
||||||
endfor
|
|
||||||
python3 << EOF
|
|
||||||
import vim
|
|
||||||
kwargs = vim.eval("kwargs")
|
|
||||||
EOF
|
|
||||||
:py3 Black(**kwargs)
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function black#BlackUpgrade()
|
function black#BlackUpgrade()
|
||||||
|
44
docs/_static/custom.css
vendored
Normal file
44
docs/_static/custom.css
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* Make the sidebar scrollable. Fixes https://github.com/psf/black/issues/990 */
|
||||||
|
div.sphinxsidebar {
|
||||||
|
max-height: calc(100% - 18px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||||
|
div.sphinxsidebar::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide scrollbar for IE 6, 7 and 8 */
|
||||||
|
@media \0screen\, screen\9 {
|
||||||
|
div.sphinxsidebar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide scrollbar for IE 9 and 10 */
|
||||||
|
/* backslash-9 removes ie11+ & old Safari 4 */
|
||||||
|
@media screen and (min-width: 0\0) {
|
||||||
|
div.sphinxsidebar {
|
||||||
|
-ms-overflow-style: none\9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide scrollbar for IE 11 and up */
|
||||||
|
_:-ms-fullscreen,
|
||||||
|
:root div.sphinxsidebar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide scrollbar for Edge */
|
||||||
|
@supports (-ms-ime-align: auto) {
|
||||||
|
div.sphinxsidebar {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nicer style for local document toc */
|
||||||
|
.contents.topic {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
}
|
@ -1,3 +1,3 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203,E701
|
extend-ignore = E203
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203,E701
|
extend-ignore = E203
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203,E701
|
extend-ignore = E203
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
[pycodestyle]
|
|
||||||
max-line-length = 88
|
|
||||||
ignore = E203,E701
|
|
@ -1,3 +0,0 @@
|
|||||||
[pycodestyle]
|
|
||||||
max-line-length = 88
|
|
||||||
ignore = E203,E701
|
|
@ -1,3 +0,0 @@
|
|||||||
[pycodestyle]
|
|
||||||
max-line-length = 88
|
|
||||||
ignore = E203,E701
|
|
@ -1,2 +1,5 @@
|
|||||||
|
[MESSAGES CONTROL]
|
||||||
|
disable = C0330, C0326
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
|
[tool.pylint.messages_control]
|
||||||
|
disable = "C0330, C0326"
|
||||||
|
|
||||||
[tool.pylint.format]
|
[tool.pylint.format]
|
||||||
max-line-length = "88"
|
max-line-length = "88"
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
[pylint]
|
[pylint]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
|
|
||||||
|
[pylint.messages_control]
|
||||||
|
disable = C0330, C0326
|
||||||
|
84
docs/conf.py
84
docs/conf.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Configuration file for the Sphinx documentation builder.
|
# Configuration file for the Sphinx documentation builder.
|
||||||
#
|
#
|
||||||
@ -13,12 +14,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import string
|
import string
|
||||||
from importlib.metadata import version
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from sphinx.application import Sphinx
|
from pkg_resources import get_distribution
|
||||||
|
|
||||||
CURRENT_DIR = Path(__file__).parent
|
CURRENT_DIR = Path(__file__).parent
|
||||||
|
|
||||||
@ -26,33 +25,12 @@
|
|||||||
def make_pypi_svg(version: str) -> None:
|
def make_pypi_svg(version: str) -> None:
|
||||||
template: Path = CURRENT_DIR / "_static" / "pypi_template.svg"
|
template: Path = CURRENT_DIR / "_static" / "pypi_template.svg"
|
||||||
target: Path = CURRENT_DIR / "_static" / "pypi.svg"
|
target: Path = CURRENT_DIR / "_static" / "pypi.svg"
|
||||||
with open(str(template), encoding="utf8") as f:
|
with open(str(template), "r", encoding="utf8") as f:
|
||||||
svg: str = string.Template(f.read()).substitute(version=version)
|
svg: str = string.Template(f.read()).substitute(version=version)
|
||||||
with open(str(target), "w", encoding="utf8") as f:
|
with open(str(target), "w", encoding="utf8") as f:
|
||||||
f.write(svg)
|
f.write(svg)
|
||||||
|
|
||||||
|
|
||||||
def replace_pr_numbers_with_links(content: str) -> str:
|
|
||||||
"""Replaces all PR numbers with the corresponding GitHub link."""
|
|
||||||
return re.sub(r"#(\d+)", r"[#\1](https://github.com/psf/black/pull/\1)", content)
|
|
||||||
|
|
||||||
|
|
||||||
def handle_include_read(
|
|
||||||
app: Sphinx,
|
|
||||||
relative_path: Path,
|
|
||||||
parent_docname: str,
|
|
||||||
content: list[str],
|
|
||||||
) -> None:
|
|
||||||
"""Handler for the include-read sphinx event."""
|
|
||||||
if parent_docname == "change_log":
|
|
||||||
content[0] = replace_pr_numbers_with_links(content[0])
|
|
||||||
|
|
||||||
|
|
||||||
def setup(app: Sphinx) -> None:
|
|
||||||
"""Sets up a minimal sphinx extension."""
|
|
||||||
app.connect("include-read", handle_include_read)
|
|
||||||
|
|
||||||
|
|
||||||
# Necessary so Click doesn't hit an encode error when called by
|
# Necessary so Click doesn't hit an encode error when called by
|
||||||
# sphinxcontrib-programoutput on Windows.
|
# sphinxcontrib-programoutput on Windows.
|
||||||
os.putenv("pythonioencoding", "utf-8")
|
os.putenv("pythonioencoding", "utf-8")
|
||||||
@ -65,7 +43,7 @@ def setup(app: Sphinx) -> None:
|
|||||||
|
|
||||||
# Autopopulate version
|
# Autopopulate version
|
||||||
# The version, including alpha/beta/rc tags, but not commit hash and datestamps
|
# The version, including alpha/beta/rc tags, but not commit hash and datestamps
|
||||||
release = version("black").split("+")[0]
|
release = get_distribution("black").version.split("+")[0]
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = release
|
version = release
|
||||||
for sp in "abcfr":
|
for sp in "abcfr":
|
||||||
@ -77,7 +55,7 @@ def setup(app: Sphinx) -> None:
|
|||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
needs_sphinx = "4.4"
|
needs_sphinx = "3.0"
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
@ -109,7 +87,7 @@ def setup(app: Sphinx) -> None:
|
|||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = "en"
|
language = None
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
@ -127,22 +105,39 @@ def setup(app: Sphinx) -> None:
|
|||||||
# Prettier support formatting some MyST syntax but not all, so let's disable the
|
# Prettier support formatting some MyST syntax but not all, so let's disable the
|
||||||
# unsupported yet still enabled by default ones.
|
# unsupported yet still enabled by default ones.
|
||||||
myst_disable_syntax = [
|
myst_disable_syntax = [
|
||||||
"colon_fence",
|
|
||||||
"myst_block_break",
|
"myst_block_break",
|
||||||
"myst_line_comment",
|
"myst_line_comment",
|
||||||
"math_block",
|
"math_block",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Optional MyST Syntaxes
|
|
||||||
myst_enable_extensions = []
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = "furo"
|
html_theme = "alabaster"
|
||||||
html_logo = "_static/logo2-readme.png"
|
|
||||||
|
html_sidebars = {
|
||||||
|
"**": [
|
||||||
|
"about.html",
|
||||||
|
"navigation.html",
|
||||||
|
"relations.html",
|
||||||
|
"searchbox.html",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
html_theme_options = {
|
||||||
|
"show_related": False,
|
||||||
|
"description": "“Any color you like.”",
|
||||||
|
"github_button": True,
|
||||||
|
"github_user": "psf",
|
||||||
|
"github_repo": "black",
|
||||||
|
"github_type": "star",
|
||||||
|
"show_powered_by": True,
|
||||||
|
"fixed_sidebar": True,
|
||||||
|
"logo": "logo2.png",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
@ -171,13 +166,15 @@ def setup(app: Sphinx) -> None:
|
|||||||
# Grouping the document tree into LaTeX files. List of tuples
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [(
|
latex_documents = [
|
||||||
|
(
|
||||||
master_doc,
|
master_doc,
|
||||||
"black.tex",
|
"black.tex",
|
||||||
"Documentation for Black",
|
"Documentation for Black",
|
||||||
"Łukasz Langa and contributors to Black",
|
"Łukasz Langa and contributors to Black",
|
||||||
"manual",
|
"manual",
|
||||||
)]
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ------------------------------------------
|
# -- Options for manual page output ------------------------------------------
|
||||||
@ -192,7 +189,8 @@ def setup(app: Sphinx) -> None:
|
|||||||
# Grouping the document tree into Texinfo files. List of tuples
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [(
|
texinfo_documents = [
|
||||||
|
(
|
||||||
master_doc,
|
master_doc,
|
||||||
"Black",
|
"Black",
|
||||||
"Documentation for Black",
|
"Documentation for Black",
|
||||||
@ -200,7 +198,8 @@ def setup(app: Sphinx) -> None:
|
|||||||
"Black",
|
"Black",
|
||||||
"The uncompromising Python code formatter",
|
"The uncompromising Python code formatter",
|
||||||
"Miscellaneous",
|
"Miscellaneous",
|
||||||
)]
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Epub output -------------------------------------------------
|
# -- Options for Epub output -------------------------------------------------
|
||||||
@ -228,14 +227,7 @@ def setup(app: Sphinx) -> None:
|
|||||||
|
|
||||||
autodoc_member_order = "bysource"
|
autodoc_member_order = "bysource"
|
||||||
|
|
||||||
# -- sphinx-copybutton configuration ----------------------------------------
|
|
||||||
copybutton_prompt_text = (
|
|
||||||
r">>> |\.\.\. |> |\$ |\# | In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
|
|
||||||
)
|
|
||||||
copybutton_prompt_is_regexp = True
|
|
||||||
copybutton_remove_prompts = True
|
|
||||||
|
|
||||||
# -- Options for intersphinx extension ---------------------------------------
|
# -- Options for intersphinx extension ---------------------------------------
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {"<name>": ("https://docs.python.org/3/", None)}
|
intersphinx_mapping = {"https://docs.python.org/3/": None}
|
||||||
|
@ -7,52 +7,36 @@ It's recommended you evaluate the quantifiable changes your _Black_ formatting
|
|||||||
modification causes before submitting a PR. Think about if the change seems disruptive
|
modification causes before submitting a PR. Think about if the change seems disruptive
|
||||||
enough to cause frustration to projects that are already "black formatted".
|
enough to cause frustration to projects that are already "black formatted".
|
||||||
|
|
||||||
## diff-shades
|
## black-primer
|
||||||
|
|
||||||
diff-shades is a tool that runs _Black_ across a list of open-source projects recording
|
`black-primer` is a tool built for CI (and humans) to have _Black_ `--check` a number of
|
||||||
the results. The main highlight feature of diff-shades is being able to compare two
|
Git accessible projects in parallel. (configured in `primer.json`) _(A PR will be
|
||||||
revisions of _Black_. This is incredibly useful as it allows us to see what exact
|
accepted to add Mercurial support.)_
|
||||||
changes will occur, say merging a certain PR.
|
|
||||||
|
|
||||||
For more information, please see the [diff-shades documentation][diff-shades].
|
### Run flow
|
||||||
|
|
||||||
### CI integration
|
- Ensure we have a `black` + `git` in PATH
|
||||||
|
- Load projects from `primer.json`
|
||||||
|
- Run projects in parallel with `--worker` workers (defaults to CPU count / 2)
|
||||||
|
- Checkout projects
|
||||||
|
- Run black and record result
|
||||||
|
- Clean up repository checkout _(can optionally be disabled via `--keep`)_
|
||||||
|
- Display results summary to screen
|
||||||
|
- Default to cleaning up `--work-dir` (which defaults to tempfile schemantics)
|
||||||
|
- Return
|
||||||
|
- 0 for successful run
|
||||||
|
- \< 0 for environment / internal error
|
||||||
|
- \> 0 for each project with an error
|
||||||
|
|
||||||
diff-shades is also the tool behind the "diff-shades results comparing ..." /
|
### Speed up runs 🏎
|
||||||
"diff-shades reports zero changes ..." comments on PRs. The project has a GitHub Actions
|
|
||||||
workflow that analyzes and compares two revisions of _Black_ according to these rules:
|
|
||||||
|
|
||||||
| | Baseline revision | Target revision |
|
If you're running locally yourself to test black on lots of code try:
|
||||||
| --------------------- | ----------------------- | ---------------------------- |
|
|
||||||
| On PRs | latest commit on `main` | PR commit with `main` merged |
|
|
||||||
| On pushes (main only) | latest PyPI version | the pushed commit |
|
|
||||||
|
|
||||||
For pushes to main, there's only one analysis job named `preview-changes` where the
|
- Using `-k` / `--keep` + `-w` / `--work-dir` so you don't have to re-checkout the repo
|
||||||
preview style is used for all projects.
|
each run
|
||||||
|
|
||||||
For PRs they get one more analysis job: `assert-no-changes`. It's similar to
|
### CLI arguments
|
||||||
`preview-changes` but runs with the stable code style. It will fail if changes were
|
|
||||||
made. This makes sure code won't be reformatted again and again within the same year in
|
|
||||||
accordance to Black's stability policy.
|
|
||||||
|
|
||||||
Additionally for PRs, a PR comment will be posted embedding a summary of the preview
|
```{program-output} black-primer --help
|
||||||
changes and links to further information. If there's a pre-existing diff-shades comment,
|
|
||||||
it'll be updated instead the next time the workflow is triggered on the same PR.
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
The `preview-changes` job will only fail intentionally if while analyzing a file failed to
|
|
||||||
format. Otherwise a failure indicates a bug in the workflow.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The workflow uploads several artifacts upon completion:
|
|
||||||
|
|
||||||
- The raw analyses (.json)
|
|
||||||
- HTML diffs (.html)
|
|
||||||
- `.pr-comment.json` (if triggered by a PR)
|
|
||||||
|
|
||||||
The last one is downloaded by the `diff-shades-comment` workflow and shouldn't be
|
|
||||||
downloaded locally. The HTML diffs come in handy for push-based where there's no PR to
|
|
||||||
post a comment. And the analyses exist just in case you want to do further analysis
|
|
||||||
using the collected data locally.
|
|
||||||
|
|
||||||
[diff-shades]: https://github.com/ichard26/diff-shades#readme
|
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
# Contributing
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
hidden:
|
|
||||||
---
|
|
||||||
|
|
||||||
the_basics
|
|
||||||
gauging_changes
|
|
||||||
issue_triage
|
|
||||||
release_process
|
|
||||||
```
|
|
||||||
|
|
||||||
Welcome! Happy to see you willing to make the project better. Have you read the entire
|
|
||||||
[user documentation](https://black.readthedocs.io/en/latest/) yet?
|
|
||||||
|
|
||||||
```{rubric} Bird's eye view
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
In terms of inspiration, _Black_ is about as configurable as _gofmt_ (which is to say,
|
|
||||||
not very). This is deliberate. _Black_ aims to provide a consistent style and take away
|
|
||||||
opportunities for arguing about style.
|
|
||||||
|
|
||||||
Bug reports and fixes are always welcome! Please follow the
|
|
||||||
[issue templates on GitHub](https://github.com/psf/black/issues/new/choose) for best
|
|
||||||
results.
|
|
||||||
|
|
||||||
Before you suggest a new feature or configuration knob, ask yourself why you want it. If
|
|
||||||
it enables better integration with some workflow, fixes an inconsistency, speeds things
|
|
||||||
up, and so on - go for it! On the other hand, if your answer is "because I don't like a
|
|
||||||
particular formatting" then you're not ready to embrace _Black_ yet. Such changes are
|
|
||||||
unlikely to get accepted. You can still try but prepare to be disappointed.
|
|
||||||
|
|
||||||
```{rubric} Contents
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
This section covers the following topics:
|
|
||||||
|
|
||||||
- {doc}`the_basics`
|
|
||||||
- {doc}`gauging_changes`
|
|
||||||
- {doc}`release_process`
|
|
||||||
|
|
||||||
For an overview on contributing to the _Black_, please checkout {doc}`the_basics`.
|
|
43
docs/contributing/index.rst
Normal file
43
docs/contributing/index.rst
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Contributing
|
||||||
|
============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
the_basics
|
||||||
|
gauging_changes
|
||||||
|
issue_triage
|
||||||
|
release_process
|
||||||
|
reference/reference_summary
|
||||||
|
|
||||||
|
Welcome! Happy to see you willing to make the project better. Have you read the entire
|
||||||
|
`user documentation <https://black.readthedocs.io/en/latest/>`_ yet?
|
||||||
|
|
||||||
|
.. rubric:: Bird's eye view
|
||||||
|
|
||||||
|
In terms of inspiration, *Black* is about as configurable as *gofmt* (which is to say,
|
||||||
|
not very). This is deliberate. *Black* aims to provide a consistent style and take away
|
||||||
|
opportunities for arguing about style.
|
||||||
|
|
||||||
|
Bug reports and fixes are always welcome! Please follow the
|
||||||
|
`issue template on GitHub <https://github.com/psf/black/issues/new>`_ for best results.
|
||||||
|
|
||||||
|
Before you suggest a new feature or configuration knob, ask yourself why you want it. If
|
||||||
|
it enables better integration with some workflow, fixes an inconsistency, speeds things
|
||||||
|
up, and so on - go for it! On the other hand, if your answer is "because I don't like a
|
||||||
|
particular formatting" then you're not ready to embrace *Black* yet. Such changes are
|
||||||
|
unlikely to get accepted. You can still try but prepare to be disappointed.
|
||||||
|
|
||||||
|
.. rubric:: Contents
|
||||||
|
|
||||||
|
This section covers the following topics:
|
||||||
|
|
||||||
|
- :doc:`the_basics`
|
||||||
|
- :doc:`gauging_changes`
|
||||||
|
- :doc:`release_process`
|
||||||
|
- :doc:`reference/reference_summary`
|
||||||
|
|
||||||
|
For an overview on contributing to the *Black*, please checkout :doc:`the_basics`.
|
||||||
|
|
||||||
|
If you need a reference of the functions, classes, etc. available to you while
|
||||||
|
developing *Black*, there's the :doc:`reference/reference_summary` docs.
|
@ -1,6 +1,6 @@
|
|||||||
# Issue triage
|
# Issue triage
|
||||||
|
|
||||||
Currently, _Black_ uses the issue tracker for bugs, feature requests, proposed style
|
Currently, _Black_ uses the issue tracker for bugs, feature requests, proposed design
|
||||||
modifications, and general user support. Each of these issues have to be triaged so they
|
modifications, and general user support. Each of these issues have to be triaged so they
|
||||||
can be eventually be resolved somehow. This document outlines the triaging process and
|
can be eventually be resolved somehow. This document outlines the triaging process and
|
||||||
also the current guidelines and recommendations.
|
also the current guidelines and recommendations.
|
||||||
@ -42,7 +42,7 @@ The lifecycle of a bug report or user support issue typically goes something lik
|
|||||||
1. _the issue is waiting for triage_
|
1. _the issue is waiting for triage_
|
||||||
2. **identified** - has been marked with a type label and other relevant labels, more
|
2. **identified** - has been marked with a type label and other relevant labels, more
|
||||||
details or a functional reproduction may be still needed (and therefore should be
|
details or a functional reproduction may be still needed (and therefore should be
|
||||||
marked with `S: needs repro` or `S: awaiting response`)
|
marked with `S: needs repro` or `S: awaiting reponse`)
|
||||||
3. **confirmed** - the issue can reproduced and necessary details have been provided
|
3. **confirmed** - the issue can reproduced and necessary details have been provided
|
||||||
4. **discussion** - initial triage has been done and now the general details on how the
|
4. **discussion** - initial triage has been done and now the general details on how the
|
||||||
issue should be best resolved are being hashed out
|
issue should be best resolved are being hashed out
|
||||||
@ -53,13 +53,13 @@ The lifecycle of a bug report or user support issue typically goes something lik
|
|||||||
- the issue has been fixed
|
- the issue has been fixed
|
||||||
- duplicate of another pre-existing issue or is invalid
|
- duplicate of another pre-existing issue or is invalid
|
||||||
|
|
||||||
For enhancement, documentation, and style issues, the lifecycle looks very similar but
|
For enhancement, documentation, and design issues, the lifecycle looks very similar but
|
||||||
the details are different:
|
the details are different:
|
||||||
|
|
||||||
1. _the issue is waiting for triage_
|
1. _the issue is waiting for triage_
|
||||||
2. **identified** - has been marked with a type label and other relevant labels
|
2. **identified** - has been marked with a type label and other relevant labels
|
||||||
3. **discussion** - the merits of the suggested changes are currently being discussed, a
|
3. **discussion** - the merits of the suggested changes are currently being discussed, a
|
||||||
PR would be acceptable but would be at significant risk of being rejected
|
PR would be acceptable but would be at sigificant risk of being rejected
|
||||||
4. **accepted & awaiting PR** - it's been determined the suggested changes are OK and a
|
4. **accepted & awaiting PR** - it's been determined the suggested changes are OK and a
|
||||||
PR would be welcomed (`S: accepted`)
|
PR would be welcomed (`S: accepted`)
|
||||||
5. **closed**: - the issue has been resolved, reasons include:
|
5. **closed**: - the issue has been resolved, reasons include:
|
||||||
|
76
docs/contributing/reference/reference_classes.rst
Normal file
76
docs/contributing/reference/reference_classes.rst
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
*Black* classes
|
||||||
|
===============
|
||||||
|
|
||||||
|
*Contents are subject to change.*
|
||||||
|
|
||||||
|
.. currentmodule:: black
|
||||||
|
|
||||||
|
:class:`BracketTracker`
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. autoclass:: black.brackets.BracketTracker
|
||||||
|
:members:
|
||||||
|
|
||||||
|
:class:`EmptyLineTracker`
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. autoclass:: black.EmptyLineTracker
|
||||||
|
:members:
|
||||||
|
|
||||||
|
:class:`Line`
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. autoclass:: black.Line
|
||||||
|
:members:
|
||||||
|
:special-members: __str__, __bool__
|
||||||
|
|
||||||
|
:class:`LineGenerator`
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. autoclass:: black.LineGenerator
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
||||||
|
|
||||||
|
:class:`ProtoComment`
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
.. autoclass:: black.comments.ProtoComment
|
||||||
|
:members:
|
||||||
|
|
||||||
|
:class:`Report`
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. autoclass:: black.Report
|
||||||
|
:members:
|
||||||
|
:special-members: __str__
|
||||||
|
|
||||||
|
:class:`Visitor`
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. autoclass:: black.nodes.Visitor
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
||||||
|
|
||||||
|
Enums
|
||||||
|
=====
|
||||||
|
|
||||||
|
:class:`Changed`
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. autoclass:: black.Changed
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
||||||
|
|
||||||
|
:class:`Mode`
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. autoclass:: black.Mode
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
||||||
|
|
||||||
|
:class:`WriteBack`
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. autoclass:: black.WriteBack
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
12
docs/contributing/reference/reference_exceptions.rst
Normal file
12
docs/contributing/reference/reference_exceptions.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
*Black* exceptions
|
||||||
|
==================
|
||||||
|
|
||||||
|
*Contents are subject to change.*
|
||||||
|
|
||||||
|
.. currentmodule:: black
|
||||||
|
|
||||||
|
.. autoexception:: black.linegen.CannotSplit
|
||||||
|
|
||||||
|
.. autoexception:: black.NothingChanged
|
||||||
|
|
||||||
|
.. autoexception:: black.InvalidInput
|
178
docs/contributing/reference/reference_functions.rst
Normal file
178
docs/contributing/reference/reference_functions.rst
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
*Black* functions
|
||||||
|
=================
|
||||||
|
|
||||||
|
*Contents are subject to change.*
|
||||||
|
|
||||||
|
.. currentmodule:: black
|
||||||
|
|
||||||
|
Assertions and checks
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
.. autofunction:: black.assert_equivalent
|
||||||
|
|
||||||
|
.. autofunction:: black.assert_stable
|
||||||
|
|
||||||
|
.. autofunction:: black.lines.can_be_split
|
||||||
|
|
||||||
|
.. autofunction:: black.lines.can_omit_invisible_parens
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_empty_tuple
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_import
|
||||||
|
|
||||||
|
.. autofunction:: black.lines.is_line_short_enough
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_multiline_string
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_one_tuple
|
||||||
|
|
||||||
|
.. autofunction:: black.brackets.is_split_after_delimiter
|
||||||
|
|
||||||
|
.. autofunction:: black.brackets.is_split_before_delimiter
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_stub_body
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_stub_suite
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_vararg
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.is_yield
|
||||||
|
|
||||||
|
|
||||||
|
Formatting
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. autofunction:: black.format_file_contents
|
||||||
|
|
||||||
|
.. autofunction:: black.format_file_in_place
|
||||||
|
|
||||||
|
.. autofunction:: black.format_stdin_to_stdout
|
||||||
|
|
||||||
|
.. autofunction:: black.format_str
|
||||||
|
|
||||||
|
.. autofunction:: black.reformat_one
|
||||||
|
|
||||||
|
.. autofunction:: black.schedule_formatting
|
||||||
|
|
||||||
|
File operations
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. autofunction:: black.dump_to_file
|
||||||
|
|
||||||
|
.. autofunction:: black.find_project_root
|
||||||
|
|
||||||
|
.. autofunction:: black.gen_python_files
|
||||||
|
|
||||||
|
.. autofunction:: black.read_pyproject_toml
|
||||||
|
|
||||||
|
Parsing
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. autofunction:: black.decode_bytes
|
||||||
|
|
||||||
|
.. autofunction:: black.parsing.lib2to3_parse
|
||||||
|
|
||||||
|
.. autofunction:: black.parsing.lib2to3_unparse
|
||||||
|
|
||||||
|
Split functions
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.bracket_split_build_line
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.bracket_split_succeeded_or_raise
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.delimiter_split
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.left_hand_split
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.right_hand_split
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.standalone_comment_split
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.transform_line
|
||||||
|
|
||||||
|
Caching
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. autofunction:: black.cache.filter_cached
|
||||||
|
|
||||||
|
.. autofunction:: black.cache.get_cache_file
|
||||||
|
|
||||||
|
.. autofunction:: black.cache.get_cache_info
|
||||||
|
|
||||||
|
.. autofunction:: black.cache.read_cache
|
||||||
|
|
||||||
|
.. autofunction:: black.cache.write_cache
|
||||||
|
|
||||||
|
Utilities
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. py:function:: black.debug.DebugVisitor.show(code: str) -> None
|
||||||
|
|
||||||
|
Pretty-print the lib2to3 AST of a given string of `code`.
|
||||||
|
|
||||||
|
.. autofunction:: black.concurrency.cancel
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.child_towards
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.container_of
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.convert_one_fmt_off_pair
|
||||||
|
|
||||||
|
.. autofunction:: black.diff
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.dont_increase_indentation
|
||||||
|
|
||||||
|
.. autofunction:: black.numerics.format_float_or_int_string
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.ensure_visible
|
||||||
|
|
||||||
|
.. autofunction:: black.lines.enumerate_reversed
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.generate_comments
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.generate_ignored_nodes
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.is_fmt_on
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.contains_fmt_on_at_column
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.first_leaf_column
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.generate_trailers_to_omit
|
||||||
|
|
||||||
|
.. autofunction:: black.get_future_imports
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.list_comments
|
||||||
|
|
||||||
|
.. autofunction:: black.comments.make_comment
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.maybe_make_parens_invisible_in_atom
|
||||||
|
|
||||||
|
.. autofunction:: black.brackets.max_delimiter_priority_in_atom
|
||||||
|
|
||||||
|
.. autofunction:: black.normalize_fmt_off
|
||||||
|
|
||||||
|
.. autofunction:: black.numerics.normalize_numeric_literal
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.normalize_prefix
|
||||||
|
|
||||||
|
.. autofunction:: black.strings.normalize_string_prefix
|
||||||
|
|
||||||
|
.. autofunction:: black.strings.normalize_string_quotes
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.normalize_invisible_parens
|
||||||
|
|
||||||
|
.. autofunction:: black.patch_click
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.preceding_leaf
|
||||||
|
|
||||||
|
.. autofunction:: black.re_compile_maybe_verbose
|
||||||
|
|
||||||
|
.. autofunction:: black.linegen.should_split_line
|
||||||
|
|
||||||
|
.. autofunction:: black.shutdown
|
||||||
|
|
||||||
|
.. autofunction:: black.strings.sub_twice
|
||||||
|
|
||||||
|
.. autofunction:: black.nodes.whitespace
|
16
docs/contributing/reference/reference_summary.rst
Normal file
16
docs/contributing/reference/reference_summary.rst
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Developer reference
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The documentation here is quite outdated and has been neglected. Many objects worthy
|
||||||
|
of inclusion aren't documented. Contributions are appreciated!
|
||||||
|
|
||||||
|
*Contents are subject to change.*
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
reference_classes
|
||||||
|
reference_functions
|
||||||
|
reference_exceptions
|
@ -1,174 +1,89 @@
|
|||||||
# Release process
|
# Release process
|
||||||
|
|
||||||
_Black_ has had a lot of work done into standardizing and automating its release
|
_Black_ has had a lot of work automating its release process. This document sets out to
|
||||||
process. This document sets out to explain how everything works and how to release
|
explain what everything does and how to release _Black_ using said automation.
|
||||||
_Black_ using said automation.
|
|
||||||
|
|
||||||
## Release cadence
|
## Cutting a Release
|
||||||
|
|
||||||
**We aim to release whatever is on `main` every 1-2 months.** This ensures merged
|
To cut a release, you must be a _Black_ maintainer with `GitHub Release` creation
|
||||||
improvements and bugfixes are shipped to users reasonably quickly, while not massively
|
access. Using this access, the release process is:
|
||||||
fracturing the user-base with too many versions. This also keeps the workload on
|
|
||||||
maintainers consistent and predictable.
|
|
||||||
|
|
||||||
If there's not much new on `main` to justify a release, it's acceptable to skip a
|
1. Cut a new PR editing `CHANGES.md` to version the latest changes
|
||||||
month's release. Ideally January releases should not be skipped because as per our
|
1. Example PR: https://github.com/psf/black/pull/2192
|
||||||
[stability policy](labels/stability-policy), the first release in a new calendar year
|
2. Example title: `Update CHANGES.md for XX.X release`
|
||||||
may make changes to the _stable_ style. While the policy applies to the first release
|
2. Once the release PR is merged ensure all CI passes
|
||||||
(instead of only January releases), confining changes to the stable style to January
|
1. If not, ensure there is an Issue open for the cause of failing CI (generally we'd
|
||||||
will keep things predictable (and nicer) for users.
|
want this fixed before cutting a release)
|
||||||
|
3. Open `CHANGES.md` and copy the _raw markdown_ of the latest changes to use in the
|
||||||
|
description of the GitHub Release.
|
||||||
|
4. Go and [cut a release](https://github.com/psf/black/releases) using the GitHub UI so
|
||||||
|
that all workflows noted below are triggered.
|
||||||
|
1. The release version and tag should be the [CalVer](https://calver.org) version
|
||||||
|
_Black_ used for the current release e.g. `21.6` / `21.5b1`
|
||||||
|
2. _Black_ uses [setuptools scm](https://pypi.org/project/setuptools-scm/) to pull
|
||||||
|
the current version for the package builds and release.
|
||||||
|
5. Once the release is cut, you're basically done. It's a good practice to go and watch
|
||||||
|
to make sure all the [GitHub Actions](https://github.com/psf/black/actions) pass,
|
||||||
|
although you should receive an email to your registered GitHub email address should
|
||||||
|
one fail.
|
||||||
|
1. You should see all the release workflows and lint/unittests workflows running on
|
||||||
|
the new tag in the Actions UI
|
||||||
|
|
||||||
Unless there is a serious regression or bug that requires immediate patching, **there
|
If anything fails, please go read the respective action's log output and configuration
|
||||||
should not be more than one release per month**. While version numbers are cheap,
|
file to reverse engineer your way to a fix/soluton.
|
||||||
releases require a maintainer to both commit to do the actual cutting of a release, but
|
|
||||||
also to be able to deal with the potential fallout post-release. Releasing more
|
|
||||||
frequently than monthly nets rapidly diminishing returns.
|
|
||||||
|
|
||||||
## Cutting a release
|
|
||||||
|
|
||||||
**You must have `write` permissions for the _Black_ repository to cut a release.**
|
|
||||||
|
|
||||||
The 10,000 foot view of the release process is that you prepare a release PR and then
|
|
||||||
publish a [GitHub Release]. This triggers [release automation](#release-workflows) that
|
|
||||||
builds all release artifacts and publishes them to the various platforms we publish to.
|
|
||||||
|
|
||||||
We now have a `scripts/release.py` script to help with cutting the release PRs.
|
|
||||||
|
|
||||||
- `python3 scripts/release.py --help` is your friend.
|
|
||||||
- `release.py` has only been tested in Python 3.12 (so get with the times :D)
|
|
||||||
|
|
||||||
To cut a release:
|
|
||||||
|
|
||||||
1. Determine the release's version number
|
|
||||||
- **_Black_ follows the [CalVer] versioning standard using the `YY.M.N` format**
|
|
||||||
- So unless there already has been a release during this month, `N` should be `0`
|
|
||||||
- Example: the first release in January, 2022 → `22.1.0`
|
|
||||||
- `release.py` will calculate this and log to stderr for you copy paste pleasure
|
|
||||||
1. File a PR editing `CHANGES.md` and the docs to version the latest changes
|
|
||||||
- Run `python3 scripts/release.py [--debug]` to generate most changes
|
|
||||||
- Sub headings in the template, if they have no bullet points need manual removal
|
|
||||||
_PR welcome to improve :D_
|
|
||||||
1. If `release.py` fail manually edit; otherwise, yay, skip this step!
|
|
||||||
1. Replace the `## Unreleased` header with the version number
|
|
||||||
1. Remove any empty sections for the current release
|
|
||||||
1. (_optional_) Read through and copy-edit the changelog (eg. by moving entries,
|
|
||||||
fixing typos, or rephrasing entries)
|
|
||||||
1. Double-check that no changelog entries since the last release were put in the
|
|
||||||
wrong section (e.g., run `git diff <last release> CHANGES.md`)
|
|
||||||
1. Update references to the latest version in
|
|
||||||
{doc}`/integrations/source_version_control` and
|
|
||||||
{doc}`/usage_and_configuration/the_basics`
|
|
||||||
- Example PR: [GH-3139]
|
|
||||||
1. Once the release PR is merged, wait until all CI passes
|
|
||||||
- If CI does not pass, **stop** and investigate the failure(s) as generally we'd want
|
|
||||||
to fix failing CI before cutting a release
|
|
||||||
1. [Draft a new GitHub Release][new-release]
|
|
||||||
1. Click `Choose a tag` and type in the version number, then select the
|
|
||||||
`Create new tag: YY.M.N on publish` option that appears
|
|
||||||
1. Verify that the new tag targets the `main` branch
|
|
||||||
1. You can leave the release title blank, GitHub will default to the tag name
|
|
||||||
1. Copy and paste the _raw changelog Markdown_ for the current release into the
|
|
||||||
description box
|
|
||||||
1. Publish the GitHub Release, triggering [release automation](#release-workflows) that
|
|
||||||
will handle the rest
|
|
||||||
1. Once CI is done add + commit (git push - No review) a new empty template for the next
|
|
||||||
release to CHANGES.md _(Template is able to be copy pasted from release.py should we
|
|
||||||
fail)_
|
|
||||||
1. `python3 scripts/release.py --add-changes-template|-a [--debug]`
|
|
||||||
1. Should that fail, please return to copy + paste
|
|
||||||
1. At this point, you're basically done. It's good practice to go and [watch and verify
|
|
||||||
that all the release workflows pass][black-actions], although you will receive a
|
|
||||||
GitHub notification should something fail.
|
|
||||||
- If something fails, don't panic. Please go read the respective workflow's logs and
|
|
||||||
configuration file to reverse-engineer your way to a fix/solution.
|
|
||||||
|
|
||||||
Congratulations! You've successfully cut a new release of _Black_. Go and stand up and
|
|
||||||
take a break, you deserve it.
|
|
||||||
|
|
||||||
```{important}
|
|
||||||
Once the release artifacts reach PyPI, you may see new issues being filed indicating
|
|
||||||
regressions. While regressions are not great, they don't automatically mean a hotfix
|
|
||||||
release is warranted. Unless the regressions are serious and impact many users, a hotfix
|
|
||||||
release is probably unnecessary.
|
|
||||||
|
|
||||||
In the end, use your best judgement and ask other maintainers for their thoughts.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Release workflows
|
## Release workflows
|
||||||
|
|
||||||
All of _Black_'s release automation uses [GitHub Actions]. All workflows are therefore
|
All _Blacks_'s automation workflows use GitHub Actions. All workflows are therefore
|
||||||
configured using YAML files in the `.github/workflows` directory of the _Black_
|
configured using `.yml` files in the `.github/workflows` directory of the _Black_
|
||||||
repository.
|
repository.
|
||||||
|
|
||||||
They are triggered by the publication of a [GitHub Release].
|
|
||||||
|
|
||||||
Below are descriptions of our release workflows.
|
Below are descriptions of our release workflows.
|
||||||
|
|
||||||
### Publish to PyPI
|
### Docker
|
||||||
|
|
||||||
This is our main workflow. It builds an [sdist] and [wheels] to upload to PyPI where the
|
This workflow uses the QEMU powered `buildx` feature of docker to upload a `arm64` and
|
||||||
vast majority of users will download Black from. It's divided into three job groups:
|
`amd64`/`x86_64` build of the official _Black_ docker image™.
|
||||||
|
|
||||||
#### sdist + pure wheel
|
- Currently this workflow uses an API Token associated with @cooperlees account
|
||||||
|
|
||||||
This single job builds the sdist and pure Python wheel (i.e., a wheel that only contains
|
### pypi_upload
|
||||||
Python code) using [build] and then uploads them to PyPI using [twine]. These artifacts
|
|
||||||
are general-purpose and can be used on basically any platform supported by Python.
|
|
||||||
|
|
||||||
#### mypyc wheels (…)
|
This workflow builds a Python
|
||||||
|
[sdist](https://docs.python.org/3/distutils/sourcedist.html) and
|
||||||
|
[wheel](https://pythonwheels.com) using the latest
|
||||||
|
[setuptools](https://pypi.org/project/setuptools/) and
|
||||||
|
[wheel](https://pypi.org/project/wheel/) modules.
|
||||||
|
|
||||||
We use [mypyc] to compile _Black_ into a CPython C extension for significantly improved
|
It will then use [twine](https://pypi.org/project/twine/) to upload both release formats
|
||||||
performance. Wheels built with mypyc are platform and Python version specific.
|
to PyPI for general downloading of the _Black_ Python package. This is where
|
||||||
[Supported platforms are documented in the FAQ](labels/mypyc-support).
|
[pip](https://pypi.org/project/pip/) looks by default.
|
||||||
|
|
||||||
These matrix jobs use [cibuildwheel] which handles the complicated task of building C
|
- Currently this workflow uses an API token associated with @ambv's PyPI account
|
||||||
extensions for many environments for us. Since building these wheels is slow, there are
|
|
||||||
multiple mypyc wheels jobs (hence the term "matrix") that build for a specific platform
|
|
||||||
(as noted in the job name in parentheses).
|
|
||||||
|
|
||||||
Like the previous job group, the built wheels are uploaded to PyPI using [twine].
|
### Upload self-contained binaries
|
||||||
|
|
||||||
#### Update stable branch
|
This workflow builds self-contained binaries for multiple platforms. This allows people
|
||||||
|
to download the executable for their platform and run _Black_ without a
|
||||||
|
[Python Runtime](https://wiki.python.org/moin/PythonImplementations) installed.
|
||||||
|
|
||||||
So this job doesn't _really_ belong here, but updating the `stable` branch after the
|
The created binaries are attached/stored on the associated
|
||||||
other PyPI jobs pass (they must pass for this job to start) makes the most sense. This
|
[GitHub Release](https://github.com/psf/black/releases) for download over _IPv4 only_
|
||||||
saves us from remembering to update the branch sometime after cutting the release.
|
(GitHub still does not have IPv6 access 😢).
|
||||||
|
|
||||||
- _Currently this workflow uses an API token associated with @ambv's PyPI account_
|
## Moving the `stable` tag
|
||||||
|
|
||||||
### Publish executables
|
_Black_ provides a stable tag for people who want to move along as _Black_ developers
|
||||||
|
deem the newest version reliable. Here the _Black_ developers will move once the release
|
||||||
|
has been problem free for at least ~24 hours from release. Given the large _Black_
|
||||||
|
userbase we hear about bad bugs quickly. We do strive to continually improve our CI too.
|
||||||
|
|
||||||
This workflow builds native executables for multiple platforms using [PyInstaller]. This
|
### Tag moving process
|
||||||
allows people to download the executable for their platform and run _Black_ without a
|
|
||||||
[Python runtime](https://wiki.python.org/moin/PythonImplementations) installed.
|
|
||||||
|
|
||||||
The created binaries are stored on the associated GitHub Release for download over _IPv4
|
#### stable
|
||||||
only_ (GitHub still does not have IPv6 access 😢).
|
|
||||||
|
|
||||||
### docker
|
From a rebased `main` checkout:
|
||||||
|
|
||||||
This workflow uses the QEMU powered `buildx` feature of Docker to upload an `arm64` and
|
1. `git tag -f stable VERSION_TAG`
|
||||||
`amd64`/`x86_64` build of the official _Black_ Docker image™.
|
1. e.g. `git tag -f stable 21.5b1`
|
||||||
|
1. `git push --tags -f`
|
||||||
- _Currently this workflow uses an API Token associated with @cooperlees account_
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
This also runs on each push to `main`.
|
|
||||||
```
|
|
||||||
|
|
||||||
[black-actions]: https://github.com/psf/black/actions
|
|
||||||
[build]: https://pypa-build.readthedocs.io/
|
|
||||||
[calver]: https://calver.org
|
|
||||||
[cibuildwheel]: https://cibuildwheel.readthedocs.io/
|
|
||||||
[gh-3139]: https://github.com/psf/black/pull/3139
|
|
||||||
[github actions]: https://github.com/features/actions
|
|
||||||
[github release]: https://github.com/psf/black/releases
|
|
||||||
[new-release]: https://github.com/psf/black/releases/new
|
|
||||||
[mypyc]: https://mypyc.readthedocs.io/
|
|
||||||
[mypyc-platform-support]:
|
|
||||||
/faq.html#what-is-compiled-yes-no-all-about-in-the-version-output
|
|
||||||
[pyinstaller]: https://www.pyinstaller.org/
|
|
||||||
[sdist]:
|
|
||||||
https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist
|
|
||||||
[twine]: https://github.com/features/actions
|
|
||||||
[wheels]: https://packaging.python.org/en/latest/glossary/#term-Wheel
|
|
||||||
|
@ -4,27 +4,26 @@ An overview on contributing to the _Black_ project.
|
|||||||
|
|
||||||
## Technicalities
|
## Technicalities
|
||||||
|
|
||||||
Development on the latest version of Python is preferred. You can use any operating
|
Development on the latest version of Python is preferred. As of this writing it's 3.9.
|
||||||
system.
|
You can use any operating system.
|
||||||
|
|
||||||
First clone the _Black_ repository:
|
Install all development dependencies using:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ git clone https://github.com/psf/black.git
|
$ pipenv install --dev
|
||||||
$ cd black
|
$ pipenv shell
|
||||||
|
$ pre-commit install
|
||||||
```
|
```
|
||||||
|
|
||||||
Then install development dependencies inside a virtual environment of your choice, for
|
If you haven't used `pipenv` before but are comfortable with virtualenvs, just run
|
||||||
example:
|
`pip install pipenv` in the virtualenv you're already using and invoke the command above
|
||||||
|
from the cloned _Black_ repo. It will do the correct thing.
|
||||||
|
|
||||||
|
Non pipenv install works too:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ python3 -m venv .venv
|
$ pip install -r test_requirements.txt
|
||||||
$ source .venv/bin/activate # activation for linux and mac
|
$ pip install -e .[d]
|
||||||
$ .venv\Scripts\activate # activation for windows
|
|
||||||
|
|
||||||
(.venv)$ pip install -r test_requirements.txt
|
|
||||||
(.venv)$ pip install -e ".[d]"
|
|
||||||
(.venv)$ pre-commit install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Before submitting pull requests, run lints and tests with the following commands from
|
Before submitting pull requests, run lints and tests with the following commands from
|
||||||
@ -32,125 +31,69 @@ the root of the black repo:
|
|||||||
|
|
||||||
```console
|
```console
|
||||||
# Linting
|
# Linting
|
||||||
(.venv)$ pre-commit run -a
|
$ pre-commit run -a
|
||||||
|
|
||||||
# Unit tests
|
# Unit tests
|
||||||
(.venv)$ tox -e py
|
$ tox -e py
|
||||||
|
|
||||||
# Optional Fuzz testing
|
# Optional Fuzz testing
|
||||||
(.venv)$ tox -e fuzz
|
$ tox -e fuzz
|
||||||
|
|
||||||
# Format Black itself
|
# Optional CI run to test your changes on many popular python projects
|
||||||
(.venv)$ tox -e run_self
|
$ black-primer [-k -w /tmp/black_test_repos]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Development
|
|
||||||
|
|
||||||
Further examples of invoking the tests
|
|
||||||
|
|
||||||
```console
|
|
||||||
# Run all of the above mentioned, in parallel
|
|
||||||
(.venv)$ tox --parallel=auto
|
|
||||||
|
|
||||||
# Run tests on a specific python version
|
|
||||||
(.venv)$ tox -e py39
|
|
||||||
|
|
||||||
# Run an individual test
|
|
||||||
(.venv)$ pytest -k <test name>
|
|
||||||
|
|
||||||
# Pass arguments to pytest
|
|
||||||
(.venv)$ tox -e py -- --no-cov
|
|
||||||
|
|
||||||
# Print full tree diff, see documentation below
|
|
||||||
(.venv)$ tox -e py -- --print-full-tree
|
|
||||||
|
|
||||||
# Disable diff printing, see documentation below
|
|
||||||
(.venv)$ tox -e py -- --print-tree-diff=False
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
All aspects of the _Black_ style should be tested. Normally, tests should be created as
|
|
||||||
files in the `tests/data/cases` directory. These files consist of up to three parts:
|
|
||||||
|
|
||||||
- A line that starts with `# flags: ` followed by a set of command-line options. For
|
|
||||||
example, if the line is `# flags: --preview --skip-magic-trailing-comma`, the test
|
|
||||||
case will be run with preview mode on and the magic trailing comma off. The options
|
|
||||||
accepted are mostly a subset of those of _Black_ itself, except for the
|
|
||||||
`--minimum-version=` flag, which should be used when testing a grammar feature that
|
|
||||||
works only in newer versions of Python. This flag ensures that we don't try to
|
|
||||||
validate the AST on older versions and tests that we autodetect the Python version
|
|
||||||
correctly when the feature is used. For the exact flags accepted, see the function
|
|
||||||
`get_flags_parser` in `tests/util.py`. If this line is omitted, the default options
|
|
||||||
are used.
|
|
||||||
- A block of Python code used as input for the formatter.
|
|
||||||
- The line `# output`, followed by the output of _Black_ when run on the previous block.
|
|
||||||
If this is omitted, the test asserts that _Black_ will leave the input code unchanged.
|
|
||||||
|
|
||||||
_Black_ has two pytest command-line options affecting test files in `tests/data/` that
|
|
||||||
are split into an input part, and an output part, separated by a line with`# output`.
|
|
||||||
These can be passed to `pytest` through `tox`, or directly into pytest if not using
|
|
||||||
`tox`.
|
|
||||||
|
|
||||||
#### `--print-full-tree`
|
|
||||||
|
|
||||||
Upon a failing test, print the full concrete syntax tree (CST) as it is after processing
|
|
||||||
the input ("actual"), and the tree that's yielded after parsing the output ("expected").
|
|
||||||
Note that a test can fail with different output with the same CST. This used to be the
|
|
||||||
default, but now defaults to `False`.
|
|
||||||
|
|
||||||
#### `--print-tree-diff`
|
|
||||||
|
|
||||||
Upon a failing test, print the diff of the trees as described above. This is the
|
|
||||||
default. To turn it off pass `--print-tree-diff=False`.
|
|
||||||
|
|
||||||
### News / Changelog Requirement
|
### News / Changelog Requirement
|
||||||
|
|
||||||
`Black` has CI that will check for an entry corresponding to your PR in `CHANGES.md`. If
|
`Black` has CI that will check for an entry corresponding to your PR in `CHANGES.md`. If
|
||||||
you feel this PR does not require a changelog entry please state that in a comment and a
|
you feel this PR does not require a changelog entry please state that in a comment and a
|
||||||
maintainer can add a `skip news` label to make the CI pass. Otherwise, please ensure you
|
maintainer can add a `skip news` label to make the CI pass. Otherwise, please ensure you
|
||||||
have a line in the following format added below the appropriate header:
|
have a line in the following format:
|
||||||
|
|
||||||
```md
|
```md
|
||||||
- `Black` is now more awesome (#X)
|
- `Black` is now more awesome (#X)
|
||||||
```
|
```
|
||||||
|
|
||||||
<!---
|
|
||||||
The Next PR Number link uses HTML because of a bug in MyST-Parser that double-escapes the ampersand, causing the query parameters to not be processed.
|
|
||||||
MyST-Parser issue: https://github.com/executablebooks/MyST-Parser/issues/760
|
|
||||||
MyST-Parser stalled fix PR: https://github.com/executablebooks/MyST-Parser/pull/929
|
|
||||||
-->
|
|
||||||
|
|
||||||
Note that X should be your PR number, not issue number! To workout X, please use
|
Note that X should be your PR number, not issue number! To workout X, please use
|
||||||
<a href="https://ichard26.github.io/next-pr-number/?owner=psf&name=black">Next PR
|
[Next PR Number](https://ichard26.github.io/next-pr-number/?owner=psf&name=black). This
|
||||||
Number</a>. This is not perfect but saves a lot of release overhead as now the releaser
|
is not perfect but saves a lot of release overhead as now the releaser does not need to
|
||||||
does not need to go back and workout what to add to the `CHANGES.md` for each release.
|
go back and workout what to add to the `CHANGES.md` for each release.
|
||||||
|
|
||||||
### Style Changes
|
### Style Changes
|
||||||
|
|
||||||
If a change would affect the advertised code style, please modify the documentation (The
|
If a change would affect the advertised code style, please modify the documentation (The
|
||||||
_Black_ code style) to reflect that change. Patches that fix unintended bugs in
|
_Black_ code style) to reflect that change. Patches that fix unintended bugs in
|
||||||
formatting don't need to be mentioned separately though. If the change is implemented
|
formatting don't need to be mentioned separately though.
|
||||||
with the `--preview` flag, please include the change in the future style document
|
|
||||||
instead and write the changelog entry under the dedicated "Preview style" heading.
|
|
||||||
|
|
||||||
### Docs Testing
|
### Docs Testing
|
||||||
|
|
||||||
If you make changes to docs, you can test they still build locally too.
|
If you make changes to docs, you can test they still build locally too.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
(.venv)$ pip install -r docs/requirements.txt
|
$ pip install -r docs/requirements.txt
|
||||||
(.venv)$ pip install -e ".[d]"
|
$ pip install [-e] .[d]
|
||||||
(.venv)$ sphinx-build -a -b html -W docs/ docs/_build/
|
$ sphinx-build -a -b html -W docs/ docs/_build/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## black-primer
|
||||||
|
|
||||||
|
`black-primer` is used by CI to pull down well-known _Black_ formatted projects and see
|
||||||
|
if we get source code changes. It will error on formatting changes or errors. Please run
|
||||||
|
before pushing your PR to see if you get the actions you would expect from _Black_ with
|
||||||
|
your PR. You may need to change
|
||||||
|
[primer.json](https://github.com/psf/black/blob/main/src/black_primer/primer.json)
|
||||||
|
configuration for it to pass.
|
||||||
|
|
||||||
|
For more `black-primer` information visit the
|
||||||
|
[documentation](./gauging_changes.md#black-primer).
|
||||||
|
|
||||||
## Hygiene
|
## Hygiene
|
||||||
|
|
||||||
If you're fixing a bug, add a test. Run it first to confirm it fails, then fix the bug,
|
If you're fixing a bug, add a test. Run it first to confirm it fails, then fix the bug,
|
||||||
and run the test again to confirm it's really fixed.
|
run it again to confirm it's really fixed.
|
||||||
|
|
||||||
If adding a new feature, add a test. In fact, always add a test. If adding a large
|
If adding a new feature, add a test. In fact, always add a test. But wait, before adding
|
||||||
feature, please first open an issue to discuss it beforehand.
|
any large feature, first open an issue for us to discuss the idea first.
|
||||||
|
|
||||||
## Finally
|
## Finally
|
||||||
|
|
||||||
|
93
docs/faq.md
93
docs/faq.md
@ -5,32 +5,20 @@ The most common questions and issues users face are aggregated to this FAQ.
|
|||||||
```{contents}
|
```{contents}
|
||||||
:local:
|
:local:
|
||||||
:backlinks: none
|
:backlinks: none
|
||||||
:class: this-will-duplicate-information-and-it-is-still-useful-here
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Why spaces? I prefer tabs
|
|
||||||
|
|
||||||
PEP 8 recommends spaces over tabs, and they are used by most of the Python community.
|
|
||||||
_Black_ provides no options to configure the indentation style, and requests for such
|
|
||||||
options will not be considered.
|
|
||||||
|
|
||||||
However, we recognise that using tabs is an accessibility issue as well. While the
|
|
||||||
option will never be added to _Black_, visually impaired developers may find conversion
|
|
||||||
tools such as `expand/unexpand` (for Linux) useful when contributing to Python projects.
|
|
||||||
A workflow might consist of e.g. setting up appropriate pre-commit and post-merge git
|
|
||||||
hooks, and scripting `unexpand` to run after applying _Black_.
|
|
||||||
|
|
||||||
## Does Black have an API?
|
## Does Black have an API?
|
||||||
|
|
||||||
Not yet. _Black_ is fundamentally a command line tool. Many
|
Not yet. _Black_ is fundamentally a command line tool. Many
|
||||||
[integrations](/integrations/index.md) are provided, but a Python interface is not one
|
[integrations](integrations/index.rst) are provided, but a Python interface is not one
|
||||||
of them. A simple API is being [planned](https://github.com/psf/black/issues/779)
|
of them. A simple API is being [planned](https://github.com/psf/black/issues/779)
|
||||||
though.
|
though.
|
||||||
|
|
||||||
## Is Black safe to use?
|
## Is Black safe to use?
|
||||||
|
|
||||||
Yes. _Black_ is strictly about formatting, nothing else. Black strives to ensure that
|
Yes, for the most part. _Black_ is strictly about formatting, nothing else. But because
|
||||||
after formatting the AST is
|
_Black_ is still in [beta](index.rst), some edges are still a bit rough. To combat
|
||||||
|
issues, the equivalence of code after formatting is
|
||||||
[checked](the_black_code_style/current_style.md#ast-before-and-after-formatting) with
|
[checked](the_black_code_style/current_style.md#ast-before-and-after-formatting) with
|
||||||
limited special cases where the code is allowed to differ. If issues are found, an error
|
limited special cases where the code is allowed to differ. If issues are found, an error
|
||||||
is raised and the file is left untouched. Magical comments that influence linters and
|
is raised and the file is left untouched. Magical comments that influence linters and
|
||||||
@ -38,13 +26,10 @@ other tools, such as `# noqa`, may be moved by _Black_. See below for more detai
|
|||||||
|
|
||||||
## How stable is Black's style?
|
## How stable is Black's style?
|
||||||
|
|
||||||
Stable. _Black_ aims to enforce one style and one style only, with some room for
|
Quite stable. _Black_ aims to enforce one style and one style only, with some room for
|
||||||
pragmatism. See [The Black Code Style](the_black_code_style/index.md) for more details.
|
pragmatism. However, _Black_ is still in beta so style changes are both planned and
|
||||||
|
still proposed on the issue tracker. See
|
||||||
Starting in 2022, the formatting output is stable for the releases made in the same year
|
[The Black Code Style](the_black_code_style/index.rst) for more details.
|
||||||
(other than unintentional bugs). At the beginning of every year, the first release will
|
|
||||||
make changes to the stable style. It is possible to opt in to the latest formatting
|
|
||||||
styles using the `--preview` flag.
|
|
||||||
|
|
||||||
## Why is my file not formatted?
|
## Why is my file not formatted?
|
||||||
|
|
||||||
@ -58,8 +43,6 @@ _Black_ is timid about formatting Jupyter Notebooks. Cells containing any of the
|
|||||||
following will not be formatted:
|
following will not be formatted:
|
||||||
|
|
||||||
- automagics (e.g. `pip install black`)
|
- automagics (e.g. `pip install black`)
|
||||||
- non-Python cell magics (e.g. `%%writefile`). These can be added with the flag
|
|
||||||
`--python-cell-magics`, e.g. `black --python-cell-magics writefile hello.ipynb`.
|
|
||||||
- multiline magics, e.g.:
|
- multiline magics, e.g.:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@ -77,26 +60,20 @@ following will not be formatted:
|
|||||||
- invalid syntax, as it can't be safely distinguished from automagics in the absence of
|
- invalid syntax, as it can't be safely distinguished from automagics in the absence of
|
||||||
a running `IPython` kernel.
|
a running `IPython` kernel.
|
||||||
|
|
||||||
## Why does Flake8 report warnings?
|
## Why are Flake8's E203 and W503 violated?
|
||||||
|
|
||||||
Some of Flake8's rules conflict with Black's style. We recommend disabling these rules.
|
Because they go against PEP 8. E203 falsely triggers on list
|
||||||
See [Using _Black_ with other tools](labels/why-pycodestyle-warnings).
|
[slices](the_black_code_style/current_style.md#slices), and adhering to W503 hinders
|
||||||
|
readability because operators are misaligned. Disable W503 and enable the
|
||||||
|
disabled-by-default counterpart W504. E203 should be disabled while changes are still
|
||||||
|
[discussed](https://github.com/PyCQA/pycodestyle/issues/373).
|
||||||
|
|
||||||
## Which Python versions does Black support?
|
## Does Black support Python 2?
|
||||||
|
|
||||||
_Black_ generally supports all Python versions supported by CPython (see
|
For formatting, yes! [Install](getting_started.md#installation) with the `python2` extra
|
||||||
[the Python devguide](https://devguide.python.org/versions/) for current information).
|
to format Python 2 files too! There are no current plans to drop support, but most
|
||||||
We promise to support at least all Python versions that have not reached their end of
|
likely it is bound to happen. Sometime. Eventually. In terms of running _Black_ though,
|
||||||
life. This is the case for both running _Black_ and formatting code.
|
Python 3.6 or newer is required.
|
||||||
|
|
||||||
Support for formatting Python 2 code was removed in version 22.0. While we've made no
|
|
||||||
plans to stop supporting older Python 3 minor versions immediately, their support might
|
|
||||||
also be removed some time in the future without a deprecation period.
|
|
||||||
|
|
||||||
`await`/`async` as soft keywords/indentifiers are no longer supported as of 25.2.0.
|
|
||||||
|
|
||||||
Runtime support for 3.6 was removed in version 22.10.0, for 3.7 in version 23.7.0, and
|
|
||||||
for 3.8 in version 24.10.0.
|
|
||||||
|
|
||||||
## Why does my linter or typechecker complain after I format my code?
|
## Why does my linter or typechecker complain after I format my code?
|
||||||
|
|
||||||
@ -105,35 +82,3 @@ influence their behavior. While Black does its best to recognize such comments a
|
|||||||
them in the right place, this detection is not and cannot be perfect. Therefore, you'll
|
them in the right place, this detection is not and cannot be perfect. Therefore, you'll
|
||||||
sometimes have to manually move these comments to the right place after you format your
|
sometimes have to manually move these comments to the right place after you format your
|
||||||
codebase with _Black_.
|
codebase with _Black_.
|
||||||
|
|
||||||
## Can I run Black with PyPy?
|
|
||||||
|
|
||||||
Yes, there is support for PyPy 3.8 and higher.
|
|
||||||
|
|
||||||
## Why does Black not detect syntax errors in my code?
|
|
||||||
|
|
||||||
_Black_ is an autoformatter, not a Python linter or interpreter. Detecting all syntax
|
|
||||||
errors is not a goal. It can format all code accepted by CPython (if you find an example
|
|
||||||
where that doesn't hold, please report a bug!), but it may also format some code that
|
|
||||||
CPython doesn't accept.
|
|
||||||
|
|
||||||
(labels/mypyc-support)=
|
|
||||||
|
|
||||||
## What is `compiled: yes/no` all about in the version output?
|
|
||||||
|
|
||||||
While _Black_ is indeed a pure Python project, we use [mypyc] to compile _Black_ into a
|
|
||||||
C Python extension, usually doubling performance. These compiled wheels are available
|
|
||||||
for 64-bit versions of Windows, Linux (via the manylinux standard), and macOS across all
|
|
||||||
supported CPython versions.
|
|
||||||
|
|
||||||
Platforms including musl-based and/or ARM Linux distributions, and ARM Windows are
|
|
||||||
currently **not** supported. These platforms will fall back to the slower pure Python
|
|
||||||
wheel available on PyPI.
|
|
||||||
|
|
||||||
If you are experiencing exceptionally weird issues or even segfaults, you can try
|
|
||||||
passing `--no-binary black` to your pip install invocation. This flag excludes all
|
|
||||||
wheels (including the pure Python wheel), so this command will use the [sdist].
|
|
||||||
|
|
||||||
[mypyc]: https://mypyc.readthedocs.io/en/latest/
|
|
||||||
[sdist]:
|
|
||||||
https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist
|
|
||||||
|
@ -16,14 +16,14 @@ Also, you can try out _Black_ online for minimal fuss on the
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
_Black_ can be installed by running `pip install black`. It requires Python 3.9+ to run.
|
_Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
|
||||||
If you want to format Jupyter Notebooks, install with `pip install "black[jupyter]"`.
|
run, but can format Python 2 code too. Python 2 support needs the `typed_ast`
|
||||||
|
dependency, which be installed with `pip install black[python2]`. If you want to format
|
||||||
If you use pipx, you can install Black with `pipx install black`.
|
Jupyter Notebooks, install with `pip install black[jupyter]`.
|
||||||
|
|
||||||
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
If you can't wait for the latest _hotness_ and want to install from GitHub, use:
|
||||||
|
|
||||||
`pip install git+https://github.com/psf/black`
|
`pip install git+git://github.com/psf/black`
|
||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
# Guides
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
hidden:
|
|
||||||
---
|
|
||||||
|
|
||||||
introducing_black_to_your_project
|
|
||||||
using_black_with_other_tools
|
|
||||||
```
|
|
||||||
|
|
||||||
Wondering how to do something specific? You've found the right place! Listed below are
|
|
||||||
topic specific guides available:
|
|
||||||
|
|
||||||
- {doc}`introducing_black_to_your_project`
|
|
||||||
- {doc}`using_black_with_other_tools`
|
|
14
docs/guides/index.rst
Normal file
14
docs/guides/index.rst
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Guides
|
||||||
|
======
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
introducing_black_to_your_project
|
||||||
|
using_black_with_other_tools
|
||||||
|
|
||||||
|
Wondering how to do something specific? You've found the right place! Listed below
|
||||||
|
are topic specific guides available:
|
||||||
|
|
||||||
|
- :doc:`introducing_black_to_your_project`
|
||||||
|
- :doc:`using_black_with_other_tools`
|
@ -18,8 +18,7 @@ previous revision that modified those lines.
|
|||||||
|
|
||||||
So when migrating your project's code style to _Black_, reformat everything and commit
|
So when migrating your project's code style to _Black_, reformat everything and commit
|
||||||
the changes (preferably in one massive commit). Then put the full 40 characters commit
|
the changes (preferably in one massive commit). Then put the full 40 characters commit
|
||||||
identifier(s) into a file usually called `.git-blame-ignore-revs` at the root of your
|
identifier(s) into a file.
|
||||||
project directory.
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
# Migrate code style to Black
|
# Migrate code style to Black
|
||||||
@ -44,9 +43,8 @@ call to `git blame`.
|
|||||||
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||||
```
|
```
|
||||||
|
|
||||||
**The one caveat is that some online Git-repositories like GitLab do not yet support
|
**The one caveat is that GitHub and GitLab do not yet support ignoring revisions using
|
||||||
ignoring revisions using their native blame UI.** So blame information will be cluttered
|
their native UI of blame.** So blame information will be cluttered with a reformatting
|
||||||
with a reformatting commit on those platforms. (If you'd like this feature, there's an
|
commit on those platforms. (If you'd like this feature, there's an open issue for
|
||||||
open issue for [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/31423)).
|
[GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/31423) and please let GitHub
|
||||||
[GitHub supports `.git-blame-ignore-revs`](https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view)
|
know!)
|
||||||
by default in blame views however.
|
|
||||||
|
@ -51,9 +51,9 @@ line_length = 88
|
|||||||
|
|
||||||
#### Why those options above?
|
#### Why those options above?
|
||||||
|
|
||||||
_Black_ wraps imports that surpass `line-length` by moving identifiers onto separate
|
_Black_ wraps imports that surpass `line-length` by moving identifiers into their own
|
||||||
lines and by adding a trailing comma after each. A more detailed explanation of this
|
indented line. If that still doesn't fit the bill, it will put all of them in separate
|
||||||
behaviour can be
|
lines and put a trailing comma. A more detailed explanation of this behaviour can be
|
||||||
[found here](../the_black_code_style/current_style.md#how-black-wraps-lines).
|
[found here](../the_black_code_style/current_style.md#how-black-wraps-lines).
|
||||||
|
|
||||||
isort's default mode of wrapping imports that extend past the `line_length` limit is
|
isort's default mode of wrapping imports that extend past the `line_length` limit is
|
||||||
@ -97,7 +97,7 @@ does not break older versions so you can keep it if you are running previous ver
|
|||||||
<details>
|
<details>
|
||||||
<summary>.isort.cfg</summary>
|
<summary>.isort.cfg</summary>
|
||||||
|
|
||||||
```ini
|
```cfg
|
||||||
[settings]
|
[settings]
|
||||||
profile = black
|
profile = black
|
||||||
```
|
```
|
||||||
@ -107,7 +107,7 @@ profile = black
|
|||||||
<details>
|
<details>
|
||||||
<summary>setup.cfg</summary>
|
<summary>setup.cfg</summary>
|
||||||
|
|
||||||
```ini
|
```cfg
|
||||||
[isort]
|
[isort]
|
||||||
profile = black
|
profile = black
|
||||||
```
|
```
|
||||||
@ -134,10 +134,10 @@ profile = black
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### pycodestyle
|
### Flake8
|
||||||
|
|
||||||
[pycodestyle](https://pycodestyle.pycqa.org/) is a code linter. It warns you of syntax
|
[Flake8](https://pypi.org/p/flake8/) is a code linter. It warns you of syntax errors,
|
||||||
errors, possible bugs, stylistic errors, etc. For the most part, pycodestyle follows
|
possible bugs, stylistic errors, etc. For the most part, Flake8 follows
|
||||||
[PEP 8](https://www.python.org/dev/peps/pep-0008/) when warning about stylistic errors.
|
[PEP 8](https://www.python.org/dev/peps/pep-0008/) when warning about stylistic errors.
|
||||||
There are a few deviations that cause incompatibilities with _Black_.
|
There are a few deviations that cause incompatibilities with _Black_.
|
||||||
|
|
||||||
@ -145,129 +145,96 @@ There are a few deviations that cause incompatibilities with _Black_.
|
|||||||
|
|
||||||
```
|
```
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
ignore = E203,E701
|
extend-ignore = E203
|
||||||
```
|
```
|
||||||
|
|
||||||
(labels/why-pycodestyle-warnings)=
|
|
||||||
|
|
||||||
#### Why those options above?
|
#### Why those options above?
|
||||||
|
|
||||||
##### `max-line-length`
|
|
||||||
|
|
||||||
As with isort, pycodestyle should be configured to allow lines up to the length limit of
|
|
||||||
`88`, _Black_'s default.
|
|
||||||
|
|
||||||
##### `E203`
|
|
||||||
|
|
||||||
In some cases, as determined by PEP 8, _Black_ will enforce an equal amount of
|
In some cases, as determined by PEP 8, _Black_ will enforce an equal amount of
|
||||||
whitespace around slice operators. Due to this, pycodestyle will raise
|
whitespace around slice operators. Due to this, Flake8 will raise
|
||||||
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, it
|
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, Flake8
|
||||||
should be disabled.
|
should be configured to ignore it via `extend-ignore = E203`.
|
||||||
|
|
||||||
##### `E701` / `E704`
|
|
||||||
|
|
||||||
_Black_ will collapse implementations of classes and functions consisting solely of `..`
|
|
||||||
to a single line. This matches how such examples are formatted in PEP 8. It remains true
|
|
||||||
that in all other cases Black will prevent multiple statements on the same line, in
|
|
||||||
accordance with PEP 8 generally discouraging this.
|
|
||||||
|
|
||||||
However, `pycodestyle` does not mirror this logic and may raise
|
|
||||||
`E701 multiple statements on one line (colon)` in this situation. Its
|
|
||||||
disabled-by-default `E704 multiple statements on one line (def)` rule may also raise
|
|
||||||
warnings and should not be enabled.
|
|
||||||
|
|
||||||
##### `W503`
|
|
||||||
|
|
||||||
When breaking a line, _Black_ will break it before a binary operator. This is compliant
|
When breaking a line, _Black_ will break it before a binary operator. This is compliant
|
||||||
with PEP 8 as of
|
with PEP 8 as of
|
||||||
[April 2016](https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b#diff-64ec08cc46db7540f18f2af46037f599).
|
[April 2016](https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b#diff-64ec08cc46db7540f18f2af46037f599).
|
||||||
There's a disabled-by-default warning in Flake8 which goes against this PEP 8
|
There's a disabled-by-default warning in Flake8 which goes against this PEP 8
|
||||||
recommendation called `W503 line break before binary operator`. It should not be enabled
|
recommendation called `W503 line break before binary operator`. It should not be enabled
|
||||||
in your configuration. You can use its counterpart
|
in your configuration.
|
||||||
`W504 line break after binary operator` instead.
|
|
||||||
|
Also, as like with isort, flake8 should be configured to allow lines up to the length
|
||||||
|
limit of `88`, _Black_'s default. This explains `max-line-length = 88`.
|
||||||
|
|
||||||
#### Formats
|
#### Formats
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>setup.cfg, .pycodestyle, tox.ini</summary>
|
<summary>.flake8</summary>
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[pycodestyle]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
ignore = E203,E701
|
extend-ignore = E203
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Flake8
|
<details>
|
||||||
|
<summary>setup.cfg</summary>
|
||||||
|
|
||||||
[Flake8](https://pypi.org/p/flake8/) is a wrapper around multiple linters, including
|
```cfg
|
||||||
pycodestyle. As such, it has many of the same issues.
|
|
||||||
|
|
||||||
#### Bugbear
|
|
||||||
|
|
||||||
It's recommended to use [the Bugbear plugin](https://github.com/PyCQA/flake8-bugbear)
|
|
||||||
and enable
|
|
||||||
[its B950 check](https://github.com/PyCQA/flake8-bugbear#opinionated-warnings#:~:text=you%20expect%20it.-,B950,-%3A%20Line%20too%20long)
|
|
||||||
instead of using Flake8's E501, because it aligns with
|
|
||||||
[Black's 10% rule](labels/line-length).
|
|
||||||
|
|
||||||
Install Bugbear and use the following config:
|
|
||||||
|
|
||||||
```
|
|
||||||
[flake8]
|
|
||||||
max-line-length = 80
|
|
||||||
extend-select = B950
|
|
||||||
extend-ignore = E203,E501,E701
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Minimal Configuration
|
|
||||||
|
|
||||||
In cases where you can't or don't want to install Bugbear, you can use this minimally
|
|
||||||
compatible config:
|
|
||||||
|
|
||||||
```
|
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203,E701
|
extend-ignore = E203
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Why those options above?
|
</details>
|
||||||
|
|
||||||
See [the pycodestyle section](labels/why-pycodestyle-warnings) above.
|
|
||||||
|
|
||||||
#### Formats
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>.flake8, setup.cfg, tox.ini</summary>
|
<summary>tox.ini</summary>
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
extend-ignore = E203,E701
|
extend-ignore = E203
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Pylint
|
### Pylint
|
||||||
|
|
||||||
[Pylint](https://pypi.org/p/pylint/) is also a code linter like Flake8. It has many of
|
[Pylint](https://pypi.org/p/pylint/) is also a code linter like Flake8. It has the same
|
||||||
the same checks as Flake8 and more. It particularly has more formatting checks regarding
|
checks as flake8 and more. In particular, it has more formatting checks regarding style
|
||||||
style conventions like variable naming.
|
conventions like variable naming. With so many checks, Pylint is bound to have some
|
||||||
|
mixed feelings about _Black_'s formatting style.
|
||||||
|
|
||||||
#### Configuration
|
#### Configuration
|
||||||
|
|
||||||
```
|
```
|
||||||
|
disable = C0330, C0326
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Why those options above?
|
#### Why those options above?
|
||||||
|
|
||||||
Pylint should be configured to only complain about lines that surpass `88` characters
|
When _Black_ is folding very long expressions, the closing brackets will
|
||||||
via `max-line-length = 88`.
|
[be dedented](../the_black_code_style/current_style.md#how-black-wraps-lines).
|
||||||
|
|
||||||
If using `pylint<2.6.0`, also disable `C0326` and `C0330` as these are incompatible with
|
```py3
|
||||||
_Black_ formatting and have since been removed.
|
ImportantClass.important_method(
|
||||||
|
exc, limit, lookup_lines, capture_locals, callback
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Although this style is PEP 8 compliant, Pylint will raise
|
||||||
|
`C0330: Wrong hanging indentation before block (add 4 spaces)` warnings. Since _Black_
|
||||||
|
isn't configurable on this style, Pylint should be told to ignore these warnings via
|
||||||
|
`disable = C0330`.
|
||||||
|
|
||||||
|
Also, since _Black_ deals with whitespace around operators and brackets, Pylint's
|
||||||
|
warning `C0326: Bad whitespace` should be disabled using `disable = C0326`.
|
||||||
|
|
||||||
|
And as usual, Pylint should be configured to only complain about lines that surpass `88`
|
||||||
|
characters via `max-line-length = 88`.
|
||||||
|
|
||||||
#### Formats
|
#### Formats
|
||||||
|
|
||||||
@ -275,6 +242,9 @@ _Black_ formatting and have since been removed.
|
|||||||
<summary>pylintrc</summary>
|
<summary>pylintrc</summary>
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
|
[MESSAGES CONTROL]
|
||||||
|
disable = C0330, C0326
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
```
|
```
|
||||||
@ -287,6 +257,9 @@ max-line-length = 88
|
|||||||
```cfg
|
```cfg
|
||||||
[pylint]
|
[pylint]
|
||||||
max-line-length = 88
|
max-line-length = 88
|
||||||
|
|
||||||
|
[pylint.messages_control]
|
||||||
|
disable = C0330, C0326
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@ -295,6 +268,9 @@ max-line-length = 88
|
|||||||
<summary>pyproject.toml</summary>
|
<summary>pyproject.toml</summary>
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
[tool.pylint.messages_control]
|
||||||
|
disable = "C0330, C0326"
|
||||||
|
|
||||||
[tool.pylint.format]
|
[tool.pylint.format]
|
||||||
max-line-length = "88"
|
max-line-length = "88"
|
||||||
```
|
```
|
||||||
|
139
docs/index.md
139
docs/index.md
@ -1,139 +0,0 @@
|
|||||||
<!--
|
|
||||||
black documentation master file, created by
|
|
||||||
sphinx-quickstart on Fri Mar 23 10:53:30 2018.
|
|
||||||
-->
|
|
||||||
|
|
||||||
# The uncompromising code formatter
|
|
||||||
|
|
||||||
> “Any color you like.”
|
|
||||||
|
|
||||||
By using _Black_, you agree to cede control over minutiae of hand-formatting. In return,
|
|
||||||
_Black_ gives you speed, determinism, and freedom from `pycodestyle` nagging about
|
|
||||||
formatting. You will save time and mental energy for more important matters.
|
|
||||||
|
|
||||||
_Black_ makes code review faster by producing the smallest diffs possible. Blackened
|
|
||||||
code looks the same regardless of the project you're reading. Formatting becomes
|
|
||||||
transparent after a while and you can focus on the content instead.
|
|
||||||
|
|
||||||
Try it out now using the [Black Playground](https://black.vercel.app).
|
|
||||||
|
|
||||||
```{admonition} Note - Black is now stable!
|
|
||||||
*Black* is [successfully used](https://github.com/psf/black#used-by) by
|
|
||||||
many projects, small and big. *Black* has a comprehensive test suite, with efficient
|
|
||||||
parallel tests, our own auto formatting and parallel Continuous Integration runner.
|
|
||||||
Now that we have become stable, you should not expect large changes to formatting in
|
|
||||||
the future. Stylistic changes will mostly be responses to bug reports and support for new Python
|
|
||||||
syntax.
|
|
||||||
|
|
||||||
Also, as a safety measure which slows down processing, *Black* will check that the
|
|
||||||
reformatted code still produces a valid AST that is effectively equivalent to the
|
|
||||||
original (see the
|
|
||||||
[Pragmatism](./the_black_code_style/current_style.md#pragmatism)
|
|
||||||
section for details). If you're feeling confident, use `--fast`.
|
|
||||||
```
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
{doc}`Black is licensed under the MIT license <license>`.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testimonials
|
|
||||||
|
|
||||||
**Mike Bayer**, author of [SQLAlchemy](https://www.sqlalchemy.org/):
|
|
||||||
|
|
||||||
> _I can't think of any single tool in my entire programming career that has given me a
|
|
||||||
> bigger productivity increase by its introduction. I can now do refactorings in about
|
|
||||||
> 1% of the keystrokes that it would have taken me previously when we had no way for
|
|
||||||
> code to format itself._
|
|
||||||
|
|
||||||
**Dusty Phillips**,
|
|
||||||
[writer](https://smile.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=dusty+phillips):
|
|
||||||
|
|
||||||
> _Black is opinionated so you don't have to be._
|
|
||||||
|
|
||||||
**Hynek Schlawack**, creator of [attrs](https://www.attrs.org/), core developer of
|
|
||||||
Twisted and CPython:
|
|
||||||
|
|
||||||
> _An auto-formatter that doesn't suck is all I want for Xmas!_
|
|
||||||
|
|
||||||
**Carl Meyer**, [Django](https://www.djangoproject.com/) core developer:
|
|
||||||
|
|
||||||
> _At least the name is good._
|
|
||||||
|
|
||||||
**Kenneth Reitz**, creator of [requests](http://python-requests.org/) and
|
|
||||||
[pipenv](https://docs.pipenv.org/):
|
|
||||||
|
|
||||||
> _This vastly improves the formatting of our code. Thanks a ton!_
|
|
||||||
|
|
||||||
## Show your style
|
|
||||||
|
|
||||||
Use the badge in your project's README.md:
|
|
||||||
|
|
||||||
```md
|
|
||||||
[](https://github.com/psf/black)
|
|
||||||
```
|
|
||||||
|
|
||||||
Using the badge in README.rst:
|
|
||||||
|
|
||||||
```rst
|
|
||||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
|
||||||
:target: https://github.com/psf/black
|
|
||||||
```
|
|
||||||
|
|
||||||
Looks like this:
|
|
||||||
|
|
||||||
```{image} https://img.shields.io/badge/code%20style-black-000000.svg
|
|
||||||
:target: https://github.com/psf/black
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contents
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
maxdepth: 3
|
|
||||||
includehidden:
|
|
||||||
---
|
|
||||||
|
|
||||||
the_black_code_style/index
|
|
||||||
```
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
maxdepth: 3
|
|
||||||
includehidden:
|
|
||||||
caption: User Guide
|
|
||||||
---
|
|
||||||
|
|
||||||
getting_started
|
|
||||||
usage_and_configuration/index
|
|
||||||
integrations/index
|
|
||||||
guides/index
|
|
||||||
faq
|
|
||||||
```
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
maxdepth: 2
|
|
||||||
includehidden:
|
|
||||||
caption: Development
|
|
||||||
---
|
|
||||||
|
|
||||||
contributing/index
|
|
||||||
change_log
|
|
||||||
authors
|
|
||||||
```
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
hidden:
|
|
||||||
caption: Project Links
|
|
||||||
---
|
|
||||||
|
|
||||||
GitHub <https://github.com/psf/black>
|
|
||||||
PyPI <https://pypi.org/project/black>
|
|
||||||
Chat <https://discord.gg/RtVdv86PrH>
|
|
||||||
```
|
|
||||||
|
|
||||||
# Indices and tables
|
|
||||||
|
|
||||||
- {ref}`genindex`
|
|
||||||
- {ref}`search`
|
|
128
docs/index.rst
Normal file
128
docs/index.rst
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
.. black documentation master file, created by
|
||||||
|
sphinx-quickstart on Fri Mar 23 10:53:30 2018.
|
||||||
|
|
||||||
|
The uncompromising code formatter
|
||||||
|
=================================
|
||||||
|
|
||||||
|
By using *Black*, you agree to cede control over minutiae of
|
||||||
|
hand-formatting. In return, *Black* gives you speed, determinism, and
|
||||||
|
freedom from `pycodestyle` nagging about formatting. You will save time
|
||||||
|
and mental energy for more important matters.
|
||||||
|
|
||||||
|
*Black* makes code review faster by producing the smallest diffs
|
||||||
|
possible. Blackened code looks the same regardless of the project
|
||||||
|
you're reading. Formatting becomes transparent after a while and you
|
||||||
|
can focus on the content instead.
|
||||||
|
|
||||||
|
Try it out now using the `Black Playground <https://black.vercel.app>`_.
|
||||||
|
|
||||||
|
.. admonition:: Note - this is a beta product
|
||||||
|
|
||||||
|
*Black* is already `successfully used <https://github.com/psf/black#used-by>`_ by
|
||||||
|
many projects, small and big. *Black* has a comprehensive test suite, with efficient
|
||||||
|
parallel tests, our own auto formatting and parallel Continuous Integration runner.
|
||||||
|
However, *Black* is still beta. Things will probably be wonky for a while. This is
|
||||||
|
made explicit by the "Beta" trove classifier, as well as by the "b" in the version
|
||||||
|
number. What this means for you is that **until the formatter becomes stable, you
|
||||||
|
should expect some formatting to change in the future**. That being said, no drastic
|
||||||
|
stylistic changes are planned, mostly responses to bug reports.
|
||||||
|
|
||||||
|
Also, as a safety measure which slows down processing, *Black* will check that the
|
||||||
|
reformatted code still produces a valid AST that is effectively equivalent to the
|
||||||
|
original (see the
|
||||||
|
`Pragmatism <./the_black_code_style/current_style.html#pragmatism>`_
|
||||||
|
section for details). If you're feeling confident, use ``--fast``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
:doc:`Black is licensed under the MIT license <license>`.
|
||||||
|
|
||||||
|
Testimonials
|
||||||
|
------------
|
||||||
|
|
||||||
|
**Mike Bayer**, author of `SQLAlchemy <https://www.sqlalchemy.org/>`_:
|
||||||
|
|
||||||
|
*I can't think of any single tool in my entire programming career that has given me a
|
||||||
|
bigger productivity increase by its introduction. I can now do refactorings in about
|
||||||
|
1% of the keystrokes that it would have taken me previously when we had no way for
|
||||||
|
code to format itself.*
|
||||||
|
|
||||||
|
**Dusty Phillips**, `writer <https://smile.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=dusty+phillips>`_:
|
||||||
|
|
||||||
|
*Black is opinionated so you don't have to be.*
|
||||||
|
|
||||||
|
**Hynek Schlawack**, creator of `attrs <https://www.attrs.org/>`_, core
|
||||||
|
developer of Twisted and CPython:
|
||||||
|
|
||||||
|
*An auto-formatter that doesn't suck is all I want for Xmas!*
|
||||||
|
|
||||||
|
**Carl Meyer**, `Django <https://www.djangoproject.com/>`_ core developer:
|
||||||
|
|
||||||
|
*At least the name is good.*
|
||||||
|
|
||||||
|
**Kenneth Reitz**, creator of `requests <http://python-requests.org/>`_
|
||||||
|
and `pipenv <https://docs.pipenv.org/>`_:
|
||||||
|
|
||||||
|
*This vastly improves the formatting of our code. Thanks a ton!*
|
||||||
|
|
||||||
|
|
||||||
|
Show your style
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Use the badge in your project's README.md:
|
||||||
|
|
||||||
|
.. code-block:: md
|
||||||
|
|
||||||
|
[](https://github.com/psf/black)
|
||||||
|
|
||||||
|
|
||||||
|
Using the badge in README.rst:
|
||||||
|
|
||||||
|
.. code-block:: rst
|
||||||
|
|
||||||
|
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
|
:target: https://github.com/psf/black
|
||||||
|
|
||||||
|
Looks like this:
|
||||||
|
|
||||||
|
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
|
:target: https://github.com/psf/black
|
||||||
|
|
||||||
|
Contents
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 3
|
||||||
|
:includehidden:
|
||||||
|
|
||||||
|
the_black_code_style/index
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 3
|
||||||
|
:includehidden:
|
||||||
|
|
||||||
|
getting_started
|
||||||
|
usage_and_configuration/index
|
||||||
|
integrations/index
|
||||||
|
guides/index
|
||||||
|
faq
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 3
|
||||||
|
:includehidden:
|
||||||
|
|
||||||
|
contributing/index
|
||||||
|
change_log
|
||||||
|
authors
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
GitHub ↪ <https://github.com/psf/black>
|
||||||
|
PyPI ↪ <https://pypi.org/project/black>
|
||||||
|
Chat ↪ <https://discord.gg/RtVdv86PrH>
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
@ -10,67 +10,6 @@ Options include the following:
|
|||||||
|
|
||||||
## PyCharm/IntelliJ IDEA
|
## PyCharm/IntelliJ IDEA
|
||||||
|
|
||||||
There are several different ways you can use _Black_ from PyCharm:
|
|
||||||
|
|
||||||
1. Using the built-in _Black_ integration (PyCharm 2023.2 and later). This option is the
|
|
||||||
simplest to set up.
|
|
||||||
1. As local server using the BlackConnect plugin. This option formats the fastest. It
|
|
||||||
spins up {doc}`Black's HTTP server </usage_and_configuration/black_as_a_server>`, to
|
|
||||||
avoid the startup cost on subsequent formats.
|
|
||||||
1. As external tool.
|
|
||||||
1. As file watcher.
|
|
||||||
|
|
||||||
### Built-in _Black_ integration
|
|
||||||
|
|
||||||
1. Install `black`.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ pip install black
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Go to `Preferences or Settings -> Tools -> Black` and configure _Black_ to your
|
|
||||||
liking.
|
|
||||||
|
|
||||||
### As local server
|
|
||||||
|
|
||||||
1. Install _Black_ with the `d` extra.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ pip install 'black[d]'
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Install
|
|
||||||
[BlackConnect IntelliJ IDEs plugin](https://plugins.jetbrains.com/plugin/14321-blackconnect).
|
|
||||||
|
|
||||||
1. Open plugin configuration in PyCharm/IntelliJ IDEA
|
|
||||||
|
|
||||||
On macOS:
|
|
||||||
|
|
||||||
`PyCharm -> Preferences -> Tools -> BlackConnect`
|
|
||||||
|
|
||||||
On Windows / Linux / BSD:
|
|
||||||
|
|
||||||
`File -> Settings -> Tools -> BlackConnect`
|
|
||||||
|
|
||||||
1. In `Local Instance (shared between projects)` section:
|
|
||||||
|
|
||||||
1. Check `Start local blackd instance when plugin loads`.
|
|
||||||
1. Press the `Detect` button near `Path` input. The plugin should detect the `blackd`
|
|
||||||
executable.
|
|
||||||
|
|
||||||
1. In `Trigger Settings` section check `Trigger on code reformat` to enable code
|
|
||||||
reformatting with _Black_.
|
|
||||||
|
|
||||||
1. Format the currently opened file by selecting `Code -> Reformat Code` or using a
|
|
||||||
shortcut.
|
|
||||||
|
|
||||||
1. Optionally, to run _Black_ on every file save:
|
|
||||||
|
|
||||||
- In `Trigger Settings` section of plugin configuration check
|
|
||||||
`Trigger when saving changed files`.
|
|
||||||
|
|
||||||
### As external tool
|
|
||||||
|
|
||||||
1. Install `black`.
|
1. Install `black`.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
@ -118,38 +57,13 @@ There are several different ways you can use _Black_ from PyCharm:
|
|||||||
- Alternatively, you can set a keyboard shortcut by navigating to
|
- Alternatively, you can set a keyboard shortcut by navigating to
|
||||||
`Preferences or Settings -> Keymap -> External Tools -> External Tools - Black`.
|
`Preferences or Settings -> Keymap -> External Tools -> External Tools - Black`.
|
||||||
|
|
||||||
### As file watcher
|
1. Optionally, run _Black_ on every file save:
|
||||||
|
|
||||||
1. Install `black`.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ pip install black
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Locate your `black` installation folder.
|
|
||||||
|
|
||||||
On macOS / Linux / BSD:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ which black
|
|
||||||
/usr/local/bin/black # possible location
|
|
||||||
```
|
|
||||||
|
|
||||||
On Windows:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ where black
|
|
||||||
%LocalAppData%\Programs\Python\Python36-32\Scripts\black.exe # possible location
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that if you are using a virtual environment detected by PyCharm, this is an
|
|
||||||
unneeded step. In this case the path to `black` is `$PyInterpreterDirectory$/black`.
|
|
||||||
|
|
||||||
1. Make sure you have the
|
1. Make sure you have the
|
||||||
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin
|
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin
|
||||||
installed.
|
installed.
|
||||||
1. Go to `Preferences or Settings -> Tools -> File Watchers` and click `+` to add a new
|
1. Go to `Preferences or Settings -> Tools -> File Watchers` and click `+` to add a
|
||||||
watcher:
|
new watcher:
|
||||||
- Name: Black
|
- Name: Black
|
||||||
- File type: Python
|
- File type: Python
|
||||||
- Scope: Project Files
|
- Scope: Project Files
|
||||||
@ -164,51 +78,36 @@ There are several different ways you can use _Black_ from PyCharm:
|
|||||||
|
|
||||||
## Wing IDE
|
## Wing IDE
|
||||||
|
|
||||||
Wing IDE supports `black` via **Preference Settings** for system wide settings and
|
Wing supports black via the OS Commands tool, as explained in the Wing documentation on
|
||||||
**Project Properties** for per-project or workspace specific settings, as explained in
|
[pep8 formatting](https://wingware.com/doc/edit/pep8). The detailed procedure is:
|
||||||
the Wing documentation on
|
|
||||||
[Auto-Reformatting](https://wingware.com/doc/edit/auto-reformatting). The detailed
|
|
||||||
procedure is:
|
|
||||||
|
|
||||||
### Prerequistes
|
1. Install `black`.
|
||||||
|
|
||||||
- Wing IDE version 8.0+
|
|
||||||
|
|
||||||
- Install `black`.
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ pip install black
|
$ pip install black
|
||||||
```
|
```
|
||||||
|
|
||||||
- Make sure it runs from the command line, e.g.
|
1. Make sure it runs from the command line, e.g.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black --help
|
$ black --help
|
||||||
```
|
```
|
||||||
|
|
||||||
### Preference Settings
|
1. In Wing IDE, activate the **OS Commands** panel and define the command **black** to
|
||||||
|
execute black on the currently selected file:
|
||||||
|
|
||||||
If you want Wing IDE to always reformat with `black` for every project, follow these
|
- Use the Tools -> OS Commands menu selection
|
||||||
steps:
|
- click on **+** in **OS Commands** -> New: Command line..
|
||||||
|
- Title: black
|
||||||
|
- Command Line: black %s
|
||||||
|
- I/O Encoding: Use Default
|
||||||
|
- Key Binding: F1
|
||||||
|
- [x] Raise OS Commands when executed
|
||||||
|
- [x] Auto-save files before execution
|
||||||
|
- [x] Line mode
|
||||||
|
|
||||||
1. In menubar navigate to `Edit -> Preferences -> Editor -> Reformatting`.
|
1. Select a file in the editor and press **F1** , or whatever key binding you selected
|
||||||
|
in step 3, to reformat the file.
|
||||||
1. Set **Auto-Reformat** from `disable` (default) to `Line after edit` or
|
|
||||||
`Whole files before save`.
|
|
||||||
|
|
||||||
1. Set **Reformatter** from `PEP8` (default) to `Black`.
|
|
||||||
|
|
||||||
### Project Properties
|
|
||||||
|
|
||||||
If you want to just reformat for a specific project and not intervene with Wing IDE
|
|
||||||
global setting, follow these steps:
|
|
||||||
|
|
||||||
1. In menubar navigate to `Project -> Project Properties -> Options`.
|
|
||||||
|
|
||||||
1. Set **Auto-Reformat** from `Use Preferences setting` (default) to `Line after edit`
|
|
||||||
or `Whole files before save`.
|
|
||||||
|
|
||||||
1. Set **Reformatter** from `Use Preferences setting` (default) to `Black`.
|
|
||||||
|
|
||||||
## Vim
|
## Vim
|
||||||
|
|
||||||
@ -217,61 +116,23 @@ global setting, follow these steps:
|
|||||||
Commands and shortcuts:
|
Commands and shortcuts:
|
||||||
|
|
||||||
- `:Black` to format the entire file (ranges not supported);
|
- `:Black` to format the entire file (ranges not supported);
|
||||||
- you can optionally pass `target_version=<version>` with the same values as in the
|
|
||||||
command line.
|
|
||||||
- `:BlackUpgrade` to upgrade _Black_ inside the virtualenv;
|
- `:BlackUpgrade` to upgrade _Black_ inside the virtualenv;
|
||||||
- `:BlackVersion` to get the current version of _Black_ in use.
|
- `:BlackVersion` to get the current version of _Black_ inside the virtualenv.
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
|
|
||||||
- `g:black_fast` (defaults to `0`)
|
- `g:black_fast` (defaults to `0`)
|
||||||
- `g:black_linelength` (defaults to `88`)
|
- `g:black_linelength` (defaults to `88`)
|
||||||
- `g:black_skip_string_normalization` (defaults to `0`)
|
- `g:black_skip_string_normalization` (defaults to `0`)
|
||||||
- `g:black_skip_magic_trailing_comma` (defaults to `0`)
|
|
||||||
- `g:black_virtualenv` (defaults to `~/.vim/black` or `~/.local/share/nvim/black`)
|
- `g:black_virtualenv` (defaults to `~/.vim/black` or `~/.local/share/nvim/black`)
|
||||||
- `g:black_use_virtualenv` (defaults to `1`)
|
|
||||||
- `g:black_target_version` (defaults to `""`)
|
|
||||||
- `g:black_quiet` (defaults to `0`)
|
- `g:black_quiet` (defaults to `0`)
|
||||||
- `g:black_preview` (defaults to `0`)
|
|
||||||
|
|
||||||
#### Installation
|
|
||||||
|
|
||||||
This plugin **requires Vim 7.0+ built with Python 3.9+ support**. It needs Python 3.9 to
|
|
||||||
be able to run _Black_ inside the Vim process which is much faster than calling an
|
|
||||||
external command.
|
|
||||||
|
|
||||||
##### `vim-plug`
|
|
||||||
|
|
||||||
To install with [vim-plug](https://github.com/junegunn/vim-plug):
|
To install with [vim-plug](https://github.com/junegunn/vim-plug):
|
||||||
|
|
||||||
_Black_'s `stable` branch tracks official version updates, and can be used to simply
|
|
||||||
follow the most recent stable version.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
Plug 'psf/black', { 'branch': 'stable' }
|
Plug 'psf/black', { 'branch': 'stable' }
|
||||||
```
|
```
|
||||||
|
|
||||||
Another option which is a bit more explicit and offers more control is to use
|
|
||||||
`vim-plug`'s `tag` option with a shell wildcard. This will resolve to the latest tag
|
|
||||||
which matches the given pattern.
|
|
||||||
|
|
||||||
The following matches all stable versions (see the
|
|
||||||
[Release Process](../contributing/release_process.md) section for documentation of
|
|
||||||
version scheme used by Black):
|
|
||||||
|
|
||||||
```
|
|
||||||
Plug 'psf/black', { 'tag': '*.*.*' }
|
|
||||||
```
|
|
||||||
|
|
||||||
and the following demonstrates pinning to a specific year's stable style (2022 in this
|
|
||||||
case):
|
|
||||||
|
|
||||||
```
|
|
||||||
Plug 'psf/black', { 'tag': '22.*.*' }
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Vundle
|
|
||||||
|
|
||||||
or with [Vundle](https://github.com/VundleVim/Vundle.vim):
|
or with [Vundle](https://github.com/VundleVim/Vundle.vim):
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -285,14 +146,6 @@ $ cd ~/.vim/bundle/black
|
|||||||
$ git checkout origin/stable -b stable
|
$ git checkout origin/stable -b stable
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Arch Linux
|
|
||||||
|
|
||||||
On Arch Linux, the plugin is shipped with the
|
|
||||||
[`python-black`](https://archlinux.org/packages/extra/any/python-black/) package, so you
|
|
||||||
can start using it in Vim after install with no additional setup.
|
|
||||||
|
|
||||||
##### Vim 8 Native Plugin Management
|
|
||||||
|
|
||||||
or you can copy the plugin files from
|
or you can copy the plugin files from
|
||||||
[plugin/black.vim](https://github.com/psf/black/blob/stable/plugin/black.vim) and
|
[plugin/black.vim](https://github.com/psf/black/blob/stable/plugin/black.vim) and
|
||||||
[autoload/black.vim](https://github.com/psf/black/blob/stable/autoload/black.vim).
|
[autoload/black.vim](https://github.com/psf/black/blob/stable/autoload/black.vim).
|
||||||
@ -307,7 +160,9 @@ curl https://raw.githubusercontent.com/psf/black/stable/autoload/black.vim -o ~/
|
|||||||
Let me know if this requires any changes to work with Vim 8's builtin `packadd`, or
|
Let me know if this requires any changes to work with Vim 8's builtin `packadd`, or
|
||||||
Pathogen, and so on.
|
Pathogen, and so on.
|
||||||
|
|
||||||
#### Usage
|
This plugin **requires Vim 7.0+ built with Python 3.6+ support**. It needs Python 3.6 to
|
||||||
|
be able to run _Black_ inside the Vim process which is much faster than calling an
|
||||||
|
external command.
|
||||||
|
|
||||||
On first run, the plugin creates its own virtualenv using the right Python version and
|
On first run, the plugin creates its own virtualenv using the right Python version and
|
||||||
automatically installs _Black_. You can upgrade it later by calling `:BlackUpgrade` and
|
automatically installs _Black_. You can upgrade it later by calling `:BlackUpgrade` and
|
||||||
@ -317,25 +172,10 @@ If you need to do anything special to make your virtualenv work and install _Bla
|
|||||||
example you want to run a version from main), create a virtualenv manually and point
|
example you want to run a version from main), create a virtualenv manually and point
|
||||||
`g:black_virtualenv` to it. The plugin will use it.
|
`g:black_virtualenv` to it. The plugin will use it.
|
||||||
|
|
||||||
If you would prefer to use the system installation of _Black_ rather than a virtualenv,
|
To run _Black_ on save, add the following line to `.vimrc` or `init.vim`:
|
||||||
then add this to your vimrc:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
let g:black_use_virtualenv = 0
|
autocmd BufWritePre *.py execute ':Black'
|
||||||
```
|
|
||||||
|
|
||||||
Note that the `:BlackUpgrade` command is only usable and useful with a virtualenv, so
|
|
||||||
when the virtualenv is not in use, `:BlackUpgrade` is disabled. If you need to upgrade
|
|
||||||
the system installation of _Black_, then use your system package manager or pip--
|
|
||||||
whatever tool you used to install _Black_ originally.
|
|
||||||
|
|
||||||
To run _Black_ on save, add the following lines to `.vimrc` or `init.vim`:
|
|
||||||
|
|
||||||
```
|
|
||||||
augroup black_on_save
|
|
||||||
autocmd!
|
|
||||||
autocmd BufWritePre *.py Black
|
|
||||||
augroup end
|
|
||||||
```
|
```
|
||||||
|
|
||||||
To run _Black_ on a key press (e.g. F9 below), add this:
|
To run _Black_ on a key press (e.g. F9 below), add this:
|
||||||
@ -344,6 +184,60 @@ To run _Black_ on a key press (e.g. F9 below), add this:
|
|||||||
nnoremap <F9> :Black<CR>
|
nnoremap <F9> :Black<CR>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**How to get Vim with Python 3.6?** On Ubuntu 17.10 Vim comes with Python 3.6 by
|
||||||
|
default. On macOS with Homebrew run: `brew install vim`. When building Vim from source,
|
||||||
|
use: `./configure --enable-python3interp=yes`. There's many guides online how to do
|
||||||
|
this.
|
||||||
|
|
||||||
|
**I get an import error when using _Black_ from a virtual environment**: If you get an
|
||||||
|
error message like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<string>", line 63, in <module>
|
||||||
|
File "/home/gui/.vim/black/lib/python3.7/site-packages/black.py", line 45, in <module>
|
||||||
|
from typed_ast import ast3, ast27
|
||||||
|
File "/home/gui/.vim/black/lib/python3.7/site-packages/typed_ast/ast3.py", line 40, in <module>
|
||||||
|
from typed_ast import _ast3
|
||||||
|
ImportError: /home/gui/.vim/black/lib/python3.7/site-packages/typed_ast/_ast3.cpython-37m-x86_64-linux-gnu.so: undefined symbool: PyExc_KeyboardInterrupt
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you need to install `typed_ast` and `regex` directly from the source code. The
|
||||||
|
error happens because `pip` will download [Python wheels](https://pythonwheels.com/) if
|
||||||
|
they are available. Python wheels are a new standard of distributing Python packages and
|
||||||
|
packages that have Cython and extensions written in C are already compiled, so the
|
||||||
|
installation is much more faster. The problem here is that somehow the Python
|
||||||
|
environment inside Vim does not match with those already compiled C extensions and these
|
||||||
|
kind of errors are the result. Luckily there is an easy fix: installing the packages
|
||||||
|
from the source code.
|
||||||
|
|
||||||
|
The two packages that cause the problem are:
|
||||||
|
|
||||||
|
- [regex](https://pypi.org/project/regex/)
|
||||||
|
- [typed-ast](https://pypi.org/project/typed-ast/)
|
||||||
|
|
||||||
|
Now remove those two packages:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip uninstall regex typed-ast -y
|
||||||
|
```
|
||||||
|
|
||||||
|
And now you can install them with:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install --no-binary :all: regex typed-ast
|
||||||
|
```
|
||||||
|
|
||||||
|
The C extensions will be compiled and now Vim's Python environment will match. Note that
|
||||||
|
you need to have the GCC compiler and the Python development files installed (on
|
||||||
|
Ubuntu/Debian do `sudo apt-get install build-essential python3-dev`).
|
||||||
|
|
||||||
|
If you later want to update _Black_, you should do it like this:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pip install -U black --no-binary regex,typed-ast
|
||||||
|
```
|
||||||
|
|
||||||
### With ALE
|
### With ALE
|
||||||
|
|
||||||
1. Install [`ale`](https://github.com/dense-analysis/ale)
|
1. Install [`ale`](https://github.com/dense-analysis/ale)
|
||||||
@ -389,20 +283,17 @@ close and reopen your File, _Black_ will be done with its job.
|
|||||||
|
|
||||||
## Visual Studio Code
|
## Visual Studio Code
|
||||||
|
|
||||||
- Use the
|
Use the
|
||||||
[Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
|
[Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
|
||||||
([instructions](https://code.visualstudio.com/docs/python/formatting)).
|
([instructions](https://code.visualstudio.com/docs/python/editing#_formatting)).
|
||||||
|
|
||||||
- Alternatively the pre-release
|
## SublimeText 3
|
||||||
[Black Formatter](https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter)
|
|
||||||
extension can be used which runs a [Language Server Protocol](https://langserver.org/)
|
|
||||||
server for Black. Formatting is much more responsive using this extension, **but the
|
|
||||||
minimum supported version of Black is 22.3.0**.
|
|
||||||
|
|
||||||
## SublimeText
|
Use [sublack plugin](https://github.com/jgirardet/sublack).
|
||||||
|
|
||||||
For SublimeText 3, use [sublack plugin](https://github.com/jgirardet/sublack). For
|
## Jupyter Notebook Magic
|
||||||
higher versions, it is recommended to use [LSP](#python-lsp-server) as documented below.
|
|
||||||
|
Use [blackcellmagic](https://github.com/csurfer/blackcellmagic).
|
||||||
|
|
||||||
## Python LSP Server
|
## Python LSP Server
|
||||||
|
|
||||||
@ -432,4 +323,4 @@ hook global WinSetOption filetype=python %{
|
|||||||
|
|
||||||
## Thonny
|
## Thonny
|
||||||
|
|
||||||
Use [Thonny-black-formatter](https://pypi.org/project/thonny-black-formatter/).
|
Use [Thonny-black-code-format](https://github.com/Franccisco/thonny-black-code-format).
|
||||||
|
@ -8,8 +8,8 @@ environment. Great for enforcing that your code matches the _Black_ code style.
|
|||||||
This action is known to support all GitHub-hosted runner OSes. In addition, only
|
This action is known to support all GitHub-hosted runner OSes. In addition, only
|
||||||
published versions of _Black_ are supported (i.e. whatever is available on PyPI).
|
published versions of _Black_ are supported (i.e. whatever is available on PyPI).
|
||||||
|
|
||||||
Finally, this action installs _Black_ with the `colorama` extra so the `--color` flag
|
Finally, this action installs _Black_ with both the `colorama` and `python2` extras so
|
||||||
should work fine.
|
the `--color` flag and formatting Python 2 code are supported.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ jobs:
|
|||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v2
|
||||||
- uses: psf/black@stable
|
- uses: psf/black@stable
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -32,24 +32,12 @@ We recommend the use of the `@stable` tag, but per version tags also exist if yo
|
|||||||
that. Note that the action's version you select is independent of the version of _Black_
|
that. Note that the action's version you select is independent of the version of _Black_
|
||||||
the action will use.
|
the action will use.
|
||||||
|
|
||||||
The version of _Black_ the action will use can be configured via `version` or read from
|
The version of _Black_ the action will use can be configured via `version`. The action
|
||||||
the `pyproject.toml` file. `version` can be any
|
defaults to the latest release available on PyPI. Only versions available from PyPI are
|
||||||
[valid version specifier](https://packaging.python.org/en/latest/glossary/#term-Version-Specifier)
|
supported, so no commit SHAs or branch names.
|
||||||
or just the version number if you want an exact version. To read the version from the
|
|
||||||
`pyproject.toml` file instead, set `use_pyproject` to `true`. This will first look into
|
|
||||||
the `tool.black.required-version` field, then the `dependency-groups` table, then the
|
|
||||||
`project.dependencies` array and finally the `project.optional-dependencies` table. The
|
|
||||||
action defaults to the latest release available on PyPI. Only versions available from
|
|
||||||
PyPI are supported, so no commit SHAs or branch names.
|
|
||||||
|
|
||||||
If you want to include Jupyter Notebooks, _Black_ must be installed with the `jupyter`
|
|
||||||
extra. Installing the extra and including Jupyter Notebook files can be configured via
|
|
||||||
`jupyter` (default is `false`).
|
|
||||||
|
|
||||||
You can also configure the arguments passed to _Black_ via `options` (defaults to
|
You can also configure the arguments passed to _Black_ via `options` (defaults to
|
||||||
`'--check --diff'`) and `src` (default is `'.'`). Please note that the
|
`'--check --diff'`) and `src` (default is `'.'`)
|
||||||
[`--check` flag](labels/exit-code) is required so that the workflow fails if _Black_
|
|
||||||
finds files that need to be formatted.
|
|
||||||
|
|
||||||
Here's an example configuration:
|
Here's an example configuration:
|
||||||
|
|
||||||
@ -58,33 +46,5 @@ Here's an example configuration:
|
|||||||
with:
|
with:
|
||||||
options: "--check --verbose"
|
options: "--check --verbose"
|
||||||
src: "./src"
|
src: "./src"
|
||||||
jupyter: true
|
|
||||||
version: "21.5b1"
|
version: "21.5b1"
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to match versions covered by Black's
|
|
||||||
[stability policy](labels/stability-policy), you can use the compatible release operator
|
|
||||||
(`~=`):
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: psf/black@stable
|
|
||||||
with:
|
|
||||||
options: "--check --verbose"
|
|
||||||
src: "./src"
|
|
||||||
version: "~= 22.0"
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to read the version from `pyproject.toml`, set `use_pyproject` to `true`.
|
|
||||||
Note that this requires Python >= 3.11, so using the setup-python action may be
|
|
||||||
required, for example:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
- uses: psf/black@stable
|
|
||||||
with:
|
|
||||||
options: "--check --verbose"
|
|
||||||
src: "./src"
|
|
||||||
use_pyproject: true
|
|
||||||
```
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
# Integrations
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
hidden:
|
|
||||||
---
|
|
||||||
|
|
||||||
editors
|
|
||||||
github_actions
|
|
||||||
source_version_control
|
|
||||||
```
|
|
||||||
|
|
||||||
_Black_ can be integrated into many environments, providing a better and smoother
|
|
||||||
experience. Documentation for integrating _Black_ with a tool can be found for the
|
|
||||||
following areas:
|
|
||||||
|
|
||||||
- {doc}`Editor / IDE <./editors>`
|
|
||||||
- {doc}`GitHub Actions <./github_actions>`
|
|
||||||
- {doc}`Source version control <./source_version_control>`
|
|
||||||
|
|
||||||
Editors and tools not listed will require external contributions.
|
|
||||||
|
|
||||||
Patches welcome! ✨ 🍰 ✨
|
|
||||||
|
|
||||||
Any tool can pipe code through _Black_ using its stdio mode (just
|
|
||||||
[use `-` as the file name](https://www.tldp.org/LDP/abs/html/special-chars.html#DASHREF2)).
|
|
||||||
The formatted code will be returned on stdout (unless `--check` was passed). _Black_
|
|
||||||
will still emit messages on stderr but that shouldn't affect your use case.
|
|
||||||
|
|
||||||
This can be used for example with PyCharm's or IntelliJ's
|
|
||||||
[File Watchers](https://www.jetbrains.com/help/pycharm/file-watchers.html).
|
|
28
docs/integrations/index.rst
Normal file
28
docs/integrations/index.rst
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Integrations
|
||||||
|
============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
editors
|
||||||
|
github_actions
|
||||||
|
source_version_control
|
||||||
|
|
||||||
|
*Black* can be integrated into many environments, providing a better and smoother experience. Documentation for integrating *Black* with a tool can be found for the
|
||||||
|
following areas:
|
||||||
|
|
||||||
|
- :doc:`Editor / IDE <./editors>`
|
||||||
|
- :doc:`GitHub Actions <./github_actions>`
|
||||||
|
- :doc:`Source version control <./source_version_control>`
|
||||||
|
|
||||||
|
Editors and tools not listed will require external contributions.
|
||||||
|
|
||||||
|
Patches welcome! ✨ 🍰 ✨
|
||||||
|
|
||||||
|
Any tool can pipe code through *Black* using its stdio mode (just
|
||||||
|
`use \`-\` as the file name <https://www.tldp.org/LDP/abs/html/special-chars.html#DASHREF2>`_).
|
||||||
|
The formatted code will be returned on stdout (unless ``--check`` was passed). *Black*
|
||||||
|
will still emit messages on stderr but that shouldn't affect your use case.
|
||||||
|
|
||||||
|
This can be used for example with PyCharm's or IntelliJ's
|
||||||
|
`File Watchers <https://www.jetbrains.com/help/pycharm/file-watchers.html>`_.
|
@ -6,48 +6,22 @@ Use [pre-commit](https://pre-commit.com/). Once you
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
repos:
|
repos:
|
||||||
# Using this mirror lets us use mypyc-compiled black, which is about 2x faster
|
- repo: https://github.com/psf/black
|
||||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
rev: 21.8b0
|
||||||
rev: 25.1.0
|
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
# It is recommended to specify the latest version of Python
|
language_version: python3 # Should be a command that runs python3.6+
|
||||||
# supported by your project here, or alternatively use
|
|
||||||
# pre-commit's default_language_version, see
|
|
||||||
# https://pre-commit.com/#top_level-default_language_version
|
|
||||||
language_version: python3.11
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Feel free to switch out the `rev` value to a different version of Black.
|
Feel free to switch out the `rev` value to something else, like another
|
||||||
|
[tag/version][black-tags] or even a specific commit. Although we discourage the use of
|
||||||
Note if you'd like to use a specific commit in `rev`, you'll need to swap the repo
|
|
||||||
specified from the mirror to https://github.com/psf/black. We discourage the use of
|
|
||||||
branches or other mutable refs since the hook [won't auto update as you may
|
branches or other mutable refs since the hook [won't auto update as you may
|
||||||
expect][pre-commit-mutable-rev].
|
expect][pre-commit-mutable-rev].
|
||||||
|
|
||||||
## Jupyter Notebooks
|
If you want support for Jupyter Notebooks as well, then replace `id: black` with
|
||||||
|
`id: black-jupyter` (though note that it's only available from version `21.8b0`
|
||||||
There is an alternate hook `black-jupyter` that expands the targets of `black` to
|
onwards).
|
||||||
include Jupyter Notebooks. To use this hook, simply replace the hook's `id: black` with
|
|
||||||
`id: black-jupyter` in the `.pre-commit-config.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
repos:
|
|
||||||
# Using this mirror lets us use mypyc-compiled black, which is about 2x faster
|
|
||||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
||||||
rev: 25.1.0
|
|
||||||
hooks:
|
|
||||||
- id: black-jupyter
|
|
||||||
# It is recommended to specify the latest version of Python
|
|
||||||
# supported by your project here, or alternatively use
|
|
||||||
# pre-commit's default_language_version, see
|
|
||||||
# https://pre-commit.com/#top_level-default_language_version
|
|
||||||
language_version: python3.11
|
|
||||||
```
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
The `black-jupyter` hook became available in version 21.8b0.
|
|
||||||
```
|
|
||||||
|
|
||||||
|
[black-tags]: https://github.com/psf/black/tags
|
||||||
[pre-commit-mutable-rev]:
|
[pre-commit-mutable-rev]:
|
||||||
https://pre-commit.com/#using-the-latest-version-for-a-repository
|
https://pre-commit.com/#using-the-latest-version-for-a-repository
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
orphan: true
|
|
||||||
---
|
|
||||||
|
|
||||||
# License
|
|
||||||
|
|
||||||
```{include} ../LICENSE
|
|
||||||
|
|
||||||
```
|
|
6
docs/license.rst
Normal file
6
docs/license.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
:orphan:
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. include:: ../LICENSE
|
@ -1,9 +1,6 @@
|
|||||||
# Used by ReadTheDocs; pinned requirements for stability.
|
# Used by ReadTheDocs; pinned requirements for stability.
|
||||||
|
|
||||||
myst-parser==4.0.1
|
myst-parser==0.15.1
|
||||||
Sphinx==8.2.3
|
Sphinx==4.1.2
|
||||||
# Older versions break Sphinx even though they're declared to be supported.
|
sphinxcontrib-programoutput==0.17
|
||||||
docutils==0.21.2
|
sphinx_copybutton==0.4.0
|
||||||
sphinxcontrib-programoutput==0.18
|
|
||||||
sphinx_copybutton==0.5.2
|
|
||||||
furo==2024.8.6
|
|
||||||
|
@ -2,21 +2,20 @@
|
|||||||
|
|
||||||
## Code style
|
## Code style
|
||||||
|
|
||||||
_Black_ aims for consistency, generality, readability and reducing git diffs. Similar
|
_Black_ reformats entire files in place. Style configuration options are deliberately
|
||||||
language constructs are formatted with similar rules. Style configuration options are
|
limited and rarely added. It doesn't take previous formatting into account, except for
|
||||||
deliberately limited and rarely added. Previous formatting is taken into account as
|
the magic trailing comma and preserving newlines. It doesn't reformat blocks that start
|
||||||
little as possible, with rare exceptions like the magic trailing comma. The coding style
|
with `# fmt: off` and end with `# fmt: on`, or lines that ends with `# fmt: skip`.
|
||||||
used by _Black_ can be viewed as a strict subset of PEP 8.
|
`# fmt: on/off` have to be on the same level of indentation. It also recognizes
|
||||||
|
[YAPF](https://github.com/google/yapf)'s block comments to the same effect, as a
|
||||||
This document describes the current formatting style. If you're interested in trying out
|
courtesy for straddling code.
|
||||||
where the style is heading, see [future style](./future_style.md) and try running
|
|
||||||
`black --preview`.
|
|
||||||
|
|
||||||
### How _Black_ wraps lines
|
### How _Black_ wraps lines
|
||||||
|
|
||||||
_Black_ ignores previous formatting and applies uniform horizontal and vertical
|
_Black_ ignores previous formatting and applies uniform horizontal and vertical
|
||||||
whitespace to your code. The rules for horizontal whitespace can be summarized as: do
|
whitespace to your code. The rules for horizontal whitespace can be summarized as: do
|
||||||
whatever makes `pycodestyle` happy.
|
whatever makes `pycodestyle` happy. The coding style used by _Black_ can be viewed as a
|
||||||
|
strict subset of PEP 8.
|
||||||
|
|
||||||
As for vertical whitespace, _Black_ tries to render one full expression or simple
|
As for vertical whitespace, _Black_ tries to render one full expression or simple
|
||||||
statement per line. If this fits the allotted line length, great.
|
statement per line. If this fits the allotted line length, great.
|
||||||
@ -78,19 +77,6 @@ def very_important_function(
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
If a data structure literal (tuple, list, set, dict) or a line of "from" imports cannot
|
|
||||||
fit in the allotted length, it's always split into one element per line. This minimizes
|
|
||||||
diffs as well as enables readers of code to find which commit introduced a particular
|
|
||||||
entry. This also makes _Black_ compatible with
|
|
||||||
[isort](../guides/using_black_with_other_tools.md#isort) with the ready-made `black`
|
|
||||||
profile or manual configuration.
|
|
||||||
|
|
||||||
You might have noticed that closing brackets are always dedented and that a trailing
|
|
||||||
comma is always added. Such formatting produces smaller diffs; when you add or remove an
|
|
||||||
element, it's always just one line. Also, having the closing bracket dedented provides a
|
|
||||||
clear delimiter between two distinct sections of the code that otherwise share the same
|
|
||||||
indentation level (like the arguments list and the docstring in the example above).
|
|
||||||
|
|
||||||
(labels/why-no-backslashes)=
|
(labels/why-no-backslashes)=
|
||||||
|
|
||||||
_Black_ prefers parentheses over backslashes, and will remove backslashes if found.
|
_Black_ prefers parentheses over backslashes, and will remove backslashes if found.
|
||||||
@ -133,7 +119,18 @@ If you're reaching for backslashes, that's a clear signal that you can do better
|
|||||||
slightly refactor your code. I hope some of the examples above show you that there are
|
slightly refactor your code. I hope some of the examples above show you that there are
|
||||||
many ways in which you can do it.
|
many ways in which you can do it.
|
||||||
|
|
||||||
(labels/line-length)=
|
You might have noticed that closing brackets are always dedented and that a trailing
|
||||||
|
comma is always added. Such formatting produces smaller diffs; when you add or remove an
|
||||||
|
element, it's always just one line. Also, having the closing bracket dedented provides a
|
||||||
|
clear delimiter between two distinct sections of the code that otherwise share the same
|
||||||
|
indentation level (like the arguments list and the docstring in the example above).
|
||||||
|
|
||||||
|
If a data structure literal (tuple, list, set, dict) or a line of "from" imports cannot
|
||||||
|
fit in the allotted length, it's always split into one element per line. This minimizes
|
||||||
|
diffs as well as enables readers of code to find which commit introduced a particular
|
||||||
|
entry. This also makes _Black_ compatible with
|
||||||
|
[isort](../guides/using_black_with_other_tools.md#isort) with the ready-made `black`
|
||||||
|
profile or manual configuration.
|
||||||
|
|
||||||
### Line length
|
### Line length
|
||||||
|
|
||||||
@ -143,7 +140,7 @@ significantly shorter files than sticking with 80 (the most popular), or even 79
|
|||||||
by the standard library). In general,
|
by the standard library). In general,
|
||||||
[90-ish seems like the wise choice](https://youtu.be/wf-BqAjZb8M?t=260).
|
[90-ish seems like the wise choice](https://youtu.be/wf-BqAjZb8M?t=260).
|
||||||
|
|
||||||
If you're paid by the lines of code you write, you can pass `--line-length` with a lower
|
If you're paid by the line of code you write, you can pass `--line-length` with a lower
|
||||||
number. _Black_ will try to respect that. However, sometimes it won't be able to without
|
number. _Black_ will try to respect that. However, sometimes it won't be able to without
|
||||||
breaking other rules. In those rare cases, auto-formatted code will exceed your allotted
|
breaking other rules. In those rare cases, auto-formatted code will exceed your allotted
|
||||||
limit.
|
limit.
|
||||||
@ -153,10 +150,33 @@ harder to work with line lengths exceeding 100 characters. It also adversely aff
|
|||||||
side-by-side diff review on typical screen resolutions. Long lines also make it harder
|
side-by-side diff review on typical screen resolutions. Long lines also make it harder
|
||||||
to present code neatly in documentation or talk slides.
|
to present code neatly in documentation or talk slides.
|
||||||
|
|
||||||
#### Flake8 and other linters
|
If you're using Flake8, you can bump `max-line-length` to 88 and mostly forget about it.
|
||||||
|
However, it's better if you use [Bugbear](https://github.com/PyCQA/flake8-bugbear)'s
|
||||||
|
B950 warning instead of E501, and bump the max line length to 88 (or the `--line-length`
|
||||||
|
you used for black), which will align more with black's _"try to respect
|
||||||
|
`--line-length`, but don't become crazy if you can't"_. You'd do it like this:
|
||||||
|
|
||||||
See [Using _Black_ with other tools](../guides/using_black_with_other_tools.md) about
|
```ini
|
||||||
linter compatibility.
|
[flake8]
|
||||||
|
max-line-length = 88
|
||||||
|
...
|
||||||
|
select = C,E,F,W,B,B950
|
||||||
|
extend-ignore = E203, E501
|
||||||
|
```
|
||||||
|
|
||||||
|
Explanation of why E203 is disabled can be found further in this documentation. And if
|
||||||
|
you're curious about the reasoning behind B950,
|
||||||
|
[Bugbear's documentation](https://github.com/PyCQA/flake8-bugbear#opinionated-warnings)
|
||||||
|
explains it. The tl;dr is "it's like highway speed limits, we won't bother you if you
|
||||||
|
overdo it by a few km/h".
|
||||||
|
|
||||||
|
**If you're looking for a minimal, black-compatible flake8 configuration:**
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[flake8]
|
||||||
|
max-line-length = 88
|
||||||
|
extend-ignore = E203
|
||||||
|
```
|
||||||
|
|
||||||
### Empty lines
|
### Empty lines
|
||||||
|
|
||||||
@ -168,35 +188,6 @@ lines on module level left by the original editors, except when they're within
|
|||||||
parenthesized expressions. Since such expressions are always reformatted to fit minimal
|
parenthesized expressions. Since such expressions are always reformatted to fit minimal
|
||||||
space, this whitespace is lost.
|
space, this whitespace is lost.
|
||||||
|
|
||||||
```python
|
|
||||||
# in:
|
|
||||||
|
|
||||||
def function(
|
|
||||||
some_argument: int,
|
|
||||||
|
|
||||||
other_argument: int = 5,
|
|
||||||
) -> EmptyLineInParenWillBeDeleted:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("One empty line above me will be kept!")
|
|
||||||
|
|
||||||
def this_is_okay_too():
|
|
||||||
print("No empty line here")
|
|
||||||
# out:
|
|
||||||
|
|
||||||
def function(
|
|
||||||
some_argument: int,
|
|
||||||
other_argument: int = 5,
|
|
||||||
) -> EmptyLineInParenWillBeDeleted:
|
|
||||||
|
|
||||||
print("One empty line above me will be kept!")
|
|
||||||
|
|
||||||
|
|
||||||
def this_is_okay_too():
|
|
||||||
print("No empty line here")
|
|
||||||
```
|
|
||||||
|
|
||||||
It will also insert proper spacing before and after function definitions. It's one line
|
It will also insert proper spacing before and after function definitions. It's one line
|
||||||
before and after inner functions and two lines before and after module-level functions
|
before and after inner functions and two lines before and after module-level functions
|
||||||
and classes. _Black_ will not put empty lines between function/class definitions and
|
and classes. _Black_ will not put empty lines between function/class definitions and
|
||||||
@ -213,12 +204,11 @@ required due to an inner function starting immediately after.
|
|||||||
|
|
||||||
_Black_ does not format comment contents, but it enforces two spaces between code and a
|
_Black_ does not format comment contents, but it enforces two spaces between code and a
|
||||||
comment on the same line, and a space before the comment text begins. Some types of
|
comment on the same line, and a space before the comment text begins. Some types of
|
||||||
comments that require specific spacing rules are respected: shebangs (`#! comment`), doc
|
comments that require specific spacing rules are respected: doc comments (`#: comment`),
|
||||||
comments (`#: comment`), section comments with long runs of hashes, and Spyder cells.
|
section comments with long runs of hashes, and Spyder cells. Non-breaking spaces after
|
||||||
Non-breaking spaces after hashes are also preserved. Comments may sometimes be moved
|
hashes are also preserved. Comments may sometimes be moved because of formatting
|
||||||
because of formatting changes, which can break tools that assign special meaning to
|
changes, which can break tools that assign special meaning to them. See
|
||||||
them. See [AST before and after formatting](#ast-before-and-after-formatting) for more
|
[AST before and after formatting](#ast-before-and-after-formatting) for more discussion.
|
||||||
discussion.
|
|
||||||
|
|
||||||
### Trailing commas
|
### Trailing commas
|
||||||
|
|
||||||
@ -237,23 +227,16 @@ A pre-existing trailing comma informs _Black_ to always explode contents of the
|
|||||||
bracket pair into one item per line. Read more about this in the
|
bracket pair into one item per line. Read more about this in the
|
||||||
[Pragmatism](#pragmatism) section below.
|
[Pragmatism](#pragmatism) section below.
|
||||||
|
|
||||||
(labels/strings)=
|
|
||||||
|
|
||||||
### Strings
|
### Strings
|
||||||
|
|
||||||
_Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`). It
|
_Black_ prefers double quotes (`"` and `"""`) over single quotes (`'` and `'''`). It
|
||||||
will replace the latter with the former as long as it does not result in more backslash
|
will replace the latter with the former as long as it does not result in more backslash
|
||||||
escapes than before.
|
escapes than before.
|
||||||
|
|
||||||
_Black_ also standardizes string prefixes. Prefix characters are made lowercase with the
|
_Black_ also standardizes string prefixes, making them always lowercase. On top of that,
|
||||||
exception of [capital "R" prefixes](#rstrings-and-rstrings), unicode literal markers
|
if your code is already Python 3.6+ only or it's using the `unicode_literals` future
|
||||||
(`u`) are removed because they are meaningless in Python 3, and in the case of multiple
|
import, _Black_ will remove `u` from the string prefix as it is meaningless in those
|
||||||
characters "r" is put first as in spoken language: "raw f-string".
|
scenarios.
|
||||||
|
|
||||||
Another area where Python allows multiple ways to format a string is escape sequences.
|
|
||||||
For example, `"\uabcd"` and `"\uABCD"` evaluate to the same string. _Black_ normalizes
|
|
||||||
such escape sequences to lowercase, but uses uppercase for `\N` named character escapes,
|
|
||||||
such as `"\N{MEETEI MAYEK LETTER HUK}"`.
|
|
||||||
|
|
||||||
The main reason to standardize on a single form of quotes is aesthetics. Having one kind
|
The main reason to standardize on a single form of quotes is aesthetics. Having one kind
|
||||||
of quotes everywhere reduces reader distraction. It will also enable a future version of
|
of quotes everywhere reduces reader distraction. It will also enable a future version of
|
||||||
@ -277,6 +260,16 @@ If you are adopting _Black_ in a large project with pre-existing string conventi
|
|||||||
you can pass `--skip-string-normalization` on the command line. This is meant as an
|
you can pass `--skip-string-normalization` on the command line. This is meant as an
|
||||||
adoption helper, avoid using this for new projects.
|
adoption helper, avoid using this for new projects.
|
||||||
|
|
||||||
|
(labels/experimental-string)=
|
||||||
|
|
||||||
|
As an experimental option (can be enabled by `--experimental-string-processing`),
|
||||||
|
_Black_ splits long strings (using parentheses where appropriate) and merges short ones.
|
||||||
|
When split, parts of f-strings that don't need formatting are converted to plain
|
||||||
|
strings. User-made splits are respected when they do not exceed the line length limit.
|
||||||
|
Line continuation backslashes are converted into parenthesized strings. Unnecessary
|
||||||
|
parentheses are stripped. Because the functionality is experimental, feedback and issue
|
||||||
|
reports are highly encouraged!
|
||||||
|
|
||||||
_Black_ also processes docstrings. Firstly the indentation of docstrings is corrected
|
_Black_ also processes docstrings. Firstly the indentation of docstrings is corrected
|
||||||
for both quotations and the text within, although relative indentation in the text is
|
for both quotations and the text within, although relative indentation in the text is
|
||||||
preserved. Superfluous trailing whitespace on each line and unnecessary new lines at the
|
preserved. Superfluous trailing whitespace on each line and unnecessary new lines at the
|
||||||
@ -288,7 +281,8 @@ removed.
|
|||||||
|
|
||||||
_Black_ standardizes most numeric literals to use lowercase letters for the syntactic
|
_Black_ standardizes most numeric literals to use lowercase letters for the syntactic
|
||||||
parts and uppercase letters for the digits themselves: `0xAB` instead of `0XAB` and
|
parts and uppercase letters for the digits themselves: `0xAB` instead of `0XAB` and
|
||||||
`1e10` instead of `1E10`.
|
`1e10` instead of `1E10`. Python 2 long literals are styled as `2L` instead of `2l` to
|
||||||
|
avoid confusion between `l` and `1`.
|
||||||
|
|
||||||
### Line breaks & binary operators
|
### Line breaks & binary operators
|
||||||
|
|
||||||
@ -297,26 +291,6 @@ multiple lines. This is so that _Black_ is compliant with the recent changes in
|
|||||||
[PEP 8](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
|
[PEP 8](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
|
||||||
style guide, which emphasizes that this approach improves readability.
|
style guide, which emphasizes that this approach improves readability.
|
||||||
|
|
||||||
Almost all operators will be surrounded by single spaces, the only exceptions are unary
|
|
||||||
operators (`+`, `-`, and `~`), and power operators when both operands are simple. For
|
|
||||||
powers, an operand is considered simple if it's only a NAME, numeric CONSTANT, or
|
|
||||||
attribute access (chained attribute access is allowed), with or without a preceding
|
|
||||||
unary operator.
|
|
||||||
|
|
||||||
```python
|
|
||||||
# For example, these won't be surrounded by whitespace
|
|
||||||
a = x**y
|
|
||||||
b = config.base**5.2
|
|
||||||
c = config.base**runtime.config.exponent
|
|
||||||
d = 2**5
|
|
||||||
e = 2**~5
|
|
||||||
|
|
||||||
# ... but these will be surrounded by whitespace
|
|
||||||
f = 2 ** get_exponent()
|
|
||||||
g = get_x() ** get_y()
|
|
||||||
h = config['base'] ** 2
|
|
||||||
```
|
|
||||||
|
|
||||||
### Slices
|
### Slices
|
||||||
|
|
||||||
PEP 8
|
PEP 8
|
||||||
@ -409,22 +383,16 @@ recommended code style for those files is more terse than PEP 8:
|
|||||||
_Black_ enforces the above rules. There are additional guidelines for formatting `.pyi`
|
_Black_ enforces the above rules. There are additional guidelines for formatting `.pyi`
|
||||||
file that are not enforced yet but might be in a future version of the formatter:
|
file that are not enforced yet but might be in a future version of the formatter:
|
||||||
|
|
||||||
|
- all function bodies should be empty (contain `...` instead of the body);
|
||||||
|
- do not use docstrings;
|
||||||
- prefer `...` over `pass`;
|
- prefer `...` over `pass`;
|
||||||
|
- for arguments with a default, use `...` instead of the actual default;
|
||||||
- avoid using string literals in type annotations, stub files support forward references
|
- avoid using string literals in type annotations, stub files support forward references
|
||||||
natively (like Python 3.7 code with `from __future__ import annotations`);
|
natively (like Python 3.7 code with `from __future__ import annotations`);
|
||||||
- use variable annotations instead of type comments, even for stubs that target older
|
- use variable annotations instead of type comments, even for stubs that target older
|
||||||
versions of Python.
|
versions of Python;
|
||||||
|
- for arguments that default to `None`, use `Optional[]` explicitly;
|
||||||
### Line endings
|
- use `float` instead of `Union[int, float]`.
|
||||||
|
|
||||||
_Black_ will normalize line endings (`\n` or `\r\n`) based on the first line ending of
|
|
||||||
the file.
|
|
||||||
|
|
||||||
### Form feed characters
|
|
||||||
|
|
||||||
_Black_ will retain form feed characters on otherwise empty lines at the module level.
|
|
||||||
Only one form feed is retained for a group of consecutive empty lines. Where there are
|
|
||||||
two empty lines in a row, the form feed is placed on the second line.
|
|
||||||
|
|
||||||
## Pragmatism
|
## Pragmatism
|
||||||
|
|
||||||
@ -434,8 +402,6 @@ there were not many users anyway. Not many edge cases were reported. As a mature
|
|||||||
_Black_ does make some exceptions to rules it otherwise holds. This section documents
|
_Black_ does make some exceptions to rules it otherwise holds. This section documents
|
||||||
what those exceptions are and why this is the case.
|
what those exceptions are and why this is the case.
|
||||||
|
|
||||||
(labels/magic-trailing-comma)=
|
|
||||||
|
|
||||||
### The magic trailing comma
|
### The magic trailing comma
|
||||||
|
|
||||||
_Black_ in general does not take existing formatting into account.
|
_Black_ in general does not take existing formatting into account.
|
||||||
@ -472,19 +438,17 @@ default by (among others) GitHub and Visual Studio Code, differentiates between
|
|||||||
r-strings and R-strings. The former are syntax highlighted as regular expressions while
|
r-strings and R-strings. The former are syntax highlighted as regular expressions while
|
||||||
the latter are treated as true raw strings with no special semantics.
|
the latter are treated as true raw strings with no special semantics.
|
||||||
|
|
||||||
(labels/ast-changes)=
|
|
||||||
|
|
||||||
### AST before and after formatting
|
### AST before and after formatting
|
||||||
|
|
||||||
When run with `--safe` (the default), _Black_ checks that the code before and after is
|
When run with `--safe`, _Black_ checks that the code before and after is semantically
|
||||||
semantically equivalent. This check is done by comparing the AST of the source with the
|
equivalent. This check is done by comparing the AST of the source with the AST of the
|
||||||
AST of the target. There are three limited cases in which the AST does differ:
|
target. There are three limited cases in which the AST does differ:
|
||||||
|
|
||||||
1. _Black_ cleans up leading and trailing whitespace of docstrings, re-indenting them if
|
1. _Black_ cleans up leading and trailing whitespace of docstrings, re-indenting them if
|
||||||
needed. It's been one of the most popular user-reported features for the formatter to
|
needed. It's been one of the most popular user-reported features for the formatter to
|
||||||
fix whitespace issues with docstrings. While the result is technically an AST
|
fix whitespace issues with docstrings. While the result is technically an AST
|
||||||
difference, due to the various possibilities of forming docstrings, all real-world
|
difference, due to the various possibilities of forming docstrings, all realtime use
|
||||||
uses of docstrings that we're aware of sanitize indentation and leading/trailing
|
of docstrings that we're aware of sanitizes indentation and leading/trailing
|
||||||
whitespace anyway.
|
whitespace anyway.
|
||||||
|
|
||||||
1. _Black_ manages optional parentheses for some statements. In the case of the `del`
|
1. _Black_ manages optional parentheses for some statements. In the case of the `del`
|
||||||
|
@ -1,269 +1,42 @@
|
|||||||
# The (future of the) Black code style
|
# The (future of the) Black code style
|
||||||
|
|
||||||
## Preview style
|
```{warning}
|
||||||
|
Changes to this document often aren't tied and don't relate to releases of
|
||||||
(labels/preview-style)=
|
_Black_. It's recommended that you read the latest version available.
|
||||||
|
|
||||||
Experimental, potentially disruptive style changes are gathered under the `--preview`
|
|
||||||
CLI flag. At the end of each year, these changes may be adopted into the default style,
|
|
||||||
as described in [The Black Code Style](index.md). Because the functionality is
|
|
||||||
experimental, feedback and issue reports are highly encouraged!
|
|
||||||
|
|
||||||
In the past, the preview style included some features with known bugs, so that we were
|
|
||||||
unable to move these features to the stable style. Therefore, such features are now
|
|
||||||
moved to the `--unstable` style. All features in the `--preview` style are expected to
|
|
||||||
make it to next year's stable style; features in the `--unstable` style will be
|
|
||||||
stabilized only if issues with them are fixed. If bugs are discovered in a `--preview`
|
|
||||||
feature, it is demoted to the `--unstable` style. To avoid thrash when a feature is
|
|
||||||
demoted from the `--preview` to the `--unstable` style, users can use the
|
|
||||||
`--enable-unstable-feature` flag to enable specific unstable features.
|
|
||||||
|
|
||||||
(labels/preview-features)=
|
|
||||||
|
|
||||||
Currently, the following features are included in the preview style:
|
|
||||||
|
|
||||||
- `always_one_newline_after_import`: Always force one blank line after import
|
|
||||||
statements, except when the line after the import is a comment or an import statement
|
|
||||||
- `wrap_long_dict_values_in_parens`: Add parentheses around long values in dictionaries
|
|
||||||
([see below](labels/wrap-long-dict-values))
|
|
||||||
- `fix_fmt_skip_in_one_liners`: Fix `# fmt: skip` behaviour on one-liner declarations,
|
|
||||||
such as `def foo(): return "mock" # fmt: skip`, where previously the declaration
|
|
||||||
would have been incorrectly collapsed.
|
|
||||||
|
|
||||||
(labels/unstable-features)=
|
|
||||||
|
|
||||||
The unstable style additionally includes the following features:
|
|
||||||
|
|
||||||
- `string_processing`: split long string literals and related changes
|
|
||||||
([see below](labels/string-processing))
|
|
||||||
- `multiline_string_handling`: more compact formatting of expressions involving
|
|
||||||
multiline strings ([see below](labels/multiline-string-handling))
|
|
||||||
- `hug_parens_with_braces_and_square_brackets`: more compact formatting of nested
|
|
||||||
brackets ([see below](labels/hug-parens))
|
|
||||||
|
|
||||||
(labels/wrap-long-dict-values)=
|
|
||||||
|
|
||||||
### Improved parentheses management in dicts
|
|
||||||
|
|
||||||
For dict literals with long values, they are now wrapped in parentheses. Unnecessary
|
|
||||||
parentheses are now removed. For example:
|
|
||||||
|
|
||||||
```python
|
|
||||||
my_dict = {
|
|
||||||
"a key in my dict": a_very_long_variable
|
|
||||||
* and_a_very_long_function_call()
|
|
||||||
/ 100000.0,
|
|
||||||
"another key": (short_value),
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
will be changed to:
|
## Using backslashes for with statements
|
||||||
|
|
||||||
```python
|
[Backslashes are bad and should be never be used](labels/why-no-backslashes) however
|
||||||
my_dict = {
|
there is one exception: `with` statements using multiple context managers. Before Python
|
||||||
"a key in my dict": (
|
3.9 Python's grammar does not allow organizing parentheses around the series of context
|
||||||
a_very_long_variable * and_a_very_long_function_call() / 100000.0
|
managers.
|
||||||
),
|
|
||||||
"another key": short_value,
|
We don't want formatting like:
|
||||||
}
|
|
||||||
|
```py3
|
||||||
|
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
|
||||||
|
... # nothing to split on - line too long
|
||||||
```
|
```
|
||||||
|
|
||||||
(labels/hug-parens)=
|
So _Black_ will eventually format it like this:
|
||||||
|
|
||||||
### Improved multiline dictionary and list indentation for sole function parameter
|
```py3
|
||||||
|
with \
|
||||||
For better readability and less verticality, _Black_ now pairs parentheses ("(", ")")
|
make_context_manager(1) as cm1, \
|
||||||
with braces ("{", "}") and square brackets ("[", "]") on the same line. For example:
|
make_context_manager(2) as cm2, \
|
||||||
|
make_context_manager(3) as cm3, \
|
||||||
```python
|
make_context_manager(4) as cm4 \
|
||||||
foo(
|
:
|
||||||
[
|
... # backslashes and an ugly stranded colon
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
nested_array = [
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
]
|
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
will be changed to:
|
Although when the target version is Python 3.9 or higher, _Black_ will use parentheses
|
||||||
|
instead since they're allowed in Python 3.9 and higher.
|
||||||
|
|
||||||
```python
|
## Improved string processing
|
||||||
foo([
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
])
|
|
||||||
|
|
||||||
nested_array = [[
|
Currently, _Black_ does not split long strings to fit the line length limit. Currently,
|
||||||
1,
|
there is [an experimental option](labels/experimental-string) to enable splitting
|
||||||
2,
|
strings. We plan to enable this option by default once it is fully stable. This is
|
||||||
3,
|
tracked in [this issue](https://github.com/psf/black/issues/2188).
|
||||||
]]
|
|
||||||
```
|
|
||||||
|
|
||||||
This also applies to list and dictionary unpacking:
|
|
||||||
|
|
||||||
```python
|
|
||||||
foo(
|
|
||||||
*[
|
|
||||||
a_long_function_name(a_long_variable_name)
|
|
||||||
for a_long_variable_name in some_generator
|
|
||||||
]
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
will become:
|
|
||||||
|
|
||||||
```python
|
|
||||||
foo(*[
|
|
||||||
a_long_function_name(a_long_variable_name)
|
|
||||||
for a_long_variable_name in some_generator
|
|
||||||
])
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use a magic trailing comma to avoid this compacting behavior; by default,
|
|
||||||
_Black_ will not reformat the following code:
|
|
||||||
|
|
||||||
```python
|
|
||||||
foo(
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
(labels/string-processing)=
|
|
||||||
|
|
||||||
### Improved string processing
|
|
||||||
|
|
||||||
_Black_ will split long string literals and merge short ones. Parentheses are used where
|
|
||||||
appropriate. When split, parts of f-strings that don't need formatting are converted to
|
|
||||||
plain strings. f-strings will not be merged if they contain internal quotes and it would
|
|
||||||
change their quotation mark style. User-made splits are respected when they do not
|
|
||||||
exceed the line length limit. Line continuation backslashes are converted into
|
|
||||||
parenthesized strings. Unnecessary parentheses are stripped. The stability and status of
|
|
||||||
this feature istracked in [this issue](https://github.com/psf/black/issues/2188).
|
|
||||||
|
|
||||||
(labels/multiline-string-handling)=
|
|
||||||
|
|
||||||
### Improved multiline string handling
|
|
||||||
|
|
||||||
_Black_ is smarter when formatting multiline strings, especially in function arguments,
|
|
||||||
to avoid introducing extra line breaks. Previously, it would always consider multiline
|
|
||||||
strings as not fitting on a single line. With this new feature, _Black_ looks at the
|
|
||||||
context around the multiline string to decide if it should be inlined or split to a
|
|
||||||
separate line. For example, when a multiline string is passed to a function, _Black_
|
|
||||||
will only split the multiline string if a line is too long or if multiple arguments are
|
|
||||||
being passed.
|
|
||||||
|
|
||||||
For example, _Black_ will reformat
|
|
||||||
|
|
||||||
```python
|
|
||||||
textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
This is a
|
|
||||||
multiline string
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
to:
|
|
||||||
|
|
||||||
```python
|
|
||||||
textwrap.dedent("""\
|
|
||||||
This is a
|
|
||||||
multiline string
|
|
||||||
""")
|
|
||||||
```
|
|
||||||
|
|
||||||
And:
|
|
||||||
|
|
||||||
```python
|
|
||||||
MULTILINE = """
|
|
||||||
foobar
|
|
||||||
""".replace(
|
|
||||||
"\n", ""
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
to:
|
|
||||||
|
|
||||||
```python
|
|
||||||
MULTILINE = """
|
|
||||||
foobar
|
|
||||||
""".replace("\n", "")
|
|
||||||
```
|
|
||||||
|
|
||||||
Implicit multiline strings are special, because they can have inline comments. Strings
|
|
||||||
without comments are merged, for example
|
|
||||||
|
|
||||||
```python
|
|
||||||
s = (
|
|
||||||
"An "
|
|
||||||
"implicit "
|
|
||||||
"multiline "
|
|
||||||
"string"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
becomes
|
|
||||||
|
|
||||||
```python
|
|
||||||
s = "An implicit multiline string"
|
|
||||||
```
|
|
||||||
|
|
||||||
A comment on any line of the string (or between two string lines) will block the
|
|
||||||
merging, so
|
|
||||||
|
|
||||||
```python
|
|
||||||
s = (
|
|
||||||
"An " # Important comment concerning just this line
|
|
||||||
"implicit "
|
|
||||||
"multiline "
|
|
||||||
"string"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
and
|
|
||||||
|
|
||||||
```python
|
|
||||||
s = (
|
|
||||||
"An "
|
|
||||||
"implicit "
|
|
||||||
# Comment in between
|
|
||||||
"multiline "
|
|
||||||
"string"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
will not be merged. Having the comment after or before the string lines (but still
|
|
||||||
inside the parens) will merge the string. For example
|
|
||||||
|
|
||||||
```python
|
|
||||||
s = ( # Top comment
|
|
||||||
"An "
|
|
||||||
"implicit "
|
|
||||||
"multiline "
|
|
||||||
"string"
|
|
||||||
# Bottom comment
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
becomes
|
|
||||||
|
|
||||||
```python
|
|
||||||
s = ( # Top comment
|
|
||||||
"An implicit multiline string"
|
|
||||||
# Bottom comment
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
# The Black Code Style
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
hidden:
|
|
||||||
---
|
|
||||||
|
|
||||||
Current style <current_style>
|
|
||||||
Future style <future_style>
|
|
||||||
```
|
|
||||||
|
|
||||||
_Black_ is a PEP 8 compliant opinionated formatter with its own style.
|
|
||||||
|
|
||||||
While keeping the style unchanged throughout releases has always been a goal, the
|
|
||||||
_Black_ code style isn't set in stone. It evolves to accommodate for new features in the
|
|
||||||
Python language and, occasionally, in response to user feedback. Large-scale style
|
|
||||||
preferences presented in {doc}`current_style` are very unlikely to change, but minor
|
|
||||||
style aspects and details might change according to the stability policy presented
|
|
||||||
below. Ongoing style considerations are tracked on GitHub with the
|
|
||||||
[style](https://github.com/psf/black/labels/T%3A%20style) issue label.
|
|
||||||
|
|
||||||
(labels/stability-policy)=
|
|
||||||
|
|
||||||
## Stability Policy
|
|
||||||
|
|
||||||
The following policy applies for the _Black_ code style, in non pre-release versions of
|
|
||||||
_Black_:
|
|
||||||
|
|
||||||
- If code has been formatted with _Black_, it will remain unchanged when formatted with
|
|
||||||
the same options using any other release in the same calendar year.
|
|
||||||
|
|
||||||
This means projects can safely use `black ~= 22.0` without worrying about formatting
|
|
||||||
changes disrupting their project in 2022. We may still fix bugs where _Black_ crashes
|
|
||||||
on some code, and make other improvements that do not affect formatting.
|
|
||||||
|
|
||||||
In rare cases, we may make changes affecting code that has not been previously
|
|
||||||
formatted with _Black_. For example, we have had bugs where we accidentally removed
|
|
||||||
some comments. Such bugs can be fixed without breaking the stability policy.
|
|
||||||
|
|
||||||
- The first release in a new calendar year _may_ contain formatting changes, although
|
|
||||||
these will be minimised as much as possible. This is to allow for improved formatting
|
|
||||||
enabled by newer Python language syntax as well as due to improvements in the
|
|
||||||
formatting logic.
|
|
||||||
|
|
||||||
- The `--preview` and `--unstable` flags are exempt from this policy. There are no
|
|
||||||
guarantees around the stability of the output with these flags passed into _Black_.
|
|
||||||
They are intended for allowing experimentation with proposed changes to the _Black_
|
|
||||||
code style. The `--preview` style at the end of a year should closely match the stable
|
|
||||||
style for the next year, but we may always make changes.
|
|
||||||
|
|
||||||
Documentation for both the current and future styles can be found:
|
|
||||||
|
|
||||||
- {doc}`current_style`
|
|
||||||
- {doc}`future_style`
|
|
19
docs/the_black_code_style/index.rst
Normal file
19
docs/the_black_code_style/index.rst
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
The Black Code Style
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
Current style <current_style>
|
||||||
|
Future style <future_style>
|
||||||
|
|
||||||
|
*Black* is a PEP 8 compliant opinionated formatter with its own style.
|
||||||
|
|
||||||
|
It should be noted that while keeping the style unchanged throughout releases is a
|
||||||
|
goal, the *Black* code style isn't set in stone. Sometimes it's modified in response to
|
||||||
|
user feedback or even changes to the Python language!
|
||||||
|
|
||||||
|
Documentation for both the current and future styles can be found:
|
||||||
|
|
||||||
|
- :doc:`current_style`
|
||||||
|
- :doc:`future_style`
|
@ -4,15 +4,10 @@
|
|||||||
protocol. The main benefit of using it is to avoid the cost of starting up a new _Black_
|
protocol. The main benefit of using it is to avoid the cost of starting up a new _Black_
|
||||||
process every time you want to blacken a file.
|
process every time you want to blacken a file.
|
||||||
|
|
||||||
```{warning}
|
|
||||||
`blackd` should not be run as a publicly accessible server as there are no security
|
|
||||||
precautions in place to prevent abuse. **It is intended for local use only**.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`blackd` is not packaged alongside _Black_ by default because it has additional
|
`blackd` is not packaged alongside _Black_ by default because it has additional
|
||||||
dependencies. You will need to execute `pip install 'black[d]'` to install it.
|
dependencies. You will need to execute `pip install black[d]` to install it.
|
||||||
|
|
||||||
You can start the server on the default port, binding only to the local interface by
|
You can start the server on the default port, binding only to the local interface by
|
||||||
running `blackd`. You will see a single line mentioning the server's version, and the
|
running `blackd`. You will see a single line mentioning the server's version, and the
|
||||||
@ -50,24 +45,12 @@ is rejected with `HTTP 501` (Not Implemented).
|
|||||||
The headers controlling how source code is formatted are:
|
The headers controlling how source code is formatted are:
|
||||||
|
|
||||||
- `X-Line-Length`: corresponds to the `--line-length` command line flag.
|
- `X-Line-Length`: corresponds to the `--line-length` command line flag.
|
||||||
- `X-Skip-Source-First-Line`: corresponds to the `--skip-source-first-line` command line
|
|
||||||
flag. If present and its value is not an empty string, the first line of the source
|
|
||||||
code will be ignored.
|
|
||||||
- `X-Skip-String-Normalization`: corresponds to the `--skip-string-normalization`
|
- `X-Skip-String-Normalization`: corresponds to the `--skip-string-normalization`
|
||||||
command line flag. If present and its value is not the empty string, no string
|
command line flag. If present and its value is not the empty string, no string
|
||||||
normalization will be performed.
|
normalization will be performed.
|
||||||
- `X-Skip-Magic-Trailing-Comma`: corresponds to the `--skip-magic-trailing-comma`
|
- `X-Skip-Magic-Trailing-Comma`: corresponds to the `--skip-magic-trailing-comma`
|
||||||
command line flag. If present and its value is not an empty string, trailing commas
|
command line flag. If present and its value is not the empty string, trailing commas
|
||||||
will not be used as a reason to split lines.
|
will not be used as a reason to split lines.
|
||||||
- `X-Preview`: corresponds to the `--preview` command line flag. If present and its
|
|
||||||
value is not an empty string, experimental and potentially disruptive style changes
|
|
||||||
will be used.
|
|
||||||
- `X-Unstable`: corresponds to the `--unstable` command line flag. If present and its
|
|
||||||
value is not an empty string, experimental style changes that are known to be buggy
|
|
||||||
will be used.
|
|
||||||
- `X-Enable-Unstable-Feature`: corresponds to the `--enable-unstable-feature` flag. The
|
|
||||||
contents of the flag must be a comma-separated list of unstable features to be
|
|
||||||
enabled. Example: `X-Enable-Unstable-Feature: feature1, feature2`.
|
|
||||||
- `X-Fast-Or-Safe`: if set to `fast`, `blackd` will act as _Black_ does when passed the
|
- `X-Fast-Or-Safe`: if set to `fast`, `blackd` will act as _Black_ does when passed the
|
||||||
`--fast` command line flag.
|
`--fast` command line flag.
|
||||||
- `X-Python-Variant`: if set to `pyi`, `blackd` will act as _Black_ does when passed the
|
- `X-Python-Variant`: if set to `pyi`, `blackd` will act as _Black_ does when passed the
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
# Black Docker image
|
|
||||||
|
|
||||||
Official _Black_ Docker images are available on
|
|
||||||
[Docker Hub](https://hub.docker.com/r/pyfound/black).
|
|
||||||
|
|
||||||
_Black_ images with the following tags are available:
|
|
||||||
|
|
||||||
- release numbers, e.g. `21.5b2`, `21.6b0`, `21.7b0` etc.\
|
|
||||||
ℹ Recommended for users who want to use a particular version of _Black_.
|
|
||||||
- `latest_release` - tag created when a new version of _Black_ is released.\
|
|
||||||
ℹ Recommended for users who want to use released versions of _Black_. It maps to
|
|
||||||
[the latest release](https://github.com/psf/black/releases/latest) of _Black_.
|
|
||||||
- `latest_prerelease` - tag created when a new alpha (prerelease) version of _Black_ is
|
|
||||||
released.\
|
|
||||||
ℹ Recommended for users who want to preview or test alpha versions of _Black_. Note
|
|
||||||
that the most recent release may be newer than any prerelease, because no prereleases
|
|
||||||
are created before most releases.
|
|
||||||
- `latest` - tag used for the newest image of _Black_.\
|
|
||||||
ℹ Recommended for users who always want to use the latest version of _Black_, even
|
|
||||||
before it is released.
|
|
||||||
|
|
||||||
There is one more tag used for _Black_ Docker images - `latest_non_release`. It is
|
|
||||||
created for all unreleased
|
|
||||||
[commits on the `main` branch](https://github.com/psf/black/commits/main). This tag is
|
|
||||||
not meant to be used by external users.
|
|
||||||
|
|
||||||
From version 23.11.0 the Docker image installs a compiled black into the image.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
A permanent container doesn't have to be created to use _Black_ as a Docker image. It's
|
|
||||||
enough to run _Black_ commands for the chosen image denoted as `:tag`. In the below
|
|
||||||
examples, the `latest_release` tag is used. If `:tag` is omitted, the `latest` tag will
|
|
||||||
be used.
|
|
||||||
|
|
||||||
More about _Black_ usage can be found in
|
|
||||||
[Usage and Configuration: The basics](./the_basics.md).
|
|
||||||
|
|
||||||
### Check Black version
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ docker run --rm pyfound/black:latest_release black --version
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check code
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ docker run --rm --volume $(pwd):/src --workdir /src pyfound/black:latest_release black --check .
|
|
||||||
```
|
|
||||||
|
|
||||||
_Remark_: besides [regular _Black_ exit codes](./the_basics.md) returned by `--check`
|
|
||||||
option, [Docker exit codes](https://docs.docker.com/engine/reference/run/#exit-status)
|
|
||||||
should also be considered.
|
|
@ -22,12 +22,10 @@ run. The file is non-portable. The standard location on common operating systems
|
|||||||
`file-mode` is an int flag that determines whether the file was formatted as 3.6+ only,
|
`file-mode` is an int flag that determines whether the file was formatted as 3.6+ only,
|
||||||
as .pyi, and whether string normalization was omitted.
|
as .pyi, and whether string normalization was omitted.
|
||||||
|
|
||||||
To override the location of these files on all systems, set the environment variable
|
To override the location of these files on macOS or Linux, set the environment variable
|
||||||
`BLACK_CACHE_DIR` to the preferred location. Alternatively on macOS and Linux, set
|
|
||||||
`XDG_CACHE_HOME` to your preferred location. For example, if you want to put the cache
|
`XDG_CACHE_HOME` to your preferred location. For example, if you want to put the cache
|
||||||
in the directory you're running _Black_ from, set `BLACK_CACHE_DIR=.cache/black`.
|
in the directory you're running _Black_ from, set `XDG_CACHE_HOME=.cache`. _Black_ will
|
||||||
_Black_ will then write the above files to `.cache/black`. Note that `BLACK_CACHE_DIR`
|
then write the above files to `.cache/black/<version>/`.
|
||||||
will take precedence over `XDG_CACHE_HOME` if both are set.
|
|
||||||
|
|
||||||
## .gitignore
|
## .gitignore
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
# Usage and Configuration
|
|
||||||
|
|
||||||
```{toctree}
|
|
||||||
---
|
|
||||||
hidden:
|
|
||||||
---
|
|
||||||
|
|
||||||
the_basics
|
|
||||||
file_collection_and_discovery
|
|
||||||
black_as_a_server
|
|
||||||
black_docker_image
|
|
||||||
```
|
|
||||||
|
|
||||||
Sometimes, running _Black_ with its defaults and passing filepaths to it just won't cut
|
|
||||||
it. Passing each file using paths will become burdensome, and maybe you would like
|
|
||||||
_Black_ to not touch your files and just output diffs. And yes, you _can_ tweak certain
|
|
||||||
parts of _Black_'s style, but please know that configurability in this area is
|
|
||||||
purposefully limited.
|
|
||||||
|
|
||||||
Using many of these more advanced features of _Black_ will require some configuration.
|
|
||||||
Configuration that will either live on the command line or in a TOML configuration file.
|
|
||||||
|
|
||||||
This section covers features of _Black_ and configuring _Black_ in detail:
|
|
||||||
|
|
||||||
- {doc}`The basics <./the_basics>`
|
|
||||||
- {doc}`File collection and discovery <file_collection_and_discovery>`
|
|
||||||
- {doc}`Black as a server (blackd) <./black_as_a_server>`
|
|
||||||
- {doc}`Black Docker image <./black_docker_image>`
|
|
24
docs/usage_and_configuration/index.rst
Normal file
24
docs/usage_and_configuration/index.rst
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Usage and Configuration
|
||||||
|
=======================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
the_basics
|
||||||
|
file_collection_and_discovery
|
||||||
|
black_as_a_server
|
||||||
|
|
||||||
|
Sometimes, running *Black* with its defaults and passing filepaths to it just won't cut
|
||||||
|
it. Passing each file using paths will become burdensome, and maybe you would like
|
||||||
|
*Black* to not touch your files and just output diffs. And yes, you *can* tweak certain
|
||||||
|
parts of *Black*'s style, but please know that configurability in this area is
|
||||||
|
purposefully limited.
|
||||||
|
|
||||||
|
Using many of these more advanced features of *Black* will require some configuration.
|
||||||
|
Configuration that will either live on the command line or in a TOML configuration file.
|
||||||
|
|
||||||
|
This section covers features of *Black* and configuring *Black* in detail:
|
||||||
|
|
||||||
|
- :doc:`The basics <./the_basics>`
|
||||||
|
- :doc:`File collection and discovery <file_collection_and_discovery>`
|
||||||
|
- :doc:`Black as a server (blackd) <./black_as_a_server>`
|
@ -4,16 +4,15 @@ Foundational knowledge on using and configuring Black.
|
|||||||
|
|
||||||
_Black_ is a well-behaved Unix-style command-line tool:
|
_Black_ is a well-behaved Unix-style command-line tool:
|
||||||
|
|
||||||
- it does nothing if it finds no sources to format;
|
- it does nothing if no sources are passed to it;
|
||||||
- it will read from standard input and write to standard output if `-` is used as the
|
- it will read from standard input and write to standard output if `-` is used as the
|
||||||
filename;
|
filename;
|
||||||
- it only outputs messages to users on standard error;
|
- it only outputs messages to users on standard error;
|
||||||
- exits with code 0 unless an internal error occurred or a CLI option prompted it.
|
- exits with code 0 unless an internal error occurred (or `--check` was used).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
_Black_ will reformat entire files in place. To get started right away with sensible
|
To get started right away with sensible defaults:
|
||||||
defaults:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
black {source_file_or_directory}
|
black {source_file_or_directory}
|
||||||
@ -25,167 +24,66 @@ You can run _Black_ as a package if running it as a script doesn't work:
|
|||||||
python -m black {source_file_or_directory}
|
python -m black {source_file_or_directory}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Ignoring sections
|
|
||||||
|
|
||||||
Black will not reformat lines that contain `# fmt: skip` or blocks that start with
|
|
||||||
`# fmt: off` and end with `# fmt: on`. `# fmt: skip` can be mixed with other
|
|
||||||
pragmas/comments either with multiple comments (e.g. `# fmt: skip # pylint # noqa`) or
|
|
||||||
as a semicolon separated list (e.g. `# fmt: skip; pylint; noqa`). `# fmt: on/off` must
|
|
||||||
be on the same level of indentation and in the same block, meaning no unindents beyond
|
|
||||||
the initial indentation level between them. Black also recognizes
|
|
||||||
[YAPF](https://github.com/google/yapf)'s block comments to the same effect, as a
|
|
||||||
courtesy for straddling code.
|
|
||||||
|
|
||||||
### Command line options
|
### Command line options
|
||||||
|
|
||||||
The CLI options of _Black_ can be displayed by running `black --help`. All options are
|
_Black_ has quite a few knobs these days, although _Black_ is opinionated so style
|
||||||
also covered in more detail below.
|
configuration options are deliberately limited and rarely added. You can list them by
|
||||||
|
running `black --help`.
|
||||||
|
|
||||||
While _Black_ has quite a few knobs these days, it is still opinionated so style options
|
<details>
|
||||||
are deliberately limited and rarely added.
|
|
||||||
|
|
||||||
Note that all command-line options listed above can also be configured using a
|
<summary>Help output</summary>
|
||||||
`pyproject.toml` file (more on that below).
|
|
||||||
|
|
||||||
#### `-h`, `--help`
|
```{program-output} black --help
|
||||||
|
|
||||||
Show available command-line options and exit.
|
```
|
||||||
|
|
||||||
#### `-c`, `--code`
|
</details>
|
||||||
|
|
||||||
Format the code passed in as a string.
|
### Code input alternatives
|
||||||
|
|
||||||
|
#### Standard Input
|
||||||
|
|
||||||
|
_Black_ supports formatting code via stdin, with the result being printed to stdout.
|
||||||
|
Just let _Black_ know with `-` as the path.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ echo "print ( 'hello, world' )" | black -
|
||||||
|
print("hello, world")
|
||||||
|
reformatted -
|
||||||
|
All done! ✨ 🍰 ✨
|
||||||
|
1 file reformatted.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tip:** if you need _Black_ to treat stdin input as a file passed directly via the CLI,
|
||||||
|
use `--stdin-filename`. Useful to make sure _Black_ will respect the `--force-exclude`
|
||||||
|
option on some editors that rely on using stdin.
|
||||||
|
|
||||||
|
#### As a string
|
||||||
|
|
||||||
|
You can also pass code as a string using the `-c` / `--code` option.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black --code "print ( 'hello, world' )"
|
$ black --code "print ( 'hello, world' )"
|
||||||
print("hello, world")
|
print("hello, world")
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `-l`, `--line-length`
|
### Writeback and reporting
|
||||||
|
|
||||||
How many characters per line to allow. The default is 88.
|
By default _Black_ reformats the files given and/or found in place. Sometimes you need
|
||||||
|
_Black_ to just tell you what it _would_ do without actually rewriting the Python files.
|
||||||
|
|
||||||
See also [the style documentation](labels/line-length).
|
There's two variations to this mode that are independently enabled by their respective
|
||||||
|
flags. Both variations can be enabled at once.
|
||||||
|
|
||||||
#### `-t`, `--target-version`
|
#### Exit code
|
||||||
|
|
||||||
Python versions that should be supported by Black's output. You can run `black --help`
|
Passing `--check` will make _Black_ exit with:
|
||||||
and look for the `--target-version` option to see the full list of supported versions.
|
|
||||||
You should include all versions that your code supports. If you support Python 3.11
|
|
||||||
through 3.13, you should write:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black -t py311 -t py312 -t py313
|
|
||||||
```
|
|
||||||
|
|
||||||
In a [configuration file](#configuration-via-a-file), you can write:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
target-version = ["py311", "py312", "py313"]
|
|
||||||
```
|
|
||||||
|
|
||||||
By default, Black will infer target versions from the project metadata in
|
|
||||||
`pyproject.toml`, specifically the `[project.requires-python]` field. If this does not
|
|
||||||
yield conclusive results, Black will use per-file auto-detection.
|
|
||||||
|
|
||||||
_Black_ uses this option to decide what grammar to use to parse your code. In addition,
|
|
||||||
it may use it to decide what style to use. For example, support for a trailing comma
|
|
||||||
after `*args` in a function call was added in Python 3.5, so _Black_ will add this comma
|
|
||||||
only if the target versions are all Python 3.5 or higher:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black --line-length=10 --target-version=py35 -c 'f(a, *args)'
|
|
||||||
f(
|
|
||||||
a,
|
|
||||||
*args,
|
|
||||||
)
|
|
||||||
$ black --line-length=10 --target-version=py34 -c 'f(a, *args)'
|
|
||||||
f(
|
|
||||||
a,
|
|
||||||
*args
|
|
||||||
)
|
|
||||||
$ black --line-length=10 --target-version=py34 --target-version=py35 -c 'f(a, *args)'
|
|
||||||
f(
|
|
||||||
a,
|
|
||||||
*args
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `--pyi`
|
|
||||||
|
|
||||||
Format all input files like typing stubs regardless of file extension. This is useful
|
|
||||||
when piping source on standard input.
|
|
||||||
|
|
||||||
#### `--ipynb`
|
|
||||||
|
|
||||||
Format all input files like Jupyter Notebooks regardless of file extension. This is
|
|
||||||
useful when piping source on standard input.
|
|
||||||
|
|
||||||
#### `--python-cell-magics`
|
|
||||||
|
|
||||||
When processing Jupyter Notebooks, add the given magic to the list of known python-
|
|
||||||
magics. Useful for formatting cells with custom python magics.
|
|
||||||
|
|
||||||
#### `-x, --skip-source-first-line`
|
|
||||||
|
|
||||||
Skip the first line of the source code.
|
|
||||||
|
|
||||||
#### `-S, --skip-string-normalization`
|
|
||||||
|
|
||||||
By default, _Black_ uses double quotes for all strings and normalizes string prefixes,
|
|
||||||
as described in [the style documentation](labels/strings). If this option is given,
|
|
||||||
strings are left unchanged instead.
|
|
||||||
|
|
||||||
#### `-C, --skip-magic-trailing-comma`
|
|
||||||
|
|
||||||
By default, _Black_ uses existing trailing commas as an indication that short lines
|
|
||||||
should be left separate, as described in
|
|
||||||
[the style documentation](labels/magic-trailing-comma). If this option is given, the
|
|
||||||
magic trailing comma is ignored.
|
|
||||||
|
|
||||||
#### `--preview`
|
|
||||||
|
|
||||||
Enable potentially disruptive style changes that we expect to add to Black's main
|
|
||||||
functionality in the next major release. Use this if you want a taste of what next
|
|
||||||
year's style will look like.
|
|
||||||
|
|
||||||
Read more about [our preview style](labels/preview-style).
|
|
||||||
|
|
||||||
There is no guarantee on the code style produced by this flag across releases.
|
|
||||||
|
|
||||||
#### `--unstable`
|
|
||||||
|
|
||||||
Enable all style changes in `--preview`, plus additional changes that we would like to
|
|
||||||
make eventually, but that have known issues that need to be fixed before they can move
|
|
||||||
back to the `--preview` style. Use this if you want to experiment with these changes and
|
|
||||||
help fix issues with them.
|
|
||||||
|
|
||||||
There is no guarantee on the code style produced by this flag across releases.
|
|
||||||
|
|
||||||
#### `--enable-unstable-feature`
|
|
||||||
|
|
||||||
Enable specific features from the `--unstable` style. See
|
|
||||||
[the preview style documentation](labels/unstable-features) for the list of supported
|
|
||||||
features. This flag can only be used when `--preview` is enabled. Users are encouraged
|
|
||||||
to use this flag if they use `--preview` style and a feature that affects their code is
|
|
||||||
moved from the `--preview` to the `--unstable` style, but they want to avoid the thrash
|
|
||||||
from undoing this change.
|
|
||||||
|
|
||||||
There are no guarantees on the behavior of these features, or even their existence,
|
|
||||||
across releases.
|
|
||||||
|
|
||||||
(labels/exit-code)=
|
|
||||||
|
|
||||||
#### `--check`
|
|
||||||
|
|
||||||
Don't write the files back, just return the status. _Black_ will exit with:
|
|
||||||
|
|
||||||
- code 0 if nothing would change;
|
- code 0 if nothing would change;
|
||||||
- code 1 if some files would be reformatted; or
|
- code 1 if some files would be reformatted; or
|
||||||
- code 123 if there was an internal error
|
- code 123 if there was an internal error
|
||||||
|
|
||||||
If used in combination with `--quiet` then only the exit code will be returned, unless
|
|
||||||
there was an internal error.
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black test.py --check
|
$ black test.py --check
|
||||||
All done! ✨ 🍰 ✨
|
All done! ✨ 🍰 ✨
|
||||||
@ -208,17 +106,17 @@ $ echo $?
|
|||||||
123
|
123
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `--diff`
|
#### Diffs
|
||||||
|
|
||||||
Don't write the files back, just output a diff to indicate what changes _Black_ would've
|
Passing `--diff` will make _Black_ print out diffs that indicate what changes _Black_
|
||||||
made. They are printed to stdout so capturing them is simple.
|
would've made. They are printed to stdout so capturing them is simple.
|
||||||
|
|
||||||
If you'd like colored diffs, you can enable them with `--color`.
|
If you'd like colored diffs, you can enable them with the `--color`.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ black test.py --diff
|
$ black test.py --diff
|
||||||
--- test.py 2021-03-08 22:23:40.848954+00:00
|
--- test.py 2021-03-08 22:23:40.848954 +0000
|
||||||
+++ test.py 2021-03-08 22:23:47.126319+00:00
|
+++ test.py 2021-03-08 22:23:47.126319 +0000
|
||||||
@@ -1 +1 @@
|
@@ -1 +1 @@
|
||||||
-print ( 'hello, world' )
|
-print ( 'hello, world' )
|
||||||
+print("hello, world")
|
+print("hello, world")
|
||||||
@ -227,198 +125,6 @@ All done! ✨ 🍰 ✨
|
|||||||
1 file would be reformatted.
|
1 file would be reformatted.
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `--color` / `--no-color`
|
|
||||||
|
|
||||||
Show (or do not show) colored diff. Only applies when `--diff` is given.
|
|
||||||
|
|
||||||
#### `--line-ranges`
|
|
||||||
|
|
||||||
When specified, _Black_ will try its best to only format these lines.
|
|
||||||
|
|
||||||
This option can be specified multiple times, and a union of the lines will be formatted.
|
|
||||||
Each range must be specified as two integers connected by a `-`: `<START>-<END>`. The
|
|
||||||
`<START>` and `<END>` integer indices are 1-based and inclusive on both ends.
|
|
||||||
|
|
||||||
_Black_ may still format lines outside of the ranges for multi-line statements.
|
|
||||||
Formatting more than one file or any ipynb files with this option is not supported. This
|
|
||||||
option cannot be specified in the `pyproject.toml` config.
|
|
||||||
|
|
||||||
Example: `black --line-ranges=1-10 --line-ranges=21-30 test.py` will format lines from
|
|
||||||
`1` to `10` and `21` to `30`.
|
|
||||||
|
|
||||||
This option is mainly for editor integrations, such as "Format Selection".
|
|
||||||
|
|
||||||
```{note}
|
|
||||||
Due to [#4052](https://github.com/psf/black/issues/4052), `--line-ranges` might format
|
|
||||||
extra lines outside of the ranges when ther are unformatted lines with the exact
|
|
||||||
content. It also disables _Black_'s formatting stability check in `--safe` mode.
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `--fast` / `--safe`
|
|
||||||
|
|
||||||
By default, _Black_ performs [an AST safety check](labels/ast-changes) after formatting
|
|
||||||
your code. The `--fast` flag turns off this check and the `--safe` flag explicitly
|
|
||||||
enables it.
|
|
||||||
|
|
||||||
#### `--required-version`
|
|
||||||
|
|
||||||
Require a specific version of _Black_ to be running. This is useful for ensuring that
|
|
||||||
all contributors to your project are using the same version, because different versions
|
|
||||||
of _Black_ may format code a little differently. This option can be set in a
|
|
||||||
configuration file for consistent results across environments.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black --version
|
|
||||||
black, 25.1.0 (compiled: yes)
|
|
||||||
$ black --required-version 25.1.0 -c "format = 'this'"
|
|
||||||
format = "this"
|
|
||||||
$ black --required-version 31.5b2 -c "still = 'beta?!'"
|
|
||||||
Oh no! 💥 💔 💥 The required version does not match the running version!
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also pass just the major version:
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black --required-version 22 -c "format = 'this'"
|
|
||||||
format = "this"
|
|
||||||
$ black --required-version 31 -c "still = 'beta?!'"
|
|
||||||
Oh no! 💥 💔 💥 The required version does not match the running version!
|
|
||||||
```
|
|
||||||
|
|
||||||
Because of our [stability policy](../the_black_code_style/index.md), this will guarantee
|
|
||||||
stable formatting, but still allow you to take advantage of improvements that do not
|
|
||||||
affect formatting.
|
|
||||||
|
|
||||||
#### `--exclude`
|
|
||||||
|
|
||||||
A regular expression that matches files and directories that should be excluded on
|
|
||||||
recursive searches. An empty value means no paths are excluded. Use forward slashes for
|
|
||||||
directories on all platforms (Windows, too). By default, Black also ignores all paths
|
|
||||||
listed in `.gitignore`. Changing this value will override all default exclusions.
|
|
||||||
|
|
||||||
If the regular expression contains newlines, it is treated as a
|
|
||||||
[verbose regular expression](https://docs.python.org/3/library/re.html#re.VERBOSE). This
|
|
||||||
is typically useful when setting these options in a `pyproject.toml` configuration file;
|
|
||||||
see [Configuration format](#configuration-format) for more information.
|
|
||||||
|
|
||||||
#### `--extend-exclude`
|
|
||||||
|
|
||||||
Like `--exclude`, but adds additional files and directories on top of the default values
|
|
||||||
instead of overriding them.
|
|
||||||
|
|
||||||
#### `--force-exclude`
|
|
||||||
|
|
||||||
Like `--exclude`, but files and directories matching this regex will be excluded even
|
|
||||||
when they are passed explicitly as arguments. This is useful when invoking Black
|
|
||||||
programmatically on changed files, such as in a pre-commit hook or editor plugin.
|
|
||||||
|
|
||||||
#### `--stdin-filename`
|
|
||||||
|
|
||||||
The name of the file when passing it through stdin. Useful to make sure Black will
|
|
||||||
respect the `--force-exclude` option on some editors that rely on using stdin.
|
|
||||||
|
|
||||||
#### `--include`
|
|
||||||
|
|
||||||
A regular expression that matches files and directories that should be included on
|
|
||||||
recursive searches. An empty value means all files are included regardless of the name.
|
|
||||||
Use forward slashes for directories on all platforms (Windows, too). Overrides all
|
|
||||||
exclusions, including from `.gitignore` and command line options.
|
|
||||||
|
|
||||||
#### `-W`, `--workers`
|
|
||||||
|
|
||||||
When _Black_ formats multiple files, it may use a process pool to speed up formatting.
|
|
||||||
This option controls the number of parallel workers. This can also be specified via the
|
|
||||||
`BLACK_NUM_WORKERS` environment variable. Defaults to the number of CPUs in the system.
|
|
||||||
|
|
||||||
#### `-q`, `--quiet`
|
|
||||||
|
|
||||||
Stop emitting all non-critical output. Error messages will still be emitted (which can
|
|
||||||
silenced by `2>/dev/null`).
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black src/ -q
|
|
||||||
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `-v`, `--verbose`
|
|
||||||
|
|
||||||
Emit messages about files that were not changed or were ignored due to exclusion
|
|
||||||
patterns. If _Black_ is using a configuration file, a message detailing which one it is
|
|
||||||
using will be emitted.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black src/ -v
|
|
||||||
Using configuration from /tmp/pyproject.toml.
|
|
||||||
src/blib2to3 ignored: matches the --extend-exclude regular expression
|
|
||||||
src/_black_version.py wasn't modified on disk since last run.
|
|
||||||
src/black/__main__.py wasn't modified on disk since last run.
|
|
||||||
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
|
||||||
reformatted src/black_primer/lib.py
|
|
||||||
reformatted src/blackd/__init__.py
|
|
||||||
reformatted src/black/__init__.py
|
|
||||||
Oh no! 💥 💔 💥
|
|
||||||
3 files reformatted, 2 files left unchanged, 1 file failed to reformat
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `--version`
|
|
||||||
|
|
||||||
You can check the version of _Black_ you have installed using the `--version` flag.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ black --version
|
|
||||||
black, 25.1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `--config`
|
|
||||||
|
|
||||||
Read configuration options from a configuration file. See
|
|
||||||
[below](#configuration-via-a-file) for more details on the configuration file.
|
|
||||||
|
|
||||||
### Environment variable options
|
|
||||||
|
|
||||||
_Black_ supports the following configuration via environment variables.
|
|
||||||
|
|
||||||
#### `BLACK_CACHE_DIR`
|
|
||||||
|
|
||||||
The directory where _Black_ should store its cache.
|
|
||||||
|
|
||||||
#### `BLACK_NUM_WORKERS`
|
|
||||||
|
|
||||||
The number of parallel workers _Black_ should use. The command line option `-W` /
|
|
||||||
`--workers` takes precedence over this environment variable.
|
|
||||||
|
|
||||||
### Code input alternatives
|
|
||||||
|
|
||||||
_Black_ supports formatting code via stdin, with the result being printed to stdout.
|
|
||||||
Just let _Black_ know with `-` as the path.
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ echo "print ( 'hello, world' )" | black -
|
|
||||||
print("hello, world")
|
|
||||||
reformatted -
|
|
||||||
All done! ✨ 🍰 ✨
|
|
||||||
1 file reformatted.
|
|
||||||
```
|
|
||||||
|
|
||||||
**Tip:** if you need _Black_ to treat stdin input as a file passed directly via the CLI,
|
|
||||||
use `--stdin-filename`. Useful to make sure _Black_ will respect the `--force-exclude`
|
|
||||||
option on some editors that rely on using stdin.
|
|
||||||
|
|
||||||
You can also pass code as a string using the `--code` option.
|
|
||||||
|
|
||||||
### Writeback and reporting
|
|
||||||
|
|
||||||
By default _Black_ reformats the files given and/or found in place. Sometimes you need
|
|
||||||
_Black_ to just tell you what it _would_ do without actually rewriting the Python files.
|
|
||||||
|
|
||||||
There's two variations to this mode that are independently enabled by their respective
|
|
||||||
flags:
|
|
||||||
|
|
||||||
- `--check` (exit with code 1 if any file would be reformatted)
|
|
||||||
- `--diff` (print a diff instead of reformatting files)
|
|
||||||
|
|
||||||
Both variations can be enabled at once.
|
|
||||||
|
|
||||||
### Output verbosity
|
### Output verbosity
|
||||||
|
|
||||||
_Black_ in general tries to produce the right amount of output, balancing between
|
_Black_ in general tries to produce the right amount of output, balancing between
|
||||||
@ -435,7 +141,53 @@ Oh no! 💥 💔 💥
|
|||||||
3 files reformatted, 2 files left unchanged, 1 file failed to reformat.
|
3 files reformatted, 2 files left unchanged, 1 file failed to reformat.
|
||||||
```
|
```
|
||||||
|
|
||||||
The `--quiet` and `--verbose` flags control output verbosity.
|
Passing `-v` / `--verbose` will cause _Black_ to also emit messages about files that
|
||||||
|
were not changed or were ignored due to exclusion patterns. If _Black_ is using a
|
||||||
|
configuration file, a blue message detailing which one it is using will be emitted.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black src/ -v
|
||||||
|
Using configuration from /tmp/pyproject.toml.
|
||||||
|
src/blib2to3 ignored: matches the --extend-exclude regular expression
|
||||||
|
src/_black_version.py wasn't modified on disk since last run.
|
||||||
|
src/black/__main__.py wasn't modified on disk since last run.
|
||||||
|
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
||||||
|
reformatted src/black_primer/lib.py
|
||||||
|
reformatted src/blackd/__init__.py
|
||||||
|
reformatted src/black/__init__.py
|
||||||
|
Oh no! 💥 💔 💥
|
||||||
|
3 files reformatted, 2 files left unchanged, 1 file failed to reformat
|
||||||
|
```
|
||||||
|
|
||||||
|
Passing `-q` / `--quiet` will cause _Black_ to stop emitting all non-critial output.
|
||||||
|
Error messages will still be emitted (which can silenced by `2>/dev/null`).
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black src/ -q
|
||||||
|
error: cannot format src/black_primer/cli.py: Cannot parse: 5:6: mport asyncio
|
||||||
|
```
|
||||||
|
|
||||||
|
### Versions
|
||||||
|
|
||||||
|
You can check the version of _Black_ you have installed using the `--version` flag.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --version
|
||||||
|
black, version 21.8b0
|
||||||
|
```
|
||||||
|
|
||||||
|
An option to require a specific version to be running is also provided.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ black --required-version 21.8b0 -c "format = 'this'"
|
||||||
|
format = "this"
|
||||||
|
$ black --required-version 31.5b2 -c "still = 'beta?!'"
|
||||||
|
Oh no! 💥 💔 💥 The required version does not match the running version!
|
||||||
|
```
|
||||||
|
|
||||||
|
This is useful for example when running _Black_ in multiple environments that haven't
|
||||||
|
necessarily installed the correct version. This option can be set in a configuration
|
||||||
|
file for consistent results across environments.
|
||||||
|
|
||||||
## Configuration via a file
|
## Configuration via a file
|
||||||
|
|
||||||
@ -452,18 +204,16 @@ code in compliance with many other _Black_ formatted projects.
|
|||||||
|
|
||||||
[PEP 518](https://www.python.org/dev/peps/pep-0518/) defines `pyproject.toml` as a
|
[PEP 518](https://www.python.org/dev/peps/pep-0518/) defines `pyproject.toml` as a
|
||||||
configuration file to store build system requirements for Python projects. With the help
|
configuration file to store build system requirements for Python projects. With the help
|
||||||
of tools like [Poetry](https://python-poetry.org/),
|
of tools like [Poetry](https://python-poetry.org/) or
|
||||||
[Flit](https://flit.readthedocs.io/en/latest/), or
|
[Flit](https://flit.readthedocs.io/en/latest/) it can fully replace the need for
|
||||||
[Hatch](https://hatch.pypa.io/latest/) it can fully replace the need for `setup.py` and
|
`setup.py` and `setup.cfg` files.
|
||||||
`setup.cfg` files.
|
|
||||||
|
|
||||||
### Where _Black_ looks for the file
|
### Where _Black_ looks for the file
|
||||||
|
|
||||||
By default _Black_ looks for `pyproject.toml` containing a `[tool.black]` section
|
By default _Black_ looks for `pyproject.toml` starting from the common base directory of
|
||||||
starting from the common base directory of all files and directories passed on the
|
all files and directories passed on the command line. If it's not there, it looks in
|
||||||
command line. If it's not there, it looks in parent directories. It stops looking when
|
parent directories. It stops looking when it finds the file, or a `.git` directory, or a
|
||||||
it finds the file, or a `.git` directory, or a `.hg` directory, or the root of the file
|
`.hg` directory, or the root of the file system, whichever comes first.
|
||||||
system, whichever comes first.
|
|
||||||
|
|
||||||
If you're formatting standard input, _Black_ will look for configuration starting from
|
If you're formatting standard input, _Black_ will look for configuration starting from
|
||||||
the current working directory.
|
the current working directory.
|
||||||
@ -478,15 +228,15 @@ operating system, this configuration file should be stored as:
|
|||||||
`XDG_CONFIG_HOME` environment variable is not set)
|
`XDG_CONFIG_HOME` environment variable is not set)
|
||||||
|
|
||||||
Note that these are paths to the TOML file itself (meaning that they shouldn't be named
|
Note that these are paths to the TOML file itself (meaning that they shouldn't be named
|
||||||
as `pyproject.toml`), not directories where you store the configuration (i.e.,
|
as `pyproject.toml`), not directories where you store the configuration. Here, `~`
|
||||||
`black`/`.black` is the file to create and add your configuration options to, in the
|
refers to the path to your home directory. On Windows, this will be something like
|
||||||
`~/.config/` directory). Here, `~` refers to the path to your home directory. On
|
`C:\\Users\UserName`.
|
||||||
Windows, this will be something like `C:\\Users\UserName`.
|
|
||||||
|
|
||||||
You can also explicitly specify the path to a particular file that you want with
|
You can also explicitly specify the path to a particular file that you want with
|
||||||
`--config`. In this situation _Black_ will not look for any other file.
|
`--config`. In this situation _Black_ will not look for any other file.
|
||||||
|
|
||||||
If you're running with `--verbose`, you will see a message if a file was found and used.
|
If you're running with `--verbose`, you will see a blue message if a file was found and
|
||||||
|
used.
|
||||||
|
|
||||||
Please note `blackd` will not use `pyproject.toml` configuration.
|
Please note `blackd` will not use `pyproject.toml` configuration.
|
||||||
|
|
||||||
@ -509,14 +259,10 @@ expressions by Black. Use `[ ]` to denote a significant space character.
|
|||||||
line-length = 88
|
line-length = 88
|
||||||
target-version = ['py37']
|
target-version = ['py37']
|
||||||
include = '\.pyi?$'
|
include = '\.pyi?$'
|
||||||
# 'extend-exclude' excludes files or directories in addition to the defaults
|
|
||||||
extend-exclude = '''
|
extend-exclude = '''
|
||||||
# A regex preceded with ^/ will apply only to files and directories
|
# A regex preceded with ^/ will apply only to files and directories
|
||||||
# in the root of the project.
|
# in the root of the project.
|
||||||
(
|
^/foo.py # exclude a file named foo.py in the root of the project (in addition to the defaults)
|
||||||
^/foo.py # exclude a file named foo.py in the root of the project
|
|
||||||
| .*_pb2.py # exclude autogenerated Protocol Buffer files anywhere in the project
|
|
||||||
)
|
|
||||||
'''
|
'''
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -534,6 +280,9 @@ file hierarchy.
|
|||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
|
|
||||||
|
You've probably noted that not all of the options you can pass to _Black_ have been
|
||||||
|
covered. Don't worry, the rest will be covered in a later section.
|
||||||
|
|
||||||
A good next step would be configuring auto-discovery so `black .` is all you need
|
A good next step would be configuring auto-discovery so `black .` is all you need
|
||||||
instead of laborously listing every file or directory. You can get started by heading
|
instead of laborously listing every file or directory. You can get started by heading
|
||||||
over to [File collection and discovery](./file_collection_and_discovery.md).
|
over to [File collection and discovery](./file_collection_and_discovery.md).
|
||||||
|
@ -5,11 +5,13 @@
|
|||||||
a coverage-guided fuzzer I'm working on.
|
a coverage-guided fuzzer I'm working on.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
import hypothesmith
|
import hypothesmith
|
||||||
from hypothesis import HealthCheck, given, settings
|
from hypothesis import HealthCheck, given, settings, strategies as st
|
||||||
from hypothesis import strategies as st
|
|
||||||
|
|
||||||
import black
|
import black
|
||||||
|
from blib2to3.pgen2.tokenize import TokenError
|
||||||
|
|
||||||
|
|
||||||
# This test uses the Hypothesis and Hypothesmith libraries to generate random
|
# This test uses the Hypothesis and Hypothesmith libraries to generate random
|
||||||
@ -18,7 +20,7 @@
|
|||||||
max_examples=1000, # roughly 1k tests/minute, or half that under coverage
|
max_examples=1000, # roughly 1k tests/minute, or half that under coverage
|
||||||
derandomize=True, # deterministic mode to avoid CI flakiness
|
derandomize=True, # deterministic mode to avoid CI flakiness
|
||||||
deadline=None, # ignore Hypothesis' health checks; we already know that
|
deadline=None, # ignore Hypothesis' health checks; we already know that
|
||||||
suppress_health_check=list(HealthCheck), # this is slow and filter-heavy.
|
suppress_health_check=HealthCheck.all(), # this is slow and filter-heavy.
|
||||||
)
|
)
|
||||||
@given(
|
@given(
|
||||||
# Note that while Hypothesmith might generate code unlike that written by
|
# Note that while Hypothesmith might generate code unlike that written by
|
||||||
@ -30,9 +32,7 @@
|
|||||||
black.FileMode,
|
black.FileMode,
|
||||||
line_length=st.just(88) | st.integers(0, 200),
|
line_length=st.just(88) | st.integers(0, 200),
|
||||||
string_normalization=st.booleans(),
|
string_normalization=st.booleans(),
|
||||||
preview=st.booleans(),
|
|
||||||
is_pyi=st.booleans(),
|
is_pyi=st.booleans(),
|
||||||
magic_trailing_comma=st.booleans(),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
def test_idempotent_any_syntatically_valid_python(
|
def test_idempotent_any_syntatically_valid_python(
|
||||||
@ -42,7 +42,23 @@ def test_idempotent_any_syntatically_valid_python(
|
|||||||
compile(src_contents, "<string>", "exec") # else the bug is in hypothesmith
|
compile(src_contents, "<string>", "exec") # else the bug is in hypothesmith
|
||||||
|
|
||||||
# Then format the code...
|
# Then format the code...
|
||||||
|
try:
|
||||||
dst_contents = black.format_str(src_contents, mode=mode)
|
dst_contents = black.format_str(src_contents, mode=mode)
|
||||||
|
except black.InvalidInput:
|
||||||
|
# This is a bug - if it's valid Python code, as above, Black should be
|
||||||
|
# able to cope with it. See issues #970, #1012, #1358, and #1557.
|
||||||
|
# TODO: remove this try-except block when issues are resolved.
|
||||||
|
return
|
||||||
|
except TokenError as e:
|
||||||
|
if ( # Special-case logic for backslashes followed by newlines or end-of-input
|
||||||
|
e.args[0] == "EOF in multi-line statement"
|
||||||
|
and re.search(r"\\($|\r?\n)", src_contents) is not None
|
||||||
|
):
|
||||||
|
# This is a bug - if it's valid Python code, as above, Black should be
|
||||||
|
# able to cope with it. See issue #1012.
|
||||||
|
# TODO: remove this block when the issue is resolved.
|
||||||
|
return
|
||||||
|
raise
|
||||||
|
|
||||||
# And check that we got equivalent and stable output.
|
# And check that we got equivalent and stable output.
|
||||||
black.assert_equivalent(src_contents, dst_contents)
|
black.assert_equivalent(src_contents, dst_contents)
|
||||||
@ -60,14 +76,10 @@ def test_idempotent_any_syntatically_valid_python(
|
|||||||
# (if you want only bounded fuzzing, just use `pytest fuzz.py`)
|
# (if you want only bounded fuzzing, just use `pytest fuzz.py`)
|
||||||
try:
|
try:
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import atheris
|
import atheris
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
test = test_idempotent_any_syntatically_valid_python
|
test = test_idempotent_any_syntatically_valid_python
|
||||||
atheris.Setup(
|
atheris.Setup(sys.argv, test.hypothesis.fuzz_one_input)
|
||||||
sys.argv,
|
|
||||||
test.hypothesis.fuzz_one_input, # type: ignore[attr-defined]
|
|
||||||
)
|
|
||||||
atheris.Fuzz()
|
atheris.Fuzz()
|
@ -7,20 +7,29 @@
|
|||||||
import venv
|
import venv
|
||||||
import zipfile
|
import zipfile
|
||||||
from argparse import ArgumentParser, Namespace
|
from argparse import ArgumentParser, Namespace
|
||||||
from collections.abc import Generator
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from functools import lru_cache, partial
|
from functools import lru_cache, partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import NamedTuple, Optional, Union, cast
|
from typing import ( # type: ignore # typing can't see Literal
|
||||||
|
Generator,
|
||||||
|
List,
|
||||||
|
Literal,
|
||||||
|
NamedTuple,
|
||||||
|
Optional,
|
||||||
|
Tuple,
|
||||||
|
Union,
|
||||||
|
cast,
|
||||||
|
)
|
||||||
from urllib.request import urlopen, urlretrieve
|
from urllib.request import urlopen, urlretrieve
|
||||||
|
|
||||||
PYPI_INSTANCE = "https://pypi.org/pypi"
|
PYPI_INSTANCE = "https://pypi.org/pypi"
|
||||||
PYPI_TOP_PACKAGES = (
|
PYPI_TOP_PACKAGES = (
|
||||||
"https://hugovk.github.io/top-pypi-packages/top-pypi-packages.min.json"
|
"https://hugovk.github.io/top-pypi-packages/top-pypi-packages-{days}-days.json"
|
||||||
)
|
)
|
||||||
INTERNAL_BLACK_REPO = f"{tempfile.gettempdir()}/__black"
|
INTERNAL_BLACK_REPO = f"{tempfile.gettempdir()}/__black"
|
||||||
|
|
||||||
ArchiveKind = Union[tarfile.TarFile, zipfile.ZipFile]
|
ArchiveKind = Union[tarfile.TarFile, zipfile.ZipFile]
|
||||||
|
Days = Union[Literal[30], Literal[365]]
|
||||||
|
|
||||||
subprocess.run = partial(subprocess.run, check=True) # type: ignore
|
subprocess.run = partial(subprocess.run, check=True) # type: ignore
|
||||||
# https://github.com/python/mypy/issues/1484
|
# https://github.com/python/mypy/issues/1484
|
||||||
@ -55,8 +64,8 @@ def get_pypi_download_url(package: str, version: Optional[str]) -> str:
|
|||||||
return cast(str, source["url"])
|
return cast(str, source["url"])
|
||||||
|
|
||||||
|
|
||||||
def get_top_packages() -> list[str]:
|
def get_top_packages(days: Days) -> List[str]:
|
||||||
with urlopen(PYPI_TOP_PACKAGES) as page:
|
with urlopen(PYPI_TOP_PACKAGES.format(days=days)) as page:
|
||||||
result = json.load(page)
|
result = json.load(page)
|
||||||
|
|
||||||
return [package["project"] for package in result["rows"]]
|
return [package["project"] for package in result["rows"]]
|
||||||
@ -119,12 +128,13 @@ def get_package(
|
|||||||
|
|
||||||
def download_and_extract_top_packages(
|
def download_and_extract_top_packages(
|
||||||
directory: Path,
|
directory: Path,
|
||||||
|
days: Days = 365,
|
||||||
workers: int = 8,
|
workers: int = 8,
|
||||||
limit: slice = DEFAULT_SLICE,
|
limit: slice = DEFAULT_SLICE,
|
||||||
) -> Generator[Path, None, None]:
|
) -> Generator[Path, None, None]:
|
||||||
with ThreadPoolExecutor(max_workers=workers) as executor:
|
with ThreadPoolExecutor(max_workers=workers) as executor:
|
||||||
bound_downloader = partial(get_package, version=None, directory=directory)
|
bound_downloader = partial(get_package, version=None, directory=directory)
|
||||||
for package in executor.map(bound_downloader, get_top_packages()[limit]):
|
for package in executor.map(bound_downloader, get_top_packages(days)[limit]):
|
||||||
if package is not None:
|
if package is not None:
|
||||||
yield package
|
yield package
|
||||||
|
|
||||||
@ -151,7 +161,7 @@ def git_switch_branch(
|
|||||||
subprocess.run(args, cwd=repo)
|
subprocess.run(args, cwd=repo)
|
||||||
|
|
||||||
|
|
||||||
def init_repos(options: Namespace) -> tuple[Path, ...]:
|
def init_repos(options: Namespace) -> Tuple[Path, ...]:
|
||||||
options.output.mkdir(exist_ok=True)
|
options.output.mkdir(exist_ok=True)
|
||||||
|
|
||||||
if options.top_packages:
|
if options.top_packages:
|
||||||
@ -207,7 +217,7 @@ def format_repo_with_version(
|
|||||||
git_switch_branch(black_version.version, repo=black_repo)
|
git_switch_branch(black_version.version, repo=black_repo)
|
||||||
git_switch_branch(current_branch, repo=repo, new=True, from_branch=from_branch)
|
git_switch_branch(current_branch, repo=repo, new=True, from_branch=from_branch)
|
||||||
|
|
||||||
format_cmd: list[Union[Path, str]] = [
|
format_cmd: List[Union[Path, str]] = [
|
||||||
black_runner(black_version.version, black_repo),
|
black_runner(black_version.version, black_repo),
|
||||||
(black_repo / "black.py").resolve(),
|
(black_repo / "black.py").resolve(),
|
||||||
".",
|
".",
|
||||||
@ -223,7 +233,7 @@ def format_repo_with_version(
|
|||||||
return current_branch
|
return current_branch
|
||||||
|
|
||||||
|
|
||||||
def format_repos(repos: tuple[Path, ...], options: Namespace) -> None:
|
def format_repos(repos: Tuple[Path, ...], options: Namespace) -> None:
|
||||||
black_versions = tuple(
|
black_versions = tuple(
|
||||||
BlackVersion(*version.split(":")) for version in options.versions
|
BlackVersion(*version.split(":")) for version in options.versions
|
||||||
)
|
)
|
||||||
@ -244,9 +254,11 @@ def format_repos(repos: tuple[Path, ...], options: Namespace) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser = ArgumentParser(description="""Black Gallery is a script that
|
parser = ArgumentParser(
|
||||||
|
description="""Black Gallery is a script that
|
||||||
automates the process of applying different Black versions to a selected
|
automates the process of applying different Black versions to a selected
|
||||||
PyPI package and seeing the results between versions.""")
|
PyPI package and seeing the results between versions."""
|
||||||
|
)
|
||||||
|
|
||||||
group = parser.add_mutually_exclusive_group(required=True)
|
group = parser.add_mutually_exclusive_group(required=True)
|
||||||
group.add_argument("-p", "--pypi-package", help="PyPI package to download.")
|
group.add_argument("-p", "--pypi-package", help="PyPI package to download.")
|
||||||
|
41
mypy.ini
Normal file
41
mypy.ini
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[mypy]
|
||||||
|
# Specify the target platform details in config, so your developers are
|
||||||
|
# free to run mypy on Windows, Linux, or macOS and get consistent
|
||||||
|
# results.
|
||||||
|
python_version=3.6
|
||||||
|
platform=linux
|
||||||
|
|
||||||
|
mypy_path=src
|
||||||
|
|
||||||
|
show_column_numbers=True
|
||||||
|
|
||||||
|
# show error messages from unrelated files
|
||||||
|
follow_imports=normal
|
||||||
|
|
||||||
|
# suppress errors about unsatisfied imports
|
||||||
|
ignore_missing_imports=True
|
||||||
|
|
||||||
|
# be strict
|
||||||
|
disallow_untyped_calls=True
|
||||||
|
warn_return_any=True
|
||||||
|
strict_optional=True
|
||||||
|
warn_no_return=True
|
||||||
|
warn_redundant_casts=True
|
||||||
|
warn_unused_ignores=True
|
||||||
|
# Until we're not supporting 3.6 primer needs this
|
||||||
|
disallow_any_generics=False
|
||||||
|
|
||||||
|
# The following are off by default. Flip them on if you feel
|
||||||
|
# adventurous.
|
||||||
|
disallow_untyped_defs=True
|
||||||
|
check_untyped_defs=True
|
||||||
|
|
||||||
|
# No incremental mode
|
||||||
|
cache_dir=/dev/null
|
||||||
|
|
||||||
|
[mypy-aiohttp.*]
|
||||||
|
follow_imports=skip
|
||||||
|
[mypy-black]
|
||||||
|
# The following is because of `patch_click()`. Remove when
|
||||||
|
# we drop Python 3.6 support.
|
||||||
|
warn_unused_ignores=False
|
@ -15,13 +15,9 @@
|
|||||||
" 1.2:
|
" 1.2:
|
||||||
" - use autoload script
|
" - use autoload script
|
||||||
|
|
||||||
if exists("g:load_black")
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
if v:version < 700 || !has('python3')
|
if v:version < 700 || !has('python3')
|
||||||
func! __BLACK_MISSING()
|
func! __BLACK_MISSING()
|
||||||
echo "The black.vim plugin requires vim7.0+ with Python 3.9 support."
|
echo "The black.vim plugin requires vim7.0+ with Python 3.6 support."
|
||||||
endfunc
|
endfunc
|
||||||
command! Black :call __BLACK_MISSING()
|
command! Black :call __BLACK_MISSING()
|
||||||
command! BlackUpgrade :call __BLACK_MISSING()
|
command! BlackUpgrade :call __BLACK_MISSING()
|
||||||
@ -29,6 +25,10 @@ if v:version < 700 || !has('python3')
|
|||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if exists("g:load_black")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
let g:load_black = "py1.0"
|
let g:load_black = "py1.0"
|
||||||
if !exists("g:black_virtualenv")
|
if !exists("g:black_virtualenv")
|
||||||
if has("nvim")
|
if has("nvim")
|
||||||
@ -50,36 +50,11 @@ if !exists("g:black_skip_string_normalization")
|
|||||||
let g:black_skip_string_normalization = 0
|
let g:black_skip_string_normalization = 0
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
if !exists("g:black_skip_magic_trailing_comma")
|
|
||||||
if exists("g:black_magic_trailing_comma")
|
|
||||||
let g:black_skip_magic_trailing_comma = !g:black_magic_trailing_comma
|
|
||||||
else
|
|
||||||
let g:black_skip_magic_trailing_comma = 0
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
if !exists("g:black_quiet")
|
if !exists("g:black_quiet")
|
||||||
let g:black_quiet = 0
|
let g:black_quiet = 0
|
||||||
endif
|
endif
|
||||||
if !exists("g:black_target_version")
|
|
||||||
let g:black_target_version = ""
|
|
||||||
endif
|
|
||||||
if !exists("g:black_use_virtualenv")
|
|
||||||
let g:black_use_virtualenv = 1
|
|
||||||
endif
|
|
||||||
if !exists("g:black_preview")
|
|
||||||
let g:black_preview = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
function BlackComplete(ArgLead, CmdLine, CursorPos)
|
|
||||||
return [
|
|
||||||
\ 'target_version=py39',
|
|
||||||
\ 'target_version=py310',
|
|
||||||
\ 'target_version=py311',
|
|
||||||
\ 'target_version=py312',
|
|
||||||
\ 'target_version=py313',
|
|
||||||
\ ]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
command! -nargs=* -complete=customlist,BlackComplete Black :call black#Black(<f-args>)
|
command! Black :call black#Black()
|
||||||
command! BlackUpgrade :call black#BlackUpgrade()
|
command! BlackUpgrade :call black#BlackUpgrade()
|
||||||
command! BlackVersion :call black#BlackVersion()
|
command! BlackVersion :call black#BlackVersion()
|
||||||
|
232
pyproject.toml
232
pyproject.toml
@ -7,238 +7,32 @@
|
|||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
target-version = ['py39']
|
target-version = ['py36', 'py37', 'py38']
|
||||||
include = '\.pyi?$'
|
include = '\.pyi?$'
|
||||||
extend-exclude = '''
|
extend-exclude = '''
|
||||||
/(
|
/(
|
||||||
# The following are specific to Black, you probably don't want those.
|
# The following are specific to Black, you probably don't want those.
|
||||||
tests/data/
|
| blib2to3
|
||||||
| profiling/
|
| tests/data
|
||||||
| scripts/generate_schema.py # Uses match syntax
|
| profiling
|
||||||
)
|
)/
|
||||||
'''
|
'''
|
||||||
# We use the unstable style for formatting Black itself. If you
|
|
||||||
# want bug-free formatting, you should keep this off. If you want
|
|
||||||
# stable formatting across releases, you should also keep `preview = true`
|
|
||||||
# (which is implied by this flag) off.
|
|
||||||
unstable = true
|
|
||||||
|
|
||||||
# Build system information and other project-specific configuration below.
|
|
||||||
|
# Build system information below.
|
||||||
# NOTE: You don't need this in your own Black configuration.
|
# NOTE: You don't need this in your own Black configuration.
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["hatchling>=1.20.0", "hatch-vcs", "hatch-fancy-pypi-readme"]
|
# We're pinning setuptools-scm to bugfix versions only because for build-time
|
||||||
build-backend = "hatchling.build"
|
# deps having them work on install by default is really important. Especially
|
||||||
|
# since it's hard for users to work-around the specified build requirements.
|
||||||
[project]
|
requires = ["setuptools>=41.0", "setuptools_scm~=6.0.1", "wheel"]
|
||||||
name = "black"
|
build-backend = "setuptools.build_meta"
|
||||||
description = "The uncompromising code formatter."
|
|
||||||
license = "MIT"
|
|
||||||
requires-python = ">=3.9"
|
|
||||||
authors = [
|
|
||||||
{ name = "Łukasz Langa", email = "lukasz@langa.pl" },
|
|
||||||
]
|
|
||||||
keywords = [
|
|
||||||
"automation",
|
|
||||||
"autopep8",
|
|
||||||
"formatter",
|
|
||||||
"gofmt",
|
|
||||||
"pyfmt",
|
|
||||||
"rustfmt",
|
|
||||||
"yapf",
|
|
||||||
]
|
|
||||||
classifiers = [
|
|
||||||
"Development Status :: 5 - Production/Stable",
|
|
||||||
"Environment :: Console",
|
|
||||||
"Intended Audience :: Developers",
|
|
||||||
"License :: OSI Approved :: MIT License",
|
|
||||||
"Operating System :: OS Independent",
|
|
||||||
"Programming Language :: Python",
|
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
|
||||||
"Programming Language :: Python :: 3.10",
|
|
||||||
"Programming Language :: Python :: 3.11",
|
|
||||||
"Programming Language :: Python :: 3.12",
|
|
||||||
"Programming Language :: Python :: 3.13",
|
|
||||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
||||||
"Topic :: Software Development :: Quality Assurance",
|
|
||||||
]
|
|
||||||
dependencies = [
|
|
||||||
"click>=8.0.0",
|
|
||||||
"mypy_extensions>=0.4.3",
|
|
||||||
"packaging>=22.0",
|
|
||||||
"pathspec>=0.9.0",
|
|
||||||
"platformdirs>=2",
|
|
||||||
"pytokens>=0.1.10",
|
|
||||||
"tomli>=1.1.0; python_version < '3.11'",
|
|
||||||
"typing_extensions>=4.0.1; python_version < '3.11'",
|
|
||||||
]
|
|
||||||
dynamic = ["readme", "version"]
|
|
||||||
|
|
||||||
[project.optional-dependencies]
|
|
||||||
colorama = ["colorama>=0.4.3"]
|
|
||||||
uvloop = ["uvloop>=0.15.2"]
|
|
||||||
d = ["aiohttp>=3.10"]
|
|
||||||
jupyter = [
|
|
||||||
"ipython>=7.8.0",
|
|
||||||
"tokenize-rt>=3.2.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[project.scripts]
|
|
||||||
black = "black:patched_main"
|
|
||||||
blackd = "blackd:patched_main [d]"
|
|
||||||
|
|
||||||
[project.entry-points."validate_pyproject.tool_schema"]
|
|
||||||
black = "black.schema:get_schema"
|
|
||||||
|
|
||||||
[project.urls]
|
|
||||||
Documentation = "https://black.readthedocs.io/"
|
|
||||||
Changelog = "https://github.com/psf/black/blob/main/CHANGES.md"
|
|
||||||
Repository = "https://github.com/psf/black"
|
|
||||||
Issues = "https://github.com/psf/black/issues"
|
|
||||||
|
|
||||||
[tool.hatch.metadata.hooks.fancy-pypi-readme]
|
|
||||||
content-type = "text/markdown"
|
|
||||||
fragments = [
|
|
||||||
{ path = "README.md" },
|
|
||||||
{ path = "CHANGES.md" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.hatch.version]
|
|
||||||
source = "vcs"
|
|
||||||
|
|
||||||
[tool.hatch.build.hooks.vcs]
|
|
||||||
version-file = "src/_black_version.py"
|
|
||||||
template = '''
|
|
||||||
version = "{version}"
|
|
||||||
'''
|
|
||||||
|
|
||||||
[tool.hatch.build.targets.sdist]
|
|
||||||
exclude = ["/profiling"]
|
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
|
||||||
only-include = ["src"]
|
|
||||||
sources = ["src"]
|
|
||||||
# Note that we change the behaviour of this flag below
|
|
||||||
macos-max-compat = true
|
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel.hooks.mypyc]
|
|
||||||
enable-by-default = false
|
|
||||||
dependencies = [
|
|
||||||
"hatch-mypyc>=0.16.0",
|
|
||||||
"mypy>=1.12",
|
|
||||||
"click>=8.1.7",
|
|
||||||
]
|
|
||||||
require-runtime-dependencies = true
|
|
||||||
exclude = [
|
|
||||||
# There's no good reason for blackd to be compiled.
|
|
||||||
"/src/blackd",
|
|
||||||
# Not performance sensitive, so save bytes + compilation time:
|
|
||||||
"/src/blib2to3/__init__.py",
|
|
||||||
"/src/blib2to3/pgen2/__init__.py",
|
|
||||||
"/src/black/output.py",
|
|
||||||
"/src/black/concurrency.py",
|
|
||||||
"/src/black/files.py",
|
|
||||||
"/src/black/report.py",
|
|
||||||
# Breaks the test suite when compiled (and is also useless):
|
|
||||||
"/src/black/debug.py",
|
|
||||||
# Compiled modules can't be run directly and that's a problem here:
|
|
||||||
"/src/black/__main__.py",
|
|
||||||
]
|
|
||||||
mypy-args = ["--ignore-missing-imports"]
|
|
||||||
options = { debug_level = "0" }
|
|
||||||
|
|
||||||
[tool.cibuildwheel]
|
|
||||||
build-verbosity = 1
|
|
||||||
|
|
||||||
# So these are the environments we target:
|
|
||||||
# - Python: CPython 3.9+ only
|
|
||||||
# - Architecture (64-bit only): amd64 / x86_64, universal2, and arm64
|
|
||||||
# - OS: Linux (no musl), Windows, and macOS
|
|
||||||
build = "cp3*"
|
|
||||||
skip = ["*-manylinux_i686", "*-musllinux_*", "*-win32", "pp*"]
|
|
||||||
|
|
||||||
# This is the bare minimum needed to run the test suite. Pulling in the full
|
|
||||||
# test_requirements.txt would download a bunch of other packages not necessary
|
|
||||||
# here and would slow down the testing step a fair bit.
|
|
||||||
test-requires = ["pytest>=6.1.1"]
|
|
||||||
test-command = 'pytest {project} -k "not incompatible_with_mypyc"'
|
|
||||||
test-extras = ["d"," jupyter"]
|
|
||||||
# Skip trying to test arm64 builds on Intel Macs. (so cross-compilation doesn't
|
|
||||||
# straight up crash)
|
|
||||||
test-skip = ["*-macosx_arm64", "*-macosx_universal2:arm64"]
|
|
||||||
|
|
||||||
[tool.cibuildwheel.environment]
|
|
||||||
HATCH_BUILD_HOOKS_ENABLE = "1"
|
|
||||||
MYPYC_OPT_LEVEL = "3"
|
|
||||||
MYPYC_DEBUG_LEVEL = "0"
|
|
||||||
|
|
||||||
[tool.cibuildwheel.linux]
|
|
||||||
manylinux-x86_64-image = "manylinux_2_28"
|
|
||||||
before-build = [
|
|
||||||
"yum install -y clang gcc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.cibuildwheel.linux.environment]
|
|
||||||
HATCH_BUILD_HOOKS_ENABLE = "1"
|
|
||||||
MYPYC_OPT_LEVEL = "3"
|
|
||||||
MYPYC_DEBUG_LEVEL = "0"
|
|
||||||
|
|
||||||
# Black needs Clang to compile successfully on Linux.
|
|
||||||
CC = "clang"
|
|
||||||
|
|
||||||
[tool.isort]
|
|
||||||
atomic = true
|
|
||||||
profile = "black"
|
|
||||||
line_length = 88
|
|
||||||
skip_gitignore = true
|
|
||||||
skip_glob = ["tests/data", "profiling"]
|
|
||||||
known_first_party = ["black", "blib2to3", "blackd", "_black_version"]
|
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
# Option below requires `tests/optional.py`
|
# Option below requires `tests/optional.py`
|
||||||
addopts = "--strict-config --strict-markers"
|
|
||||||
optional-tests = [
|
optional-tests = [
|
||||||
|
"no_python2: run when `python2` extra NOT installed",
|
||||||
"no_blackd: run when `d` extra NOT installed",
|
"no_blackd: run when `d` extra NOT installed",
|
||||||
"no_jupyter: run when `jupyter` extra NOT installed",
|
"no_jupyter: run when `jupyter` extra NOT installed",
|
||||||
]
|
]
|
||||||
markers = [
|
|
||||||
"incompatible_with_mypyc: run when testing mypyc compiled black"
|
|
||||||
]
|
|
||||||
xfail_strict = true
|
|
||||||
filterwarnings = ["error"]
|
|
||||||
[tool.coverage.report]
|
|
||||||
omit = [
|
|
||||||
"src/blib2to3/*",
|
|
||||||
"tests/data/*",
|
|
||||||
"*/site-packages/*",
|
|
||||||
".tox/*"
|
|
||||||
]
|
|
||||||
[tool.coverage.run]
|
|
||||||
relative_files = true
|
|
||||||
branch = true
|
|
||||||
|
|
||||||
[tool.mypy]
|
|
||||||
# Specify the target platform details in config, so your developers are
|
|
||||||
# free to run mypy on Windows, Linux, or macOS and get consistent
|
|
||||||
# results.
|
|
||||||
python_version = "3.9"
|
|
||||||
mypy_path = "src"
|
|
||||||
strict = true
|
|
||||||
strict_bytes = true
|
|
||||||
local_partial_types = true
|
|
||||||
# Unreachable blocks have been an issue when compiling mypyc, let's try to avoid 'em in the first place.
|
|
||||||
warn_unreachable = true
|
|
||||||
implicit_reexport = true
|
|
||||||
show_error_codes = true
|
|
||||||
show_column_numbers = true
|
|
||||||
|
|
||||||
[[tool.mypy.overrides]]
|
|
||||||
module = ["pathspec.*", "IPython.*", "colorama.*", "tokenize_rt.*", "uvloop.*", "_black_version.*"]
|
|
||||||
ignore_missing_imports = true
|
|
||||||
|
|
||||||
# CI only checks src/, but in case users are running LSP or similar we explicitly ignore
|
|
||||||
# errors in test data files.
|
|
||||||
[[tool.mypy.overrides]]
|
|
||||||
module = ["tests.data.*"]
|
|
||||||
ignore_errors = true
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import commonmark
|
import commonmark
|
||||||
import yaml
|
import yaml
|
||||||
from bs4 import BeautifulSoup # type: ignore[import-untyped]
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
|
||||||
def main(changes: str, source_version_control: str) -> None:
|
def main(changes: str, source_version_control: str) -> None:
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
"""
|
|
||||||
Check that the rev value in the example from ``the_basics.md`` matches
|
|
||||||
the latest version of Black. This saves us from forgetting to update that
|
|
||||||
during the release process.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import commonmark
|
|
||||||
from bs4 import BeautifulSoup # type: ignore[import-untyped]
|
|
||||||
|
|
||||||
|
|
||||||
def main(changes: str, the_basics: str) -> None:
|
|
||||||
changes_html = commonmark.commonmark(changes)
|
|
||||||
changes_soup = BeautifulSoup(changes_html, "html.parser")
|
|
||||||
headers = changes_soup.find_all("h2")
|
|
||||||
tags = [header.string for header in headers if header.string != "Unreleased"]
|
|
||||||
latest_tag = tags[0]
|
|
||||||
|
|
||||||
the_basics_html = commonmark.commonmark(the_basics)
|
|
||||||
the_basics_soup = BeautifulSoup(the_basics_html, "html.parser")
|
|
||||||
version_examples = [
|
|
||||||
code_block.string
|
|
||||||
for code_block in the_basics_soup.find_all(class_="language-console")
|
|
||||||
if "$ black --version" in code_block.string
|
|
||||||
]
|
|
||||||
|
|
||||||
for tag in tags:
|
|
||||||
for version_example in version_examples:
|
|
||||||
if tag in version_example and tag != latest_tag:
|
|
||||||
print(
|
|
||||||
"Please set the version in the ``black --version`` "
|
|
||||||
"examples from ``the_basics.md`` to be the latest one.\n"
|
|
||||||
f"Expected {latest_tag}, got {tag}.\n"
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
with open("CHANGES.md", encoding="utf-8") as fd:
|
|
||||||
changes = fd.read()
|
|
||||||
with open(
|
|
||||||
os.path.join("docs", "usage_and_configuration", "the_basics.md"),
|
|
||||||
encoding="utf-8",
|
|
||||||
) as fd:
|
|
||||||
the_basics = fd.read()
|
|
||||||
main(changes, the_basics)
|
|
@ -1,231 +0,0 @@
|
|||||||
"""Helper script for psf/black's diff-shades Github Actions integration.
|
|
||||||
|
|
||||||
diff-shades is a tool for analyzing what happens when you run Black on
|
|
||||||
OSS code capturing it for comparisons or other usage. It's used here to
|
|
||||||
help measure the impact of a change *before* landing it (in particular
|
|
||||||
posting a comment on completion for PRs).
|
|
||||||
|
|
||||||
This script exists as a more maintainable alternative to using inline
|
|
||||||
Javascript in the workflow YAML files. The revision configuration and
|
|
||||||
resolving, caching, and PR comment logic is contained here.
|
|
||||||
|
|
||||||
For more information, please see the developer docs:
|
|
||||||
|
|
||||||
https://black.readthedocs.io/en/latest/contributing/gauging_changes.html#diff-shades
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
import pprint
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import zipfile
|
|
||||||
from base64 import b64encode
|
|
||||||
from io import BytesIO
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Final, Literal
|
|
||||||
|
|
||||||
import click
|
|
||||||
import urllib3
|
|
||||||
from packaging.version import Version
|
|
||||||
|
|
||||||
COMMENT_FILE: Final = ".pr-comment.json"
|
|
||||||
DIFF_STEP_NAME: Final = "Generate HTML diff report"
|
|
||||||
DOCS_URL: Final = (
|
|
||||||
"https://black.readthedocs.io/en/latest/"
|
|
||||||
"contributing/gauging_changes.html#diff-shades"
|
|
||||||
)
|
|
||||||
USER_AGENT: Final = f"psf/black diff-shades workflow via urllib3/{urllib3.__version__}"
|
|
||||||
SHA_LENGTH: Final = 10
|
|
||||||
GH_API_TOKEN: Final = os.getenv("GITHUB_TOKEN")
|
|
||||||
REPO: Final = os.getenv("GITHUB_REPOSITORY", default="psf/black")
|
|
||||||
http = urllib3.PoolManager()
|
|
||||||
|
|
||||||
|
|
||||||
def set_output(name: str, value: str) -> None:
|
|
||||||
if len(value) < 200:
|
|
||||||
print(f"[INFO]: setting '{name}' to '{value}'")
|
|
||||||
else:
|
|
||||||
print(f"[INFO]: setting '{name}' to [{len(value)} chars]")
|
|
||||||
|
|
||||||
if "GITHUB_OUTPUT" in os.environ:
|
|
||||||
if "\n" in value:
|
|
||||||
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
|
|
||||||
delimiter = b64encode(os.urandom(16)).decode()
|
|
||||||
value = f"{delimiter}\n{value}\n{delimiter}"
|
|
||||||
command = f"{name}<<{value}"
|
|
||||||
else:
|
|
||||||
command = f"{name}={value}"
|
|
||||||
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
|
|
||||||
print(command, file=f)
|
|
||||||
|
|
||||||
|
|
||||||
def http_get(url: str, *, is_json: bool = True, **kwargs: Any) -> Any:
|
|
||||||
headers = kwargs.get("headers") or {}
|
|
||||||
headers["User-Agent"] = USER_AGENT
|
|
||||||
if "github" in url:
|
|
||||||
if GH_API_TOKEN:
|
|
||||||
headers["Authorization"] = f"token {GH_API_TOKEN}"
|
|
||||||
headers["Accept"] = "application/vnd.github.v3+json"
|
|
||||||
kwargs["headers"] = headers
|
|
||||||
|
|
||||||
r = http.request("GET", url, **kwargs)
|
|
||||||
if is_json:
|
|
||||||
data = json.loads(r.data.decode("utf-8"))
|
|
||||||
else:
|
|
||||||
data = r.data
|
|
||||||
print(f"[INFO]: issued GET request for {r.geturl()}")
|
|
||||||
if not (200 <= r.status < 300):
|
|
||||||
pprint.pprint(dict(r.info()))
|
|
||||||
pprint.pprint(data)
|
|
||||||
raise RuntimeError(f"unexpected status code: {r.status}")
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
def get_main_revision() -> str:
|
|
||||||
data = http_get(
|
|
||||||
f"https://api.github.com/repos/{REPO}/commits",
|
|
||||||
fields={"per_page": "1", "sha": "main"},
|
|
||||||
)
|
|
||||||
assert isinstance(data[0]["sha"], str)
|
|
||||||
return data[0]["sha"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_pr_revision(pr: int) -> str:
|
|
||||||
data = http_get(f"https://api.github.com/repos/{REPO}/pulls/{pr}")
|
|
||||||
assert isinstance(data["head"]["sha"], str)
|
|
||||||
return data["head"]["sha"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_pypi_version() -> Version:
|
|
||||||
data = http_get("https://pypi.org/pypi/black/json")
|
|
||||||
versions = [Version(v) for v in data["releases"]]
|
|
||||||
sorted_versions = sorted(versions, reverse=True)
|
|
||||||
return sorted_versions[0]
|
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
|
||||||
def main() -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@main.command("config", help="Acquire run configuration and metadata.")
|
|
||||||
@click.argument("event", type=click.Choice(["push", "pull_request"]))
|
|
||||||
def config(event: Literal["push", "pull_request"]) -> None:
|
|
||||||
import diff_shades # type: ignore[import-not-found]
|
|
||||||
|
|
||||||
if event == "push":
|
|
||||||
jobs = [{"mode": "preview-changes", "force-flag": "--force-preview-style"}]
|
|
||||||
# Push on main, let's use PyPI Black as the baseline.
|
|
||||||
baseline_name = str(get_pypi_version())
|
|
||||||
baseline_cmd = f"git checkout {baseline_name}"
|
|
||||||
target_rev = os.getenv("GITHUB_SHA")
|
|
||||||
assert target_rev is not None
|
|
||||||
target_name = "main-" + target_rev[:SHA_LENGTH]
|
|
||||||
target_cmd = f"git checkout {target_rev}"
|
|
||||||
|
|
||||||
elif event == "pull_request":
|
|
||||||
jobs = [
|
|
||||||
{"mode": "preview-changes", "force-flag": "--force-preview-style"},
|
|
||||||
{"mode": "assert-no-changes", "force-flag": "--force-stable-style"},
|
|
||||||
]
|
|
||||||
# PR, let's use main as the baseline.
|
|
||||||
baseline_rev = get_main_revision()
|
|
||||||
baseline_name = "main-" + baseline_rev[:SHA_LENGTH]
|
|
||||||
baseline_cmd = f"git checkout {baseline_rev}"
|
|
||||||
pr_ref = os.getenv("GITHUB_REF")
|
|
||||||
assert pr_ref is not None
|
|
||||||
pr_num = int(pr_ref[10:-6])
|
|
||||||
pr_rev = get_pr_revision(pr_num)
|
|
||||||
target_name = f"pr-{pr_num}-{pr_rev[:SHA_LENGTH]}"
|
|
||||||
target_cmd = f"gh pr checkout {pr_num} && git merge origin/main"
|
|
||||||
|
|
||||||
env = f"{platform.system()}-{platform.python_version()}-{diff_shades.__version__}"
|
|
||||||
for entry in jobs:
|
|
||||||
entry["baseline-analysis"] = f"{entry['mode']}-{baseline_name}.json"
|
|
||||||
entry["baseline-setup-cmd"] = baseline_cmd
|
|
||||||
entry["target-analysis"] = f"{entry['mode']}-{target_name}.json"
|
|
||||||
entry["target-setup-cmd"] = target_cmd
|
|
||||||
entry["baseline-cache-key"] = f"{env}-{baseline_name}-{entry['mode']}"
|
|
||||||
if event == "pull_request":
|
|
||||||
# These are only needed for the PR comment.
|
|
||||||
entry["baseline-sha"] = baseline_rev
|
|
||||||
entry["target-sha"] = pr_rev
|
|
||||||
|
|
||||||
set_output("matrix", json.dumps(jobs, indent=None))
|
|
||||||
pprint.pprint(jobs)
|
|
||||||
|
|
||||||
|
|
||||||
@main.command("comment-body", help="Generate the body for a summary PR comment.")
|
|
||||||
@click.argument("baseline", type=click.Path(exists=True, path_type=Path))
|
|
||||||
@click.argument("target", type=click.Path(exists=True, path_type=Path))
|
|
||||||
@click.argument("baseline-sha")
|
|
||||||
@click.argument("target-sha")
|
|
||||||
@click.argument("pr-num", type=int)
|
|
||||||
def comment_body(
|
|
||||||
baseline: Path, target: Path, baseline_sha: str, target_sha: str, pr_num: int
|
|
||||||
) -> None:
|
|
||||||
# fmt: off
|
|
||||||
cmd = [
|
|
||||||
sys.executable, "-m", "diff_shades", "--no-color",
|
|
||||||
"compare", str(baseline), str(target), "--quiet", "--check"
|
|
||||||
]
|
|
||||||
# fmt: on
|
|
||||||
proc = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf-8")
|
|
||||||
if not proc.returncode:
|
|
||||||
body = (
|
|
||||||
f"**diff-shades** reports zero changes comparing this PR ({target_sha}) to"
|
|
||||||
f" main ({baseline_sha}).\n\n---\n\n"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
body = (
|
|
||||||
f"**diff-shades** results comparing this PR ({target_sha}) to main"
|
|
||||||
f" ({baseline_sha}). The full diff is [available in the logs]"
|
|
||||||
f'($job-diff-url) under the "{DIFF_STEP_NAME}" step.'
|
|
||||||
)
|
|
||||||
body += "\n```text\n" + proc.stdout.strip() + "\n```\n"
|
|
||||||
body += (
|
|
||||||
f"[**What is this?**]({DOCS_URL}) | [Workflow run]($workflow-run-url) |"
|
|
||||||
" [diff-shades documentation](https://github.com/ichard26/diff-shades#readme)"
|
|
||||||
)
|
|
||||||
print(f"[INFO]: writing comment details to {COMMENT_FILE}")
|
|
||||||
with open(COMMENT_FILE, "w", encoding="utf-8") as f:
|
|
||||||
json.dump({"body": body, "pr-number": pr_num}, f)
|
|
||||||
|
|
||||||
|
|
||||||
@main.command("comment-details", help="Get PR comment resources from a workflow run.")
|
|
||||||
@click.argument("run-id")
|
|
||||||
def comment_details(run_id: str) -> None:
|
|
||||||
data = http_get(f"https://api.github.com/repos/{REPO}/actions/runs/{run_id}")
|
|
||||||
if data["event"] != "pull_request" or data["conclusion"] == "cancelled":
|
|
||||||
set_output("needs-comment", "false")
|
|
||||||
return
|
|
||||||
|
|
||||||
set_output("needs-comment", "true")
|
|
||||||
jobs = http_get(data["jobs_url"])["jobs"]
|
|
||||||
job = next(j for j in jobs if j["name"] == "analysis / preview-changes")
|
|
||||||
diff_step = next(s for s in job["steps"] if s["name"] == DIFF_STEP_NAME)
|
|
||||||
diff_url = job["html_url"] + f"#step:{diff_step['number']}:1"
|
|
||||||
|
|
||||||
artifacts = http_get(data["artifacts_url"])["artifacts"]
|
|
||||||
comment_artifact = next(a for a in artifacts if a["name"] == COMMENT_FILE)
|
|
||||||
comment_url = comment_artifact["archive_download_url"]
|
|
||||||
comment_zip = BytesIO(http_get(comment_url, is_json=False))
|
|
||||||
with zipfile.ZipFile(comment_zip) as zfile:
|
|
||||||
with zfile.open(COMMENT_FILE) as rf:
|
|
||||||
comment_data = json.loads(rf.read().decode("utf-8"))
|
|
||||||
|
|
||||||
set_output("pr-number", str(comment_data["pr-number"]))
|
|
||||||
body = comment_data["body"]
|
|
||||||
# It's more convenient to fill in these fields after the first workflow is done
|
|
||||||
# since this command can access the workflows API (doing it in the main workflow
|
|
||||||
# while it's still in progress seems impossible).
|
|
||||||
body = body.replace("$workflow-run-url", data["html_url"])
|
|
||||||
body = body.replace("$job-diff-url", diff_url)
|
|
||||||
set_output("comment-body", body)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,74 +0,0 @@
|
|||||||
import json
|
|
||||||
from typing import IO, Any
|
|
||||||
|
|
||||||
import click
|
|
||||||
|
|
||||||
import black
|
|
||||||
|
|
||||||
|
|
||||||
def generate_schema_from_click(
|
|
||||||
cmd: click.Command,
|
|
||||||
) -> dict[str, Any]:
|
|
||||||
result: dict[str, dict[str, Any]] = {}
|
|
||||||
for param in cmd.params:
|
|
||||||
if not isinstance(param, click.Option) or param.is_eager:
|
|
||||||
continue
|
|
||||||
|
|
||||||
assert param.name
|
|
||||||
name = param.name.replace("_", "-")
|
|
||||||
|
|
||||||
result[name] = {}
|
|
||||||
|
|
||||||
match param.type:
|
|
||||||
case click.types.IntParamType():
|
|
||||||
result[name]["type"] = "integer"
|
|
||||||
case click.types.StringParamType() | click.types.Path():
|
|
||||||
result[name]["type"] = "string"
|
|
||||||
case click.types.Choice(choices=choices):
|
|
||||||
result[name]["enum"] = choices
|
|
||||||
case click.types.BoolParamType():
|
|
||||||
result[name]["type"] = "boolean"
|
|
||||||
case _:
|
|
||||||
msg = f"{param.type!r} not a known type for {param}"
|
|
||||||
raise TypeError(msg)
|
|
||||||
|
|
||||||
if param.multiple:
|
|
||||||
result[name] = {"type": "array", "items": result[name]}
|
|
||||||
|
|
||||||
result[name]["description"] = param.help
|
|
||||||
|
|
||||||
if param.default is not None and not param.multiple:
|
|
||||||
result[name]["default"] = param.default
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
@click.command(context_settings={"help_option_names": ["-h", "--help"]})
|
|
||||||
@click.option("--schemastore", is_flag=True, help="SchemaStore format")
|
|
||||||
@click.option("--outfile", type=click.File(mode="w"), help="Write to file")
|
|
||||||
def main(schemastore: bool, outfile: IO[str]) -> None:
|
|
||||||
properties = generate_schema_from_click(black.main)
|
|
||||||
del properties["line-ranges"]
|
|
||||||
|
|
||||||
schema: dict[str, Any] = {
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"$id": (
|
|
||||||
"https://github.com/psf/black/blob/main/src/black/resources/black.schema.json"
|
|
||||||
),
|
|
||||||
"$comment": "tool.black table in pyproject.toml",
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": False,
|
|
||||||
"properties": properties,
|
|
||||||
}
|
|
||||||
|
|
||||||
if schemastore:
|
|
||||||
schema["$id"] = "https://json.schemastore.org/partial-black.json"
|
|
||||||
# The precise list of unstable features may change frequently, so don't
|
|
||||||
# bother putting it in SchemaStore
|
|
||||||
schema["properties"]["enable-unstable-feature"]["items"] = {"type": "string"}
|
|
||||||
|
|
||||||
print(json.dumps(schema, indent=2), file=outfile)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,66 +0,0 @@
|
|||||||
"""Generates a width table for Unicode characters.
|
|
||||||
|
|
||||||
This script generates a width table for Unicode characters that are not
|
|
||||||
narrow (width 1). The table is written to src/black/_width_table.py (note
|
|
||||||
that although this file is generated, it is checked into Git) and is used
|
|
||||||
by the char_width() function in src/black/strings.py.
|
|
||||||
|
|
||||||
You should run this script when you upgrade wcwidth, which is expected to
|
|
||||||
happen when a new Unicode version is released. The generated table contains
|
|
||||||
the version of wcwidth and Unicode that it was generated for.
|
|
||||||
|
|
||||||
In order to run this script, you need to install the latest version of wcwidth.
|
|
||||||
You can do this by running:
|
|
||||||
|
|
||||||
pip install -U wcwidth
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from collections.abc import Iterable
|
|
||||||
from os.path import basename, dirname, join
|
|
||||||
|
|
||||||
import wcwidth # type: ignore[import-not-found]
|
|
||||||
|
|
||||||
|
|
||||||
def make_width_table() -> Iterable[tuple[int, int, int]]:
|
|
||||||
start_codepoint = -1
|
|
||||||
end_codepoint = -1
|
|
||||||
range_width = -2
|
|
||||||
for codepoint in range(0, sys.maxunicode + 1):
|
|
||||||
width = wcwidth.wcwidth(chr(codepoint))
|
|
||||||
if width <= 1:
|
|
||||||
# Ignore narrow characters along with zero-width characters so that
|
|
||||||
# they are treated as single-width. Note that treating zero-width
|
|
||||||
# characters as single-width is consistent with the heuristics built
|
|
||||||
# on top of str.isascii() in the str_width() function in strings.py.
|
|
||||||
continue
|
|
||||||
if start_codepoint < 0:
|
|
||||||
start_codepoint = codepoint
|
|
||||||
range_width = width
|
|
||||||
elif width != range_width or codepoint != end_codepoint + 1:
|
|
||||||
yield (start_codepoint, end_codepoint, range_width)
|
|
||||||
start_codepoint = codepoint
|
|
||||||
range_width = width
|
|
||||||
end_codepoint = codepoint
|
|
||||||
if start_codepoint >= 0:
|
|
||||||
yield (start_codepoint, end_codepoint, range_width)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
table_path = join(dirname(__file__), "..", "src", "black", "_width_table.py")
|
|
||||||
with open(table_path, "w") as f:
|
|
||||||
f.write(f"""# Generated by {basename(__file__)}
|
|
||||||
# wcwidth {wcwidth.__version__}
|
|
||||||
# Unicode {wcwidth.list_versions()[-1]}
|
|
||||||
from typing import Final
|
|
||||||
|
|
||||||
WIDTH_TABLE: Final[list[tuple[int, int, int]]] = [
|
|
||||||
""")
|
|
||||||
for triple in make_width_table():
|
|
||||||
f.write(f" {triple!r},\n")
|
|
||||||
f.write("]\n")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@ -1,96 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# check out every commit added by the current branch, blackify them,
|
|
||||||
# and generate diffs to reconstruct the original commits, but then
|
|
||||||
# blackified
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from subprocess import PIPE, Popen, check_output, run
|
|
||||||
|
|
||||||
|
|
||||||
def git(*args: str) -> str:
|
|
||||||
return check_output(["git", *args]).decode("utf8").strip()
|
|
||||||
|
|
||||||
|
|
||||||
def blackify(base_branch: str, black_command: str, logger: logging.Logger) -> int:
|
|
||||||
current_branch = git("branch", "--show-current")
|
|
||||||
|
|
||||||
if not current_branch or base_branch == current_branch:
|
|
||||||
logger.error("You need to check out a feature branch to work on")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if not os.path.exists(".git"):
|
|
||||||
logger.error("Run me in the root of your repo")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
merge_base = git("merge-base", "HEAD", base_branch)
|
|
||||||
if not merge_base:
|
|
||||||
logger.error(
|
|
||||||
f"Could not find a common commit for current head and {base_branch}"
|
|
||||||
)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
commits = git(
|
|
||||||
"log", "--reverse", "--pretty=format:%H", f"{merge_base}~1..HEAD"
|
|
||||||
).split()
|
|
||||||
for commit in commits:
|
|
||||||
git("checkout", commit, f"-b{commit}-black")
|
|
||||||
check_output(black_command, shell=True)
|
|
||||||
git("commit", "-aqm", "blackify")
|
|
||||||
|
|
||||||
git("checkout", base_branch, f"-b{current_branch}-black")
|
|
||||||
|
|
||||||
for last_commit, commit in zip(commits, commits[1:]):
|
|
||||||
allow_empty = (
|
|
||||||
b"--allow-empty" in run(["git", "apply", "-h"], stdout=PIPE).stdout
|
|
||||||
)
|
|
||||||
quiet = b"--quiet" in run(["git", "apply", "-h"], stdout=PIPE).stdout
|
|
||||||
git_diff = Popen(
|
|
||||||
[
|
|
||||||
"git",
|
|
||||||
"diff",
|
|
||||||
"--binary",
|
|
||||||
"--find-copies",
|
|
||||||
f"{last_commit}-black..{commit}-black",
|
|
||||||
],
|
|
||||||
stdout=PIPE,
|
|
||||||
)
|
|
||||||
git_apply = Popen(
|
|
||||||
[
|
|
||||||
"git",
|
|
||||||
"apply",
|
|
||||||
]
|
|
||||||
+ (["--quiet"] if quiet else [])
|
|
||||||
+ [
|
|
||||||
"-3",
|
|
||||||
"--intent-to-add",
|
|
||||||
]
|
|
||||||
+ (["--allow-empty"] if allow_empty else [])
|
|
||||||
+ [
|
|
||||||
"-",
|
|
||||||
],
|
|
||||||
stdin=git_diff.stdout,
|
|
||||||
)
|
|
||||||
if git_diff.stdout is not None:
|
|
||||||
git_diff.stdout.close()
|
|
||||||
git_apply.communicate()
|
|
||||||
git("commit", "--allow-empty", "-aqC", commit)
|
|
||||||
|
|
||||||
for commit in commits:
|
|
||||||
git("branch", "-qD", f"{commit}-black")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("base_branch")
|
|
||||||
parser.add_argument("--black_command", default="black -q .")
|
|
||||||
parser.add_argument("--logfile", type=argparse.FileType("w"), default=sys.stdout)
|
|
||||||
args = parser.parse_args()
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
logger.addHandler(logging.StreamHandler(args.logfile))
|
|
||||||
logger.setLevel(logging.INFO)
|
|
||||||
sys.exit(blackify(args.base_branch, args.black_command, logger))
|
|
@ -1,244 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tool to help automate changes needed in commits during and after releases
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from subprocess import run
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
NEW_VERSION_CHANGELOG_TEMPLATE = """\
|
|
||||||
## Unreleased
|
|
||||||
|
|
||||||
### Highlights
|
|
||||||
|
|
||||||
<!-- Include any especially major or disruptive changes here -->
|
|
||||||
|
|
||||||
### Stable style
|
|
||||||
|
|
||||||
<!-- Changes that affect Black's stable style -->
|
|
||||||
|
|
||||||
### Preview style
|
|
||||||
|
|
||||||
<!-- Changes that affect Black's preview style -->
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
<!-- Changes to how Black can be configured -->
|
|
||||||
|
|
||||||
### Packaging
|
|
||||||
|
|
||||||
<!-- Changes to how Black is packaged, such as dependency requirements -->
|
|
||||||
|
|
||||||
### Parser
|
|
||||||
|
|
||||||
<!-- Changes to the parser or to version autodetection -->
|
|
||||||
|
|
||||||
### Performance
|
|
||||||
|
|
||||||
<!-- Changes that improve Black's performance. -->
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
<!-- Changes to Black's terminal output and error messages -->
|
|
||||||
|
|
||||||
### _Blackd_
|
|
||||||
|
|
||||||
<!-- Changes to blackd -->
|
|
||||||
|
|
||||||
### Integrations
|
|
||||||
|
|
||||||
<!-- For example, Docker, GitHub Actions, pre-commit, editors -->
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
<!-- Major changes to documentation and policies. Small docs changes
|
|
||||||
don't need a changelog entry. -->
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class NoGitTagsError(Exception): ... # noqa: E701,E761
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: Do better with alpha + beta releases
|
|
||||||
# Maybe we vendor packaging library
|
|
||||||
def get_git_tags(versions_only: bool = True) -> list[str]:
|
|
||||||
"""Pull out all tags or calvers only"""
|
|
||||||
cp = run(["git", "tag"], capture_output=True, check=True, encoding="utf8")
|
|
||||||
if not cp.stdout:
|
|
||||||
LOG.error(f"Returned no git tags stdout: {cp.stderr}")
|
|
||||||
raise NoGitTagsError
|
|
||||||
git_tags = cp.stdout.splitlines()
|
|
||||||
if versions_only:
|
|
||||||
return [t for t in git_tags if t[0].isdigit()]
|
|
||||||
return git_tags
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: Support sorting alhpa/beta releases correctly
|
|
||||||
def tuple_calver(calver: str) -> tuple[int, ...]: # mypy can't notice maxsplit below
|
|
||||||
"""Convert a calver string into a tuple of ints for sorting"""
|
|
||||||
try:
|
|
||||||
return tuple(map(int, calver.split(".", maxsplit=2)))
|
|
||||||
except ValueError:
|
|
||||||
return (0, 0, 0)
|
|
||||||
|
|
||||||
|
|
||||||
class SourceFiles:
|
|
||||||
def __init__(self, black_repo_dir: Path):
|
|
||||||
# File path fun all pathlib to be platform agnostic
|
|
||||||
self.black_repo_path = black_repo_dir
|
|
||||||
self.changes_path = self.black_repo_path / "CHANGES.md"
|
|
||||||
self.docs_path = self.black_repo_path / "docs"
|
|
||||||
self.version_doc_paths = (
|
|
||||||
self.docs_path / "integrations" / "source_version_control.md",
|
|
||||||
self.docs_path / "usage_and_configuration" / "the_basics.md",
|
|
||||||
)
|
|
||||||
self.current_version = self.get_current_version()
|
|
||||||
self.next_version = self.get_next_version()
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"""\
|
|
||||||
> SourceFiles ENV:
|
|
||||||
Repo path: {self.black_repo_path}
|
|
||||||
CHANGES.md path: {self.changes_path}
|
|
||||||
docs path: {self.docs_path}
|
|
||||||
Current version: {self.current_version}
|
|
||||||
Next version: {self.next_version}
|
|
||||||
"""
|
|
||||||
|
|
||||||
def add_template_to_changes(self) -> int:
|
|
||||||
"""Add the template to CHANGES.md if it does not exist"""
|
|
||||||
LOG.info(f"Adding template to {self.changes_path}")
|
|
||||||
|
|
||||||
with self.changes_path.open("r") as cfp:
|
|
||||||
changes_string = cfp.read()
|
|
||||||
|
|
||||||
if "## Unreleased" in changes_string:
|
|
||||||
LOG.error(f"{self.changes_path} already has unreleased template")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
templated_changes_string = changes_string.replace(
|
|
||||||
"# Change Log\n",
|
|
||||||
f"# Change Log\n\n{NEW_VERSION_CHANGELOG_TEMPLATE}",
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.changes_path.open("w") as cfp:
|
|
||||||
cfp.write(templated_changes_string)
|
|
||||||
|
|
||||||
LOG.info(f"Added template to {self.changes_path}")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def cleanup_changes_template_for_release(self) -> None:
|
|
||||||
LOG.info(f"Cleaning up {self.changes_path}")
|
|
||||||
|
|
||||||
with self.changes_path.open("r") as cfp:
|
|
||||||
changes_string = cfp.read()
|
|
||||||
|
|
||||||
# Change Unreleased to next version
|
|
||||||
versioned_changes = changes_string.replace(
|
|
||||||
"## Unreleased", f"## {self.next_version}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove all comments (subheadings are harder - Human required still)
|
|
||||||
no_comments_changes = []
|
|
||||||
for line in versioned_changes.splitlines():
|
|
||||||
if line.startswith("<!--") or line.endswith("-->"):
|
|
||||||
continue
|
|
||||||
no_comments_changes.append(line)
|
|
||||||
|
|
||||||
with self.changes_path.open("w") as cfp:
|
|
||||||
cfp.write("\n".join(no_comments_changes) + "\n")
|
|
||||||
|
|
||||||
LOG.debug(f"Finished Cleaning up {self.changes_path}")
|
|
||||||
|
|
||||||
def get_current_version(self) -> str:
|
|
||||||
"""Get the latest git (version) tag as latest version"""
|
|
||||||
return sorted(get_git_tags(), key=lambda k: tuple_calver(k))[-1]
|
|
||||||
|
|
||||||
def get_next_version(self) -> str:
|
|
||||||
"""Workout the year and month + version number we need to move to"""
|
|
||||||
base_calver = datetime.today().strftime("%y.%m")
|
|
||||||
calver_parts = base_calver.split(".")
|
|
||||||
base_calver = f"{calver_parts[0]}.{int(calver_parts[1])}" # Remove leading 0
|
|
||||||
git_tags = get_git_tags()
|
|
||||||
same_month_releases = [
|
|
||||||
t for t in git_tags if t.startswith(base_calver) and "a" not in t
|
|
||||||
]
|
|
||||||
if len(same_month_releases) < 1:
|
|
||||||
return f"{base_calver}.0"
|
|
||||||
same_month_version = same_month_releases[-1].split(".", 2)[-1]
|
|
||||||
return f"{base_calver}.{int(same_month_version) + 1}"
|
|
||||||
|
|
||||||
def update_repo_for_release(self) -> int:
|
|
||||||
"""Update CHANGES.md + doc files ready for release"""
|
|
||||||
self.cleanup_changes_template_for_release()
|
|
||||||
self.update_version_in_docs()
|
|
||||||
return 0 # return 0 if no exceptions hit
|
|
||||||
|
|
||||||
def update_version_in_docs(self) -> None:
|
|
||||||
for doc_path in self.version_doc_paths:
|
|
||||||
LOG.info(f"Updating black version to {self.next_version} in {doc_path}")
|
|
||||||
|
|
||||||
with doc_path.open("r") as dfp:
|
|
||||||
doc_string = dfp.read()
|
|
||||||
|
|
||||||
next_version_doc = doc_string.replace(
|
|
||||||
self.current_version, self.next_version
|
|
||||||
)
|
|
||||||
|
|
||||||
with doc_path.open("w") as dfp:
|
|
||||||
dfp.write(next_version_doc)
|
|
||||||
|
|
||||||
LOG.debug(
|
|
||||||
f"Finished updating black version to {self.next_version} in {doc_path}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _handle_debug(debug: bool) -> None:
|
|
||||||
"""Turn on debugging if asked otherwise INFO default"""
|
|
||||||
log_level = logging.DEBUG if debug else logging.INFO
|
|
||||||
logging.basicConfig(
|
|
||||||
format="[%(asctime)s] %(levelname)s: %(message)s (%(filename)s:%(lineno)d)",
|
|
||||||
level=log_level,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args() -> argparse.Namespace:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"-a",
|
|
||||||
"--add-changes-template",
|
|
||||||
action="store_true",
|
|
||||||
help="Add the Unreleased template to CHANGES.md",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-d", "--debug", action="store_true", help="Verbose debug output"
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
_handle_debug(args.debug)
|
|
||||||
return args
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
args = parse_args()
|
|
||||||
|
|
||||||
# Need parent.parent cause script is in scripts/ directory
|
|
||||||
sf = SourceFiles(Path(__file__).parent.parent)
|
|
||||||
|
|
||||||
if args.add_changes_template:
|
|
||||||
return sf.add_template_to_changes()
|
|
||||||
|
|
||||||
LOG.info(f"Current version detected to be {sf.current_version}")
|
|
||||||
LOG.info(f"Next version will be {sf.next_version}")
|
|
||||||
return sf.update_repo_for_release()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": # pragma: no cover
|
|
||||||
sys.exit(main())
|
|
@ -1,69 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
from pathlib import Path
|
|
||||||
from shutil import rmtree
|
|
||||||
from tempfile import TemporaryDirectory
|
|
||||||
from typing import Any
|
|
||||||
from unittest.mock import Mock, patch
|
|
||||||
|
|
||||||
from release import SourceFiles, tuple_calver # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
class FakeDateTime:
|
|
||||||
"""Used to mock the date to test generating next calver function"""
|
|
||||||
|
|
||||||
def today(*args: Any, **kwargs: Any) -> "FakeDateTime": # noqa
|
|
||||||
return FakeDateTime()
|
|
||||||
|
|
||||||
# Add leading 0 on purpose to ensure we remove it
|
|
||||||
def strftime(*args: Any, **kwargs: Any) -> str: # noqa
|
|
||||||
return "69.01"
|
|
||||||
|
|
||||||
|
|
||||||
class TestRelease(unittest.TestCase):
|
|
||||||
def setUp(self) -> None:
|
|
||||||
# We only test on >= 3.12
|
|
||||||
self.tempdir = TemporaryDirectory(delete=False) # type: ignore
|
|
||||||
self.tempdir_path = Path(self.tempdir.name)
|
|
||||||
self.sf = SourceFiles(self.tempdir_path)
|
|
||||||
|
|
||||||
def tearDown(self) -> None:
|
|
||||||
rmtree(self.tempdir.name)
|
|
||||||
return super().tearDown()
|
|
||||||
|
|
||||||
@patch("release.get_git_tags")
|
|
||||||
def test_get_current_version(self, mocked_git_tags: Mock) -> None:
|
|
||||||
mocked_git_tags.return_value = ["1.1.0", "69.1.0", "69.1.1", "2.2.0"]
|
|
||||||
self.assertEqual("69.1.1", self.sf.get_current_version())
|
|
||||||
|
|
||||||
@patch("release.get_git_tags")
|
|
||||||
@patch("release.datetime", FakeDateTime)
|
|
||||||
def test_get_next_version(self, mocked_git_tags: Mock) -> None:
|
|
||||||
# test we handle no args
|
|
||||||
mocked_git_tags.return_value = []
|
|
||||||
self.assertEqual(
|
|
||||||
"69.1.0",
|
|
||||||
self.sf.get_next_version(),
|
|
||||||
"Unable to get correct next version with no git tags",
|
|
||||||
)
|
|
||||||
|
|
||||||
# test we handle
|
|
||||||
mocked_git_tags.return_value = ["1.1.0", "69.1.0", "69.1.1", "2.2.0"]
|
|
||||||
self.assertEqual(
|
|
||||||
"69.1.2",
|
|
||||||
self.sf.get_next_version(),
|
|
||||||
"Unable to get correct version with 2 previous versions released this"
|
|
||||||
" month",
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_tuple_calver(self) -> None:
|
|
||||||
first_month_release = tuple_calver("69.1.0")
|
|
||||||
second_month_release = tuple_calver("69.1.1")
|
|
||||||
self.assertEqual((69, 1, 0), first_month_release)
|
|
||||||
self.assertEqual((0, 0, 0), tuple_calver("69.1.1a0")) # Hack for alphas/betas
|
|
||||||
self.assertTrue(first_month_release < second_month_release)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
118
setup.py
Normal file
118
setup.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# Copyright (C) 2020 Łukasz Langa
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
assert sys.version_info >= (3, 6, 2), "black requires Python 3.6.2+"
|
||||||
|
from pathlib import Path # noqa E402
|
||||||
|
|
||||||
|
CURRENT_DIR = Path(__file__).parent
|
||||||
|
sys.path.insert(0, str(CURRENT_DIR)) # for setuptools.build_meta
|
||||||
|
|
||||||
|
|
||||||
|
def get_long_description() -> str:
|
||||||
|
return (
|
||||||
|
(CURRENT_DIR / "README.md").read_text(encoding="utf8")
|
||||||
|
+ "\n\n"
|
||||||
|
+ (CURRENT_DIR / "CHANGES.md").read_text(encoding="utf8")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
USE_MYPYC = False
|
||||||
|
# To compile with mypyc, a mypyc checkout must be present on the PYTHONPATH
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == "--use-mypyc":
|
||||||
|
sys.argv.pop(1)
|
||||||
|
USE_MYPYC = True
|
||||||
|
if os.getenv("BLACK_USE_MYPYC", None) == "1":
|
||||||
|
USE_MYPYC = True
|
||||||
|
|
||||||
|
if USE_MYPYC:
|
||||||
|
mypyc_targets = [
|
||||||
|
"src/black/__init__.py",
|
||||||
|
"src/blib2to3/pytree.py",
|
||||||
|
"src/blib2to3/pygram.py",
|
||||||
|
"src/blib2to3/pgen2/parse.py",
|
||||||
|
"src/blib2to3/pgen2/grammar.py",
|
||||||
|
"src/blib2to3/pgen2/token.py",
|
||||||
|
"src/blib2to3/pgen2/driver.py",
|
||||||
|
"src/blib2to3/pgen2/pgen.py",
|
||||||
|
]
|
||||||
|
|
||||||
|
from mypyc.build import mypycify
|
||||||
|
|
||||||
|
opt_level = os.getenv("MYPYC_OPT_LEVEL", "3")
|
||||||
|
ext_modules = mypycify(mypyc_targets, opt_level=opt_level)
|
||||||
|
else:
|
||||||
|
ext_modules = []
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="black",
|
||||||
|
use_scm_version={
|
||||||
|
"write_to": "src/_black_version.py",
|
||||||
|
"write_to_template": 'version = "{version}"\n',
|
||||||
|
},
|
||||||
|
description="The uncompromising code formatter.",
|
||||||
|
long_description=get_long_description(),
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
keywords="automation formatter yapf autopep8 pyfmt gofmt rustfmt",
|
||||||
|
author="Łukasz Langa",
|
||||||
|
author_email="lukasz@langa.pl",
|
||||||
|
url="https://github.com/psf/black",
|
||||||
|
project_urls={"Changelog": "https://github.com/psf/black/blob/main/CHANGES.md"},
|
||||||
|
license="MIT",
|
||||||
|
py_modules=["_black_version"],
|
||||||
|
ext_modules=ext_modules,
|
||||||
|
packages=find_packages(where="src"),
|
||||||
|
package_dir={"": "src"},
|
||||||
|
package_data={
|
||||||
|
"blib2to3": ["*.txt"],
|
||||||
|
"black": ["py.typed"],
|
||||||
|
"black_primer": ["primer.json"],
|
||||||
|
},
|
||||||
|
python_requires=">=3.6.2",
|
||||||
|
zip_safe=False,
|
||||||
|
install_requires=[
|
||||||
|
"click>=7.1.2",
|
||||||
|
"platformdirs>=2",
|
||||||
|
"tomli>=0.2.6,<2.0.0",
|
||||||
|
"typed-ast>=1.4.2; python_version < '3.8'",
|
||||||
|
"regex>=2020.1.8",
|
||||||
|
"pathspec>=0.9.0, <1",
|
||||||
|
"dataclasses>=0.6; python_version < '3.7'",
|
||||||
|
"typing_extensions>=3.10.0.0",
|
||||||
|
# 3.10.0.1 is broken on at least Python 3.10,
|
||||||
|
# https://github.com/python/typing/issues/865
|
||||||
|
"typing_extensions!=3.10.0.1; python_version >= '3.10'",
|
||||||
|
"mypy_extensions>=0.4.3",
|
||||||
|
],
|
||||||
|
extras_require={
|
||||||
|
"d": ["aiohttp>=3.6.0", "aiohttp-cors>=0.4.0"],
|
||||||
|
"colorama": ["colorama>=0.4.3"],
|
||||||
|
"python2": ["typed-ast>=1.4.2"],
|
||||||
|
"uvloop": ["uvloop>=0.15.2"],
|
||||||
|
"jupyter": ["ipython>=7.8.0", "tokenize-rt>=3.2.0"],
|
||||||
|
},
|
||||||
|
test_suite="tests.test_black",
|
||||||
|
classifiers=[
|
||||||
|
"Development Status :: 4 - Beta",
|
||||||
|
"Environment :: Console",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3.6",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: Software Development :: Quality Assurance",
|
||||||
|
],
|
||||||
|
entry_points={
|
||||||
|
"console_scripts": [
|
||||||
|
"black=black:patched_main",
|
||||||
|
"blackd=blackd:patched_main [d]",
|
||||||
|
"black-primer=black_primer.cli:main",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user