Exemplo n.º 1
0
    def set_log_path(self, fname: str) -> None:
        """Set the filename parameter for Logging.FileHandler().

        Creates parent directory if it does not exist.

        .. warning::
            This is an experimental API.
        """
        fpath = Path(fname)

        if not fpath.is_absolute():
            fpath = self._config.rootpath / fpath

        if not fpath.parent.exists():
            fpath.parent.mkdir(exist_ok=True, parents=True)

        stream = fpath.open(mode="w", encoding="UTF-8")
        if sys.version_info >= (3, 7):
            old_stream = self.log_file_handler.setStream(stream)
        else:
            old_stream = self.log_file_handler.stream
            self.log_file_handler.acquire()
            try:
                self.log_file_handler.flush()
                self.log_file_handler.stream = stream
            finally:
                self.log_file_handler.release()
        if old_stream:
            old_stream.close()
Exemplo n.º 2
0
def validate_basetemp(path: str) -> str:
    # GH 7119
    msg = "basetemp must not be empty, the current working directory or any parent directory of it"

    # empty path
    if not path:
        raise argparse.ArgumentTypeError(msg)

    def is_ancestor(base: Path, query: Path) -> bool:
        """ return True if query is an ancestor of base, else False."""
        if base == query:
            return True
        for parent in base.parents:
            if parent == query:
                return True
        return False

    # check if path is an ancestor of cwd
    if is_ancestor(Path.cwd(), Path(path).absolute()):
        raise argparse.ArgumentTypeError(msg)

    # check symlinks for ancestors
    if is_ancestor(Path.cwd().resolve(), Path(path).resolve()):
        raise argparse.ArgumentTypeError(msg)

    return path
Exemplo n.º 3
0
    def test_get_cache_dir(self, monkeypatch, prefix, source, expected):
        if prefix:
            if sys.version_info < (3, 8):
                pytest.skip("pycache_prefix not available in py<38")
            monkeypatch.setattr(sys, "pycache_prefix", prefix)

        assert get_cache_dir(Path(source)) == Path(expected)
Exemplo n.º 4
0
def test_commonpath() -> None:
    path = Path("/foo/bar/baz/path")
    subpath = path / "sampledir"
    assert commonpath(path, subpath) == path
    assert commonpath(subpath, path) == path
    assert commonpath(Path(str(path) + "suffix"), path) == path.parent
    assert commonpath(path, path.parent.parent) == path.parent.parent
Exemplo n.º 5
0
def attempt_symlink_to(path, to_path):
    """Try to make a symlink from "path" to "to_path", skipping in case this platform
    does not support it or we don't have sufficient privileges (common on Windows)."""
    try:
        Path(path).symlink_to(Path(to_path))
    except OSError:
        pytest.skip("could not create symbolic link")
Exemplo n.º 6
0
def test_invocation_args(testdir):
    """Ensure that Config.invocation_* arguments are correctly defined"""
    class DummyPlugin:
        pass

    p = testdir.makepyfile("def test(): pass")
    plugin = DummyPlugin()
    rec = testdir.inline_run(p, "-v", plugins=[plugin])
    calls = rec.getcalls("pytest_runtest_protocol")
    assert len(calls) == 1
    call = calls[0]
    config = call.item.config

    assert config.invocation_params.args == (p, "-v")
    assert config.invocation_params.dir == Path(str(testdir.tmpdir))

    plugins = config.invocation_params.plugins
    assert len(plugins) == 2
    assert plugins[0] is plugin
    assert type(
        plugins[1]).__name__ == "Collect"  # installed by testdir.inline_run()

    # args cannot be None
    with pytest.raises(TypeError):
        Config.InvocationParams(args=None, plugins=None, dir=Path())
