예제 #1
0
 def __init__(
         self,
         path,  # type: Path
         source_root=None,  # type: Optional[Path]
 ):
     """
     :param path: a full path to the file to be included
     :param source_root: the root path to resolve to
     """
     self.path = Path(path)
     self.source_root = None if not source_root else Path(
         source_root).resolve()
     if not self.path.is_absolute() and self.source_root:
         self.path = (self.source_root / self.path).resolve()
     else:
         self.path = self.path.resolve()
예제 #2
0
def test_metadata_homepage_default():
    builder = Builder(Factory().create_poetry(
        Path(__file__).parent / "fixtures" / "simple_version"))

    metadata = Parser().parsestr(builder.get_metadata_content())

    assert metadata["Home-page"] is None
예제 #3
0
def get_vcs(directory):  # type: (Path) -> Git
    working_dir = Path.cwd()
    os.chdir(str(directory.resolve()))

    try:
        git_dir = decode(
            subprocess.check_output(["git", "rev-parse", "--show-toplevel"],
                                    stderr=subprocess.STDOUT)).strip()

        vcs = Git(Path(git_dir))

    except (subprocess.CalledProcessError, OSError):
        vcs = None
    finally:
        os.chdir(str(working_dir))

    return vcs
def test_directory_dependency_pep_508_local_absolute():
    path = (Path(__file__).parent.parent / "fixtures" /
            "project_with_multi_constraints_dependency")
    requirement = "{} @ file://{}".format("demo", path.as_posix())
    _test_directory_dependency_pep_508("demo", path, requirement)

    requirement = "{} @ {}".format("demo", path)
    _test_directory_dependency_pep_508("demo", path, requirement)
예제 #5
0
def test_builder_find_excluded_files(mocker):
    p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files")
    p.return_value = []

    builder = Builder(
        Factory().create_poetry(Path(__file__).parent / "fixtures" / "complete")
    )

    assert builder.find_excluded_files() == {"my_package/sub_pkg1/extra_file.xml"}
예제 #6
0
파일: test_sdist.py 프로젝트: hoefling/core
def test_default_with_excluded_data(mocker):
    # Patch git module to return specific excluded files
    p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files")
    p.return_value = [
        (
            (
                Path(__file__).parent
                / "fixtures"
                / "default_with_excluded_data"
                / "my_package"
                / "data"
                / "sub_data"
                / "data2.txt"
            )
            .relative_to(project("default_with_excluded_data"))
            .as_posix()
        )
    ]
    poetry = Factory().create_poetry(project("default_with_excluded_data"))

    builder = SdistBuilder(poetry)

    # Check setup.py
    setup = builder.build_setup()
    setup_ast = ast.parse(setup)

    setup_ast.body = [n for n in setup_ast.body if isinstance(n, ast.Assign)]
    ns = {}
    exec(compile(setup_ast, filename="setup.py", mode="exec"), ns)
    assert "package_dir" not in ns
    assert ns["packages"] == ["my_package"]
    assert ns["package_data"] == {
        "": ["*"],
        "my_package": ["data/*", "data/sub_data/data3.txt"],
    }

    builder.build()

    sdist = (
        fixtures_dir / "default_with_excluded_data" / "dist" / "my-package-1.2.3.tar.gz"
    )

    assert sdist.exists()

    with tarfile.open(str(sdist), "r") as tar:
        names = tar.getnames()
        assert len(names) == len(set(names))
        assert "my-package-1.2.3/LICENSE" in names
        assert "my-package-1.2.3/README.rst" in names
        assert "my-package-1.2.3/my_package/__init__.py" in names
        assert "my-package-1.2.3/my_package/data/data1.txt" in names
        assert "my-package-1.2.3/pyproject.toml" in names
        assert "my-package-1.2.3/setup.py" in names
        assert "my-package-1.2.3/PKG-INFO" in names
        # all last modified times should be set to a valid timestamp
        for tarinfo in tar.getmembers():
            assert 0 < tarinfo.mtime
