diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/python/pytest/py3/_pytest/config/findpaths.py | |
download | ydb-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.py | 167 |
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 {} |