diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 21a090414..9c9d254d0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,52 @@ .. towncrier release notes start +Pytest 3.6.3 (2018-07-04) +========================= + +Bug Fixes +--------- + +- Fix ``ImportWarning`` triggered by explicit relative imports in + assertion-rewritten package modules. (`#3061 + `_) + +- Fix error in ``pytest.approx`` when dealing with 0-dimension numpy + arrays. (`#3593 `_) + +- No longer raise ``ValueError`` when using the ``get_marker`` API. (`#3605 + `_) + +- Fix problem where log messages with non-ascii characters would not + appear in the output log file. + (`#3630 `_) + +- No longer raise ``AttributeError`` when legacy marks can't be stored in + functions. (`#3631 `_) + + +Improved Documentation +---------------------- + +- The description above the example for ``@pytest.mark.skipif`` now better + matches the code. (`#3611 + `_) + + +Trivial/Internal Changes +------------------------ + +- Internal refactoring: removed unused ``CallSpec2tox ._globalid_args`` + attribute and ``metafunc`` parameter from ``CallSpec2.copy()``. (`#3598 + `_) + +- Silence usage of ``reduce`` warning in Python 2 (`#3609 + `_) + +- Fix usage of ``attr.ib`` deprecated ``convert`` parameter. (`#3653 + `_) + + Pytest 3.6.2 (2018-06-20) ========================= diff --git a/HOWTORELEASE.rst b/HOWTORELEASE.rst index 97bddf720..b5e852d3b 100644 --- a/HOWTORELEASE.rst +++ b/HOWTORELEASE.rst @@ -10,10 +10,6 @@ taking a lot of time to make a new one. pytest releases must be prepared on **Linux** because the docs and examples expect to be executed in that platform. -#. Install development dependencies in a virtual environment with:: - - pip3 install -U -r tasks/requirements.txt - #. Create a branch ``release-X.Y.Z`` with the version for the release. * **patch releases**: from the latest ``master``; @@ -22,9 +18,19 @@ taking a lot of time to make a new one. Ensure your are in a clean work tree. -#. Generate docs, changelog, announcements and a **local** tag:: +#. Install development dependencies in a virtual environment with:: + + $ pip3 install -U -r tasks/requirements.txt + +#. Generate docs, changelog, announcements, and a **local** tag:: + + $ invoke generate.pre-release + +#. Execute pre-commit on all files to ensure the docs are conformant and commit your results:: + + $ pre-commit run --all-files + $ git commit -am "Fix files with pre-commit" - invoke generate.pre-release #. Open a PR for this branch targeting ``master``. diff --git a/changelog/3061.bugfix.rst b/changelog/3061.bugfix.rst deleted file mode 100644 index 1bdd1064e..000000000 --- a/changelog/3061.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ``ImportWarning`` triggered by explicit relative imports in assertion-rewritten package modules. diff --git a/changelog/3593.bugfix.rst b/changelog/3593.bugfix.rst deleted file mode 100644 index 37aa30577..000000000 --- a/changelog/3593.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -If the user pass as a expected value a numpy array created like -numpy.array(5); it will creates an array with one element without shape, -when used with approx it will raise an error for the `repr` -'TypeError: iteration over a 0-d array'. With this PR pytest will iterate -properly in the numpy array even with 0 dimension. diff --git a/changelog/3598.trivial.rst b/changelog/3598.trivial.rst deleted file mode 100644 index fd80f58cd..000000000 --- a/changelog/3598.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Internal refactoring: removed unused ``CallSpec2tox ._globalid_args`` attribute and ``metafunc`` parameter from ``CallSpec2.copy()``. diff --git a/changelog/3605.bugfix.rst b/changelog/3605.bugfix.rst deleted file mode 100644 index 58a294ecb..000000000 --- a/changelog/3605.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -no longer ValueError when using the ``get_marker`` api. diff --git a/changelog/3609.trivial.rst b/changelog/3609.trivial.rst deleted file mode 100644 index 96e720d92..000000000 --- a/changelog/3609.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Silence usage of ``reduce`` warning in python 2 diff --git a/changelog/3611.doc.rst b/changelog/3611.doc.rst deleted file mode 100644 index fe19cc025..000000000 --- a/changelog/3611.doc.rst +++ /dev/null @@ -1 +0,0 @@ -The description above the example for ``@pytest.mark.skipif`` now better matches the code. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 107fcd2ad..8283bf86d 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.6.3 release-3.6.2 release-3.6.1 release-3.6.0 diff --git a/doc/en/announce/release-3.6.3.rst b/doc/en/announce/release-3.6.3.rst new file mode 100644 index 000000000..1aff2bc38 --- /dev/null +++ b/doc/en/announce/release-3.6.3.rst @@ -0,0 +1,28 @@ +pytest-3.6.3 +======================================= + +pytest 3.6.3 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 http://doc.pytest.org/en/latest/changelog.html. + +Thanks to all who contributed to this release, among them: + +* AdamEr8 +* Anthony Sottile +* Bruno Oliveira +* Jean-Paul Calderone +* Jon Dufresne +* Marcelo Duarte Trevisani +* Ondřej Súkup +* Ronny Pfannschmidt +* T.E.A de Souza +* Victor +* victor + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index c2d23469b..e52151a1b 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -90,7 +90,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a monkeypatch.setitem(mapping, name, value) monkeypatch.delitem(obj, name, raising=True) monkeypatch.setenv(name, value, prepend=False) - monkeypatch.delenv(name, value, raising=True) + monkeypatch.delenv(name, raising=True) monkeypatch.syspath_prepend(path) monkeypatch.chdir(path) diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 180637ae9..ed2c9d67a 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -416,7 +416,7 @@ Now we can profile which test functions execute the slowest:: ========================= slowest 3 test durations ========================= 0.30s call test_some_are_slow.py::test_funcslow2 0.20s call test_some_are_slow.py::test_funcslow1 - 0.10s call test_some_are_slow.py::test_funcfast + 0.13s call test_some_are_slow.py::test_funcfast ========================= 3 passed in 0.12 seconds ========================= incremental testing - test steps diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 2d3e6126b..1472b0dbd 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -408,7 +408,9 @@ class LoggingPlugin(object): config, "log_file_date_format", "log_date_format" ) # Each pytest runtests session will write to a clean logfile - self.log_file_handler = logging.FileHandler(log_file, mode="w") + self.log_file_handler = logging.FileHandler( + log_file, mode="w", encoding="UTF-8" + ) log_file_formatter = logging.Formatter( log_file_format, datefmt=log_file_date_format ) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index d416e422b..3c161c4a6 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -259,7 +259,7 @@ def store_legacy_markinfo(func, mark): if holder is None: holder = MarkInfo.for_mark(mark) setattr(func, mark.name, holder) - else: + elif isinstance(holder, MarkInfo): holder.add_mark(mark) @@ -294,7 +294,7 @@ def _marked(func, mark): class MarkInfo(object): """ Marking object created by :class:`MarkDecorator` instances. """ - _marks = attr.ib(convert=list) + _marks = attr.ib(converter=list) @_marks.validator def validate_marks(self, attribute, value): diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index e6928f96b..22ffffd4c 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -22,7 +22,7 @@ def monkeypatch(): monkeypatch.setitem(mapping, name, value) monkeypatch.delitem(obj, name, raising=True) monkeypatch.setenv(name, value, prepend=False) - monkeypatch.delenv(name, value, raising=True) + monkeypatch.delenv(name, raising=True) monkeypatch.syspath_prepend(path) monkeypatch.chdir(path) diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 0a8a58506..07c092191 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import re import os +from io import open import six @@ -827,6 +828,43 @@ def test_log_file_ini_level(testdir): assert "This log message won't be shown" not in contents +def test_log_file_unicode(testdir): + log_file = testdir.tmpdir.join("pytest.log").strpath + + testdir.makeini( + """ + [pytest] + log_file={} + log_file_level = INFO + """.format( + log_file + ) + ) + testdir.makepyfile( + """ + # -*- coding: utf-8 -*- + from __future__ import unicode_literals + import logging + + def test_log_file(): + logging.getLogger('catchlog').info("Normal message") + logging.getLogger('catchlog').info("├") + logging.getLogger('catchlog').info("Another normal message") + """ + ) + + result = testdir.runpytest() + + # make sure that that we get a '0' exit code for the testsuite + assert result.ret == 0 + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert "Normal message" in contents + assert u"├" in contents + assert "Another normal message" in contents + + @pytest.mark.parametrize("has_capture_manager", [True, False]) def test_live_logging_suspends_capture(has_capture_manager, request): """Test that capture manager is suspended when we emitting messages for live logging. diff --git a/testing/test_mark.py b/testing/test_mark.py index ddeff2789..e47981aca 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -63,6 +63,19 @@ class TestMark(object): mark.hello(f) assert f.hello + def test_mark_legacy_ignore_fail(self): + def add_attribute(func): + func.foo = 1 + return func + + @pytest.mark.foo + @add_attribute + def test_fun(): + pass + + assert test_fun.foo == 1 + assert test_fun.pytestmark + @ignore_markinfo def test_pytest_mark_keywords(self): mark = Mark()