Skip to content

Commit eced536

Browse files
authored
Merge pull request #7435 from bluetech/python-cleanups
python: a few cleanups
2 parents bd4977e + ae83dbd commit eced536

File tree

3 files changed

+32
-55
lines changed

3 files changed

+32
-55
lines changed

src/_pytest/mark/structures.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@
2727
from _pytest.outcomes import fail
2828
from _pytest.warning_types import PytestUnknownMarkWarning
2929

30-
if TYPE_CHECKING:
31-
from _pytest.python import FunctionDefinition
32-
3330

3431
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
3532

@@ -159,7 +156,7 @@ def _for_parametrize(
159156
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
160157
func,
161158
config: Config,
162-
function_definition: "FunctionDefinition",
159+
nodeid: str,
163160
) -> Tuple[Union[List[str], Tuple[str, ...]], List["ParameterSet"]]:
164161
argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues)
165162
parameters = cls._parse_parametrize_parameters(argvalues, force_tuple)
@@ -177,7 +174,7 @@ def _for_parametrize(
177174
)
178175
fail(
179176
msg.format(
180-
nodeid=function_definition.nodeid,
177+
nodeid=nodeid,
181178
values=param.values,
182179
names=argnames,
183180
names_len=len(argnames),

src/_pytest/python.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,12 @@ def pytest_pycollect_makemodule(path: py.path.local, parent) -> "Module":
209209
return mod
210210

211211

212-
@hookimpl(hookwrapper=True)
213-
def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj):
214-
outcome = yield
215-
res = outcome.get_result()
216-
if res is not None:
217-
return
212+
@hookimpl(trylast=True)
213+
def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj: object):
218214
# nothing was collected elsewhere, let's do it here
219215
if safe_isclass(obj):
220216
if collector.istestclass(obj, name):
221-
outcome.force_result(Class.from_parent(collector, name=name, obj=obj))
217+
return Class.from_parent(collector, name=name, obj=obj)
222218
elif collector.istestfunction(obj, name):
223219
# mock seems to store unbound methods (issue473), normalize it
224220
obj = getattr(obj, "__func__", obj)
@@ -245,7 +241,7 @@ def pytest_pycollect_makeitem(collector: "PyCollector", name: str, obj):
245241
res.warn(PytestCollectionWarning(reason))
246242
else:
247243
res = list(collector._genfunctions(name, obj))
248-
outcome.force_result(res)
244+
return res
249245

250246

251247
class PyobjMixin:
@@ -980,7 +976,7 @@ def parametrize(
980976
argvalues,
981977
self.function,
982978
self.config,
983-
function_definition=self.definition,
979+
nodeid=self.definition.nodeid,
984980
)
985981
del argvalues
986982

