Example #1
0
def test_import_another_sitecustomize(project, invoke, capfd):
    project.meta["requires-python"] = ">=2.7"
    project.write_pyproject()
    # a script for checking another sitecustomize is imported
    project.root.joinpath("foo.py").write_text(
        textwrap.dedent("""
            import sys
            module = sys.modules.get('another_sitecustomize')
            if module:
                print(module.__file__)
            """))
    # ensure there have at least one sitecustomize can be imported
    # there may have more than one sitecustomize.py in sys.path
    project.root.joinpath("sitecustomize.py").write_text("# do nothing")
    env = os.environ.copy()
    paths = [str(project.root)]
    original_paths = env.get("PYTHONPATH", "")
    if original_paths:
        paths.insert(0, original_paths)
    env["PYTHONPATH"] = os.pathsep.join(paths)
    # invoke pdm commands
    invoke = functools.partial(invoke, env=env, obj=project)
    project._environment = None
    capfd.readouterr()
    with cd(project.root):
        invoke(["run", "python", "foo.py"])
    # only the first and second sitecustomize module will be imported
    # as sitecustomize and another_sitecustomize
    # the first one is pdm.pep582.sitecustomize for sure
    # the second one maybe not the dummy module injected here
    out, _ = capfd.readouterr()
    assert out.strip()
Example #2
0
def test_convert_poetry(project):
    golden_file = FIXTURES / "pyproject-poetry.toml"
    assert poetry.check_fingerprint(project, golden_file)
    with cd(FIXTURES):
        result, settings = poetry.convert(
            project, golden_file, Namespace(dev=False, group=None)
        )

    assert result["authors"][0] == {
        "name": "Sébastien Eustace",
        "email": "*****@*****.**",
    }
    assert result["name"] == "poetry"
    assert result["version"] == "1.0.0"
    assert result["license-expression"] == "MIT"
    assert "repository" in result["urls"]
    assert result["requires-python"] == ">=2.7,<4.0,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
    assert 'cleo<1.0.0,>=0.7.6; python_version ~= "2.7"' in result["dependencies"]
    assert (
        'cachecontrol[filecache]<1.0.0,>=0.12.4; python_version >= "3.4" '
        'and python_version < "4.0"' in result["dependencies"]
    )
    assert "babel==2.9.0" in result["dependencies"]
    assert "mysql" in result["optional-dependencies"]
    assert "psycopg2<3.0,>=2.7" in result["optional-dependencies"]["pgsql"]
    assert len(settings["dev-dependencies"]["dev"]) == 2

    assert result["scripts"] == {"poetry": "poetry.console:run"}
    assert result["entry-points"]["blogtool.parsers"] == {
        ".rst": "some_module:SomeClass"
    }
    assert settings["includes"] == ["lib/my_package", "tests", "CHANGELOG.md"]
    assert settings["excludes"] == ["my_package/excluded.py"]
Example #3
0
File: poetry.py Project: ulwlu/pdm
def convert(project, filename, options):
    with open(filename, encoding="utf-8") as fp, cd(
            os.path.dirname(os.path.abspath(filename))):
        converter = PoetryMetaConverter(
            toml.load(fp)["tool"]["poetry"],
            project.core.ui if project else None)
        return converter.convert()
Example #4
0
 def get_dependencies(self,
                      section: Optional[str] = None
                      ) -> Dict[str, Requirement]:
     metadata = self.meta
     optional_dependencies = metadata.get("optional-dependencies", {})
     dev_dependencies = self.tool_settings.get("dev-dependencies", {})
     if section in (None, "default"):
         deps = metadata.get("dependencies", [])
     else:
         if section in optional_dependencies and section in dev_dependencies:
             self.core.ui.echo(
                 f"The {section} section exists in both [optional-dependencies] "
                 "and [dev-dependencies], the former is taken.",
                 err=True,
                 fg="yellow",
             )
         if section in optional_dependencies:
             deps = optional_dependencies[section]
         elif section in dev_dependencies:
             deps = dev_dependencies[section]
         else:
             raise PdmUsageError(f"Non-exist section {section}")
     result = {}
     with cd(self.root):
         for line in deps:
             if line.startswith("-e "):
                 req = parse_requirement(line[3:].strip(), True)
             else:
                 req = parse_requirement(line)
             # make editable packages behind normal ones to override correctly.
             result[req.identify()] = req
     return result
