Merge master into features

This commit is contained in:
Daniel Hahler 2019-03-15 00:52:12 +01:00
commit 7afe17740f
21 changed files with 132 additions and 40 deletions

View File

@ -86,6 +86,9 @@ jobs:
- env: TOXENV=py36-xdist
python: '3.6'
- env: TOXENV=linting,docs,doctesting PYTEST_COVERAGE=1
cache:
directories:
- $HOME/.cache/pre-commit
- stage: deploy
python: '3.6'
@ -144,7 +147,4 @@ notifications:
skip_join: true
email:
- pytest-commit@python.org
cache:
directories:
- $HOME/.cache/pip
- $HOME/.cache/pre-commit
cache: false

View File

@ -18,6 +18,28 @@ with advance notice in the **Deprecations** section of releases.
.. towncrier release notes start
pytest 4.3.1 (2019-03-11)
=========================
Bug Fixes
---------
- `#4810 <https://github.com/pytest-dev/pytest/issues/4810>`_: Logging messages inside ``pytest_runtest_logreport()`` are now properly captured and displayed.
- `#4861 <https://github.com/pytest-dev/pytest/issues/4861>`_: Improve validation of contents written to captured output so it behaves the same as when capture is disabled.
- `#4898 <https://github.com/pytest-dev/pytest/issues/4898>`_: Fix ``AttributeError: FixtureRequest has no 'confg' attribute`` bug in ``testdir.copy_example``.
Trivial/Internal Changes
------------------------
- `#4768 <https://github.com/pytest-dev/pytest/issues/4768>`_: Avoid pkg_resources import at the top-level.
pytest 4.3.0 (2019-02-16)
=========================

View File

@ -1 +0,0 @@
Logging messages inside ``pytest_runtest_logreport()`` are now properly captured and displayed.

View File

@ -1 +0,0 @@
Improve validation of contents written to captured output so it behaves the same as when capture is disabled.

View File

@ -0,0 +1 @@
Use the correct modified time for years after 2038 in rewritten ``.pyc`` files.

View File

@ -0,0 +1 @@
Remove deprecated Sphinx directive, ``add_description_unit()``.

View File

@ -0,0 +1 @@
Fix pytest tests invocation with custom ``PYTHONPATH``.

View File

@ -6,6 +6,7 @@ Release announcements
:maxdepth: 2
release-4.3.1
release-4.3.0
release-4.2.1
release-4.2.0

View File

@ -0,0 +1,29 @@
pytest-4.3.1
=======================================
pytest 4.3.1 has just been released to PyPI.
This is a bug-fix release, being a drop-in replacement. To upgrade::
pip install --upgrade pytest
The full changelog is available at https://docs.pytest.org/en/latest/changelog.html.
Thanks to all who contributed to this release, among them:
* Andras Mitzki
* Anthony Sottile
* Bruno Oliveira
* Daniel Hahler
* Danilo Horta
* Grygorii Iermolenko
* Jeff Hale
* Kyle Altendorf
* Stephan Hoyer
* Zac Hatfield-Dodds
* Zac-HD
* songbowen
Happy testing,
The pytest Development Team

View File