@@ -1003,7 +999,9 @@ def parametrize(
1003999
if generated_ids is not None:
10041000
ids = generated_ids
10051001

1006-
ids = self._resolve_arg_ids(argnames, ids, parameters, item=self.definition)
1002+
ids = self._resolve_arg_ids(
1003+
argnames, ids, parameters, nodeid=self.definition.nodeid
1004+
)
10071005

10081006
# Store used (possibly generated) ids with parametrize Marks.
10091007
if _param_mark and _param_mark._param_ids_from and generated_ids is None:
@@ -1042,15 +1040,15 @@ def _resolve_arg_ids(
10421040
]
10431041
],
10441042
parameters: typing.Sequence[ParameterSet],
1045-
item,
1043+
nodeid: str,
10461044
) -> List[str]:
10471045
"""Resolves the actual ids for the given argnames, based on the ``ids`` parameter given
10481046
to ``parametrize``.
10491047
10501048
:param List[str] argnames: list of argument names passed to ``parametrize()``.
10511049
:param ids: the ids parameter of the parametrized call (see docs).
10521050
:param List[ParameterSet] parameters: the list of parameter values, same size as ``argnames``.
1053-
:param Item item: the item that generated this parametrized call.
1051+
:param str str: the nodeid of the item that generated this parametrized call.
10541052
:rtype: List[str]
10551053
:return: the list of ids for each argname given
10561054
"""
@@ -1063,7 +1061,7 @@ def _resolve_arg_ids(
10631061
else:
10641062
idfn = None
10651063
ids_ = self._validate_ids(ids, parameters, self.function.__name__)
1066-
return idmaker(argnames, parameters, idfn, ids_, self.config, item=item)
1064+
return idmaker(argnames, parameters, idfn, ids_, self.config, nodeid=nodeid)
10671065

10681066
def _validate_ids(
10691067
self,
@@ -1223,7 +1221,7 @@ def _idval(
12231221
argname: str,
12241222
idx: int,
12251223
idfn: Optional[Callable[[object], Optional[object]]],
1226-
item,
1224+
nodeid: Optional[str],
12271225
config: Optional[Config],
12281226
) -> str:
12291227
if idfn:
@@ -1232,8 +1230,9 @@ def _idval(
12321230
if generated_id is not None:
12331231
val = generated_id
12341232
except Exception as e:
1235-
msg = "{}: error raised while trying to determine id of parameter '{}' at position {}"
1236-
msg = msg.format(item.nodeid, argname, idx)
1233+
prefix = "{}: ".format(nodeid) if nodeid is not None else ""
1234+
msg = "error raised while trying to determine id of parameter '{}' at position {}"
1235+
msg = prefix + msg.format(argname, idx)
12371236
raise ValueError(msg) from e
12381237
elif config:
12391238
hook_id = config.hook.pytest_make_parametrize_id(
@@ -1263,15 +1262,15 @@ def _idvalset(
12631262
argnames: Iterable[str],
12641263
idfn: Optional[Callable[[object], Optional[object]]],
12651264
ids: Optional[List[Union[None, str]]],
1266-
item,
1265+
nodeid: Optional[str],
12671266
config: Optional[Config],
12681267
):
12691268
if parameterset.id is not None:
12701269
return parameterset.id
12711270
id = None if ids is None or idx >= len(ids) else ids[idx]
12721271
if id is None:
12731272
this_id = [
1274-
_idval(val, argname, idx, idfn, item=item, config=config)
1273+
_idval(val, argname, idx, idfn, nodeid=nodeid, config=config)
12751274
for val, argname in zip(parameterset.values, argnames)
12761275
]
12771276
return "-".join(this_id)
@@ -1285,10 +1284,12 @@ def idmaker(
12851284
idfn: Optional[Callable[[object], Optional[object]]] = None,
12861285
ids: Optional[List[Union[None, str]]] = None,
12871286
config: Optional[Config] = None,
1288-
item=None,
1287+
nodeid: Optional[str] = None,
12891288
) -> List[str]:
12901289
resolved_ids = [
1291-
_idvalset(valindex, parameterset, argnames, idfn, ids, config=config, item=item)
1290+
_idvalset(
1291+
valindex, parameterset, argnames, idfn, ids, config=config, nodeid=nodeid
1292+
)
12921293
for valindex, parameterset in enumerate(parametersets)
12931294
]
12941295

@@ -1589,9 +1590,8 @@ def _prunetraceback(self, excinfo: ExceptionInfo) -> None:
15891590

15901591
# TODO: Type ignored -- breaks Liskov Substitution.
15911592
def repr_failure( # type: ignore[override] # noqa: F821
1592-
self, excinfo: ExceptionInfo[BaseException], outerr: None = None
1593+
self, excinfo: ExceptionInfo[BaseException],
15931594
) -> Union[str, TerminalRepr]:
1594-
assert outerr is None, "XXX outerr usage is deprecated"
15951595
style = self.config.getoption("tbstyle", "auto")
15961596
if style == "auto":
15971597
style = "long"

testing/python/metafunc.py

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from _pytest.outcomes import fail
2020
from _pytest.pytester import Testdir
2121
from _pytest.python import _idval
22+
from _pytest.python import idmaker
2223

2324

2425
class TestMetafunc:
@@ -35,10 +36,11 @@ def __init__(self, names):
3536
@attr.s
3637
class DefinitionMock(python.FunctionDefinition):
3738
obj = attr.ib()
39+
_nodeid = attr.ib()
3840

3941
names = fixtures.getfuncargnames(func)
4042
fixtureinfo = FuncFixtureInfoMock(names) # type: Any
41-
definition = DefinitionMock._create(func) # type: Any
43+
definition = DefinitionMock._create(func, "mock::nodeid") # type: Any
4244
return python.Metafunc(definition, fixtureinfo, config)
4345

4446
def test_no_funcargs(self) -> None:
@@ -270,7 +272,7 @@ class A:
270272
deadline=400.0
271273
) # very close to std deadline and CI boxes are not reliable in CPU power
272274
def test_idval_hypothesis(self, value) -> None:
273-
escaped = _idval(value, "a", 6, None, item=None, config=None)
275+
escaped = _idval(value, "a", 6, None, nodeid=None, config=None)
274276
assert isinstance(escaped, str)
275277
escaped.encode("ascii")
276278

@@ -292,7 +294,7 @@ def test_unicode_idval(self) -> None:
292294
),
293295
]
294296
for val, expected in values:
295-
assert _idval(val, "a", 6, None, item=None, config=None) == expected
297+
assert _idval(val, "a", 6, None, nodeid=None, config=None) == expected
296298

297299
def test_unicode_idval_with_config(self) -> None:
298300
"""unittest for expected behavior to obtain ids with
@@ -321,7 +323,7 @@ def getini(self, name):
321323
("ação", MockConfig({option: False}), "a\\xe7\\xe3o"),
322324
] # type: List[Tuple[str, Any, str]]
323325
for val, config, expected in values:
324-
actual = _idval(val, "a", 6, None, item=None, config=config)
326+
actual = _idval(val, "a", 6, None, nodeid=None, config=config)
325327
assert actual == expected
326328

327329
def test_bytes_idval(self) -> None:
@@ -338,7 +340,7 @@ def test_bytes_idval(self) -> None:
338340
("αρά".encode(), "\\xce\\xb1\\xcf\\x81\\xce\\xac"),
339341
]
340342
for val, expected in values:
341-
assert _idval(val, "a", 6, idfn=None, item=None, config=None) == expected
343+
assert _idval(val, "a", 6, idfn=None, nodeid=None, config=None) == expected
342344

343345
def test_class_or_function_idval(self) -> None:
344346
"""unittest for the expected behavior to obtain ids for parametrized
@@ -353,12 +355,10 @@ def test_function():
353355

354356
values = [(TestClass, "TestClass"), (test_function, "test_function")]
355357
for val, expected in values:
356-
assert _idval(val, "a", 6, None, item=None, config=None) == expected
358+
assert _idval(val, "a", 6, None, nodeid=None, config=None) == expected
357359

358360
def test_idmaker_autoname(self) -> None:
359361
"""#250"""
360-
from _pytest.python import idmaker
361-
362362
result = idmaker(
363363
("a", "b"), [pytest.param("string", 1.0), pytest.param("st-ring", 2.0)]
364364
)
@@ -373,14 +373,10 @@ def test_idmaker_autoname(self) -> None:
373373
assert result == ["a0-\\xc3\\xb4"]
374374

375375
def test_idmaker_with_bytes_regex(self) -> None:
376-
from _pytest.python import idmaker
377-
378376
result = idmaker(("a"), [pytest.param(re.compile(b"foo"), 1.0)])
379377
assert result == ["foo"]
380378

381379
def test_idmaker_native_strings(self) -> None:
382-
from _pytest.python import idmaker
383-
384380
result = idmaker(
385381
("a", "b"),
386382
[
@@ -414,8 +410,6 @@ def test_idmaker_native_strings(self) -> None:
414410
]
415411

416412
def test_idmaker_non_printable_characters(self) -> None:
417-
from _pytest.python import idmaker
418-
419413
result = idmaker(
420414
("s", "n"),
421415
[
@@ -430,8 +424,6 @@ def test_idmaker_non_printable_characters(self) -> None:
430424
assert result == ["\\x00-1", "\\x05-2", "\\x00-3", "\\x05-4", "\\t-5", "\\t-6"]
431425

432426
def test_idmaker_manual_ids_must_be_printable(self) -> None:
433-
from _pytest.python import idmaker
434-
435427
result = idmaker(
436428
("s",),
437429
[
@@ -442,16 +434,13 @@ def test_idmaker_manual_ids_must_be_printable(self) -> None:
442434
assert result == ["hello \\x00", "hello \\x05"]
443435

444436
def test_idmaker_enum(self) -> None:
445-
from _pytest.python import idmaker
446-
447437
enum = pytest.importorskip("enum")
448438
e = enum.Enum("Foo", "one, two")
449439
result = idmaker(("a", "b"), [pytest.param(e.one, e.two)])
450440
assert result == ["Foo.one-Foo.two"]
451441

452442
def test_idmaker_idfn(self) -> None:
453443
"""#351"""
454-
from _pytest.python import idmaker
455444

456445
def ids(val: object) -> Optional[str]:
457446
if isinstance(val, Exception):
@@ -471,7 +460,6 @@ def ids(val: object) -> Optional[str]:
471460

472461
def test_idmaker_idfn_unique_names(self) -> None:
473462
"""#351"""
474-
from _pytest.python import idmaker
475463

476464
def ids(val: object) -> str:
477465
return "a"
@@ -492,7 +480,6 @@ def test_idmaker_with_idfn_and_config(self) -> None:
492480
disable_test_id_escaping_and_forfeit_all_rights_to_community_support
493481
option. (#5294)
494482
"""
495-
from _pytest.python import idmaker
496483

497484
class MockConfig:
498485
def __init__(self, config):
@@ -525,7 +512,6 @@ def test_idmaker_with_ids_and_config(self) -> None:
525512
disable_test_id_escaping_and_forfeit_all_rights_to_community_support
526513
option. (#5294)
527514
"""
528-
from _pytest.python import idmaker
529515

530516
class MockConfig:
531517
def __init__(self, config):
@@ -607,16 +593,12 @@ def test_int(arg):
607593
)
608594

609595
def test_idmaker_with_ids(self) -> None:
610-
from _pytest.python import idmaker
611-
612596
result = idmaker(
613597
("a", "b"), [pytest.param(1, 2), pytest.param(3, 4)], ids=["a", None]
614598
)
615599
assert result == ["a", "3-4"]
616600

617601
def test_idmaker_with_paramset_id(self) -> None:
618-
from _pytest.python import idmaker
619-
620602
result = idmaker(
621603
("a", "b"),
622604
[pytest.param(1, 2, id="me"), pytest.param(3, 4, id="you")],
@@ -625,8 +607,6 @@ def test_idmaker_with_paramset_id(self) -> None:
625607
assert result == ["me", "you"]
626608

627609
def test_idmaker_with_ids_unique_names(self) -> None:
628-
from _pytest.python import idmaker
629-
630610
result = idmaker(
631611
("a"), map(pytest.param, [1, 2, 3, 4, 5]), ids=["a", "a", "b", "c", "b"]
632612
)

0 commit comments

Comments
 (0)