Example #5
0
def test_run_expand_env_vars(project, invoke, capfd):
    (project.root /
     "test_script.py").write_text("import os; print(os.getenv('FOO'))")
    project.tool_settings["scripts"] = {
        "test_cmd": 'python -c "foo, bar = 0, 1;print($FOO)"',
        "test_cmd_no_expand": "python -c 'print($FOO)'",
        "test_script": "python test_script.py",
        "test_cmd_array": ["python", "test_script.py"],
        "test_shell": {
            "shell": "echo $FOO"
        },
    }
    project.write_pyproject()
    capfd.readouterr()
    with cd(project.root), temp_environ():
        os.environ["FOO"] = "bar"
        invoke(["run", "test_cmd"], obj=project)
        assert capfd.readouterr()[0].strip() == "1"

        result = invoke(["run", "test_cmd_no_expand"], obj=project)
        assert result.exit_code == 1

        invoke(["run", "test_script"], obj=project)
        assert capfd.readouterr()[0].strip() == "bar"

        invoke(["run", "test_cmd_array"], obj=project)
        assert capfd.readouterr()[0].strip() == "bar"

        invoke(["run", "test_shell"], obj=project)
        assert capfd.readouterr()[0].strip() == "bar"
Example #6
0
def test_run_script_override_global_env(project, invoke, capfd):
    (project.root /
     "test_script.py").write_text("import os; print(os.getenv('FOO'))")
    project.tool_settings["scripts"] = {
        "_": {
            "env": {
                "FOO": "bar"
            }
        },
        "test_env": {
            "cmd": "python test_script.py"
        },
        "test_env_override": {
            "cmd": "python test_script.py",
            "env": {
                "FOO": "foobar"
            }
        },
    }
    project.write_pyproject()
    capfd.readouterr()
    with cd(project.root):
        invoke(["run", "test_env"], obj=project)
        assert capfd.readouterr()[0].strip() == "bar"
        invoke(["run", "test_env_override"], obj=project)
        assert capfd.readouterr()[0].strip() == "foobar"
Example #7
0
def test_search_package(invoke, tmp_path):
    with cd(tmp_path):
        result = invoke(["search", "requests"])
    assert result.exit_code == 0
    assert len(result.output.splitlines()) > 0
    assert not tmp_path.joinpath("__pypackages__").exists()
    assert not tmp_path.joinpath(".pdm.toml").exists()
Example #8
0
def test_run_call_script(project, invoke):
    (project.root / "test_script.py").write_text(
        textwrap.dedent("""
            import argparse
            import sys

            def main(argv=None):
                parser = argparse.ArgumentParser()
                parser.add_argument("-c", "--code", type=int)
                args = parser.parse_args(argv)
                sys.exit(args.code)
            """))
    project.tool_settings["scripts"] = {
        "test_script": {
            "call": "test_script:main"
        },
        "test_script_with_args": {
            "call": "test_script:main(['-c', '9'])"
        },
    }
    project.write_pyproject()
    with cd(project.root):
        result = invoke(["run", "test_script", "-c", "8"], obj=project)
        assert result.exit_code == 8

        result = invoke(["run", "test_script_with_args"], obj=project)
        assert result.exit_code == 9
Example #9
0
def test_export_replace_project_root(project):
    artifact = FIXTURES / "artifacts/first-2.0.2-py2.py3-none-any.whl"
    shutil.copy2(artifact, project.root)
    with cd(project.root):
        req = parse_requirement(f"./{artifact.name}")
    result = requirements.export(project, [req], Namespace(hashes=False))
    assert "${PROJECT_ROOT}" not in result
Example #10
0
def test_auto_global_project(tmp_path, core):
    tmp_path.joinpath(".pdm-home").mkdir()
    (tmp_path / ".pdm-home/config.toml").write_text(
        "[global_project]\nfallback = true\n"
    )
    with cd(tmp_path):
        project = core.create_project(global_config=tmp_path / ".pdm-home/config.toml")
    assert project.is_global
Example #11
0
def convert(project: Optional[Project], filename: PathLike,
            options: Optional[Namespace]) -> Tuple[Mapping, Mapping]:
    with open(filename, encoding="utf-8") as fp, cd(
            os.path.dirname(os.path.abspath(filename))):
        converter = FlitMetaConverter(
            toml.load(fp)["tool"]["flit"],
            project.core.ui if project else None)
        return converter.convert()