Exemplo n.º 7
0
def test_bestrelpath() -> None:
    curdir = Path("/foo/bar/baz/path")
    assert bestrelpath(curdir, curdir) == "."
    assert bestrelpath(curdir, curdir / "hello" /
                       "world") == "hello" + os.sep + "world"
    assert bestrelpath(curdir,
                       curdir.parent / "sister") == ".." + os.sep + "sister"
    assert bestrelpath(curdir, curdir.parent) == ".."
    assert bestrelpath(curdir, Path("hello")) == "hello"
Exemplo n.º 8
0
def attempt_symlink_to(path, to_path):
    """Try to make a symlink from "path" to "to_path", skipping in case this platform
    does not support it or we don't have sufficient privileges (common on Windows)."""
    if sys.platform.startswith("win") and six.PY2:
        pytest.skip("pathlib for some reason cannot make symlinks on Python 2")
    try:
        Path(path).symlink_to(Path(to_path))
    except OSError:
        pytest.skip("could not create symbolic link")
Exemplo n.º 9
0
    def _repr_failure_py(
        self,
        excinfo: ExceptionInfo[BaseException],
        style=None,
    ) -> Union[str, ReprExceptionInfo, ExceptionChainRepr,
               FixtureLookupErrorRepr]:
        if isinstance(excinfo.value, ConftestImportFailure):
            excinfo = ExceptionInfo(excinfo.value.excinfo)
        if isinstance(excinfo.value, fail.Exception):
            if not excinfo.value.pytrace:
                return str(excinfo.value)
        if isinstance(excinfo.value, FixtureLookupError):
            return excinfo.value.formatrepr()
        if self.config.getoption("fulltrace", False):
            style = "long"
        else:
            tb = _pytest._code.Traceback([excinfo.traceback[-1]])
            self._prunetraceback(excinfo)
            if len(excinfo.traceback) == 0:
                excinfo.traceback = tb
            if style == "auto":
                style = "long"
        # XXX should excinfo.getrepr record all data and toterminal() process it?
        if style is None:
            if self.config.getoption("tbstyle", "auto") == "short":
                style = "short"
            else:
                style = "long"

        if self.config.getoption("verbose", 0) > 1:
            truncate_locals = False
        else:
            truncate_locals = True

        # excinfo.getrepr() formats paths relative to the CWD if `abspath` is False.
        # It is possible for a fixture/test to change the CWD while this code runs, which
        # would then result in the user seeing confusing paths in the failure message.
        # To fix this, if the CWD changed, always display the full absolute path.
        # It will be better to just always display paths relative to invocation_dir, but
        # this requires a lot of plumbing (#6428).
        try:
            abspath = Path(os.getcwd()) != Path(self.config.invocation_dir)
        except OSError:
            abspath = True

        return excinfo.getrepr(
            funcargs=True,
            abspath=abspath,
            showlocals=self.config.getoption("showlocals", False),
            style=style,
            tbfilter=False,  # pruned already, or in --fulltrace mode.
            truncate_locals=truncate_locals,
        )
Exemplo n.º 10
0
def get_cache_dir(file_path: Path) -> Path:
    """Return the cache directory to write .pyc files for the given .py file path."""
    if sys.version_info >= (3, 8) and sys.pycache_prefix:
        # given:
        #   prefix = '/tmp/pycs'
        #   path = '/home/user/proj/test_app.py'
        # we want:
        #   '/tmp/pycs/home/user/proj'
        return Path(sys.pycache_prefix) / Path(*file_path.parts[1:-1])
    else:
        # classic pycache directory
        return file_path.parent / "__pycache__"
Exemplo n.º 11
0
def get_cache_dir(file_path: Path) -> Path:
    """Returns the cache directory to write .pyc files for the given .py file path"""
    # Type ignored until added in next mypy release.
    if sys.version_info >= (3, 8) and sys.pycache_prefix:  # type: ignore
        # given:
        #   prefix = '/tmp/pycs'
        #   path = '/home/user/proj/test_app.py'
        # we want:
        #   '/tmp/pycs/home/user/proj'
        return Path(sys.pycache_prefix) / Path(
            *file_path.parts[1:-1])  # type: ignore
    else:
        # classic pycache directory
        return file_path.parent / "__pycache__"
