Skip to content

Commit b86cf9d

Browse files
authored
Merge pull request #23 from xoryman/master
Fix bug fix literal string annotations
2 parents 2080fe1 + 20c9170 commit b86cf9d

File tree

10 files changed

+58
-32
lines changed

10 files changed

+58
-32
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
runs-on: ubuntu-latest
1010
strategy:
1111
matrix:
12-
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
12+
python-version: ['3.9', '3.10', '3.11']
1313
steps:
1414
- uses: actions/checkout@v2
1515
- name: Set up Python ${{ matrix.python-version }}

.github/workflows/build_pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
runs-on: ubuntu-latest
1010
strategy:
1111
matrix:
12-
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
12+
python-version: ['3.9', '3.10', '3.11']
1313
steps:
1414
- uses: actions/checkout@v2
1515
- name: Set up Python ${{ matrix.python-version }}

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
13+
python-version: ['3.9', '3.10', '3.11']
1414
steps:
1515
- uses: actions/checkout@v2
1616
- name: Set up Python ${{ matrix.python-version }}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.0.8'
1+
__version__ = '0.1.0'

flake8_annotations_complexity/ast_helpers.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,57 @@
11
import ast
2-
import sys
2+
from logging import getLogger
33
from typing import List, Tuple, Any
44

5+
logger = getLogger(__name__)
56

6-
def get_annotation_complexity(annotation_node, default_complexity: int = 1) -> int:
7+
8+
def get_annotation_complexity(annotation_node) -> int:
9+
"""
10+
Recursively counts complexity of annotation nodes.
11+
12+
When annotations are written as strings,
13+
we additionally parse them to ``ast`` nodes.
14+
"""
715
if isinstance(annotation_node, ast.Str):
16+
# try to parse string-wrapped annotations
817
try:
918
annotation_node = ast.parse(annotation_node.s).body[0].value # type: ignore
10-
except (SyntaxError, IndexError):
11-
return default_complexity
12-
complexity = default_complexity
19+
except Exception as exc:
20+
logger.debug(f'Cannot parse string-wrapped annotation: {exc!r}')
21+
return 1
22+
1323
if isinstance(annotation_node, ast.Subscript):
14-
if sys.version_info >= (3, 9):
15-
complexity = 1 + get_annotation_complexity(annotation_node.slice)
16-
else:
17-
complexity = 1 + get_annotation_complexity(annotation_node.slice.value) # type: ignore
18-
if isinstance(annotation_node, ast.Tuple):
19-
complexity = max((get_annotation_complexity(n) for n in annotation_node.elts), default=1)
20-
return complexity
24+
return 1 + get_annotation_complexity(annotation_node.slice)
25+
26+
if isinstance(annotation_node, (ast.Tuple, ast.List)):
27+
return max((get_annotation_complexity(n) for n in annotation_node.elts), default=1)
28+
29+
return 1
2130

2231

2332
def get_annotation_len(annotation_node) -> int:
24-
annotation_len = 0
33+
"""
34+
Recursively counts length of annotation nodes.
35+
36+
When annotations are written as strings,
37+
we additionally parse them to ``ast`` nodes.
38+
"""
2539
if isinstance(annotation_node, ast.Str):
40+
# try to parse string-wrapped annotations
2641
try:
2742
annotation_node = ast.parse(annotation_node.s).body[0].value # type: ignore
28-
except (SyntaxError, IndexError):
29-
return annotation_len
43+
except Exception as exc:
44+
logger.debug(f'Cannot parse string-wrapped annotation: {exc!r}')
45+
return 0
46+
3047
if isinstance(annotation_node, ast.Subscript):
3148
try:
32-
if sys.version_info >= (3, 9):
33-
annotation_len = len(annotation_node.slice.elts) # type: ignore
34-
else:
35-
annotation_len = len(annotation_node.slice.value.elts) # type: ignore
49+
return len(annotation_node.slice.elts) # type: ignore
3650
except AttributeError:
37-
annotation_len = 0
38-
return annotation_len
51+
logger.debug('Attribute error on annotation length counting')
52+
return 0
53+
54+
return 0
3955

4056

4157
def validate_annotations_in_ast_node(

requirements_dev.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pytest-cov==3.0.0
33
pydocstyle==6.1.1
44
flake8==4.0.1
55
flake8-2020==1.6.0
6-
flake8-annotations-complexity==0.0.6
76
flake8-blind-except==0.2.0
87
flake8-broken-line==0.4.0
98
flake8-bugbear==22.1.11

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
[flake8]
22
max-complexity = 8
33
max-line-length = 120
4-
ignore = W503, P103, D
4+
ignore = W503, P103, D, B902
55
exclude = node_modules,env,venv,venv36,tests
66
max-annotations-complexity = 4
7+
max-returns-amount = 4
78
var_names_exclude_pathes = node_modules,env,venv,venv36
89
assert_allowed_in_pathes = tests,migrations,env,venv,venv36
910
adjustable-default-max-complexity = 8

setup.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,13 @@ def get_long_description() -> str:
3030
'Topic :: Software Development :: Libraries :: Python Modules',
3131
'Topic :: Software Development :: Quality Assurance',
3232
'Programming Language :: Python',
33-
'Programming Language :: Python :: 3.7',
34-
'Programming Language :: Python :: 3.8',
3533
'Programming Language :: Python :: 3.9',
3634
'Programming Language :: Python :: 3.10',
3735
'Programming Language :: Python :: 3.11',
3836
],
3937
long_description=get_long_description(),
4038
long_description_content_type='text/markdown',
41-
python_requires='>=3.7',
39+
python_requires='>=3.9',
4240
packages=find_packages(),
4341
include_package_data=True,
4442
keywords='flake8 annotations',

tests/test_annotations_complexity.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ def test_ok_for_unannotated_file():
2020
def test_ok_for_dynamic_annotations_file():
2121
errors = run_validator_for_test_file('dynamic_annotations.py')
2222
assert len(errors) == 1
23+
errors = run_validator_for_test_file('dynamic_annotations.py', max_annotations_complexity=2)
24+
assert len(errors) == 1
2325
errors = run_validator_for_test_file('dynamic_annotations.py', max_annotations_complexity=1)
24-
assert len(errors) == 2
26+
assert len(errors) == 3
2527

2628

2729
def test_ok_for_string_annotations_file():
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
from typing import List, Dict, Optional, Tuple
1+
from typing import (
2+
List,
3+
Dict,
4+
Optional,
5+
Tuple,
6+
Literal,
7+
)
28

39

410
def foo() -> List[int]:
@@ -7,3 +13,7 @@ def foo() -> List[int]:
713

814
def bar(arg1: str, arg2: Tuple[List[int], Optional[Dict[str, int]]]) -> int:
915
return 1
16+
17+
18+
def gaz() -> Literal['regular', 'raise', 'is']:
19+
raise Exception

0 commit comments

Comments
 (0)