Example #12
0
def test_run_script_with_dotenv_file(project, invoke, capfd):
    (project.root / "test_script.py").write_text("import os; print(os.getenv('FOO'))")
    project.tool_settings["scripts"] = {
        "test_script": {"cmd": "python test_script.py", "env_file": ".env"}
    }
    project.write_pyproject()
    (project.root / ".env").write_text("FOO=bar")
    capfd.readouterr()
    with cd(project.root):
        invoke(["run", "test_script"], obj=project)
        assert capfd.readouterr()[0].strip() == "bar"
Example #13
0
def convert(
    project: Project | None,
    filename: str | Path,
    options: Namespace | None,
) -> tuple[Mapping[str, Any], Mapping[str, Any]]:
    with open(filename,
              "rb") as fp, cd(os.path.dirname(os.path.abspath(filename))):
        converter = PoetryMetaConverter(
            tomli.load(fp)["tool"]["poetry"],
            project.core.ui if project else None)
        return converter.convert()
Example #14
0
def test_run_shell_script(project, invoke):
    project.tool_settings["scripts"] = {
        "test_script": {
            "shell": "echo hello > output.txt"
        }
    }
    project.write_pyproject()
    with cd(project.root):
        result = invoke(["run", "test_script"], obj=project)
    assert result.exit_code == 0
    assert (project.root / "output.txt").read_text().strip() == "hello"
Example #15
0
def invoke(isolated, monkeypatch):
    runner = CliRunner(mix_stderr=False)
    core = Core()
    invoker = functools.partial(runner.invoke, core, prog_name="pdm")
    monkeypatch.delenv("PDM_IGNORE_SAVED_PYTHON", raising=False)
    with cd(isolated):
        invoker(["config", "venv.location", str(isolated / "venvs")])
        invoker(["config", "venv.backend", os.getenv("VENV_BACKEND", "virtualenv")])
        if (isolated / ".pdm.toml").exists():
            (isolated / ".pdm.toml").unlink()
        yield invoker
Example #16
0
def test_project_with_combined_extras(fixture_project):
    project = fixture_project("demo-combined-extras")
    (project.root / "build").mkdir(exist_ok=True)
    with cd(project.root.as_posix()):
        wheel_name = build_wheel(str(project.root / "build"))
        wheel = distlib.wheel.Wheel(str(project.root / "build" / wheel_name))

    all_requires = filter_requirements_with_extras(wheel.metadata.run_requires,
                                                   ("all", ))
    for dep in ("urllib3", "chardet", "idna"):
        assert dep in all_requires
Example #17
0
def convert(
    project: Optional[Project],
    filename: PathLike,
    options: Optional[Namespace],
) -> Tuple[Dict[str, Any], Dict]:
    with open(filename, encoding="utf-8") as fp, cd(
        os.path.dirname(os.path.abspath(filename))
    ):
        converter = PoetryMetaConverter(
            toml.load(fp)["tool"]["poetry"], project.core.ui if project else None
        )
        return converter.convert()
Example #18
0
def test_run_with_patched_sysconfig(project, invoke, capfd):
    project.root.joinpath("script.py").write_text("""\
import sysconfig
import json
print(json.dumps(sysconfig.get_paths()))
""")
    capfd.readouterr()
    with cd(project.root):
        result = invoke(["run", "python", "script.py"], obj=project)
    assert result.exit_code == 0
    out = json.loads(capfd.readouterr()[0])
    assert "__pypackages__" in out["purelib"]
Example #19
0
def test_run_script_with_extra_args(project, invoke, capfd):
    (project.root / "test_script.py").write_text(
        textwrap.dedent("""
            import sys
            print(*sys.argv[1:], sep='\\n')
            """))
    project.tool_settings["scripts"] = {"test_script": "python test_script.py"}
    project.write_pyproject()
    with cd(project.root):
        invoke(["run", "test_script", "-a", "-b", "-c"], obj=project)
    out, _ = capfd.readouterr()
    assert out.splitlines()[-3:] == ["-a", "-b", "-c"]