Exemplo n.º 12
0
def getlocation(function, curdir: Optional[str] = None) -> str:
    from _pytest.pathlib import Path

    function = get_real_func(function)
    fn = Path(inspect.getfile(function))
    lineno = function.__code__.co_firstlineno
    if curdir is not None:
        try:
            relfn = fn.relative_to(curdir)
        except ValueError:
            pass
        else:
            return "%s:%d" % (relfn, lineno + 1)
    return "%s:%d" % (fn, lineno + 1)
Exemplo n.º 13
0
    def _setup_tree(self, testdir):  # for issue616
        # example mostly taken from:
        # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
        runner = testdir.mkdir("empty")
        package = testdir.mkdir("package")

        package.join("conftest.py").write(
            textwrap.dedent("""\
                import pytest
                @pytest.fixture
                def fxtr():
                    return "from-package"
                """))
        package.join("test_pkgroot.py").write(
            textwrap.dedent("""\
                def test_pkgroot(fxtr):
                    assert fxtr == "from-package"
                """))

        swc = package.mkdir("swc")
        swc.join("__init__.py").ensure()
        swc.join("conftest.py").write(
            textwrap.dedent("""\
                import pytest
                @pytest.fixture
                def fxtr():
                    return "from-swc"
                """))
        swc.join("test_with_conftest.py").write(
            textwrap.dedent("""\
                def test_with_conftest(fxtr):
                    assert fxtr == "from-swc"
                """))

        snc = package.mkdir("snc")
        snc.join("__init__.py").ensure()
        snc.join("test_no_conftest.py").write(
            textwrap.dedent("""\
                def test_no_conftest(fxtr):
                    assert fxtr == "from-package"   # No local conftest.py, so should
                                                    # use value from parent dir's
                """))
        print("created directory structure:")
        tmppath = Path(str(testdir.tmpdir))
        for x in tmppath.rglob(""):
            print("   " + str(x.relative_to(tmppath)))

        return {"runner": runner, "package": package, "swc": swc, "snc": snc}
Exemplo n.º 14
0
    def __init__(self, pluginmanager, *, invocation_params=None) -> None:
        from .argparsing import Parser, FILE_OR_DIR

        if invocation_params is None:
            invocation_params = self.InvocationParams(args=(),
                                                      plugins=None,
                                                      dir=Path().resolve())

        self.option = argparse.Namespace()
        self.invocation_params = invocation_params

        _a = FILE_OR_DIR
        self._parser = Parser(
            usage="%(prog)s [options] [{}] [{}] [...]".format(_a, _a),
            processopt=self._processopt,
        )
        self.pluginmanager = pluginmanager
        self.trace = self.pluginmanager.trace.root.get("config")
        self.hook = self.pluginmanager.hook
        self._inicache = {}  # type: Dict[str, Any]
        self._override_ini = ()  # type: Sequence[str]
        self._opt2dest = {}  # type: Dict[str, str]
        self._cleanup = []  # type: List[Callable[[], None]]
        # A place where plugins can store information on the config for their
        # own use. Currently only intended for internal plugins.
        self._store = Store()
        self.pluginmanager.register(self, "pytestconfig")
        self._configured = False
        self.hook.pytest_addoption.call_historic(
            kwargs=dict(parser=self._parser, pluginmanager=self.pluginmanager))

        if TYPE_CHECKING:
            from _pytest.cacheprovider import Cache

            self.cache = None  # type: Optional[Cache]
