flake8-assertive 2.1.0__tar.gz → 2.3.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,19 @@
1
+ =======
1
2
  Changes
2
3
  =======
3
4
 
5
+ 2.3.0 (2026-10-14)
6
+ ------------------
7
+
8
+ * Add support for Python 3.15.
9
+ * Drop support for Python 3.10. Python 3.11+ is now required.
10
+ * Drop support for flake8 versions older than 6.0.
11
+
12
+ 2.2.0 (2025-10-11)
13
+ ------------------
14
+
15
+ * Drop support for Python 3.7, 3.8, and 3.9. Python 3.10+ is now required.
16
+
4
17
  2.1.0 (2022-03-15)
5
18
  ------------------
6
19
 
@@ -1,32 +1,35 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: flake8-assertive
3
- Version: 2.1.0
3
+ Version: 2.3.0
4
4
  Summary: Flake8 unittest assert method checker
5
- Home-page: https://github.com/jparise/flake8-assertive
6
- Author: Jon Parise
7
- Author-email: jon@indelible.org
8
- License: MIT
9
- Project-URL: Source Code, https://github.com/jparise/flake8-assertive
10
- Project-URL: Issue Tracker, https://github.com/jparise/flake8-assertive/issues
11
- Keywords: flake8 testing unittest assert
12
- Platform: UNKNOWN
5
+ Author-email: Jon Parise <jon@indelible.org>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jparise/flake8-assertive
8
+ Project-URL: Repository, https://github.com/jparise/flake8-assertive
9
+ Project-URL: Issues, https://github.com/jparise/flake8-assertive/issues
10
+ Project-URL: Changelog, https://github.com/jparise/flake8-assertive/blob/main/CHANGELOG.rst
11
+ Keywords: flake8,testing,unittest,assert
13
12
  Classifier: Development Status :: 5 - Production/Stable
14
13
  Classifier: Environment :: Console
15
14
  Classifier: Framework :: Flake8
16
15
  Classifier: Intended Audience :: Developers
17
- Classifier: License :: OSI Approved :: MIT License
18
16
  Classifier: Programming Language :: Python
19
17
  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
- Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
24
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
24
  Classifier: Topic :: Software Development :: Quality Assurance
26
25
  Classifier: Topic :: Software Development :: Testing
27
26
  Classifier: Topic :: Software Development :: Testing :: Unit
28
- Requires-Python: >=3.7
27
+ Requires-Python: >=3.11
28
+ Description-Content-Type: text/x-rst
29
29
  License-File: LICENSE
30
+ Requires-Dist: flake8>=6.0.0
31
+ Dynamic: license-file
32
+ Dynamic: requires-python
30
33
 
31
34
  =================================
32
35
  Flake8 Unittest Assertion Checker
@@ -135,7 +138,7 @@ that it has been loaded by inspecting the ``flake8 --version`` string.
135
138
  .. code-block:: sh
136
139
 
137
140
  $ flake8 --version
138
- 4.0.1 (assertive: 2.1.0, ...) CPython 3.9.10 on Darwin
141
+ 7.3.0 (assertive: 2.3.0, ...) CPython 3.11.10 on Darwin
139
142
 
140
143
 
141
144
  Error Codes