예제 #7
0
def test_builder_find_invalid_case_sensitive_excluded_files(mocker):
    p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files")
    p.return_value = []

    builder = Builder(Factory().create_poetry(
        Path(__file__).parent / "fixtures" /
        "invalid_case_sensitive_exclusions"))

    assert {"my_package/Bar/foo/bar/Foo.py"} == builder.find_excluded_files()
예제 #8
0
def test_metadata_with_vcs_dependencies():
    builder = Builder(Factory().create_poetry(
        Path(__file__).parent / "fixtures" / "with_vcs_dependency"))

    metadata = Parser().parsestr(builder.get_metadata_content())

    requires_dist = metadata["Requires-Dist"]

    assert "cleo @ git+https://github.com/sdispater/cleo.git@master" == requires_dist
예제 #9
0
def test_to_dependency_for_directory():
    path = Path(__file__).parent.parent.joinpath("fixtures/simple_project")
    package = Package(
        "foo",
        "1.2.3",
        source_type="directory",
        source_url=path.as_posix(),
        features=["baz", "bar"],
    )
    dep = package.to_dependency()

    assert "foo" == dep.name
    assert package.version == dep.constraint
    assert frozenset({"bar", "baz"}) == dep.features
    assert dep.is_directory()
    assert path == dep.path
    assert "directory" == dep.source_type
    assert path.as_posix() == dep.source_url
예제 #10
0
파일: api.py 프로젝트: pexip/os-poetry-core
def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
    poetry = Factory().create_poetry(Path(".").resolve())
    builder = WheelBuilder(poetry)

    dist_info = Path(metadata_directory, builder.dist_info)
    dist_info.mkdir(parents=True, exist_ok=True)

    if "scripts" in poetry.local_config or "plugins" in poetry.local_config:
        with (dist_info / "entry_points.txt").open("w", encoding="utf-8") as f:
            builder._write_entry_points(f)

    with (dist_info / "WHEEL").open("w", encoding="utf-8") as f:
        builder._write_wheel_file(f)

    with (dist_info / "METADATA").open("w", encoding="utf-8") as f:
        builder._write_metadata_file(f)

    return dist_info.name
예제 #11
0
def test_to_dependency_for_file():
    path = Path(__file__).parent.parent.joinpath(
        "fixtures/distributions/demo-0.1.0.tar.gz")
    package = Package(
        "foo",
        "1.2.3",
        source_type="file",
        source_url=path.as_posix(),
        features=["baz", "bar"],
    )
    dep = package.to_dependency()

    assert "foo" == dep.name
    assert package.version == dep.constraint
    assert frozenset({"bar", "baz"}) == dep.features
    assert dep.is_file()
    assert path == dep.path
    assert "file" == dep.source_type
    assert path.as_posix() == dep.source_url
예제 #12
0
파일: sdist.py 프로젝트: tomgrin10/core
        def find_nearest_pkg(rel_path):
            parts = rel_path.split(os.sep)
            for i in reversed(range(1, len(parts))):
                ancestor = "/".join(parts[:i])
                if ancestor in subpkg_paths:
                    pkg = ".".join([pkg_name] + parts[:i])
                    return pkg, "/".join(parts[i:])

            # Relative to the top-level package
            return pkg_name, Path(rel_path).as_posix()
예제 #13
0
def test_pip_wheel_build(temporary_directory, project_source_root):
    tmp = str(temporary_directory)
    pip = subprocess_run("pip", "wheel", "--use-pep517", "-w", tmp,
                         str(project_source_root))
    assert "Successfully built poetry-core" in pip.stdout

    assert pip.returncode == 0

    wheels = list(Path(tmp).glob("poetry_core-*-none-any.whl"))
    assert len(wheels) == 1
예제 #14
0
파일: complete.py 프로젝트: tomgrin10/core
    def unpacked_tarball(cls, path):
        tf = tarfile.open(str(path))

        with cls.temporary_directory() as tmpdir:
            tf.extractall(tmpdir)
            files = os.listdir(tmpdir)

            assert len(files) == 1, files

            yield Path(tmpdir) / files[0]
