Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow install under pypy #2559

Merged
merged 25 commits into from Nov 14, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2726ce8
Allow install under pypy
olliemath Oct 21, 2021
6ae0833
Add pypy3 test action
olliemath Oct 22, 2021
648f1c9
Compat: handle bad cache items under pypy
olliemath Oct 22, 2021
756a129
Update changes for #2559
olliemath Oct 22, 2021
88cada4
Fix typo in .github/workflows/test.yml
olliemath Oct 22, 2021
db928b8
Support only pypy3.7+
olliemath Oct 22, 2021
2279abf
Testing: only support pypy3.7+
olliemath Oct 22, 2021
8efb3aa
Tox: create a pypy3 section
olliemath Oct 22, 2021
5885d63
Update github actions for pypy
olliemath Oct 22, 2021
fe1d91d
Use python_implementation to detect pypy
olliemath Oct 27, 2021
6c66ab3
Tox: simplify pypy command
olliemath Oct 27, 2021
39bfb28
Add PyPy section to FAQ
olliemath Oct 27, 2021
e5dd160
Merge branch 'main' into main
olliemath Oct 28, 2021
c35ad03
Revert "Tox: simplify pypy command"
olliemath Oct 28, 2021
8e75e5a
Testing: handle windows symlinks under pypy
olliemath Oct 28, 2021
da70ee6
Prettier test.yml
olliemath Oct 28, 2021
ce4dc83
Merge branch 'main' into main
olliemath Oct 29, 2021
7a24885
Fix bad merge of changes
olliemath Oct 29, 2021
1677ddb
Tighten up PyPy faq
olliemath Oct 31, 2021
640a192
Prettier FAQ
olliemath Oct 31, 2021
0e78f39
Merge branch 'main' into main
olliemath Nov 1, 2021
0e93564
Merge branch 'main' into olliemath/main
ichard26 Nov 12, 2021
3215f3c
Move changelog to unreleased section
ichard26 Nov 12, 2021
57de57f
Merge branch 'main' into main
JelleZijlstra Nov 14, 2021
f345ef6
Update CHANGES.md
JelleZijlstra Nov 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/test.yml
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "pypy-3.7"]
os: [ubuntu-latest, macOS-latest, windows-latest]

steps:
Expand All @@ -41,9 +41,15 @@ jobs:
python -m pip install --upgrade tox

