Compare commits

..

24 Commits

Author SHA1 Message Date
Bruno Oliveira
f27265cd28 Prepare CHANGELOG for 1.18.2 2017-07-28 07:31:45 -03:00
Bruno Oliveira
6b0a8c633b Fix changelog grammar 2017-07-28 07:31:27 -03:00
Ronny Pfannschmidt
7f2ca0aecb Merge pull request #194 from nicoddemus/error-handler
Fix internal handling in process_from_remote
2017-07-28 07:33:56 +02:00
Bruno Oliveira
64f8ad5469 Fix internal handling in process_from_remote
Fix #175
2017-07-27 20:50:09 -03:00
Ronny Pfannschmidt
144b37ae4b Merge pull request #192 from pytest-dev/update-readme
Update README.rst
2017-07-24 20:15:18 +02:00
Florian Bruhin
e41ba03edb Update README.rst
Remove easy_install because (hopefully) nobody uses that anymore nowadays, and remove the outdated note about using the pytest issue tracker.
2017-07-24 20:04:58 +02:00
Bruno Oliveira
cb3e734397 Add towncrier link to PULL_REQUEST_TEMPLATE.md 2017-07-17 17:56:58 -03:00
Ronny Pfannschmidt
af8a5742ad Merge pull request #186 from jayvdb/patch-1
Correction of example news file extension
2017-07-16 10:02:14 +02:00
Ronny Pfannschmidt
d2d5ae9f5f Merge pull request #185 from jayvdb/remove-implicit-dep
Removal of unnecessary dependency on py
2017-07-16 10:01:29 +02:00
John Vandenberg
05932011ed Correction of example news file extension 2017-07-14 19:48:56 +07:00
John Vandenberg
cd12d174c4 Removal of unnecessary dependency on py
`pytest-xdist` depends on `pytest>=3`.
`pytest 3.0.0` requires `py>=1.4.29`
and latest pytest requires `py>=1.4.33`.
Thus it is unnecessary for pytest-xdist to include
a requirement on `py>=1.4.22`

Fixes https://github.com/pytest-dev/pytest-xdist/issues/105
2017-07-14 19:40:40 +07:00
Bruno Oliveira
3652e21f3b Prepare release 1.18.1 2017-07-05 21:25:10 -03:00
Bruno Oliveira
a84b106a3b Add issue links to changelog template 2017-07-05 21:17:16 -03:00
Bruno Oliveira
5d757f9db3 Merge pull request #178 from timyhou/locals_d_issue
Unserialize reprlocals to a ReprLocal instance
2017-07-05 12:46:41 -03:00
Bruno Oliveira
674c623ffa Merge pull request #180 from luisincrespo/patch-1
Update CHANGELOG.rst
2017-07-05 12:36:00 -03:00
Luis Crespo
1fca8ee16d Update CHANGELOG.rst 2017-07-05 11:17:54 -04:00
Luis Crespo
185595f596 Update CHANGELOG.rst 2017-07-05 11:17:36 -04:00
Luis Crespo
55bc8c49d6 Update CHANGELOG.rst
Update `1.18.0` entry in CHANGELOG to reflect that `pytest-xdist` now requires `pytest>=3.0.0`.
2017-07-05 11:14:52 -04:00
thou
530c9b234a Unserialize reprlocals to a ReprLocal instance 2017-06-30 15:00:50 -05:00
Bruno Oliveira
1ca9eff35d Fixed changelog wording to be more user friendly 2017-06-28 18:32:59 -03:00
Bruno Oliveira
5320d25e47 Merge pull request #171 from timyhou/longrepr.sections_issue
Serialization/Deserialization was dropping longrepr.sections
2017-06-28 18:31:19 -03:00
thou
96ad4d1cfd Added news fragment 2017-06-28 10:58:37 -05:00
thou
5c1a35fee4 Serialization / Deserialization was dropping longrepr.sections 2017-06-27 16:30:49 -05:00
Bruno Oliveira
665b8eda8d Merge pull request #170 from nicoddemus/release-1.18.0
release 1.18.0
2017-06-26 21:28:30 -03:00
8 changed files with 111 additions and 30 deletions