예제 #15
0
def test_pyproject_toml_no_build_system_defaults():
    pyproject_toml = (Path(__file__).parent.parent / "fixtures" /
                      "project_with_build_system_requires" / "pyproject.toml")

    build_system = PyProjectTOML(pyproject_toml).build_system
    assert build_system.requires == ["poetry-core", "Cython~=0.29.6"]

    assert len(build_system.dependencies) == 2
    assert build_system.dependencies[0].to_pep_508() == "poetry-core"
    assert build_system.dependencies[1].to_pep_508(
    ) == "Cython (>=0.29.6,<0.30.0)"
예제 #16
0
파일: __init__.py 프로젝트: tomgrin10/core
def _make_file_or_dir_dep(
    name,
    path,
    base=None
):  # type: (str, Path, Optional[Path]) -> Optional[Union[FileDependency, DirectoryDependency]]
    """
    Helper function to create a file or directoru dependency with the given arguments. If
    path is not a file or directory that exists, `None` is returned.
    """
    _path = path
    if not path.is_absolute() and base:
        # a base path was specified, so we should respect that
        _path = Path(base) / path

    if _path.is_file():
        return FileDependency(name, path, base=base)
    elif _path.is_dir():
        return DirectoryDependency(name, path, base=base)

    return None
def _test_directory_dependency_pep_508(name,
                                       path,
                                       pep_508_input,
                                       pep_508_output=None):
    dep = dependency_from_pep_508(pep_508_input,
                                  relative_to=Path(__file__).parent)

    assert dep.is_directory()
    assert dep.name == name
    assert dep.path == path
    assert dep.to_pep_508() == pep_508_output or pep_508_input
예제 #18
0
def test_url_to_path(url, win_expected, non_win_expected):
    if sys.platform == "win32":
        expected_path = win_expected
    else:
        expected_path = non_win_expected

    if expected_path is None:
        with pytest.raises(ValueError):
            url_to_path(url)
    else:
        assert url_to_path(url) == Path(expected_path)
예제 #19
0
def test_metadata_with_url_dependencies():
    builder = Builder(Factory().create_poetry(
        Path(__file__).parent / "fixtures" / "with_url_dependency"))

    metadata = Parser().parsestr(builder.get_metadata_content())

    requires_dist = metadata["Requires-Dist"]

    assert (
        "demo @ https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
        == requires_dist)
예제 #20
0
def test_find_files_to_add():
    poetry = Factory().create_poetry(project("complete"))

    builder = SdistBuilder(poetry)
    result = [f.relative_to_source_root() for f in builder.find_files_to_add()]

    assert sorted(result) == sorted([
        Path("LICENSE"),
        Path("README.rst"),
        Path("my_package/__init__.py"),
        Path("my_package/data1/test.json"),
        Path("my_package/sub_pkg1/__init__.py"),
        Path("my_package/sub_pkg2/__init__.py"),
        Path("my_package/sub_pkg2/data2/data.json"),
        Path("my_package/sub_pkg3/foo.py"),
        Path("pyproject.toml"),
    ])
예제 #21
0
def _test_file_dependency_pep_508(
    mocker, name, path, pep_508_input, pep_508_output=None
):
    mocker.patch.object(Path, "exists").return_value = True
    mocker.patch.object(Path, "is_file").return_value = True

    dep = dependency_from_pep_508(pep_508_input, relative_to=Path(__file__).parent)

    assert dep.is_file()
    assert dep.name == name
    assert dep.path == path
    assert dep.to_pep_508() == pep_508_output or pep_508_input
예제 #22
0
def executable():
    global _executable

    if _executable is not None:
        return _executable

    if WINDOWS and PY36:
        # Finding git via where.exe
        where = "%WINDIR%\\System32\\where.exe"
        paths = decode(
            subprocess.check_output([where, "git"], shell=True,
                                    encoding="oem")).split("\n")
        for path in paths:
            if not path:
                continue

            path = Path(path.strip())
            try:
                path.relative_to(Path.cwd())
            except ValueError:
                _executable = str(path)

                break
    else:
        _executable = "git"

    if _executable is None:
        raise RuntimeError("Unable to find a valid git executable")

    return _executable
