Skip to content

Commit

Permalink
Drop support for Python 3.7
Browse files Browse the repository at this point in the history
  • Loading branch information
hauntsaninja committed Jul 5, 2023
1 parent 8e618f3 commit 37e61a5
Show file tree
Hide file tree
Showing 15 changed files with 29 additions and 186 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
54 changes: 0 additions & 54 deletions docs/integrations/editors.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 2 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
]
Expand Down Expand Up @@ -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"]
Expand Down Expand Up @@ -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 = [
Expand All @@ -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*-*"
Expand Down Expand Up @@ -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''',
Expand Down
5 changes: 1 addition & 4 deletions src/black/_width_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
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

WIDTH_TABLE: Final[List[Tuple[int, int, int]]] = [
(0, 0, 0),
Expand Down
5 changes: 1 addition & 4 deletions src/black/brackets.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
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 Final

from black.nodes import (
BRACKET,
Expand Down
5 changes: 1 addition & 4 deletions src/black/comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
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

from black.nodes import (
CLOSING_BRACKETS,
Expand Down
5 changes: 1 addition & 4 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
from typing import Dict, Set
from warnings import warn

if sys.version_info < (3, 8):
from typing_extensions import Final
else:
from typing import Final
from typing import Final

from black.const import DEFAULT_LINE_LENGTH

Expand Down
5 changes: 1 addition & 4 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import sys
from typing import Generic, Iterator, List, Optional, Set, Tuple, TypeVar, Union

if sys.version_info >= (3, 8):
from typing import Final
else:
from typing_extensions import Final
from typing import Final
if sys.version_info >= (3, 10):
from typing import TypeGuard
else:
Expand Down
100 changes: 15 additions & 85 deletions src/black/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@
Parse Python code and perform AST validation.
"""
import ast
import platform
import sys
from typing import Any, Iterable, Iterator, List, Set, Tuple, Type, Union
from typing import Any, Iterable, Iterator, List, Set, Tuple, Type

if sys.version_info < (3, 8):
from typing_extensions import Final
else:
from typing import Final
from typing import Final

from black.mode import VERSION_TO_FEATURES, Feature, TargetVersion, supports_feature
from black.nodes import syms
Expand All @@ -20,25 +16,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."


Expand Down Expand Up @@ -147,31 +124,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)
return ast.parse(
src, filename, feature_version=version, type_comments=type_comments
)


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)]

Expand All @@ -193,9 +153,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...
Expand All @@ -206,23 +163,16 @@ 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)

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):
break
# TypeIgnore has only one field 'lineno' which breaks this comparison
if isinstance(node, ast.TypeIgnore):
break

try:
value: object = getattr(node, field)
Expand All @@ -237,22 +187,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:
Expand All @@ -271,17 +215,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 changes: 1 addition & 4 deletions src/black/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@

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

from black._width_table import WIDTH_TABLE

Expand Down
5 changes: 1 addition & 4 deletions src/black/trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@
Union,
)

if sys.version_info < (3, 8):
from typing_extensions import Final, Literal
else:
from typing import Literal, Final
from typing import Literal, Final

from mypy_extensions import trait

Expand Down
5 changes: 1 addition & 4 deletions src/blib2to3/pgen2/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import sys
from typing import Dict

if sys.version_info < (3, 8):
from typing_extensions import Final
else:
from typing import Final
from typing import Final

# Taken from Python (r53757) and modified to include some tokens
# originally monkeypatched in by pgen2.tokenize
Expand Down

0 comments on commit 37e61a5

Please sign in to comment.