Exemplo n.º 15
0
    def pytest_collection_modifyitems(self, session, config, items):
        if not self.active:
            return

        (files_changed, _, contexts) = self.who_tested_what()

        selected_items = [
            item for item in items if item.nodeid in contexts or any(
                Path(item.nodeid.partition("::")[0]) == changed_file
                for changed_file in files_changed)
        ]
        selected_set = set(selected_items)
        skipped_items = [item for item in items if item not in selected_set]

        items[:] = selected_items
        config.hook.pytest_deselected(items=skipped_items)

        noun = "tests" if len(selected_items) else "test"
        self._report_status = "{} {} cover the changed lines ({} deselected)".format(
            len(selected_items), noun, len(skipped_items))

        if self._skipped_files > 0:
            files_noun = "file" if self._skipped_files == 1 else "files"
            self._report_status += " (skipped {files} {files_noun})".format(
                files=self._skipped_files, files_noun=files_noun)
Exemplo n.º 16
0
    def __init__(self, pluginmanager, invocation_params=None, *args):
        from .argparsing import Parser, FILE_OR_DIR

        if invocation_params is None:
            invocation_params = self.InvocationParams(
                args=(), plugins=None, dir=Path().resolve()
            )

        #: access to command line option as attributes.
        #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
        self.option = argparse.Namespace()

        self.invocation_params = invocation_params

        _a = FILE_OR_DIR
        self._parser = Parser(
            usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
            processopt=self._processopt,
        )
        #: a pluginmanager instance
        self.pluginmanager = pluginmanager
        self.trace = self.pluginmanager.trace.root.get("config")
        self.hook = self.pluginmanager.hook
        self._inicache = {}
        self._override_ini = ()
        self._opt2dest = {}
        self._cleanup = []
        self.pluginmanager.register(self, "pytestconfig")
        self._configured = False
        self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
Exemplo n.º 17
0
def _folded_skips(
    startpath: Path, skipped: Sequence[CollectReport]
) -> List[Tuple[int, str, Optional[int], str]]:
    d = {}  # type: Dict[Tuple[str, Optional[int], str], List[CollectReport]]
    for event in skipped:
        assert event.longrepr is not None
        assert isinstance(event.longrepr, tuple), (event, event.longrepr)
        assert len(event.longrepr) == 3, (event, event.longrepr)
        fspath, lineno, reason = event.longrepr
        # For consistency, report all fspaths in relative form.
        fspath = bestrelpath(startpath, Path(fspath))
        keywords = getattr(event, "keywords", {})
        # Folding reports with global pytestmark variable.
        # This is a workaround, because for now we cannot identify the scope of a skip marker
        # TODO: Revisit after marks scope would be fixed.
        if (
            event.when == "setup"
            and "skip" in keywords
            and "pytestmark" not in keywords
        ):
            key = (fspath, None, reason)  # type: Tuple[str, Optional[int], str]
        else:
            key = (fspath, lineno, reason)
        d.setdefault(key, []).append(event)
    values = []  # type: List[Tuple[int, str, Optional[int], str]]
    for key, events in d.items():
        values.append((len(events), *key))
    return values
Exemplo n.º 18
0
    def _importconftest(self, conftestpath):
        # Use a resolved Path object as key to avoid loading the same conftest twice
        # with build systems that create build directories containing
        # symlinks to actual files.
        # Using Path().resolve() is better than py.path.realpath because
        # it resolves to the correct path/drive in case-insensitive file systems (#5792)
        key = Path(str(conftestpath)).resolve()
        try:
            return self._conftestpath2mod[key]
        except KeyError:
            pkgpath = conftestpath.pypkgpath()
            if pkgpath is None:
                _ensure_removed_sysmodule(conftestpath.purebasename)
            try:
                mod = conftestpath.pyimport()
                if (hasattr(mod, "pytest_plugins") and self._configured
                        and not self._using_pyargs):
                    _fail_on_non_top_pytest_plugins(conftestpath,
                                                    self._confcutdir)
            except Exception:
                raise ConftestImportFailure(conftestpath, sys.exc_info())

            self._conftest_plugins.add(mod)
            self._conftestpath2mod[key] = mod
            dirpath = conftestpath.dirpath()
            if dirpath in self._dirpath2confmods:
                for path, mods in self._dirpath2confmods.items():
                    if path and path.relto(dirpath) or path == dirpath:
                        assert mod not in mods
                        mods.append(mod)
            self.trace("loaded conftestmodule %r" % (mod))
            self.consider_conftest(mod)
            return mod
