Skip to content

Commit 5dd509c

Browse files
authored
Merge pull request pytest-dev#4338 from blueyed/merge-master
Merge master into features
2 parents 4c00552 + 9d838fa commit 5dd509c

14 files changed

+153
-131
lines changed

CHANGELOG.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Features
3030
existing ``pytest_enter_pdb`` hook.
3131

3232

33-
- `#4147 <https://github.com/pytest-dev/pytest/issues/4147>`_: Add ``-sw``, ``--stepwise`` as an alternative to ``--lf -x`` for stopping at the first failure, but starting the next test invocation from that test. See `the documentation <https://docs.pytest.org/en/latest/cache.html#stepwise>`__ for more info.
33+
- `#4147 <https://github.com/pytest-dev/pytest/issues/4147>`_: Add ``--sw``, ``--stepwise`` as an alternative to ``--lf -x`` for stopping at the first failure, but starting the next test invocation from that test. See `the documentation <https://docs.pytest.org/en/latest/cache.html#stepwise>`__ for more info.
3434

3535

3636
- `#4188 <https://github.com/pytest-dev/pytest/issues/4188>`_: Make ``--color`` emit colorful dots when not running in verbose mode. Earlier, it would only colorize the test-by-test output if ``--verbose`` was also passed.
@@ -60,6 +60,8 @@ Bug Fixes
6060
- `#611 <https://github.com/pytest-dev/pytest/issues/611>`_: Naming a fixture ``request`` will now raise a warning: the ``request`` fixture is internal and
6161
should not be overwritten as it will lead to internal errors.
6262

63+
- `#4266 <https://github.com/pytest-dev/pytest/issues/4266>`_: Handle (ignore) exceptions raised during collection, e.g. with Django's LazySettings proxy class.
64+
6365

6466

6567
Improved Documentation

changelog/4305.trivial.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replace byte/unicode helpers in test_capture with python level syntax.

changelog/4306.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Parse ``minversion`` as an actual version and not as dot-separated strings.

changelog/4310.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix duplicate collection due to multiple args matching the same packages.

doc/4266.bugfix.rst

-1
This file was deleted.

doc/en/plugins.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ To see a complete list of all plugins with their latest testing
5959
status against different pytest and Python versions, please visit
6060
`plugincompat <http://plugincompat.herokuapp.com/>`_.
6161

62-
You may also discover more plugins through a `pytest- pypi.python.org search`_.
62+
You may also discover more plugins through a `pytest- pypi.org search`_.
6363

64-
.. _`pytest- pypi.python.org search`: https://pypi.org/search/?q=pytest-
64+
.. _`pytest- pypi.org search`: https://pypi.org/search/?q=pytest-
6565

6666

6767
.. _`available installable plugins`:

src/_pytest/assertion/util.py

+34-42
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
import _pytest._code
1212
from ..compat import Sequence
1313

14-
u = six.text_type
15-
1614
# The _reprcompare attribute on the util module is used by the new assertion
1715
# interpretation code and assertion rewriter to detect this plugin was
1816
# loaded and in turn call the hooks defined here as part of the
@@ -23,9 +21,9 @@
2321
# the re-encoding is needed for python2 repr
2422
# with non-ascii characters (see issue 877 and 1379)
2523
def ecu(s):
26-
try:
27-
return u(s, "utf-8", "replace")
28-
except TypeError:
24+
if isinstance(s, bytes):
25+
return s.decode("UTF-8", "replace")
26+
else:
2927
return s
3028

3129

@@ -42,7 +40,7 @@ def format_explanation(explanation):
4240
explanation = ecu(explanation)
4341
lines = _split_explanation(explanation)
4442
result = _format_lines(lines)
45-
return u("\n").join(result)
43+
return u"\n".join(result)
4644

4745

