Skip to content

Commit 943bbdd

Browse files
authored
Merge pull request #4100 from nicoddemus/merge-master-into-features
Merge master into features
2 parents b895816 + 9a3836a commit 943bbdd

38 files changed

+176
-162
lines changed

.pre-commit-config.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ repos:
77
args: [--safe, --quiet]
88
language_version: python3
99
- repo: https://github.com/asottile/blacken-docs
10-
rev: v0.2.0
10+
rev: v0.3.0
1111
hooks:
1212
- id: blacken-docs
13-
additional_dependencies: [black==18.6b4]
13+
additional_dependencies: [black==18.9b0]
1414
language_version: python3
1515
- repo: https://github.com/pre-commit/pre-commit-hooks
16-
rev: v1.3.0
16+
rev: v1.4.0-1
1717
hooks:
1818
- id: trailing-whitespace
1919
- id: end-of-file-fixer
@@ -22,11 +22,12 @@ repos:
2222
exclude: _pytest/debugging.py
2323
- id: flake8
2424
- repo: https://github.com/asottile/pyupgrade
25-
rev: v1.2.0
25+
rev: v1.8.0
2626
hooks:
27-
- id: pyupgrade
27+
- id: pyupgrade
28+
args: [--keep-percent-format]
2829
- repo: https://github.com/pre-commit/pygrep-hooks
29-
rev: v1.0.0
30+
rev: v1.1.0
3031
hooks:
3132
- id: rst-backticks
3233
- repo: local

bench/bench_argcomplete.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
# 10000 iterations, just for relative comparison
42
# 2.7.5 3.3.2
53
# FilesCompleter 75.1109 69.2116

bench/manyparam.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import pytest
32

43

changelog/2535.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve error message when test functions of ``unittest.TestCase`` subclasses use a parametrized fixture.

changelog/3057.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``request.fixturenames`` now correctly returns the name of fixtures created by ``request.getfixturevalue()``.

changelog/4058.doc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update fixture documentation to specify that a fixture can be invoked twice in the scope it's defined for.

changelog/4064.doc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
According to unittest.rst, setUpModule and tearDownModule were not implemented, but it turns out they are. So updated the documentation for unittest.

changelog/4066.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix source reindenting by using ``textwrap.dedent`` directly.

doc/en/announce/release-3.6.3.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ Thanks to all who contributed to this release, among them:
2020
* Ondřej Súkup
2121
* Ronny Pfannschmidt
2222
* T.E.A de Souza
23-
* Victor
24-
* victor
23+
* Victor Maryama
2524

2625

2726
Happy testing,

doc/en/announce/release-3.7.3.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ Thanks to all who contributed to this release, among them:
2222
* Ronny Pfannschmidt
2323
* Sankt Petersbug
2424
* Tyler Richard
25-
* Victor
25+
* Victor Maryama
2626
* Vlad Shcherbina
2727
* turturica
28-
* victor
2928
* wim glenn
3029

3130

doc/en/example/assertion/failure_demo.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ class A(object):
245245
a = 1
246246

247247
b = 2
248-
assert (
249-
A.a == b
250-
), "A.a appears not to be b\n" "or does not appear to be b\none of those"
248+
assert A.a == b, (
249+
"A.a appears not to be b\n" "or does not appear to be b\none of those"
250+
)
251251

252252
def test_custom_repr(self):
253253
class JSON(object):

doc/en/example/assertion/global_testmodule_config/test_hello_world.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
hello = "world"
32

43

doc/en/example/assertion/test_failures.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import py
32

43
failure_demo = py.path.local(__file__).dirpath("failure_demo.py")

doc/en/example/costlysetup/conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import pytest
32

43

doc/en/example/simple.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,8 @@ In that order.
852852
can be changed between releases (even bug fixes) so it shouldn't be relied on for scripting
853853
or automation.
854854

855+
.. _freezing-pytest:
856+
855857
Freezing pytest
856858
---------------
857859

doc/en/fixture.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,11 @@ instance, you can simply declare it:
259259
260260
Finally, the ``class`` scope will invoke the fixture once per test *class*.
261261

262+
.. note::
263+
264+
Pytest will only cache one instance of a fixture at a time.
265+
This means that when using a parametrized fixture, pytest may invoke a fixture more than once in the given scope.
266+
262267

263268
``package`` scope (experimental)
264269
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

doc/en/plugins.rst

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,15 @@ You may also discover more plugins through a `pytest- pypi.python.org search`_.
6969
Requiring/Loading plugins in a test module or conftest file
7070
-----------------------------------------------------------
7171

