Compare commits
No commits in common. "main" and "21.6b0" 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]
|
||||
# B905 should be enabled when we drop support for 3.9
|
||||
ignore = E203, E266, E501, E701, E704, W503, B905, B907
|
||||
ignore = E203, E266, E501, W503
|
||||
# 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-complexity = 18
|
||||
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
|
65
.github/ISSUE_TEMPLATE/bug_report.md
vendored
65
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,66 +1,47 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Black's quality
|
||||
about: Create a report to help us improve
|
||||
title: ""
|
||||
labels: "T: bug"
|
||||
labels: bug
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
<!--
|
||||
Please make sure that the bug is not already fixed either in newer versions or the
|
||||
current development version. To confirm this, you have three options:
|
||||
|
||||
1. Update Black's version if a newer release exists: `pip install -U black`
|
||||
2. 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**
|
||||
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**To Reproduce**
|
||||
|
||||
<!--
|
||||
Minimal steps to reproduce the behavior with source code and Black's configuration.
|
||||
-->
|
||||
<!-- Steps to reproduce the behavior:
|
||||
|
||||
For example, take this code:
|
||||
|
||||
```python
|
||||
this = "code"
|
||||
```
|
||||
|
||||
And run it with these arguments:
|
||||
|
||||
```sh
|
||||
$ black file.py --target-version py39
|
||||
```
|
||||
|
||||
The resulting error is:
|
||||
|
||||
> cannot format file.py: INTERNAL ERROR: ...
|
||||
For example:
|
||||
1. Take this file '...'
|
||||
1. Run _Black_ on it with these arguments '...'
|
||||
1. See error -->
|
||||
|
||||
**Expected behavior**
|
||||
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Environment**
|
||||
**Environment (please complete the following information):**
|
||||
|
||||
<!-- Please complete the following information: -->
|
||||
|
||||
- Black's version: <!-- e.g. [main] -->
|
||||
- Version: <!-- e.g. [main] -->
|
||||
- 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**
|
||||
|
||||
<!-- Add any other context about the problem here. -->
|
||||
|
12
.github/ISSUE_TEMPLATE/config.yml
vendored
12
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,12 +0,0 @@
|
||||
# See also: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
|
||||
|
||||
# This is the default and blank issues are useful so let's keep 'em.
|
||||
blank_issues_enabled: true
|
||||
|
||||
contact_links:
|
||||
- name: Chat on Python Discord
|
||||
url: https://discord.gg/RtVdv86PrH
|
||||
about: |
|
||||
User support, questions, and other lightweight requests can be
|
||||
handled via the #black-formatter text channel we have on Python
|
||||
Discord.
|
27
.github/ISSUE_TEMPLATE/docs-issue.md
vendored
27
.github/ISSUE_TEMPLATE/docs-issue.md
vendored
@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Documentation
|
||||
about: Report a problem with or suggest something for the documentation
|
||||
title: ""
|
||||
labels: "T: documentation"
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
**Is this related to a problem? Please describe.**
|
||||
|
||||
<!-- A clear and concise description of what the problem is.
|
||||
e.g. I'm always frustrated when [...] / I wished that [...] -->
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
<!-- A clear and concise description of what you want to
|
||||
happen or see changed. -->
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
<!-- A clear and concise description of any
|
||||
alternative solutions or features you've considered. -->
|
||||
|
||||
**Additional context**
|
||||
|
||||
<!-- Add any other context or screenshots about the issue
|
||||
here. -->
|
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -2,7 +2,7 @@
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ""
|
||||
labels: "T: enhancement"
|
||||
labels: enhancement
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
|
6
.github/ISSUE_TEMPLATE/style_issue.md
vendored
6
.github/ISSUE_TEMPLATE/style_issue.md
vendored
@ -1,8 +1,8 @@
|
||||
---
|
||||
name: Code style issue
|
||||
about: Help us improve the Black code style
|
||||
name: Style issue
|
||||
about: Help us improve the Black style
|
||||
title: ""
|
||||
labels: "T: style"
|
||||
labels: design
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
|
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,36 +0,0 @@
|
||||
<!-- Hello! Thanks for submitting a PR. To help make things go a bit more
|
||||
smoothly we would appreciate that you go through this template. -->
|
||||
|
||||
### Description
|
||||
|
||||
<!-- Good things to put here include: reasoning for the change (please link
|
||||
any relevant issues!), any noteworthy (or hacky) choices to be aware of,
|
||||
or what the problem resolved here looked like ... we won't mind a ranty
|
||||
story :) -->
|
||||
|
||||
### Checklist - did you ...
|
||||
|
||||
<!-- If any of the following items aren't relevant for your contribution
|
||||
please still tick them so we know you've gone through the checklist.
|
||||
|
||||
All user-facing changes should get an entry. Otherwise, signal to us
|
||||
this should get the magical label to silence the CHANGELOG entry check.
|
||||
Tests are required for bugfixes and new features. Documentation changes
|
||||
are necessary for formatting and most enhancement changes. -->
|
||||
|
||||
- [ ] Add an entry in `CHANGES.md` if necessary?
|
||||
- [ ] Add / update tests if necessary?
|
||||
- [ ] Add new / update outdated documentation?
|
||||
|
||||
<!-- Just as a reminder, everyone in all psf/black spaces including PRs
|
||||
must follow the PSF Code of Conduct (link below).
|
||||
|
||||
Finally, once again thanks for your time and effort. If you have any
|
||||
feedback in regards to your experience contributing here, please
|
||||
let us know!
|
||||
|
||||
Helpful links:
|
||||
|
||||
PSF COC: https://www.python.org/psf/conduct/
|
||||
Contributing docs: https://black.readthedocs.io/en/latest/contributing/index.html
|
||||
Chat on Python Discord: https://discord.gg/RtVdv86PrH -->
|
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:
|
||||
types: [opened, synchronize, labeled, unlabeled, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Changelog Entry Check
|
||||
@ -14,11 +11,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Grep CHANGES.md for PR number
|
||||
if: contains(github.event.pull_request.labels.*.name, 'skip news') != true
|
||||
run: |
|
||||
grep -Pz "\((\n\s*)?#${{ github.event.pull_request.number }}(\n\s*)?\)" CHANGES.md || \
|
||||
(echo "Please add '(#${{ github.event.pull_request.number }})' change line to CHANGES.md (or if appropriate, ask a maintainer to add the 'skip news' label)" && \
|
||||
(echo "Please add '(#${{ github.event.pull_request.number }})' change line to CHANGES.md" && \
|
||||
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]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# 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 }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up latest Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.13"
|
||||
allow-prereleases: true
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install uv
|
||||
python -m uv venv
|
||||
python -m uv pip install -e ".[d]"
|
||||
python -m uv pip install -r "docs/requirements.txt"
|
||||
python -m pip install --upgrade pip setuptools wheel
|
||||
python -m pip install -e ".[d]"
|
||||
python -m pip install -r "docs/requirements.txt"
|
||||
|
||||
- name: Build documentation
|
||||
run: sphinx-build -a -b html -W --keep-going docs/ docs/_build
|
||||
|
37
.github/workflows/docker.yml
vendored
37
.github/workflows/docker.yml
vendored
@ -5,10 +5,7 @@ on:
|
||||
branches:
|
||||
- "main"
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
types: created
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
@ -16,16 +13,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@ -36,34 +33,12 @@ jobs:
|
||||
latest_non_release)" >> $GITHUB_ENV
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: pyfound/black:latest,pyfound/black:${{ env.GIT_TAG }}
|
||||
|
||||
- name: Build and push latest_release 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_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
|
||||
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]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# 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:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.9", "3.10", "3.11", "3.12.4", "3.13"]
|
||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
|
||||
- name: Install dependencies
|
||||
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]
|
||||
|
||||
@ -14,35 +14,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Assert PR target is main
|
||||
if: github.event_name == 'pull_request' && github.repository == 'psf/black'
|
||||
run: |
|
||||
if [ "$GITHUB_BASE_REF" != "main" ]; then
|
||||
echo "::error::PR targeting '$GITHUB_BASE_REF', please refile targeting 'main'." && exit 1
|
||||
fi
|
||||
|
||||
- name: Set up latest Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.13"
|
||||
allow-prereleases: true
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install -e '.'
|
||||
python -m pip install tox
|
||||
python -m pip install -e '.[d]'
|
||||
|
||||
- name: Run pre-commit hooks
|
||||
uses: pre-commit/action@v3.0.1
|
||||
|
||||
- name: Format ourselves
|
||||
run: |
|
||||
tox -e run_self
|
||||
|
||||
- name: Regenerate schema
|
||||
run: |
|
||||
tox -e generate_schema
|
||||
git diff --exit-code
|
||||
- name: Lint
|
||||
uses: pre-commit/action@v2.0.2
|
||||
|
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]
|
||||
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]"
|
||||
|
||||
- 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:
|
||||
release:
|
||||
types: [published]
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
types: created
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: sdist + pure wheel
|
||||
build:
|
||||
name: PyPI Upload
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up latest Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.13"
|
||||
allow-prereleases: true
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
|
||||
- name: Install latest pip, build, twine
|
||||
- name: Install latest pip, setuptools, twine + wheel
|
||||
run: |
|
||||
python -m pip install --upgrade --disable-pip-version-check pip
|
||||
python -m pip install --upgrade build twine
|
||||
python -m pip install --upgrade pip setuptools twine wheel
|
||||
|
||||
- name: Build wheel and source distributions
|
||||
run: python -m build
|
||||
- name: Build wheels
|
||||
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:
|
||||
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: |
|
||||
pipx install cibuildwheel==2.22.0
|
||||
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
|
||||
twine upload --verbose -u '__token__' dist/*
|
||||
|
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/**"
|
||||
- "*.md"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
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.
|
||||
@ -31,39 +24,35 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
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]
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
allow-prereleases: true
|
||||
|
||||
- name: Install tox
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install --upgrade tox
|
||||
|
||||
- name: Unit tests
|
||||
if: "!startsWith(matrix.python-version, 'pypy')"
|
||||
run:
|
||||
tox -e ci-py$(echo ${{ matrix.python-version }} | tr -d '.') -- -v --color=yes
|
||||
run: |
|
||||
tox -e ci-py -- -v --color=yes
|
||||
|
||||
- name: Unit tests (pypy)
|
||||
if: "startsWith(matrix.python-version, 'pypy')"
|
||||
run: tox -e ci-pypy3 -- -v --color=yes
|
||||
|
||||
- name: Upload coverage to Coveralls
|
||||
# Upload coverage if we are on the main repository and
|
||||
- name: Publish coverage to Coveralls
|
||||
# If pushed / is a pull request against main repo AND
|
||||
# we're running on Linux (this action only supports Linux)
|
||||
if:
|
||||
github.repository == 'psf/black' && matrix.os == 'ubuntu-latest' &&
|
||||
!startsWith(matrix.python-version, 'pypy')
|
||||
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
|
||||
((github.event_name == 'push' && github.repository == 'psf/black') ||
|
||||
github.event.pull_request.base.repo.full_name == 'psf/black') && matrix.os ==
|
||||
'ubuntu-latest'
|
||||
|
||||
uses: AndreMiras/coveralls-python-action@v20201129
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
parallel: true
|
||||
@ -71,40 +60,17 @@ jobs:
|
||||
debug: true
|
||||
|
||||
coveralls-finish:
|
||||
needs: main
|
||||
if: github.repository == 'psf/black'
|
||||
needs: build
|
||||
# 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
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Send finished signal to Coveralls
|
||||
uses: AndreMiras/coveralls-python-action@ac868b9540fad490f7ca82b8ca00480fd751ed19
|
||||
- uses: actions/checkout@v2
|
||||
- name: Coveralls finished
|
||||
uses: AndreMiras/coveralls-python-action@v20201129
|
||||
with:
|
||||
parallel-finished: true
|
||||
debug: true
|
||||
|
||||
uvloop:
|
||||
if:
|
||||
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
||||
github.repository
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
|
||||
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:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: write # actions/upload-release-asset needs this.
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-2019, ubuntu-22.04, macos-latest]
|
||||
os: [windows-2019, ubuntu-20.04, macos-latest]
|
||||
include:
|
||||
- os: windows-2019
|
||||
pathsep: ";"
|
||||
asset_name: black_windows.exe
|
||||
executable_mime: "application/vnd.microsoft.portable-executable"
|
||||
- os: ubuntu-22.04
|
||||
- os: ubuntu-20.04
|
||||
pathsep: ":"
|
||||
asset_name: black_linux
|
||||
executable_mime: "application/x-executable"
|
||||
@ -29,28 +26,22 @@ jobs:
|
||||
executable_mime: "application/x-mach-binary"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up latest Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.12.4"
|
||||
python-version: "*"
|
||||
|
||||
- name: Install Black and PyInstaller
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip wheel
|
||||
python -m pip install .[colorama]
|
||||
python -m pip install --upgrade pip wheel setuptools
|
||||
python -m pip install .
|
||||
python -m pip install pyinstaller
|
||||
|
||||
- name: Build executable with PyInstaller
|
||||
run: >
|
||||
python -m PyInstaller -F --name ${{ matrix.asset_name }} --add-data
|
||||
'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
|
||||
|
||||
- name: Quickly test executable
|
||||
- name: Build binary
|
||||
run: |
|
||||
./dist/${{ matrix.asset_name }} --version
|
||||
./dist/${{ matrix.asset_name }} src --verbose
|
||||
python -m PyInstaller -F --name ${{ matrix.asset_name }} --add-data 'src/blib2to3${{ matrix.pathsep }}blib2to3' src/black/__main__.py
|
||||
|
||||
- name: Upload binary as release asset
|
||||
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
|
12
.gitignore
vendored
12
.gitignore
vendored
@ -4,25 +4,17 @@
|
||||
_build
|
||||
.DS_Store
|
||||
.vscode
|
||||
.python-version
|
||||
docs/_static/pypi.svg
|
||||
.tox
|
||||
__pycache__
|
||||
|
||||
# Packaging artifacts
|
||||
black.egg-info
|
||||
black.dist-info
|
||||
build/
|
||||
dist/
|
||||
pip-wheel-metadata/
|
||||
.eggs
|
||||
|
||||
src/_black_version.py
|
||||
.idea
|
||||
|
||||
.eggs
|
||||
.dmypy.json
|
||||
*.swp
|
||||
.hypothesis/
|
||||
venv/
|
||||
.ipynb_checkpoints/
|
||||
node_modules/
|
||||
venv/
|
@ -1,83 +1,30 @@
|
||||
# Note: don't use this config for your own repositories. Instead, see
|
||||
# "Version control integration" in docs/integrations/source_version_control.md
|
||||
exclude: ^(profiling/|tests/data/)
|
||||
# "Version control integration" in README.md.
|
||||
exclude: ^(src/blib2to3/|profiling/|tests/data/)
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-pre-commit-rev-in-example
|
||||
name: Check pre-commit rev in example
|
||||
language: python
|
||||
entry: python -m scripts.check_pre_commit_rev_in_example
|
||||
files: '(CHANGES\.md|source_version_control\.md)$'
|
||||
additional_dependencies:
|
||||
&version_check_dependencies [
|
||||
commonmark==0.9.1,
|
||||
pyyaml==6.0.1,
|
||||
beautifulsoup4==4.9.3,
|
||||
]
|
||||
- id: black
|
||||
name: black
|
||||
language: system
|
||||
entry: black
|
||||
minimum_pre_commit_version: 2.9.2
|
||||
require_serial: true
|
||||
types_or: [python, pyi]
|
||||
|
||||
- id: check-version-in-the-basics-example
|
||||
name: Check black version in the basics example
|
||||
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
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.9.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies:
|
||||
- flake8-bugbear==24.2.6
|
||||
- flake8-comprehensions
|
||||
- flake8-simplify
|
||||
exclude: ^src/blib2to3/
|
||||
additional_dependencies: [flake8-bugbear]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.15.0
|
||||
rev: v0.812
|
||||
hooks:
|
||||
- id: mypy
|
||||
exclude: ^(docs/conf.py|scripts/generate_schema.py)$
|
||||
args: []
|
||||
additional_dependencies: &mypy_deps
|
||||
- types-PyYAML
|
||||
- types-atheris
|
||||
- tomli >= 0.2.6, < 2.0.0
|
||||
- click >= 8.2.0
|
||||
# Click is intentionally out-of-sync with pyproject.toml
|
||||
# v8.2 has breaking changes. We work around them at runtime, but we need the newer stubs.
|
||||
- packaging >= 22.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
|
||||
exclude: ^docs/conf.py
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: v3.5.3
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v2.2.1
|
||||
hooks:
|
||||
- id: prettier
|
||||
types_or: [markdown, yaml, json]
|
||||
exclude: \.github/workflows/diff_shades\.yml
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
|
||||
ci:
|
||||
autoupdate_schedule: quarterly
|
||||
|
@ -1,20 +1,9 @@
|
||||
# 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
|
||||
name: black
|
||||
description: "Black: The uncompromising Python code formatter"
|
||||
entry: black
|
||||
language: python
|
||||
language_version: python3
|
||||
minimum_pre_commit_version: 2.9.2
|
||||
require_serial: true
|
||||
types_or: [python, pyi]
|
||||
- id: black-jupyter
|
||||
name: black-jupyter
|
||||
description:
|
||||
"Black: The uncompromising Python code formatter (with Jupyter Notebook support)"
|
||||
entry: black
|
||||
language: python
|
||||
minimum_pre_commit_version: 2.9.2
|
||||
require_serial: true
|
||||
types_or: [python, pyi, jupyter]
|
||||
additional_dependencies: [".[jupyter]"]
|
||||
|
@ -3,12 +3,8 @@ version: 2
|
||||
formats:
|
||||
- htmlzip
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
python:
|
||||
version: 3.8
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
@ -16,6 +12,3 @@ python:
|
||||
path: .
|
||||
extra_requirements:
|
||||
- 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).
|
||||
|
||||
Maintained with:
|
||||
|
||||
- [Carol Willing](mailto:carolcode@willingconsulting.com)
|
||||
- [Carl Meyer](mailto:carl@oddbird.net)
|
||||
- [Jelle Zijlstra](mailto:jelle.zijlstra@gmail.com)
|
||||
- [Mika Naylor](mailto:mail@autophagy.io)
|
||||
- [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)
|
||||
Maintained with [Carol Willing](mailto:carolcode@willingconsulting.com),
|
||||
[Carl Meyer](mailto:carl@oddbird.net),
|
||||
[Jelle Zijlstra](mailto:jelle.zijlstra@gmail.com),
|
||||
[Mika Naylor](mailto:mail@autophagy.io),
|
||||
[Zsolt Dollenstein](mailto:zsol.zsol@gmail.com),
|
||||
[Cooper Lees](mailto:me@cooperlees.com), and Richard Si.
|
||||
|
||||
Multiple contributions by:
|
||||
|
||||
- [Abdur-Rahmaan Janhangeer](mailto:arj.python@gmail.com)
|
||||
- [Adam Johnson](mailto:me@adamj.eu)
|
||||
- [Adam Williamson](mailto:adamw@happyassassin.net)
|
||||
- [Alexander Huynh](mailto:ahrex-gh-psf-black@e.sc)
|
||||
- [Alexandr Artemyev](mailto:mogost@gmail.com)
|
||||
- [Alexander Huynh](mailto:github@grande.coffee)
|
||||
- [Alex Vandiver](mailto:github@chmrr.net)
|
||||
- [Allan Simon](mailto:allan.simon@supinfo.com)
|
||||
- Anders-Petter Ljungquist
|
||||
- [Amethyst Reese](mailto:amy@n7.gg)
|
||||
- [Andrew Thorp](mailto:andrew.thorp.dev@gmail.com)
|
||||
- [Andrew Zhou](mailto:andrewfzhou@gmail.com)
|
||||
- [Andrey](mailto:dyuuus@yandex.ru)
|
||||
- [Andy Freeland](mailto:andy@andyfreeland.net)
|
||||
- [Anthony Sottile](mailto:asottile@umich.edu)
|
||||
- [Antonio Ossa Guerra](mailto:aaossa+black@uc.cl)
|
||||
- [Arjaan Buijk](mailto:arjaan.buijk@gmail.com)
|
||||
- [Arnav Borbornah](mailto:arnavborborah11@gmail.com)
|
||||
- [Artem Malyshev](mailto:proofit404@gmail.com)
|
||||
@ -82,7 +73,6 @@ Multiple contributions by:
|
||||
- [Hugo Barrera](mailto::hugo@barrera.io)
|
||||
- Hugo van Kemenade
|
||||
- [Hynek Schlawack](mailto:hs@ox.cx)
|
||||
- [Ionite](mailto:dev@ionite.io)
|
||||
- [Ivan Katanić](mailto:ivan.katanic@gmail.com)
|
||||
- [Jakub Kadlubiec](mailto:jakub.kadlubiec@skyscanner.net)
|
||||
- [Jakub Warczarek](mailto:jakub.warczarek@gmail.com)
|
||||
@ -153,7 +143,6 @@ Multiple contributions by:
|
||||
- [Rishikesh Jha](mailto:rishijha424@gmail.com)
|
||||
- [Rupert Bedford](mailto:rupert@rupertb.com)
|
||||
- Russell Davis
|
||||
- [Sagi Shadur](mailto:saroad2@gmail.com)
|
||||
- [Rémi Verschelde](mailto:rverschelde@gmail.com)
|
||||
- [Sami Salonen](mailto:sakki@iki.fi)
|
||||
- [Samuel Cormier-Iijima](mailto:samuel@cormier-iijima.com)
|
||||
@ -181,7 +170,6 @@ Multiple contributions by:
|
||||
- [Tony Narlock](mailto:tony@git-pull.com)
|
||||
- [Tsuyoshi Hombashi](mailto:tsuyoshi.hombashi@gmail.com)
|
||||
- [Tushar Chandra](mailto:tusharchandra2018@u.northwestern.edu)
|
||||
- [Tushar Sadhwani](mailto:tushar.sadhwani000@gmail.com)
|
||||
- [Tzu-ping Chung](mailto:uranusjr@gmail.com)
|
||||
- [Utsav Shah](mailto:ukshah2@illinois.edu)
|
||||
- utsav-dbx
|
||||
|
1324
CHANGES.md
1324
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_
|
||||
|
||||
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
|
||||
specific, the [user documentation](https://black.readthedocs.io/en/latest/) is the best
|
||||
place to look.
|
||||
Our [contributing documentation](https://black.readthedocs.org/en/latest/contributing/)
|
||||
contains details on all you need to know about contributing to _Black_, the basics to
|
||||
the internals of _Black_.
|
||||
|
||||
For getting started on contributing, please read the
|
||||
[contributing documentation](https://black.readthedocs.org/en/latest/contributing/) for
|
||||
all you need to know.
|
||||
|
||||
Thank you, and we look forward to your contributions!
|
||||
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
|
||||
COPY . /src/
|
||||
ENV VIRTUAL_ENV=/opt/venv
|
||||
ENV HATCH_BUILD_HOOKS_ENABLE=1
|
||||
# Install build tools to compile black + dependencies
|
||||
RUN apt update && apt install -y build-essential git python3-dev
|
||||
RUN python -m venv $VIRTUAL_ENV
|
||||
RUN python -m pip install --no-cache-dir hatch hatch-fancy-pypi-readme hatch-vcs
|
||||
RUN . /opt/venv/bin/activate && pip install --no-cache-dir --upgrade pip setuptools \
|
||||
&& cd /src && hatch build -t wheel \
|
||||
&& pip install --no-cache-dir dist/*-cp* \
|
||||
&& pip install black[colorama,d,uvloop]
|
||||
RUN pip install --no-cache-dir --upgrade pip setuptools wheel \
|
||||
&& apt update && apt install -y git \
|
||||
&& cd /src \
|
||||
&& pip install --no-cache-dir .[colorama,d] \
|
||||
&& rm -rf /src \
|
||||
&& apt remove -y git \
|
||||
&& apt autoremove -y \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM python:3.12-slim
|
||||
|
||||
# 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"]
|
||||
CMD ["black"]
|
||||
|
36
Pipfile
Normal file
36
Pipfile
Normal file
@ -0,0 +1,36 @@
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.python.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
Sphinx = ">=3.1.2"
|
||||
coverage = "*"
|
||||
docutils = "==0.15" # not a direct dependency, see https://github.com/pypa/pipenv/issues/3865
|
||||
flake8 = "*"
|
||||
flake8-bugbear = "*"
|
||||
mypy = ">=0.812"
|
||||
pre-commit = "*"
|
||||
readme_renderer = "*"
|
||||
MyST-Parser = ">=0.13.7"
|
||||
sphinxcontrib-programoutput = ">=0.17"
|
||||
sphinx-copybutton = ">=0.3.0"
|
||||
setuptools = ">=39.2.0"
|
||||
setuptools-scm = "*"
|
||||
twine = ">=1.11.0"
|
||||
wheel = ">=0.31.1"
|
||||
black = {editable = true, extras = ["d"], path = "."}
|
||||
|
||||
[packages]
|
||||
aiohttp = ">=3.6.0"
|
||||
aiohttp-cors = ">=0.4.0"
|
||||
appdirs = "*"
|
||||
click = ">=7.1.2"
|
||||
mypy_extensions = ">=0.4.3"
|
||||
pathspec = ">=0.8.1"
|
||||
regex = ">=2020.1.8"
|
||||
toml = ">=0.10.1"
|
||||
typed-ast = "==1.4.2"
|
||||
typing_extensions = {"python_version <" = "3.8","version >=" = "3.7.4"}
|
||||
black = {editable = true,extras = ["d"],path = "."}
|
||||
dataclasses = {"python_version <" = "3.7","version >" = "0.6"}
|
1262
Pipfile.lock
generated
Normal file
1262
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>
|
||||
|
||||
<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/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://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://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://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
||||
</p>
|
||||
@ -38,12 +39,13 @@ Try it out now using the [Black Playground](https://black.vercel.app). Watch the
|
||||
|
||||
### Installation
|
||||
|
||||
_Black_ can be installed by running `pip install black`. It requires Python 3.9+ to run.
|
||||
If you want to format Jupyter Notebooks, install with `pip install "black[jupyter]"`.
|
||||
_Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
|
||||
run. If you want to format Python 2 code as well, install with
|
||||
`pip install black[python2]`.
|
||||
|
||||
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
|
||||
|
||||
@ -63,13 +65,16 @@ Further information can be found in our docs:
|
||||
|
||||
- [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
|
||||
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
|
||||
we have become stable, you should not expect large formatting changes in the future.
|
||||
Stylistic changes will mostly be responses to bug reports and support for new Python
|
||||
syntax. For more information please refer to
|
||||
[The Black Code Style](https://black.readthedocs.io/en/stable/the_black_code_style/index.html).
|
||||
projects, small and big. Black has a comprehensive test suite, with efficient parallel
|
||||
tests, and 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
|
||||
@ -81,20 +86,14 @@ section for details). If you're feeling confident, use `--fast`.
|
||||
|
||||
_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
|
||||
take previous formatting into account (see
|
||||
[Pragmatism](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#pragmatism)
|
||||
for exceptions).
|
||||
take previous formatting into account (see [Pragmatism](#pragmatism) for exceptions).
|
||||
|
||||
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: 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
|
||||
intended behaviour.
|
||||
|
||||
@ -132,13 +131,11 @@ code in compliance with many other _Black_ formatted projects.
|
||||
## Used by
|
||||
|
||||
The following notable open-source projects trust _Black_ with enforcing a consistent
|
||||
code style: pytest, tox, Pyramid, Django, Django Channels, Hypothesis, attrs,
|
||||
SQLAlchemy, Poetry, PyPA applications (Warehouse, Bandersnatch, Pipenv, virtualenv),
|
||||
pandas, Pillow, Twisted, LocalStack, every Datadog Agent Integration, Home Assistant,
|
||||
Zulip, Kedro, OpenOA, FLORIS, ORBIT, WOMBAT, and many more.
|
||||
code style: pytest, tox, Pyramid, Django Channels, Hypothesis, attrs, SQLAlchemy,
|
||||
Poetry, PyPA applications (Warehouse, Bandersnatch, Pipenv, virtualenv), pandas, Pillow,
|
||||
every Datadog Agent Integration, Home Assistant, Zulip.
|
||||
|
||||
The following organizations use _Black_: Dropbox, KeepTruckin, Lyft, Mozilla, Quora,
|
||||
Duolingo, QuantumBlack, Tesla, Archer Aviation.
|
||||
The following organizations use _Black_: Facebook, Dropbox, Mozilla, Quora.
|
||||
|
||||
Are we missing anyone? Let us know.
|
||||
|
||||
@ -165,8 +162,8 @@ Twisted and CPython:
|
||||
|
||||
> At least the name is good.
|
||||
|
||||
**Kenneth Reitz**, creator of [`requests`](https://requests.readthedocs.io/en/latest/)
|
||||
and [`pipenv`](https://readthedocs.org/projects/pipenv/):
|
||||
**Kenneth Reitz**, creator of [`requests`](http://python-requests.org/) and
|
||||
[`pipenv`](https://readthedocs.org/projects/pipenv/):
|
||||
|
||||
> This vastly improves the formatting of our code. Thanks a ton!
|
||||
|
||||
@ -203,7 +200,7 @@ You can also take a look at the rest of the contributing docs or talk with the
|
||||
developers:
|
||||
|
||||
- [Contributing documentation](https://black.readthedocs.io/en/latest/contributing/index.html)
|
||||
- [Chat on Discord](https://discord.gg/RtVdv86PrH)
|
||||
- [IRC channel on Freenode](https://webchat.freenode.net/?channels=%23blackformatter)
|
||||
|
||||
## Change log
|
||||
|
||||
|
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:
|
||||
description:
|
||||
"Options passed to Black. Use `black --help` to see available options. Default:
|
||||
'--check --diff'"
|
||||
'--check'"
|
||||
required: false
|
||||
default: "--check --diff"
|
||||
src:
|
||||
description: "Source to run Black. Default: '.'"
|
||||
required: false
|
||||
default: "."
|
||||
jupyter:
|
||||
description:
|
||||
"Set this option to true to include Jupyter Notebook files. Default: false"
|
||||
required: false
|
||||
default: false
|
||||
black_args:
|
||||
description: "[DEPRECATED] Black input arguments."
|
||||
required: false
|
||||
@ -27,53 +22,38 @@ inputs:
|
||||
description: 'Python Version specifier (PEP440) - e.g. "21.5b1"'
|
||||
required: false
|
||||
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:
|
||||
color: "black"
|
||||
icon: "check-circle"
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: black
|
||||
run: |
|
||||
# Even when black fails, do not close the shell
|
||||
set +e
|
||||
- run: |
|
||||
# Exists since using github.action_path + path to main script doesn't work because bash
|
||||
# interprets the backslashes in github.action_path (which are used when the runner OS
|
||||
# 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
|
||||
runner="python"
|
||||
echo $entrypoint | python
|
||||
else
|
||||
runner="python3"
|
||||
echo $entrypoint | python3
|
||||
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:
|
||||
# TODO: Remove once https://github.com/actions/runner/issues/665 is fixed.
|
||||
INPUT_OPTIONS: ${{ inputs.options }}
|
||||
INPUT_SRC: ${{ inputs.src }}
|
||||
INPUT_JUPYTER: ${{ inputs.jupyter }}
|
||||
INPUT_BLACK_ARGS: ${{ inputs.black_args }}
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
INPUT_USE_PYPROJECT: ${{ inputs.use_pyproject }}
|
||||
pythonioencoding: utf-8
|
||||
shell: bash
|
||||
|
159
action/main.py
159
action/main.py
@ -1,182 +1,39 @@
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from subprocess import PIPE, STDOUT, run
|
||||
from typing import Union
|
||||
from subprocess import run, PIPE, STDOUT
|
||||
|
||||
ACTION_PATH = Path(os.environ["GITHUB_ACTION_PATH"])
|
||||
ENV_PATH = ACTION_PATH / ".black-env"
|
||||
ENV_BIN = ENV_PATH / ("Scripts" if sys.platform == "win32" else "bin")
|
||||
OPTIONS = os.getenv("INPUT_OPTIONS", default="")
|
||||
SRC = os.getenv("INPUT_SRC", default="")
|
||||
JUPYTER = os.getenv("INPUT_JUPYTER") == "true"
|
||||
BLACK_ARGS = os.getenv("INPUT_BLACK_ARGS", 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)
|
||||
|
||||
version_specifier = determine_version_specifier()
|
||||
if JUPYTER:
|
||||
extra_deps = "[colorama,jupyter]"
|
||||
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)
|
||||
req = "black[colorama,python2]"
|
||||
if VERSION:
|
||||
req += f"=={VERSION}"
|
||||
pip_proc = run(
|
||||
[str(ENV_BIN / "python"), "-m", "pip", "install", req],
|
||||
stdout=PIPE,
|
||||
stderr=STDOUT,
|
||||
encoding="utf-8",
|
||||
cwd=ACTION_PATH,
|
||||
)
|
||||
if pip_proc.returncode:
|
||||
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)
|
||||
|
||||
|
||||
base_cmd = [str(ENV_BIN / "black")]
|
||||
if BLACK_ARGS:
|
||||
# TODO: remove after a while since this is deprecated in favour of SRC + OPTIONS.
|
||||
proc = run(
|
||||
[*base_cmd, *shlex.split(BLACK_ARGS)],
|
||||
stdout=PIPE,
|
||||
stderr=STDOUT,
|
||||
encoding="utf-8",
|
||||
)
|
||||
proc = run([*base_cmd, *shlex.split(BLACK_ARGS)])
|
||||
else:
|
||||
proc = run(
|
||||
[*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)
|
||||
proc = run([*base_cmd, *shlex.split(OPTIONS), *shlex.split(SRC)])
|
||||
|
||||
sys.exit(proc.returncode)
|
||||
|
@ -3,13 +3,8 @@ import collections
|
||||
import os
|
||||
import sys
|
||||
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")):
|
||||
@property
|
||||
@ -27,14 +22,12 @@ class Flag(collections.namedtuple("FlagBase", "name, cast")):
|
||||
FLAGS = [
|
||||
Flag(name="line_length", cast=int),
|
||||
Flag(name="fast", cast=strtobool),
|
||||
Flag(name="skip_string_normalization", cast=strtobool),
|
||||
Flag(name="string_normalization", 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:
|
||||
default = vim.eval("g:pymode_python").strip()
|
||||
except vim.error:
|
||||
@ -43,15 +36,7 @@ def _get_python_binary(exec_prefix, pyver):
|
||||
return default
|
||||
if sys.platform[:3] == "win":
|
||||
return exec_prefix / 'python.exe'
|
||||
bin_path = exec_prefix / "bin"
|
||||
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")
|
||||
return exec_prefix / 'bin' / 'python3'
|
||||
|
||||
def _get_pip(venv_path):
|
||||
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'
|
||||
|
||||
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]
|
||||
if pyver < (3, 9):
|
||||
print("Sorry, Black requires Python 3.9+ to run.")
|
||||
if pyver < (3, 6, 2):
|
||||
print("Sorry, Black requires Python 3.6.2+ to run.")
|
||||
return False
|
||||
|
||||
from pathlib import Path
|
||||
@ -90,7 +65,7 @@ def _initialize_black_env(upgrade=False):
|
||||
_executable = sys.executable
|
||||
_base_executable = getattr(sys, "_base_executable", _executable)
|
||||
try:
|
||||
executable = str(_get_python_binary(Path(sys.exec_prefix), pyver))
|
||||
executable = str(_get_python_binary(Path(sys.exec_prefix)))
|
||||
sys.executable = executable
|
||||
sys._base_executable = executable
|
||||
print(f'Creating a virtualenv in {virtualenv_path}...')
|
||||
@ -123,49 +98,13 @@ if _initialize_black_env():
|
||||
import black
|
||||
import time
|
||||
|
||||
def get_target_version(tv):
|
||||
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.
|
||||
"""
|
||||
def Black():
|
||||
start = time.time()
|
||||
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(
|
||||
line_length=configs["line_length"],
|
||||
string_normalization=not configs["skip_string_normalization"],
|
||||
string_normalization=configs["string_normalization"],
|
||||
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"]
|
||||
|
||||
@ -178,9 +117,9 @@ def Black(**kwargs):
|
||||
)
|
||||
except black.NothingChanged:
|
||||
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:
|
||||
print(f'Black: {exc}')
|
||||
print(exc)
|
||||
else:
|
||||
current_buffer = vim.current.window.buffer
|
||||
cursors = []
|
||||
@ -197,18 +136,17 @@ def Black(**kwargs):
|
||||
except vim.error:
|
||||
window.cursor = (len(window.buffer), 0)
|
||||
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():
|
||||
filename = vim.eval("@%")
|
||||
path_pyproject_toml = black.find_pyproject_toml((filename,))
|
||||
path_pyproject_toml = black.find_pyproject_toml(vim.eval("fnamemodify(getcwd(), ':t')"))
|
||||
if path_pyproject_toml:
|
||||
toml_config = black.parse_pyproject_toml(path_pyproject_toml)
|
||||
else:
|
||||
toml_config = {}
|
||||
|
||||
return {
|
||||
flag.var_name: toml_config.get(flag.name, flag.cast(vim.eval(flag.vim_rc_name)))
|
||||
flag.var_name: flag.cast(toml_config.get(flag.name, vim.eval(flag.vim_rc_name)))
|
||||
for flag in FLAGS
|
||||
}
|
||||
|
||||
@ -221,17 +159,8 @@ def BlackVersion():
|
||||
|
||||
EndPython3
|
||||
|
||||
function black#Black(...)
|
||||
let kwargs = {}
|
||||
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)
|
||||
function black#Black()
|
||||
:py3 Black()
|
||||
endfunction
|
||||
|
||||
function black#BlackUpgrade()
|
||||
|
@ -17,4 +17,4 @@ help:
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
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;
|
||||
}
|
2
docs/_static/license.svg
vendored
2
docs/_static/license.svg
vendored
@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="78" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="78" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h47v20H0z"/><path fill="#7900CA" d="M47 0h31v20H47z"/><path fill="url(#b)" d="M0 0h78v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><text x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">license</text><text x="245" y="140" transform="scale(.1)" textLength="370">license</text><text x="615" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">MIT</text><text x="615" y="140" transform="scale(.1)" textLength="210">MIT</text></g> </svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="78" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="78" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h47v20H0z"/><path fill="#7900CA" d="M47 0h31v20H47z"/><path fill="url(#b)" d="M0 0h78v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><text x="245" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">license</text><text x="245" y="140" transform="scale(.1)" textLength="370">license</text><text x="615" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">MIT</text><text x="615" y="140" transform="scale(.1)" textLength="210">MIT</text></g> </svg>
|
Before Width: | Height: | Size: 950 B After Width: | Height: | Size: 949 B |
@ -1,3 +1,3 @@
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = E203,E701
|
||||
extend-ignore = E203
|
||||
|
@ -1,3 +1,3 @@
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = E203,E701
|
||||
extend-ignore = E203
|
||||
|
@ -1,3 +1,3 @@
|
||||
[flake8]
|
||||
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]
|
||||
max-line-length = 88
|
||||
|
@ -1,2 +1,5 @@
|
||||
[tool.pylint.messages_control]
|
||||
disable = "C0330, C0326"
|
||||
|
||||
[tool.pylint.format]
|
||||
max-line-length = "88"
|
||||
|
@ -1,2 +1,5 @@
|
||||
[pylint]
|
||||
max-line-length = 88
|
||||
|
||||
[pylint.messages_control]
|
||||
disable = C0330, C0326
|
||||
|
108
docs/conf.py
108
docs/conf.py
@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
@ -13,12 +14,10 @@
|
||||
#
|
||||
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
from importlib.metadata import version
|
||||
from pathlib import Path
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from pkg_resources import get_distribution
|
||||
|
||||
CURRENT_DIR = Path(__file__).parent
|
||||
|
||||
@ -26,33 +25,12 @@
|
||||
def make_pypi_svg(version: str) -> None:
|
||||
template: Path = CURRENT_DIR / "_static" / "pypi_template.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)
|
||||
with open(str(target), "w", encoding="utf8") as f:
|
||||
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
|
||||
# sphinxcontrib-programoutput on Windows.
|
||||
os.putenv("pythonioencoding", "utf-8")
|
||||
@ -65,7 +43,7 @@ def setup(app: Sphinx) -> None:
|
||||
|
||||
# Autopopulate version
|
||||
# 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.
|
||||
version = release
|
||||
for sp in "abcfr":
|
||||
@ -77,7 +55,7 @@ def setup(app: Sphinx) -> None:
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# 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
|
||||
# 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.
|
||||
# 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
|
||||
# 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
|
||||
# unsupported yet still enabled by default ones.
|
||||
myst_disable_syntax = [
|
||||
"colon_fence",
|
||||
"myst_block_break",
|
||||
"myst_line_comment",
|
||||
"math_block",
|
||||
]
|
||||
|
||||
# Optional MyST Syntaxes
|
||||
myst_enable_extensions = []
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "furo"
|
||||
html_logo = "_static/logo2-readme.png"
|
||||
html_theme = "alabaster"
|
||||
|
||||
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,
|
||||
# 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
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [(
|
||||
master_doc,
|
||||
"black.tex",
|
||||
"Documentation for Black",
|
||||
"Łukasz Langa and contributors to Black",
|
||||
"manual",
|
||||
)]
|
||||
latex_documents = [
|
||||
(
|
||||
master_doc,
|
||||
"black.tex",
|
||||
"Documentation for Black",
|
||||
"Łukasz Langa and contributors to Black",
|
||||
"manual",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
@ -192,15 +189,17 @@ def setup(app: Sphinx) -> None:
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [(
|
||||
master_doc,
|
||||
"Black",
|
||||
"Documentation for Black",
|
||||
author,
|
||||
"Black",
|
||||
"The uncompromising Python code formatter",
|
||||
"Miscellaneous",
|
||||
)]
|
||||
texinfo_documents = [
|
||||
(
|
||||
master_doc,
|
||||
"Black",
|
||||
"Documentation for Black",
|
||||
author,
|
||||
"Black",
|
||||
"The uncompromising Python code formatter",
|
||||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
@ -228,14 +227,7 @@ def setup(app: Sphinx) -> None:
|
||||
|
||||
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 ---------------------------------------
|
||||
|
||||
# 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
|
||||
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
|
||||
the results. The main highlight feature of diff-shades is being able to compare two
|
||||
revisions of _Black_. This is incredibly useful as it allows us to see what exact
|
||||
changes will occur, say merging a certain PR.
|
||||
`black-primer` is a tool built for CI (and humans) to have _Black_ `--check` a number of
|
||||
Git accessible projects in parallel. (configured in `primer.json`) _(A PR will be
|
||||
accepted to add Mercurial support.)_
|
||||
|
||||
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 ..." /
|
||||
"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:
|
||||
### Speed up runs 🏎
|
||||
|
||||
| | Baseline revision | Target revision |
|
||||
| --------------------- | ----------------------- | ---------------------------- |
|
||||
| On PRs | latest commit on `main` | PR commit with `main` merged |
|
||||
| On pushes (main only) | latest PyPI version | the pushed commit |
|
||||
If you're running locally yourself to test black on lots of code try:
|
||||
|
||||
For pushes to main, there's only one analysis job named `preview-changes` where the
|
||||
preview style is used for all projects.
|
||||
- Using `-k` / `--keep` + `-w` / `--work-dir` so you don't have to re-checkout the repo
|
||||
each run
|
||||
|
||||
For PRs they get one more analysis job: `assert-no-changes`. It's similar to
|
||||
`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.
|
||||
### CLI arguments
|
||||
|
||||
Additionally for PRs, a PR comment will be posted embedding a summary of the preview
|
||||
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.
|
||||
```{program-output} black-primer --help
|
||||
|
||||
```{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`.
|
42
docs/contributing/index.rst
Normal file
42
docs/contributing/index.rst
Normal file
@ -0,0 +1,42 @@
|
||||
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*. This is
|
||||
deliberate.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
can be eventually be resolved somehow. This document outlines the triaging process and
|
||||
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_
|
||||
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
|
||||
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
|
||||
4. **discussion** - initial triage has been done and now the general details on how the
|
||||
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
|
||||
- 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:
|
||||
|
||||
1. _the issue is waiting for triage_
|
||||
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
|
||||
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
|
||||
PR would be welcomed (`S: accepted`)
|
||||
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
|
||||
|
||||
_Black_ has had a lot of work done into standardizing and automating its release
|
||||
process. This document sets out to explain how everything works and how to release
|
||||
_Black_ using said automation.
|
||||
_Black_ has had a lot of work automating its release process. This document sets out to
|
||||
explain what everything does and how to release _Black_ using said automation.
|
||||
|
||||
## Release cadence
|
||||
## Cutting a Release
|
||||
|
||||
**We aim to release whatever is on `main` every 1-2 months.** This ensures merged
|
||||
improvements and bugfixes are shipped to users reasonably quickly, while not massively
|
||||
fracturing the user-base with too many versions. This also keeps the workload on
|
||||
maintainers consistent and predictable.
|
||||
To cut a release, you must be a _Black_ maintainer with `GitHub Release` creation
|
||||
access. Using this access, the release process is:
|
||||
|
||||
If there's not much new on `main` to justify a release, it's acceptable to skip a
|
||||
month's release. Ideally January releases should not be skipped because as per our
|
||||
[stability policy](labels/stability-policy), the first release in a new calendar year
|
||||
may make changes to the _stable_ style. While the policy applies to the first release
|
||||
(instead of only January releases), confining changes to the stable style to January
|
||||
will keep things predictable (and nicer) for users.
|
||||
1. Cut a new PR editing `CHANGES.md` to version the latest changes
|
||||
1. Example PR: https://github.com/psf/black/pull/2192
|
||||
2. Example title: `Update CHANGES.md for XX.X release`
|
||||
2. Once the release PR is merged ensure all CI passes
|
||||
1. If not, ensure there is an Issue open for the cause of failing CI (generally we'd
|
||||
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
|
||||
should not be more than one release per month**. While version numbers are cheap,
|
||||
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.
|
||||
```
|
||||
If anything fails, please go read the respective action's log output and configuration
|
||||
file to reverse engineer your way to a fix/soluton.
|
||||
|
||||
## Release workflows
|
||||
|
||||
All of _Black_'s release automation uses [GitHub Actions]. All workflows are therefore
|
||||
configured using YAML files in the `.github/workflows` directory of the _Black_
|
||||
All _Blacks_'s automation workflows use GitHub Actions. All workflows are therefore
|
||||
configured using `.yml` files in the `.github/workflows` directory of the _Black_
|
||||
repository.
|
||||
|
||||
They are triggered by the publication of a [GitHub Release].
|
||||
|
||||
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
|
||||
vast majority of users will download Black from. It's divided into three job groups:
|
||||
This workflow uses the QEMU powered `buildx` feature of docker to upload a `arm64` and
|
||||
`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
|
||||
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.
|
||||
### pypi_upload
|
||||
|
||||
#### 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
|
||||
performance. Wheels built with mypyc are platform and Python version specific.
|
||||
[Supported platforms are documented in the FAQ](labels/mypyc-support).
|
||||
It will then use [twine](https://pypi.org/project/twine/) to upload both release formats
|
||||
to PyPI for general downloading of the _Black_ Python package. This is where
|
||||
[pip](https://pypi.org/project/pip/) looks by default.
|
||||
|
||||
These matrix jobs use [cibuildwheel] which handles the complicated task of building C
|
||||
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).
|
||||
- Currently this workflow uses an API token associated with @ambv's PyPI account
|
||||
|
||||
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
|
||||
other PyPI jobs pass (they must pass for this job to start) makes the most sense. This
|
||||
saves us from remembering to update the branch sometime after cutting the release.
|
||||
The created binaries are attached/stored on the associated
|
||||
[GitHub Release](https://github.com/psf/black/releases) for download over _IPv4 only_
|
||||
(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
|
||||
allows people to download the executable for their platform and run _Black_ without a
|
||||
[Python runtime](https://wiki.python.org/moin/PythonImplementations) installed.
|
||||
### Tag moving process
|
||||
|
||||
The created binaries are stored on the associated GitHub Release for download over _IPv4
|
||||
only_ (GitHub still does not have IPv6 access 😢).
|
||||
#### stable
|
||||
|
||||
### docker
|
||||
From a rebased `main` checkout:
|
||||
|
||||
This workflow uses the QEMU powered `buildx` feature of Docker to upload an `arm64` and
|
||||
`amd64`/`x86_64` build of the official _Black_ Docker image™.
|
||||
|
||||
- _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
|
||||
1. `git tag -f stable VERSION_TAG`
|
||||
1. e.g. `git tag -f stable 21.5b1`
|
||||
1. `git push --tags -f`
|
||||
|
@ -4,27 +4,26 @@ An overview on contributing to the _Black_ project.
|
||||
|
||||
## Technicalities
|
||||
|
||||
Development on the latest version of Python is preferred. You can use any operating
|
||||
system.
|
||||
Development on the latest version of Python is preferred. As of this writing it's 3.9.
|
||||
You can use any operating system.
|
||||
|
||||
First clone the _Black_ repository:
|
||||
Install all development dependencies using:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/psf/black.git
|
||||
$ cd black
|
||||
$ pipenv install --dev
|
||||
$ pipenv shell
|
||||
$ pre-commit install
|
||||
```
|
||||
|
||||
Then install development dependencies inside a virtual environment of your choice, for
|
||||
example:
|
||||
If you haven't used `pipenv` before but are comfortable with virtualenvs, just run
|
||||
`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
|
||||
$ python3 -m venv .venv
|
||||
$ source .venv/bin/activate # activation for linux and mac
|
||||
$ .venv\Scripts\activate # activation for windows
|
||||
|
||||
(.venv)$ pip install -r test_requirements.txt
|
||||
(.venv)$ pip install -e ".[d]"
|
||||
(.venv)$ pre-commit install
|
||||
$ pip install -r test_requirements.txt
|
||||
$ pip install -e .[d]
|
||||
```
|
||||
|
||||
Before submitting pull requests, run lints and tests with the following commands from
|
||||
@ -32,125 +31,69 @@ the root of the black repo:
|
||||
|
||||
```console
|
||||
# Linting
|
||||
(.venv)$ pre-commit run -a
|
||||
$ pre-commit run -a
|
||||
|
||||
# Unit tests
|
||||
(.venv)$ tox -e py
|
||||
$ tox -e py
|
||||
|
||||
# Optional Fuzz testing
|
||||
(.venv)$ tox -e fuzz
|
||||
$ tox -e fuzz
|
||||
|
||||
# Format Black itself
|
||||
(.venv)$ tox -e run_self
|
||||
# Optional CI run to test your changes on many popular python projects
|
||||
$ 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
|
||||
|
||||
`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
|
||||
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
|
||||
- `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
|
||||
<a href="https://ichard26.github.io/next-pr-number/?owner=psf&name=black">Next PR
|
||||
Number</a>. This is not perfect but saves a lot of release overhead as now the releaser
|
||||
does not need to go back and workout what to add to the `CHANGES.md` for each release.
|
||||
[Next PR Number](https://ichard26.github.io/next-pr-number/?owner=psf&name=black). This
|
||||
is not perfect but saves a lot of release overhead as now the releaser does not need to
|
||||
go back and workout what to add to the `CHANGES.md` for each release.
|
||||
|
||||
### Style Changes
|
||||
|
||||
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
|
||||
formatting don't need to be mentioned separately though. If the change is implemented
|
||||
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.
|
||||
formatting don't need to be mentioned separately though.
|
||||
|
||||
### Docs Testing
|
||||
|
||||
If you make changes to docs, you can test they still build locally too.
|
||||
|
||||
```console
|
||||
(.venv)$ pip install -r docs/requirements.txt
|
||||
(.venv)$ pip install -e ".[d]"
|
||||
(.venv)$ sphinx-build -a -b html -W docs/ docs/_build/
|
||||
$ pip install -r docs/requirements.txt
|
||||
$ pip install [-e] .[d]
|
||||
$ 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
|
||||
|
||||
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
|
||||
feature, please first open an issue to discuss it beforehand.
|
||||
If adding a new feature, add a test. In fact, always add a test. But wait, before adding
|
||||
any large feature, first open an issue for us to discuss the idea first.
|
||||
|
||||
## Finally
|
||||
|
||||
|
116
docs/faq.md
116
docs/faq.md
@ -5,32 +5,20 @@ The most common questions and issues users face are aggregated to this FAQ.
|
||||
```{contents}
|
||||
:local:
|
||||
: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?
|
||||
|
||||
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)
|
||||
though.
|
||||
|
||||
## Is Black safe to use?
|
||||
|
||||
Yes. _Black_ is strictly about formatting, nothing else. Black strives to ensure that
|
||||
after formatting the AST is
|
||||
Yes, for the most part. _Black_ is strictly about formatting, nothing else. But because
|
||||
_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
|
||||
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
|
||||
@ -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?
|
||||
|
||||
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.
|
||||
|
||||
Starting in 2022, the formatting output is stable for the releases made in the same year
|
||||
(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.
|
||||
Quite stable. _Black_ aims to enforce one style and one style only, with some room for
|
||||
pragmatism. However, _Black_ is still in beta so style changes are both planned and
|
||||
still proposed on the issue tracker. See
|
||||
[The Black Code Style](the_black_code_style/index.rst) for more details.
|
||||
|
||||
## Why is my file not formatted?
|
||||
|
||||
@ -52,51 +37,20 @@ Most likely because it is ignored in `.gitignore` or excluded with configuration
|
||||
[file collection and discovery](usage_and_configuration/file_collection_and_discovery.md)
|
||||
for details.
|
||||
|
||||
## Why is my Jupyter Notebook cell not formatted?
|
||||
## Why are Flake8's E203 and W503 violated?
|
||||
|
||||
_Black_ is timid about formatting Jupyter Notebooks. Cells containing any of the
|
||||
following will not be formatted:
|
||||
Because they go against PEP 8. E203 falsely triggers on list
|
||||
[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).
|
||||
|
||||
- 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.:
|
||||
## Does Black support Python 2?
|
||||
|
||||
```python
|
||||
%timeit f(1, \
|
||||
2, \
|
||||
3)
|
||||
```
|
||||
|
||||
- code which `IPython`'s `TransformerManager` would transform magics into, e.g.:
|
||||
|
||||
```python
|
||||
get_ipython().system('ls')
|
||||
```
|
||||
|
||||
- invalid syntax, as it can't be safely distinguished from automagics in the absence of
|
||||
a running `IPython` kernel.
|
||||
|
||||
## Why does Flake8 report warnings?
|
||||
|
||||
Some of Flake8's rules conflict with Black's style. We recommend disabling these rules.
|
||||
See [Using _Black_ with other tools](labels/why-pycodestyle-warnings).
|
||||
|
||||
## Which Python versions does Black support?
|
||||
|
||||
_Black_ generally supports all Python versions supported by CPython (see
|
||||
[the Python devguide](https://devguide.python.org/versions/) for current information).
|
||||
We promise to support at least all Python versions that have not reached their end of
|
||||
life. This is the case for both running _Black_ and formatting code.
|
||||
|
||||
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.
|
||||
For formatting, yes! [Install](getting_started.md#installation) with the `python2` extra
|
||||
to format Python 2 files too! There are no current plans to drop support, but most
|
||||
likely it is bound to happen. Sometime. Eventually. In terms of running _Black_ though,
|
||||
Python 3.6 or newer is required.
|
||||
|
||||
## Why does my linter or typechecker complain after I format my code?
|
||||
|
||||
@ -105,35 +59,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
|
||||
sometimes have to manually move these comments to the right place after you format your
|
||||
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,13 @@ Also, you can try out _Black_ online for minimal fuss on the
|
||||
|
||||
## Installation
|
||||
|
||||
_Black_ can be installed by running `pip install black`. It requires Python 3.9+ to run.
|
||||
If you want to format Jupyter Notebooks, install with `pip install "black[jupyter]"`.
|
||||
|
||||
If you use pipx, you can install Black with `pipx install black`.
|
||||
_Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
|
||||
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 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
|
||||
|
||||
|
@ -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
|
||||
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
|
||||
project directory.
|
||||
identifier(s) into a file.
|
||||
|
||||
```text
|
||||
# Migrate code style to Black
|
||||
@ -44,9 +43,8 @@ call to `git blame`.
|
||||
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
```
|
||||
|
||||
**The one caveat is that some online Git-repositories like GitLab do not yet support
|
||||
ignoring revisions using their native blame UI.** So blame information will be cluttered
|
||||
with a reformatting commit on those platforms. (If you'd like this feature, there's an
|
||||
open issue for [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/31423)).
|
||||
[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)
|
||||
by default in blame views however.
|
||||
**The one caveat is that GitHub and GitLab do not yet support ignoring revisions using
|
||||
their native UI of blame.** So blame information will be cluttered with a reformatting
|
||||
commit on those platforms. (If you'd like this feature, there's an open issue for
|
||||
[GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/31423) and please let GitHub
|
||||
know!)
|
||||
|
@ -24,10 +24,10 @@ to conflicting changes.
|
||||
#### Profile
|
||||
|
||||
Since version 5.0.0, isort supports
|
||||
[profiles](https://pycqa.github.io/isort/docs/configuration/profiles.html) to allow easy
|
||||
[profiles](https://pycqa.github.io/isort/docs/configuration/profiles/) to allow easy
|
||||
interoperability with common code styles. You can set the black profile in any of the
|
||||
[config files](https://pycqa.github.io/isort/docs/configuration/config_files.html)
|
||||
supported by isort. Below, an example for `pyproject.toml`:
|
||||
[config files](https://pycqa.github.io/isort/docs/configuration/config_files/) supported
|
||||
by isort. Below, an example for `pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[tool.isort]
|
||||
@ -51,9 +51,9 @@ line_length = 88
|
||||
|
||||
#### Why those options above?
|
||||
|
||||
_Black_ wraps imports that surpass `line-length` by moving identifiers onto separate
|
||||
lines and by adding a trailing comma after each. A more detailed explanation of this
|
||||
behaviour can be
|
||||
_Black_ wraps imports that surpass `line-length` by moving identifiers into their own
|
||||
indented line. If that still doesn't fit the bill, it will put all of them in separate
|
||||
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).
|
||||
|
||||
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>
|
||||
<summary>.isort.cfg</summary>
|
||||
|
||||
```ini
|
||||
```cfg
|
||||
[settings]
|
||||
profile = black
|
||||
```
|
||||
@ -107,7 +107,7 @@ profile = black
|
||||
<details>
|
||||
<summary>setup.cfg</summary>
|
||||
|
||||
```ini
|
||||
```cfg
|
||||
[isort]
|
||||
profile = black
|
||||
```
|
||||
@ -134,10 +134,10 @@ profile = black
|
||||
|
||||
</details>
|
||||
|
||||
### pycodestyle
|
||||
### Flake8
|
||||
|
||||
[pycodestyle](https://pycodestyle.pycqa.org/) is a code linter. It warns you of syntax
|
||||
errors, possible bugs, stylistic errors, etc. For the most part, pycodestyle follows
|
||||
[Flake8](https://pypi.org/p/flake8/) is a code linter. It warns you of syntax errors,
|
||||
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.
|
||||
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
|
||||
ignore = E203,E701
|
||||
extend-ignore = E203
|
||||
```
|
||||
|
||||
(labels/why-pycodestyle-warnings)=
|
||||
|
||||
#### 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
|
||||
whitespace around slice operators. Due to this, pycodestyle will raise
|
||||
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, it
|
||||
should be disabled.
|
||||
|
||||
##### `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`
|
||||
whitespace around slice operators. Due to this, Flake8 will raise
|
||||
`E203 whitespace before ':'` warnings. Since this warning is not PEP 8 compliant, Flake8
|
||||
should be configured to ignore it via `extend-ignore = E203`.
|
||||
|
||||
When breaking a line, _Black_ will break it before a binary operator. This is compliant
|
||||
with PEP 8 as of
|
||||
[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
|
||||
recommendation called `W503 line break before binary operator`. It should not be enabled
|
||||
in your configuration. You can use its counterpart
|
||||
`W504 line break after binary operator` instead.
|
||||
in your configuration.
|
||||
|
||||
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
|
||||
|
||||
<details>
|
||||
<summary>setup.cfg, .pycodestyle, tox.ini</summary>
|
||||
<summary>.flake8</summary>
|
||||
|
||||
```ini
|
||||
[pycodestyle]
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
ignore = E203,E701
|
||||
extend-ignore = E203
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Flake8
|
||||
<details>
|
||||
<summary>setup.cfg</summary>
|
||||
|
||||
[Flake8](https://pypi.org/p/flake8/) is a wrapper around multiple linters, including
|
||||
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:
|
||||
|
||||
```
|
||||
```cfg
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = E203,E701
|
||||
extend-ignore = E203
|
||||
```
|
||||
|
||||
#### Why those options above?
|
||||
|
||||
See [the pycodestyle section](labels/why-pycodestyle-warnings) above.
|
||||
|
||||
#### Formats
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>.flake8, setup.cfg, tox.ini</summary>
|
||||
<summary>tox.ini</summary>
|
||||
|
||||
```ini
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = E203,E701
|
||||
extend-ignore = E203
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Pylint
|
||||
|
||||
[Pylint](https://pypi.org/p/pylint/) is also a code linter like Flake8. It has many of
|
||||
the same checks as Flake8 and more. It particularly has more formatting checks regarding
|
||||
style conventions like variable naming.
|
||||
[Pylint](https://pypi.org/p/pylint/) is also a code linter like Flake8. It has the same
|
||||
checks as flake8 and more. In particular, it has more formatting checks regarding style
|
||||
conventions like variable naming. With so many checks, Pylint is bound to have some
|
||||
mixed feelings about _Black_'s formatting style.
|
||||
|
||||
#### Configuration
|
||||
|
||||
```
|
||||
disable = C0330, C0326
|
||||
max-line-length = 88
|
||||
```
|
||||
|
||||
#### Why those options above?
|
||||
|
||||
Pylint should be configured to only complain about lines that surpass `88` characters
|
||||
via `max-line-length = 88`.
|
||||
When _Black_ is folding very long expressions, the closing brackets will
|
||||
[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
|
||||
_Black_ formatting and have since been removed.
|
||||
```py3
|
||||
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
|
||||
|
||||
@ -275,6 +242,9 @@ _Black_ formatting and have since been removed.
|
||||
<summary>pylintrc</summary>
|
||||
|
||||
```ini
|
||||
[MESSAGES CONTROL]
|
||||
disable = C0330, C0326
|
||||
|
||||
[format]
|
||||
max-line-length = 88
|
||||
```
|
||||
@ -287,6 +257,9 @@ max-line-length = 88
|
||||
```cfg
|
||||
[pylint]
|
||||
max-line-length = 88
|
||||
|
||||
[pylint.messages_control]
|
||||
disable = C0330, C0326
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -295,6 +268,9 @@ max-line-length = 88
|
||||
<summary>pyproject.toml</summary>
|
||||
|
||||
```toml
|
||||
[tool.pylint.messages_control]
|
||||
disable = "C0330, C0326"
|
||||
|
||||
[tool.pylint.format]
|
||||
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>
|
||||
IRC ↪ <https://webchat.freenode.net/?channels=%23blackformatter>
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
@ -10,67 +10,6 @@ Options include the following:
|
||||
|
||||
## 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`.
|
||||
|
||||
```console
|
||||
@ -118,7 +57,29 @@ There are several different ways you can use _Black_ from PyCharm:
|
||||
- Alternatively, you can set a keyboard shortcut by navigating to
|
||||
`Preferences or Settings -> Keymap -> External Tools -> External Tools - Black`.
|
||||
|
||||
### As file watcher
|
||||
1. Optionally, run _Black_ on every file save:
|
||||
|
||||
1. Make sure you have the
|
||||
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin
|
||||
installed.
|
||||
1. Go to `Preferences or Settings -> Tools -> File Watchers` and click `+` to add a
|
||||
new watcher:
|
||||
- Name: Black
|
||||
- File type: Python
|
||||
- Scope: Project Files
|
||||
- Program: \<install_location_from_step_2>
|
||||
- Arguments: `$FilePath$`
|
||||
- Output paths to refresh: `$FilePath$`
|
||||
- Working directory: `$ProjectFileDir$`
|
||||
|
||||
- In Advanced Options
|
||||
- Uncheck "Auto-save edited files to trigger the watcher"
|
||||
- Uncheck "Trigger the watcher on external changes"
|
||||
|
||||
## Wing IDE
|
||||
|
||||
Wing supports black via the OS Commands tool, as explained in the Wing documentation on
|
||||
[pep8 formatting](https://wingware.com/doc/edit/pep8). The detailed procedure is:
|
||||
|
||||
1. Install `black`.
|
||||
|
||||
@ -126,89 +87,27 @@ There are several different ways you can use _Black_ from PyCharm:
|
||||
$ pip install black
|
||||
```
|
||||
|
||||
1. Locate your `black` installation folder.
|
||||
|
||||
On macOS / Linux / BSD:
|
||||
1. Make sure it runs from the command line, e.g.
|
||||
|
||||
```console
|
||||
$ which black
|
||||
/usr/local/bin/black # possible location
|
||||
$ black --help
|
||||
```
|
||||
|
||||
On Windows:
|
||||
1. In Wing IDE, activate the **OS Commands** panel and define the command **black** to
|
||||
execute black on the currently selected file:
|
||||
|
||||
```console
|
||||
$ where black
|
||||
%LocalAppData%\Programs\Python\Python36-32\Scripts\black.exe # possible location
|
||||
```
|
||||
- Use the Tools -> OS Commands menu selection
|
||||
- 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
|
||||
|
||||
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
|
||||
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin
|
||||
installed.
|
||||
1. Go to `Preferences or Settings -> Tools -> File Watchers` and click `+` to add a new
|
||||
watcher:
|
||||
- Name: Black
|
||||
- File type: Python
|
||||
- Scope: Project Files
|
||||
- Program: \<install_location_from_step_2>
|
||||
- Arguments: `$FilePath$`
|
||||
- Output paths to refresh: `$FilePath$`
|
||||
- Working directory: `$ProjectFileDir$`
|
||||
|
||||
- In Advanced Options
|
||||
- Uncheck "Auto-save edited files to trigger the watcher"
|
||||
- Uncheck "Trigger the watcher on external changes"
|
||||
|
||||
## Wing IDE
|
||||
|
||||
Wing IDE supports `black` via **Preference Settings** for system wide settings and
|
||||
**Project Properties** for per-project or workspace specific settings, as explained in
|
||||
the Wing documentation on
|
||||
[Auto-Reformatting](https://wingware.com/doc/edit/auto-reformatting). The detailed
|
||||
procedure is:
|
||||
|
||||
### Prerequistes
|
||||
|
||||
- Wing IDE version 8.0+
|
||||
|
||||
- Install `black`.
|
||||
|
||||
```console
|
||||
$ pip install black
|
||||
```
|
||||
|
||||
- Make sure it runs from the command line, e.g.
|
||||
|
||||
```console
|
||||
$ black --help
|
||||
```
|
||||
|
||||
### Preference Settings
|
||||
|
||||
If you want Wing IDE to always reformat with `black` for every project, follow these
|
||||
steps:
|
||||
|
||||
1. In menubar navigate to `Edit -> Preferences -> Editor -> Reformatting`.
|
||||
|
||||
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`.
|
||||
1. Select a file in the editor and press **F1** , or whatever key binding you selected
|
||||
in step 3, to reformat the file.
|
||||
|
||||
## Vim
|
||||
|
||||
@ -217,61 +116,23 @@ global setting, follow these steps:
|
||||
Commands and shortcuts:
|
||||
|
||||
- `: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;
|
||||
- `:BlackVersion` to get the current version of _Black_ in use.
|
||||
- `:BlackVersion` to get the current version of _Black_ inside the virtualenv.
|
||||
|
||||
Configuration:
|
||||
|
||||
- `g:black_fast` (defaults to `0`)
|
||||
- `g:black_linelength` (defaults to `88`)
|
||||
- `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_use_virtualenv` (defaults to `1`)
|
||||
- `g:black_target_version` (defaults to `""`)
|
||||
- `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):
|
||||
|
||||
_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' }
|
||||
```
|
||||
|
||||
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):
|
||||
|
||||
```
|
||||
@ -285,14 +146,6 @@ $ cd ~/.vim/bundle/black
|
||||
$ 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
|
||||
[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).
|
||||
@ -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
|
||||
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
|
||||
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
|
||||
`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,
|
||||
then add this to your vimrc:
|
||||
To run _Black_ on save, add the following line to `.vimrc` or `init.vim`:
|
||||
|
||||
```
|
||||
let g:black_use_virtualenv = 0
|
||||
```
|
||||
|
||||
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
|
||||
autocmd BufWritePre *.py execute ':Black'
|
||||
```
|
||||
|
||||
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>
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
1. Install [`ale`](https://github.com/dense-analysis/ale)
|
||||
@ -389,27 +283,24 @@ close and reopen your File, _Black_ will be done with its job.
|
||||
|
||||
## Visual Studio Code
|
||||
|
||||
- Use the
|
||||
[Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
|
||||
([instructions](https://code.visualstudio.com/docs/python/formatting)).
|
||||
Use the
|
||||
[Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)
|
||||
([instructions](https://code.visualstudio.com/docs/python/editing#_formatting)).
|
||||
|
||||
- Alternatively the pre-release
|
||||
[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 3
|
||||
|
||||
## SublimeText
|
||||
Use [sublack plugin](https://github.com/jgirardet/sublack).
|
||||
|
||||
For SublimeText 3, use [sublack plugin](https://github.com/jgirardet/sublack). For
|
||||
higher versions, it is recommended to use [LSP](#python-lsp-server) as documented below.
|
||||
## Jupyter Notebook Magic
|
||||
|
||||
## Python LSP Server
|
||||
Use [blackcellmagic](https://github.com/csurfer/blackcellmagic).
|
||||
|
||||
## Python Language Server
|
||||
|
||||
If your editor supports the [Language Server Protocol](https://langserver.org/) (Atom,
|
||||
Sublime Text, Visual Studio Code and many more), you can use the
|
||||
[Python LSP Server](https://github.com/python-lsp/python-lsp-server) with the
|
||||
[python-lsp-black](https://github.com/python-lsp/python-lsp-black) plugin.
|
||||
[Python Language Server](https://github.com/palantir/python-language-server) with the
|
||||
[pyls-black](https://github.com/rupert/pyls-black) plugin.
|
||||
|
||||
## Atom/Nuclide
|
||||
|
||||
@ -432,4 +323,4 @@ hook global WinSetOption filetype=python %{
|
||||
|
||||
## 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).
|
||||
|
@ -3,13 +3,13 @@
|
||||
You can use _Black_ within a GitHub Actions workflow without setting your own Python
|
||||
environment. Great for enforcing that your code matches the _Black_ code style.
|
||||
|
||||
## Compatibility
|
||||
## Compatiblity
|
||||
|
||||
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).
|
||||
|
||||
Finally, this action installs _Black_ with the `colorama` extra so the `--color` flag
|
||||
should work fine.
|
||||
Finally, this action installs _Black_ with both the `colorama` and `python2` extras so
|
||||
the `--color` flag and formatting Python 2 code are supported.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -24,7 +24,7 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- 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_
|
||||
the action will use.
|
||||
|
||||
The version of _Black_ the action will use can be configured via `version` or read from
|
||||
the `pyproject.toml` file. `version` can be any
|
||||
[valid version specifier](https://packaging.python.org/en/latest/glossary/#term-Version-Specifier)
|
||||
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`).
|
||||
The version of _Black_ the action will use can be configured via `version`. The action
|
||||
defaults to the latest release available on PyPI. Only versions available from PyPI are
|
||||
supported, so no commit SHAs or branch names.
|
||||
|
||||
You can also configure the arguments passed to _Black_ via `options` (defaults to
|
||||
`'--check --diff'`) and `src` (default is `'.'`). Please note that the
|
||||
[`--check` flag](labels/exit-code) is required so that the workflow fails if _Black_
|
||||
finds files that need to be formatted.
|
||||
`'--check --diff'`) and `src` (default is `'.'`)
|
||||
|
||||
Here's an example configuration:
|
||||
|
||||
@ -58,33 +46,5 @@ Here's an example configuration:
|
||||
with:
|
||||
options: "--check --verbose"
|
||||
src: "./src"
|
||||
jupyter: true
|
||||
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,9 @@ Use [pre-commit](https://pre-commit.com/). Once you
|
||||
|
||||
```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
|
||||
- repo: https://github.com/psf/black
|
||||
rev: stable # Replace by any tag/version: https://github.com/psf/black/tags
|
||||
hooks:
|
||||
- id: black
|
||||
# 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
|
||||
language_version: python3 # Should be a command that runs python3.6+
|
||||
```
|
||||
|
||||
Feel free to switch out the `rev` value to a different version of Black.
|
||||
|
||||
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
|
||||
expect][pre-commit-mutable-rev].
|
||||
|
||||
## Jupyter Notebooks
|
||||
|
||||
There is an alternate hook `black-jupyter` that expands the targets of `black` to
|
||||
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.
|
||||
```
|
||||
|
||||
[pre-commit-mutable-rev]:
|
||||
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.
|
||||
|
||||
myst-parser==4.0.1
|
||||
Sphinx==8.2.3
|
||||
# Older versions break Sphinx even though they're declared to be supported.
|
||||
docutils==0.21.2
|
||||
sphinxcontrib-programoutput==0.18
|
||||
sphinx_copybutton==0.5.2
|
||||
furo==2024.8.6
|
||||
MyST-Parser==0.14.0
|
||||
Sphinx==3.5.4
|
||||
sphinxcontrib-programoutput==0.17
|
||||
sphinx_copybutton==0.3.1
|
||||
|
@ -2,21 +2,20 @@
|
||||
|
||||
## Code style
|
||||
|
||||
_Black_ aims for consistency, generality, readability and reducing git diffs. Similar
|
||||
language constructs are formatted with similar rules. Style configuration options are
|
||||
deliberately limited and rarely added. Previous formatting is taken into account as
|
||||
little as possible, with rare exceptions like the magic trailing comma. The coding style
|
||||
used by _Black_ can be viewed as a strict subset of PEP 8.
|
||||
|
||||
This document describes the current formatting style. If you're interested in trying out
|
||||
where the style is heading, see [future style](./future_style.md) and try running
|
||||
`black --preview`.
|
||||
_Black_ reformats entire files in place. Style configuration options are deliberately
|
||||
limited and rarely added. It doesn't take previous formatting into account, except for
|
||||
the magic trailing comma and preserving newlines. It doesn't reformat blocks that start
|
||||
with `# fmt: off` and end with `# fmt: on`, or lines that ends with `# fmt: skip`.
|
||||
`# 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
|
||||
courtesy for straddling code.
|
||||
|
||||
### How _Black_ wraps lines
|
||||
|
||||
_Black_ ignores previous formatting and applies uniform horizontal and vertical
|
||||
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
|
||||
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)=
|
||||
|
||||
_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
|
||||
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
|
||||
|
||||
@ -143,7 +140,7 @@ significantly shorter files than sticking with 80 (the most popular), or even 79
|
||||
by the standard library). In general,
|
||||
[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
|
||||
breaking other rules. In those rare cases, auto-formatted code will exceed your allotted
|
||||
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
|
||||
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
|
||||
linter compatibility.
|
||||
```ini
|
||||
[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
|
||||
|
||||
@ -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
|
||||
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
|
||||
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
|
||||
@ -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
|
||||
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 (`#: comment`), section comments with long runs of hashes, and Spyder cells.
|
||||
Non-breaking spaces after hashes are also preserved. Comments may sometimes be moved
|
||||
because of formatting changes, which can break tools that assign special meaning to
|
||||
them. See [AST before and after formatting](#ast-before-and-after-formatting) for more
|
||||
discussion.
|
||||
comments that require specific spacing rules are respected: doc comments (`#: comment`),
|
||||
section comments with long runs of hashes, and Spyder cells. Non-breaking spaces after
|
||||
hashes are also preserved. Comments may sometimes be moved because of formatting
|
||||
changes, which can break tools that assign special meaning to them. See
|
||||
[AST before and after formatting](#ast-before-and-after-formatting) for more discussion.
|
||||
|
||||
### 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
|
||||
[Pragmatism](#pragmatism) section below.
|
||||
|
||||
(labels/strings)=
|
||||
|
||||
### Strings
|
||||
|
||||
_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
|
||||
escapes than before.
|
||||
|
||||
_Black_ also standardizes string prefixes. Prefix characters are made lowercase with the
|
||||
exception of [capital "R" prefixes](#rstrings-and-rstrings), unicode literal markers
|
||||
(`u`) are removed because they are meaningless in Python 3, and in the case of multiple
|
||||
characters "r" is put first as in spoken language: "raw f-string".
|
||||
|
||||
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}"`.
|
||||
_Black_ also standardizes string prefixes, making them always lowercase. On top of that,
|
||||
if your code is already Python 3.6+ only or it's using the `unicode_literals` future
|
||||
import, _Black_ will remove `u` from the string prefix as it is meaningless in those
|
||||
scenarios.
|
||||
|
||||
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
|
||||
@ -277,18 +260,29 @@ 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
|
||||
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
|
||||
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
|
||||
end of the docstring are removed. All leading tabs are converted to spaces, but tabs
|
||||
inside text are preserved. Whitespace leading and trailing one-line docstrings is
|
||||
removed.
|
||||
removed. The quotations of an empty docstring are separated with one space.
|
||||
|
||||
### Numeric literals
|
||||
|
||||
_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
|
||||
`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
|
||||
|
||||
@ -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)
|
||||
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
|
||||
|
||||
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`
|
||||
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`;
|
||||
- for arguments with a default, use `...` instead of the actual default;
|
||||
- avoid using string literals in type annotations, stub files support forward references
|
||||
natively (like Python 3.7 code with `from __future__ import annotations`);
|
||||
- use variable annotations instead of type comments, even for stubs that target older
|
||||
versions of Python.
|
||||
|
||||
### Line endings
|
||||
|
||||
_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.
|
||||
versions of Python;
|
||||
- for arguments that default to `None`, use `Optional[]` explicitly;
|
||||
- use `float` instead of `Union[int, float]`.
|
||||
|
||||
## 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
|
||||
what those exceptions are and why this is the case.
|
||||
|
||||
(labels/magic-trailing-comma)=
|
||||
|
||||
### The magic trailing comma
|
||||
|
||||
_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
|
||||
the latter are treated as true raw strings with no special semantics.
|
||||
|
||||
(labels/ast-changes)=
|
||||
|
||||
### AST before and after formatting
|
||||
|
||||
When run with `--safe` (the default), _Black_ checks that the code before and after is
|
||||
semantically equivalent. This check is done by comparing the AST of the source with the
|
||||
AST of the target. There are three limited cases in which the AST does differ:
|
||||
When run with `--safe`, _Black_ checks that the code before and after is semantically
|
||||
equivalent. This check is done by comparing the AST of the source with the AST of the
|
||||
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
|
||||
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
|
||||
difference, due to the various possibilities of forming docstrings, all real-world
|
||||
uses of docstrings that we're aware of sanitize indentation and leading/trailing
|
||||
difference, due to the various possibilities of forming docstrings, all realtime use
|
||||
of docstrings that we're aware of sanitizes indentation and leading/trailing
|
||||
whitespace anyway.
|
||||
|
||||
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
|
||||
|
||||
## Preview style
|
||||
|
||||
(labels/preview-style)=
|
||||
|
||||
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),
|
||||
}
|
||||
```{warning}
|
||||
Changes to this document often aren't tied and don't relate to releases of
|
||||
_Black_. It's recommended that you read the latest version available.
|
||||
```
|
||||
|
||||
will be changed to:
|
||||
## Using backslashes for with statements
|
||||
|
||||
```python
|
||||
my_dict = {
|
||||
"a key in my dict": (
|
||||
a_very_long_variable * and_a_very_long_function_call() / 100000.0
|
||||
),
|
||||
"another key": short_value,
|
||||
}
|
||||
[Backslashes are bad and should be never be used](labels/why-no-backslashes) however
|
||||
there is one exception: `with` statements using multiple context managers. Before Python
|
||||
3.9 Python's grammar does not allow organizing parentheses around the series of context
|
||||
managers.
|
||||
|
||||
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
|
||||
|
||||
For better readability and less verticality, _Black_ now pairs parentheses ("(", ")")
|
||||
with braces ("{", "}") and square brackets ("[", "]") on the same line. For example:
|
||||
|
||||
```python
|
||||
foo(
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
)
|
||||
|
||||
nested_array = [
|
||||
[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
]
|
||||
```py3
|
||||
with \
|
||||
make_context_manager(1) as cm1, \
|
||||
make_context_manager(2) as cm2, \
|
||||
make_context_manager(3) as cm3, \
|
||||
make_context_manager(4) as cm4 \
|
||||
:
|
||||
... # backslashes and an ugly stranded colon
|
||||
```
|
||||
|
||||
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
|
||||
foo([
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
])
|
||||
## Improved string processing
|
||||
|
||||
nested_array = [[
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]]
|
||||
```
|
||||
|
||||
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
|
||||
)
|
||||
```
|
||||
Currently, _Black_ does not split long strings to fit the line length limit. Currently,
|
||||
there is [an experimental option](labels/experimental-string) to enable splitting
|
||||
strings. We plan to enable this option by default once it is fully stable. This is
|
||||
tracked in [this issue](https://github.com/psf/black/issues/2188).
|
||||
|
@ -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_
|
||||
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
|
||||
|
||||
`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
|
||||
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:
|
||||
|
||||
- `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`
|
||||
command line flag. If present and its value is not the empty string, no string
|
||||
normalization will be performed.
|
||||
- `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.
|
||||
- `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
|
||||
`--fast` command line flag.
|
||||
- `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,
|
||||
as .pyi, and whether string normalization was omitted.
|
||||
|
||||
To override the location of these files on all systems, set the environment variable
|
||||
`BLACK_CACHE_DIR` to the preferred location. Alternatively on macOS and Linux, set
|
||||
To override the location of these files on macOS or Linux, set the environment variable
|
||||
`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`.
|
||||
_Black_ will then write the above files to `.cache/black`. Note that `BLACK_CACHE_DIR`
|
||||
will take precedence over `XDG_CACHE_HOME` if both are set.
|
||||
in the directory you're running _Black_ from, set `XDG_CACHE_HOME=.cache`. _Black_ will
|
||||
then write the above files to `.cache/black/<version>/`.
|
||||
|
||||
## .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:
|
||||
|
||||
- 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
|
||||
filename;
|
||||
- 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
|
||||
|
||||
_Black_ will reformat entire files in place. To get started right away with sensible
|
||||
defaults:
|
||||
To get started right away with sensible defaults:
|
||||
|
||||
```sh
|
||||
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}
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
The CLI options of _Black_ can be displayed by running `black --help`. All options are
|
||||
also covered in more detail below.
|
||||
_Black_ has quite a few knobs these days, although _Black_ is opinionated so style
|
||||
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
|
||||
are deliberately limited and rarely added.
|
||||
<details>
|
||||
|
||||
Note that all command-line options listed above can also be configured using a
|
||||
`pyproject.toml` file (more on that below).
|
||||
<summary>Help output</summary>
|
||||
|
||||
#### `-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
|
||||
$ black --code "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`
|
||||
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:
|
||||
Passing `--check` will make _Black_ exit with:
|
||||
|
||||
- code 0 if nothing would change;
|
||||
- code 1 if some files would be reformatted; or
|
||||
- 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
|
||||
$ black test.py --check
|
||||
All done! ✨ 🍰 ✨
|
||||
@ -208,17 +106,17 @@ $ echo $?
|
||||
123
|
||||
```
|
||||
|
||||
#### `--diff`
|
||||
#### Diffs
|
||||
|
||||
Don't write the files back, just output a diff to indicate what changes _Black_ would've
|
||||
made. They are printed to stdout so capturing them is simple.
|
||||
Passing `--diff` will make _Black_ print out diffs that indicate what changes _Black_
|
||||
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
|
||||
$ black test.py --diff
|
||||
--- test.py 2021-03-08 22:23:40.848954+00:00
|
||||
+++ test.py 2021-03-08 22:23:47.126319+00:00
|
||||
--- test.py 2021-03-08 22:23:40.848954 +0000
|
||||
+++ test.py 2021-03-08 22:23:47.126319 +0000
|
||||
@@ -1 +1 @@
|
||||
-print ( 'hello, world' )
|
||||
+print("hello, world")
|
||||
@ -227,198 +125,6 @@ All done! ✨ 🍰 ✨
|
||||
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
|
||||
|
||||
_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.
|
||||
```
|
||||
|
||||
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.5b0
|
||||
```
|
||||
|
||||
An option to require a specific version to be running is also provided.
|
||||
|
||||
```console
|
||||
$ black --required-version 21.5b2 -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
|
||||
|
||||
@ -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
|
||||
configuration file to store build system requirements for Python projects. With the help
|
||||
of tools like [Poetry](https://python-poetry.org/),
|
||||
[Flit](https://flit.readthedocs.io/en/latest/), or
|
||||
[Hatch](https://hatch.pypa.io/latest/) it can fully replace the need for `setup.py` and
|
||||
`setup.cfg` files.
|
||||
of tools like [Poetry](https://python-poetry.org/) or
|
||||
[Flit](https://flit.readthedocs.io/en/latest/) it can fully replace the need for
|
||||
`setup.py` and `setup.cfg` files.
|
||||
|
||||
### Where _Black_ looks for the file
|
||||
|
||||
By default _Black_ looks for `pyproject.toml` containing a `[tool.black]` section
|
||||
starting from the common base directory of all files and directories passed on the
|
||||
command line. If it's not there, it looks in parent directories. It stops looking when
|
||||
it finds the file, or a `.git` directory, or a `.hg` directory, or the root of the file
|
||||
system, whichever comes first.
|
||||
By default _Black_ looks for `pyproject.toml` starting from the common base directory of
|
||||
all files and directories passed on the command line. If it's not there, it looks in
|
||||
parent directories. It stops looking when it finds the file, or a `.git` directory, or a
|
||||
`.hg` directory, or the root of the file system, whichever comes first.
|
||||
|
||||
If you're formatting standard input, _Black_ will look for configuration starting from
|
||||
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)
|
||||
|
||||
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.,
|
||||
`black`/`.black` is the file to create and add your configuration options to, in the
|
||||
`~/.config/` directory). Here, `~` refers to the path to your home directory. On
|
||||
Windows, this will be something like `C:\\Users\UserName`.
|
||||
as `pyproject.toml`), not directories where you store the configuration. Here, `~`
|
||||
refers to the path to your home directory. On Windows, this will be something like
|
||||
`C:\\Users\UserName`.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
@ -509,14 +259,10 @@ expressions by Black. Use `[ ]` to denote a significant space character.
|
||||
line-length = 88
|
||||
target-version = ['py37']
|
||||
include = '\.pyi?$'
|
||||
# 'extend-exclude' excludes files or directories in addition to the defaults
|
||||
extend-exclude = '''
|
||||
# A regex preceded with ^/ will apply only to files and directories
|
||||
# in the root of the project.
|
||||
(
|
||||
^/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
|
||||
)
|
||||
^/foo.py # exclude a file named foo.py in the root of the project (in addition to the defaults)
|
||||
'''
|
||||
```
|
||||
|
||||
@ -534,6 +280,9 @@ file hierarchy.
|
||||
|
||||
## 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
|
||||
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).
|
||||
|
@ -5,11 +5,13 @@
|
||||
a coverage-guided fuzzer I'm working on.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
import hypothesmith
|
||||
from hypothesis import HealthCheck, given, settings
|
||||
from hypothesis import strategies as st
|
||||
from hypothesis import HealthCheck, given, settings, strategies as st
|
||||
|
||||
import black
|
||||
from blib2to3.pgen2.tokenize import TokenError
|
||||
|
||||
|
||||
# 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
|
||||
derandomize=True, # deterministic mode to avoid CI flakiness
|
||||
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(
|
||||
# Note that while Hypothesmith might generate code unlike that written by
|
||||
@ -30,9 +32,7 @@
|
||||
black.FileMode,
|
||||
line_length=st.just(88) | st.integers(0, 200),
|
||||
string_normalization=st.booleans(),
|
||||
preview=st.booleans(),
|
||||
is_pyi=st.booleans(),
|
||||
magic_trailing_comma=st.booleans(),
|
||||
),
|
||||
)
|
||||
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
|
||||
|
||||
# Then format the code...
|
||||
dst_contents = black.format_str(src_contents, mode=mode)
|
||||
try:
|
||||
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.
|
||||
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`)
|
||||
try:
|
||||
import sys
|
||||
|
||||
import atheris
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
test = test_idempotent_any_syntatically_valid_python
|
||||
atheris.Setup(
|
||||
sys.argv,
|
||||
test.hypothesis.fuzz_one_input, # type: ignore[attr-defined]
|
||||
)
|
||||
atheris.Setup(sys.argv, test.hypothesis.fuzz_one_input)
|
||||
atheris.Fuzz()
|
@ -7,20 +7,29 @@
|
||||
import venv
|
||||
import zipfile
|
||||
from argparse import ArgumentParser, Namespace
|
||||
from collections.abc import Generator
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from functools import lru_cache, partial
|
||||
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
|
||||
|
||||
PYPI_INSTANCE = "https://pypi.org/pypi"
|
||||
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"
|
||||
|
||||
ArchiveKind = Union[tarfile.TarFile, zipfile.ZipFile]
|
||||
Days = Union[Literal[30], Literal[365]]
|
||||
|
||||
subprocess.run = partial(subprocess.run, check=True) # type: ignore
|
||||
# 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"])
|
||||
|
||||
|
||||
def get_top_packages() -> list[str]:
|
||||
with urlopen(PYPI_TOP_PACKAGES) as page:
|
||||
def get_top_packages(days: Days) -> List[str]:
|
||||
with urlopen(PYPI_TOP_PACKAGES.format(days=days)) as page:
|
||||
result = json.load(page)
|
||||
|
||||
return [package["project"] for package in result["rows"]]
|
||||
@ -119,12 +128,13 @@ def get_package(
|
||||
|
||||
def download_and_extract_top_packages(
|
||||
directory: Path,
|
||||
days: Days = 365,
|
||||
workers: int = 8,
|
||||
limit: slice = DEFAULT_SLICE,
|
||||
) -> Generator[Path, None, None]:
|
||||
with ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
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:
|
||||
yield package
|
||||
|
||||
@ -151,7 +161,7 @@ def git_switch_branch(
|
||||
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)
|
||||
|
||||
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(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_repo / "black.py").resolve(),
|
||||
".",
|
||||
@ -223,7 +233,7 @@ def format_repo_with_version(
|
||||
return current_branch
|
||||
|
||||
|
||||
def format_repos(repos: tuple[Path, ...], options: Namespace) -> None:
|
||||
def format_repos(repos: Tuple[Path, ...], options: Namespace) -> None:
|
||||
black_versions = tuple(
|
||||
BlackVersion(*version.split(":")) for version in options.versions
|
||||
)
|
||||
@ -244,9 +254,11 @@ def format_repos(repos: tuple[Path, ...], options: Namespace) -> 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
|
||||
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.add_argument("-p", "--pypi-package", help="PyPI package to download.")
|
||||
|
39
mypy.ini
Normal file
39
mypy.ini
Normal file
@ -0,0 +1,39 @@
|
||||
[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
|
||||
|
||||
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:
|
||||
" - use autoload script
|
||||
|
||||
if exists("g:load_black")
|
||||
finish
|
||||
endif
|
||||
|
||||
if v:version < 700 || !has('python3')
|
||||
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
|
||||
command! Black :call __BLACK_MISSING()
|
||||
command! BlackUpgrade :call __BLACK_MISSING()
|
||||
@ -29,6 +25,10 @@ if v:version < 700 || !has('python3')
|
||||
finish
|
||||
endif
|
||||
|
||||
if exists("g:load_black")
|
||||
finish
|
||||
endif
|
||||
|
||||
let g:load_black = "py1.0"
|
||||
if !exists("g:black_virtualenv")
|
||||
if has("nvim")
|
||||
@ -43,43 +43,18 @@ endif
|
||||
if !exists("g:black_linelength")
|
||||
let g:black_linelength = 88
|
||||
endif
|
||||
if !exists("g:black_skip_string_normalization")
|
||||
if exists("g:black_string_normalization")
|
||||
let g:black_skip_string_normalization = !g:black_string_normalization
|
||||
if !exists("g:black_string_normalization")
|
||||
if exists("g:black_skip_string_normalization")
|
||||
let g:black_string_normalization = !g:black_skip_string_normalization
|
||||
else
|
||||
let g:black_skip_string_normalization = 0
|
||||
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
|
||||
let g:black_string_normalization = 1
|
||||
endif
|
||||
endif
|
||||
if !exists("g:black_quiet")
|
||||
let g:black_quiet = 0
|
||||
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! BlackVersion :call black#BlackVersion()
|
||||
|
232
pyproject.toml
232
pyproject.toml
@ -7,238 +7,28 @@
|
||||
|
||||
[tool.black]
|
||||
line-length = 88
|
||||
target-version = ['py39']
|
||||
target-version = ['py36', 'py37', 'py38']
|
||||
include = '\.pyi?$'
|
||||
extend-exclude = '''
|
||||
/(
|
||||
# The following are specific to Black, you probably don't want those.
|
||||
tests/data/
|
||||
| profiling/
|
||||
| scripts/generate_schema.py # Uses match syntax
|
||||
)
|
||||
| blib2to3
|
||||
| tests/data
|
||||
| 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.
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling>=1.20.0", "hatch-vcs", "hatch-fancy-pypi-readme"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "black"
|
||||
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"]
|
||||
requires = ["setuptools>=41.0", "setuptools-scm", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
# Option below requires `tests/optional.py`
|
||||
addopts = "--strict-config --strict-markers"
|
||||
optional-tests = [
|
||||
"no_python2: run when `python2` extra NOT installed",
|
||||
"no_blackd: run when `d` 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
|
||||
]
|
@ -1,54 +0,0 @@
|
||||
"""
|
||||
Check that the rev value in the example pre-commit configuration matches
|
||||
the latest version of Black. This saves us from forgetting to update that
|
||||
during the release process.
|
||||
|
||||
Why can't we just use `rev: stable` and call it a day? Well pre-commit
|
||||
won't auto update the hook as you may expect (and for good reasons, some
|
||||
technical and some pragmatic). Encouraging bad practice is also just
|
||||
not ideal. xref: https://github.com/psf/black/issues/420
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import commonmark
|
||||
import yaml
|
||||
from bs4 import BeautifulSoup # type: ignore[import-untyped]
|
||||
|
||||
|
||||
def main(changes: str, source_version_control: str) -> None:
|
||||
changes_html = commonmark.commonmark(changes)
|
||||
changes_soup = BeautifulSoup(changes_html, "html.parser")
|
||||
headers = changes_soup.find_all("h2")
|
||||
latest_tag, *_ = [
|
||||
header.string for header in headers if header.string != "Unreleased"
|
||||
]
|
||||
|
||||
source_version_control_html = commonmark.commonmark(source_version_control)
|
||||
source_version_control_soup = BeautifulSoup(
|
||||
source_version_control_html, "html.parser"
|
||||
)
|
||||
pre_commit_repos = yaml.safe_load(
|
||||
source_version_control_soup.find(class_="language-yaml").string
|
||||
)["repos"]
|
||||
|
||||
for repo in pre_commit_repos:
|
||||
pre_commit_rev = repo["rev"]
|
||||
if not pre_commit_rev == latest_tag:
|
||||
print(
|
||||
"Please set the rev in ``source_version_control.md`` to be the latest "
|
||||
f"one.\nExpected {latest_tag}, got {pre_commit_rev}.\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", "integrations", "source_version_control.md"),
|
||||
encoding="utf-8",
|
||||
) as fd:
|
||||
source_version_control = fd.read()
|
||||
main(changes, source_version_control)
|
@ -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()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user