From 4c9990023635ece68671324124801f6b75dab2a8 Mon Sep 17 00:00:00 2001 From: Blandes22 <96037855+Blandes22@users.noreply.github.com> Date: Thu, 22 Sep 2022 22:19:31 -0500 Subject: [PATCH 1/6] Make context manager examples in future style docs consistent (#3274) --- docs/the_black_code_style/future_style.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/the_black_code_style/future_style.md b/docs/the_black_code_style/future_style.md index a17d9a10673..a028a2888ed 100644 --- a/docs/the_black_code_style/future_style.md +++ b/docs/the_black_code_style/future_style.md @@ -23,10 +23,10 @@ So _Black_ will eventually format it like this: ```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 \ + make_context_manager1() as cm1, \ + make_context_manager2() as cm2, \ + make_context_manager3() as cm3, \ + make_context_manager4() as cm4 \ : ... # backslashes and an ugly stranded colon ``` @@ -40,10 +40,10 @@ following way: ```python with contextlib.ExitStack() as exit_stack: - cm1 = exit_stack.enter_context(make_context_manager(1)) - cm2 = exit_stack.enter_context(make_context_manager(2)) - cm3 = exit_stack.enter_context(make_context_manager(3)) - cm4 = exit_stack.enter_context(make_context_manager(4)) + cm1 = exit_stack.enter_context(make_context_manager1()) + cm2 = exit_stack.enter_context(make_context_manager2()) + cm3 = exit_stack.enter_context(make_context_manager3()) + cm4 = exit_stack.enter_context(make_context_manager4()) ... ``` From bfc013ab93d0993a6e24235291dddd4c4ecd64ee Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Fri, 23 Sep 2022 05:23:35 +0200 Subject: [PATCH 2/6] Support version specifiers in GH action (#3265) Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com> --- CHANGES.md | 3 +++ action/main.py | 7 ++++--- docs/integrations/github_actions.md | 21 ++++++++++++++++++--- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0fa80ad8124..67d007c21ae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -47,6 +47,9 @@ +- Update GitHub Action to support use of version specifiers (e.g. `<23`) for Black + version (#3265) + ### Documentation +- Fix a crash when `# fmt: on` is used on a different block level than `# fmt: off` + (#3281) + ### Preview style diff --git a/docs/contributing/reference/reference_functions.rst b/docs/contributing/reference/reference_functions.rst index 50eaeb31e15..3bda5de1774 100644 --- a/docs/contributing/reference/reference_functions.rst +++ b/docs/contributing/reference/reference_functions.rst @@ -137,9 +137,9 @@ Utilities .. autofunction:: black.comments.is_fmt_on -.. autofunction:: black.comments.contains_fmt_on_at_column +.. autofunction:: black.comments.children_contains_fmt_on -.. autofunction:: black.nodes.first_leaf_column +.. autofunction:: black.nodes.first_leaf_of .. autofunction:: black.linegen.generate_trailers_to_omit diff --git a/src/black/comments.py b/src/black/comments.py index dc58934f9d3..2a4c254ecd9 100644 --- a/src/black/comments.py +++ b/src/black/comments.py @@ -14,11 +14,12 @@ STANDALONE_COMMENT, WHITESPACE, container_of, - first_leaf_column, + first_leaf_of, preceding_leaf, + syms, ) from blib2to3.pgen2 import token -from blib2to3.pytree import Leaf, Node, type_repr +from blib2to3.pytree import Leaf, Node # types LN = Union[Leaf, Node] @@ -230,7 +231,7 @@ def generate_ignored_nodes( return # fix for fmt: on in children - if contains_fmt_on_at_column(container, leaf.column, preview=preview): + if children_contains_fmt_on(container, preview=preview): for child in container.children: if isinstance(child, Leaf) and is_fmt_on(child, preview=preview): if child.type in CLOSING_BRACKETS: @@ -240,10 +241,14 @@ def generate_ignored_nodes( # The alternative is to fail the formatting. yield child return - if contains_fmt_on_at_column(child, leaf.column, preview=preview): + if children_contains_fmt_on(child, preview=preview): return yield child else: + if container.type == token.DEDENT and container.next_sibling is None: + # This can happen when there is no matching `# fmt: on` comment at the + # same level as `# fmt: on`. We need to keep this DEDENT. + return yield container container = container.next_sibling @@ -268,9 +273,7 @@ def _generate_ignored_nodes_from_fmt_skip( for sibling in siblings: yield sibling elif ( - parent is not None - and type_repr(parent.type) == "suite" - and leaf.type == token.NEWLINE + parent is not None and parent.type == syms.suite and leaf.type == token.NEWLINE ): # The `# fmt: skip` is on the colon line of the if/while/def/class/... # statements. The ignored nodes should be previous siblings of the @@ -278,7 +281,7 @@ def _generate_ignored_nodes_from_fmt_skip( leaf.prefix = "" ignored_nodes: List[LN] = [] parent_sibling = parent.prev_sibling - while parent_sibling is not None and type_repr(parent_sibling.type) != "suite": + while parent_sibling is not None and parent_sibling.type != syms.suite: ignored_nodes.insert(0, parent_sibling) parent_sibling = parent_sibling.prev_sibling # Special case for `async_stmt` where the ASYNC token is on the @@ -306,17 +309,12 @@ def is_fmt_on(container: LN, preview: bool) -> bool: return fmt_on -def contains_fmt_on_at_column(container: LN, column: int, *, preview: bool) -> bool: - """Determine if children at a given column have formatting switched on.""" +def children_contains_fmt_on(container: LN, *, preview: bool) -> bool: + """Determine if children have formatting switched on.""" for child in container.children: - if ( - isinstance(child, Node) - and first_leaf_column(child) == column - or isinstance(child, Leaf) - and child.column == column - ): - if is_fmt_on(child, preview=preview): - return True + leaf = first_leaf_of(child) + if leaf is not None and is_fmt_on(leaf, preview=preview): + return True return False diff --git a/src/black/nodes.py b/src/black/nodes.py index 8f341ab35d6..aeb2be389c8 100644 --- a/src/black/nodes.py +++ b/src/black/nodes.py @@ -502,12 +502,14 @@ def container_of(leaf: Leaf) -> LN: return container -def first_leaf_column(node: Node) -> Optional[int]: - """Returns the column of the first leaf child of a node.""" - for child in node.children: - if isinstance(child, Leaf): - return child.column - return None +def first_leaf_of(node: LN) -> Optional[Leaf]: + """Returns the first leaf of the node tree.""" + if isinstance(node, Leaf): + return node + if node.children: + return first_leaf_of(node.children[0]) + else: + return None def is_arith_like(node: LN) -> bool: diff --git a/tests/data/simple_cases/fmtonoff5.py b/tests/data/simple_cases/fmtonoff5.py index 746aa41f4e4..71b1381ed0d 100644 --- a/tests/data/simple_cases/fmtonoff5.py +++ b/tests/data/simple_cases/fmtonoff5.py @@ -34,3 +34,125 @@ def test_func(): return True return False + + +# Regression test for https://github.com/psf/black/issues/2567. +if True: + # fmt: off + for _ in range( 1 ): + # fmt: on + print ( "This won't be formatted" ) + print ( "This won't be formatted either" ) +else: + print ( "This will be formatted" ) + + +# Regression test for https://github.com/psf/black/issues/3184. +class A: + async def call(param): + if param: + # fmt: off + if param[0:4] in ( + "ABCD", "EFGH" + ) : + # fmt: on + print ( "This won't be formatted" ) + + elif param[0:4] in ("ZZZZ",): + print ( "This won't be formatted either" ) + + print ( "This will be formatted" ) + + +# Regression test for https://github.com/psf/black/issues/2985 +class Named(t.Protocol): + # fmt: off + @property + def this_wont_be_formatted ( self ) -> str: ... + +class Factory(t.Protocol): + def this_will_be_formatted ( self, **kwargs ) -> Named: ... + # fmt: on + + +# output + + +# Regression test for https://github.com/psf/black/issues/3129. +setup( + entry_points={ + # fmt: off + "console_scripts": [ + "foo-bar" + "=foo.bar.:main", + # fmt: on + ] # Includes an formatted indentation. + }, +) + + +# Regression test for https://github.com/psf/black/issues/2015. +run( + # fmt: off + [ + "ls", + "-la", + ] + # fmt: on + + path, + check=True, +) + + +# Regression test for https://github.com/psf/black/issues/3026. +def test_func(): + # yapf: disable + if unformatted( args ): + return True + # yapf: enable + elif b: + return True + + return False + + +# Regression test for https://github.com/psf/black/issues/2567. +if True: + # fmt: off + for _ in range( 1 ): + # fmt: on + print ( "This won't be formatted" ) + print ( "This won't be formatted either" ) +else: + print("This will be formatted") + + +# Regression test for https://github.com/psf/black/issues/3184. +class A: + async def call(param): + if param: + # fmt: off + if param[0:4] in ( + "ABCD", "EFGH" + ) : + # fmt: on + print ( "This won't be formatted" ) + + elif param[0:4] in ("ZZZZ",): + print ( "This won't be formatted either" ) + + print("This will be formatted") + + +# Regression test for https://github.com/psf/black/issues/2985 +class Named(t.Protocol): + # fmt: off + @property + def this_wont_be_formatted ( self ) -> str: ... + + +class Factory(t.Protocol): + def this_will_be_formatted(self, **kwargs) -> Named: + ... + + # fmt: on From 4b4680a0a9e06ae926abfbf0d209725de44860a8 Mon Sep 17 00:00:00 2001 From: Stijn de Gooijer Date: Sun, 25 Sep 2022 11:28:43 +0200 Subject: [PATCH 4/6] Make README logo link to docs (#3285) docs: Make README logo link to docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 624d4d755eb..4c761606514 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Black Logo](https://raw.githubusercontent.com/psf/black/main/docs/_static/logo2-readme.png) +[![Black Logo](https://raw.githubusercontent.com/psf/black/main/docs/_static/logo2-readme.png)](https://black.readthedocs.io/en/stable/)

The Uncompromising Code Formatter

From 468ceafca571454fd279f3b428076631fdaffd3d Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Sun, 25 Sep 2022 14:54:33 -0700 Subject: [PATCH 5/6] Switch build backend to Hatchling (#3233) This implements PEP 621, obviating the need for `setup.py`, `setup.cfg`, and `MANIFEST.in`. The build backend Hatchling (of which I am a maintainer in the PyPA) is now used as that is the default in the official Python packaging tutorial. Hatchling is available on all the major distribution channels such as Debian, Fedora, and many more. ## Python support The earliest supported Python 3 version of Hatchling is 3.7, therefore I've also set that as the minimum here. Python 3.6 is EOL and other build backends like flit-core and setuptools also dropped support. Python 3.6 accounted for 3-4% of downloads in the last month. ## Plugins Configuration is now completely static with the help of 3 plugins: ### Readme hynek's hatch-fancy-pypi-readme allows for the dynamic construction of the readme which was previously coded up in `setup.py`. Now it's simply: ```toml [tool.hatch.metadata.hooks.fancy-pypi-readme] content-type = "text/markdown" fragments = [ { path = "README.md" }, { path = "CHANGES.md" }, ] ``` ### Versioning hatch-vcs is currently just a wrapper around setuptools-scm (which despite the legacy naming is actually now decoupled from setuptools): ```toml [tool.hatch.version] source = "vcs" [tool.hatch.build.hooks.vcs] version-file = "src/_black_version.py" template = ''' version = "{version}" ''' ``` ### mypyc hatch-mypyc offers many benefits over the existing approach: - No need to manually select files for inclusion - Avoids the need for the current CI workaround for https://github.com/mypyc/mypyc/issues/946 - Intermediate artifacts (like `build/`) from setuptools and mypyc itself no longer clutter the project directory - Runtime dependencies required at build time no longer need to be manually redeclared as this is a built-in option of Hatchling Co-authored-by: Richard Si <63936253+ichard26@users.noreply.github.com> Co-authored-by: Jelle Zijlstra --- .github/mypyc-requirements.txt | 14 -- .github/workflows/diff_shades.yml | 12 +- .github/workflows/fuzz.yml | 2 +- .github/workflows/pypi_upload.yml | 2 - .github/workflows/test.yml | 2 +- CHANGES.md | 5 + MANIFEST.in | 1 - docs/faq.md | 6 +- docs/usage_and_configuration/the_basics.md | 7 +- pyproject.toml | 135 +++++++++++++++++--- setup.cfg | 3 - setup.py | 141 --------------------- tox.ini | 5 +- 13 files changed, 140 insertions(+), 195 deletions(-) delete mode 100644 .github/mypyc-requirements.txt delete mode 100644 MANIFEST.in delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.github/mypyc-requirements.txt b/.github/mypyc-requirements.txt deleted file mode 100644 index 352d36c0070..00000000000 --- a/.github/mypyc-requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -mypy == 0.971 - -# A bunch of packages for type information -mypy-extensions >= 0.4.3 -tomli >= 0.10.2 -types-typed-ast >= 1.4.2 -types-dataclasses >= 0.1.3 -typing-extensions > 3.10.0.1 -click >= 8.0.0 -platformdirs >= 2.1.0 - -# And because build isolation is disabled, we'll need to pull this too -setuptools-scm[toml] >= 6.3.1 -wheel diff --git a/.github/workflows/diff_shades.yml b/.github/workflows/diff_shades.yml index fef9637c92f..a126756f102 100644 --- a/.github/workflows/diff_shades.yml +++ b/.github/workflows/diff_shades.yml @@ -3,10 +3,10 @@ name: diff-shades on: push: branches: [main] - paths: ["src/**", "setup.*", "pyproject.toml", ".github/workflows/*"] + paths: ["src/**", "pyproject.toml", ".github/workflows/*"] pull_request: - paths: ["src/**", "setup.*", "pyproject.toml", ".github/workflows/*"] + paths: ["src/**", "pyproject.toml", ".github/workflows/*"] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} @@ -41,6 +41,7 @@ jobs: 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-12 @@ -64,7 +65,6 @@ jobs: run: | python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip python -m pip install click packaging urllib3 - python -m pip install -r .github/mypyc-requirements.txt # 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" @@ -83,8 +83,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: > ${{ matrix.baseline-setup-cmd }} - && python setup.py --use-mypyc bdist_wheel - && python -m pip install dist/*.whl && rm build dist -r + && python -m pip install . - name: Analyze baseline revision if: steps.baseline-cache.outputs.cache-hit != 'true' @@ -97,8 +96,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} run: > ${{ matrix.target-setup-cmd }} - && python setup.py --use-mypyc bdist_wheel - && python -m pip install dist/*.whl + && python -m pip install . - name: Analyze target revision run: > diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index a2810e25f77..ebb8a9fda9e 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ["3.7", "3.8", "3.9", "3.10"] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/pypi_upload.yml b/.github/workflows/pypi_upload.yml index ae26a814c9e..2c288284444 100644 --- a/.github/workflows/pypi_upload.yml +++ b/.github/workflows/pypi_upload.yml @@ -61,8 +61,6 @@ jobs: uses: pypa/cibuildwheel@v2.10.0 env: CIBW_ARCHS_MACOS: "${{ matrix.macos_arch }}" - # This isn't supported in pyproject.toml which makes sense (but is annoying). - CIBW_PROJECT_REQUIRES_PYTHON: ">=3.6.2" - name: Upload wheels as workflow artifacts uses: actions/upload-artifact@v2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7cc55d1bf76..372d1fd5d38 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy-3.7", "pypy-3.8"] + python-version: ["3.7", "3.8", "3.9", "3.10", "pypy-3.7", "pypy-3.8"] os: [ubuntu-latest, macOS-latest, windows-latest] steps: diff --git a/CHANGES.md b/CHANGES.md index 48f5035c133..a775c76e4a5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,9 @@ +- Runtime support for Python 3.6 has been removed. Formatting 3.6 code will still be + supported until further notice. + ### Stable style @@ -28,6 +31,8 @@ +- Hatchling is now used as the build backend. This will not have any effect for users + who install Black with its wheels from PyPI. (#3233) - Faster compiled wheels are now available for CPython 3.11 (#3276) ### Parser diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 5e53af336e2..00000000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -prune profiling diff --git a/docs/faq.md b/docs/faq.md index aeb9634789f..8b9ffb0202e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -86,8 +86,8 @@ disabled-by-default counterpart W504. E203 should be disabled while changes are ## Which Python versions does Black support? -Currently the runtime requires Python 3.6-3.10. Formatting is supported for files -containing syntax from Python 3.3 to 3.10. We promise to support at least all Python +Currently the runtime requires Python 3.7-3.11. Formatting is supported for files +containing syntax from Python 3.3 to 3.11. 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. @@ -95,6 +95,8 @@ Support for formatting Python 2 code was removed in version 22.0. While we've ma 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. +Runtime support for 3.6 was removed in version 22.9.0. + ## Why does my linter or typechecker complain after I format my code? Some linters and other tools use magical comments (e.g., `# noqa`, `# type: ignore`) to diff --git a/docs/usage_and_configuration/the_basics.md b/docs/usage_and_configuration/the_basics.md index 2dc2a14f91a..aa176c4ba3f 100644 --- a/docs/usage_and_configuration/the_basics.md +++ b/docs/usage_and_configuration/the_basics.md @@ -204,9 +204,10 @@ 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/) or -[Flit](https://flit.readthedocs.io/en/latest/) it can fully replace the need for -`setup.py` and `setup.cfg` files. +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. ### Where _Black_ looks for the file diff --git a/pyproject.toml b/pyproject.toml index 122a49e004b..c37702616fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ [tool.black] line-length = 88 -target-version = ['py36', 'py37', 'py38'] +target-version = ['py37', 'py38'] include = '\.pyi?$' extend-exclude = ''' /( @@ -26,18 +26,128 @@ preview = true # NOTE: You don't need this in your own Black configuration. [build-system] -requires = ["setuptools>=45.0", "setuptools_scm[toml]>=6.3.1", "wheel"] -build-backend = "setuptools.build_meta" +requires = ["hatchling>=1.8.0", "hatch-vcs", "hatch-fancy-pypi-readme"] +build-backend = "hatchling.build" + +[project] +name = "black" +description = "The uncompromising code formatter." +license = "MIT" +requires-python = ">=3.7" +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.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Quality Assurance", +] +dependencies = [ + "click>=8.0.0", + "mypy_extensions>=0.4.3", + "pathspec>=0.9.0", + "platformdirs>=2", + "tomli>=1.1.0; python_full_version < '3.11.0a7'", + "typed-ast>=1.4.2; python_version < '3.8' and implementation_name == 'cpython'", + "typing_extensions>=3.10.0.0; python_version < '3.10'", +] +dynamic = ["readme", "version"] + +[project.optional-dependencies] +colorama = ["colorama>=0.4.3"] +uvloop = ["uvloop>=0.15.2"] +d = [ + "aiohttp>=3.7.4", +] +jupyter = [ + "ipython>=7.8.0", + "tokenize-rt>=3.2.0", +] + +[project.scripts] +black = "black:patched_main" +blackd = "blackd:patched_main [d]" + +[project.urls] +Changelog = "https://github.com/psf/black/blob/main/CHANGES.md" +Homepage = "https://github.com/psf/black" + +[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"] + +[tool.hatch.build.targets.wheel.hooks.mypyc] +enable-by-default = false +dependencies = [ + "hatch-mypyc>=0.13.0", + "mypy==0.971", + # Required stubs to be removed when the packages support PEP 561 themselves + "types-typed-ast>=1.4.2", +] +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", +] +options = { debug_level = "0" } [tool.cibuildwheel] build-verbosity = 1 # So these are the environments we target: -# - Python: CPython 3.6+ only +# - Python: CPython 3.7+ 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-*"] -before-build = ["pip install -r .github/mypyc-requirements.txt"] # 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. @@ -49,7 +159,7 @@ test-extras = ["d"," jupyter"] test-skip = ["*-macosx_arm64", "*-macosx_universal2:arm64"] [tool.cibuildwheel.environment] -BLACK_USE_MYPYC = "1" +HATCH_BUILD_HOOKS_ENABLE = "1" MYPYC_OPT_LEVEL = "3" MYPYC_DEBUG_LEVEL = "0" # The dependencies required to build wheels with mypyc aren't specified in @@ -61,28 +171,17 @@ AIOHTTP_NO_EXTENSIONS = "1" [tool.cibuildwheel.linux] before-build = [ - "pip install -r .github/mypyc-requirements.txt", "yum install -y clang gcc", ] [tool.cibuildwheel.linux.environment] -BLACK_USE_MYPYC = "1" +HATCH_BUILD_HOOKS_ENABLE = "1" MYPYC_OPT_LEVEL = "3" MYPYC_DEBUG_LEVEL = "0" -PIP_NO_BUILD_ISOLATION = "no" # Black needs Clang to compile successfully on Linux. CC = "clang" AIOHTTP_NO_EXTENSIONS = "1" -[tool.cibuildwheel.windows] -# For some reason, (compiled) mypyc is failing to start up with "ImportError: DLL load -# failed: A dynamic link library (DLL) initialization routine failed." on Windows for -# at least 3.6. Let's just use interpreted mypy[c]. -# See also: https://github.com/mypyc/mypyc/issues/819. -before-build = [ - "pip install -r .github/mypyc-requirements.txt --no-binary mypy" -] - [tool.isort] atomic = true profile = "black" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 1a0a217eb91..00000000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[options] -setup_requires = - setuptools_scm[toml]>=6.3.1 diff --git a/setup.py b/setup.py deleted file mode 100644 index 2cf455573c9..00000000000 --- a/setup.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (C) 2020 Łukasz Langa -import os -import sys - -from setuptools import find_packages, setup - -assert sys.version_info >= (3, 6, 2), "black requires Python 3.6.2+" -from pathlib import Path # noqa E402 -from typing import List # noqa: E402 - -CURRENT_DIR = Path(__file__).parent -sys.path.insert(0, str(CURRENT_DIR)) # for setuptools.build_meta - - -def get_long_description() -> str: - return ( - (CURRENT_DIR / "README.md").read_text(encoding="utf8") - + "\n\n" - + (CURRENT_DIR / "CHANGES.md").read_text(encoding="utf8") - ) - - -def find_python_files(base: Path) -> List[Path]: - files = [] - for entry in base.iterdir(): - if entry.is_file() and entry.suffix == ".py": - files.append(entry) - elif entry.is_dir(): - files.extend(find_python_files(entry)) - - return files - - -USE_MYPYC = False -# To compile with mypyc, a mypyc checkout must be present on the PYTHONPATH -if len(sys.argv) > 1 and sys.argv[1] == "--use-mypyc": - sys.argv.pop(1) - USE_MYPYC = True -if os.getenv("BLACK_USE_MYPYC", None) == "1": - USE_MYPYC = True - -if USE_MYPYC: - from mypyc.build import mypycify - - src = CURRENT_DIR / "src" - # TIP: filepaths are normalized to use forward slashes and are relative to ./src/ - # before being checked against. - blocklist = [ - # Not performance sensitive, so save bytes + compilation time: - "blib2to3/__init__.py", - "blib2to3/pgen2/__init__.py", - "black/output.py", - "black/concurrency.py", - "black/files.py", - "black/report.py", - # Breaks the test suite when compiled (and is also useless): - "black/debug.py", - # Compiled modules can't be run directly and that's a problem here: - "black/__main__.py", - ] - discovered = [] - # There's no good reason for blackd to be compiled. - discovered.extend(find_python_files(src / "black")) - discovered.extend(find_python_files(src / "blib2to3")) - mypyc_targets = [ - str(p) for p in discovered if p.relative_to(src).as_posix() not in blocklist - ] - - opt_level = os.getenv("MYPYC_OPT_LEVEL", "3") - debug_level = os.getenv("MYPYC_DEBUG_LEVEL", "3") - ext_modules = mypycify( - mypyc_targets, opt_level=opt_level, debug_level=debug_level, verbose=True - ) -else: - ext_modules = [] - -setup( - name="black", - use_scm_version={ - "write_to": "src/_black_version.py", - "write_to_template": 'version = "{version}"\n', - }, - description="The uncompromising code formatter.", - long_description=get_long_description(), - long_description_content_type="text/markdown", - keywords="automation formatter yapf autopep8 pyfmt gofmt rustfmt", - author="Łukasz Langa", - author_email="lukasz@langa.pl", - url="https://github.com/psf/black", - project_urls={"Changelog": "https://github.com/psf/black/blob/main/CHANGES.md"}, - license="MIT", - py_modules=["_black_version"], - ext_modules=ext_modules, - packages=find_packages(where="src"), - package_dir={"": "src"}, - package_data={ - "blib2to3": ["*.txt"], - "black": ["py.typed"], - }, - python_requires=">=3.6.2", - zip_safe=False, - install_requires=[ - "click>=8.0.0", - "platformdirs>=2", - "tomli>=1.1.0; python_full_version < '3.11.0a7'", - "typed-ast>=1.4.2; python_version < '3.8' and implementation_name == 'cpython'", - "pathspec>=0.9.0", - "dataclasses>=0.6; python_version < '3.7'", - "typing_extensions>=3.10.0.0; python_version < '3.10'", - "mypy_extensions>=0.4.3", - ], - extras_require={ - "d": ["aiohttp>=3.7.4"], - "colorama": ["colorama>=0.4.3"], - "uvloop": ["uvloop>=0.15.2"], - "jupyter": ["ipython>=7.8.0", "tokenize-rt>=3.2.0"], - }, - 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.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3 :: Only", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Software Development :: Quality Assurance", - ], - entry_points={ - "console_scripts": [ - "black=black:patched_main", - "blackd=blackd:patched_main [d]", - ] - }, -) diff --git a/tox.ini b/tox.ini index 098f06c9828..4934514264b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] -envlist = {,ci-}py{36,37,38,39,310,311,py3},fuzz,run_self +isolated_build = true +envlist = {,ci-}py{37,38,39,310,311,py3},fuzz,run_self [testenv] setenv = PYTHONPATH = {toxinidir}/src @@ -96,4 +97,4 @@ setenv = PYTHONPATH = {toxinidir}/src skip_install = True commands = pip install -e .[d] - black --check {toxinidir}/src {toxinidir}/tests {toxinidir}/setup.py + black --check {toxinidir}/src {toxinidir}/tests From 2189bcaac01d9b6289411a75557a23cf4a06b783 Mon Sep 17 00:00:00 2001 From: Richard Si <63936253+ichard26@users.noreply.github.com> Date: Sun, 25 Sep 2022 20:24:18 -0400 Subject: [PATCH 6/6] Fix outdated references to 3.6 and run pyupgrade (#3286) I also missed the accidental removal of the 3.11 classifier in the PR. --- README.md | 5 ++--- docs/getting_started.md | 5 ++--- docs/integrations/editors.md | 2 +- pyproject.toml | 1 + src/black/comments.py | 3 +-- src/black/concurrency.py | 12 ++---------- src/black/trans.py | 2 +- 7 files changed, 10 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 4c761606514..b2593024676 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,8 @@ 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.6.2+ 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.7+ to run. +If you want to format Jupyter Notebooks, install with `pip install 'black[jupyter]'`. If you can't wait for the latest _hotness_ and want to install from GitHub, use: diff --git a/docs/getting_started.md b/docs/getting_started.md index fca960915a8..1825f3b5aa3 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -16,9 +16,8 @@ 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.6.2+ 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.7+ to run. +If you want to format Jupyter Notebooks, install with `pip install 'black[jupyter]'`. If you can't wait for the latest _hotness_ and want to install from GitHub, use: diff --git a/docs/integrations/editors.md b/docs/integrations/editors.md index 318e0e295d0..28c9f48a09f 100644 --- a/docs/integrations/editors.md +++ b/docs/integrations/editors.md @@ -148,7 +148,7 @@ 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. -This plugin **requires Vim 7.0+ built with Python 3.6+ support**. It needs Python 3.6 to +This plugin **requires Vim 7.0+ built with Python 3.7+ support**. It needs Python 3.7 to be able to run _Black_ inside the Vim process which is much faster than calling an external command. diff --git a/pyproject.toml b/pyproject.toml index c37702616fc..412e46cbc05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Quality Assurance", ] diff --git a/src/black/comments.py b/src/black/comments.py index 2a4c254ecd9..dce83abf1bb 100644 --- a/src/black/comments.py +++ b/src/black/comments.py @@ -270,8 +270,7 @@ def _generate_ignored_nodes_from_fmt_skip( while "\n" not in prev_sibling.prefix and prev_sibling.prev_sibling is not None: prev_sibling = prev_sibling.prev_sibling siblings.insert(0, prev_sibling) - for sibling in siblings: - yield sibling + yield from siblings elif ( parent is not None and parent.type == syms.suite and leaf.type == token.NEWLINE ): diff --git a/src/black/concurrency.py b/src/black/concurrency.py index bdc368d5add..10e288f4f93 100644 --- a/src/black/concurrency.py +++ b/src/black/concurrency.py @@ -58,12 +58,7 @@ def shutdown(loop: asyncio.AbstractEventLoop) -> None: for task in to_cancel: task.cancel() - if sys.version_info >= (3, 7): - loop.run_until_complete(asyncio.gather(*to_cancel, return_exceptions=True)) - else: - loop.run_until_complete( - asyncio.gather(*to_cancel, loop=loop, return_exceptions=True) - ) + loop.run_until_complete(asyncio.gather(*to_cancel, return_exceptions=True)) finally: # `concurrent.futures.Future` objects cannot be cancelled once they # are already running. There might be some when the `shutdown()` happened. @@ -191,9 +186,6 @@ async def schedule_formatting( sources_to_cache.append(src) report.done(src, changed) if cancelled: - if sys.version_info >= (3, 7): - await asyncio.gather(*cancelled, return_exceptions=True) - else: - await asyncio.gather(*cancelled, loop=loop, return_exceptions=True) + await asyncio.gather(*cancelled, return_exceptions=True) if sources_to_cache: write_cache(cache, sources_to_cache, mode) diff --git a/src/black/trans.py b/src/black/trans.py index 74b932bb422..7e2d8e67c1a 100644 --- a/src/black/trans.py +++ b/src/black/trans.py @@ -1256,7 +1256,7 @@ def do_transform(self, line: Line, string_idx: int) -> Iterator[TResult[Line]]: string_op_leaves = self._get_string_operator_leaves(LL) string_op_leaves_length = ( - sum([len(str(prefix_leaf)) for prefix_leaf in string_op_leaves]) + 1 + sum(len(str(prefix_leaf)) for prefix_leaf in string_op_leaves) + 1 if string_op_leaves else 0 )