Exemplo n.º 19
0
    def __init__(self, pluginmanager, *, invocation_params=None) -> None:
        from .argparsing import Parser, FILE_OR_DIR

        if invocation_params is None:
            invocation_params = self.InvocationParams(args=(),
                                                      plugins=None,
                                                      dir=Path().resolve())

        self.option = argparse.Namespace()
        self.invocation_params = invocation_params

        _a = FILE_OR_DIR
        self._parser = Parser(
            usage="%(prog)s [options] [{}] [{}] [...]".format(_a, _a),
            processopt=self._processopt,
        )
        self.pluginmanager = pluginmanager
        self.trace = self.pluginmanager.trace.root.get("config")
        self.hook = self.pluginmanager.hook
        self._inicache = {}  # type: Dict[str, Any]
        self._override_ini = ()  # type: Sequence[str]
        self._opt2dest = {}  # type: Dict[str, str]
        self._cleanup = []  # type: List[Callable[[], None]]
        self.pluginmanager.register(self, "pytestconfig")
        self._configured = False
        self.hook.pytest_addoption.call_historic(
            kwargs=dict(parser=self._parser, pluginmanager=self.pluginmanager))
Exemplo n.º 20
0
def filter_traceback(entry: TracebackEntry) -> bool:
    """Return True if a TracebackEntry instance should be included in tracebacks.

    We hide traceback entries of:

    * dynamically generated code (no code to show up for it);
    * internal traceback from pytest or its internal libraries, py and pluggy.
    """
    # entry.path might sometimes return a str object when the entry
    # points to dynamically generated code.
    # See https://bitbucket.org/pytest-dev/py/issues/71.
    raw_filename = entry.frame.code.raw.co_filename
    is_generated = "<" in raw_filename and ">" in raw_filename
    if is_generated:
        return False

    # entry.path might point to a non-existing file, in which case it will
    # also return a str object. See #1133.
    p = Path(entry.path)

    parents = p.parents
    if _PLUGGY_DIR in parents:
        return False
    if _PYTEST_DIR in parents:
        return False
    if _PY_DIR in parents:
        return False

    return True
Exemplo n.º 21
0
    def _importconftest(self, conftestpath):
        # Use a resolved Path object as key to avoid loading the same conftest twice
        # with build systems that create build directories containing
        # symlinks to actual files.
        # Using Path().resolve() is better than py.path.realpath because
        # it resolves to the correct path/drive in case-insensitive file systems (#5792)
        key = Path(str(conftestpath)).resolve()

        with contextlib.suppress(KeyError):
            return self._conftestpath2mod[key]

        pkgpath = conftestpath.pypkgpath()
        if pkgpath is None:
            _ensure_removed_sysmodule(conftestpath.purebasename)

        try:
            mod = conftestpath.pyimport()
        except Exception as e:
            raise ConftestImportFailure(conftestpath, sys.exc_info()) from e

        self._check_non_top_pytest_plugins(mod, conftestpath)

        self._conftest_plugins.add(mod)
        self._conftestpath2mod[key] = mod
        dirpath = conftestpath.dirpath()
        if dirpath in self._dirpath2confmods:
            for path, mods in self._dirpath2confmods.items():
                if path and path.relto(dirpath) or path == dirpath:
                    assert mod not in mods
                    mods.append(mod)
        self.trace("loading conftestmodule {!r}".format(mod))
        self.consider_conftest(mod)
        return mod
