Skip to content
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

tmp_path_retention_policy crash when skipping from fixture #10502

Closed
The-Compiler opened this issue Nov 16, 2022 · 0 comments · Fixed by #10517
Closed

tmp_path_retention_policy crash when skipping from fixture #10502

The-Compiler opened this issue Nov 16, 2022 · 0 comments · Fixed by #10517
Labels
plugin: tmpdir related to the tmpdir builtin plugin status: critical grave problem or usability issue that affects lots of users type: regression indicates a problem that was introduced in a release which was working previously

Comments

@The-Compiler
Copy link
Member

With #10442, this:

import pytest


@pytest.fixture
def fixt(tmp_path):
    pytest.skip()


def test_fixt(fixt):
    pass

results in:

________________________ ERROR at teardown of test_fixt ________________________

cls = <class '_pytest.runner.CallInfo'>
func = <function call_runtest_hook.<locals>.<lambda> at 0x7f0e90dab760>
when = 'teardown'
reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)

    @classmethod
    def from_call(
        cls,
        func: "Callable[[], TResult]",
        when: "Literal['collect', 'setup', 'call', 'teardown']",
        reraise: Optional[
            Union[Type[BaseException], Tuple[Type[BaseException], ...]]
        ] = None,
    ) -> "CallInfo[TResult]":
        """Call func, wrapping the result in a CallInfo.
    
        :param func:
            The function to call. Called without arguments.
        :param when:
            The phase in which the function is called.
        :param reraise:
            Exception or exceptions that shall propagate if raised by the
            function, instead of being wrapped in the CallInfo.
        """
        excinfo = None
        start = timing.time()
        precise_start = timing.perf_counter()
        try:
>           result: Optional[TResult] = func()

src/_pytest/runner.py:342: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/_pytest/runner.py:263: in <lambda>
    lambda: ihook(item=item, **kwds), when=when, reraise=reraise
.venv/lib/python3.10/site-packages/pluggy/_hooks.py:265: in __call__
    return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
.venv/lib/python3.10/site-packages/pluggy/_manager.py:80: in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
src/_pytest/runner.py:183: in pytest_runtest_teardown
    item.session._setupstate.teardown_exact(nextitem)
src/_pytest/runner.py:538: in teardown_exact
    raise exceptions[0]
src/_pytest/runner.py:527: in teardown_exact
    fin()
src/_pytest/fixtures.py:684: in <lambda>
    subrequest.node.addfinalizer(lambda: fixturedef.finish(request=subrequest))
src/_pytest/fixtures.py:1036: in finish
    raise exc
src/_pytest/fixtures.py:1029: in finish
    func()
src/_pytest/fixtures.py:916: in _teardown_yield_fixture
    next(it)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

request = <SubRequest 'tmp_path' for <Function test_fixt>>
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x7f0e91345780>, _basetemp=PosixPath('/tmp/pytest-of-florian/pytest-29'), _retention_count=3, _retention_policy='failed')

    @fixture
    def tmp_path(
        request: FixtureRequest, tmp_path_factory: TempPathFactory
    ) -> Generator[Path, None, None]:
        """Return a temporary directory path object which is unique to each test
        function invocation, created as a sub directory of the base temporary
        directory.
    
        By default, a new base temporary directory is created each test session,
        and old bases are removed after 3 sessions, to aid in debugging. If
        ``--basetemp`` is used then it is cleared each session. See :ref:`base
        temporary directory`.
    
        The returned object is a :class:`pathlib.Path` object.
        """
    
        path = _mk_tmp(request, tmp_path_factory)
        yield path
    
        # Remove the tmpdir if the policy is "failed" and the test passed.
        tmp_path_factory: TempPathFactory = request.session.config._tmp_path_factory  # type: ignore
        policy = tmp_path_factory._retention_policy
>       if policy == "failed" and request.node._tmp_path_result_call.passed:
E       AttributeError: 'Function' object has no attribute '_tmp_path_result_call'. Did you mean: '_tmp_path_result_setup'?

src/_pytest/tmpdir.py:276: AttributeError

cc @yusuke-kadowaki

@The-Compiler The-Compiler added status: critical grave problem or usability issue that affects lots of users type: regression indicates a problem that was introduced in a release which was working previously plugin: tmpdir related to the tmpdir builtin plugin labels Nov 16, 2022
nicoddemus pushed a commit that referenced this issue Nov 23, 2022
)

Also uses the stash to save the test status.

Fix #10502
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: tmpdir related to the tmpdir builtin plugin status: critical grave problem or usability issue that affects lots of users type: regression indicates a problem that was introduced in a release which was working previously
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant