Beispiel #1
0
    def _pep517_metadata(cls, path):  # type (Path) -> PackageInfo
        """
        Helper method to use PEP-517 library to build and read package metadata.

        :param path: Path to package source to build and read metadata for.
        """
        info = None
        try:
            info = cls.from_setup_files(path)
            if info.requires_dist is not None:
                return info
        except PackageInfoError:
            pass

        with temporary_directory() as tmp_dir:
            # TODO: cache PEP 517 build environment corresponding to each project venv
            venv_dir = Path(tmp_dir) / ".venv"
            EnvManager.build_venv(venv_dir.as_posix())
            venv = VirtualEnv(venv_dir, venv_dir)

            dest_dir = Path(tmp_dir) / "dist"
            dest_dir.mkdir()

            try:
                venv.run("python", "-m", "pip", "install",
                         "--disable-pip-version-check", "--ignore-installed",
                         *PEP517_META_BUILD_DEPS)
                venv.run(
                    "python",
                    "-",
                    input_=PEP517_META_BUILD.format(source=path.as_posix(),
                                                    dest=dest_dir.as_posix()),
                )
                return cls.from_metadata(dest_dir)
            except EnvCommandError as e:
                # something went wrong while attempting pep517 metadata build
                # fallback to egg_info if setup.py available
                cls._log("PEP517 build failed: {}".format(e), level="debug")
                setup_py = path / "setup.py"
                if not setup_py.exists():
                    raise PackageInfoError(path)

                cwd = Path.cwd()
                os.chdir(path.as_posix())
                try:
                    venv.run("python", "setup.py", "egg_info")
                    return cls.from_metadata(path)
                except EnvCommandError:
                    raise PackageInfoError(path)
                finally:
                    os.chdir(cwd.as_posix())

        if info:
            cls._log(
                "Falling back to parsed setup.py file for {}".format(path),
                "debug")
            return info

        # if we reach here, everything has failed and all hope is lost
        raise PackageInfoError(path)
Beispiel #2
0
    def _from_sdist_file(cls, path):  # type: (Path) -> PackageInfo
        """
        Helper method to parse package information from an sdist file. We attempt to first inspect the
        file using `pkginfo.SDist`. If this does not provide us with package requirements, we extract the
        source and handle it as a directory.

        :param path: The sdist file to parse information from.
        """
        info = None

        try:
            info = cls._from_distribution(pkginfo.SDist(str(path)))
        except ValueError:
            # Unable to determine dependencies
            # We pass and go deeper
            pass
        else:
            if info.requires_dist is not None:
                # we successfully retrieved dependencies from sdist metadata
                return info

        # Still not dependencies found
        # So, we unpack and introspect
        suffix = path.suffix

        if suffix == ".zip":
            context = zipfile.ZipFile
        else:
            if suffix == ".bz2":
                suffixes = path.suffixes
                if len(suffixes) > 1 and suffixes[-2] == ".tar":
                    suffix = ".tar.bz2"
            else:
                suffix = ".tar.gz"

            context = tarfile.open

        with temporary_directory() as tmp:
            tmp = Path(tmp)
            with context(path.as_posix()) as archive:
                archive.extractall(tmp.as_posix())

            # a little bit of guess work to determine the directory we care about
            elements = list(tmp.glob("*"))

            if len(elements) == 1 and elements[0].is_dir():
                sdist_dir = elements[0]
            else:
                sdist_dir = tmp / path.name.rstrip(suffix)
                if not sdist_dir.is_dir():
                    sdist_dir = tmp

            # now this is an unpacked directory we know how to deal with
            new_info = cls.from_directory(path=sdist_dir)

        if not info:
            return new_info

        return info.update(new_info)
Beispiel #3
0
def test_build_wheel_extended():
    with temporary_directory() as tmp_dir, cwd(
            os.path.join(fixtures, "extended")):
        filename = api.build_wheel(tmp_dir)
        whl = Path(tmp_dir) / filename
        assert whl.exists()
        validate_wheel_contents(name="extended",
                                version="0.1",
                                path=whl.as_posix())