Exemplo n.º 22
0
 def safe_exists(path: Path) -> bool:
     # This can throw on paths that contain characters unrepresentable at the OS level,
     # or with invalid syntax on Windows (https://bugs.python.org/issue35306)
     try:
         return path.exists()
     except OSError:
         return False
Exemplo n.º 23
0
def resolve_collection_argument(
        invocation_dir: py.path.local,
        arg: str,
        *,
        as_pypath: bool = False) -> Tuple[py.path.local, List[str]]:
    """Parse path arguments optionally containing selection parts and return (fspath, names).

    Command-line arguments can point to files and/or directories, and optionally contain
    parts for specific tests selection, for example:

        "pkg/tests/test_foo.py::TestClass::test_foo"

    This function ensures the path exists, and returns a tuple:

        (py.path.path("/full/path/to/pkg/tests/test_foo.py"), ["TestClass", "test_foo"])

    When as_pypath is True, expects that the command-line argument actually contains
    module paths instead of file-system paths:

        "pkg.tests.test_foo::TestClass::test_foo"

    In which case we search sys.path for a matching module, and then return the *path* to the
    found module.

    If the path doesn't exist, raise UsageError.
    If the path is a directory and selection parts are present, raise UsageError.
    """
    strpath, *parts = str(arg).split("::")
    if as_pypath:
        strpath = search_pypath(strpath)
    fspath = Path(str(invocation_dir), strpath)
    fspath = absolutepath(fspath)
    if not fspath.exists():
        msg = ("module or package not found: {arg} (missing __init__.py?)"
               if as_pypath else "file or directory not found: {arg}")
        raise UsageError(msg.format(arg=arg))
    if parts and fspath.is_dir():
        msg = ("package argument cannot contain :: selection parts: {arg}"
               if as_pypath else
               "directory argument cannot contain :: selection parts: {arg}")
        raise UsageError(msg.format(arg=arg))
    return py.path.local(str(fspath)), parts
Exemplo n.º 24
0
    def set_log_path(self, fname):
        """Public method, which can set filename parameter for
        Logging.FileHandler(). Also creates parent directory if
        it does not exist.

        .. warning::
            Please considered as an experimental API.
        """
        fname = Path(fname)

        if not fname.is_absolute():
            fname = Path(self._config.rootdir, fname)

        if not fname.parent.exists():
            fname.parent.mkdir(exist_ok=True, parents=True)

        self.log_file_handler = logging.FileHandler(
            str(fname), mode="w", encoding="UTF-8"
        )
        self.log_file_handler.setFormatter(self.log_file_formatter)
Exemplo n.º 25
0
 def __init__(self, config):
     self._config = config
     log_path = Path(config.option.xlog)
     self._log_path = log_path
     log_path.parent.mkdir(parents=True, exist_ok=True)
     self._file = log_path.open("w", buffering=1, encoding="UTF-8")
     self._always_report = {}
     for item in config.option.xopt:
         if '=' in item:
             keytree = item.split('=')[0]
             key = keytree
             cur = self._always_report
             for key in keytree.split('.'):
                 if not cur.get(key):
                     cur[key] = {}
                 if key != keytree.split('.')[-1]:
                     cur = cur[key]
             cur[key] = item.split('=')[1]
     self._always_report['session_id'] = int(time())
     self._results = {}
Exemplo n.º 26
0
    def set_log_path(self, fname):
        """Public method, which can set filename parameter for
        Logging.FileHandler(). Also creates parent directory if
        it does not exist.

        .. warning::
            Please considered as an experimental API.
        """
        fname = Path(fname)

        if not fname.is_absolute():
            fname = Path(self._config.rootdir, fname)

        if not fname.parent.exists():
            fname.parent.mkdir(exist_ok=True, parents=True)

        self.log_file_handler = logging.FileHandler(str(fname),
                                                    mode="w",
                                                    encoding="UTF-8")
        self.log_file_handler.setFormatter(self.log_file_formatter)
