pycodestyle 2.12.0__tar.gz → 2.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/PKG-INFO +2 -2
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.egg-info/PKG-INFO +2 -2
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.py +31 -22
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/setup.cfg +1 -1
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_E901.py +2 -2
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_pycodestyle.py +19 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/LICENSE +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/README.rst +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.egg-info/SOURCES.txt +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.egg-info/dependency_links.txt +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.egg-info/entry_points.txt +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.egg-info/not-zip-safe +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/pycodestyle.egg-info/top_level.txt +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/setup.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_E101.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_all.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_api.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_blank_lines.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_data.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_parser.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_self_doctests.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_shell.py +0 -0
- {pycodestyle-2.12.0 → pycodestyle-2.13.0}/tests/test_util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycodestyle
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.13.0
|
|
4
4
|
Summary: Python style guide checker
|
|
5
5
|
Home-page: https://pycodestyle.pycqa.org/
|
|
6
6
|
Author: Johann C. Rocholl
|
|
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
21
21
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
22
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
25
|
Description-Content-Type: text/x-rst
|
|
26
26
|
License-File: LICENSE
|
|
27
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycodestyle
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.13.0
|
|
4
4
|
Summary: Python style guide checker
|
|
5
5
|
Home-page: https://pycodestyle.pycqa.org/
|
|
6
6
|
Author: Johann C. Rocholl
|
|
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
21
21
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
22
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
25
|
Description-Content-Type: text/x-rst
|
|
26
26
|
License-File: LICENSE
|
|
27
27
|
|
|
@@ -68,7 +68,7 @@ if (
|
|
|
68
68
|
): # pragma: no cover (<py310)
|
|
69
69
|
tokenize._compile = lru_cache(tokenize._compile) # type: ignore
|
|
70
70
|
|
|
71
|
-
__version__ = '2.
|
|
71
|
+
__version__ = '2.13.0'
|
|
72
72
|
|
|
73
73
|
DEFAULT_EXCLUDE = '.svn,CVS,.bzr,.hg,.git,__pycache__,.tox'
|
|
74
74
|
DEFAULT_IGNORE = 'E121,E123,E126,E226,E24,E704,W503,W504'
|
|
@@ -135,6 +135,7 @@ OPERATOR_REGEX = re.compile(r'(?:[^,\s])(\s*)(?:[-+*/|!<=>%&^]+|:=)(\s*)')
|
|
|
135
135
|
LAMBDA_REGEX = re.compile(r'\blambda\b')
|
|
136
136
|
HUNK_REGEX = re.compile(r'^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@.*$')
|
|
137
137
|
STARTSWITH_DEF_REGEX = re.compile(r'^(async\s+def|def)\b')
|
|
138
|
+
STARTSWITH_GENERIC_REGEX = re.compile(r'^(async\s+def|def|class|type)\s+\w+\[')
|
|
138
139
|
STARTSWITH_TOP_LEVEL_REGEX = re.compile(r'^(async\s+def\s+|def\s+|class\s+|@)')
|
|
139
140
|
STARTSWITH_INDENT_STATEMENT_REGEX = re.compile(
|
|
140
141
|
r'^\s*({})\b'.format('|'.join(s.replace(' ', r'\s+') for s in (
|
|
@@ -233,9 +234,11 @@ def trailing_whitespace(physical_line):
|
|
|
233
234
|
W291: spam(1) \n#
|
|
234
235
|
W293: class Foo(object):\n \n bang = 12
|
|
235
236
|
"""
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
# Strip these trailing characters:
|
|
238
|
+
# - chr(10), newline
|
|
239
|
+
# - chr(13), carriage return
|
|
240
|
+
# - chr(12), form feed, ^L
|
|
241
|
+
physical_line = physical_line.rstrip('\n\r\x0c')
|
|
239
242
|
stripped = physical_line.rstrip(' \t\v')
|
|
240
243
|
if physical_line != stripped:
|
|
241
244
|
if stripped:
|
|
@@ -783,7 +786,6 @@ def whitespace_before_parameters(logical_line, tokens):
|
|
|
783
786
|
# Allow "return (a.foo for a in range(5))"
|
|
784
787
|
not keyword.iskeyword(prev_text) and
|
|
785
788
|
(
|
|
786
|
-
sys.version_info < (3, 9) or
|
|
787
789
|
# 3.12+: type is a soft keyword but no braces after
|
|
788
790
|
prev_text == 'type' or
|
|
789
791
|
not keyword.issoftkeyword(prev_text)
|
|
@@ -958,10 +960,8 @@ def missing_whitespace(logical_line, tokens):
|
|
|
958
960
|
# Allow argument unpacking: foo(*args, **kwargs).
|
|
959
961
|
if prev_type == tokenize.OP and prev_text in '}])' or (
|
|
960
962
|
prev_type != tokenize.OP and
|
|
961
|
-
prev_text not in KEYWORDS and
|
|
962
|
-
|
|
963
|
-
not keyword.issoftkeyword(prev_text)
|
|
964
|
-
)
|
|
963
|
+
prev_text not in KEYWORDS and
|
|
964
|
+
not keyword.issoftkeyword(prev_text)
|
|
965
965
|
):
|
|
966
966
|
need_space = None
|
|
967
967
|
elif text in WS_OPTIONAL_OPERATORS:
|
|
@@ -1020,12 +1020,13 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
|
|
|
1020
1020
|
E251: return magic(r = real, i = imag)
|
|
1021
1021
|
E252: def complex(real, image: float=0.0):
|
|
1022
1022
|
"""
|
|
1023
|
-
|
|
1023
|
+
paren_stack = []
|
|
1024
1024
|
no_space = False
|
|
1025
1025
|
require_space = False
|
|
1026
1026
|
prev_end = None
|
|
1027
1027
|
annotated_func_arg = False
|
|
1028
1028
|
in_def = bool(STARTSWITH_DEF_REGEX.match(logical_line))
|
|
1029
|
+
in_generic = bool(STARTSWITH_GENERIC_REGEX.match(logical_line))
|
|
1029
1030
|
|
|
1030
1031
|
message = "E251 unexpected spaces around keyword / parameter equals"
|
|
1031
1032
|
missing_message = "E252 missing whitespace around parameter equals"
|
|
@@ -1043,15 +1044,22 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
|
|
|
1043
1044
|
yield (prev_end, missing_message)
|
|
1044
1045
|
if token_type == tokenize.OP:
|
|
1045
1046
|
if text in '([':
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1047
|
+
paren_stack.append(text)
|
|
1048
|
+
# PEP 696 defaults always use spaced-style `=`
|
|
1049
|
+
# type A[T = default] = ...
|
|
1050
|
+
# def f[T = default](): ...
|
|
1051
|
+
# class C[T = default](): ...
|
|
1052
|
+
if in_generic and paren_stack == ['[']:
|
|
1053
|
+
annotated_func_arg = True
|
|
1054
|
+
elif text in ')]' and paren_stack:
|
|
1055
|
+
paren_stack.pop()
|
|
1056
|
+
# def f(arg: tp = default): ...
|
|
1057
|
+
elif text == ':' and in_def and paren_stack == ['(']:
|
|
1050
1058
|
annotated_func_arg = True
|
|
1051
|
-
elif
|
|
1059
|
+
elif len(paren_stack) == 1 and text == ',':
|
|
1052
1060
|
annotated_func_arg = False
|
|
1053
|
-
elif
|
|
1054
|
-
if annotated_func_arg and
|
|
1061
|
+
elif paren_stack and text == '=':
|
|
1062
|
+
if annotated_func_arg and len(paren_stack) == 1:
|
|
1055
1063
|
require_space = True
|
|
1056
1064
|
if start == prev_end:
|
|
1057
1065
|
yield (prev_end, missing_message)
|
|
@@ -1059,7 +1067,7 @@ def whitespace_around_named_parameter_equals(logical_line, tokens):
|
|
|
1059
1067
|
no_space = True
|
|
1060
1068
|
if start != prev_end:
|
|
1061
1069
|
yield (prev_end, message)
|
|
1062
|
-
if not
|
|
1070
|
+
if not paren_stack:
|
|
1063
1071
|
annotated_func_arg = False
|
|
1064
1072
|
|
|
1065
1073
|
prev_end = end
|
|
@@ -1910,9 +1918,7 @@ class Checker:
|
|
|
1910
1918
|
|
|
1911
1919
|
def run_check(self, check, argument_names):
|
|
1912
1920
|
"""Run a check plugin."""
|
|
1913
|
-
arguments = []
|
|
1914
|
-
for name in argument_names:
|
|
1915
|
-
arguments.append(getattr(self, name))
|
|
1921
|
+
arguments = [getattr(self, name) for name in argument_names]
|
|
1916
1922
|
return check(*arguments)
|
|
1917
1923
|
|
|
1918
1924
|
def init_checker_state(self, name, argument_names):
|
|
@@ -1949,7 +1955,10 @@ class Checker:
|
|
|
1949
1955
|
if token_type == tokenize.STRING:
|
|
1950
1956
|
text = mute_string(text)
|
|
1951
1957
|
elif token_type == FSTRING_MIDDLE: # pragma: >=3.12 cover
|
|
1952
|
-
|
|
1958
|
+
# fstring tokens are "unescaped" braces -- re-escape!
|
|
1959
|
+
brace_count = text.count('{') + text.count('}')
|
|
1960
|
+
text = 'x' * (len(text) + brace_count)
|
|
1961
|
+
end = (end[0], end[1] + brace_count)
|
|
1953
1962
|
if prev_row:
|
|
1954
1963
|
(start_row, start_col) = start
|
|
1955
1964
|
if prev_row != start_row: # different row
|
|
@@ -23,7 +23,7 @@ def lasting(self, duration=300):
|
|
|
23
23
|
'''
|
|
24
24
|
errors = errors_from_src(src)
|
|
25
25
|
if sys.version_info < (3, 12): # pragma: <3.12 cover
|
|
26
|
-
expected = ['E122:4:1'
|
|
26
|
+
expected = ['E122:4:1']
|
|
27
27
|
else: # pragma: >=3.12 cover
|
|
28
|
-
expected = ['E122:4:1', '
|
|
28
|
+
expected = ['E122:4:1', 'E901:5:1'] # noqa: E501
|
|
29
29
|
self.assertEqual(errors, expected)
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import sys
|
|
3
|
+
import tokenize
|
|
4
|
+
|
|
1
5
|
import pytest
|
|
2
6
|
|
|
7
|
+
from pycodestyle import Checker
|
|
3
8
|
from pycodestyle import expand_indent
|
|
4
9
|
from pycodestyle import mute_string
|
|
5
10
|
|
|
@@ -27,3 +32,17 @@ def test_expand_indent(s, expected):
|
|
|
27
32
|
)
|
|
28
33
|
def test_mute_string(s, expected):
|
|
29
34
|
assert mute_string(s) == expected
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_fstring_logical_line():
|
|
38
|
+
src = '''\
|
|
39
|
+
f'hello {{ {thing} }} world'
|
|
40
|
+
'''
|
|
41
|
+
checker = Checker(lines=src.splitlines())
|
|
42
|
+
checker.tokens = list(tokenize.generate_tokens(io.StringIO(src).readline))
|
|
43
|
+
checker.build_tokens_line()
|
|
44
|
+
|
|
45
|
+
if sys.version_info >= (3, 12): # pragma: >3.12 cover
|
|
46
|
+
assert checker.logical_line == "f'xxxxxxxxx{thing}xxxxxxxxx'"
|
|
47
|
+
else:
|
|
48
|
+
assert checker.logical_line == "f'xxxxxxxxxxxxxxxxxxxxxxxxx'"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|