예제 #23
0
    def __init__(
        self,
        name,  # type: str
        path,  # type: Path
        category="main",  # type: str
        optional=False,  # type: bool
        base=None,  # type: Path
        develop=False,  # type: bool
        extras=None,  # type: Union[List[str], FrozenSet[str]]
    ):
        self._path = path
        self._base = base or Path.cwd()
        self._full_path = path

        if not self._path.is_absolute():
            try:
                self._full_path = self._base.joinpath(self._path).resolve()
            except FileNotFoundError:
                raise ValueError("Directory {} does not exist".format(self._path))

        self._develop = develop
        self._supports_poetry = False

        if not self._full_path.exists():
            raise ValueError("Directory {} does not exist".format(self._path))

        if self._full_path.is_file():
            raise ValueError("{} is a file, expected a directory".format(self._path))

        # Checking content to determine actions
        setup = self._full_path / "setup.py"
        self._supports_poetry = PyProjectTOML(
            self._full_path / "pyproject.toml"
        ).is_poetry_project()

        if not setup.exists() and not self._supports_poetry:
            raise ValueError(
                "Directory {} does not seem to be a Python package".format(
                    self._full_path
                )
            )

        super(DirectoryDependency, self).__init__(
            name,
            "*",
            category=category,
            optional=optional,
            allows_prereleases=True,
            source_type="directory",
            source_url=self._full_path.as_posix(),
            extras=extras,
        )
예제 #24
0
def test_get_metadata_content():
    builder = Builder(Factory().create_poetry(
        Path(__file__).parent / "fixtures" / "complete"))

    metadata = builder.get_metadata_content()

    p = Parser()
    parsed = p.parsestr(metadata)

    assert parsed["Metadata-Version"] == "2.1"
    assert parsed["Name"] == "my-package"
    assert parsed["Version"] == "1.2.3"
    assert parsed["Summary"] == "Some description."
    assert parsed["Author"] == "Sébastien Eustace"
    assert parsed["Author-email"] == "*****@*****.**"
    assert parsed["Keywords"] == "packaging,dependency,poetry"
    assert parsed["Requires-Python"] == ">=3.6,<4.0"
    assert parsed["License"] == "MIT"
    assert parsed["Home-page"] == "https://python-poetry.org/"

    classifiers = parsed.get_all("Classifier")
    assert classifiers == [
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Topic :: Software Development :: Build Tools",
        "Topic :: Software Development :: Libraries :: Python Modules",
    ]

    extras = parsed.get_all("Provides-Extra")
    assert extras == ["time"]

    requires = parsed.get_all("Requires-Dist")
    assert requires == [
        "cachy[msgpack] (>=0.2.0,<0.3.0)",
        "cleo (>=0.6,<0.7)",
        'pendulum (>=1.4,<2.0); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time")',
    ]

    urls = parsed.get_all("Project-URL")
    assert urls == [
        "Documentation, https://python-poetry.org/docs",
        "Issue Tracker, https://github.com/python-poetry/poetry/issues",
        "Repository, https://github.com/python-poetry/poetry",
    ]
예제 #25
0
def test_make_pkg_info_multi_constraints_dependency():
    poetry = Factory().create_poetry(
        Path(__file__).parent.parent.parent / "fixtures" /
        "project_with_multi_constraints_dependency")

    builder = SdistBuilder(poetry)
    pkg_info = builder.build_pkg_info()
    p = Parser()
    parsed = p.parsestr(to_str(pkg_info))

    requires = parsed.get_all("Requires-Dist")
    assert requires == [
        'pendulum (>=1.5,<2.0); python_version < "3.4"',
        'pendulum (>=2.0,<3.0); python_version >= "3.4" and python_version < "4.0"',
    ]