@ -335,7 +335,7 @@ intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
def setup(app):
# from sphinx.ext.autodoc import cut_lines
# app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
app.add_description_unit(
app.add_object_type(
"confval",
"confval",
objname="configuration value",

View File

@ -436,8 +436,10 @@ Running it results in some skips if we don't have all the python interpreters in
.. code-block:: pytest
. $ pytest -rs -q multipython.py
........................... [100%]
27 passed in 0.12 seconds
...sss...sssssssss...sss... [100%]
========================= short test summary info ==========================
SKIPPED [15] $REGENDOC_TMPDIR/CWD/multipython.py:30: 'python3.4' not found
12 passed, 15 skipped in 0.12 seconds
Indirect parametrization of optional implementations/imports
--------------------------------------------------------------------

View File

@ -584,6 +584,8 @@ Initialization hooks called for plugins and ``conftest.py`` files.
.. autofunction:: pytest_sessionstart
.. autofunction:: pytest_sessionfinish
.. autofunction:: pytest_plugin_registered
Test running hooks
~~~~~~~~~~~~~~~~~~
@ -607,6 +609,8 @@ into interactive debugging when a test failure occurs.
The :py:mod:`_pytest.terminal` reported specifically uses
the reporting hook to print information about a test run.
.. autofunction:: pytest_pyfunc_call
Collection hooks
~~~~~~~~~~~~~~~~
@ -616,6 +620,7 @@ Collection hooks
.. autofunction:: pytest_ignore_collect
.. autofunction:: pytest_collect_directory
.. autofunction:: pytest_collect_file
.. autofunction:: pytest_pycollect_makemodule
For influencing the collection of objects in Python modules
you can use the following hook:
@ -629,12 +634,15 @@ items, delete or otherwise amend the test items:
.. autofunction:: pytest_collection_modifyitems
.. autofunction:: pytest_collection_finish
Reporting hooks
~~~~~~~~~~~~~~~
Session related reporting hooks:
.. autofunction:: pytest_collectstart
.. autofunction:: pytest_make_collect_report
.. autofunction:: pytest_itemcollected
.. autofunction:: pytest_collectreport
.. autofunction:: pytest_deselected

View File

@ -1,4 +1,4 @@
pygments-pytest>=1.1.0
sphinx>=1.8.2
sphinx>=1.8.2,<2.0
sphinxcontrib-trio
sphinx-removed-in>=0.1.3

View File

@ -66,7 +66,6 @@ Running this would result in a passed test except for the last
test_tmp_path.py:13: AssertionError
========================= 1 failed in 0.12 seconds =========================
.. _`tmp_path_factory example`:
The ``tmp_path_factory`` fixture

View File

@ -347,9 +347,11 @@ def _write_pyc(state, co, source_stat, pyc):
try:
with atomicwrites.atomic_write(pyc, mode="wb", overwrite=True) as fp:
fp.write(imp.get_magic())
mtime = int(source_stat.mtime)
# as of now, bytecode header expects 32-bit numbers for size and mtime (#4903)
mtime = int(source_stat.mtime) & 0xFFFFFFFF
size = source_stat.size & 0xFFFFFFFF
fp.write(struct.pack("<ll", mtime, size))
# "<LL" stands for 2 unsigned longs, little-ending
fp.write(struct.pack("<LL", mtime, size))
fp.write(marshal.dumps(co))
except EnvironmentError as e:
state.trace("error writing pyc file at %s: errno=%s" % (pyc, e.errno))
@ -444,7 +446,7 @@ def _read_pyc(source, pyc, trace=lambda x: None):
if (
len(data) != 12
or data[:4] != imp.get_magic()
or struct.unpack("<ll", data[4:]) != (mtime, size)
or struct.unpack("<LL", data[4:]) != (mtime & 0xFFFFFFFF, size & 0xFFFFFFFF)
):
trace("_read_pyc(%s): invalid or out of date pyc" % source)
return None

View File

@ -14,7 +14,6 @@ import warnings
import py
import six
from pkg_resources import parse_version
from pluggy import HookimplMarker
from pluggy import HookspecMarker
from pluggy import PluginManager
@ -853,6 +852,7 @@ class Config(object):
def _checkversion(self):
import pytest
from pkg_resources import parse_version
minver = self.inicfg.get("minversion", None)
if minver:

View File

@ -652,7 +652,7 @@ class Testdir(object):
else:
raise LookupError(
"{} cant be found as module or package in {}".format(
func_name, example_dir.bestrelpath(self.request.confg.rootdir)
func_name, example_dir.bestrelpath(self.request.config.rootdir)
)
)
else:

View File

@ -238,25 +238,24 @@ class PyobjMixin(PyobjContext):
def __init__(self, *k, **kw):
super(PyobjMixin, self).__init__(*k, **kw)
def obj():
def fget(self):
obj = getattr(self, "_obj", None)
if obj is None:
self._obj = obj = self._getobj()
# XXX evil hack
# used to avoid Instance collector marker duplication
if self._ALLOW_MARKERS:
self.own_markers.extend(get_unpacked_marks(self.obj))
return obj
@property
def obj(self):
"""Underlying Python object."""
obj = getattr(self, "_obj", None)
if obj is None:
self._obj = obj = self._getobj()
# XXX evil hack
# used to avoid Instance collector marker duplication
if self._ALLOW_MARKERS:
self.own_markers.extend(get_unpacked_marks(self.obj))
return obj
def fset(self, value):
self._obj = value
return property(fget, fset, None, "underlying python object")
obj = obj()
@obj.setter
def obj(self, value):
self._obj = value
def _getobj(self):
"""Gets the underlying Python object. May be overwritten by subclasses."""
return getattr(self.parent.obj, self.name)
def getmodpath(self, stopatmodule=True, includemodule=False):

View File

@ -1197,6 +1197,29 @@ class TestIssue2121:
result.stdout.fnmatch_lines("*E*assert (1 + 1) == 3")
@pytest.mark.parametrize("offset", [-1, +1])
def test_source_mtime_long_long(testdir, offset):
"""Support modification dates after 2038 in rewritten files (#4903).
pytest would crash with:
fp.write(struct.pack("<ll", mtime, size))
E struct.error: argument out of range
"""
p = testdir.makepyfile(
"""
def test(): pass
"""
)
# use unsigned long timestamp which overflows signed long,
# which was the cause of the bug
# +1 offset also tests masking of 0xFFFFFFFF
timestamp = 2 ** 32 + offset
os.utime(str(p), (timestamp, timestamp))
result = testdir.runpytest()
assert result.ret == 0
def test_rewrite_infinite_recursion(testdir, pytestconfig, monkeypatch):
"""Fix infinite recursion when writing pyc files: if an import happens to be triggered when writing the pyc
file, this would cause another call to the hook, which would trigger another pyc writing, which could

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import pprint
import sys
import textwrap
@ -1108,7 +1109,7 @@ def test_collect_pyargs_with_testpaths(testdir, monkeypatch):
"""
)
)
monkeypatch.setenv("PYTHONPATH", str(testdir.tmpdir))
monkeypatch.setenv("PYTHONPATH", str(testdir.tmpdir), prepend=os.pathsep)
with root.as_cwd():
result = testdir.runpytest_subprocess()
result.stdout.fnmatch_lines(["*1 passed in*"])