72-
You can require plugins in a test module or a conftest file like this::
72+
You can require plugins in a test module or a conftest file like this:
7373

74-
pytest_plugins = "myapp.testsupport.myplugin",
74+
.. code-block:: python
75+
76+
pytest_plugins = ("myapp.testsupport.myplugin",)
7577
7678
When the test module or conftest plugin is loaded the specified plugins
7779
will be loaded as well.
7880

79-
pytest_plugins = "myapp.testsupport.myplugin"
80-
81-
which will import the specified module as a ``pytest`` plugin.
82-
8381
.. note::
8482
Requiring plugins using a ``pytest_plugins`` variable in non-root
8583
``conftest.py`` files is deprecated. See

doc/en/reference.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ pytest.warns
8484
.. autofunction:: pytest.warns(expected_warning: Exception, [match])
8585
:with:
8686

87+
pytest.freeze_includes
88+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89+
90+
**Tutorial**: :ref:`freezing-pytest`.
91+
92+
.. autofunction:: pytest.freeze_includes
8793

8894
.. _`marks ref`:
8995

doc/en/unittest.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,15 @@ Almost all ``unittest`` features are supported:
2222

2323
* ``@unittest.skip`` style decorators;
2424
* ``setUp/tearDown``;
25-
* ``setUpClass/tearDownClass()``;
25+
* ``setUpClass/tearDownClass``;
26+
* ``setUpModule/tearDownModule``;
2627

2728
.. _`load_tests protocol`: https://docs.python.org/3/library/unittest.html#load-tests-protocol
28-
.. _`setUpModule/tearDownModule`: https://docs.python.org/3/library/unittest.html#setupmodule-and-teardownmodule
2929
.. _`subtests`: https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests
3030

3131
Up to this point pytest does not have support for the following features:
3232

3333
* `load_tests protocol`_;
34-
* `setUpModule/tearDownModule`_;
3534
* `subtests`_;
3635

3736
Benefits out of the box