예제 #26
0
class BuildIncludeFile:
    def __init__(
            self,
            path,  # type: Path
            source_root=None,  # type: Optional[Path]
    ):
        """
        :param path: a full path to the file to be included
        :param source_root: the root path to resolve to
        """
        self.path = Path(path)
        self.source_root = None if not source_root else Path(
            source_root).resolve()
        if not self.path.is_absolute() and self.source_root:
            self.path = (self.source_root / self.path).resolve()
        else:
            self.path = self.path.resolve()

    def __eq__(self, other):  # type: (Union[BuildIncludeFile, Path]) -> bool
        if hasattr(other, "path"):
            return self.path == other.path
        return self.path == other

    def __ne__(self, other):  # type: (Union[BuildIncludeFile, Path]) -> bool
        return not self.__eq__(other)

    def __hash__(self):
        return hash(self.path)

    def __repr__(self):  # type: () -> str
        return str(self.path)

    def relative_to_source_root(self):  # type(): -> Path
        if self.source_root is not None:
            return self.path.relative_to(self.source_root)
        return self.path
예제 #27
0
    def __init__(
        self, poetry, ignore_packages_formats=False, executable=None
    ):  # type: ("Poetry", bool, Optional[Union[Path, str]]) -> None
        self._poetry = poetry
        self._package = poetry.package
        self._path = poetry.file.parent
        self._original_path = self._path
        self._excluded_files = None
        self._executable = Path(executable or sys.executable)  # type: Path

        packages = []
        for p in self._package.packages:
            formats = p.get("format", [])
            if not isinstance(formats, list):
                formats = [formats]

            if (
                formats
                and self.format
                and self.format not in formats
                and not ignore_packages_formats
            ):
                continue

            packages.append(p)

        includes = []
        for include in self._package.include:
            formats = include.get("format", [])

            if (
                formats
                and self.format
                and self.format not in formats
                and not ignore_packages_formats
            ):
                continue

            includes.append(include)

        self._module = Module(
            self._package.name,
            self._path.as_posix(),
            packages=packages,
            includes=includes,
        )

        self._meta = Metadata.from_package(self._package)
예제 #28
0
def test_builder_find_case_sensitive_excluded_files(mocker):
    p = mocker.patch("poetry.core.vcs.git.Git.get_ignored_files")
    p.return_value = []

    builder = Builder(Factory().create_poetry(
        Path(__file__).parent / "fixtures" / "case_sensitive_exclusions"))

    assert builder.find_excluded_files() == {
        "my_package/FooBar/Bar.py",
        "my_package/FooBar/lowercasebar.py",
        "my_package/Foo/SecondBar.py",
        "my_package/Foo/Bar.py",
        "my_package/Foo/lowercasebar.py",
        "my_package/bar/foo.py",
        "my_package/bar/CapitalFoo.py",
    }
예제 #29
0
    def _find_dist_info(path):  # type: (Path) -> Iterator[Path]
        """
        Discover all `*.*-info` directories in a given path.

        :param path: Path to search.
        """
        pattern = "**/*.*-info"
        if PY35:
            # Sometimes pathlib will fail on recursive symbolic links, so we need to workaround it
            # and use the glob module instead. Note that this does not happen with pathlib2
            # so it's safe to use it for Python < 3.4.
            directories = glob.iglob(path.joinpath(pattern).as_posix(), recursive=True)
        else:
            directories = path.glob(pattern)

        for d in directories:
            yield Path(d)
예제 #30
0
def test_create_poetry_fails_on_invalid_configuration():
    with pytest.raises(RuntimeError) as e:
        Factory().create_poetry(
            Path(__file__).parent / "fixtures" / "invalid_pyproject" /
            "pyproject.toml")

    if PY2:
        expected = """\
The Poetry configuration is invalid:
  - u'description' is a required property
"""
    else:
        expected = """\
The Poetry configuration is invalid:
  - 'description' is a required property
"""
    assert expected == str(e.value)