Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
TomFryers committed Apr 22, 2022
2 parents 06b2587 + 8ed3e3d commit 54976a3
Show file tree
Hide file tree
Showing 17 changed files with 245 additions and 13 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/diff_shades.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,19 @@ jobs:
${{ matrix.baseline-analysis }} ${{ matrix.target-analysis }}
- name: Upload diff report
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.mode }}-diff.html
path: diff.html

- name: Upload baseline analysis
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.baseline-analysis }}
path: ${{ matrix.baseline-analysis }}

- name: Upload target analysis
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.target-analysis }}
path: ${{ matrix.target-analysis }}
Expand All @@ -135,7 +135,7 @@ jobs:
- name: Upload summary file (PR only)
if: github.event_name == 'pull_request' && matrix.mode == 'preview-changes'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: .pr-comment.json
path: .pr-comment.json
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@

### Parser

- [PEP 654](https://peps.python.org/pep-0654/#except) syntax (for example,
`except *ExceptionGroup:`) is now supported (#3016)

<!-- Changes to the parser or to version autodetection -->

### Performance
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,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]`.
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:

Expand Down
3 changes: 2 additions & 1 deletion docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,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]`.
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:

Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ myst-parser==0.16.1
Sphinx==4.5.0
sphinxcontrib-programoutput==0.17
sphinx_copybutton==0.5.0
furo==2022.3.4
furo==2022.4.7
2 changes: 1 addition & 1 deletion docs/usage_and_configuration/black_as_a_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ process every time you want to blacken a file.
## 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
Expand Down
4 changes: 2 additions & 2 deletions docs/usage_and_configuration/black_docker_image.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Black Docker image

Official _Black_ Docker images are available on Docker Hub:
https://hub.docker.com/r/pyfound/black
Official _Black_ Docker images are available on
[Docker Hub](https://hub.docker.com/r/pyfound/black).

_Black_ images with the following tags are available:

Expand Down
7 changes: 7 additions & 0 deletions src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,13 @@ def get_features_used( # noqa: C901
):
features.add(Feature.ANN_ASSIGN_EXTENDED_RHS)

elif (
n.type == syms.except_clause
and len(n.children) >= 2
and n.children[1].type == token.STAR
):
features.add(Feature.EXCEPT_STAR)

return features


Expand Down
9 changes: 9 additions & 0 deletions src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,15 @@ def normalize_invisible_parens(
node.insert_child(index, Leaf(token.LPAR, ""))
node.append_child(Leaf(token.RPAR, ""))
break
elif (
index == 1
and child.type == token.STAR
and node.type == syms.except_clause
):
# In except* (PEP 654), the star is actually part of
# of the keyword. So we need to skip the insertion of
# invisible parentheses to work more precisely.
continue

elif not (isinstance(child, Leaf) and is_multiline_string(child)):
wrap_in_parentheses(node, child, visible=False)
Expand Down
17 changes: 17 additions & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class TargetVersion(Enum):
PY38 = 8
PY39 = 9
PY310 = 10
PY311 = 11


class Feature(Enum):
Expand All @@ -47,6 +48,7 @@ class Feature(Enum):
PATTERN_MATCHING = 11
UNPACKING_ON_FLOW = 12
ANN_ASSIGN_EXTENDED_RHS = 13
EXCEPT_STAR = 14
FORCE_OPTIONAL_PARENTHESES = 50

# __future__ flags
Expand Down Expand Up @@ -116,6 +118,21 @@ class Feature(Enum):
Feature.ANN_ASSIGN_EXTENDED_RHS,
Feature.PATTERN_MATCHING,
},
TargetVersion.PY311: {
Feature.F_STRINGS,
Feature.NUMERIC_UNDERSCORES,
Feature.TRAILING_COMMA_IN_CALL,
Feature.TRAILING_COMMA_IN_DEF,
Feature.ASYNC_KEYWORDS,
Feature.FUTURE_ANNOTATIONS,
Feature.ASSIGNMENT_EXPRESSIONS,
Feature.RELAXED_DECORATORS,
Feature.POS_ONLY_ARGUMENTS,
Feature.UNPACKING_ON_FLOW,
Feature.ANN_ASSIGN_EXTENDED_RHS,
Feature.PATTERN_MATCHING,
Feature.EXCEPT_STAR,
},
}


