Skip to content

Commit

Permalink
Support ast.TryStar and except* (#2891)
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Mar 25, 2024
1 parent 8afb4d4 commit 4b45d31
Show file tree
Hide file tree
Showing 26 changed files with 310 additions and 57 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ Semantic versioning in our case means:
- Fixes `ObjectInBaseClassesListViolation`, `UnpythonicGetterSetterViolation`,
`ImplicitInConditionViolation`, `RedundantSubscriptViolation`,
`TooLongCompareViolation` to include better error details
- Fixes `TooDeepNestingViolation` for `TryStar` and `Match` statements
- Fixes `TooLongTryBodyViolation` and `TooManyExceptCasesViolation`
to work for `TryStar` statements as well
- Fixes `UselessNodeViolation` to work with `TryStar`
- Fixes `DuplicateExceptionViolation` to work with `TryStar`
- Fixes `TryExceptMultipleReturnPathViolation` to work with `TryStar`
- Fixes `IncorrectExceptOrderViolation` to work with `TryStar`

### Misc

Expand Down
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ rules =
# 3.10
"sys_version_info < (3, 10)": py-lt-310
"sys_version_info >= (3, 10)": py-gte-310
# 3.11
"sys_version_info < (3, 11)": py-lt-311
"sys_version_info >= (3, 11)": py-gte-311
# 3.12
"sys_version_info < (3, 12)": py-lt-312
"sys_version_info >= (3, 12)": py-gte-312
Expand Down
6 changes: 3 additions & 3 deletions tests/test_visitors/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def assert_errors():
"""Helper function to assert visitor violations."""
def factory(
visitor: BaseVisitor,
errors: Sequence[str],
expected_errors: Sequence[str],
*,
ignored_types: _IgnoredTypes = None,
) -> None:
Expand All @@ -36,10 +36,10 @@ def factory(
else:
real_errors = visitor.violations

assert len(errors) == len(real_errors)
assert len(expected_errors) == len(real_errors)

for index, error in enumerate(real_errors):
assert error.code == errors[index].code
assert error.code == expected_errors[index].code
if isinstance(error, (ASTViolation, TokenizeViolation)):
assert error._node is not None # noqa: WPS437
assert error._location() != (0, 0) # noqa: WPS437
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from wemake_python_styleguide.compat.constants import PY311
from wemake_python_styleguide.violations.complexity import (
TooLongTryBodyViolation,
)
Expand All @@ -21,6 +22,13 @@
...
"""

try_star_except = """
try:
{0}
except* ValueError:
...
"""

try_except_with_else = """
try:
{0}
Expand Down Expand Up @@ -77,10 +85,16 @@
simple_try_except,
try_except_with_else,
full_except_with_else,
pytest.param(
try_star_except,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
])
def test_try_body_count_default(
assert_errors,
assert_error_text,
parse_ast_tree,
default_options,
code,
Expand All @@ -105,6 +119,13 @@ def test_try_body_count_default(
simple_try_except,
try_except_with_else,
full_except_with_else,
pytest.param(
try_star_except,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
])
def test_try_body_wrong_custom_options(
assert_errors,
Expand Down Expand Up @@ -137,6 +158,13 @@ def test_try_body_wrong_custom_options(
simple_try_except,
try_except_with_else,
full_except_with_else,
pytest.param(
try_star_except,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
])
def test_try_body_count_custom_options(
assert_errors,
Expand Down Expand Up @@ -165,6 +193,13 @@ def test_try_body_count_custom_options(
simple_try_except,
try_except_with_else,
full_except_with_else,
pytest.param(
try_star_except,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
])
def test_try_body_correct_default(
assert_errors,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from wemake_python_styleguide.compat.constants import PY311
from wemake_python_styleguide.violations.complexity import (
TooManyExceptCasesViolation,
)
Expand Down Expand Up @@ -56,15 +57,39 @@
...
"""

complex_try_star_except = """
try:
...
except* ValueError:
...
except* KeyError:
...
except* IndexError as exc:
...
except* TypeError:
...
"""


@pytest.mark.parametrize('code', [
complex_try_except,
pytest.param(
complex_try_star_except,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
])
def test_try_except_count_default(
assert_errors,
assert_error_text,
parse_ast_tree,
code,
default_options,
):
"""Testing that default settings raise a warning."""
tree = parse_ast_tree(complex_try_except)
tree = parse_ast_tree(code)

visitor = TryExceptVisitor(default_options, tree=tree)
visitor.run()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from wemake_python_styleguide.compat.constants import PY310, PY311
from wemake_python_styleguide.visitors.ast.complexity.offset import (
OffsetVisitor,
TooDeepNestingViolation,
Expand Down Expand Up @@ -40,6 +41,14 @@ def container():
raise
"""

nested_try_star = """
def container():
try:
...
except* ...:
...
"""

nested_with = """
def container():
with open('some') as temp:
Expand All @@ -52,6 +61,13 @@ def container():
continue
"""

nested_match = """
def container():
match ...:
case 1:
...
"""

real_nested_values = """
def container():
if some > 1:
Expand All @@ -76,8 +92,22 @@ async def update_control():
nested_for,
nested_try,
nested_try2,
pytest.param(
nested_try_star,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in 3.11',
),
),
nested_with,
nested_while,
pytest.param(
nested_match,
marks=pytest.mark.skipif(
not PY310,
reason='Pattern matching was added in 3.10',
),
),
])
def test_nested_offset(
assert_errors,
Expand Down Expand Up @@ -119,8 +149,10 @@ def test_nested_offset_regression320(
(nested_for, 1),
(nested_try, 2),
(nested_try2, 4),
(nested_try_star, 2),
(nested_with, 1),
(nested_while, 1),
(nested_match, 1),
])
def test_nested_offset_errors(
monkeypatch,
Expand All @@ -132,6 +164,11 @@ def test_nested_offset_errors(
mode,
):
"""Testing that nested expressions are restricted."""
if code == nested_try_star and not PY311:
pytest.skip(reason='ExceptionGroup was added in 3.11')
if code == nested_match and not PY310:
pytest.skip(reason='Pattern matching was added in 3.10')

tree = parse_ast_tree(mode(code))

monkeypatch.setattr(OffsetVisitor, '_max_offset_blocks', 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from wemake_python_styleguide.compat.constants import PY311
from wemake_python_styleguide.violations.best_practices import (
DuplicateExceptionViolation,
)
Expand Down Expand Up @@ -98,6 +99,15 @@
...
"""

wrong_simple_star = """
try:
...
except* ValueError as ex:
...
except* ValueError:
...
"""


@pytest.mark.parametrize('code', [
correct_bare_except,
Expand Down Expand Up @@ -128,6 +138,13 @@ def test_correct_exceptions(
wrong_simple,
wrong_single_tuple,
wrong_different_tuples,
pytest.param(
wrong_simple_star,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
])
def test_duplicate_exceptions(
assert_errors,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from wemake_python_styleguide.compat.constants import PY311
from wemake_python_styleguide.violations.best_practices import (
IncorrectExceptOrderViolation,
)
Expand All @@ -16,6 +17,15 @@
...
"""

exception_star_template = """
try:
...
except {0}:
...
except {1}:
...
"""

custom_exception_template1 = """
try:
...
Expand All @@ -41,6 +51,13 @@

@pytest.mark.parametrize('code', [
exception_template,
pytest.param(
exception_star_template,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
custom_exception_template1,
custom_exception_template2,
])
Expand All @@ -67,6 +84,13 @@ def test_correct_order_exception(

@pytest.mark.parametrize('code', [
exception_template,
pytest.param(
exception_star_template,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
custom_exception_template1,
custom_exception_template2,
])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from wemake_python_styleguide.compat.constants import PY311
from wemake_python_styleguide.violations.best_practices import (
TryExceptMultipleReturnPathViolation,
)
Expand Down Expand Up @@ -185,6 +186,17 @@ def function():
{0}
"""

wrong_try_star_finally = """
def function():
for _ in range(10):
try:
{0}
except* TypeError:
...
finally:
{0}
"""

wrong_except_finally = """
def function():
for _ in range(10):
Expand Down Expand Up @@ -372,6 +384,13 @@ def function():
wrong_multiple_except_finally3,
wrong_else_finally,
wrong_try_finally,
pytest.param(
wrong_try_star_finally,
marks=pytest.mark.skipif(
not PY311,
reason='ExceptionGroup was added in python 3.11',
),
),
wrong_try_else,
wrong_try_except_else,
wrong_all1,
Expand Down

0 comments on commit 4b45d31

Please sign in to comment.