Beispiel #4
0
def test_file_dependency_pep_508_local_file_relative_path(mocker):
    path = Path("..") / "fixtures" / "distributions" / "demo-0.2.0.tar.gz"

    with pytest.raises(ValueError):
        requirement = "{} @ file://{}".format("demo", path.as_posix())
        _test_file_dependency_pep_508(mocker, "demo", path, requirement)

    requirement = "{} @ {}".format("demo", path)
    _test_file_dependency_pep_508(mocker, "demo", path, requirement)
Beispiel #5
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
Beispiel #6
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
def test_directory_dependency_pep_508_local_relative():
    path = Path(
        "..") / "fixtures" / "project_with_multi_constraints_dependency"

    with pytest.raises(ValueError):
        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)
Beispiel #8
0
    def is_excluded(self, filepath):  # type: (Union[str, Path]) -> bool
        exclude_path = Path(filepath)

        while True:
            if exclude_path.as_posix() in self.find_excluded_files():
                return True

            if len(exclude_path.parts) > 1:
                exclude_path = exclude_path.parent
            else:
                break

        return False
Beispiel #9
0
def test_complete_no_vcs():
    # Copy the complete fixtures dir to a temporary directory
    module_path = fixtures_dir / "complete"
    temporary_dir = Path(tempfile.mkdtemp()) / "complete"

    shutil.copytree(module_path.as_posix(), temporary_dir.as_posix())

    builder = Builder(Factory().create_poetry(temporary_dir))
    builder.build(fmt="all")

    whl = temporary_dir / "dist" / "my_package-1.2.3-py3-none-any.whl"

    assert whl.exists()

    zip = zipfile.ZipFile(str(whl))

    # Check the zipped file to be sure that included and excluded files are
    # correctly taken account of without vcs
    expected_name_list = [
        "my_package/__init__.py",
        "my_package/data1/test.json",
        "my_package/sub_pkg1/__init__.py",
        "my_package/sub_pkg2/__init__.py",
        "my_package/sub_pkg2/data2/data.json",
        "my_package/sub_pkg3/foo.py",
        "my_package-1.2.3.dist-info/entry_points.txt",
        "my_package-1.2.3.dist-info/LICENSE",
        "my_package-1.2.3.dist-info/WHEEL",
        "my_package-1.2.3.dist-info/METADATA",
        "my_package-1.2.3.dist-info/RECORD",
    ]

    assert sorted(zip.namelist()) == sorted(expected_name_list)

    try:
        entry_points = zip.read("my_package-1.2.3.dist-info/entry_points.txt")

        assert (decode(entry_points.decode()) == """\
[console_scripts]
extra-script=my_package.extra:main[time]
my-2nd-script=my_package:main2
my-script=my_package:main

""")
        wheel_data = decode(zip.read("my_package-1.2.3.dist-info/WHEEL"))

        assert (wheel_data == """\
Wheel-Version: 1.0
Generator: poetry {}
Root-Is-Purelib: true
Tag: py3-none-any
""".format(__version__))
        wheel_data = decode(zip.read("my_package-1.2.3.dist-info/METADATA"))

        assert (wheel_data == """\
Metadata-Version: 2.1
Name: my-package
Version: 1.2.3
Summary: Some description.
Home-page: https://python-poetry.org/
License: MIT
Keywords: packaging,dependency,poetry
Author: Sébastien Eustace
Author-email: [email protected]
Maintainer: People Everywhere
Maintainer-email: [email protected]
Requires-Python: >=3.6,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Provides-Extra: time
Requires-Dist: cachy[msgpack] (>=0.2.0,<0.3.0)
Requires-Dist: cleo (>=0.6,<0.7)
Requires-Dist: pendulum (>=1.4,<2.0); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time")
Project-URL: Documentation, https://python-poetry.org/docs
Project-URL: Issue Tracker, https://github.com/python-poetry/poetry/issues
Project-URL: Repository, https://github.com/python-poetry/poetry
Description-Content-Type: text/x-rst

My Package
==========

""")
    finally:
        zip.close()
Beispiel #10
0
 def __init__(self, path):  # type: (Union[str, Path]) -> None
     if isinstance(path, str):
         path = Path(path)
     super(TOMLFile, self).__init__(path.as_posix())
     self.__path = path