@@ -195,89 +198,13 @@ 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
-
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
-
223
- Changes
224
- =======
225
-
226
- 2.1.0 (2022-03-15)
227
- ------------------
228
-
229
- * Suggest using an explicit `msg` keyword argument with ``assertTrue()`` and
230
- ``assertFalse()`` to avoid accidental two-argument misuse. This is controlled
231
- by a new error code: ``A504``
232
-
233
- 2.0.0 (2021-12-30)
234
- ------------------
235
-
236
- * Drop support for Python 2.7 and 3.6, and add 3.10.
237
- * Drop support for flake8 2.x versions.
238
-
239
- 1.3.0 (2020-10-12)
240
- ------------------
241
-
242
- * Drop Python version 3.5 support and add version 3.9.
243
-
244
- 1.2.1 (2019-12-08)
245
- ------------------
246
-
247
- * Support keyword arguments in assert method calls.
248
-
249
- 1.2.0 (2019-12-05)
250
- ------------------
251
-
252
- * Suggest the preferred names for deprecated methods, such as
253
- ``assertEqual()`` instead of ``assertEquals()``.
254
-
255
- 1.1.0 (2019-06-26)
256
- ------------------
257
-
258
- * Suggest ``assertAlmostEqual(a, b, x)`` for ``round()`` expressions like in
259
- ``assertEqual(a, round(b, x))`` and ``assertAlmostEqual(a, round(b, x))``
260
- (and similar for ``assertNotEqual()`` and ``assertNotAlmostEqual()``.
261
- * Recognize ``assertAmostEquals()`` and ``assertNotAlmostEquals()`` as aliases
262
- for ``assertAlmostEqual()`` and ``assertNotAlmostEqual()``.
263
- * Drop Python 3.4 as a supported version since it has been officially retired.
264
-
265
- 1.0.1 (2018-07-03)
266
- ------------------
267
-
268
- * Don't make suggestions for assertions containing multiple comparison
269
- operations (e.g. ``assertTrue(a == b == c)``).
270
-
271
- 1.0.0 (2018-06-04)
272
- ------------------
273
-
274
- * Suggest ``assertIsNone(a)`` for ``assertTrue(a is None)``, etc.
275
- * Recognize ``assertEquals()`` and ``assertNotEquals()`` as aliases for
276
- ``assertEqual()`` and ``assertNotEqual()``.
277
-
278
- 0.9.0 (2018-05-14)
279
- ------------------
280
-
281
- * Initial beta release
282
-
283
-
@@ -105,7 +105,7 @@ that it has been loaded by inspecting the ``flake8 --version`` string.
105
105
  .. code-block:: sh
106
106
 
107
107
  $ flake8 --version
108
- 4.0.1 (assertive: 2.1.0, ...) CPython 3.9.10 on Darwin
108
+ 7.3.0 (assertive: 2.3.0, ...) CPython 3.11.10 on Darwin
109
109
 
110
110
 
111
111
  Error Codes
@@ -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
@@ -0,0 +1,53 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "flake8-assertive"
7
+ dynamic = ["version"]
8
+ description = "Flake8 unittest assert method checker"
9
+ authors = [
10
+ {name = "Jon Parise", email = "jon@indelible.org"},
11
+ ]
12
+ readme = "README.rst"
13
+ license = "MIT"
14
+ keywords = ["flake8", "testing", "unittest", "assert"]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Environment :: Console",
18
+ "Framework :: Flake8",
19
+ "Intended Audience :: Developers",
20
+ "Programming Language :: Python",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
26
+ "Programming Language :: Python :: 3.15",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ "Topic :: Software Development :: Quality Assurance",
29
+ "Topic :: Software Development :: Testing",
30
+ "Topic :: Software Development :: Testing :: Unit",
31
+ ]
32
+ requires-python = ">= 3.11"
33
+ dependencies = [
34
+ "flake8>=6.0.0",
35
+ ]
36
+
37
+ [dependency-groups]
38
+ dev = [
39
+ "pytest>=8",
40
+ "ruff==0.17.0",
41
+ ]
42
+
43
+ [project.entry-points."flake8.extension"]
44
+ A50 = "flake8_assertive:Checker"
45
+
46
+ [project.urls]
47
+ Homepage = "https://github.com/jparise/flake8-assertive"
48
+ Repository = "https://github.com/jparise/flake8-assertive"
49
+ Issues = "https://github.com/jparise/flake8-assertive/issues"
50
+ Changelog = "https://github.com/jparise/flake8-assertive/blob/main/CHANGELOG.rst"
51
+
52
+ [tool.setuptools.dynamic]
53
+ version = {attr = "flake8_assertive.__version__"}
@@ -0,0 +1,9 @@
1
+ [flake8]
2
+ exclude = .eggs/,.git/,.venv/,build/,dist/
3
+ extend-ignore = E203
4
+ max-line-length = 88
5
+
6
+ [egg_info]
7
+ tag_build =
8
+ tag_date = 0
9
+
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env python
2
+
3
+ from setuptools import setup
4
+
5
+ setup(
6
+ name="flake8-assertive",
7
+ install_requires=["flake8>=6.0.0"],
8
+ python_requires=">=3.11",
9
+ )
@@ -1,32 +1,35 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: flake8-assertive
3
- Version: 2.1.0
3
+ Version: 2.3.0
4
4
  Summary: Flake8 unittest assert method checker
