Move pathlist support to legacypath plugin
This commit is contained in:
		
							parent
							
								
									d9ca55c648
								
							
						
					
					
						commit
						ce7cff9f8e
					
				| 
						 | 
					@ -49,7 +49,6 @@ from _pytest._code import filter_traceback
 | 
				
			||||||
from _pytest._io import TerminalWriter
 | 
					from _pytest._io import TerminalWriter
 | 
				
			||||||
from _pytest.compat import final
 | 
					from _pytest.compat import final
 | 
				
			||||||
from _pytest.compat import importlib_metadata
 | 
					from _pytest.compat import importlib_metadata
 | 
				
			||||||
from _pytest.compat import legacy_path
 | 
					 | 
				
			||||||
from _pytest.outcomes import fail
 | 
					from _pytest.outcomes import fail
 | 
				
			||||||
from _pytest.outcomes import Skipped
 | 
					from _pytest.outcomes import Skipped
 | 
				
			||||||
from _pytest.pathlib import absolutepath
 | 
					from _pytest.pathlib import absolutepath
 | 
				
			||||||
| 
						 | 
					@ -1369,6 +1368,12 @@ class Config:
 | 
				
			||||||
            self._inicache[name] = val = self._getini(name)
 | 
					            self._inicache[name] = val = self._getini(name)
 | 
				
			||||||
            return val
 | 
					            return val
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Meant for easy monkeypatching by legacypath plugin.
 | 
				
			||||||
 | 
					    # Can be inlined back (with no cover removed) once legacypath is gone.
 | 
				
			||||||
 | 
					    def _getini_unknown_type(self, name: str, type: str, value: Union[str, List[str]]):
 | 
				
			||||||
 | 
					        msg = f"unknown configuration type: {type}"
 | 
				
			||||||
 | 
					        raise ValueError(msg, value)  # pragma: no cover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _getini(self, name: str):
 | 
					    def _getini(self, name: str):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            description, type, default = self._parser._inidict[name]
 | 
					            description, type, default = self._parser._inidict[name]
 | 
				
			||||||
| 
						 | 
					@ -1401,13 +1406,7 @@ class Config:
 | 
				
			||||||
        #     a_line_list = ["tests", "acceptance"]
 | 
					        #     a_line_list = ["tests", "acceptance"]
 | 
				
			||||||
        #   in this case, we already have a list ready to use.
 | 
					        #   in this case, we already have a list ready to use.
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
        if type == "pathlist":
 | 
					        if type == "paths":
 | 
				
			||||||
            # TODO: This assert is probably not valid in all cases.
 | 
					 | 
				
			||||||
            assert self.inipath is not None
 | 
					 | 
				
			||||||
            dp = self.inipath.parent
 | 
					 | 
				
			||||||
            input_values = shlex.split(value) if isinstance(value, str) else value
 | 
					 | 
				
			||||||
            return [legacy_path(str(dp / x)) for x in input_values]
 | 
					 | 
				
			||||||
        elif type == "paths":
 | 
					 | 
				
			||||||
            # TODO: This assert is probably not valid in all cases.
 | 
					            # TODO: This assert is probably not valid in all cases.
 | 
				
			||||||
            assert self.inipath is not None
 | 
					            assert self.inipath is not None
 | 
				
			||||||
            dp = self.inipath.parent
 | 
					            dp = self.inipath.parent
 | 
				
			||||||
