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.
@@ -1,6 +1,12 @@
1
+ =======
1
2
  Changes
2
3
  =======
3
4
 
5
+ 2.2.0 (2025-10-11)
6
+ ------------------
7
+
8
+ * Drop support for Python 3.7, 3.8, and 3.9. Python 3.10+ is now required.
9
+
4
10
  2.1.0 (2022-03-15)
5
11
  ------------------
6
12
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: flake8-assertive
3
- Version: 2.1.0
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.7
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
- Copyright (c) 2018-present Jon Parise
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
1
+ Metadata-Version: 2.4
2
2
  Name: flake8-assertive
3
- Version: 2.1.0
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.7
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
- Copyright (c) 2018-present Jon Parise
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
@@ -1,3 +1,2 @@
1
1
  [flake8.extension]
2
2
  A50 = flake8_assertive:Checker
3
-
@@ -24,29 +24,31 @@ import ast
24
24
  import fnmatch
25
25
  import re
26
26
 
27
- __all__ = ['Checker']
28
- __version__ = '2.1.0'
27
+ __all__ = ["Checker"]
28
+ __version__ = "2.2.0"
29
29
 
30
30
 
31
- # Python 3.4 introduced `ast.NameConstant` for `None`, `True`, and `False`.
32
- if hasattr(ast, 'NameConstant'):
33
- def is_constant(node, obj):
34
- return isinstance(node, ast.NameConstant) and node.value is obj
35
- else:
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 (isinstance(node, ast.Call) and
42
- isinstance(node.func, ast.Name) and
43
- node.func.id == name)
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 (isinstance(node, ast.Call) and
48
- isinstance(node.func, ast.Attribute) and
49
- node.func.attr.startswith('assert'))
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, 'A503', func=name, name=node.func.attr)
73
+ yield self.error(node, "A503", func=name, name=node.func.attr)
74
+
71
75
  return wrapper
72
76
 
73
77
 
74
- class Checker(object):
78
+ class Checker:
75
79
  """Unittest assert method checker"""
76
80
 
77
- name = 'assertive'
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
- '--assertive-snakecase',
99
+ "--assertive-snakecase",
96
100
  help="Use snake_case assert method names ('assert_true()')",
97
- action='store_true',
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
- '--assertive-test-pattern',
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'([A-Z])', r'_\1', func).lower()
114
- message = code + ' ' + getattr(self, code).format(func=func, **kwargs)
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, 'check_' + name, None)
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, 'A502', 'assertIsNone', obj=None)
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, 'A502', 'assertTrue', obj=True)
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, 'A502', 'assertFalse', obj=False)
138
- elif any(arg for arg in args(node) if is_function_call(arg, 'round')):
139
- yield self.error(node, 'A501',
140
- 'built-in rounding of assertAlmostEqual',
141
- op='round')
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, 'round')):
145
- yield self.error(node, 'A501',
146
- 'built-in rounding of assertAlmostEqual',
147
- op='round')
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, 'A502', 'assertIsNotNone', obj=None)
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, 'A502', 'assertFalse', obj=True)
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, 'A502', 'assertTrue', obj=False)
156
- elif any(arg for arg in args(node) if is_function_call(arg, 'round')):
157
- yield self.error(node, 'A501',
158
- 'built-in rounding of assertNotAlmostEqual',
159
- op='round')
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, 'round')):
163
- yield self.error(node, 'A501',
164
- 'built-in rounding of assertNotAlmostEqual',
165
- op='round')
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, 'A504', 'assertTrue')
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, 'A501', 'assertIn', op='in')
180
+ yield self.error(node, "A501", "assertIn", op="in")
175
181
  elif isinstance(op, ast.NotIn):
176
- yield self.error(node, 'A501', 'assertNotIn', op='in')
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, 'A502', 'assertIsNone', obj=None)
185
+ yield self.error(node, "A502", "assertIsNone", obj=None)
180
186
  else:
181
- yield self.error(node, 'A501', 'assertIs', op='is')
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, 'A502', 'assertIsNotNone', obj=None)
190
+ yield self.error(node, "A502", "assertIsNotNone", obj=None)
185
191
  else:
186
- yield self.error(node, 'A501', 'assertIsNot', op='is')
192
+ yield self.error(node, "A501", "assertIsNot", op="is")
187
193
  elif isinstance(op, ast.Eq):
188
- yield self.error(node, 'A500', 'assertEqual', op='==')
194
+ yield self.error(node, "A500", "assertEqual", op="==")
189
195
  elif isinstance(op, ast.NotEq):
190
- yield self.error(node, 'A500', 'assertNotEqual', op='!=')
196
+ yield self.error(node, "A500", "assertNotEqual", op="!=")
191
197
  elif isinstance(op, ast.Lt):
192
- yield self.error(node, 'A500', 'assertLess', op='<')
198
+ yield self.error(node, "A500", "assertLess", op="<")
193
199
  elif isinstance(op, ast.LtE):
194
- yield self.error(node, 'A500', 'assertLessEqual', op='<=')
200
+ yield self.error(node, "A500", "assertLessEqual", op="<=")
195
201
  elif isinstance(op, ast.Gt):
196
- yield self.error(node, 'A500', 'assertGreater', op='>')
202
+ yield self.error(node, "A500", "assertGreater", op=">")
197
203
  elif isinstance(op, ast.GtE):
198
- yield self.error(node, 'A500', 'assertGreaterEqual', op='>=')
199
- elif is_function_call(arg, 'isinstance'):
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, 'A504', 'assertFalse')
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, 'A501', 'assertNotIn', op='in')
215
+ yield self.error(node, "A501", "assertNotIn", op="in")
211
216
  elif isinstance(op, ast.NotIn):
212
- yield self.error(node, 'A501', 'assertIn', op='in')
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, 'A502', 'assertIsNotNone', obj=None)
220
+ yield self.error(node, "A502", "assertIsNotNone", obj=None)
216
221
  else:
217
- yield self.error(node, 'A501', 'assertIsNot', op='is')
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, 'A502', 'assertIsNone', obj=None)
225
+ yield self.error(node, "A502", "assertIsNone", obj=None)
221
226
  else:
222
- yield self.error(node, 'A501', 'assertIs', op='is')
227
+ yield self.error(node, "A501", "assertIs", op="is")
223
228
  elif isinstance(op, ast.Eq):
224
- yield self.error(node, 'A500', 'assertNotEqual', op='==')
229
+ yield self.error(node, "A500", "assertNotEqual", op="==")
225
230
  elif isinstance(op, ast.NotEq):
226
- yield self.error(node, 'A500', 'assertEqual', op='!=')
227
- elif is_function_call(arg, 'isinstance'):
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
- 'assertAlmostEqual')
240
+ check_assertalmostequal, "assertAlmostEqual"
241
+ )
242
242
 
243
243
  check_assertnotalmostequals = wrap_deprecated(
244
- check_assertnotalmostequal,
245
- 'assertNotAlmostEqual')
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, LICENSE, CHANGELOG.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.7
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,10 @@
1
+ #!/usr/bin/env python
2
+
3
+ from setuptools import setup
4
+
5
+ setup(
6
+ name="flake8-assertive",
7
+ install_requires=["flake8>=3.0.0"],
8
+ tests_require=["flake8>=3.0.0"],
9
+ test_suite="tests",
10
+ )
@@ -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)
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env python
2
-
3
- from setuptools import setup
4
-
5
-
6
- setup(
7
- name='flake8-assertive',
8
- install_requires=['flake8>=3.0.0'],
9
- tests_require=['flake8>=3.0.0'],
10
- test_suite='tests',
11
- )