Support for the new builtin breakpoint function in Python 3.7#3331
Support for the new builtin breakpoint function in Python 3.7#3331RonnyPfannschmidt merged 22 commits intopytest-dev:featuresfrom tonybaloney:breakpoint_support
Conversation
|
Discovered that the debugging module has no test coverage, so I want to develop tests for it before I start fiddling with it's behaviours. |
|
@tonybaloney for historic reasons its in |
|
@RonnyPfannschmidt where would you recommend I put these tests? is |
|
@tonybaloney for now please put them into test-pdb, as a follow-up it seems sensible to rename that file |
…esetting back when system default (pdb) is used""
…ystem default is set
…akpoint() not supported
…alled when breakpoint() is used
|
This PR is ready for review, I still need to add some documentation to explain the behaviours, but would like feedback on the work so far (most of it was just tests tbh!) |
|
Tested with the example IPython class, which breaks but seems to be caused by #2064 |
|
@nicoddemus @RonnyPfannschmidt done (except docs) |
|
Build failed on 1 test https://travis-ci.org/pytest-dev/pytest/jobs/357232290#L585 I asserted the output was "1 passed" but it is "2 passed" on Travis. Might have something to do with Hypothesis, trying to repro locally, but I can make the assertion a bit more vauge |
|
Yep. once I install hypothesis, it changes to 2 passed locally as well (which I guess makes sense as the hypothesis plugin is designed to do that) |
…veloping in pytest)
nicoddemus
left a comment
There was a problem hiding this comment.
Awesome work @tonybaloney, many thanks. Please take a look at my comments.
_pytest/debugging.py
Outdated
|
|
||
| # Use custom Pdb class set_trace instead of default Pdb on breakpoint() call | ||
| if SUPPORTS_BREAKPOINT_BUILTIN: | ||
| _environ_pythonbreakpoint = getattr(os.environ, 'PYTHONBREAKPOINT', '') |
There was a problem hiding this comment.
This seems like it should be _environ_pythonbreakpoint = os.environ.get('PYTHONBREAKPOINT', '') right?
changelog/3180.feature.rst
Outdated
| @@ -0,0 +1,12 @@ | |||
| Support for Python 3.7s builtin breakpoint() method. | |||
There was a problem hiding this comment.
Thanks for the detailed changelog entry, but unfortunately towncrier can't format multi-paragraph entries correctly in the CHANGELOG.
I suggest adding this to a new section after pdb section in the docs, and reducing the changelog entry to:
Support for Python 3.7s builtin ``breakpoint()`` method, see `the debugging documentation <link here>`_ for details.The new section could be named something like Support for breakpoint() support and provide a link to the relevant PEP as well which would act as an introduction to the topic as well.
testing/test_pdb.py
Outdated
| called.append("set_trace") | ||
|
|
||
| _pytest._CustomDebugger = _CustomDebugger | ||
| return called |
There was a problem hiding this comment.
It probably doesn't matter, but I think it is better to get rid of the reference to the class after the test:
_pytest._CustomDebugger = _CustomDebugger
yield called
del _pytest._CustomDebugger
testing/test_pdb.py
Outdated
| """ | ||
| config = testdir.parseconfig() | ||
|
|
||
| pytest_configure(config) |
There was a problem hiding this comment.
This is clever, but it might be dangerous to call pytest_configure by hand like this. How about:
testdir.makeconftest("""
from pytest import hookimpl
from _pytest.debugging import pytestPDB
@hookimpl(hookwrapper=True)
def pytest_configure(config):
yield
assert sys.breakpointhook is pytestPDB.set_trace
@hookimpl(hookwrapper=True)
def pytest_unconfigure(config):
yield
assert sys.breakpointhook is sys.__breakpoint__
""")
testdir.makepyfile("""
def test_nothing(): pass
""")There was a problem hiding this comment.
I couldn't locate the right test pattern looking at the others. This makes sense
testing/test_pdb.py
Outdated
| assert sys.breakpointhook != pytestPDB.set_trace | ||
|
|
||
| @pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin") | ||
| def test_sys_breakpointhook_configure_and_unconfigure_with_pdb_flag(self, testdir): |
There was a problem hiding this comment.
You can probably parametrize this test with the above.
@pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
@pytest.mark.parametrize('args', [('--pdb',), ()])
def test_sys_breakpointhook_configure_and_unconfigure(self, testdir, args):
...
result = testdir.runpytest_inprocess(*args)(It's not necessary to pass p1 to runpytest_inprocess).
testing/test_pdb.py
Outdated
| def test_pdb_not_altered(self, testdir): | ||
| """ | ||
| Test that calling PDB set_trace() is not affected | ||
| when PYTHONBREAKPOINT=0 |
There was a problem hiding this comment.
Is this comment correct? I don't see PYTHONBREAKPOINT being set in the test..
testing/test_pdb.py
Outdated
| import pytest | ||
|
|
||
|
|
||
| _ENVIRON_PYTHONBREAKPOINT = getattr(os.environ, 'PYTHONBREAKPOINT', '') |
There was a problem hiding this comment.
Again this seems like it should be `_ENVIRON_PYTHONBREAKPOINT = os.environ.get('PYTHONBREAKPOINT', '')
|
@nicoddemus made the code changes. Docs still need improving, but explain the behaviour for now. I can add more examples later when I've got some more time |
|
Hi @tonybaloney thanks for the quick response! I made some doc formatting changes (all minor), hope you don't mind. I worry though that the |
Our rst-linter unfortunately doesn't accept `ref` directives in the CHANGELOG files
|
@nicoddemus not sure I really understood this properly. It doesn't seem to execute. If I change the assertions it doesnt fail the tests |
|
@tonybaloney Oh my bad, my example was incomplete: ...
testdir.makepyfile("""
def test_nothing(): pass
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
'*1 passed in *',
])IOW, |
|
@nicoddemus that makes sense, but all 3 fail now I looked at the documentation and https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_configure that hook doesn't support hookwrapper=True. I tried taking that out and just get another error |
* Execute pytest in a subprocess in cases of tests which change global state * Parametrize with --pdb and without the flag
testing/test_pdb.py
Outdated
| Test that sys.breakpointhook by default is set to pytest's internal class. | ||
| """ | ||
| assert sys.breakpointhook != pytestPDB.set_trace | ||
| assert sys.breakpointhook == pytestPDB.set_trace |
There was a problem hiding this comment.
This test seemed incorrect to me and it was failing on my system: wasn't sys.breakpoint supposed to be set in the normal circumstance? I changed the logic and docstring to reflect that and it passes. @tonybaloney please double check here.
|
@tonybaloney sorry my bad, I forgot
|
|
@nicoddemus I figured out why that last test was failing, because the test is being run inside a pytest session, the new behaviour would mean that sys.breakpointhook is going to be unpredictable depending on the version of pytest being used and it doesn't test anything other than runtime assumptions. I'm all done now :) |
nicoddemus
left a comment
There was a problem hiding this comment.
Thanks a lot @tonybaloney!
I would like a second set of eyes to take a look before merging though, do you have some time to review this @RonnyPfannschmidt?
| Test that supports breakpoint global marks on Python 3.7+ and not on | ||
| CPython 3.5, 2.7 | ||
| """ | ||
| if sys.version_info.major == 3 and sys.version_info.minor >= 7: |
There was a problem hiding this comment.
could use sys.version_info >= (3, 7) as a slightly more readable alternative.
| Andy Freeland | ||
| Anthon van der Neut | ||
| Anthony Shaw | ||
| Anthony Sottile |
|
well done, im happy to merge 👍 |
Working on conditions stated in #3180
Support for Python 3.7s builtin breakpoint() method.
These are the behaviours:
Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs (you can delete this text from the final description, this is
just a guideline):
changelogfolder, with a name like<ISSUE NUMBER>.<TYPE>.rst. See changelog/README.rst for details.masterbranch for bug fixes, documentation updates and trivial changes.featuresbranch for new features and removals/deprecations.Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
AUTHORSin alphabetical order;