5
- Home-page: https://github.com/jparise/flake8-assertive
6
- Author: Jon Parise
7
- Author-email: jon@indelible.org
8
- License: MIT
9
- Project-URL: Source Code, https://github.com/jparise/flake8-assertive
10
- Project-URL: Issue Tracker, https://github.com/jparise/flake8-assertive/issues
11
- Keywords: flake8 testing unittest assert
12
- Platform: UNKNOWN
5
+ Author-email: Jon Parise <jon@indelible.org>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jparise/flake8-assertive
8
+ Project-URL: Repository, https://github.com/jparise/flake8-assertive
9
+ Project-URL: Issues, https://github.com/jparise/flake8-assertive/issues
10
+ Project-URL: Changelog, https://github.com/jparise/flake8-assertive/blob/main/CHANGELOG.rst
11
+ Keywords: flake8,testing,unittest,assert
13
12
  Classifier: Development Status :: 5 - Production/Stable
14
13
  Classifier: Environment :: Console
15
14
  Classifier: Framework :: Flake8
16
15
  Classifier: Intended Audience :: Developers
17
- Classifier: License :: OSI Approved :: MIT License
18
16
  Classifier: Programming Language :: Python
19
17
  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
- Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
24
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
24
  Classifier: Topic :: Software Development :: Quality Assurance
26
25
  Classifier: Topic :: Software Development :: Testing
27
26
  Classifier: Topic :: Software Development :: Testing :: Unit
28
- Requires-Python: >=3.7
27
+ Requires-Python: >=3.11
28
+ Description-Content-Type: text/x-rst
29
29
  License-File: LICENSE
30
+ Requires-Dist: flake8>=6.0.0
31
+ Dynamic: license-file
32
+ Dynamic: requires-python
30
33
 
31
34
  =================================
32
35
  Flake8 Unittest Assertion Checker
@@ -135,7 +138,7 @@ that it has been loaded by inspecting the ``flake8 --version`` string.
135
138
  .. code-block:: sh
136
139
 
137
140
  $ flake8 --version
138
- 4.0.1 (assertive: 2.1.0, ...) CPython 3.9.10 on Darwin
141
+ 7.3.0 (assertive: 2.3.0, ...) CPython 3.11.10 on Darwin
139
142
 
140
143
 
141
144
  Error Codes