Expand Down
4 changes: 4 additions & 0 deletions src/black/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa: C901
elif p.type == syms.sliceop:
return NO

elif p.type == syms.except_clause:
if t == token.STAR:
return NO

return SPACE


Expand Down
2 changes: 1 addition & 1 deletion src/blib2to3/Grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ try_stmt: ('try' ':' suite
with_stmt: 'with' asexpr_test (',' asexpr_test)* ':' suite

# NB compile.c makes sure that the default except clause is last
except_clause: 'except' [test [(',' | 'as') test]]
except_clause: 'except' ['*'] [test [(',' | 'as') test]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

# Backward compatibility cruft to support:
Expand Down
53 changes: 53 additions & 0 deletions tests/data/pep_654.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
try:
raise OSError("blah")
except* ExceptionGroup as e:
pass


try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except* ValueError:
pass

try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except* Exception:
pass
1 / 0
except Exception as e:
exc = e

try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except* TypeError as e:
tes = e
raise
except* ValueError as e:
ves = e
pass
except Exception as e:
exc = e

try:
try:
raise orig
except* (TypeError, ValueError) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e

try:
try:
raise orig
except* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e
111 changes: 111 additions & 0 deletions tests/data/pep_654_style.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
try:
raise OSError("blah")
except * ExceptionGroup as e:
pass


try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except *ValueError:
pass

try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except *(Exception):
pass
1 / 0
except Exception as e:
exc = e

try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except \
*TypeError as e:
tes = e
raise
except * ValueError as e:
ves = e
pass
except Exception as e:
exc = e

try:
try:
raise orig
except *(TypeError, ValueError, *OTHER_EXCEPTIONS) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e

try:
try:
raise orig
except\
* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e

# output

try:
raise OSError("blah")
except* ExceptionGroup as e:
pass


try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except* ValueError:
pass

try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except* (Exception):
pass
1 / 0
except Exception as e:
exc = e

try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except* TypeError as e:
tes = e
raise
except* ValueError as e:
ves = e
pass
except Exception as e:
exc = e

try:
try:
raise orig
except* (TypeError, ValueError, *OTHER_EXCEPTIONS) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e

try:
try:
raise orig
except* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e
6 changes: 6 additions & 0 deletions tests/test_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,12 @@ def test_get_features_used(self) -> None:
self.assertEqual(
black.get_features_used(node), {Feature.ANN_ASSIGN_EXTENDED_RHS}
)
node = black.lib2to3_parse("try: pass\nexcept Something: pass")
self.assertEqual(black.get_features_used(node), set())
node = black.lib2to3_parse("try: pass\nexcept (*Something,): pass")
self.assertEqual(black.get_features_used(node), set())
node = black.lib2to3_parse("try: pass\nexcept *Group: pass")
self.assertEqual(black.get_features_used(node), {Feature.EXCEPT_STAR})

def test_get_features_used_for_future_flags(self) -> None:
for src, features in [
Expand Down
12 changes: 12 additions & 0 deletions tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@
"parenthesized_context_managers",
]

PY311_CASES: List[str] = [
"pep_654",
"pep_654_style",
]

PREVIEW_CASES: List[str] = [
# string processing
"cantfit",
Expand Down Expand Up @@ -228,6 +233,13 @@ def test_patma_invalid() -> None:
exc_info.match("Cannot parse: 10:11")


@pytest.mark.parametrize("filename", PY311_CASES)
def test_python_311(filename: str) -> None:
source, expected = read_data(filename)
mode = black.Mode(target_versions={black.TargetVersion.PY311})
assert_format(source, expected, mode, minimum_version=(3, 11))


def test_python_2_hint() -> None:
with pytest.raises(black.parsing.InvalidInput) as exc_info:
assert_format("print 'daylily'", "print 'daylily'")
Expand Down
Loading

0 comments on commit 54976a3

Please sign in to comment.