Drop support for Python 3.7 (#3765)
This commit is contained in:
parent
cf4cc29819
commit
b4dca26c7d
2
.github/workflows/fuzz.yml
vendored
2
.github/workflows/fuzz.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "pypy-3.7", "pypy-3.8"]
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.8"]
|
||||
os: [ubuntu-latest, macOS-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
<!-- Include any especially major or disruptive changes here -->
|
||||
|
||||
- Runtime support for Python 3.7 has been removed. Formatting 3.7 code will still be
|
||||
supported until further notice (#3765)
|
||||
|
||||
### Stable style
|
||||
|
||||
<!-- Changes that affect Black's stable style -->
|
||||
|
@ -334,60 +334,6 @@ To run _Black_ on a key press (e.g. F9 below), add this:
|
||||
nnoremap <F9> :Black<CR>
|
||||
```
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
**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` 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 package that causes problems is:
|
||||
|
||||
- [typed-ast](https://pypi.org/project/typed-ast/)
|
||||
|
||||
Now remove those two packages:
|
||||
|
||||
```console
|
||||
$ pip uninstall typed-ast -y
|
||||
```
|
||||
|
||||
And now you can install them with:
|
||||
|
||||
```console
|
||||
$ pip install --no-binary :all: 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 typed-ast
|
||||
```
|
||||
|
||||
### With ALE
|
||||
|
||||
1. Install [`ale`](https://github.com/dense-analysis/ale)
|
||||
|
2
mypy.ini
2
mypy.ini
@ -2,7 +2,7 @@
|
||||
# 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.7
|
||||
python_version=3.8
|
||||
|
||||
mypy_path=src
|
||||
|
||||
|
@ -33,7 +33,7 @@ build-backend = "hatchling.build"
|
||||
name = "black"
|
||||
description = "The uncompromising code formatter."
|
||||
license = { text = "MIT" }
|
||||
requires-python = ">=3.7"
|
||||
requires-python = ">=3.8"
|
||||
authors = [
|
||||
{ name = "Łukasz Langa", email = "lukasz@langa.pl" },
|
||||
]
|
||||
@ -69,7 +69,6 @@ dependencies = [
|
||||
"pathspec>=0.9.0",
|
||||
"platformdirs>=2",
|
||||
"tomli>=1.1.0; python_version < '3.11'",
|
||||
"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"]
|
||||
@ -121,8 +120,6 @@ enable-by-default = false
|
||||
dependencies = [
|
||||
"hatch-mypyc>=0.16.0",
|
||||
"mypy==1.3",
|
||||
# Required stubs to be removed when the packages support PEP 561 themselves
|
||||
"types-typed-ast>=1.4.2",
|
||||
]
|
||||
require-runtime-dependencies = true
|
||||
exclude = [
|
||||
@ -145,7 +142,7 @@ options = { debug_level = "0" }
|
||||
[tool.cibuildwheel]
|
||||
build-verbosity = 1
|
||||
# So these are the environments we target:
|
||||
# - Python: CPython 3.7+ only
|
||||
# - Python: CPython 3.8+ only
|
||||
# - Architecture (64-bit only): amd64 / x86_64, universal2, and arm64
|
||||
# - OS: Linux (no musl), Windows, and macOS
|
||||
build = "cp3*-*"
|
||||
@ -208,9 +205,6 @@ filterwarnings = [
|
||||
# this is mitigated by a try/catch in https://github.com/psf/black/pull/3198/
|
||||
# this ignore can be removed when support for aiohttp 3.x is dropped.
|
||||
'''ignore:Middleware decorator is deprecated since 4\.0 and its behaviour is default, you can simply remove this decorator:DeprecationWarning''',
|
||||
# this is mitigated by https://github.com/python/cpython/issues/79071 in python 3.8+
|
||||
# this ignore can be removed when support for 3.7 is dropped.
|
||||
'''ignore:Bare functions are deprecated, use async ones:DeprecationWarning''',
|
||||
# aiohttp is using deprecated cgi modules - Safe to remove when fixed:
|
||||
# https://github.com/aio-libs/aiohttp/issues/6905
|
||||
'''ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning''',
|
||||
|
@ -52,13 +52,7 @@ def main() -> None:
|
||||
f.write(f"""# Generated by {basename(__file__)}
|
||||
# wcwidth {wcwidth.__version__}
|
||||
# Unicode {wcwidth.list_versions()[-1]}
|
||||
import sys
|
||||
from typing import List, Tuple
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
from typing import Final, List, Tuple
|
||||
|
||||
WIDTH_TABLE: Final[List[Tuple[int, int, int]]] = [
|
||||
""")
|
||||
|
@ -1,13 +1,7 @@
|
||||
# Generated by make_width_table.py
|
||||
# wcwidth 0.2.6
|
||||
# Unicode 15.0.0
|
||||
import sys
|
||||
from typing import List, Tuple
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
from typing import Final, List, Tuple
|
||||
|
||||
WIDTH_TABLE: Final[List[Tuple[int, int, int]]] = [
|
||||
(0, 0, 0),
|
||||
|
@ -1,13 +1,7 @@
|
||||
"""Builds on top of nodes.py to track brackets."""
|
||||
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, Iterable, List, Optional, Sequence, Set, Tuple, Union
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
from typing import Dict, Final, Iterable, List, Optional, Sequence, Set, Tuple, Union
|
||||
|
||||
from black.nodes import (
|
||||
BRACKET,
|
||||
|
@ -1,13 +1,7 @@
|
||||
import re
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from functools import lru_cache
|
||||
from typing import Iterator, List, Optional, Union
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Final
|
||||
else:
|
||||
from typing_extensions import Final
|
||||
from typing import Final, Iterator, List, Optional, Union
|
||||
|
||||
from black.nodes import (
|
||||
CLOSING_BRACKETS,
|
||||
|
@ -4,19 +4,13 @@
|
||||
chosen by the user.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum, auto
|
||||
from hashlib import sha256
|
||||
from operator import attrgetter
|
||||
from typing import Dict, Set
|
||||
from typing import Dict, Final, Set
|
||||
from warnings import warn
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
|
||||
from black.const import DEFAULT_LINE_LENGTH
|
||||
|
||||
|
||||
|
@ -3,12 +3,8 @@
|
||||
"""
|
||||
|
||||
import sys
|
||||
from typing import Generic, Iterator, List, Optional, Set, Tuple, TypeVar, Union
|
||||
from typing import Final, Generic, Iterator, List, Optional, Set, Tuple, TypeVar, Union
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Final
|
||||
else:
|
||||
from typing_extensions import Final
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeGuard
|
||||
else:
|
||||
|
@ -2,14 +2,8 @@
|
||||
Parse Python code and perform AST validation.
|
||||
"""
|
||||
import ast
|
||||
import platform
|
||||
import sys
|
||||
from typing import Any, Iterable, Iterator, List, Set, Tuple, Type, Union
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
from typing import Final, Iterable, Iterator, List, Set, Tuple
|
||||
|
||||
from black.mode import VERSION_TO_FEATURES, Feature, TargetVersion, supports_feature
|
||||
from black.nodes import syms
|
||||
@ -20,25 +14,6 @@
|
||||
from blib2to3.pgen2.tokenize import TokenError
|
||||
from blib2to3.pytree import Leaf, Node
|
||||
|
||||
ast3: Any
|
||||
|
||||
_IS_PYPY = platform.python_implementation() == "PyPy"
|
||||
|
||||
try:
|
||||
from typed_ast import ast3
|
||||
except ImportError:
|
||||
if sys.version_info < (3, 8) and not _IS_PYPY:
|
||||
print(
|
||||
"The typed_ast package is required but not installed.\n"
|
||||
"You can upgrade to Python 3.8+ or install typed_ast with\n"
|
||||
"`python3 -m pip install typed-ast`.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
else:
|
||||
ast3 = ast
|
||||
|
||||
|
||||
PY2_HINT: Final = "Python 2 support was removed in version 22.0."
|
||||
|
||||
|
||||
@ -147,31 +122,14 @@ def lib2to3_unparse(node: Node) -> str:
|
||||
|
||||
def parse_single_version(
|
||||
src: str, version: Tuple[int, int], *, type_comments: bool
|
||||
) -> Union[ast.AST, ast3.AST]:
|
||||
) -> ast.AST:
|
||||
filename = "<unknown>"
|
||||
# typed-ast is needed because of feature version limitations in the builtin ast 3.8>
|
||||
if sys.version_info >= (3, 8) and version >= (3,):
|
||||
return ast.parse(
|
||||
src, filename, feature_version=version, type_comments=type_comments
|
||||
)
|
||||
|
||||
if _IS_PYPY:
|
||||
# PyPy 3.7 doesn't support type comment tracking which is not ideal, but there's
|
||||
# not much we can do as typed-ast won't work either.
|
||||
if sys.version_info >= (3, 8):
|
||||
return ast3.parse(src, filename, type_comments=type_comments)
|
||||
else:
|
||||
return ast3.parse(src, filename)
|
||||
else:
|
||||
if type_comments:
|
||||
# Typed-ast is guaranteed to be used here and automatically tracks type
|
||||
# comments separately.
|
||||
return ast3.parse(src, filename, feature_version=version[1])
|
||||
else:
|
||||
return ast.parse(src, filename)
|
||||
|
||||
|
||||
def parse_ast(src: str) -> Union[ast.AST, ast3.AST]:
|
||||
def parse_ast(src: str) -> ast.AST:
|
||||
# TODO: support Python 4+ ;)
|
||||
versions = [(3, minor) for minor in range(3, sys.version_info[1] + 1)]
|
||||
|
||||
@ -193,9 +151,6 @@ def parse_ast(src: str) -> Union[ast.AST, ast3.AST]:
|
||||
raise SyntaxError(first_error)
|
||||
|
||||
|
||||
ast3_AST: Final[Type[ast3.AST]] = ast3.AST
|
||||
|
||||
|
||||
def _normalize(lineend: str, value: str) -> str:
|
||||
# To normalize, we strip any leading and trailing space from
|
||||
# each line...
|
||||
@ -206,22 +161,24 @@ def _normalize(lineend: str, value: str) -> str:
|
||||
return normalized.strip()
|
||||
|
||||
|
||||
def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[str]:
|
||||
def stringify_ast(node: ast.AST, depth: int = 0) -> Iterator[str]:
|
||||
"""Simple visitor generating strings to compare ASTs by content."""
|
||||
|
||||
node = fixup_ast_constants(node)
|
||||
if (
|
||||
isinstance(node, ast.Constant)
|
||||
and isinstance(node.value, str)
|
||||
and node.kind == "u"
|
||||
):
|
||||
# It's a quirk of history that we strip the u prefix over here. We used to
|
||||
# rewrite the AST nodes for Python version compatibility and we never copied
|
||||
# over the kind
|
||||
node.kind = None
|
||||
|
||||
yield f"{' ' * depth}{node.__class__.__name__}("
|
||||
|
||||
type_ignore_classes: Tuple[Type[Any], ...]
|
||||
for field in sorted(node._fields): # noqa: F402
|
||||
# TypeIgnore will not be present using pypy < 3.8, so need for this
|
||||
if not (_IS_PYPY and sys.version_info < (3, 8)):
|
||||
# TypeIgnore has only one field 'lineno' which breaks this comparison
|
||||
type_ignore_classes = (ast3.TypeIgnore,)
|
||||
if sys.version_info >= (3, 8):
|
||||
type_ignore_classes += (ast.TypeIgnore,)
|
||||
if isinstance(node, type_ignore_classes):
|
||||
if isinstance(node, ast.TypeIgnore):
|
||||
break
|
||||
|
||||
try:
|
||||
@ -237,22 +194,16 @@ def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[st
|
||||
# parentheses and they change the AST.
|
||||
if (
|
||||
field == "targets"
|
||||
and isinstance(node, (ast.Delete, ast3.Delete))
|
||||
and isinstance(item, (ast.Tuple, ast3.Tuple))
|
||||
and isinstance(node, ast.Delete)
|
||||
and isinstance(item, ast.Tuple)
|
||||
):
|
||||
for elt in item.elts:
|
||||
yield from stringify_ast(elt, depth + 2)
|
||||
|
||||
elif isinstance(item, (ast.AST, ast3.AST)):
|
||||
elif isinstance(item, ast.AST):
|
||||
yield from stringify_ast(item, depth + 2)
|
||||
|
||||
# Note that we are referencing the typed-ast ASTs via global variables and not
|
||||
# direct module attribute accesses because that breaks mypyc. It's probably
|
||||
# something to do with the ast3 variables being marked as Any leading
|
||||
# mypy to think this branch is always taken, leaving the rest of the code
|
||||
# unanalyzed. Tighting up the types for the typed-ast AST types avoids the
|
||||
# mypyc crash.
|
||||
elif isinstance(value, (ast.AST, ast3_AST)):
|
||||
elif isinstance(value, ast.AST):
|
||||
yield from stringify_ast(value, depth + 2)
|
||||
|
||||
else:
|
||||
@ -271,17 +222,3 @@ def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[st
|
||||
yield f"{' ' * (depth+2)}{normalized!r}, # {value.__class__.__name__}"
|
||||
|
||||
yield f"{' ' * depth}) # /{node.__class__.__name__}"
|
||||
|
||||
|
||||
def fixup_ast_constants(node: Union[ast.AST, ast3.AST]) -> Union[ast.AST, ast3.AST]:
|
||||
"""Map ast nodes deprecated in 3.8 to Constant."""
|
||||
if isinstance(node, (ast.Str, ast3.Str, ast.Bytes, ast3.Bytes)):
|
||||
return ast.Constant(value=node.s)
|
||||
|
||||
if isinstance(node, (ast.Num, ast3.Num)):
|
||||
return ast.Constant(value=node.n)
|
||||
|
||||
if isinstance(node, (ast.NameConstant, ast3.NameConstant)):
|
||||
return ast.Constant(value=node.value)
|
||||
|
||||
return node
|
||||
|
@ -5,16 +5,10 @@
|
||||
import re
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from typing import List, Match, Pattern
|
||||
|
||||
from blib2to3.pytree import Leaf
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
from typing import Final, List, Match, Pattern
|
||||
|
||||
from black._width_table import WIDTH_TABLE
|
||||
from blib2to3.pytree import Leaf
|
||||
|
||||
STRING_PREFIX_CHARS: Final = "furbFURB" # All possible string prefix characters.
|
||||
STRING_PREFIX_RE: Final = re.compile(
|
||||
|
@ -2,7 +2,6 @@
|
||||
String transformers that can split and merge strings.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
@ -12,9 +11,11 @@
|
||||
ClassVar,
|
||||
Collection,
|
||||
Dict,
|
||||
Final,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Literal,
|
||||
Optional,
|
||||
Sequence,
|
||||
Set,
|
||||
@ -23,11 +24,6 @@
|
||||
Union,
|
||||
)
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final, Literal
|
||||
else:
|
||||
from typing import Literal, Final
|
||||
|
||||
from mypy_extensions import trait
|
||||
|
||||
from black.comments import contains_pragma_comment
|
||||
|
@ -3,9 +3,6 @@
|
||||
import sys
|
||||
from typing import Dict
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from typing_extensions import Final
|
||||
else:
|
||||
from typing import Final
|
||||
|
||||
# Taken from Python (r53757) and modified to include some tokens
|
||||
|
@ -42,10 +42,7 @@
|
||||
cast,
|
||||
)
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import Final
|
||||
else:
|
||||
from typing_extensions import Final
|
||||
|
||||
from blib2to3.pgen2.token import *
|
||||
from blib2to3.pgen2.grammar import Grammar
|
||||
|
Loading…
Reference in New Issue
Block a user