Example #20
0
def test_run_with_another_project_root(project, local_finder, invoke, capfd):
    project.meta["requires-python"] = ">=3.6"
    project.write_pyproject()
    invoke(["add", "first"], obj=project)
    with TemporaryDirectory(prefix="pytest-run-") as tmp_dir:
        Path(tmp_dir).joinpath("main.py").write_text(
            "import first;print(first.first([0, False, 1, 2]))\n")
        capfd.readouterr()
        with cd(tmp_dir):
            ret = invoke(["run", "-p", str(project.root), "python", "main.py"])
            assert ret.exit_code == 0
            out, _ = capfd.readouterr()
            assert out.strip() == "1"
Example #21
0
def test_run_with_another_project_root(project, invoke, capfd):
    project.meta["requires-python"] = ">=3.6"
    project.write_pyproject()
    invoke(["add", "requests==2.24.0"], obj=project)
    with TemporaryDirectory(prefix="pytest-run-") as tmp_dir:
        Path(tmp_dir).joinpath("main.py").write_text(
            "import requests\nprint(requests.__version__)\n")
        capfd.readouterr()
        with cd(tmp_dir):
            ret = invoke(["run", "-p", str(project.root), "python", "main.py"])
            assert ret.exit_code == 0
            out, _ = capfd.readouterr()
            assert out.strip() == "2.24.0"
Example #22
0
 def dev_dependencies(self) -> Dict[str, Requirement]:
     """All development dependencies"""
     dev_group = self.tool_settings.get("dev-dependencies", {})
     if not dev_group:
         return {}
     result = {}
     with cd(self.root):
         for _, deps in dev_group.items():
             for line in deps:
                 if line.startswith("-e "):
                     req = parse_requirement(line[3:].strip(), True)
                 else:
                     req = parse_requirement(line)
                 result[req.identify()] = req
     return result
Example #23
0
def test_basic_integration(python_version, project_no_init, strict_invoke):
    """An e2e test case to ensure PDM works on all supported Python versions"""
    project = project_no_init
    project.root.joinpath("foo.py").write_text("import django\n")
    strict_invoke(["init"], input="\ny\n\n\n\n\n\n>=2.7\n", obj=project)
    strict_invoke(["use", "-f", python_version], obj=project)
    project._environment = None
    strict_invoke(["add", "django"], obj=project)
    with cd(project.root):
        strict_invoke(["run", "python", "foo.py"], obj=project)
        if python_version != "2.7":
            strict_invoke(["build", "-v"], obj=project)
    strict_invoke(["remove", "django"], obj=project)
    result = strict_invoke(["list"], obj=project)
    assert not any(line.strip().lower().startswith("django")
                   for line in result.output.splitlines())
Example #24
0
 def install_editable(self, ireq: shims.InstallRequirement) -> None:
     setup_path = ireq.setup_py_path
     paths = self.environment.get_paths()
     install_script = importlib.import_module(
         "pdm._editable_install"
     ).__file__.rstrip("co")
     install_args = [
         self.environment.python_executable,
         "-u",
         install_script,
         setup_path,
         paths["prefix"],
         paths["purelib"],
         paths["scripts"],
     ]
     with self.environment.activate(True), cd(ireq.unpacked_source_directory):
         result = subprocess.run(install_args, capture_output=True, check=True)
         stream.logger.debug(result.stdout.decode("utf-8"))
Example #25
0
 def get_dependencies(self, section: Optional[str] = None) -> Dict[str, Requirement]:
     metadata = self.meta
     if section in (None, "default"):
         deps = metadata.get("dependencies", [])
     elif section == "dev":
         deps = metadata.get("dev-dependencies", [])
     else:
         deps = metadata.get("optional-dependencies", {}).get(section, [])
     result = {}
     with cd(self.root):
         for line in deps:
             if line.startswith("-e "):
                 req = parse_requirement(line[3:].strip(), True)
             else:
                 req = parse_requirement(line)
             req.from_section = section or "default"
             # make editable packages behind normal ones to override correctly.
             result[req.identify()] = req
     return result
