Merge pull request #4926 from blueyed/merge-master-into-features
Merge master into features
This commit is contained in:
commit
5c57d92978
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
=========================
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Logging messages inside ``pytest_runtest_logreport()`` are now properly captured and displayed.
|
|
@ -1 +0,0 @@
|
|||
Improve validation of contents written to captured output so it behaves the same as when capture is disabled.
|
|
@ -0,0 +1 @@
|
|||
Use the correct modified time for years after 2038 in rewritten ``.pyc`` files.
|
|
@ -0,0 +1 @@
|
|||
Remove deprecated Sphinx directive, ``add_description_unit()``.
|
|
@ -0,0 +1 @@
|
|||
Fix pytest tests invocation with custom ``PYTHONPATH``.
|
|
@ -6,6 +6,7 @@ Release announcements
|
|||
:maxdepth: 2
|
||||
|
||||
|
||||
release-4.3.1
|
||||
release-4.3.0
|
||||
release-4.2.1
|
||||
release-4.2.0
|
||||
|
|
|
@ -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
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
--------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -238,8 +238,9 @@ class PyobjMixin(PyobjContext):
|
|||
def __init__(self, *k, **kw):
|
||||
super(PyobjMixin, self).__init__(*k, **kw)
|
||||
|
||||
def obj():
|
||||
def fget(self):
|
||||
@property
|
||||
def obj(self):
|
||||
"""Underlying Python object."""
|
||||
obj = getattr(self, "_obj", None)
|
||||
if obj is None:
|
||||
self._obj = obj = self._getobj()
|
||||
|
@ -249,14 +250,12 @@ class PyobjMixin(PyobjContext):
|
|||
self.own_markers.extend(get_unpacked_marks(self.obj))
|
||||
return obj
|
||||
|
||||
def fset(self, value):
|
||||
@obj.setter
|
||||
def obj(self, value):
|
||||
self._obj = value
|
||||
|
||||
return property(fget, fset, None, "underlying python object")
|
||||
|
||||
obj = obj()
|
||||
|
||||
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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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*"])
|
||||
|
|
|
@ -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__,
|
||||
|
|
Loading…
Reference in New Issue