@@ -195,89 +198,13 @@ 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
-
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
-
223
- Changes
224
- =======
225
-
226
- 2.1.0 (2022-03-15)
227
- ------------------
228
-
229
- * Suggest using an explicit `msg` keyword argument with ``assertTrue()`` and
230
- ``assertFalse()`` to avoid accidental two-argument misuse. This is controlled
231
- by a new error code: ``A504``
232
-
233
- 2.0.0 (2021-12-30)
234
- ------------------
235
-
236
- * Drop support for Python 2.7 and 3.6, and add 3.10.
237
- * Drop support for flake8 2.x versions.
238
-
239
- 1.3.0 (2020-10-12)
240
- ------------------
241
-
242
- * Drop Python version 3.5 support and add version 3.9.
243
-
244
- 1.2.1 (2019-12-08)
245
- ------------------
246
-
247
- * Support keyword arguments in assert method calls.
248
-
249
- 1.2.0 (2019-12-05)
250
- ------------------
251
-
252
- * Suggest the preferred names for deprecated methods, such as
253
- ``assertEqual()`` instead of ``assertEquals()``.
254
-
255
- 1.1.0 (2019-06-26)
256
- ------------------
257
-
258
- * Suggest ``assertAlmostEqual(a, b, x)`` for ``round()`` expressions like in
259
- ``assertEqual(a, round(b, x))`` and ``assertAlmostEqual(a, round(b, x))``
260
- (and similar for ``assertNotEqual()`` and ``assertNotAlmostEqual()``.
261
- * Recognize ``assertAmostEquals()`` and ``assertNotAlmostEquals()`` as aliases
262
- for ``assertAlmostEqual()`` and ``assertNotAlmostEqual()``.
263
- * Drop Python 3.4 as a supported version since it has been officially retired.
264
-
265
- 1.0.1 (2018-07-03)
266
- ------------------
267
-
268
- * Don't make suggestions for assertions containing multiple comparison
269
- operations (e.g. ``assertTrue(a == b == c)``).
270
-
271
- 1.0.0 (2018-06-04)
272
- ------------------
273
-
274
- * Suggest ``assertIsNone(a)`` for ``assertTrue(a is None)``, etc.
275
- * Recognize ``assertEquals()`` and ``assertNotEquals()`` as aliases for
276
- ``assertEqual()`` and ``assertNotEqual()``.
277
-
278
- 0.9.0 (2018-05-14)
279
- ------------------
280
-
281
- * Initial beta release
282
-
283
-
@@ -0,0 +1,15 @@
1
+ CHANGELOG.rst
2
+ LICENSE
3
+ MANIFEST.in
4
+ README.rst
5
+ pyproject.toml
6
+ setup.cfg
7
+ setup.py
8
+ src/flake8_assertive.py
9
+ src/flake8_assertive.egg-info/PKG-INFO
10
+ src/flake8_assertive.egg-info/SOURCES.txt
11
+ src/flake8_assertive.egg-info/dependency_links.txt
12
+ src/flake8_assertive.egg-info/entry_points.txt
13
+ src/flake8_assertive.egg-info/requires.txt
14
+ src/flake8_assertive.egg-info/top_level.txt
15
+ tests/test_checker.py
@@ -1,3 +1,2 @@
1
1
  [flake8.extension]
2
2
  A50 = flake8_assertive:Checker
3
-
@@ -24,29 +24,28 @@ 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.3.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
+ def is_constant(node, obj):
32
+ return isinstance(node, ast.Constant) and node.value is obj
38
33
 
39
34
 
40
35
  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)
36
+ return (
37
+ isinstance(node, ast.Call)
38
+ and isinstance(node.func, ast.Name)
39
+ and node.func.id == name
40
+ )
44
41
 
45
42
 
46
43
  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'))
44
+ return (
45
+ isinstance(node, ast.Call)
46
+ and isinstance(node.func, ast.Attribute)
47
+ and node.func.attr.startswith("assert")
48
+ )
50
49
 
51
50
 
52
51
  def args(node):
@@ -63,18 +62,18 @@ def wrap_deprecated(func, name):
63
62
  check function doesn't yield any errors of its own, this function will
64
63
  yield an A503 error that includes the new name of the deprecated method.