Example #26
0
def test_import_another_sitecustomize(project, invoke, capfd):
    project.meta["requires-python"] = ">=2.7"
    project.write_pyproject()
    # a script for checking another sitecustomize is imported
    project.root.joinpath("foo.py").write_text(
        "import os;print(os.getenv('FOO'))")
    # ensure there have at least one sitecustomize can be imported
    # there may have more than one sitecustomize.py in sys.path
    project.root.joinpath("sitecustomize.py").write_text(
        "import os;os.environ['FOO'] = 'foo'")
    env = os.environ.copy()
    paths = env.get("PYTHONPATH")
    this_path = str(project.root)
    new_paths = [this_path] if not paths else [this_path, paths]
    env["PYTHONPATH"] = os.pathsep.join(new_paths)
    project._environment = None
    capfd.readouterr()
    with cd(project.root):
        result = invoke(["run", "python", "foo.py"], env=env)
    assert result.exit_code == 0, result.stderr
    out, _ = capfd.readouterr()
    assert out.strip() == "foo"
Example #27
0
def test_basic_integration(python_version, core, tmp_path, invoke):
    """An e2e test case to ensure PDM works on all supported Python versions"""
    project = core.create_project(tmp_path)
    project.root.joinpath("foo.py").write_text("import django\n")
    additional_args = ["--no-self"] if python_version == "2.7" else []
    invoke(["use", "-f", python_version], obj=project, strict=True)
    invoke(["init", "-n"], obj=project, strict=True)
    project.meta["name"] = "test-project"
    project.meta[
        "requires-python"] = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*"
    project.write_pyproject()
    project._environment = None
    invoke(["add", "django", "-v"] + additional_args, obj=project, strict=True)
    with cd(project.root):
        invoke(["run", "python", "foo.py"], obj=project, strict=True)
        if python_version != "2.7":
            invoke(["build", "-v"], obj=project, strict=True)
    invoke(["remove", "-v", "django"] + additional_args,
           obj=project,
           strict=True)
    result = invoke(["list"], obj=project, strict=True)
    assert not any(line.strip().lower().startswith("django")
                   for line in result.output.splitlines())
Example #28
0
def test_info_global_project(invoke, tmp_path):
    with cd(tmp_path):
        result = invoke(["info", "-g", "--where"])
    assert "global-project" in result.output.strip()
Example #29
0
    def convert_package_paths(self) -> Dict[str, Union[List, Dict]]:
        """Return a {package_dir, packages, package_data, exclude_package_data} dict."""
        package_dir = {}
        packages = []
        py_modules = []
        package_data = {"": ["*"]}
        exclude_package_data = {}

        with cd(self.project.root.as_posix()):
            if not self.includes:
                if os.path.isdir("src"):
                    package_dir[""] = "src"
                    packages = setuptools.find_packages("src")
                else:
                    packages = setuptools.find_packages(
                        exclude=["tests", "tests.*"])
                if not packages:
                    py_modules = [path[:-3] for path in glob.glob("*.py")]
            else:
                packages_set = set()
                includes = self.includes
                for include in includes[:]:
                    if include.replace("\\", "/").endswith("/*"):
                        include = include[:-2]
                    if "*" not in include and os.path.isdir(include):
                        include = include.rstrip("/\\")
                        temp = setuptools.find_packages(include)
                        if os.path.exists(include + "/__init__.py"):
                            temp = [include
                                    ] + [f"{include}.{part}" for part in temp]
                        elif temp:
                            package_dir[""] = include
                        packages_set.update(temp)
                        includes.remove(include)
                packages[:] = list(packages_set)
                for include in includes:
                    for path in glob.glob(include):
                        if "/" not in path.lstrip("./") and path.endswith(
                                ".py"):
                            # Only include top level py modules
                            py_modules.append(path.lstrip("./")[:-3])
                    if include.endswith(".py"):
                        continue
                    for package in packages:
                        relpath = os.path.relpath(include, package)
                        if not relpath.startswith(".."):
                            package_data.setdefault(package,
                                                    []).append(relpath)
                for exclude in self.excludes or []:
                    for package in packages:
                        relpath = os.path.relpath(exclude, package)
                        if not relpath.startswith(".."):
                            exclude_package_data.setdefault(package,
                                                            []).append(relpath)
            if packages and py_modules:
                raise ProjectError(
                    "Can't specify packages and py_modules at the same time.")
        return {
            "package_dir": package_dir,
            "packages": packages,
            "py_modules": py_modules,
            "package_data": package_data,
            "exclude_package_data": exclude_package_data,
        }
Example #30
0
def convert(project, filename):
    with open(filename, encoding="utf-8") as fp, cd(
            os.path.dirname(os.path.abspath(filename))):
        converter = PoetryMetaConverter(toml.load(fp)["tool"]["poetry"])
        return dict(converter), converter.settings