Skip to content

Commit e351976

Browse files
committed
Merge remote-tracking branch 'upstream/features' into RonnyPfannschmidt/introduce-attrs
2 parents e58e8fa + b18a9de commit e351976

23 files changed

+279
-81
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Dave Hunt
4747
David Díaz-Barquero
4848
David Mohr
4949
David Vierra
50+
Daw-Ran Liou
5051
Denis Kirisov
5152
Diego Russo
5253
Dmitry Dygalo

_pytest/assertion/rewrite.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -591,23 +591,26 @@ def run(self, mod):
591591
# docstrings and __future__ imports.
592592
aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
593593
ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
594-
expect_docstring = True
594+
doc = getattr(mod, "docstring", None)
595+
expect_docstring = doc is None
596+
if doc is not None and self.is_rewrite_disabled(doc):
597+
return
595598
pos = 0
596-
lineno = 0
599+
lineno = 1
597600
for item in mod.body:
598601
if (expect_docstring and isinstance(item, ast.Expr) and
599602
isinstance(item.value, ast.Str)):
600603
doc = item.value.s
601-
if "PYTEST_DONT_REWRITE" in doc:
602-
# The module has disabled assertion rewriting.
604+
if self.is_rewrite_disabled(doc):
603605
return
604-
lineno += len(doc) - 1
605606
expect_docstring = False
606607
elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
607608
item.module != "__future__"):
608609
lineno = item.lineno
609610
break
610611
pos += 1
612+
else:
613+
lineno = item.lineno
611614
imports = [ast.Import([alias], lineno=lineno, col_offset=0)
612615
for alias in aliases]
613616
mod.body[pos:pos] = imports
@@ -633,6 +636,9 @@ def run(self, mod):
633636
not isinstance(field, ast.expr)):
634637
nodes.append(field)
635638

639+
def is_rewrite_disabled(self, docstring):
640+
return "PYTEST_DONT_REWRITE" in docstring
641+
636642
def variable(self):
637643
"""Get a new variable."""
638644
# Use a character invalid in python identifiers to avoid clashing.

_pytest/deprecated.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,8 @@ class RemovedInPytest4Warning(DeprecationWarning):
4040
" please use pytest.param(..., marks=...) instead.\n"
4141
"For more details, see: https://docs.pytest.org/en/latest/parametrize.html"
4242
)
43+
44+
COLLECTOR_MAKEITEM = RemovedInPytest4Warning(
45+
"pycollector makeitem was removed "
46+
"as it is an accidentially leaked internal api"
47+
)

_pytest/doctest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def repr_failure(self, excinfo):
127127
lines = ["%03d %s" % (i + test.lineno + 1, x)
128128
for (i, x) in enumerate(lines)]
129129
# trim docstring error lines to 10
130-
lines = lines[example.lineno - 9:example.lineno + 1]
130+
lines = lines[max(example.lineno - 9, 0):example.lineno + 1]
131131
else:
132132
lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
133133
indent = '>>>'

_pytest/mark.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from operator import attrgetter
99
from six.moves import map
1010
from .deprecated import MARK_PARAMETERSET_UNPACKING
11+
from .compat import NOTSET, getfslineno
1112

1213

1314
def alias(name, warning=None):
@@ -68,6 +69,30 @@ def extract_from(cls, parameterset, legacy_force_tuple=False):
6869

6970
return cls(argval, marks=newmarks, id=None)
7071

72+
@classmethod
73+
def _for_parameterize(cls, argnames, argvalues, function):
74+
if not isinstance(argnames, (tuple, list)):
75+
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
76+
force_tuple = len(argnames) == 1
77+
else:
78+
force_tuple = False
79+
parameters = [
80+
ParameterSet.extract_from(x, legacy_force_tuple=force_tuple)
81+
for x in argvalues]
82+
del argvalues
83+
84+
if not parameters:
85+
fs, lineno = getfslineno(function)
86+
reason = "got empty parameter set %r, function %s at %s:%d" % (
87+
argnames, function.__name__, fs, lineno)
88+
mark = MARK_GEN.skip(reason=reason)
89+
parameters.append(ParameterSet(
90+
values=(NOTSET,) * len(argnames),
91+
marks=[mark],
92+
id=None,
93+
))
94+
return argnames, parameters
95+
7196

