flake8-assertive 2.1.0__tar.gz → 2.2.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.
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/CHANGELOG.rst +6 -0
- {flake8-assertive-2.1.0/flake8_assertive.egg-info → flake8_assertive-2.2.0}/PKG-INFO +22 -29
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/README.rst +6 -0
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0/flake8_assertive.egg-info}/PKG-INFO +22 -29
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/SOURCES.txt +2 -1
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/entry_points.txt +0 -1
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.py +87 -87
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/setup.cfg +8 -5
- flake8_assertive-2.2.0/setup.py +10 -0
- flake8_assertive-2.2.0/tests/test_checker.py +204 -0
- flake8-assertive-2.1.0/setup.py +0 -11
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/LICENSE +0 -0
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/MANIFEST.in +0 -0
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/dependency_links.txt +0 -0
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/requires.txt +0 -0
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/top_level.txt +0 -0
- {flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/zip-safe +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: flake8-assertive
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Flake8 unittest assert method checker
|
|
5
5
|
Home-page: https://github.com/jparise/flake8-assertive
|
|
6
6
|
Author: Jon Parise
|
|
@@ -9,7 +9,6 @@ License: MIT
|
|
|
9
9
|
Project-URL: Source Code, https://github.com/jparise/flake8-assertive
|
|
10
10
|
Project-URL: Issue Tracker, https://github.com/jparise/flake8-assertive/issues
|
|
11
11
|
Keywords: flake8 testing unittest assert
|
|
12
|
-
Platform: UNKNOWN
|
|
13
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
13
|
Classifier: Environment :: Console
|
|
15
14
|
Classifier: Framework :: Flake8
|
|
@@ -17,16 +16,20 @@ Classifier: Intended Audience :: Developers
|
|
|
17
16
|
Classifier: License :: OSI Approved :: MIT License
|
|
18
17
|
Classifier: Programming Language :: Python
|
|
19
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
23
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
24
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
25
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
26
26
|
Classifier: Topic :: Software Development :: Testing
|
|
27
27
|
Classifier: Topic :: Software Development :: Testing :: Unit
|
|
28
|
-
Requires-Python: >=3.
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
29
|
License-File: LICENSE
|
|
30
|
+
Requires-Dist: flake8>=3.0.0
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
Dynamic: requires-dist
|
|
30
33
|
|
|
31
34
|
=================================
|
|
32
35
|
Flake8 Unittest Assertion Checker
|
|
@@ -195,34 +198,26 @@ values of ``a`` and ``b``.
|
|
|
195
198
|
|
|
196
199
|
Suggested by: `Serhiy Storchaka <https://twitter.com/SerhiyStorchaka>`_
|
|
197
200
|
|
|
201
|
+
Alternatives
|
|
202
|
+
------------
|
|
203
|
+
|
|
204
|
+
- `Teyit <https://github.com/isidentical/teyit>`_ is a Python unit test formatter that
|
|
205
|
+
can perform similar assertion transformations.
|
|
206
|
+
|
|
198
207
|
.. |PyPI Version| image:: https://img.shields.io/pypi/v/flake8-assertive.svg
|
|
199
208
|
:target: https://pypi.python.org/pypi/flake8-assertive
|
|
200
209
|
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/flake8-assertive.svg
|
|
201
210
|
:target: https://pypi.python.org/pypi/flake8-assertive
|
|
202
211
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
206
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
207
|
-
in the Software without restriction, including without limitation the rights
|
|
208
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
209
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
210
|
-
furnished to do so, subject to the following conditions:
|
|
211
|
-
|
|
212
|
-
The above copyright notice and this permission notice shall be included in all
|
|
213
|
-
copies or substantial portions of the Software.
|
|
214
|
-
|
|
215
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
216
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
217
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
218
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
219
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
220
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
221
|
-
SOFTWARE.
|
|
222
|
-
|
|
212
|
+
=======
|
|
223
213
|
Changes
|
|
224
214
|
=======
|
|
225
215
|
|
|
216
|
+
2.2.0 (2025-10-11)
|
|
217
|
+
------------------
|
|
218
|
+
|
|
219
|
+
* Drop support for Python 3.7, 3.8, and 3.9. Python 3.10+ is now required.
|
|
220
|
+
|
|
226
221
|
2.1.0 (2022-03-15)
|
|
227
222
|
------------------
|
|
228
223
|
|
|
@@ -279,5 +274,3 @@ Changes
|
|
|
279
274
|
------------------
|
|
280
275
|
|
|
281
276
|
* Initial beta release
|
|
282
|
-
|
|
283
|
-
|
|
@@ -165,6 +165,12 @@ values of ``a`` and ``b``.
|
|
|
165
165
|
|
|
166
166
|
Suggested by: `Serhiy Storchaka <https://twitter.com/SerhiyStorchaka>`_
|
|
167
167
|
|
|
168
|
+
Alternatives
|
|
169
|
+
------------
|
|
170
|
+
|
|
171
|
+
- `Teyit <https://github.com/isidentical/teyit>`_ is a Python unit test formatter that
|
|
172
|
+
can perform similar assertion transformations.
|
|
173
|
+
|
|
168
174
|
.. |PyPI Version| image:: https://img.shields.io/pypi/v/flake8-assertive.svg
|
|
169
175
|
:target: https://pypi.python.org/pypi/flake8-assertive
|
|
170
176
|
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/flake8-assertive.svg
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: flake8-assertive
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Flake8 unittest assert method checker
|
|
5
5
|
Home-page: https://github.com/jparise/flake8-assertive
|
|
6
6
|
Author: Jon Parise
|
|
@@ -9,7 +9,6 @@ License: MIT
|
|
|
9
9
|
Project-URL: Source Code, https://github.com/jparise/flake8-assertive
|
|
10
10
|
Project-URL: Issue Tracker, https://github.com/jparise/flake8-assertive/issues
|
|
11
11
|
Keywords: flake8 testing unittest assert
|
|
12
|
-
Platform: UNKNOWN
|
|
13
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
13
|
Classifier: Environment :: Console
|
|
15
14
|
Classifier: Framework :: Flake8
|
|
@@ -17,16 +16,20 @@ Classifier: Intended Audience :: Developers
|
|
|
17
16
|
Classifier: License :: OSI Approved :: MIT License
|
|
18
17
|
Classifier: Programming Language :: Python
|
|
19
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
23
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
24
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
25
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
26
26
|
Classifier: Topic :: Software Development :: Testing
|
|
27
27
|
Classifier: Topic :: Software Development :: Testing :: Unit
|
|
28
|
-
Requires-Python: >=3.
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
29
|
License-File: LICENSE
|
|
30
|
+
Requires-Dist: flake8>=3.0.0
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
Dynamic: requires-dist
|
|
30
33
|
|
|
31
34
|
=================================
|
|
32
35
|
Flake8 Unittest Assertion Checker
|
|
@@ -195,34 +198,26 @@ values of ``a`` and ``b``.
|
|
|
195
198
|
|
|
196
199
|
Suggested by: `Serhiy Storchaka <https://twitter.com/SerhiyStorchaka>`_
|
|
197
200
|
|
|
201
|
+
Alternatives
|
|
202
|
+
------------
|
|
203
|
+
|
|
204
|
+
- `Teyit <https://github.com/isidentical/teyit>`_ is a Python unit test formatter that
|
|
205
|
+
can perform similar assertion transformations.
|
|
206
|
+
|
|
198
207
|
.. |PyPI Version| image:: https://img.shields.io/pypi/v/flake8-assertive.svg
|
|
199
208
|
:target: https://pypi.python.org/pypi/flake8-assertive
|
|
200
209
|
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/flake8-assertive.svg
|
|
201
210
|
:target: https://pypi.python.org/pypi/flake8-assertive
|
|
202
211
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
206
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
207
|
-
in the Software without restriction, including without limitation the rights
|
|
208
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
209
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
210
|
-
furnished to do so, subject to the following conditions:
|
|
211
|
-
|
|
212
|
-
The above copyright notice and this permission notice shall be included in all
|
|
213
|
-
copies or substantial portions of the Software.
|
|
214
|
-
|
|
215
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
216
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
217
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
218
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
219
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
220
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
221
|
-
SOFTWARE.
|
|
222
|
-
|
|
212
|
+
=======
|
|
223
213
|
Changes
|
|
224
214
|
=======
|
|
225
215
|
|
|
216
|
+
2.2.0 (2025-10-11)
|
|
217
|
+
------------------
|
|
218
|
+
|
|
219
|
+
* Drop support for Python 3.7, 3.8, and 3.9. Python 3.10+ is now required.
|
|
220
|
+
|
|
226
221
|
2.1.0 (2022-03-15)
|
|
227
222
|
------------------
|
|
228
223
|
|
|
@@ -279,5 +274,3 @@ Changes
|
|
|
279
274
|
------------------
|
|
280
275
|
|
|
281
276
|
* Initial beta release
|
|
282
|
-
|
|
283
|
-
|
|
@@ -11,4 +11,5 @@ flake8_assertive.egg-info/dependency_links.txt
|
|
|
11
11
|
flake8_assertive.egg-info/entry_points.txt
|
|
12
12
|
flake8_assertive.egg-info/requires.txt
|
|
13
13
|
flake8_assertive.egg-info/top_level.txt
|
|
14
|
-
flake8_assertive.egg-info/zip-safe
|
|
14
|
+
flake8_assertive.egg-info/zip-safe
|
|
15
|
+
tests/test_checker.py
|
|
@@ -24,29 +24,31 @@ import ast
|
|
|
24
24
|
import fnmatch
|
|
25
25
|
import re
|
|
26
26
|
|
|
27
|
-
__all__ = [
|
|
28
|
-
__version__ =
|
|
27
|
+
__all__ = ["Checker"]
|
|
28
|
+
__version__ = "2.2.0"
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def is_constant(node, obj):
|
|
37
|
-
return isinstance(node, ast.Name) and node.id == str(obj)
|
|
31
|
+
Constant = ast.Constant if hasattr(ast, "Constant") else ast.NameConstant
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_constant(node, obj):
|
|
35
|
+
return isinstance(node, Constant) and node.value is obj
|
|
38
36
|
|
|
39
37
|
|
|
40
38
|
def is_function_call(node, name):
|
|
41
|
-
return (
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
return (
|
|
40
|
+
isinstance(node, ast.Call)
|
|
41
|
+
and isinstance(node.func, ast.Name)
|
|
42
|
+
and node.func.id == name
|
|
43
|
+
)
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def is_assert_method_call(node):
|
|
47
|
-
return (
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
return (
|
|
48
|
+
isinstance(node, ast.Call)
|
|
49
|
+
and isinstance(node.func, ast.Attribute)
|
|
50
|
+
and node.func.attr.startswith("assert")
|
|
51
|
+
)
|
|
50
52
|
|
|
51
53
|
|
|
52
54
|
def args(node):
|
|
@@ -63,18 +65,20 @@ def wrap_deprecated(func, name):
|
|
|
63
65
|
check function doesn't yield any errors of its own, this function will
|
|
64
66
|
yield an A503 error that includes the new name of the deprecated method.
|
|
65
67
|
"""
|
|
68
|
+
|
|
66
69
|
def wrapper(self, node):
|
|
67
70
|
for error in func(self, node):
|
|
68
71
|
yield error
|
|
69
72
|
else:
|
|
70
|
-
yield self.error(node,
|
|
73
|
+
yield self.error(node, "A503", func=name, name=node.func.attr)
|
|
74
|
+
|
|
71
75
|
return wrapper
|
|
72
76
|
|
|
73
77
|
|
|
74
|
-
class Checker
|
|
78
|
+
class Checker:
|
|
75
79
|
"""Unittest assert method checker"""
|
|
76
80
|
|
|
77
|
-
name =
|
|
81
|
+
name = "assertive"
|
|
78
82
|
version = __version__
|
|
79
83
|
pattern = None
|
|
80
84
|
snakecase = False
|
|
@@ -92,16 +96,18 @@ class Checker(object):
|
|
|
92
96
|
@classmethod
|
|
93
97
|
def add_options(cls, parser):
|
|
94
98
|
parser.add_option(
|
|
95
|
-
|
|
99
|
+
"--assertive-snakecase",
|
|
96
100
|
help="Use snake_case assert method names ('assert_true()')",
|
|
97
|
-
action=
|
|
101
|
+
action="store_true",
|
|
98
102
|
default=False,
|
|
99
|
-
parse_from_config=True
|
|
103
|
+
parse_from_config=True,
|
|
104
|
+
)
|
|
100
105
|
parser.add_option(
|
|
101
|
-
|
|
106
|
+
"--assertive-test-pattern",
|
|
102
107
|
help="fnmatch() pattern for identifying unittest test files",
|
|
103
108
|
default=None,
|
|
104
|
-
parse_from_config=True
|
|
109
|
+
parse_from_config=True,
|
|
110
|
+
)
|
|
105
111
|
|
|
106
112
|
@classmethod
|
|
107
113
|
def parse_options(cls, options):
|
|
@@ -110,8 +116,8 @@ class Checker(object):
|
|
|
110
116
|
|
|
111
117
|
def error(self, node, code, func, **kwargs):
|
|
112
118
|
if self.snakecase:
|
|
113
|
-
func = re.sub(r
|
|
114
|
-
message = code +
|
|
119
|
+
func = re.sub(r"([A-Z])", r"_\1", func).lower()
|
|
120
|
+
message = code + " " + getattr(self, code).format(func=func, **kwargs)
|
|
115
121
|
return (node.lineno, node.col_offset, message, self)
|
|
116
122
|
|
|
117
123
|
def run(self):
|
|
@@ -122,124 +128,118 @@ class Checker(object):
|
|
|
122
128
|
# Visit all of the assert method calls in the tree.
|
|
123
129
|
for node in ast.walk(self.tree):
|
|
124
130
|
if is_assert_method_call(node):
|
|
125
|
-
name = node.func.attr.lower().replace(
|
|
126
|
-
func = getattr(self,
|
|
131
|
+
name = node.func.attr.lower().replace("_", "")
|
|
132
|
+
func = getattr(self, "check_" + name, None)
|
|
127
133
|
if func is not None:
|
|
128
134
|
for error in func(node):
|
|
129
135
|
yield error
|
|
130
136
|
|
|
131
137
|
def check_assertequal(self, node):
|
|
132
138
|
if any(arg for arg in args(node) if is_constant(arg, None)):
|
|
133
|
-
yield self.error(node,
|
|
139
|
+
yield self.error(node, "A502", "assertIsNone", obj=None)
|
|
134
140
|
elif any(arg for arg in args(node) if is_constant(arg, True)):
|
|
135
|
-
yield self.error(node,
|
|
141
|
+
yield self.error(node, "A502", "assertTrue", obj=True)
|
|
136
142
|
elif any(arg for arg in args(node) if is_constant(arg, False)):
|
|
137
|
-
yield self.error(node,
|
|
138
|
-
elif any(arg for arg in args(node) if is_function_call(arg,
|
|
139
|
-
yield self.error(
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
yield self.error(node, "A502", "assertFalse", obj=False)
|
|
144
|
+
elif any(arg for arg in args(node) if is_function_call(arg, "round")):
|
|
145
|
+
yield self.error(
|
|
146
|
+
node, "A501", "built-in rounding of assertAlmostEqual", op="round"
|
|
147
|
+
)
|
|
142
148
|
|
|
143
149
|
def check_assertalmostequal(self, node):
|
|
144
|
-
if any(arg for arg in args(node) if is_function_call(arg,
|
|
145
|
-
yield self.error(
|
|
146
|
-
|
|
147
|
-
|
|
150
|
+
if any(arg for arg in args(node) if is_function_call(arg, "round")):
|
|
151
|
+
yield self.error(
|
|
152
|
+
node, "A501", "built-in rounding of assertAlmostEqual", op="round"
|
|
153
|
+
)
|
|
148
154
|
|
|
149
155
|
def check_assertnotequal(self, node):
|
|
150
156
|
if any(arg for arg in args(node) if is_constant(arg, None)):
|
|
151
|
-
yield self.error(node,
|
|
157
|
+
yield self.error(node, "A502", "assertIsNotNone", obj=None)
|
|
152
158
|
elif any(arg for arg in args(node) if is_constant(arg, True)):
|
|
153
|
-
yield self.error(node,
|
|
159
|
+
yield self.error(node, "A502", "assertFalse", obj=True)
|
|
154
160
|
elif any(arg for arg in args(node) if is_constant(arg, False)):
|
|
155
|
-
yield self.error(node,
|
|
156
|
-
elif any(arg for arg in args(node) if is_function_call(arg,
|
|
157
|
-
yield self.error(
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
yield self.error(node, "A502", "assertTrue", obj=False)
|
|
162
|
+
elif any(arg for arg in args(node) if is_function_call(arg, "round")):
|
|
163
|
+
yield self.error(
|
|
164
|
+
node, "A501", "built-in rounding of assertNotAlmostEqual", op="round"
|
|
165
|
+
)
|
|
160
166
|
|
|
161
167
|
def check_assertnotalmostequal(self, node):
|
|
162
|
-
if any(arg for arg in args(node) if is_function_call(arg,
|
|
163
|
-
yield self.error(
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
if any(arg for arg in args(node) if is_function_call(arg, "round")):
|
|
169
|
+
yield self.error(
|
|
170
|
+
node, "A501", "built-in rounding of assertNotAlmostEqual", op="round"
|
|
171
|
+
)
|
|
166
172
|
|
|
167
173
|
def check_asserttrue(self, node):
|
|
168
174
|
if len(node.args) > 1:
|
|
169
|
-
yield self.error(node,
|
|
175
|
+
yield self.error(node, "A504", "assertTrue")
|
|
170
176
|
arg = next(args(node), None)
|
|
171
177
|
if arg and isinstance(arg, ast.Compare) and len(arg.ops) == 1:
|
|
172
178
|
op = arg.ops[0]
|
|
173
179
|
if isinstance(op, ast.In):
|
|
174
|
-
yield self.error(node,
|
|
180
|
+
yield self.error(node, "A501", "assertIn", op="in")
|
|
175
181
|
elif isinstance(op, ast.NotIn):
|
|
176
|
-
yield self.error(node,
|
|
182
|
+
yield self.error(node, "A501", "assertNotIn", op="in")
|
|
177
183
|
elif isinstance(op, ast.Is):
|
|
178
184
|
if is_constant(arg.comparators[0], None):
|
|
179
|
-
yield self.error(node,
|
|
185
|
+
yield self.error(node, "A502", "assertIsNone", obj=None)
|
|
180
186
|
else:
|
|
181
|
-
yield self.error(node,
|
|
187
|
+
yield self.error(node, "A501", "assertIs", op="is")
|
|
182
188
|
elif isinstance(op, ast.IsNot):
|
|
183
189
|
if is_constant(arg.comparators[0], None):
|
|
184
|
-
yield self.error(node,
|
|
190
|
+
yield self.error(node, "A502", "assertIsNotNone", obj=None)
|
|
185
191
|
else:
|
|
186
|
-
yield self.error(node,
|
|
192
|
+
yield self.error(node, "A501", "assertIsNot", op="is")
|
|
187
193
|
elif isinstance(op, ast.Eq):
|
|
188
|
-
yield self.error(node,
|
|
194
|
+
yield self.error(node, "A500", "assertEqual", op="==")
|
|
189
195
|
elif isinstance(op, ast.NotEq):
|
|
190
|
-
yield self.error(node,
|
|
196
|
+
yield self.error(node, "A500", "assertNotEqual", op="!=")
|
|
191
197
|
elif isinstance(op, ast.Lt):
|
|
192
|
-
yield self.error(node,
|
|
198
|
+
yield self.error(node, "A500", "assertLess", op="<")
|
|
193
199
|
elif isinstance(op, ast.LtE):
|
|
194
|
-
yield self.error(node,
|
|
200
|
+
yield self.error(node, "A500", "assertLessEqual", op="<=")
|
|
195
201
|
elif isinstance(op, ast.Gt):
|
|
196
|
-
yield self.error(node,
|
|
202
|
+
yield self.error(node, "A500", "assertGreater", op=">")
|
|
197
203
|
elif isinstance(op, ast.GtE):
|
|
198
|
-
yield self.error(node,
|
|
199
|
-
elif is_function_call(arg,
|
|
200
|
-
yield self.error(
|
|
201
|
-
node, 'A501', 'assertIsInstance', op='isinstance()')
|
|
204
|
+
yield self.error(node, "A500", "assertGreaterEqual", op=">=")
|
|
205
|
+
elif is_function_call(arg, "isinstance"):
|
|
206
|
+
yield self.error(node, "A501", "assertIsInstance", op="isinstance()")
|
|
202
207
|
|
|
203
208
|
def check_assertfalse(self, node):
|
|
204
209
|
if len(node.args) > 1:
|
|
205
|
-
yield self.error(node,
|
|
210
|
+
yield self.error(node, "A504", "assertFalse")
|
|
206
211
|
arg = next(args(node), None)
|
|
207
212
|
if arg and isinstance(arg, ast.Compare) and len(arg.ops) == 1:
|
|
208
213
|
op = arg.ops[0]
|
|
209
214
|
if isinstance(op, ast.In):
|
|
210
|
-
yield self.error(node,
|
|
215
|
+
yield self.error(node, "A501", "assertNotIn", op="in")
|
|
211
216
|
elif isinstance(op, ast.NotIn):
|
|
212
|
-
yield self.error(node,
|
|
217
|
+
yield self.error(node, "A501", "assertIn", op="in")
|
|
213
218
|
elif isinstance(op, ast.Is):
|
|
214
219
|
if is_constant(arg.comparators[0], None):
|
|
215
|
-
yield self.error(node,
|
|
220
|
+
yield self.error(node, "A502", "assertIsNotNone", obj=None)
|
|
216
221
|
else:
|
|
217
|
-
yield self.error(node,
|
|
222
|
+
yield self.error(node, "A501", "assertIsNot", op="is")
|
|
218
223
|
elif isinstance(op, ast.IsNot):
|
|
219
224
|
if is_constant(arg.comparators[0], None):
|
|
220
|
-
yield self.error(node,
|
|
225
|
+
yield self.error(node, "A502", "assertIsNone", obj=None)
|
|
221
226
|
else:
|
|
222
|
-
yield self.error(node,
|
|
227
|
+
yield self.error(node, "A501", "assertIs", op="is")
|
|
223
228
|
elif isinstance(op, ast.Eq):
|
|
224
|
-
yield self.error(node,
|
|
229
|
+
yield self.error(node, "A500", "assertNotEqual", op="==")
|
|
225
230
|
elif isinstance(op, ast.NotEq):
|
|
226
|
-
yield self.error(node,
|
|
227
|
-
elif is_function_call(arg,
|
|
228
|
-
yield self.error(
|
|
229
|
-
node, 'A501', 'assertNotIsInstance', op='isinstance()')
|
|
231
|
+
yield self.error(node, "A500", "assertEqual", op="!=")
|
|
232
|
+
elif is_function_call(arg, "isinstance"):
|
|
233
|
+
yield self.error(node, "A501", "assertNotIsInstance", op="isinstance()")
|
|
230
234
|
|
|
231
|
-
check_assertequals = wrap_deprecated(
|
|
232
|
-
check_assertequal,
|
|
233
|
-
'assertEqual')
|
|
235
|
+
check_assertequals = wrap_deprecated(check_assertequal, "assertEqual")
|
|
234
236
|
|
|
235
|
-
check_assertnotequals = wrap_deprecated(
|
|
236
|
-
check_assertnotequal,
|
|
237
|
-
'assertNotEqual')
|
|
237
|
+
check_assertnotequals = wrap_deprecated(check_assertnotequal, "assertNotEqual")
|
|
238
238
|
|
|
239
239
|
check_assertalmostequals = wrap_deprecated(
|
|
240
|
-
check_assertalmostequal,
|
|
241
|
-
|
|
240
|
+
check_assertalmostequal, "assertAlmostEqual"
|
|
241
|
+
)
|
|
242
242
|
|
|
243
243
|
check_assertnotalmostequals = wrap_deprecated(
|
|
244
|
-
check_assertnotalmostequal,
|
|
245
|
-
|
|
244
|
+
check_assertnotalmostequal, "assertNotAlmostEqual"
|
|
245
|
+
)
|
|
@@ -4,7 +4,7 @@ version = attr: flake8_assertive.__version__
|
|
|
4
4
|
author = Jon Parise
|
|
5
5
|
author_email = jon@indelible.org
|
|
6
6
|
description = Flake8 unittest assert method checker
|
|
7
|
-
long_description = file: README.rst,
|
|
7
|
+
long_description = file: README.rst, CHANGELOG.rst
|
|
8
8
|
license = MIT
|
|
9
9
|
url = https://github.com/jparise/flake8-assertive
|
|
10
10
|
project_urls =
|
|
@@ -19,10 +19,11 @@ classifiers =
|
|
|
19
19
|
License :: OSI Approved :: MIT License
|
|
20
20
|
Programming Language :: Python
|
|
21
21
|
Programming Language :: Python :: 3 :: Only
|
|
22
|
-
Programming Language :: Python :: 3.7
|
|
23
|
-
Programming Language :: Python :: 3.8
|
|
24
|
-
Programming Language :: Python :: 3.9
|
|
25
22
|
Programming Language :: Python :: 3.10
|
|
23
|
+
Programming Language :: Python :: 3.11
|
|
24
|
+
Programming Language :: Python :: 3.12
|
|
25
|
+
Programming Language :: Python :: 3.13
|
|
26
|
+
Programming Language :: Python :: 3.14
|
|
26
27
|
Topic :: Software Development :: Libraries :: Python Modules
|
|
27
28
|
Topic :: Software Development :: Quality Assurance
|
|
28
29
|
Topic :: Software Development :: Testing
|
|
@@ -30,7 +31,7 @@ classifiers =
|
|
|
30
31
|
|
|
31
32
|
[options]
|
|
32
33
|
py_modules = flake8_assertive
|
|
33
|
-
python_requires = >= 3.
|
|
34
|
+
python_requires = >= 3.10
|
|
34
35
|
zip_safe = True
|
|
35
36
|
|
|
36
37
|
[options.entry_points]
|
|
@@ -39,6 +40,8 @@ flake8.extension =
|
|
|
39
40
|
|
|
40
41
|
[flake8]
|
|
41
42
|
exclude = .eggs/,.git/,.venv/,build/,dist/
|
|
43
|
+
extend-ignore = E203
|
|
44
|
+
max-line-length = 88
|
|
42
45
|
|
|
43
46
|
[egg_info]
|
|
44
47
|
tag_build =
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import re
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
from flake8_assertive import Checker
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestChecks(unittest.TestCase):
|
|
9
|
+
def tearDown(self):
|
|
10
|
+
Checker.pattern = None
|
|
11
|
+
Checker.snakecase = False
|
|
12
|
+
|
|
13
|
+
def check(self, code, expected=None, pattern=None, filename="test.py"):
|
|
14
|
+
tree = ast.parse(code, filename)
|
|
15
|
+
checker = Checker(tree, filename)
|
|
16
|
+
error = next(checker.run(), None)
|
|
17
|
+
|
|
18
|
+
if expected is None:
|
|
19
|
+
return self.assertIsNone(error)
|
|
20
|
+
|
|
21
|
+
self.assertIsNotNone(error, "expected {0} error".format(expected))
|
|
22
|
+
self.assertEqual(expected, error[2].split(" ")[0])
|
|
23
|
+
if pattern is not None:
|
|
24
|
+
self.assertRegex(error[2], re.escape(pattern))
|
|
25
|
+
|
|
26
|
+
def test_assertequal_none(self):
|
|
27
|
+
self.check("self.assertEqual(None, 1)", "A502", "assertIsNone()")
|
|
28
|
+
self.check("self.assertEqual(1, None)", "A502", "assertIsNone()")
|
|
29
|
+
|
|
30
|
+
def test_assertequal_true(self):
|
|
31
|
+
self.check("self.assertEqual(True, a)", "A502", "assertTrue()")
|
|
32
|
+
self.check("self.assertEqual(a, True)", "A502", "assertTrue()")
|
|
33
|
+
|
|
34
|
+
def test_assertequal_false(self):
|
|
35
|
+
self.check("self.assertEqual(False, a)", "A502", "assertFalse()")
|
|
36
|
+
self.check("self.assertEqual(a, False)", "A502", "assertFalse()")
|
|
37
|
+
|
|
38
|
+
def test_assertequal_round(self):
|
|
39
|
+
self.check(
|
|
40
|
+
"self.assertEqual(1.01, round(a, 2))",
|
|
41
|
+
"A501",
|
|
42
|
+
"built-in rounding of assertAlmostEqual()",
|
|
43
|
+
)
|
|
44
|
+
self.check(
|
|
45
|
+
"self.assertEqual(round(a, 2), 1.01)",
|
|
46
|
+
"A501",
|
|
47
|
+
"built-in rounding of assertAlmostEqual()",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def test_assertnotequal_none(self):
|
|
51
|
+
self.check("self.assertNotEqual(None, 1)", "A502", "assertIsNotNone()")
|
|
52
|
+
self.check("self.assertNotEqual(1, None)", "A502", "assertIsNotNone()")
|
|
53
|
+
|
|
54
|
+
def test_assertnotequal_true(self):
|
|
55
|
+
self.check("self.assertNotEqual(True, a)", "A502", "assertFalse()")
|
|
56
|
+
self.check("self.assertNotEqual(a, True)", "A502", "assertFalse()")
|
|
57
|
+
|
|
58
|
+
def test_assertnotequal_false(self):
|
|
59
|
+
self.check("self.assertNotEqual(False, a)", "A502", "assertTrue()")
|
|
60
|
+
self.check("self.assertNotEqual(a, False)", "A502", "assertTrue()")
|
|
61
|
+
|
|
62
|
+
def test_assertnotequal_round(self):
|
|
63
|
+
self.check(
|
|
64
|
+
"self.assertNotEqual(1.01, round(a, 2))",
|
|
65
|
+
"A501",
|
|
66
|
+
"built-in rounding of assertNotAlmostEqual()",
|
|
67
|
+
)
|
|
68
|
+
self.check(
|
|
69
|
+
"self.assertNotEqual(round(a, 2), 1.01)",
|
|
70
|
+
"A501",
|
|
71
|
+
"built-in rounding of assertNotAlmostEqual()",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def test_assertequals(self):
|
|
75
|
+
self.check("self.assertEquals(True, a)", "A502", "assertTrue()")
|
|
76
|
+
|
|
77
|
+
def test_assertnotequals(self):
|
|
78
|
+
self.check("self.assertNotEquals(True, a)", "A502", "assertFalse()")
|
|
79
|
+
|
|
80
|
+
def test_assertalmostequal_round(self):
|
|
81
|
+
self.check(
|
|
82
|
+
"self.assertAlmostEqual(1.01, round(a, 2))",
|
|
83
|
+
"A501",
|
|
84
|
+
"built-in rounding of assertAlmostEqual()",
|
|
85
|
+
)
|
|
86
|
+
self.check(
|
|
87
|
+
"self.assertAlmostEqual(round(a, 2), 1.01)",
|
|
88
|
+
"A501",
|
|
89
|
+
"built-in rounding of assertAlmostEqual()",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def test_assertalmostequals(self):
|
|
93
|
+
self.check(
|
|
94
|
+
"self.assertEquals(1.01, round(a, 2))",
|
|
95
|
+
"A501",
|
|
96
|
+
"built-in rounding of assertAlmostEqual()",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def test_assertnotalmostequal_round(self):
|
|
100
|
+
self.check(
|
|
101
|
+
"self.assertNotAlmostEqual(1.01, round(a, 2))",
|
|
102
|
+
"A501",
|
|
103
|
+
"built-in rounding of assertNotAlmostEqual()",
|
|
104
|
+
)
|
|
105
|
+
self.check(
|
|
106
|
+
"self.assertNotAlmostEqual(round(a, 2), 1.01)",
|
|
107
|
+
"A501",
|
|
108
|
+
"built-in rounding of assertNotAlmostEqual()",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def test_assertnotalmostequals(self):
|
|
112
|
+
self.check(
|
|
113
|
+
"self.assertNotAlmostEquals(1.01, round(a, 2))",
|
|
114
|
+
"A501",
|
|
115
|
+
"built-in rounding of assertNotAlmostEqual()",
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def test_asserttrue_is(self):
|
|
119
|
+
self.check("self.assertTrue(True is True)", "A501", "assertIs()")
|
|
120
|
+
self.check("self.assertTrue(True is not False)", "A501", "assertIsNot()")
|
|
121
|
+
|
|
122
|
+
def test_asserttrue_is_none(self):
|
|
123
|
+
self.check("self.assertTrue(a is None)", "A502", "assertIsNone()")
|
|
124
|
+
self.check("self.assertTrue(a is not None)", "A502", "assertIsNotNone()")
|
|
125
|
+
|
|
126
|
+
def test_assertfalse_is(self):
|
|
127
|
+
self.check("self.assertFalse(True is False)", "A501", "assertIsNot()")
|
|
128
|
+
self.check("self.assertFalse(True is not True)", "A501", "assertIs()")
|
|
129
|
+
|
|
130
|
+
def test_assertfalse_is_none(self):
|
|
131
|
+
self.check("self.assertFalse(a is None)", "A502", "assertIsNotNone()")
|
|
132
|
+
self.check("self.assertFalse(a is not None)", "A502", "assertIsNone()")
|
|
133
|
+
|
|
134
|
+
def test_asserttrue_in(self):
|
|
135
|
+
self.check("self.assertTrue(1 in [1])", "A501", "assertIn()")
|
|
136
|
+
self.check("self.assertTrue(1 not in [2])", "A501", "assertNotIn()")
|
|
137
|
+
|
|
138
|
+
def test_assertfalse_in(self):
|
|
139
|
+
self.check("self.assertFalse(1 in [2])", "A501", "assertNotIn()")
|
|
140
|
+
self.check("self.assertFalse(1 not in [1])", "A501", "assertIn()")
|
|
141
|
+
|
|
142
|
+
def test_asserttrue_equal(self):
|
|
143
|
+
self.check("self.assertTrue(1 == 1)", "A500", "assertEqual() for '=='")
|
|
144
|
+
self.check("self.assertTrue(1 != 1)", "A500", "assertNotEqual() for '!='")
|
|
145
|
+
|
|
146
|
+
def test_asserttrue_less(self):
|
|
147
|
+
self.check("self.assertTrue(0 < 1)", "A500", "assertLess() for '<'")
|
|
148
|
+
self.check("self.assertTrue(0 <= 1)", "A500", "assertLessEqual() for '<='")
|
|
149
|
+
|
|
150
|
+
def test_asserttrue_greater(self):
|
|
151
|
+
self.check("self.assertTrue(1 > 0)", "A500", "assertGreater() for '>'")
|
|
152
|
+
self.check("self.assertTrue(1 >= 0)", "A500", "assertGreaterEqual() for '>='")
|
|
153
|
+
|
|
154
|
+
def test_asserttrue_isinstance(self):
|
|
155
|
+
self.check(
|
|
156
|
+
"self.assertTrue(isinstance(True, bool))",
|
|
157
|
+
"A501",
|
|
158
|
+
"assertIsInstance() for 'isinstance()'",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def test_assertfalse_isinstance(self):
|
|
162
|
+
self.check(
|
|
163
|
+
"self.assertFalse(isinstance(True, bool))",
|
|
164
|
+
"A501",
|
|
165
|
+
"assertNotIsInstance() for 'isinstance()'",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
def test_assertfalse_equal(self):
|
|
169
|
+
self.check("self.assertFalse(1 == 1)", "A500", "assertNotEqual() for '=='")
|
|
170
|
+
self.check("self.assertFalse(1 != 0)", "A500", "assertEqual() for '!='")
|
|
171
|
+
|
|
172
|
+
def test_keyword_args(self):
|
|
173
|
+
self.check("self.assertTrue(expr=1)", expected=None)
|
|
174
|
+
self.check("self.assertTrue(expr=(True is True))", expected="A501")
|
|
175
|
+
self.check("self.assertEqual(first=1, second=1)", expected=None)
|
|
176
|
+
self.check("self.assertEqual(first=1, second=None)", "A502")
|
|
177
|
+
self.check("self.assertEqual(first=None, second=1)", "A502")
|
|
178
|
+
self.check("self.assertEqual(1, second=1)", expected=None)
|
|
179
|
+
self.check("self.assertEqual(None, second=1)", "A502")
|
|
180
|
+
|
|
181
|
+
def test_multiple_comparison_ops(self):
|
|
182
|
+
self.check("self.assertTrue(1 == 1 == 1)", expected=None)
|
|
183
|
+
self.check("self.assertFalse(1 == 1 == 1)", expected=None)
|
|
184
|
+
|
|
185
|
+
def test_pattern(self):
|
|
186
|
+
Checker.pattern = "[a-m]*.py"
|
|
187
|
+
self.check("self.assertTrue(1 == 1)", expected="A500", filename="a.py")
|
|
188
|
+
self.check("self.assertTrue(1 == 1)", expected=None, filename="z.py")
|
|
189
|
+
|
|
190
|
+
def test_snakecase(self):
|
|
191
|
+
Checker.snakecase = True
|
|
192
|
+
self.check("self.assert_equal(True, a)", "A502", "assert_true()")
|
|
193
|
+
|
|
194
|
+
def test_deprecated(self):
|
|
195
|
+
self.check("self.assertEquals(True, a)", "A502", "assertTrue()")
|
|
196
|
+
self.check("self.assertEquals(a, b)", "A503", "assertEqual()")
|
|
197
|
+
|
|
198
|
+
def test_asserttrue_misuse(self):
|
|
199
|
+
self.check("self.assertTrue(a, 'foo')", expected="A504")
|
|
200
|
+
self.check("self.assertTrue(a, msg='foo')", expected=None)
|
|
201
|
+
|
|
202
|
+
def test_assertfalse_misuse(self):
|
|
203
|
+
self.check("self.assertFalse(a, 'foo')", expected="A504")
|
|
204
|
+
self.check("self.assertFalse(a, msg='foo')", expected=None)
|
flake8-assertive-2.1.0/setup.py
DELETED
|
File without changes
|
|
File without changes
|
{flake8-assertive-2.1.0 → flake8_assertive-2.2.0}/flake8_assertive.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|