- name: Unit tests
if: "!startsWith(matrix.python-version, 'pypy')"
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: Publish coverage to Coveralls
# If pushed / is a pull request against main repo AND
# we're running on Linux (this action only supports Linux)
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -8,6 +8,7 @@
- Add new `--workers` parameter (#2514)
- Fixed feature detection for positional-only arguments in lambdas (#2532)
- Bumped typed-ast version minimum to 1.4.3 for 3.10 compatiblity (#2519)
- Add experimental pypy support (#2559)

### _Blackd_

Expand Down
6 changes: 6 additions & 0 deletions docs/faq.md
Expand Up @@ -88,3 +88,9 @@ 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 _experimental_ support for PyPy 3.7 and higher. You cannot format Python 2
olliemath marked this conversation as resolved.
Show resolved Hide resolved
files under PyPy, because PyPy's inbuilt ast module does not support this. For the most
stable user-experience, we recommend using CPython if possible.
olliemath marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -75,7 +75,7 @@ def get_long_description() -> str:
"click>=7.1.2",
"platformdirs>=2",
"tomli>=0.2.6,<2.0.0",
"typed-ast>=1.4.2; python_version < '3.8'",
"typed-ast>=1.4.2; python_version < '3.8' and implementation_name == 'cpython'",
"regex>=2020.1.8",
"pathspec>=0.9.0, <1",
"dataclasses>=0.6; python_version < '3.7'",
Expand Down
2 changes: 1 addition & 1 deletion src/black/cache.py
Expand Up @@ -35,7 +35,7 @@ def read_cache(mode: Mode) -> Cache:
with cache_file.open("rb") as fobj:
try:
cache: Cache = pickle.load(fobj)
except (pickle.UnpicklingError, ValueError):
except (pickle.UnpicklingError, ValueError, IndexError):
return {}

return cache
Expand Down
25 changes: 17 additions & 8 deletions src/black/parsing.py
Expand Up @@ -2,6 +2,7 @@
Parse Python code and perform AST validation.
"""
import ast
import platform
import sys
from typing import Iterable, Iterator, List, Set, Union, Tuple

Expand All @@ -15,10 +16,13 @@
from black.mode import TargetVersion, Feature, supports_feature
from black.nodes import syms

_IS_PYPY = platform.python_implementation() == "PyPy"

try:
from typed_ast import ast3, ast27
except ImportError:
if sys.version_info < (3, 8):
# Either our python version is too low, or we're on pypy
if sys.version_info < (3, 7) or (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"
Expand Down Expand Up @@ -114,7 +118,10 @@ def parse_single_version(
if sys.version_info >= (3, 8) and version >= (3,):
return ast.parse(src, filename, feature_version=version)
elif version >= (3,):
return ast3.parse(src, filename, feature_version=version[1])
if _IS_PYPY:
return ast3.parse(src, filename)
else:
return ast3.parse(src, filename, feature_version=version[1])
elif version == (2, 7):
return ast27.parse(src)
raise AssertionError("INTERNAL ERROR: Tried parsing unsupported Python version!")
Expand Down Expand Up @@ -148,12 +155,14 @@ def stringify_ast(
yield f"{' ' * depth}{node.__class__.__name__}("

for field in sorted(node._fields): # noqa: F402
# TypeIgnore has only one field 'lineno' which breaks this comparison
type_ignore_classes = (ast3.TypeIgnore, ast27.TypeIgnore)
if sys.version_info >= (3, 8):
type_ignore_classes += (ast.TypeIgnore,)
if isinstance(node, type_ignore_classes):
break
# 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, ast27.TypeIgnore)
if sys.version_info >= (3, 8):
type_ignore_classes += (ast.TypeIgnore,)
if isinstance(node, type_ignore_classes):
break

try:
value = getattr(node, field)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_black.py
Expand Up @@ -943,7 +943,7 @@ def test_broken_symlink(self) -> None:
symlink = workspace / "broken_link.py"
try:
symlink.symlink_to("nonexistent.py")
except OSError as e:
except (OSError, NotImplementedError) as e:
self.skipTest(f"Can't create symlinks: {e}")
self.invokeBlack([str(workspace.resolve())])

Expand Down
27 changes: 26 additions & 1 deletion tox.ini
@@ -1,5 +1,5 @@
[tox]
envlist = {,ci-}py{36,37,38,39,310},fuzz
envlist = {,ci-}py{36,37,38,39,310,py3},fuzz

[testenv]
setenv = PYTHONPATH = {toxinidir}/src
Expand Down Expand Up @@ -31,6 +31,31 @@ commands =
--cov --cov-append {posargs}
coverage report

[testenv:{,ci-}pypy3]
setenv = PYTHONPATH = {toxinidir}/src
skip_install = True
recreate = True
deps =
-r{toxinidir}/test_requirements.txt
; a separate worker is required in ci due to https://foss.heptapod.net/pypy/pypy/-/issues/3317
; this seems to cause tox to wait forever
; remove this when pypy releases the bugfix
commands =
pip install -e .[d]
coverage erase
pytest tests --run-optional no_python2 \
--run-optional no_jupyter \
!ci: --numprocesses auto \
ci: --numprocesses 1 \
--cov {posargs}
pip install -e .[jupyter]
pytest tests --run-optional jupyter \
-m jupyter \
!ci: --numprocesses auto \
ci: --numprocesses 1 \
--cov --cov-append {posargs}
coverage report

[testenv:fuzz]
skip_install = True
deps =
Expand Down