7297
class MarkerError(Exception):
7398

@@ -273,8 +298,9 @@ def _check(self, name):
273298
pass
274299
self._markers = l = set()
275300
for line in self._config.getini("markers"):
276-
beginning = line.split(":", 1)
277-
x = beginning[0].split("(", 1)[0]
301+
marker, _ = line.split(":", 1)
302+
marker = marker.rstrip()
303+
x = marker.split("(", 1)[0]
278304
l.add(x)
279305
if name not in self._markers:
280306
raise AttributeError("%r not a registered marker" % (name,))

_pytest/python.py

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
import sys
77
import os
88
import collections
9+
import warnings
910
from textwrap import dedent
1011
from itertools import count
1112

13+
1214
import py
1315
import six
1416
from _pytest.mark import MarkerError
@@ -18,6 +20,7 @@
1820
import pluggy
1921
from _pytest import fixtures
2022
from _pytest import main
23+
from _pytest import deprecated
2124
from _pytest.compat import (
2225
isclass, isfunction, is_generator, ascii_escaped,
2326
REGEX_TYPE, STRING_TYPES, NoneType, NOTSET,
@@ -328,7 +331,7 @@ def collect(self):
328331
if name in seen:
329332
continue
330333
seen[name] = True
331-
res = self.makeitem(name, obj)
334+
res = self._makeitem(name, obj)
332335
if res is None:
333336
continue
334337
if not isinstance(res, list):
@@ -338,6 +341,10 @@ def collect(self):
338341
return l
339342

340343
def makeitem(self, name, obj):
344+
warnings.warn(deprecated.COLLECTOR_MAKEITEM, stacklevel=2)
345+
self._makeitem(name, obj)
346+
347+
def _makeitem(self, name, obj):
341348
# assert self.ihook.fspath == self.fspath, self
342349
return self.ihook.pytest_pycollect_makeitem(
343350
collector=self, name=name, obj=obj)
@@ -769,30 +776,12 @@ def parametrize(self, argnames, argvalues, indirect=False, ids=None,
769776
to set a dynamic scope using test context or configuration.
770777
"""
771778
from _pytest.fixtures import scope2index
772-
from _pytest.mark import MARK_GEN, ParameterSet
779+
from _pytest.mark import ParameterSet
773780
from py.io import saferepr
774-
775-
if not isinstance(argnames, (tuple, list)):
776-
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
777-
force_tuple = len(argnames) == 1
778-
else:
779-
force_tuple = False
780-
parameters = [
781-
ParameterSet.extract_from(x, legacy_force_tuple=force_tuple)
782-
for x in argvalues]
781+
argnames, parameters = ParameterSet._for_parameterize(
782+
argnames, argvalues, self.function)
783783
del argvalues
784784

785-
if not parameters:
786-
fs, lineno = getfslineno(self.function)
787-
reason = "got empty parameter set %r, function %s at %s:%d" % (
788-
argnames, self.function.__name__, fs, lineno)
789-
mark = MARK_GEN.skip(reason=reason)
790-
parameters.append(ParameterSet(
791-
values=(NOTSET,) * len(argnames),
792-
marks=[mark],
793-
id=None,
794-
))
795-
796785
if scope is None:
797786
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
798787

changelog/1505.doc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduce a dedicated section about conftest.py.

changelog/2658.doc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Append example for pytest.param in the example/parametrize document.

changelog/2856.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Strip whitespace from marker names when reading them from INI config.

changelog/2877.trivial

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Internal move of the parameterset extraction to a more maintainable place.

0 commit comments

Comments
 (0)