Exemplo n.º 27
0
def test_setinitial_conftest_subdirs(testdir, name):
    sub = testdir.mkdir(name)
    subconftest = sub.ensure("conftest.py")
    conftest = PytestPluginManager()
    conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
    key = Path(str(subconftest)).resolve()
    if name not in ("whatever", ".dotdir"):
        assert key in conftest._conftestpath2mod
        assert len(conftest._conftestpath2mod) == 1
    else:
        assert key not in conftest._conftestpath2mod
        assert len(conftest._conftestpath2mod) == 0
Exemplo n.º 28
0
    def test_read_pyc(self, tmp_path: Path) -> None:
        """
        Ensure that the `_read_pyc` can properly deal with corrupted pyc files.
        In those circumstances it should just give up instead of generating
        an exception that is propagated to the caller.
        """
        import py_compile
        from _pytest.assertion.rewrite import _read_pyc

        source = tmp_path / "source.py"
        pyc = Path(str(source) + "c")

        source.write_text("def test(): pass")
        py_compile.compile(str(source), str(pyc))

        contents = pyc.read_bytes()
        strip_bytes = 20  # header is around 8 bytes, strip a little more
        assert len(contents) > strip_bytes
        pyc.write_bytes(contents[:strip_bytes])

        assert _read_pyc(source, pyc) is None  # no error
Exemplo n.º 29
0
 def pytest_ignore_collect(self, path):
     """
     Ignore this file path if we are in --wtw mode and it is not in the list of
     files to test.
     """
     if self.active and self.config.getoption("wtw") and path.isfile():
         (files_changed, context_files, _) = self.who_tested_what()
         if Path(path) not in (files_changed | context_files):
             self._skipped_files += 1
             return True
         else:
             return False
Exemplo n.º 30
0
    def test_sys_pycache_prefix_integration(self, tmp_path, monkeypatch,
                                            testdir):
        """Integration test for sys.pycache_prefix (#4730)."""
        pycache_prefix = tmp_path / "my/pycs"
        monkeypatch.setattr(sys, "pycache_prefix", str(pycache_prefix))
        monkeypatch.setattr(sys, "dont_write_bytecode", False)

        testdir.makepyfile(
            **{
                "src/test_foo.py": """
                import bar
                def test_foo():
                    pass
            """,
                "src/bar/__init__.py": "",
            })
        result = testdir.runpytest()
        assert result.ret == 0

        test_foo = Path(testdir.tmpdir) / "src/test_foo.py"
        bar_init = Path(testdir.tmpdir) / "src/bar/__init__.py"
        assert test_foo.is_file()
        assert bar_init.is_file()

        # test file: rewritten, custom pytest cache tag
        test_foo_pyc = get_cache_dir(test_foo) / ("test_foo" + PYC_TAIL)
        assert test_foo_pyc.is_file()

        # normal file: not touched by pytest, normal cache tag
        bar_init_pyc = get_cache_dir(
            bar_init) / "__init__.{cache_tag}.pyc".format(
                cache_tag=sys.implementation.cache_tag)
        assert bar_init_pyc.is_file()
Exemplo n.º 31
0
    def set_log_path(self, fname):
        """Public method, which can set filename parameter for
        Logging.FileHandler(). Also creates parent directory if
        it does not exist.

        .. warning::
            Please considered as an experimental API.
        """
        fname = Path(fname)

        if not fname.is_absolute():
            fname = Path(self._config.rootdir, fname)

        if not fname.parent.exists():
            fname.parent.mkdir(exist_ok=True, parents=True)

        stream = fname.open(mode="w", encoding="UTF-8")
        if sys.version_info >= (3, 7):
            old_stream = self.log_file_handler.setStream(stream)
        else:
            old_stream = self.log_file_handler.stream
            self.log_file_handler.acquire()
            try:
                self.log_file_handler.flush()
                self.log_file_handler.stream = stream
            finally:
                self.log_file_handler.release()
        if old_stream:
            old_stream.close()