View File

@@ -4,8 +4,8 @@ Here's a quick checklist that should be present in PRs:
- [ ] Make sure to include reasonable tests for your change if necessary - [ ] Make sure to include reasonable tests for your change if necessary
- [ ] Add a *news* file into the `changelog` folder, following these guidelines: - [ ] We use [towncrier](https://pypi.python.org/pypi/towncrier) for changelog management, so please add a *news* file into the `changelog` folder following these guidelines:
* Name it `$issue_id.$type` for example `588.bug` * Name it `$issue_id.$type` for example `588.bugfix`;
* If you don't have an issue_id change it to the PR id after creating it * If you don't have an issue_id change it to the PR id after creating it
* Ensure type is one of `removal`, `feature`, `bugfix`, `vendor`, `doc` or `trivial` * Ensure type is one of `removal`, `feature`, `bugfix`, `vendor`, `doc` or `trivial`
* Make sure to use full sentences with correct case and punctuation, for example: * Make sure to use full sentences with correct case and punctuation, for example:

View File

@@ -1,6 +1,36 @@
pytest-xdist 1.18.2 (2017-07-28)
================================
Bug Fixes
---------
- Removal of unnecessary dependency on incorrect version of py. (`#105
<https://github.com/pytest-dev/pytest-xdist/issues/105>`_)
- Fix bug in internal event-loop error handler in the master node. This bug
would shadow the original errors making extremely hard/impossible for users
to diagnose the problem properly. (`#175 <https://github.com/pytest-
dev/pytest-xdist/issues/175>`_)
pytest-xdist 1.18.1 (2017-07-05)
================================
Bug Fixes
---------
- Fixed serialization of ``longrepr.sections`` during error reporting from
workers. (`#171 <https://github.com/pytest-dev/pytest-xdist/issues/171>`_)
- Fix ``ReprLocal`` not being unserialized breaking --showlocals usages. (`#176
<https://github.com/pytest-dev/pytest-xdist/issues/176>`_)
pytest-xdist 1.18.0 (2017-06-26) pytest-xdist 1.18.0 (2017-06-26)
================================ ================================
- ``pytest-xdist`` now requires ``pytest>=3.0.0``.
Features Features
-------- --------

View File

@@ -44,10 +44,6 @@ Installation
Install the plugin with:: Install the plugin with::
easy_install pytest-xdist
# or
pip install pytest-xdist pip install pytest-xdist
or use the package in develop/in-place mode with or use the package in develop/in-place mode with
@@ -262,9 +258,3 @@ where the configuration file was found.
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist .. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
.. _`pytest-xdist repository`: https://github.com/pytest-dev/pytest-xdist .. _`pytest-xdist repository`: https://github.com/pytest-dev/pytest-xdist
.. _`pytest`: http://pytest.org .. _`pytest`: http://pytest.org
Issue and Bug Tracker
------------------------
Please use the `pytest issue tracker <https://github.com/pytest-dev/pytest/issues>`_
for reporting bugs in this plugin.

View File

@@ -6,14 +6,14 @@
{% endif %} {% endif %}
{% if sections[section] %} {% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section] and category != 'trivial' %} {% for category, val in definitions.items() if category in sections[section] %}
{{ definitions[category]['name'] }} {{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }} {{ underline * definitions[category]['name']|length }}
{% if definitions[category]['showcontent'] %} {% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category]|dictsort(by='value') %} {% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}{% if category != 'vendor' %} ({{ values|sort|join(', ') }}){% endif %} - {{ text }}{% if category != 'vendor' %} (`{{ values[0] }} <https://github.com/pytest-dev/pytest-xdist/issues/{{ values[0][1:] }}>`_){% endif %}
{% endfor %} {% endfor %}

View File

@@ -20,7 +20,7 @@ setup(
], ],
}, },
zip_safe=False, zip_safe=False,
install_requires=['execnet>=1.1', 'pytest>=3.0.0', 'py>=1.4.22'], install_requires=['execnet>=1.1', 'pytest>=3.0.0'],
setup_requires=['setuptools_scm'], setup_requires=['setuptools_scm'],
classifiers=[ classifiers=[
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',

View File

@@ -29,9 +29,9 @@ class EventCall:
class SlaveSetup: class SlaveSetup:
use_callback = False use_callback = False
def __init__(self, request): def __init__(self, request, testdir):
self.testdir = request.getfuncargvalue("testdir")
self.request = request self.request = request
self.testdir = testdir
self.events = queue.Queue() self.events = queue.Queue()
def setup(self, ): def setup(self, ):
@@ -65,8 +65,8 @@ class SlaveSetup:
@pytest.fixture @pytest.fixture
def slave(request): def slave(request, testdir):
return SlaveSetup(request) return SlaveSetup(request, testdir)
@pytest.mark.xfail(reason='#59') @pytest.mark.xfail(reason='#59')
@@ -86,12 +86,54 @@ class TestReportSerialization:
""") """)
reports = reprec.getreports("pytest_runtest_logreport") reports = reprec.getreports("pytest_runtest_logreport")
assert len(reports) == 3 assert len(reports) == 3
initial_failure_report = reports[1] rep = reports[1]
d = serialize_report(initial_failure_report) added_section = ('Failure Metadata', str("metadata metadata"), "*")
rep.longrepr.sections.append(added_section)
d = serialize_report(rep)
check_marshallable(d) check_marshallable(d)
processed_report = unserialize_report("testreport", d) a = unserialize_report("testreport", d)
assert 'Expected Message' \ # Check assembled == rep
in processed_report.longrepr.reprcrash.message assert a.__dict__.keys() == rep.__dict__.keys()
for key in rep.__dict__.keys():
if key != 'longrepr':
assert getattr(a, key) == getattr(rep, key)
assert rep.longrepr.reprcrash.lineno == a.longrepr.reprcrash.lineno
assert rep.longrepr.reprcrash.message == a.longrepr.reprcrash.message
assert rep.longrepr.reprcrash.path == a.longrepr.reprcrash.path
assert rep.longrepr.reprtraceback.entrysep \
== a.longrepr.reprtraceback.entrysep
assert rep.longrepr.reprtraceback.extraline \
== a.longrepr.reprtraceback.extraline
assert rep.longrepr.reprtraceback.style \
== a.longrepr.reprtraceback.style
assert rep.longrepr.sections == a.longrepr.sections
assert rep.longrepr.reprtraceback.reprentries \
== a.longrepr.reprtraceback.reprentries
# Missing section attribute PR171
assert added_section in a.longrepr.sections
def test_reprentries_serialization_170(self, testdir):
reprec = testdir.inline_runsource("""
def test_fail():
x = 0
assert x
""", '--showlocals', '-n1')
reports = reprec.getreports("pytest_runtest_logreport")
assert len(reports) == 3
rep = reports[1]
d = serialize_report(rep)
a = unserialize_report("testreport", d)
rep_entries = rep.longrepr.reprtraceback.reprentries
a_entries = a.longrepr.reprtraceback.reprentries
assert rep_entries == a_entries
for i in range(len(a_entries)):
assert rep_entries[i].lines == a_entries[i].lines
assert rep_entries[i].localssep == a_entries[i].localssep
assert rep_entries[i].reprfileloc == a_entries[i].reprfileloc
assert rep_entries[i].reprfuncargs == a_entries[i].reprfuncargs
assert rep_entries[i].reprlocals == a_entries[i].reprlocals
assert rep_entries[i].style == a_entries[i].style
def test_itemreport_outcomes(self, testdir): def test_itemreport_outcomes(self, testdir):
reprec = testdir.inline_runsource(""" reprec = testdir.inline_runsource("""
@@ -277,6 +319,15 @@ class TestSlaveInteractor:
("pytest_collectreport", "report.collector.fspath == bbb"), ("pytest_collectreport", "report.collector.fspath == bbb"),
]) ])
def test_process_from_remote_error_handling(self, slave, capsys):
slave.use_callback = True
slave.setup()
slave.slp.process_from_remote(('<nonono>', ()))
out, err = capsys.readouterr()
assert 'INTERNALERROR> ValueError: unknown event: <nonono>' in out
ev = slave.popevent()
assert ev.name == "errordown"
def test_remote_env_vars(testdir): def test_remote_env_vars(testdir):
testdir.makepyfile(''' testdir.makepyfile('''

View File

@@ -114,7 +114,8 @@ def serialize_report(rep):
return { return {
'reprcrash': reprcrash, 'reprcrash': reprcrash,
'reprtraceback': reprtraceback 'reprtraceback': reprtraceback,
'sections': rep.longrepr.sections
} }
import py import py

View File

@@ -323,16 +323,19 @@ class SlaveController(object):
except: except:
excinfo = py.code.ExceptionInfo() excinfo = py.code.ExceptionInfo()
py.builtin.print_("!" * 20, excinfo) py.builtin.print_("!" * 20, excinfo)
self.config.pluginmanager.notify_exception(excinfo) self.config.notify_exception(excinfo)
self.shutdown()
self.notify_inproc("errordown", node=self, error=excinfo)
def unserialize_report(name, reportdict): def unserialize_report(name, reportdict):
def assembled_report(reportdict): def assembled_report(reportdict):
from _pytest._code.code import ( from _pytest._code.code import (
ReprEntry,
ReprExceptionInfo, ReprExceptionInfo,
ReprFileLocation, ReprFileLocation,
ReprEntry,
ReprFuncArgs, ReprFuncArgs,
ReprLocals,
ReprTraceback ReprTraceback
) )
if reportdict['longrepr']: if reportdict['longrepr']:
@@ -343,26 +346,32 @@ def unserialize_report(name, reportdict):
unserialized_entries = [] unserialized_entries = []
for entry in reprtraceback['reprentries']: for entry in reprtraceback['reprentries']:
reprfuncargs, reprfileloc = None, None reprfuncargs, reprfileloc, reprlocals = None, None, None
if entry['reprfuncargs']: if entry['reprfuncargs']:
reprfuncargs = ReprFuncArgs(**entry['reprfuncargs']) reprfuncargs = ReprFuncArgs(**entry['reprfuncargs'])
if entry['reprfileloc']: if entry['reprfileloc']:
reprfileloc = ReprFileLocation(**entry['reprfileloc']) reprfileloc = ReprFileLocation(**entry['reprfileloc'])
if entry['reprlocals']:
reprlocals = ReprLocals(entry['reprlocals']['lines'])
reprentry = ReprEntry( reprentry = ReprEntry(
lines=entry['lines'], lines=entry['lines'],
reprfuncargs=reprfuncargs, reprfuncargs=reprfuncargs,
reprlocals=entry['reprlocals'], reprlocals=reprlocals,
filelocrepr=reprfileloc, filelocrepr=reprfileloc,
style=entry['style'] style=entry['style']
) )
unserialized_entries.append(reprentry) unserialized_entries.append(reprentry)
reprtraceback['reprentries'] = unserialized_entries reprtraceback['reprentries'] = unserialized_entries
reportdict['longrepr'] = ReprExceptionInfo( exception_info = ReprExceptionInfo(
reprtraceback=ReprTraceback(**reprtraceback), reprtraceback=ReprTraceback(**reprtraceback),
reprcrash=ReprFileLocation(**reprcrash), reprcrash=ReprFileLocation(**reprcrash),
) )
for section in reportdict['longrepr']['sections']:
exception_info.addsection(*section)
reportdict['longrepr'] = exception_info
return reportdict return reportdict
if name == "testreport": if name == "testreport":