65
64
  """
65
+
66
66
  def wrapper(self, node):
67
- for error in func(self, node):
68
- yield error
69
- else:
70
- yield self.error(node, 'A503', func=name, name=node.func.attr)
67
+ yield from func(self, node)
68
+ yield self.error(node, "A503", func=name, name=node.func.attr)
69
+
71
70
  return wrapper
72
71
 
73
72
 
74
- class Checker(object):
73
+ class Checker:
75
74
  """Unittest assert method checker"""
76
75
 
77
- name = 'assertive'
76
+ name = "assertive"
78
77
  version = __version__
79
78
  pattern = None
80
79
  snakecase = False
@@ -92,16 +91,18 @@ class Checker(object):
92
91
  @classmethod
93
92
  def add_options(cls, parser):
94
93
  parser.add_option(
95
- '--assertive-snakecase',
94
+ "--assertive-snakecase",
96
95
  help="Use snake_case assert method names ('assert_true()')",
97
- action='store_true',
96
+ action="store_true",
98
97
  default=False,
99
- parse_from_config=True)
98
+ parse_from_config=True,
99
+ )
100
100
  parser.add_option(
101
- '--assertive-test-pattern',
101
+ "--assertive-test-pattern",
102
102
  help="fnmatch() pattern for identifying unittest test files",
103
103
  default=None,
104
- parse_from_config=True)
104
+ parse_from_config=True,
105
+ )
105
106
 
106
107
  @classmethod
107
108
  def parse_options(cls, options):
@@ -110,8 +111,8 @@ class Checker(object):
110
111
 
111
112
  def error(self, node, code, func, **kwargs):
112
113
  if self.snakecase:
113
- func = re.sub(r'([A-Z])', r'_\1', func).lower()
114
- message = code + ' ' + getattr(self, code).format(func=func, **kwargs)
114
+ func = re.sub(r"([A-Z])", r"_\1", func).lower()
115
+ message = code + " " + getattr(self, code).format(func=func, **kwargs)
115
116
  return (node.lineno, node.col_offset, message, self)
116
117
 
117
118
  def run(self):
@@ -122,124 +123,117 @@ class Checker(object):
122
123
  # Visit all of the assert method calls in the tree.
123
124
  for node in ast.walk(self.tree):
124
125
  if is_assert_method_call(node):
125
- name = node.func.attr.lower().replace('_', '')
126
- func = getattr(self, 'check_' + name, None)
126
+ name = node.func.attr.lower().replace("_", "")
127
+ func = getattr(self, "check_" + name, None)
127
128
  if func is not None:
128
- for error in func(node):
129
- yield error
129
+ yield from func(node)
130
130
 
131
131
  def check_assertequal(self, node):
132
132
  if any(arg for arg in args(node) if is_constant(arg, None)):
133
- yield self.error(node, 'A502', 'assertIsNone', obj=None)
133
+ yield self.error(node, "A502", "assertIsNone", obj=None)
134
134
  elif any(arg for arg in args(node) if is_constant(arg, True)):
135
- yield self.error(node, 'A502', 'assertTrue', obj=True)
135
+ yield self.error(node, "A502", "assertTrue", obj=True)
136
136
  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')
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(
140
+ node, "A501", "built-in rounding of assertAlmostEqual", op="round"
141
+ )
142
142
 
143
143
  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')
144
+ if 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
+ )
148
148
 
149
149
  def check_assertnotequal(self, node):
150
150
  if any(arg for arg in args(node) if is_constant(arg, None)):
151
- yield self.error(node, 'A502', 'assertIsNotNone', obj=None)
151
+ yield self.error(node, "A502", "assertIsNotNone", obj=None)
152
152
  elif any(arg for arg in args(node) if is_constant(arg, True)):
153
- yield self.error(node, 'A502', 'assertFalse', obj=True)
153
+ yield self.error(node, "A502", "assertFalse", obj=True)
154
154
  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')
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(
158
+ node, "A501", "built-in rounding of assertNotAlmostEqual", op="round"
159
+ )
160
160
 
161
161
  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')
162
+ if 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
+ )
166
166
 
167
167
  def check_asserttrue(self, node):
168
168
  if len(node.args) > 1:
169
- yield self.error(node, 'A504', 'assertTrue')
169
+ yield self.error(node, "A504", "assertTrue")
170
170
  arg = next(args(node), None)
171
171
  if arg and isinstance(arg, ast.Compare) and len(arg.ops) == 1:
172
172
  op = arg.ops[0]
173
173
  if isinstance(op, ast.In):
174
- yield self.error(node, 'A501', 'assertIn', op='in')
174
+ yield self.error(node, "A501", "assertIn", op="in")
175
175
  elif isinstance(op, ast.NotIn):
176
- yield self.error(node, 'A501', 'assertNotIn', op='in')
176
+ yield self.error(node, "A501", "assertNotIn", op="in")
177
177
  elif isinstance(op, ast.Is):
178
178
  if is_constant(arg.comparators[0], None):
179
- yield self.error(node, 'A502', 'assertIsNone', obj=None)
179
+ yield self.error(node, "A502", "assertIsNone", obj=None)
180
180
  else:
181
- yield self.error(node, 'A501', 'assertIs', op='is')
181
+ yield self.error(node, "A501", "assertIs", op="is")
182
182
  elif isinstance(op, ast.IsNot):
183
183
  if is_constant(arg.comparators[0], None):
184
- yield self.error(node, 'A502', 'assertIsNotNone', obj=None)
184
+ yield self.error(node, "A502", "assertIsNotNone", obj=None)
185
185
  else:
186
- yield self.error(node, 'A501', 'assertIsNot', op='is')
186
+ yield self.error(node, "A501", "assertIsNot", op="is")
187
187
  elif isinstance(op, ast.Eq):
188
- yield self.error(node, 'A500', 'assertEqual', op='==')
188
+ yield self.error(node, "A500", "assertEqual", op="==")
189
189
  elif isinstance(op, ast.NotEq):
190
- yield self.error(node, 'A500', 'assertNotEqual', op='!=')
190
+ yield self.error(node, "A500", "assertNotEqual", op="!=")
191
191
  elif isinstance(op, ast.Lt):
192
- yield self.error(node, 'A500', 'assertLess', op='<')
192
+ yield self.error(node, "A500", "assertLess", op="<")
193
193
  elif isinstance(op, ast.LtE):
194
- yield self.error(node, 'A500', 'assertLessEqual', op='<=')
194
+ yield self.error(node, "A500", "assertLessEqual", op="<=")
195
195
  elif isinstance(op, ast.Gt):
196
- yield self.error(node, 'A500', 'assertGreater', op='>')
196
+ yield self.error(node, "A500", "assertGreater", op=">")
197
197
  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()')
198
+ yield self.error(node, "A500", "assertGreaterEqual", op=">=")
199
+ elif is_function_call(arg, "isinstance"):
200
+ yield self.error(node, "A501", "assertIsInstance", op="isinstance()")
202
201
 
203
202
  def check_assertfalse(self, node):
204
203
  if len(node.args) > 1:
205
- yield self.error(node, 'A504', 'assertFalse')
204
+ yield self.error(node, "A504", "assertFalse")
206
205
  arg = next(args(node), None)
207
206
  if arg and isinstance(arg, ast.Compare) and len(arg.ops) == 1:
208
207
  op = arg.ops[0]
209
208
  if isinstance(op, ast.In):
210
- yield self.error(node, 'A501', 'assertNotIn', op='in')
209
+ yield self.error(node, "A501", "assertNotIn", op="in")
211
210
  elif isinstance(op, ast.NotIn):
212
- yield self.error(node, 'A501', 'assertIn', op='in')
211
+ yield self.error(node, "A501", "assertIn", op="in")
213
212
  elif isinstance(op, ast.Is):
214
213
  if is_constant(arg.comparators[0], None):
215
- yield self.error(node, 'A502', 'assertIsNotNone', obj=None)
214
+ yield self.error(node, "A502", "assertIsNotNone", obj=None)
216
215
  else:
217
- yield self.error(node, 'A501', 'assertIsNot', op='is')
216
+ yield self.error(node, "A501", "assertIsNot", op="is")
218
217
  elif isinstance(op, ast.IsNot):
219
218
  if is_constant(arg.comparators[0], None):
220
- yield self.error(node, 'A502', 'assertIsNone', obj=None)
219
+ yield self.error(node, "A502", "assertIsNone", obj=None)
221
220
  else:
222
- yield self.error(node, 'A501', 'assertIs', op='is')
221
+ yield self.error(node, "A501", "assertIs", op="is")
223
222
  elif isinstance(op, ast.Eq):
224
- yield self.error(node, 'A500', 'assertNotEqual', op='==')
223
+ yield self.error(node, "A500", "assertNotEqual", op="==")
225
224
  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()')
225
+ yield self.error(node, "A500", "assertEqual", op="!=")
226
+ elif is_function_call(arg, "isinstance"):
227
+ yield self.error(node, "A501", "assertNotIsInstance", op="isinstance()")
230
228
 
231
- check_assertequals = wrap_deprecated(
232
- check_assertequal,
233
- 'assertEqual')
229
+ check_assertequals = wrap_deprecated(check_assertequal, "assertEqual")
234
230
 
235
- check_assertnotequals = wrap_deprecated(
236
- check_assertnotequal,
237
- 'assertNotEqual')
231
+ check_assertnotequals = wrap_deprecated(check_assertnotequal, "assertNotEqual")
238
232
 
239
233
  check_assertalmostequals = wrap_deprecated(
240
- check_assertalmostequal,
241
- 'assertAlmostEqual')
234
+ check_assertalmostequal, "assertAlmostEqual"
235
+ )
242
236
 
243
237
  check_assertnotalmostequals = wrap_deprecated(
244
- check_assertnotalmostequal,
245
- 'assertNotAlmostEqual')
238
+ check_assertnotalmostequal, "assertNotAlmostEqual"
239
+ )
@@ -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, f"expected {expected} error")
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,14 +0,0 @@
1
- CHANGELOG.rst
2
- LICENSE
3
- MANIFEST.in
4
- README.rst
5
- flake8_assertive.py
6
- setup.cfg
7
- setup.py
8
- flake8_assertive.egg-info/PKG-INFO
9
- flake8_assertive.egg-info/SOURCES.txt
10
- flake8_assertive.egg-info/dependency_links.txt
11
- flake8_assertive.egg-info/entry_points.txt
12
- flake8_assertive.egg-info/requires.txt
13
- flake8_assertive.egg-info/top_level.txt
14
- flake8_assertive.egg-info/zip-safe
@@ -1 +0,0 @@
1
- flake8>=3.0.0
@@ -1,46 +0,0 @@
1
- [metadata]
2
- name = flake8-assertive
3
- version = attr: flake8_assertive.__version__
4
- author = Jon Parise
5
- author_email = jon@indelible.org
6
- description = Flake8 unittest assert method checker
7
- long_description = file: README.rst, LICENSE, CHANGELOG.rst
8
- license = MIT
9
- url = https://github.com/jparise/flake8-assertive
10
- project_urls =
11
- Source Code = https://github.com/jparise/flake8-assertive
12
- Issue Tracker = https://github.com/jparise/flake8-assertive/issues
13
- keywords = flake8 testing unittest assert
14
- classifiers =
15
- Development Status :: 5 - Production/Stable
16
- Environment :: Console
17
- Framework :: Flake8
18
- Intended Audience :: Developers
19
- License :: OSI Approved :: MIT License
20
- Programming Language :: Python
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
- Programming Language :: Python :: 3.10
26
- Topic :: Software Development :: Libraries :: Python Modules
27
- Topic :: Software Development :: Quality Assurance
28
- Topic :: Software Development :: Testing
29
- Topic :: Software Development :: Testing :: Unit
30
-
31
- [options]
32
- py_modules = flake8_assertive
33
- python_requires = >= 3.7
34
- zip_safe = True
35
-
36
- [options.entry_points]
37
- flake8.extension =
38
- A50 = flake8_assertive:Checker
39
-
40
- [flake8]
41
- exclude = .eggs/,.git/,.venv/,build/,dist/
42
-
43
- [egg_info]
44
- tag_build =
45
- tag_date = 0
46
-
@@ -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
- )