4846
def _split_explanation(explanation):
@@ -52,7 +50,7 @@ def _split_explanation(explanation):
5250
Any other newlines will be escaped and appear in the line as the
5351
literal '\n' characters.
5452
"""
55-
raw_lines = (explanation or u("")).split("\n")
53+
raw_lines = (explanation or u"").split("\n")
5654
lines = [raw_lines[0]]
5755
for values in raw_lines[1:]:
5856
if values and values[0] in ["{", "}", "~", ">"]:
@@ -77,13 +75,13 @@ def _format_lines(lines):
7775
for line in lines[1:]:
7876
if line.startswith("{"):
7977
if stackcnt[-1]:
80-
s = u("and ")
78+
s = u"and "
8179
else:
82-
s = u("where ")
80+
s = u"where "
8381
stack.append(len(result))
8482
stackcnt[-1] += 1
8583
stackcnt.append(0)
86-
result.append(u(" +") + u(" ") * (len(stack) - 1) + s + line[1:])
84+
result.append(u" +" + u" " * (len(stack) - 1) + s + line[1:])
8785
elif line.startswith("}"):
8886
stack.pop()
8987
stackcnt.pop()
@@ -92,7 +90,7 @@ def _format_lines(lines):
9290
assert line[0] in ["~", ">"]
9391
stack[-1] += 1
9492
indent = len(stack) if line.startswith("~") else len(stack) - 1
95-
result.append(u(" ") * indent + line[1:])
93+
result.append(u" " * indent + line[1:])
9694
assert len(stack) == 1
9795
return result
9896

@@ -110,7 +108,7 @@ def assertrepr_compare(config, op, left, right):
110108
left_repr = py.io.saferepr(left, maxsize=int(width // 2))
111109
right_repr = py.io.saferepr(right, maxsize=width - len(left_repr))
112110

113-
summary = u("%s %s %s") % (ecu(left_repr), op, ecu(right_repr))
111+
summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr))
114112

115113
def issequence(x):
116114
return isinstance(x, Sequence) and not isinstance(x, basestring)
@@ -155,11 +153,9 @@ def isiterable(obj):
155153
explanation = _notin_text(left, right, verbose)
156154
except Exception:
157155
explanation = [
158-
u(
159-
"(pytest_assertion plugin: representation of details failed. "
160-
"Probably an object has a faulty __repr__.)"
161-
),
162-
u(_pytest._code.ExceptionInfo()),
156+
u"(pytest_assertion plugin: representation of details failed. "
157+
u"Probably an object has a faulty __repr__.)",
158+
six.text_type(_pytest._code.ExceptionInfo()),
163159
]
164160

165161
if not explanation:
@@ -203,8 +199,7 @@ def escape_for_readable_diff(binary_text):
203199
if i > 42:
204200
i -= 10 # Provide some context
205201
explanation = [
206-
u("Skipping %s identical leading characters in diff, use -v to show")
207-
% i
202+
u"Skipping %s identical leading characters in diff, use -v to show" % i
208203
]
209204
left = left[i:]
210205
right = right[i:]
@@ -215,11 +210,8 @@ def escape_for_readable_diff(binary_text):
215210
if i > 42:
216211
i -= 10 # Provide some context
217212
explanation += [
218-
u(
219-
"Skipping %s identical trailing "
220-
"characters in diff, use -v to show"
221-
)
222-
% i
213+
u"Skipping {} identical trailing "
214+
u"characters in diff, use -v to show".format(i)
223215
]
224216
left = left[:-i]
225217
right = right[:-i]
@@ -237,21 +229,21 @@ def escape_for_readable_diff(binary_text):
237229

238230
def _compare_eq_iterable(left, right, verbose=False):
239231
if not verbose:
240-
return [u("Use -v to get the full diff")]
232+
return [u"Use -v to get the full diff"]
241233
# dynamic import to speedup pytest
242234
import difflib
243235

244236
try:
245237
left_formatting = pprint.pformat(left).splitlines()
246238
right_formatting = pprint.pformat(right).splitlines()
247-
explanation = [u("Full diff:")]
239+
explanation = [u"Full diff:"]
248240
except Exception:
249241
# hack: PrettyPrinter.pformat() in python 2 fails when formatting items that can't be sorted(), ie, calling
250242
# sorted() on a list would raise. See issue #718.
251243
# As a workaround, the full diff is generated by using the repr() string of each item of each container.
252244
left_formatting = sorted(repr(x) for x in left)
253245
right_formatting = sorted(repr(x) for x in right)
254-
explanation = [u("Full diff (fallback to calling repr on each item):")]
246+
explanation = [u"Full diff (fallback to calling repr on each item):"]
255247
explanation.extend(
256248
line.strip() for line in difflib.ndiff(left_formatting, right_formatting)
257249
)
@@ -262,16 +254,16 @@ def _compare_eq_sequence(left, right, verbose=False):
262254
explanation = []
263255
for i in range(min(len(left), len(right))):
264256
if left[i] != right[i]:
265-
explanation += [u("At index %s diff: %r != %r") % (i, left[i], right[i])]
257+
explanation += [u"At index %s diff: %r != %r" % (i, left[i], right[i])]
266258
break
267259
if len(left) > len(right):
268260
explanation += [
269-
u("Left contains more items, first extra item: %s")
261+
u"Left contains more items, first extra item: %s"
270262
% py.io.saferepr(left[len(right)])
271263
]
272264
elif len(left) < len(right):
273265
explanation += [
274-
u("Right contains more items, first extra item: %s")
266+
u"Right contains more items, first extra item: %s"
275267
% py.io.saferepr(right[len(left)])
276268
]
277269
return explanation
@@ -282,11 +274,11 @@ def _compare_eq_set(left, right, verbose=False):
282274
diff_left = left - right
283275
diff_right = right - left
284276
if diff_left:
285-
explanation.append(u("Extra items in the left set:"))
277+
explanation.append(u"Extra items in the left set:")
286278
for item in diff_left:
287279
explanation.append(py.io.saferepr(item))
288280
if diff_right:
289-
explanation.append(u("Extra items in the right set:"))
281+
explanation.append(u"Extra items in the right set:")
290282
for item in diff_right:
291283
explanation.append(py.io.saferepr(item))
292284
return explanation
@@ -297,26 +289,26 @@ def _compare_eq_dict(left, right, verbose=False):
297289
common = set(left).intersection(set(right))
298290
same = {k: left[k] for k in common if left[k] == right[k]}
299291
if same and verbose < 2:
300-
explanation += [u("Omitting %s identical items, use -vv to show") % len(same)]
292+
explanation += [u"Omitting %s identical items, use -vv to show" % len(same)]
301293
elif same:
302-
explanation += [u("Common items:")]
294+
explanation += [u"Common items:"]
303295
explanation += pprint.pformat(same).splitlines()
304296
diff = {k for k in common if left[k] != right[k]}
305297
if diff:
306-
explanation += [u("Differing items:")]
298+
explanation += [u"Differing items:"]
307299
for k in diff:
308300
explanation += [
309301
py.io.saferepr({k: left[k]}) + " != " + py.io.saferepr({k: right[k]})
310302
]
311303
extra_left = set(left) - set(right)
312304
if extra_left:
313-
explanation.append(u("Left contains more items:"))
305+
explanation.append(u"Left contains more items:")
314306
explanation.extend(
315307
pprint.pformat({k: left[k] for k in extra_left}).splitlines()
316308
)
317309
extra_right = set(right) - set(left)
318310
if extra_right:
319-
explanation.append(u("Right contains more items:"))
311+
explanation.append(u"Right contains more items:")
320312
explanation.extend(
321313
pprint.pformat({k: right[k] for k in extra_right}).splitlines()
322314
)
@@ -329,14 +321,14 @@ def _notin_text(term, text, verbose=False):
329321
tail = text[index + len(term) :]
330322
correct_text = head + tail
331323
diff = _diff_text(correct_text, text, verbose)
332-
newdiff = [u("%s is contained here:") % py.io.saferepr(term, maxsize=42)]
324+
newdiff = [u"%s is contained here:" % py.io.saferepr(term, maxsize=42)]
333325
for line in diff:
334-
if line.startswith(u("Skipping")):
326+
if line.startswith(u"Skipping"):
335327
continue
336-
if line.startswith(u("- ")):
328+
if line.startswith(u"- "):
337329
continue
338-
if line.startswith(u("+ ")):
339-
newdiff.append(u(" ") + line[2:])
330+
if line.startswith(u"+ "):
331+
newdiff.append(u" " + line[2:])
340332
else:
341333
newdiff.append(line)
342334
return newdiff

src/_pytest/capture.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ class FDCaptureBinary(object):
504504
snap() produces `bytes`
505505
"""
506506

507-
EMPTY_BUFFER = bytes()
507+
EMPTY_BUFFER = b""
508508

509509
def __init__(self, targetfd, tmpfile=None):
510510
self.targetfd = targetfd
@@ -630,7 +630,7 @@ def writeorg(self, data):
630630

631631

632632
class SysCaptureBinary(SysCapture):
633-
EMPTY_BUFFER = bytes()
633+
EMPTY_BUFFER = b""
634634

635635
def snap(self):
636636
res = self.tmpfile.buffer.getvalue()

src/_pytest/config/__init__.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import sys
1212
import types
1313
import warnings
14+
from distutils.version import LooseVersion
1415

1516
import py
1617
import six
@@ -817,9 +818,7 @@ def _checkversion(self):
817818

818819
minver = self.inicfg.get("minversion", None)
819820
if minver:
820-
ver = minver.split(".")
821-
myver = pytest.__version__.split(".")
822-
if myver < ver:
821+
if LooseVersion(minver) > LooseVersion(pytest.__version__):
823822
raise pytest.UsageError(
824823
"%s:%d: requires pytest-%s, actual pytest-%s'"
825824
% (

0 commit comments

Comments
 (0)