aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py3/_pytest/config/findpaths.py
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/python/pytest/py3/_pytest/config/findpaths.py
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/config/findpaths.py')
-rw-r--r--contrib/python/pytest/py3/_pytest/config/findpaths.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/contrib/python/pytest/py3/_pytest/config/findpaths.py b/contrib/python/pytest/py3/_pytest/config/findpaths.py
new file mode 100644
index 0000000000..fb84160c1f
--- /dev/null
+++ b/contrib/python/pytest/py3/_pytest/config/findpaths.py
@@ -0,0 +1,167 @@
+import os
+from typing import Any
+from typing import Iterable
+from typing import List
+from typing import Optional
+from typing import Tuple
+
+import py
+
+from .exceptions import UsageError
+from _pytest.compat import TYPE_CHECKING
+from _pytest.outcomes import fail
+
+if TYPE_CHECKING:
+ from . import Config # noqa: F401
+
+
+def exists(path, ignore=EnvironmentError):
+ try:
+ return path.check()
+ except ignore:
+ return False
+
+
+def getcfg(args, config=None):
+ """
+ Search the list of arguments for a valid ini-file for pytest,
+ and return a tuple of (rootdir, inifile, cfg-dict).
+
+ note: config is optional and used only to issue warnings explicitly (#2891).
+ """
+ inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
+ args = [x for x in args if not str(x).startswith("-")]
+ if not args:
+ args = [py.path.local()]
+ for arg in args:
+ arg = py.path.local(arg)
+ for base in arg.parts(reverse=True):
+ for inibasename in inibasenames:
+ p = base.join(inibasename)
+ if exists(p):
+ try:
+ iniconfig = py.iniconfig.IniConfig(p)
+ except py.iniconfig.ParseError as exc:
+ raise UsageError(str(exc))
+
+ if (
+ inibasename == "setup.cfg"
+ and "tool:pytest" in iniconfig.sections
+ ):
+ return base, p, iniconfig["tool:pytest"]
+ elif "pytest" in iniconfig.sections:
+ if inibasename == "setup.cfg" and config is not None:
+
+ fail(
+ CFG_PYTEST_SECTION.format(filename=inibasename),
+ pytrace=False,
+ )
+ return base, p, iniconfig["pytest"]
+ elif inibasename == "pytest.ini":
+ # allowed to be empty
+ return base, p, {}
+ return None, None, None
+
+
+def get_common_ancestor(paths: Iterable[py.path.local]) -> py.path.local:
+ common_ancestor = None
+ for path in paths:
+ if not path.exists():
+ continue
+ if common_ancestor is None:
+ common_ancestor = path
+ else:
+ if path.relto(common_ancestor) or path == common_ancestor:
+ continue
+ elif common_ancestor.relto(path):
+ common_ancestor = path
+ else:
+ shared = path.common(common_ancestor)
+ if shared is not None:
+ common_ancestor = shared
+ if common_ancestor is None:
+ common_ancestor = py.path.local()
+ elif common_ancestor.isfile():
+ common_ancestor = common_ancestor.dirpath()
+ return common_ancestor
+
+
+def get_dirs_from_args(args):
+ def is_option(x):
+ return str(x).startswith("-")
+
+ def get_file_part_from_node_id(x):
+ return str(x).split("::")[0]
+
+ def get_dir_from_path(path):
+ if path.isdir():
+ return path
+ return py.path.local(path.dirname)
+
+ # These look like paths but may not exist
+ possible_paths = (
+ py.path.local(get_file_part_from_node_id(arg))
+ for arg in args
+ if not is_option(arg)
+ )
+
+ return [get_dir_from_path(path) for path in possible_paths if path.exists()]
+
+
+CFG_PYTEST_SECTION = "[pytest] section in {filename} files is no longer supported, change to [tool:pytest] instead."
+
+
+def determine_setup(
+ inifile: Optional[str],
+ args: List[str],
+ rootdir_cmd_arg: Optional[str] = None,
+ config: Optional["Config"] = None,
+) -> Tuple[py.path.local, Optional[str], Any]:
+ dirs = get_dirs_from_args(args)
+ if inifile:
+ iniconfig = py.iniconfig.IniConfig(inifile)
+ is_cfg_file = str(inifile).endswith(".cfg")
+ sections = ["tool:pytest", "pytest"] if is_cfg_file else ["pytest"]
+ for section in sections:
+ try:
+ inicfg = iniconfig[
+ section
+ ] # type: Optional[py.iniconfig._SectionWrapper]
+ if is_cfg_file and section == "pytest" and config is not None:
+ fail(
+ CFG_PYTEST_SECTION.format(filename=str(inifile)), pytrace=False
+ )
+ break
+ except KeyError:
+ inicfg = None
+ if rootdir_cmd_arg is None:
+ rootdir = get_common_ancestor(dirs)
+ else:
+ ancestor = get_common_ancestor(dirs)
+ rootdir, inifile, inicfg = getcfg([ancestor], config=config)
+ if rootdir is None and rootdir_cmd_arg is None:
+ for possible_rootdir in ancestor.parts(reverse=True):
+ if possible_rootdir.join("setup.py").exists():
+ rootdir = possible_rootdir
+ break
+ else:
+ if dirs != [ancestor]:
+ rootdir, inifile, inicfg = getcfg(dirs, config=config)
+ if rootdir is None:
+ if config is not None:
+ cwd = config.invocation_dir
+ else:
+ cwd = py.path.local()
+ rootdir = get_common_ancestor([cwd, ancestor])
+ is_fs_root = os.path.splitdrive(str(rootdir))[1] == "/"
+ if is_fs_root:
+ rootdir = ancestor
+ if rootdir_cmd_arg:
+ rootdir = py.path.local(os.path.expandvars(rootdir_cmd_arg))
+ if not rootdir.isdir():
+ raise UsageError(
+ "Directory '{}' not found. Check your '--rootdir' option.".format(
+ rootdir
+ )
+ )
+ return rootdir, inifile, inicfg or {}