src/_pytest/_argcomplete.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
"""allow bash-completion for argparse with argcomplete if installed
32
needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
43
to find the magic string, so _ARGCOMPLETE env. var is never set, and

src/_pytest/_code/source.py

Lines changed: 6 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import six
99
import inspect
10+
import textwrap
1011
import tokenize
1112
import py
1213

@@ -23,7 +24,6 @@ class Source(object):
2324
def __init__(self, *parts, **kwargs):
2425
self.lines = lines = []
2526
de = kwargs.get("deindent", True)
26-
rstrip = kwargs.get("rstrip", True)
2727
for part in parts:
2828
if not part:
2929
partlines = []
@@ -33,11 +33,6 @@ def __init__(self, *parts, **kwargs):
3333
partlines = [x.rstrip("\n") for x in part]
3434
elif isinstance(part, six.string_types):
3535
partlines = part.split("\n")
36-
if rstrip:
37-
while partlines:
38-
if partlines[-1].strip():
39-
break
40-
partlines.pop()
4136
else:
4237
partlines = getsource(part, deindent=de).lines
4338
if de:
@@ -115,17 +110,10 @@ def getstatementrange(self, lineno):
115110
ast, start, end = getstatementrange_ast(lineno, self)
116111
return start, end
117112

118-
def deindent(self, offset=None):
119-
""" return a new source object deindented by offset.
120-
If offset is None then guess an indentation offset from
121-
the first non-blank line. Subsequent lines which have a
122-
lower indentation offset will be copied verbatim as
123-
they are assumed to be part of multilines.
124-
"""
125-
# XXX maybe use the tokenizer to properly handle multiline
126-
# strings etc.pp?
113+
def deindent(self):
114+
"""return a new source object deindented."""
127115
newsource = Source()
128-
newsource.lines[:] = deindent(self.lines, offset)
116+
newsource.lines[:] = deindent(self.lines)
129117
return newsource
130118

131119
def isparseable(self, deindent=True):
@@ -268,47 +256,8 @@ def getsource(obj, **kwargs):
268256
return Source(strsrc, **kwargs)
269257

270258

271-
def deindent(lines, offset=None):
272-
if offset is None:
273-
for line in lines:
274-
line = line.expandtabs()
275-
s = line.lstrip()
276-
if s:
277-
offset = len(line) - len(s)
278-
break
279-
else:
280-
offset = 0
281-
if offset == 0:
282-
return list(lines)
283-
newlines = []
284-
285-
def readline_generator(lines):
286-
for line in lines:
287-
yield line + "\n"
288-
289-
it = readline_generator(lines)
290-
291-
try:
292-
for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(
293-
lambda: next(it)
294-
):
295-
if sline > len(lines):
296-
break # End of input reached
297-
if sline > len(newlines):
298-
line = lines[sline - 1].expandtabs()
299-
if line.lstrip() and line[:offset].isspace():
300-
line = line[offset:] # Deindent
301-
newlines.append(line)
302-
303-
for i in range(sline, eline):
304-
# Don't deindent continuing lines of
305-
# multiline tokens (i.e. multiline strings)
306-
newlines.append(lines[i])
307-
except (IndentationError, tokenize.TokenError):
308-
pass
309-
# Add any lines we didn't see. E.g. if an exception was raised.
310-
newlines.extend(lines[len(newlines) :])
311-
return newlines
259+
def deindent(lines):
260+
return textwrap.dedent("\n".join(lines)).splitlines()
312261

313262

314263
def get_statement_startend2(lineno, node):

src/_pytest/fixtures.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,10 @@ def __init__(self, pyfuncitem):
359359

360360
@property
361361
def fixturenames(self):
362-
# backward incompatible note: now a readonly property
363-
return list(self._pyfuncitem._fixtureinfo.names_closure)
362+
"""names of all active fixtures in this request"""
363+
result = list(self._pyfuncitem._fixtureinfo.names_closure)
364+
result.extend(set(self._fixture_defs).difference(result))
365+
return result
364366

365367
@property
366368
def node(self):
@@ -565,7 +567,20 @@ def _compute_fixture_value(self, fixturedef):
565567
except (AttributeError, ValueError):
566568
param = NOTSET
567569
param_index = 0
568-
if fixturedef.params is not None:
570+
has_params = fixturedef.params is not None
571+
fixtures_not_supported = getattr(funcitem, "nofuncargs", False)
572+
if has_params and fixtures_not_supported:
573+
msg = (
574+
"{name} does not support fixtures, maybe unittest.TestCase subclass?\n"
575+
"Node id: {nodeid}\n"
576+
"Function type: {typename}"
577+
).format(
578+
name=funcitem.name,
579+
nodeid=funcitem.nodeid,
580+
typename=type(funcitem).__name__,
581+
)
582+
fail(msg)
583+
if has_params:
569584
frame = inspect.stack()[3]
570585
frameinfo = inspect.getframeinfo(frame[0])
571586
source_path = frameinfo.filename
@@ -574,9 +589,11 @@ def _compute_fixture_value(self, fixturedef):
574589
if source_path.relto(funcitem.config.rootdir):
575590
source_path = source_path.relto(funcitem.config.rootdir)
576591
msg = (
577-
"The requested fixture has no parameter defined for the "
578-
"current test.\n\nRequested fixture '{}' defined in:\n{}"
592+
"The requested fixture has no parameter defined for test:\n"
593+
" {}\n\n"
594+
"Requested fixture '{}' defined in:\n{}"
579595
"\n\nRequested here:\n{}:{}".format(
596+
funcitem.nodeid,
580597
fixturedef.argname,
581598
getlocation(fixturedef.func, funcitem.config.rootdir),
582599
source_path,

src/_pytest/junitxml.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Junit(py.xml.Namespace):
3838
# this dynamically instead of hardcoding it. The spec range of valid
3939
# chars is: Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
4040
# | [#x10000-#x10FFFF]
41-
_legal_chars = (0x09, 0x0A, 0x0d)
41+
_legal_chars = (0x09, 0x0A, 0x0D)
4242
_legal_ranges = ((0x20, 0x7E), (0x80, 0xD7FF), (0xE000, 0xFFFD), (0x10000, 0x10FFFF))
4343
_legal_xml_re = [
4444
unicode("%s-%s") % (unichr(low), unichr(high))

src/_pytest/logging.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ class LogCaptureFixture(object):
213213
def __init__(self, item):
214214
"""Creates a new funcarg."""
215215
self._item = item
216-
self._initial_log_levels = {} # type: Dict[str, int] # dict of log name -> log level
216+
# dict of log name -> log level
217+
self._initial_log_levels = {} # type: Dict[str, int]
217218

218219
def _finalize(self):
219220
"""Finalizes the fixture.

src/_pytest/mark/evaluate.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ def _istrue(self):
9090
else:
9191
if "reason" not in mark.kwargs:
9292
# XXX better be checked at collection time
93-
msg = "you need to specify reason=STRING " "when using booleans as conditions."
93+
msg = (
94+
"you need to specify reason=STRING "
95+
"when using booleans as conditions."
96+
)
9497
fail(msg)
9598
result = bool(expr)
9699
if result:

0 commit comments

Comments
 (0)