| 
						 | 
					@ -1422,9 +1421,12 @@ class Config:
 | 
				
			||||||
                return value
 | 
					                return value
 | 
				
			||||||
        elif type == "bool":
 | 
					        elif type == "bool":
 | 
				
			||||||
            return _strtobool(str(value).strip())
 | 
					            return _strtobool(str(value).strip())
 | 
				
			||||||
        else:
 | 
					        elif type == "string":
 | 
				
			||||||
            assert type in [None, "string"]
 | 
					 | 
				
			||||||
            return value
 | 
					            return value
 | 
				
			||||||
 | 
					        elif type is None:
 | 
				
			||||||
 | 
					            return value
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return self._getini_unknown_type(name, type, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _getconftest_pathlist(
 | 
					    def _getconftest_pathlist(
 | 
				
			||||||
        self, name: str, path: Path, rootpath: Path
 | 
					        self, name: str, path: Path, rootpath: Path
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
"""Add backward compatibility support for the legacy py path type."""
 | 
					"""Add backward compatibility support for the legacy py path type."""
 | 
				
			||||||
 | 
					import shlex
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
| 
						 | 
					@ -372,6 +373,19 @@ def Session_stardir(self: pytest.Session) -> LEGACY_PATH:
 | 
				
			||||||
    return legacy_path(self.startpath)
 | 
					    return legacy_path(self.startpath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def Config__getini_unknown_type(
 | 
				
			||||||
 | 
					    self, name: str, type: str, value: Union[str, List[str]]
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    if type == "pathlist":
 | 
				
			||||||
 | 
					        # TODO: This assert is probably not valid in all cases.
 | 
				
			||||||
 | 
					        assert self.inipath is not None
 | 
				
			||||||
 | 
					        dp = self.inipath.parent
 | 
				
			||||||
 | 
					        input_values = shlex.split(value) if isinstance(value, str) else value
 | 
				
			||||||
 | 
					        return [legacy_path(str(dp / x)) for x in input_values]
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        raise ValueError(f"unknown configuration type: {type}", value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_configure(config: pytest.Config) -> None:
 | 
					def pytest_configure(config: pytest.Config) -> None:
 | 
				
			||||||
    mp = pytest.MonkeyPatch()
 | 
					    mp = pytest.MonkeyPatch()
 | 
				
			||||||
    config.add_cleanup(mp.undo)
 | 
					    config.add_cleanup(mp.undo)
 | 
				
			||||||
| 
						 | 
					@ -412,3 +426,6 @@ def pytest_configure(config: pytest.Config) -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Add Session.startdir property.
 | 
					    # Add Session.startdir property.
 | 
				
			||||||
    mp.setattr(pytest.Session, "startdir", property(Session_stardir), raising=False)
 | 
					    mp.setattr(pytest.Session, "startdir", property(Session_stardir), raising=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Add pathlist configuration type.
 | 
				
			||||||
 | 
					    mp.setattr(pytest.Config, "_getini_unknown_type", Config__getini_unknown_type)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -635,14 +635,11 @@ class TestConfigAPI:
 | 
				
			||||||
        pytest.raises(ValueError, config.getini, "other")
 | 
					        pytest.raises(ValueError, config.getini, "other")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("config_type", ["ini", "pyproject"])
 | 
					    @pytest.mark.parametrize("config_type", ["ini", "pyproject"])
 | 
				
			||||||
    @pytest.mark.parametrize("ini_type", ["paths", "pathlist"])
 | 
					    def test_addini_paths(self, pytester: Pytester, config_type: str) -> None:
 | 
				
			||||||
    def test_addini_paths(
 | 
					 | 
				
			||||||
        self, pytester: Pytester, config_type: str, ini_type: str
 | 
					 | 
				
			||||||
    ) -> None:
 | 
					 | 
				
			||||||
        pytester.makeconftest(
 | 
					        pytester.makeconftest(
 | 
				
			||||||
            f"""
 | 
					            """
 | 
				
			||||||
            def pytest_addoption(parser):
 | 
					            def pytest_addoption(parser):
 | 
				
			||||||
                parser.addini("paths", "my new ini value", type="{ini_type}")
 | 
					                parser.addini("paths", "my new ini value", type="paths")
 | 
				
			||||||
                parser.addini("abc", "abc value")
 | 
					                parser.addini("abc", "abc value")
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -1521,12 +1518,11 @@ class TestOverrideIniArgs:
 | 
				
			||||||
        assert result.ret == 0
 | 
					        assert result.ret == 0
 | 
				
			||||||
        result.stdout.fnmatch_lines(["custom_option:3.0"])
 | 
					        result.stdout.fnmatch_lines(["custom_option:3.0"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("ini_type", ["paths", "pathlist"])
 | 
					    def test_override_ini_paths(self, pytester: Pytester) -> None:
 | 
				
			||||||
    def test_override_ini_paths(self, pytester: Pytester, ini_type: str) -> None:
 | 
					 | 
				
			||||||
        pytester.makeconftest(
 | 
					        pytester.makeconftest(
 | 
				
			||||||
            f"""
 | 
					            """
 | 
				
			||||||
            def pytest_addoption(parser):
 | 
					            def pytest_addoption(parser):
 | 
				
			||||||
                parser.addini("paths", "my new ini value", type="{ini_type}")"""
 | 
					                parser.addini("paths", "my new ini value", type="paths")"""
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        pytester.makeini(
 | 
					        pytester.makeini(
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
| 
						 | 
					@ -1534,14 +1530,11 @@ class TestOverrideIniArgs:
 | 
				
			||||||
            paths=blah.py"""
 | 
					            paths=blah.py"""
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        pytester.makepyfile(
 | 
					        pytester.makepyfile(
 | 
				
			||||||
            rf"""
 | 
					            r"""
 | 
				
			||||||
            def test_overriden(pytestconfig):
 | 
					            def test_overriden(pytestconfig):
 | 
				
			||||||
                config_paths = pytestconfig.getini("paths")
 | 
					                config_paths = pytestconfig.getini("paths")
 | 
				
			||||||
                print(config_paths)
 | 
					                print(config_paths)
 | 
				
			||||||
                for cpf in config_paths:
 | 
					                for cpf in config_paths:
 | 
				
			||||||
                    if "{ini_type}" == "pathlist":
 | 
					 | 
				
			||||||
                        print('\nuser_path:%s' % cpf.basename)
 | 
					 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                    print('\nuser_path:%s' % cpf.name)
 | 
					                    print('\nuser_path:%s' % cpf.name)
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,3 +94,58 @@ class TestFixtureRequestSessionScoped:
 | 
				
			||||||
            match="path not available in session-scoped context",
 | 
					            match="path not available in session-scoped context",
 | 
				
			||||||
        ):
 | 
					        ):
 | 
				
			||||||
            session_request.fspath
 | 
					            session_request.fspath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.parametrize("config_type", ["ini", "pyproject"])
 | 
				
			||||||
 | 
					def test_addini_paths(pytester: pytest.Pytester, config_type: str) -> None:
 | 
				
			||||||
 | 
					    pytester.makeconftest(
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        def pytest_addoption(parser):
 | 
				
			||||||
 | 
					            parser.addini("paths", "my new ini value", type="pathlist")
 | 
				
			||||||
 | 
					            parser.addini("abc", "abc value")
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    if config_type == "ini":
 | 
				
			||||||
 | 
					        inipath = pytester.makeini(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					            [pytest]
 | 
				
			||||||
 | 
					            paths=hello world/sub.py
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    elif config_type == "pyproject":
 | 
				
			||||||
 | 
					        inipath = pytester.makepyprojecttoml(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					            [tool.pytest.ini_options]
 | 
				
			||||||
 | 
					            paths=["hello", "world/sub.py"]
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    config = pytester.parseconfig()
 | 
				
			||||||
 | 
					    values = config.getini("paths")
 | 
				
			||||||
 | 
					    assert len(values) == 2
 | 
				
			||||||
 | 
					    assert values[0] == inipath.parent.joinpath("hello")
 | 
				
			||||||
 | 
					    assert values[1] == inipath.parent.joinpath("world/sub.py")
 | 
				
			||||||
 | 
					    pytest.raises(ValueError, config.getini, "other")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_override_ini_paths(pytester: pytest.Pytester) -> None:
 | 
				
			||||||
 | 
					    pytester.makeconftest(
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        def pytest_addoption(parser):
 | 
				
			||||||
 | 
					            parser.addini("paths", "my new ini value", type="pathlist")"""
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    pytester.makeini(
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        [pytest]
 | 
				
			||||||
 | 
					        paths=blah.py"""
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    pytester.makepyfile(
 | 
				
			||||||
 | 
					        r"""
 | 
				
			||||||
 | 
					        def test_overriden(pytestconfig):
 | 
				
			||||||
 | 
					            config_paths = pytestconfig.getini("paths")
 | 
				
			||||||
 | 
					            print(config_paths)
 | 
				
			||||||
 | 
					            for cpf in config_paths:
 | 
				
			||||||
 | 
					                print('\nuser_path:%s' % cpf.basename)
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    result = pytester.runpytest("--override-ini", "paths=foo/bar1.py foo/bar2.py", "-s")
 | 
				
			||||||
 | 
					    result.stdout.fnmatch_lines(["user_path:bar1.py", "user_path:bar2.py"])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue