Merge "Add H216 to flag use of third party mock"

This commit is contained in:
Zuul 2021-01-26 20:37:07 +00:00 committed by Gerrit Code Review
commit 213936559e
7 changed files with 92 additions and 3 deletions

View File

@ -361,6 +361,24 @@ exception possible should be used.
assertEqual(A in B, False) or assertEqual(False, A in B) to the more
specific assertIn/NotIn(A, B)
- [H216] Make sure unittest.mock is used instead of the third party mock
library. On by default.
Starting with Python 3.3 and later, the mock module was added under unittest.
Previously, this functionality was only available by using the third party
``mock`` library.
Most users are not aware of this subtle distinction. This results in issues
where the project does not declare the ``mock`` library in its requirements
file, but the code does an ``import mock`` assuming that the module is
present. This may work initially if one of the project's dependencies ends up
pulling that dependency in indirectly, but then can cause things to suddenly
break if that transitive dependency goes away.
Since this third party library usage is done without being aware of it, this
check is enabled by default to make sure those projects that actually do
intend to use the ``mock`` library are doing so explicitly.
OpenStack Trademark
-------------------

View File

@ -11,6 +11,7 @@
# under the License.
import ast
import re
from hacking import core
@ -139,3 +140,37 @@ class FunctionNameFinder(ast.NodeVisitor):
if isinstance(node, ast.Call):
return super(FunctionNameFinder, self).visit(node.func)
return super(FunctionNameFinder, self).visit(node)
third_party_mock = re.compile('^import.mock')
from_third_party_mock = re.compile('^from.mock.import')
@core.flake8ext
def hacking_no_third_party_mock(logical_line, noqa):
"""Check for use of mock instead of unittest.mock.
Projects have had issues with using mock without including it in their
requirements, thinking it is the standard library version. This makes it so
these projects need to explicitly turn off this check to make it clear they
intended to use it.
Okay: from unittest import mock
Okay: from unittest.mock import patch
Okay: import unittest.mock
H216: import mock
H216: from mock import patch
Okay: try: import mock
Okay: import mock # noqa
"""
msg = ('H216: The unittest.mock module should be used rather than the '
'third party mock package unless actually needed. If so, disable '
'the H216 check in hacking config and ensure mock is declared in '
"the project's requirements.")
if noqa:
return
if (re.match(third_party_mock, logical_line) or
re.match(from_third_party_mock, logical_line)):
yield (0, msg)

View File

@ -12,8 +12,8 @@
# limitations under the License.
import textwrap
from unittest import mock
import mock
import pycodestyle
from hacking.checks import except_checks

View File

@ -0,0 +1,37 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import ddt
from hacking.checks import mock_checks
from hacking import tests
@ddt.ddt
class MockingTestCase(tests.TestCase):
"""This tests hacking checks related to the use of mocking."""
@ddt.unpack
@ddt.data(
(1, 'import mock', None),
(0, 'from unittest import mock', None),
(1, 'from mock import patch', None),
(0, 'from unittest.mock import patch', None),
(0, 'from mock', '# noqa'))
def test_H216_hacking_no_third_party_mock(self, err_count, line, noqa):
if err_count > 0:
self.assertCheckFails(mock_checks.hacking_no_third_party_mock,
line, noqa)
else:
self.assertCheckPasses(mock_checks.hacking_no_third_party_mock,
line, noqa)

View File

@ -12,7 +12,6 @@ Jinja2==2.10
linecache2==1.0.0
MarkupSafe==1.0
mccabe==0.6.0
mock==3.0.0
pycodestyle==2.4.0
pyflakes==2.1.1
Pygments==2.2.0

View File

@ -45,6 +45,7 @@ flake8.extension =
H213 = hacking.checks.except_checks:hacking_assert_raises_regexp
H214 = hacking.checks.except_checks:hacking_assert_true_or_false_with_in
H215 = hacking.checks.except_checks:hacking_assert_equal_in
H216 = hacking.checks.mock_checks:hacking_no_third_party_mock
H231 = hacking.checks.python23:hacking_python3x_except_compatible
H232 = hacking.checks.python23:hacking_python3x_octal_literals
H233 = hacking.checks.python23:hacking_python3x_print_function

View File

@ -3,7 +3,6 @@
# process, which may cause wedges in the gate later.
coverage!=4.4,>=4.0 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
mock>=3.0.0 # BSD
python-subunit>=1.0.0 # Apache-2.0/BSD
stestr>=2.0.0 # Apache-2.0
testscenarios>=0.4 # Apache-2.0/BSD