Skip to content
This repository was archived by the owner on Dec 8, 2022. It is now read-only.

Commit 27b2736

Browse files
author
Leonidas Loucas
committed
feat: Support for pytest_describe
1 parent a86b89e commit 27b2736

File tree

12 files changed

+140
-5
lines changed

12 files changed

+140
-5
lines changed

pylint_pytest/checkers/fixture.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
import os
23
import sys
34
from pathlib import Path
@@ -10,6 +11,7 @@
1011
import pytest
1112
from ..utils import (
1213
_can_use_fixture,
14+
_is_in_describe_section_when_enabled,
1315
_is_pytest_mark,
1416
_is_pytest_mark_usefixtures,
1517
_is_pytest_fixture,
@@ -72,6 +74,7 @@ class FixtureChecker(BasePytestChecker):
7274
_invoked_with_func_args = set()
7375
_invoked_with_usefixtures = set()
7476
_original_add_message = callable
77+
enable_plugin = True
7578

7679
def open(self):
7780
# patch VariablesChecker.add_message
@@ -217,6 +220,11 @@ def patch_add_message(self, msgid, line=None, node=None, args=None,
217220
'''
218221
- intercept and discard unwanted warning messages
219222
'''
223+
if not FixtureChecker.enable_plugin:
224+
FixtureChecker._original_add_message(
225+
self, msgid, line, node, args, confidence, col_offset
226+
)
227+
return
220228
# check W0611 unused-import
221229
if msgid == 'unused-import':
222230
# actual attribute name is not passed as arg so...dirty hack
@@ -265,6 +273,12 @@ def patch_add_message(self, msgid, line=None, node=None, args=None,
265273
node.name in FixtureChecker._pytest_fixtures:
266274
return
267275

276+
# check W0612 unused-variable
277+
if msgid == 'unused-variable' and \
278+
_is_in_describe_section_when_enabled(node):
279+
return
280+
281+
268282
if int(pylint.__version__.split('.')[0]) >= 2:
269283
FixtureChecker._original_add_message(
270284
self, msgid, line, node, args, confidence, col_offset)

pylint_pytest/utils.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
11
import inspect
2+
import re
23
import astroid
4+
import pytest
5+
import sys
6+
7+
8+
PYTEST_LT_7_0 = getattr(pytest, 'version_tuple', (0, 0)) < (7, 0)
9+
10+
11+
try:
12+
import pytest_describe
13+
PYTEST_DESCRIBE = True
14+
except ImportError:
15+
PYTEST_DESCRIBE = False
16+
describe_prefixes_option = ()
17+
18+
19+
if PYTEST_DESCRIBE:
20+
describe_prefix = "describe"
21+
try:
22+
import _pytest.config.findpaths
23+
config = _pytest.config.findpaths.determine_setup([], sys.argv[1:])
24+
if config:
25+
if PYTEST_LT_7_0:
26+
describe_prefix = config[2].config.sections.get('tool:pytest', {}).get('describe_prefixes', describe_prefix)
27+
else:
28+
describe_prefix = config[2].get('describe_prefixes', describe_prefix)
29+
finally:
30+
describe_prefixes_option = tuple(describe_prefix.split(' '))
31+
32+
33+
describe_prefix_matcher = re.compile(fr'^{"|".join(describe_prefixes_option)}_.+$')
34+
35+
36+
def _is_in_describe_section_when_enabled(node):
37+
import _pytest.config.findpaths
38+
describe_prefix = "describe"
39+
config = _pytest.config.findpaths.determine_setup([], sys.argv[1:])
40+
if config:
41+
if PYTEST_LT_7_0:
42+
describe_prefix = config[2].config.sections.get('tool:pytest', {}).get('describe_prefixes', describe_prefix)
43+
else:
44+
describe_prefix = config[2].get('describe_prefixes', describe_prefix)
45+
return (PYTEST_DESCRIBE and
46+
(node.parent is not None and isinstance(node.parent, astroid.FunctionDef) and re.match(describe_prefix_matcher, node.parent.name)))
347

448

549
def _is_pytest_mark_usefixtures(decorator):
@@ -84,7 +128,7 @@ def _can_use_fixture(function):
84128
if isinstance(function, astroid.FunctionDef):
85129

86130
# test_*, *_test
87-
if function.name.startswith('test_') or function.name.endswith('_test'):
131+
if function.name.startswith('test_') or function.name.endswith('_test') or _is_in_describe_section_when_enabled(function):
88132
return True
89133

90134
if function.decorators:

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ test = pytest
44
[tool:pytest]
55
addopts = --verbose
66
python_files = tests/test_*.py
7+
describe_prefixes = describe context
78

89
[bdist_wheel]
9-
universal = 1
10+
universal = 1

setup.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
setup(
1414
name='pylint-pytest',
15-
version='1.1.2',
15+
version='1.1.3',
1616
author='Reverb Chu',
1717
author_email='pylint-pytest@reverbc.tw',
1818
maintainer='Reverb Chu',
@@ -27,6 +27,9 @@
2727
'pylint',
2828
'pytest>=4.6',
2929
],
30+
extras_require={
31+
'pytest_describe': ['pytest_describe'],
32+
},
3033
python_requires='>=3.6',
3134
classifiers=[
3235
'Development Status :: 5 - Production/Stable',
@@ -43,6 +46,6 @@
4346
'Operating System :: OS Independent',
4447
'License :: OSI Approved :: MIT License',
4548
],
46-
tests_require=['pytest', 'pylint'],
49+
tests_require=['pytest', 'pytest_describe', 'pylint'],
4750
keywords=['pylint', 'pytest', 'plugin'],
4851
)

tests/base_tester.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class BasePytestTester(object):
2828

2929
def run_linter(self, enable_plugin, file_path=None):
3030
self.enable_plugin = enable_plugin
31+
self.CHECKER_CLASS.enable_plugin = enable_plugin
3132

3233
# pylint: disable=protected-access
3334
if file_path is None:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import pytest
2+
3+
def describe_stuff():
4+
@pytest.fixture()
5+
def fix():
6+
pass
7+
8+
def run(fix):
9+
pass
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import pytest
2+
3+
def describe_stuff():
4+
@pytest.fixture()
5+
def fix():
6+
pass
7+
8+
def context_more():
9+
def run(fix):
10+
pass
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import pytest
2+
3+
def describe_stuff():
4+
@pytest.fixture()
5+
def fix():
6+
pass
7+
8+
def run(fix):
9+
pass
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pytest
2+
3+
def describe_stuff():
4+
@pytest.fixture()
5+
def fix():
6+
pass
7+
8+
def context_more():
9+
@pytest.fixture()
10+
def fix(fix):
11+
pass
12+
13+
def run(fix):
14+
pass

tests/test_unused_argument.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,13 @@ def test_caller_not_a_test_func(self, enable_plugin):
2828
def test_args_and_kwargs(self, enable_plugin):
2929
self.run_linter(enable_plugin)
3030
self.verify_messages(2)
31+
32+
@pytest.mark.parametrize('enable_plugin', [True, False])
33+
def test_describe(self, enable_plugin):
34+
self.run_linter(enable_plugin)
35+
self.verify_messages(0 if enable_plugin else 1)
36+
37+
@pytest.mark.parametrize('enable_plugin', [True, False])
38+
def test_describe_nested(self, enable_plugin):
39+
self.run_linter(enable_plugin)
40+
self.verify_messages(0 if enable_plugin else 1)

0 commit comments

Comments
 (0)