Skip to content

Merge master into features #6712

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c9eeafa
Fix favicon for Chrome and Opera (#6639)
hugovk Jan 31, 2020
a9c5d31
PyCollector._genfunctions: use already created fixtureinfo (#6636)
blueyed Feb 1, 2020
8bd612b
typing: wrap_session
bluetech Feb 2, 2020
99d162e
Handle `Exit` exception in `pytest_sessionfinish`
blueyed Feb 2, 2020
c55bf23
doc: s/pytest_mark/pytestmark (#6661)
rebecca-palmer Feb 3, 2020
fb28966
Remove testing/test_modimport.py
blueyed Feb 3, 2020
abffd16
Keep (revisited) comment from https://github.com/pytest-dev/pytest/co…
blueyed Feb 3, 2020
1480aa3
Explicitly state on the PR template that we can squash commits (#6662)
nicoddemus Feb 3, 2020
b0d4526
internal: clean up getfslineno
blueyed Feb 2, 2020
61f2a26
Code/getfslineno: keep empty co_filename
blueyed Feb 3, 2020
dab90ef
typing: fix getfslineno
blueyed Feb 3, 2020
9c7f1d9
Remove compat.getfslineno
blueyed Feb 4, 2020
aa03287
assertion: save/restore hooks on item (#6646)
blueyed Feb 4, 2020
4316fe8
testing/conftest.py: testdir: set PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 (#…
blueyed Feb 4, 2020
bc49466
Remove testing/test_modimport.py (#6666)
blueyed Feb 4, 2020
632800a
internal: clean up getfslineno (#6656)
blueyed Feb 4, 2020
cdc7e13
pytester: clarify _makefile signature (#6675)
blueyed Feb 5, 2020
ef437ea
Remove incorrect choices comment (#6677)
rana-ahmed Feb 5, 2020
a8fc056
Handle `Exit` exception in `pytest_sessionfinish` (#6660)
blueyed Feb 6, 2020
30cb598
Typing around/from types in docs (#6699)
blueyed Feb 9, 2020
a62d9a4
ci: Travis: 3.5.1: upgrade pip, setuptools, virtualenv
blueyed Feb 10, 2020
12824e6
ci: Travis: remove non-py35 jobs
blueyed Feb 10, 2020
4492904
test_argcomplete: remove usage of `distutils.spawn` (#6703)
blueyed Feb 10, 2020
0ee007c
Fix CI (Travis) (#6704)
blueyed Feb 10, 2020
78baa7b
Merge remote-tracking branch 'upstream/master' into mm
nicoddemus Feb 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Here is a quick checklist that should be present in PRs.
- [ ] Target the `features` branch for new features, improvements, and removals/deprecations.
- [ ] Include documentation when adding new features.
- [ ] Include new tests or update existing tests when applicable.
- [X] Allow maintainers to push and squash when merging my commits. Please uncheck this if you prefer to squash the commits yourself.

Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:

Expand Down
35 changes: 5 additions & 30 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: python
dist: xenial
python: '3.7'
dist: trusty
python: '3.5.1'
cache: false

env:
Expand All @@ -16,36 +16,11 @@ install:

jobs:
include:
# OSX tests - first (in test stage), since they are the slower ones.
# Coverage for:
# - osx
# - verbose=1
- os: osx
osx_image: xcode10.1
language: generic
env: TOXENV=py37-xdist PYTEST_COVERAGE=1 PYTEST_ADDOPTS=-v
before_install:
- which python3
- python3 -V
- ln -sfn "$(which python3)" /usr/local/bin/python
- python -V
- test $(python -c 'import sys; print("%d%d" % sys.version_info[0:2])') = 37

# Full run of latest supported version, without xdist.
# Coverage for:
# - pytester's LsofFdLeakChecker
# - TestArgComplete (linux only)
# - numpy
# - old attrs
# - verbose=0
# - test_sys_breakpoint_interception (via pexpect).
- env: TOXENV=py37-lsof-numpy-oldattrs-pexpect-twisted PYTEST_COVERAGE=1 PYTEST_ADDOPTS=
python: '3.7'

# Coverage for Python 3.5.{0,1} specific code, mostly typing related.
- env: TOXENV=py35 PYTEST_COVERAGE=1 PYTEST_ADDOPTS="-k test_raises_cyclic_reference"
python: '3.5.1'
dist: trusty
before_install:
# Work around https://github.com/jaraco/zipp/issues/40.
- python -m pip install -U pip 'setuptools>=34.4.0' virtualenv

before_script:
- |
Expand Down
1 change: 1 addition & 0 deletions changelog/6646.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest <_pytest.pytester.Testdir.runpytest>` etc.
1 change: 1 addition & 0 deletions changelog/6660.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:func:`pytest.exit() <_pytest.outcomes.exit>` is handled when emitted from the :func:`pytest_sessionfinish <_pytest.hookspec.pytest_sessionfinish>` hook. This includes quitting from a debugger.
2 changes: 1 addition & 1 deletion doc/en/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = "img/pytest1favi.ico"
html_favicon = "img/favicon.png"

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
Expand Down
Binary file added doc/en/img/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/en/img/pytest1favi.ico
Binary file not shown.
4 changes: 2 additions & 2 deletions doc/en/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -901,8 +901,8 @@ Can be either a ``str`` or ``Sequence[str]``.
pytest_plugins = ("myapp.testsupport.tools", "myapp.testsupport.regression")


pytest_mark
~~~~~~~~~~~
pytestmark
~~~~~~~~~~

**Tutorial**: :ref:`scoped-marking`

Expand Down
2 changes: 2 additions & 0 deletions src/_pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ def path(self) -> Union[py.path.local, str]:
""" return a path object pointing to source code (or a str in case
of OSError / non-existing file).
"""
if not self.raw.co_filename:
return ""
try:
p = py.path.local(self.raw.co_filename)
# maybe don't try this checking
Expand Down
19 changes: 13 additions & 6 deletions src/_pytest/_code/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from bisect import bisect_right
from types import CodeType
from types import FrameType
from typing import Any
from typing import Iterator
from typing import List
from typing import Optional
Expand All @@ -17,6 +18,7 @@

import py

from _pytest.compat import get_real_func
from _pytest.compat import overload
from _pytest.compat import TYPE_CHECKING

Expand Down Expand Up @@ -277,14 +279,21 @@ def compile_( # noqa: F811
return s.compile(filename, mode, flags, _genframe=_genframe)


def getfslineno(obj) -> Tuple[Optional[Union["Literal['']", py.path.local]], int]:
def getfslineno(obj: Any) -> Tuple[Union[str, py.path.local], int]:
""" Return source location (path, lineno) for the given object.
If the source cannot be determined return ("", -1).

The line number is 0-based.
"""
from .code import Code

# xxx let decorators etc specify a sane ordering
# NOTE: this used to be done in _pytest.compat.getfslineno, initially added
# in 6ec13a2b9. It ("place_as") appears to be something very custom.
obj = get_real_func(obj)
if hasattr(obj, "place_as"):
obj = obj.place_as

try:
code = Code(obj)
except TypeError:
Expand All @@ -293,18 +302,16 @@ def getfslineno(obj) -> Tuple[Optional[Union["Literal['']", py.path.local]], int
except TypeError:
return "", -1

fspath = fn and py.path.local(fn) or None
fspath = fn and py.path.local(fn) or ""
lineno = -1
if fspath:
try:
_, lineno = findsource(obj)
except IOError:
pass
return fspath, lineno
else:
fspath = code.path
lineno = code.firstlineno
assert isinstance(lineno, int)
return fspath, lineno
return code.path, code.firstlineno


#
Expand Down
10 changes: 6 additions & 4 deletions src/_pytest/assertion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from _pytest.assertion import truncate
from _pytest.assertion import util
from _pytest.compat import TYPE_CHECKING
from _pytest.config import hookimpl

if TYPE_CHECKING:
from _pytest.main import Session
Expand Down Expand Up @@ -105,7 +106,8 @@ def pytest_collection(session: "Session") -> None:
assertstate.hook.set_session(session)


def pytest_runtest_setup(item):
@hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_protocol(item):
"""Setup the pytest_assertrepr_compare and pytest_assertion_pass hooks

The newinterpret and rewrite modules will use util._reprcompare if
Expand Down Expand Up @@ -143,6 +145,7 @@ def callbinrepr(op, left, right):
return res
return None

saved_assert_hooks = util._reprcompare, util._assertion_pass
util._reprcompare = callbinrepr

if item.ihook.pytest_assertion_pass.get_hookimpls():
Expand All @@ -154,10 +157,9 @@ def call_assertion_pass_hook(lineno, orig, expl):

util._assertion_pass = call_assertion_pass_hook

yield

def pytest_runtest_teardown(item):
util._reprcompare = None
util._assertion_pass = None
util._reprcompare, util._assertion_pass = saved_assert_hooks


def pytest_sessionfinish(session):
Expand Down
11 changes: 0 additions & 11 deletions src/_pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import attr
import py

import _pytest
from _pytest._io.saferepr import saferepr
from _pytest.outcomes import fail
from _pytest.outcomes import TEST_OUTCOME
Expand Down Expand Up @@ -308,16 +307,6 @@ def get_real_method(obj, holder):
return obj


def getfslineno(obj) -> Tuple[Union[str, py.path.local], int]:
# xxx let decorators etc specify a sane ordering
obj = get_real_func(obj)
if hasattr(obj, "place_as"):
obj = obj.place_as
fslineno = _pytest._code.getfslineno(obj)
assert isinstance(fslineno[1], int), obj
return fslineno


def getimfunc(func):
try:
return func.__func__
Expand Down
5 changes: 4 additions & 1 deletion src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from pluggy import PluginManager

import _pytest._code
import _pytest.assertion
import _pytest.deprecated
import _pytest.hookspec # the extension point definitions
from .exceptions import PrintHelp
Expand Down Expand Up @@ -284,6 +283,8 @@ class PytestPluginManager(PluginManager):
"""

def __init__(self):
import _pytest.assertion

super().__init__("pytest")
# The objects are module objects, only used generically.
self._conftest_plugins = set() # type: Set[object]
Expand Down Expand Up @@ -917,6 +918,8 @@ def _consider_importhook(self, args: Sequence[str]) -> None:
ns, unknown_args = self._parser.parse_known_and_unknown_args(args)
mode = getattr(ns, "assertmode", "plain")
if mode == "rewrite":
import _pytest.assertion

try:
hook = _pytest.assertion.install_importhook(self)
except SystemError:
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import _pytest
from _pytest._code.code import FormattedExcinfo
from _pytest._code.code import TerminalRepr
from _pytest._code.source import getfslineno
from _pytest._io import TerminalWriter
from _pytest.compat import _format_args
from _pytest.compat import _PytestWrapper
from _pytest.compat import get_real_func
from _pytest.compat import get_real_method
from _pytest.compat import getfslineno
from _pytest.compat import getfuncargnames
from _pytest.compat import getimfunc
from _pytest.compat import getlocation
Expand Down
23 changes: 13 additions & 10 deletions src/_pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from typing import Mapping

import pytest
from _pytest import nodes
from _pytest.compat import nullcontext
from _pytest.config import _strtobool
from _pytest.config import create_terminal_writer
Expand Down Expand Up @@ -326,13 +327,13 @@ def _finalize(self) -> None:
logger.setLevel(level)

@property
def handler(self):
def handler(self) -> LogCaptureHandler:
"""
:rtype: LogCaptureHandler
"""
return self._item.catch_log_handler
return self._item.catch_log_handler # type: ignore[no-any-return] # noqa: F723

def get_records(self, when):
def get_records(self, when: str) -> List[logging.LogRecord]:
"""
Get the logging records for one of the possible test phases.

Expand All @@ -346,7 +347,7 @@ def get_records(self, when):
"""
handler = self._item.catch_log_handlers.get(when)
if handler:
return handler.records
return handler.records # type: ignore[no-any-return] # noqa: F723
else:
return []

Expand Down Expand Up @@ -619,7 +620,9 @@ def _runtest_for(self, item, when):
yield

@contextmanager
def _runtest_for_main(self, item, when):
def _runtest_for_main(
self, item: nodes.Item, when: str
) -> Generator[None, None, None]:
"""Implements the internals of pytest_runtest_xxx() hook."""
with catching_logs(
LogCaptureHandler(), formatter=self.formatter, level=self.log_level
Expand All @@ -632,15 +635,15 @@ def _runtest_for_main(self, item, when):
return

if not hasattr(item, "catch_log_handlers"):
item.catch_log_handlers = {}
item.catch_log_handlers[when] = log_handler
item.catch_log_handler = log_handler
item.catch_log_handlers = {} # type: ignore[attr-defined] # noqa: F821
item.catch_log_handlers[when] = log_handler # type: ignore[attr-defined] # noqa: F821
item.catch_log_handler = log_handler # type: ignore[attr-defined] # noqa: F821
try:
yield # run test
finally:
if when == "teardown":
del item.catch_log_handler
del item.catch_log_handlers
del item.catch_log_handler # type: ignore[attr-defined] # noqa: F821
del item.catch_log_handlers # type: ignore[attr-defined] # noqa: F821

if self.print_logs:
# Add a captured log section to the report.
Expand Down
Loading