View File

@ -459,7 +459,7 @@ class TestPDB(object):
child.read()
self.flush(child)
def test_pdb_interaction_doctest(self, testdir):
def test_pdb_interaction_doctest(self, testdir, monkeypatch):
p1 = testdir.makepyfile(
"""
import pytest
@ -470,11 +470,18 @@ class TestPDB(object):
'''
"""
)
# Prevent ~/.pdbrc etc to output anything.
monkeypatch.setenv("HOME", str(testdir))
child = testdir.spawn_pytest("--doctest-modules --pdb %s" % p1)
child.expect("Pdb")
child.sendline("i")
child.expect("0")
assert "UNEXPECTED EXCEPTION: AssertionError()" in child.before.decode("utf8")
child.sendline("'i=%i.' % i")
child.expect("Pdb")
assert "\r\n'i=0.'\r\n" in child.before.decode("utf8")
child.sendeof()
rest = child.read().decode("utf8")
assert "1 failed" in rest
@ -530,15 +537,13 @@ class TestPDB(object):
import sys
import types
newglobals = {
'Pdb': self.__class__, # NOTE: different with pdb.Pdb
'sys': sys,
}
if sys.version_info < (3, ):
do_debug_func = pdb.Pdb.do_debug.im_func
else:
do_debug_func = pdb.Pdb.do_debug
newglobals = do_debug_func.__globals__.copy()
newglobals['Pdb'] = self.__class__
orig_do_debug = types.FunctionType(
do_debug_func.__code__, newglobals,
do_debug_func.__name__, do_debug_func.__defaults__,