diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f75e83bbe..70295eaef 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,186 @@ .. towncrier release notes start +Pytest 3.3.0 (2017-11-23) +========================= + +Deprecations and Removals +------------------------- + +- Pytest no longer supports Python **2.6** and **3.3**. Those Python versions + are EOL for some time now and incur maintenance and compatibility costs on + the pytest core team, and following up with the rest of the community we + decided that they will no longer be supported starting on this version. Users + which still require those versions should pin pytest to ``<3.3``. (`#2812 + `_) + +- Remove internal ``_preloadplugins()`` function. This removal is part of the + ``pytest_namespace()`` hook deprecation. (`#2236 + `_) + +- Internally change ``CallSpec2`` to have a list of marks instead of a broken + mapping of keywords. This removes the keywords attribute of the internal + ``CallSpec2`` class. (`#2672 + `_) + +- Remove ParameterSet.deprecated_arg_dict - its not a public api and the lack + of the underscore was a naming error. (`#2675 + `_) + +- Remove the internal multi-typed attribute ``Node._evalskip`` and replace it + with the boolean ``Node._skipped_by_mark``. (`#2767 + `_) + +Features +-------- + +- ``pytest_fixture_post_finalizer`` hook can now receive a ``request`` + argument. (`#2124 `_) + +- Replace the old introspection code in compat.py that determines the available + arguments of fixtures with inspect.signature on Python 3 and + funcsigs.signature on Python 2. This should respect ``__signature__`` + declarations on functions. (`#2267 + `_) + +- Report tests with global ``pytestmark`` variable only once. (`#2549 + `_) + +- Now pytest displays the total progress percentage while running tests. The + previous output style can be set by configuring the ``console_output_style`` + setting to ``classic``. (`#2657 `_) + +- Match ``warns`` signature to ``raises`` by adding ``match`` keyword. (`#2708 + `_) + +- Pytest now captures and displays output from the standard `logging` module. + The user can control the logging level to be captured by specifying options + in ``pytest.ini``, the command line and also during individual tests using + markers. Also, a ``caplog`` fixture is available that enables users to test + the captured log during specific tests (similar to ``capsys`` for example). + For more information, please see the `logging docs + `_. This feature was + introduced by merging the popular `pytest-catchlog + `_ plugin, thanks to `Thomas Hisch + `_. Be advised that during the merging the + backward compatibility interface with the defunct ``pytest-capturelog`` has + been dropped. (`#2794 `_) + +- Add ``allow_module_level`` kwarg to ``pytest.skip()``, enabling to skip the + whole module. (`#2808 `_) + +- Allow setting ``file_or_dir``, ``-c``, and ``-o`` in PYTEST_ADDOPTS. (`#2824 + `_) + +- Return stdout/stderr capture results as a ``namedtuple``, so ``out`` and + ``err`` can be accessed by attribute. (`#2879 + `_) + +- Add ``capfdbinary``, a version of ``capfd`` which returns bytes from + ``readouterr()``. (`#2923 + `_) + +- Add ``capsysbinary`` a version of ``capsys`` which returns bytes from + ``readouterr()``. (`#2934 + `_) + +- Implement feature to skip ``setup.py`` files when run with + ``--doctest-modules``. (`#502 + `_) + + +Bug Fixes +--------- + +- Resume output capturing after ``capsys/capfd.disabled()`` context manager. + (`#1993 `_) + +- ``pytest_fixture_setup`` and ``pytest_fixture_post_finalizer`` hooks are now + called for all ``conftest.py`` files. (`#2124 + `_) + +- If an exception happens while loading a plugin, pytest no longer hides the + original traceback. In python2 it will show the original traceback with a new + message that explains in which plugin. In python3 it will show 2 canonized + exceptions, the original exception while loading the plugin in addition to an + exception that PyTest throws about loading a plugin. (`#2491 + `_) + +- ``capsys`` and ``capfd`` can now be used by other fixtures. (`#2709 + `_) + +- Internal ``pytester`` plugin properly encodes ``bytes`` arguments to + ``utf-8``. (`#2738 `_) + +- ``testdir`` now uses use the same method used by ``tmpdir`` to create its + temporary directory. This changes the final structure of the ``testdir`` + directory slightly, but should not affect usage in normal scenarios and + avoids a number of potential problems. (`#2751 + `_) + +- Pytest no longer complains about warnings with unicode messages being + non-ascii compatible even for ascii-compatible messages. As a result of this, + warnings with unicode messages are converted first to an ascii representation + for safety. (`#2809 `_) + +- Change return value of pytest command when ``--maxfail`` is reached from + ``2`` (interrupted) to ``1`` (failed). (`#2845 + `_) + +- Fix issue in assertion rewriting which could lead it to rewrite modules which + should not be rewritten. (`#2939 + `_) + +- Handle marks without description in ``pytest.ini``. (`#2942 + `_) + + +Trivial/Internal Changes +------------------------ + +- pytest now depends on `attrs `_ for internal + structures to ease code maintainability. (`#2641 + `_) + +- Refactored internal Python 2/3 compatibility code to use ``six``. (`#2642 + `_) + +- Stop vendoring ``pluggy`` - we're missing out on its latest changes for not + much benefit (`#2719 `_) + +- Internal refactor: simplify ascii string escaping by using the + backslashreplace error handler in newer Python 3 versions. (`#2734 + `_) + +- Remove unnecessary mark evaluator in unittest plugin (`#2767 + `_) + +- Calls to ``Metafunc.addcall`` now emit a deprecation warning. This function + is scheduled to be removed in ``pytest-4.0``. (`#2876 + `_) + +- Internal move of the parameterset extraction to a more maintainable place. + (`#2877 `_) + +- Internal refactoring to simplify scope node lookup. (`#2910 + `_) + +- Configure ``pytest`` to prevent pip from installing pytest in unsupported + Python versions. (`#2922 + `_) + + +Pytest 3.2.5 (2017-11-15) +========================= + +Bug Fixes +--------- + +- Remove ``py<1.5`` restriction from ``pytest`` as this can cause version + conflicts in some installations. (`#2926 + `_) + + Pytest 3.2.4 (2017-11-13) ========================= @@ -28,6 +208,8 @@ Bug Fixes failed example in the docstring is < 9. (`#2882 `_) +- Match fixture paths against actual path segments in order to avoid matching folders which share a prefix. + (`#2836 `_) Improved Documentation ---------------------- @@ -179,7 +361,7 @@ Deprecations and Removals ------------------------- - ``pytest.approx`` no longer supports ``>``, ``>=``, ``<`` and ``<=`` - operators to avoid surprising/inconsistent behavior. See `the docs + operators to avoid surprising/inconsistent behavior. See `the approx docs `_ for more information. (`#2003 `_) diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py index 1ab474cf7..d0f90db9f 100644 --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -168,7 +168,7 @@ class AssertionRewritingHook(object): return True for marked in self._must_rewrite: - if name.startswith(marked): + if name == marked or name.startswith(marked + '.'): state.trace("matched marked file %r (from %r)" % (name, marked)) return True diff --git a/_pytest/config.py b/_pytest/config.py index b65ce9a51..6eb2d6c5c 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -242,6 +242,10 @@ class PytestPluginManager(PluginManager): return opts def register(self, plugin, name=None): + if name == 'pytest_catchlog': + self._warn('pytest-catchlog plugin has been merged into the core, ' + 'please remove it from your requirements.') + return ret = super(PytestPluginManager, self).register(plugin, name) if ret: self.hook.pytest_plugin_registered.call_historic( @@ -931,7 +935,7 @@ class Config(object): fslocation=fslocation, nodeid=nodeid)) def get_terminal_writer(self): - return self.pluginmanager.get_plugin("terminalreporter").writer + return self.pluginmanager.get_plugin("terminalreporter")._tw def pytest_cmdline_parse(self, pluginmanager, args): # REF1 assert self == pluginmanager.config, (self, pluginmanager.config) diff --git a/_pytest/debugging.py b/_pytest/debugging.py index a67752751..d7dca7809 100644 --- a/_pytest/debugging.py +++ b/_pytest/debugging.py @@ -83,7 +83,7 @@ def _enter_pdb(node, excinfo, rep): # XXX we re-use the TerminalReporter's terminalwriter # because this seems to avoid some encoding related troubles # for not completely clear reasons. - tw = node.config.pluginmanager.getplugin("terminalreporter").writer + tw = node.config.pluginmanager.getplugin("terminalreporter")._tw tw.line() tw.sep(">", "traceback") rep.toterminal(tw) diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py index 8438c3004..e744637f8 100644 --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -107,7 +107,7 @@ def pytest_cmdline_main(config): def showhelp(config): reporter = config.pluginmanager.get_plugin('terminalreporter') - tw = reporter.writer + tw = reporter._tw tw.write(config._parser.optparser.format_help()) tw.line() tw.line() diff --git a/_pytest/mark.py b/_pytest/mark.py index b7d50e05e..3f1f01b1a 100644 --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -141,7 +141,9 @@ def pytest_cmdline_main(config): config._do_configure() tw = _pytest.config.create_terminal_writer(config) for line in config.getini("markers"): - name, rest = line.split(":", 1) + parts = line.split(":", 1) + name = parts[0] + rest = parts[1] if len(parts) == 2 else '' tw.write("@pytest.mark.%s:" % name, bold=True) tw.line(rest) tw.line() @@ -298,7 +300,7 @@ class MarkGenerator: pass self._markers = values = set() for line in self._config.getini("markers"): - marker, _ = line.split(":", 1) + marker = line.split(":", 1)[0] marker = marker.rstrip() x = marker.split("(", 1)[0] values.add(x) diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py index 68aa331f7..b588b021b 100644 --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -25,7 +25,7 @@ def pytest_configure(config): if tr is not None: # pastebin file will be utf-8 encoded binary file config._pastebinfile = tempfile.TemporaryFile('w+b') - oldwrite = tr.writer.write + oldwrite = tr._tw.write def tee_write(s, **kwargs): oldwrite(s, **kwargs) @@ -33,7 +33,7 @@ def pytest_configure(config): s = s.encode('utf-8') config._pastebinfile.write(s) - tr.writer.write = tee_write + tr._tw.write = tee_write def pytest_unconfigure(config): @@ -45,7 +45,7 @@ def pytest_unconfigure(config): del config._pastebinfile # undo our patching in the terminal reporter tr = config.pluginmanager.getplugin('terminalreporter') - del tr.writer.__dict__['write'] + del tr._tw.__dict__['write'] # write summary tr.write_sep("=", "Sending information to Paste Service") pastebinurl = create_new_paste(sessionlog) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index ab46911e6..a1e5b4380 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -308,9 +308,9 @@ def pytest_terminal_summary(terminalreporter): show_simple(terminalreporter, lines, 'passed', "PASSED %s") if lines: - tr.writer.sep("=", "short test summary info") + tr._tw.sep("=", "short test summary info") for line in lines: - tr.writer.line(line) + tr._tw.line(line) def show_simple(terminalreporter, lines, stat, format): diff --git a/_pytest/terminal.py b/_pytest/terminal.py index 7a18b94a7..8538ee6aa 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -8,7 +8,6 @@ import itertools import platform import sys import time -import warnings import pluggy import py @@ -145,25 +144,15 @@ class TerminalReporter: self.startdir = py.path.local() if file is None: file = sys.stdout - self._writer = _pytest.config.create_terminal_writer(config, file) - self._screen_width = self.writer.fullwidth + self._tw = _pytest.config.create_terminal_writer(config, file) + self._screen_width = self._tw.fullwidth self.currentfspath = None self.reportchars = getreportopt(config) - self.hasmarkup = self.writer.hasmarkup + self.hasmarkup = self._tw.hasmarkup self.isatty = file.isatty() self._progress_items_reported = 0 self._show_progress_info = self.config.getini('console_output_style') == 'progress' - @property - def writer(self): - return self._writer - - @property - def _tw(self): - warnings.warn(DeprecationWarning('TerminalReporter._tw is deprecated, use TerminalReporter.writer instead'), - stacklevel=2) - return self.writer - def hasopt(self, char): char = {'xfailed': 'x', 'skipped': 's'}.get(char, char) return char in self.reportchars @@ -175,33 +164,33 @@ class TerminalReporter: self._write_progress_information_filling_space() self.currentfspath = fspath fspath = self.startdir.bestrelpath(fspath) - self.writer.line() - self.writer.write(fspath + " ") - self.writer.write(res) + self._tw.line() + self._tw.write(fspath + " ") + self._tw.write(res) def write_ensure_prefix(self, prefix, extra="", **kwargs): if self.currentfspath != prefix: - self.writer.line() + self._tw.line() self.currentfspath = prefix - self.writer.write(prefix) + self._tw.write(prefix) if extra: - self.writer.write(extra, **kwargs) + self._tw.write(extra, **kwargs) self.currentfspath = -2 self._write_progress_information_filling_space() def ensure_newline(self): if self.currentfspath: - self.writer.line() + self._tw.line() self.currentfspath = None def write(self, content, **markup): - self.writer.write(content, **markup) + self._tw.write(content, **markup) def write_line(self, line, **markup): if not isinstance(line, six.text_type): line = six.text_type(line, errors="replace") self.ensure_newline() - self.writer.line(line, **markup) + self._tw.line(line, **markup) def rewrite(self, line, **markup): """ @@ -214,22 +203,22 @@ class TerminalReporter: """ erase = markup.pop('erase', False) if erase: - fill_count = self.writer.fullwidth - len(line) - 1 + fill_count = self._tw.fullwidth - len(line) - 1 fill = ' ' * fill_count else: fill = '' line = str(line) - self.writer.write("\r" + line + fill, **markup) + self._tw.write("\r" + line + fill, **markup) def write_sep(self, sep, title=None, **markup): self.ensure_newline() - self.writer.sep(sep, title, **markup) + self._tw.sep(sep, title, **markup) def section(self, title, sep="=", **kw): - self.writer.sep(sep, title, **kw) + self._tw.sep(sep, title, **kw) def line(self, msg, **kw): - self.writer.line(msg, **kw) + self._tw.line(msg, **kw) def pytest_internalerror(self, excrepr): for line in six.text_type(excrepr).split("\n"): @@ -282,7 +271,7 @@ class TerminalReporter: if not running_xdist and self.showfspath: self.write_fspath_result(rep.nodeid, letter) else: - self.writer.write(letter) + self._tw.write(letter) self._write_progress_if_past_edge() else: if markup is None: @@ -299,13 +288,13 @@ class TerminalReporter: self.write_ensure_prefix(line, word, **markup) else: self.ensure_newline() - self.writer.write("[%s]" % rep.node.gateway.id) + self._tw.write("[%s]" % rep.node.gateway.id) if self._show_progress_info: - self.writer.write(self._get_progress_information_message() + " ", cyan=True) + self._tw.write(self._get_progress_information_message() + " ", cyan=True) else: - self.writer.write(' ') - self.writer.write(word, **markup) - self.writer.write(" " + line) + self._tw.write(' ') + self._tw.write(word, **markup) + self._tw.write(" " + line) self.currentfspath = -2 def _write_progress_if_past_edge(self): @@ -316,10 +305,10 @@ class TerminalReporter: self._write_progress_information_filling_space() return - past_edge = self.writer.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width + past_edge = self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width if past_edge: msg = self._get_progress_information_message() - self.writer.write(msg + '\n', cyan=True) + self._tw.write(msg + '\n', cyan=True) _PROGRESS_LENGTH = len(' [100%]') @@ -331,7 +320,7 @@ class TerminalReporter: if not self._show_progress_info: return msg = self._get_progress_information_message() - fill = ' ' * (self.writer.fullwidth - self.writer.chars_on_current_line - len(msg) - 1) + fill = ' ' * (self._tw.fullwidth - self._tw.chars_on_current_line - len(msg) - 1) self.write(fill + msg, cyan=True) def pytest_collection(self): @@ -418,9 +407,9 @@ class TerminalReporter: if self.config.option.collectonly: self._printcollecteditems(session.items) if self.stats.get('failed'): - self.writer.sep("!", "collection failures") + self._tw.sep("!", "collection failures") for rep in self.stats.get('failed'): - rep.toterminal(self.writer) + rep.toterminal(self._tw) return 1 return 0 lines = self.config.hook.pytest_report_collectionfinish( @@ -438,12 +427,12 @@ class TerminalReporter: name = item.nodeid.split('::', 1)[0] counts[name] = counts.get(name, 0) + 1 for name, count in sorted(counts.items()): - self.writer.line("%s: %d" % (name, count)) + self._tw.line("%s: %d" % (name, count)) else: for item in items: nodeid = item.nodeid nodeid = nodeid.replace("::()::", "::") - self.writer.line(nodeid) + self._tw.line(nodeid) return stack = [] indent = "" @@ -458,13 +447,13 @@ class TerminalReporter: # if col.name == "()": # continue indent = (len(stack) - 1) * " " - self.writer.line("%s%s" % (indent, col)) + self._tw.line("%s%s" % (indent, col)) @pytest.hookimpl(hookwrapper=True) def pytest_sessionfinish(self, exitstatus): outcome = yield outcome.get_result() - self.writer.line("") + self._tw.line("") summary_exit_codes = ( EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED) @@ -494,10 +483,10 @@ class TerminalReporter: self.write_sep("!", msg) if "KeyboardInterrupt" in msg: if self.config.option.fulltrace: - excrepr.toterminal(self.writer) + excrepr.toterminal(self._tw) else: - self.writer.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True) - excrepr.reprcrash.toterminal(self.writer) + self._tw.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True) + excrepr.reprcrash.toterminal(self._tw) def _locationline(self, nodeid, fspath, lineno, domain): def mkrel(nodeid): @@ -554,13 +543,13 @@ class TerminalReporter: self.write_sep("=", "warnings summary", yellow=True, bold=False) for location, warning_records in grouped: - self.writer.line(str(location) or '') + self._tw.line(str(location) or '') for w in warning_records: lines = w.message.splitlines() indented = '\n'.join(' ' + x for x in lines) - self.writer.line(indented) - self.writer.line() - self.writer.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html') + self._tw.line(indented) + self._tw.line() + self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html') def summary_passes(self): if self.config.option.tbstyle != "no": @@ -577,10 +566,10 @@ class TerminalReporter: def print_teardown_sections(self, rep): for secname, content in rep.sections: if 'teardown' in secname: - self.writer.sep('-', secname) + self._tw.sep('-', secname) if content[-1:] == "\n": content = content[:-1] - self.writer.line(content) + self._tw.line(content) def summary_failures(self): if self.config.option.tbstyle != "no": @@ -620,12 +609,12 @@ class TerminalReporter: self._outrep_summary(rep) def _outrep_summary(self, rep): - rep.toterminal(self.writer) + rep.toterminal(self._tw) for secname, content in rep.sections: - self.writer.sep("-", secname) + self._tw.sep("-", secname) if content[-1:] == "\n": content = content[:-1] - self.writer.line(content) + self._tw.line(content) def summary_stats(self): session_duration = time.time() - self._sessionstarttime diff --git a/changelog/1993.bugfix b/changelog/1993.bugfix deleted file mode 100644 index 07a78cc91..000000000 --- a/changelog/1993.bugfix +++ /dev/null @@ -1 +0,0 @@ -Resume output capturing after ``capsys/capfd.disabled()`` context manager. diff --git a/changelog/2124.bugfix b/changelog/2124.bugfix deleted file mode 100644 index e1c5e044c..000000000 --- a/changelog/2124.bugfix +++ /dev/null @@ -1 +0,0 @@ -``pytest_fixture_setup`` and ``pytest_fixture_post_finalizer`` hooks are now called for all ``conftest.py`` files. diff --git a/changelog/2124.feature b/changelog/2124.feature deleted file mode 100644 index 267fdabc9..000000000 --- a/changelog/2124.feature +++ /dev/null @@ -1 +0,0 @@ -``pytest_fixture_post_finalizer`` hook can now receive a ``request`` argument. diff --git a/changelog/2236.removal b/changelog/2236.removal deleted file mode 100644 index 84f98d009..000000000 --- a/changelog/2236.removal +++ /dev/null @@ -1 +0,0 @@ -- Remove internal ``_preloadplugins()`` function. This removal is part of the ``pytest_namespace()`` hook deprecation. \ No newline at end of file diff --git a/changelog/2267.feature b/changelog/2267.feature deleted file mode 100644 index a2f14811e..000000000 --- a/changelog/2267.feature +++ /dev/null @@ -1,4 +0,0 @@ -Replace the old introspection code in compat.py that determines the -available arguments of fixtures with inspect.signature on Python 3 and -funcsigs.signature on Python 2. This should respect __signature__ -declarations on functions. diff --git a/changelog/2491.bugfix b/changelog/2491.bugfix deleted file mode 100644 index fbb16e17e..000000000 --- a/changelog/2491.bugfix +++ /dev/null @@ -1,4 +0,0 @@ -If an exception happens while loading a plugin, pytest no longer hides the original traceback. -In python2 it will show the original traceback with a new message that explains in which plugin. -In python3 it will show 2 canonized exceptions, the original exception while loading the plugin -in addition to an exception that PyTest throws about loading a plugin. diff --git a/changelog/2549.feature b/changelog/2549.feature deleted file mode 100644 index 4866d990d..000000000 --- a/changelog/2549.feature +++ /dev/null @@ -1 +0,0 @@ -Report only once tests with global ``pytestmark`` variable. \ No newline at end of file diff --git a/changelog/2641.trivial b/changelog/2641.trivial deleted file mode 100644 index 1799f90d2..000000000 --- a/changelog/2641.trivial +++ /dev/null @@ -1 +0,0 @@ -pytest now depends on `attrs `_ for internal structures to ease code maintainability. diff --git a/changelog/2642.trivial b/changelog/2642.trivial deleted file mode 100644 index bae449dba..000000000 --- a/changelog/2642.trivial +++ /dev/null @@ -1 +0,0 @@ -Refactored internal Python 2/3 compatibility code to use ``six``. diff --git a/changelog/2657.feature b/changelog/2657.feature deleted file mode 100644 index d0cc3bfd4..000000000 --- a/changelog/2657.feature +++ /dev/null @@ -1 +0,0 @@ -Now pytest displays the total progress percentage while running tests. The previous output style can be set by setting the new ``console_output_style`` to ``classic``. diff --git a/changelog/2672.removal b/changelog/2672.removal deleted file mode 100644 index e660c27fd..000000000 --- a/changelog/2672.removal +++ /dev/null @@ -1,2 +0,0 @@ -Internally change ``CallSpec2`` to have a list of marks instead of a broken mapping of keywords. -This removes the keywords attribute of the internal ``CallSpec2`` class. \ No newline at end of file diff --git a/changelog/2675.removal b/changelog/2675.removal deleted file mode 100644 index 44f597892..000000000 --- a/changelog/2675.removal +++ /dev/null @@ -1 +0,0 @@ -remove ParameterSet.deprecated_arg_dict - its not a public api and the lack of the underscore was a naming error. \ No newline at end of file diff --git a/changelog/2708.feature b/changelog/2708.feature deleted file mode 100644 index f6039ede9..000000000 --- a/changelog/2708.feature +++ /dev/null @@ -1 +0,0 @@ -Match ``warns`` signature to ``raises`` by adding ``match`` keyworkd. \ No newline at end of file diff --git a/changelog/2709.bugfix b/changelog/2709.bugfix deleted file mode 100644 index 88503b050..000000000 --- a/changelog/2709.bugfix +++ /dev/null @@ -1 +0,0 @@ -``capsys`` and ``capfd`` can now be used by other fixtures. diff --git a/changelog/2719.trivial b/changelog/2719.trivial deleted file mode 100644 index 008f1dd20..000000000 --- a/changelog/2719.trivial +++ /dev/null @@ -1 +0,0 @@ -Stop vendoring ``pluggy`` - we're missing out on it's latest changes for not much benefit diff --git a/changelog/2734.trivial b/changelog/2734.trivial deleted file mode 100644 index b3f8471af..000000000 --- a/changelog/2734.trivial +++ /dev/null @@ -1 +0,0 @@ -Internal refactor: simplify ascii string escaping by using the backslashreplace error handler in newer Python 3 versions. diff --git a/changelog/2738.bugfix b/changelog/2738.bugfix deleted file mode 100644 index c53869f49..000000000 --- a/changelog/2738.bugfix +++ /dev/null @@ -1 +0,0 @@ -Internal ``pytester`` plugin properly encodes ``bytes`` arguments to ``utf-8``. diff --git a/changelog/2751.bugfix b/changelog/2751.bugfix deleted file mode 100644 index 76004a653..000000000 --- a/changelog/2751.bugfix +++ /dev/null @@ -1 +0,0 @@ -``testdir`` now uses use the same method used by ``tmpdir`` to create its temporary directory. This changes the final structure of the ``testdir`` directory slightly, but should not affect usage in normal scenarios and avoids a number of potential problems. \ No newline at end of file diff --git a/changelog/2767.removal b/changelog/2767.removal deleted file mode 100644 index b9c3984cd..000000000 --- a/changelog/2767.removal +++ /dev/null @@ -1 +0,0 @@ -Remove the internal multi-typed attribute ``Node._evalskip`` and replace it with the boolean ``Node._skipped_by_mark``. \ No newline at end of file diff --git a/changelog/2767.trivial b/changelog/2767.trivial deleted file mode 100644 index c42a06e07..000000000 --- a/changelog/2767.trivial +++ /dev/null @@ -1 +0,0 @@ -* remove unnecessary mark evaluator in unittest plugin \ No newline at end of file diff --git a/changelog/2794.feature b/changelog/2794.feature deleted file mode 100644 index 9cff1c4bb..000000000 --- a/changelog/2794.feature +++ /dev/null @@ -1,3 +0,0 @@ -Pytest now captures and displays output from the standard `logging` module. The user can control the logging level to be captured by specifying options in ``pytest.ini``, the command line and also during individual tests using markers. Also, a ``caplog`` fixture is available that enables users to test the captured log during specific tests (similar to ``capsys`` for example). For more information, please see the `docs `_. - -This feature was introduced by merging the popular `pytest-catchlog `_ plugin, thanks to `Thomas Hisch `_. Be advised that during the merging the backward compatibility interface with the defunct ``pytest-capturelog`` has been dropped. \ No newline at end of file diff --git a/changelog/2803.removal b/changelog/2803.removal deleted file mode 100644 index 4ebdb903e..000000000 --- a/changelog/2803.removal +++ /dev/null @@ -1 +0,0 @@ -``TerminalReporter._tw`` has been deprecated in favor of ``TerminalReporter.writer`` and will be removed in a future version. Also, ``TerminalReporter.writer`` is now read-only. diff --git a/changelog/2808.feature b/changelog/2808.feature deleted file mode 100644 index 26245f047..000000000 --- a/changelog/2808.feature +++ /dev/null @@ -1 +0,0 @@ -Add ``allow_module_level`` kwarg to ``pytest.skip()``, enabling to skip the whole module. diff --git a/changelog/2809.bugfix b/changelog/2809.bugfix deleted file mode 100644 index 6db7e8c6c..000000000 --- a/changelog/2809.bugfix +++ /dev/null @@ -1 +0,0 @@ -Pytest no longer complains about warnings with unicode messages being non-ascii compatible even for ascii-compatible messages. As a result of this, warnings with unicode messages are converted first to an ascii representation for safety. \ No newline at end of file diff --git a/changelog/2812.removal b/changelog/2812.removal deleted file mode 100644 index 74894e0ef..000000000 --- a/changelog/2812.removal +++ /dev/null @@ -1 +0,0 @@ -Pytest no longer supports Python **2.6** and **3.3**. Those Python versions are EOL for some time now and incurr maintanance and compatibility costs on the pytest core team, and following up with the rest of the community we decided that they will no longer be supported starting on this version. Users which still require those versions should pin pytest to ``<3.3``. diff --git a/changelog/2824.feature b/changelog/2824.feature deleted file mode 100644 index 690ca939a..000000000 --- a/changelog/2824.feature +++ /dev/null @@ -1 +0,0 @@ -Allow setting ``file_or_dir``, ``-c``, and ``-o`` in PYTEST_ADDOPTS. diff --git a/changelog/2836.bug b/changelog/2836.bug deleted file mode 100644 index afa1961d7..000000000 --- a/changelog/2836.bug +++ /dev/null @@ -1 +0,0 @@ -Match fixture paths against actual path segments in order to avoid matching folders which share a prefix. diff --git a/changelog/2845.bugfix b/changelog/2845.bugfix deleted file mode 100644 index c6767631e..000000000 --- a/changelog/2845.bugfix +++ /dev/null @@ -1 +0,0 @@ -Change return value of pytest command when ``--maxfail`` is reached from ``2`` (interrupted) to ``1`` (failed). diff --git a/changelog/2876.trivial b/changelog/2876.trivial deleted file mode 100644 index 354f6ad5c..000000000 --- a/changelog/2876.trivial +++ /dev/null @@ -1 +0,0 @@ -Calls to ``Metafunc.addcall`` now emit a deprecation warning. This function is scheduled to be removed in ``pytest-4.0``. diff --git a/changelog/2877.trivial b/changelog/2877.trivial deleted file mode 100644 index c4198af97..000000000 --- a/changelog/2877.trivial +++ /dev/null @@ -1 +0,0 @@ -Internal move of the parameterset extraction to a more maintainable place. diff --git a/changelog/2879.feature b/changelog/2879.feature deleted file mode 100644 index 8932d8c30..000000000 --- a/changelog/2879.feature +++ /dev/null @@ -1 +0,0 @@ -Return stdout/stderr capture results as a ``namedtuple``, so ``out`` and ``err`` can be accessed by attribute. diff --git a/changelog/2910.trivial b/changelog/2910.trivial deleted file mode 100644 index 87bf00dfe..000000000 --- a/changelog/2910.trivial +++ /dev/null @@ -1 +0,0 @@ -Internal refactoring to simplify scope node lookup. diff --git a/changelog/2922.trivial b/changelog/2922.trivial deleted file mode 100644 index 06d1346bb..000000000 --- a/changelog/2922.trivial +++ /dev/null @@ -1 +0,0 @@ -Configure ``pytest`` to prevent pip from installing pytest in unsupported Python versions. diff --git a/changelog/2923.feature b/changelog/2923.feature deleted file mode 100644 index c6937741f..000000000 --- a/changelog/2923.feature +++ /dev/null @@ -1,2 +0,0 @@ -Add ``capfdbinary`` a version of ``capfd`` which returns bytes from -``readouterr()``. diff --git a/changelog/2934.feature b/changelog/2934.feature deleted file mode 100644 index 38dcb5f73..000000000 --- a/changelog/2934.feature +++ /dev/null @@ -1,2 +0,0 @@ -Add ``capsysbinary`` a version of ``capsys`` which returns bytes from -``readouterr()``. diff --git a/changelog/502.feature b/changelog/502.feature deleted file mode 100644 index eb61640b9..000000000 --- a/changelog/502.feature +++ /dev/null @@ -1 +0,0 @@ -Implement feature to skip ``setup.py`` files when ran with ``--doctest-modules``. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 2e3b45805..1a5f3760b 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,8 @@ Release announcements :maxdepth: 2 + release-3.3.0 + release-3.2.5 release-3.2.4 release-3.2.3 release-3.2.2 diff --git a/doc/en/announce/release-3.2.5.rst b/doc/en/announce/release-3.2.5.rst new file mode 100644 index 000000000..a520ce2b3 --- /dev/null +++ b/doc/en/announce/release-3.2.5.rst @@ -0,0 +1,18 @@ +pytest-3.2.5 +======================================= + +pytest 3.2.5 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: + +* Bruno Oliveira + + +Happy testing, +The pytest Development Team diff --git a/doc/en/announce/release-3.3.0.rst b/doc/en/announce/release-3.3.0.rst new file mode 100644 index 000000000..e0740e7d5 --- /dev/null +++ b/doc/en/announce/release-3.3.0.rst @@ -0,0 +1,50 @@ +pytest-3.3.0 +======================================= + +The pytest team is proud to announce the 3.3.0 release! + +pytest is a mature Python testing tool with more than a 1600 tests +against itself, passing on many different interpreters and platforms. + +This release contains a number of bugs fixes and improvements, so users are encouraged +to take a look at the CHANGELOG: + + http://doc.pytest.org/en/latest/changelog.html + +For complete documentation, please visit: + + http://docs.pytest.org + +As usual, you can upgrade from pypi via: + + pip install -U pytest + +Thanks to all who contributed to this release, among them: + +* Anthony Sottile +* Bruno Oliveira +* Ceridwen +* Daniel Hahler +* Dirk Thomas +* Dmitry Malinovsky +* Florian Bruhin +* George Y. Kussumoto +* Hugo +* Jesús Espino +* Joan Massich +* Ofir +* OfirOshir +* Ronny Pfannschmidt +* Samuel Dion-Girardeau +* Srinivas Reddy Thatiparthy +* Sviatoslav Abakumov +* Tarcisio Fischer +* Thomas Hisch +* Tyler Goodlet +* hugovk +* je +* prokaktus + + +Happy testing, +The Pytest Development Team diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index 8ceada52d..84f2c43ed 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -10,3 +10,96 @@ With the pytest 3.0 release we introduced a clear communication scheme for when To communicate changes we are already issuing deprecation warnings, but they are not displayed by default. In pytest 3.0 we changed the default setting so that pytest deprecation warnings are displayed if not explicitly silenced (with ``--disable-pytest-warnings``). We will only remove deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we will not remove it in 4.0 but in 5.0). + + +Deprecation Roadmap +------------------- + +This page lists deprecated features and when we plan to remove them. It is important to list the feature, the version where it got deprecated and the version we plan to remove it. + +Following our deprecation policy, we should aim to keep features for *at least* two minor versions after it was considered deprecated. + + +Future Releases +~~~~~~~~~~~~~~~ + +3.4 +^^^ + +**Old style classes** + +Issue: `#2147 `_. + +Deprecated in ``3.2``. + +4.0 +^^^ + +**Yield tests** + +Deprecated in ``3.0``. + +**pytest-namespace hook** + +deprecated in ``3.2``. + +**Marks in parameter sets** + +Deprecated in ``3.2``. + +**--result-log** + +Deprecated in ``3.0``. + +See `#830 `_ for more information. Suggested alternative: `pytest-tap `_. + +**metafunc.addcall** + +Issue: `#2876 `_. + +Deprecated in ``3.3``. + +**pytest_plugins in non-toplevel conftests** + +There is a deep conceptual confusion as ``conftest.py`` files themselves are activated/deactivated based on path, but the plugins they depend on aren't. + +Issue: `#2639 `_. + +Not yet officially deprecated. + +**passing a single string to pytest.main()** + +Pass a list of strings to ``pytest.main()`` instead. + +Deprecated in ``3.1``. + +**[pytest] section in setup.cfg** + +Use ``[tool:pytest]`` instead for compatibility with other tools. + +Deprecated in ``3.0``. + +Past Releases +~~~~~~~~~~~~~ + +3.0 +^^^ + +* The following deprecated commandline options were removed: + + * ``--genscript``: no longer supported; + * ``--no-assert``: use ``--assert=plain`` instead; + * ``--nomagic``: use ``--assert=plain`` instead; + * ``--report``: use ``-r`` instead; + +* Removed all ``py.test-X*`` entry points. The versioned, suffixed entry points + were never documented and a leftover from a pre-virtualenv era. These entry + points also created broken entry points in wheels, so removing them also + removes a source of confusion for users. + + + +3.3 +^^^ + +* Dropped support for EOL Python 2.6 and 3.3. \ No newline at end of file diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 49852ed7b..dd01b2527 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -411,11 +411,8 @@ is to be run with different sets of arguments for its three arguments: Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize):: . $ pytest -rs -q multipython.py - ssssssssssssssssssssssss... [100%] - ========================= short test summary info ========================== - SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:24: 'python2.7' not found - SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:24: 'python3.4' not found - 3 passed, 24 skipped in 0.12 seconds + ........................... [100%] + 27 passed in 0.12 seconds Indirect parametrization of optional implementations/imports -------------------------------------------------------------------- diff --git a/setup.py b/setup.py index f586101ea..3eb38efe6 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ def main(): # if _PYTEST_SETUP_SKIP_PLUGGY_DEP is set, skip installing pluggy; # used by tox.ini to test with pluggy master if '_PYTEST_SETUP_SKIP_PLUGGY_DEP' not in os.environ: - install_requires.append('pluggy>=0.5,<0.6') + install_requires.append('pluggy>=0.5,<0.7') if has_environment_marker_support(): extras_require[':python_version<"3.0"'] = ['funcsigs'] extras_require[':sys_platform=="win32"'] = ['colorama'] diff --git a/tasks/__init__.py b/tasks/__init__.py index 992f4a4ad..8ea038f0a 100644 --- a/tasks/__init__.py +++ b/tasks/__init__.py @@ -4,10 +4,9 @@ Invoke tasks to help with pytest development and release process. import invoke -from . import generate, vendoring +from . import generate ns = invoke.Collection( generate, - vendoring ) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 6e1e16331..f3c40cb3d 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -99,3 +99,16 @@ def test_metafunc_addcall_deprecated(testdir): "*Metafunc.addcall is deprecated*", "*2 passed, 2 warnings*", ]) + + +def test_pytest_catchlog_deprecated(testdir): + testdir.makepyfile(""" + def test_func(pytestconfig): + pytestconfig.pluginmanager.register(None, 'pytest_catchlog') + """) + res = testdir.runpytest() + assert res.ret == 0 + res.stdout.fnmatch_lines([ + "*pytest-catchlog plugin has been merged into the core*", + "*1 passed, 1 warnings*", + ]) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 6c1443c30..0cce03f1d 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -129,6 +129,24 @@ class TestImportHookInstallation(object): result = testdir.runpytest_subprocess('--assert=rewrite') assert result.ret == 0 + def test_pytest_plugins_rewrite_module_names_correctly(self, testdir): + """Test that we match files correctly when they are marked for rewriting (#2939).""" + contents = { + 'conftest.py': """ + pytest_plugins = "ham" + """, + 'ham.py': "", + 'hamster.py': "", + 'test_foo.py': """ + def test_foo(pytestconfig): + assert pytestconfig.pluginmanager.rewrite_hook.find_module('ham') is not None + assert pytestconfig.pluginmanager.rewrite_hook.find_module('hamster') is None + """, + } + testdir.makepyfile(**contents) + result = testdir.runpytest_subprocess('--assert=rewrite') + assert result.ret == 0 + @pytest.mark.parametrize('mode', ['plain', 'rewrite']) @pytest.mark.parametrize('plugin_state', ['development', 'installed']) def test_installed_plugin_rewrite(self, testdir, mode, plugin_state): diff --git a/testing/test_mark.py b/testing/test_mark.py index 3ac42daee..46bf0b0e7 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -161,11 +161,13 @@ def test_markers_option(testdir): markers = a1: this is a webtest marker a1some: another marker + nodescription """) result = testdir.runpytest("--markers", ) result.stdout.fnmatch_lines([ "*a1*this is a webtest*", "*a1some*another marker", + "*nodescription*", ]) @@ -186,6 +188,21 @@ def test_ini_markers_whitespace(testdir): rec.assertoutcome(passed=1) +def test_marker_without_description(testdir): + testdir.makefile(".cfg", setup=""" + [tool:pytest] + markers=slow + """) + testdir.makeconftest(""" + import pytest + pytest.mark.xfail('FAIL') + """) + ftdir = testdir.mkdir("ft1_dummy") + testdir.tmpdir.join("conftest.py").move(ftdir.join("conftest.py")) + rec = testdir.runpytest_subprocess("--strict") + rec.assert_outcomes() + + def test_markers_option_with_plugin_in_current_dir(testdir): testdir.makeconftest('pytest_plugins = "flip_flop"') testdir.makepyfile(flip_flop="""\ @@ -576,7 +593,7 @@ class TestFunctional(object): request.applymarker(pytest.mark.hello) def pytest_terminal_summary(terminalreporter): values = terminalreporter.stats['passed'] - terminalreporter.writer.line("keyword: %s" % values[0].keywords) + terminalreporter._tw.line("keyword: %s" % values[0].keywords) """) testdir.makepyfile(""" def test_func(arg): diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 485a3d8c4..98a8ca121 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -219,7 +219,7 @@ class TestTerminal(object): f = py.io.TextIO() monkeypatch.setattr(f, 'isatty', lambda *args: True) tr = TerminalReporter(config, f) - tr.writer.fullwidth = 10 + tr._tw.fullwidth = 10 tr.write('hello') tr.rewrite('hey', erase=True) assert f.getvalue() == 'hello' + '\r' + 'hey' + (6 * ' ')