예제 #1
0
def test_accepts_fails_with_python_versions_mismatch():
    dependency = Dependency("A", "^1.0")
    dependency.python_versions = "^3.6"
    package = Package("B", "1.4")
    package.python_versions = "~3.5"

    assert not dependency.accepts(package)
예제 #2
0
def test_accepts_python_versions():
    dependency = Dependency('A', '^1.0')
    dependency.python_versions = '^3.6'
    package = Package('A', '1.4')
    package.python_versions = '~3.6'

    assert dependency.accepts(package)
예제 #3
0
def test_accepts_python_versions():
    dependency = Dependency("A", "^1.0")
    dependency.python_versions = "^3.6"
    package = Package("A", "1.4")
    package.python_versions = "~3.6"

    assert dependency.accepts(package)
예제 #4
0
def test_accepts_fails_with_python_versions_mismatch():
    dependency = Dependency('A', '^1.0')
    dependency.python_versions = '^3.6'
    package = Package('B', '1.4')
    package.python_versions = '~3.5'

    assert not dependency.accepts(package)
def test_accepts_python_versions():
    dependency = Dependency("A", "^1.0")
    dependency.python_versions = "^3.6"
    package = Package("A", "1.4")
    package.python_versions = "~3.6"

    assert dependency.accepts(package)
def test_accepts_fails_with_python_versions_mismatch():
    dependency = Dependency("A", "^1.0")
    dependency.python_versions = "^3.6"
    package = Package("B", "1.4")
    package.python_versions = "~3.5"

    assert not dependency.accepts(package)
예제 #7
0
    def get_package_from_file(cls, file_path):  # type: (Path) -> Package
        if file_path.suffix == ".whl":
            meta = pkginfo.Wheel(str(file_path))
        else:
            # Assume sdist
            meta = pkginfo.SDist(str(file_path))

        package = Package(meta.name, meta.version)
        package.source_type = "file"
        package.source_url = file_path.as_posix()

        package.description = meta.summary
        for req in meta.requires_dist:
            dep = dependency_from_pep_508(req)
            for extra in dep.in_extras:
                if extra not in package.extras:
                    package.extras[extra] = []

                package.extras[extra].append(dep)

            if not dep.is_optional():
                package.requires.append(dep)

        if meta.requires_python:
            package.python_versions = meta.requires_python

        return package
예제 #8
0
    def get_package_from_file(cls, file_path):  # type: (Path) -> Package
        info = Inspector().inspect(file_path)
        if not info["name"]:
            raise RuntimeError(
                "Unable to determine the package name of {}".format(file_path))

        package = Package(info["name"], info["version"])
        package.source_type = "file"
        package.source_url = file_path.as_posix()

        package.description = info["summary"]
        for req in info["requires_dist"]:
            dep = dependency_from_pep_508(req)
            for extra in dep.in_extras:
                if extra not in package.extras:
                    package.extras[extra] = []

                package.extras[extra].append(dep)

            if not dep.is_optional():
                package.requires.append(dep)

        if info["requires_python"]:
            package.python_versions = info["requires_python"]

        return package
예제 #9
0
def add_to_repo(repository, name, version, deps=None, python=None):
    package = Package(name, version)
    if python:
        package.python_versions = python

    if deps:
        for dep_name, dep_constraint in deps.items():
            package.add_dependency(dep_name, dep_constraint)

    repository.add_package(package)
예제 #10
0
파일: helpers.py 프로젝트: shawegit/poetry
def add_to_repo(repository, name, version, deps=None, python=None):
    package = Package(name, version)
    if python:
        package.python_versions = python

    if deps:
        for dep_name, dep_constraint in deps.items():
            package.add_dependency(dep_name, dep_constraint)

    repository.add_package(package)
예제 #11
0
    def search_for_file(self, dependency):  # type: (FileDependency) -> List[Package]
        package = Package(dependency.name, dependency.pretty_constraint)
        package.source_type = "file"
        package.source_url = dependency.path.as_posix()

        package.description = dependency.metadata.summary
        for req in dependency.metadata.requires_dist:
            package.requires.append(dependency_from_pep_508(req))

        if dependency.metadata.requires_python:
            package.python_versions = dependency.metadata.requires_python

        if dependency.metadata.platforms:
            package.platform = " || ".join(dependency.metadata.platforms)

        package.hashes = [dependency.hash()]

        return [package]
예제 #12
0
파일: provider.py 프로젝트: festinuz/poetry
    def search_for_file(self, dependency):  # type: (FileDependency) -> List[Package]
        package = Package(dependency.name, dependency.pretty_constraint)
        package.source_type = "file"
        package.source_url = dependency.path.as_posix()

        package.description = dependency.metadata.summary
        for req in dependency.metadata.requires_dist:
            package.requires.append(dependency_from_pep_508(req))

        if dependency.metadata.requires_python:
            package.python_versions = dependency.metadata.requires_python

        if dependency.metadata.platforms:
            package.platform = " || ".join(dependency.metadata.platforms)

        package.hashes = [dependency.hash()]

        return [package]
예제 #13
0
파일: provider.py 프로젝트: zhyr/poetry
    def search_for_file(self, dependency):  # type: (FileDependency) -> List[Package]
        if dependency.path.suffix == ".whl":
            meta = pkginfo.Wheel(str(dependency.full_path))
        else:
            # Assume sdist
            meta = pkginfo.SDist(str(dependency.full_path))

        if dependency.name != meta.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}".format(
                    dependency.name, meta.name
                )
            )

        package = Package(meta.name, meta.version)
        package.source_type = "file"
        package.source_url = dependency.path.as_posix()

        package.description = meta.summary
        for req in meta.requires_dist:
            dep = dependency_from_pep_508(req)
            for extra in dep.in_extras:
                if extra not in package.extras:
                    package.extras[extra] = []

                package.extras[extra].append(dep)

            if not dep.is_optional():
                package.requires.append(dep)

        if meta.requires_python:
            package.python_versions = meta.requires_python

        package.hashes = [dependency.hash()]

        for extra in dependency.extras:
            if extra in package.extras:
                for dep in package.extras[extra]:
                    dep.activate()

                package.requires += package.extras[extra]

        return [package]
예제 #14
0
    def search_for_directory(
            self, dependency):  # type: (DirectoryDependency) -> List[Package]
        if dependency.supports_poetry():
            from poetry.poetry import Poetry

            poetry = Poetry.create(dependency.full_path)

            pkg = poetry.package
            package = Package(pkg.name, pkg.version)

            for dep in pkg.requires:
                if not dep.is_optional():
                    package.requires.append(dep)

            for extra, deps in pkg.extras.items():
                if extra not in package.extras:
                    package.extras[extra] = []

                for dep in deps:
                    package.extras[extra].append(dep)

            package.python_versions = pkg.python_versions
        else:
            # Execute egg_info
            current_dir = os.getcwd()
            os.chdir(str(dependency.full_path))

            try:
                cwd = dependency.full_path
                venv = Env.get(NullIO(), cwd=cwd)
                venv.run("python", "setup.py", "egg_info")
            except EnvCommandError:
                result = SetupReader.read_from_directory(dependency.full_path)
                if not result["name"]:
                    # The name could not be determined
                    # We use the dependency name
                    result["name"] = dependency.name

                if not result["version"]:
                    # The version could not be determined
                    # so we raise an error since it is mandatory
                    raise RuntimeError(
                        "Unable to retrieve the package version for {}".format(
                            dependency.path))

                package_name = result["name"]
                package_version = result["version"]
                python_requires = result["python_requires"]
                if python_requires is None:
                    python_requires = "*"

                package_summary = ""

                requires = ""
                for dep in result["install_requires"]:
                    requires += dep + "\n"

                if result["extras_require"]:
                    requires += "\n"

                for extra_name, deps in result["extras_require"].items():
                    requires += "[{}]\n".format(extra_name)

                    for dep in deps:
                        requires += dep + "\n"

                    requires += "\n"

                reqs = parse_requires(requires)
            else:
                os.chdir(current_dir)
                # 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.
                if PY35:
                    egg_info = next(
                        Path(p) for p in glob.glob(
                            os.path.join(str(dependency.full_path), "**",
                                         "*.egg-info"),
                            recursive=True,
                        ))
                else:
                    egg_info = next(dependency.full_path.glob("**/*.egg-info"))

                meta = pkginfo.UnpackedSDist(str(egg_info))
                package_name = meta.name
                package_version = meta.version
                package_summary = meta.summary
                python_requires = meta.requires_python

                if meta.requires_dist:
                    reqs = list(meta.requires_dist)
                else:
                    reqs = []
                    requires = egg_info / "requires.txt"
                    if requires.exists():
                        with requires.open() as f:
                            reqs = parse_requires(f.read())
            finally:
                os.chdir(current_dir)

            package = Package(package_name, package_version)

            if dependency.name != package.name:
                # For now, the dependency's name must match the actual package's name
                raise RuntimeError(
                    "The dependency name for {} does not match the actual package's name: {}"
                    .format(dependency.name, package.name))

            package.description = package_summary

            for req in reqs:
                dep = dependency_from_pep_508(req)
                if dep.in_extras:
                    for extra in dep.in_extras:
                        if extra not in package.extras:
                            package.extras[extra] = []

                        package.extras[extra].append(dep)

                if not dep.is_optional():
                    package.requires.append(dep)

            if python_requires:
                package.python_versions = python_requires

        package.source_type = "directory"
        package.source_url = dependency.path.as_posix()

        for extra in dependency.extras:
            if extra in package.extras:
                for dep in package.extras[extra]:
                    dep.activate()

                package.requires += package.extras[extra]

        return [package]
예제 #15
0
    def search_for_vcs(self,
                       dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != 'git':
            raise ValueError('Unsupported VCS dependency {}'.format(
                dependency.vcs))

        tmp_dir = Path(
            mkdtemp(prefix='pypoetry-git-{}'.format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / 'pyproject.toml')
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read(True)
                has_poetry = ('tool' in pyproject_content
                              and 'poetry' in pyproject_content['tool'])

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content['tool']['poetry']

                name = info['name']
                version = info['version']
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info['dependencies'].items():
                    if req_name == 'python':
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run('python', 'setup.py', 'egg_info')

                    egg_info = list(tmp_dir.glob('*.egg-info'))[0]

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / 'requires.txt'
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        package.requires.append(dependency_from_pep_508(req))
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = 'git'
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        return [package]
예제 #16
0
    def package(
        self,
        name,  # type: str
        version,  # type: str
        extras=None,  # type: (Union[list, None])
    ):  # type: (...) -> Union[Package, None]
        if extras is None:
            extras = []

        release_info = self.get_release_info(name, version)
        package = Package(name, version, version)
        requires_dist = release_info["requires_dist"] or []
        for req in requires_dist:
            try:
                dependency = dependency_from_pep_508(req)
            except InvalidMarker:
                # Invalid marker
                # We strip the markers hoping for the best
                req = req.split(";")[0]

                dependency = dependency_from_pep_508(req)
            except ValueError:
                # Likely unable to parse constraint so we skip it
                self._log(
                    "Invalid constraint ({}) found in {}-{} dependencies, "
                    "skipping".format(req, package.name, package.version),
                    level="debug",
                )
                continue

            if dependency.extras:
                for extra in dependency.extras:
                    if extra not in package.extras:
                        package.extras[extra] = []

                    package.extras[extra].append(dependency)

            if not dependency.is_optional():
                package.requires.append(dependency)

        # Adding description
        package.description = release_info.get("summary", "")

        if release_info["requires_python"]:
            package.python_versions = release_info["requires_python"]

        if release_info["platform"]:
            package.platform = release_info["platform"]

        # Adding hashes information
        package.hashes = release_info["digests"]

        # Activate extra dependencies
        for extra in extras:
            if extra in package.extras:
                for dep in package.extras[extra]:
                    dep.activate()

                package.requires += package.extras[extra]

        return package
예제 #17
0
파일: provider.py 프로젝트: oca159/poetry
    def search_for_vcs(self,
                       dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != 'git':
            raise ValueError('Unsupported VCS dependency {}'.format(
                dependency.vcs))

        tmp_dir = Path(
            mkdtemp(prefix='pypoetry-git-{}'.format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / 'pyproject.toml')
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read(True)
                has_poetry = ('tool' in pyproject_content
                              and 'poetry' in pyproject_content['tool'])

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content['tool']['poetry']

                name = info['name']
                version = info['version']
                package = Package(name, version, version)
                for req_name, req_constraint in info['dependencies'].items():
                    if req_name == 'python':
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv = Venv.create(self._io)
                    output = venv.run('python', 'setup.py', '--name',
                                      '--version')
                    output = output.split('\n')
                    name = output[-3]
                    version = output[-2]
                    package = Package(name, version, version)
                    # Figure out a way to get requirements
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = 'git'
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        return [package]
예제 #18
0
    def package(self,
                name,        # type: str
                version,     # type: str
                extras=None  # type: (Union[list, None])
                ):  # type: (...) -> Union[Package, None]
        try:
            index = self._packages.index(Package(name, version, version))

            return self._packages[index]
        except ValueError:
            if extras is None:
                extras = []

            release_info = self.get_release_info(name, version)
            if (
                self._fallback
                and release_info['requires_dist'] is None
                and not release_info['requires_python']
                and '_fallback' not in release_info
            ):
                # Force cache update
                self._log(
                    'No dependencies found, downloading archives',
                    level='debug'
                )
                self._cache.forget('{}:{}'.format(name, version))
                release_info = self.get_release_info(name, version)

            package = Package(name, version, version)
            requires_dist = release_info['requires_dist'] or []
            for req in requires_dist:
                try:
                    dependency = dependency_from_pep_508(req)
                except InvalidMarker:
                    # Invalid marker
                    # We strip the markers hoping for the best
                    req = req.split(';')[0]

                    dependency = dependency_from_pep_508(req)
                except ValueError:
                    # Likely unable to parse constraint so we skip it
                    self._log(
                        'Invalid constraint ({}) found in {}-{} dependencies, '
                        'skipping'.format(
                            req, package.name, package.version
                        ),
                        level='debug'
                    )
                    continue

                if dependency.extras:
                    for extra in dependency.extras:
                        if extra not in package.extras:
                            package.extras[extra] = []

                        package.extras[extra].append(dependency)

                if not dependency.is_optional():
                    package.requires.append(dependency)

            # Adding description
            package.description = release_info.get('summary', '')

            if release_info['requires_python']:
                package.python_versions = release_info['requires_python']

            if release_info['platform']:
                package.platform = release_info['platform']

            # Adding hashes information
            package.hashes = release_info['digests']

            # Activate extra dependencies
            for extra in extras:
                if extra in package.extras:
                    for dep in package.extras[extra]:
                        dep.activate()

                    package.requires += package.extras[extra]

            self._packages.append(package)

            return package
예제 #19
0
    def search_for_vcs(self, dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(dependency.vcs))

        tmp_dir = Path(mkdtemp(prefix="pypoetry-git-{}".format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / "pyproject.toml")
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read()
                has_poetry = (
                    "tool" in pyproject_content
                    and "poetry" in pyproject_content["tool"]
                )

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content["tool"]["poetry"]

                name = info["name"]
                version = info["version"]
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info["dependencies"].items():
                    if req_name == "python":
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run("python", "setup.py", "egg_info")

                    # 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.
                    if PY35:
                        egg_info = next(
                            Path(p)
                            for p in glob.glob(
                                os.path.join(str(tmp_dir), "**", "*.egg-info"),
                                recursive=True,
                            )
                        )
                    else:
                        egg_info = next(tmp_dir.glob("**/*.egg-info"))

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / "requires.txt"
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        dep = dependency_from_pep_508(req)
                        if dep.in_extras:
                            for extra in dep.in_extras:
                                if extra not in package.extras:
                                    package.extras[extra] = []

                                package.extras[extra].append(dep)

                        package.requires.append(dep)
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = "git"
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        if dependency.name != package.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}".format(
                    dependency.name, package.name
                )
            )

        if dependency.extras:
            for extra in dependency.extras:
                if extra in package.extras:
                    for dep in package.extras[extra]:
                        dep.activate()

        return [package]
예제 #20
0
    def get_package_from_directory(
            cls,
            directory,
            name=None):  # type: (Path, Optional[str]) -> Package
        supports_poetry = False
        pyproject = directory.joinpath("pyproject.toml")
        if pyproject.exists():
            pyproject = TomlFile(pyproject)
            pyproject_content = pyproject.read()
            supports_poetry = ("tool" in pyproject_content
                               and "poetry" in pyproject_content["tool"])

        if supports_poetry:
            poetry = Factory().create_poetry(directory)

            pkg = poetry.package
            package = Package(pkg.name, pkg.version)

            for dep in pkg.requires:
                if not dep.is_optional():
                    package.requires.append(dep)

            for extra, deps in pkg.extras.items():
                if extra not in package.extras:
                    package.extras[extra] = []

                for dep in deps:
                    package.extras[extra].append(dep)

            package.python_versions = pkg.python_versions
        else:
            # Execute egg_info
            current_dir = os.getcwd()
            os.chdir(str(directory))

            try:
                cwd = directory
                venv = EnvManager().get(cwd)
                venv.run("python", "setup.py", "egg_info")
            except EnvCommandError:
                result = SetupReader.read_from_directory(directory)
                if not result["name"]:
                    # The name could not be determined
                    # We use the dependency name
                    result["name"] = name

                if not result["version"]:
                    # The version could not be determined
                    # so we raise an error since it is mandatory
                    raise RuntimeError(
                        "Unable to retrieve the package version for {}".format(
                            directory))

                package_name = result["name"]
                package_version = result["version"]
                python_requires = result["python_requires"]
                if python_requires is None:
                    python_requires = "*"

                package_summary = ""

                requires = ""
                for dep in result["install_requires"]:
                    requires += dep + "\n"

                if result["extras_require"]:
                    requires += "\n"

                for extra_name, deps in result["extras_require"].items():
                    requires += "[{}]\n".format(extra_name)

                    for dep in deps:
                        requires += dep + "\n"

                    requires += "\n"

                reqs = parse_requires(requires)
            else:
                os.chdir(current_dir)
                # 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.
                if PY35:
                    egg_info = next(
                        Path(p) for p in glob.glob(
                            os.path.join(str(directory), "**", "*.egg-info"),
                            recursive=True,
                        ))
                else:
                    egg_info = next(directory.glob("**/*.egg-info"))

                meta = pkginfo.UnpackedSDist(str(egg_info))
                package_name = meta.name
                package_version = meta.version
                package_summary = meta.summary
                python_requires = meta.requires_python

                if meta.requires_dist:
                    reqs = list(meta.requires_dist)
                else:
                    reqs = []
                    requires = egg_info / "requires.txt"
                    if requires.exists():
                        with requires.open(encoding="utf-8") as f:
                            reqs = parse_requires(f.read())
            finally:
                os.chdir(current_dir)

            package = Package(package_name, package_version)
            package.description = package_summary

            for req in reqs:
                dep = dependency_from_pep_508(req)
                if dep.in_extras:
                    for extra in dep.in_extras:
                        if extra not in package.extras:
                            package.extras[extra] = []

                        package.extras[extra].append(dep)

                if not dep.is_optional():
                    package.requires.append(dep)

            if python_requires:
                package.python_versions = python_requires

        if name and name != package.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}"
                .format(name, package.name))

        package.source_type = "directory"
        package.source_url = directory.as_posix()

        return package
예제 #21
0
    def search_for_vcs(self,
                       dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(
                dependency.vcs))

        tmp_dir = Path(
            mkdtemp(prefix="pypoetry-git-{}".format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / "pyproject.toml")
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read()
                has_poetry = ("tool" in pyproject_content
                              and "poetry" in pyproject_content["tool"])

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content["tool"]["poetry"]

                name = info["name"]
                version = info["version"]
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info["dependencies"].items():
                    if req_name == "python":
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run("python", "setup.py", "egg_info")

                    # 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.
                    if PY35:
                        egg_info = next(
                            Path(p) for p in glob.glob(
                                os.path.join(str(tmp_dir), "**", "*.egg-info"),
                                recursive=True,
                            ))
                    else:
                        egg_info = next(tmp_dir.glob("**/*.egg-info"))

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / "requires.txt"
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        dep = dependency_from_pep_508(req)
                        if dep.in_extras:
                            for extra in dep.in_extras:
                                if extra not in package.extras:
                                    package.extras[extra] = []

                                package.extras[extra].append(dep)

                        package.requires.append(dep)
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = "git"
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        if dependency.name != package.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}"
                .format(dependency.name, package.name))

        if dependency.extras:
            for extra in dependency.extras:
                if extra in package.extras:
                    for dep in package.extras[extra]:
                        dep.activate()

        return [package]
예제 #22
0
    def package(
            self,
            name,  # type: str
            version,  # type: str
            extras=None,  # type: (Union[list, None])
    ):  # type: (...) -> Union[Package, None]
        if extras is None:
            extras = []

        release_info = self.get_release_info(name, version)
        package = Package(name, version, version)
        requires_dist = release_info["requires_dist"] or []
        for req in requires_dist:
            try:
                dependency = dependency_from_pep_508(req)
            except InvalidMarker:
                # Invalid marker
                # We strip the markers hoping for the best
                req = req.split(";")[0]

                dependency = dependency_from_pep_508(req)
            except ValueError:
                # Likely unable to parse constraint so we skip it
                self._log(
                    "Invalid constraint ({}) found in {}-{} dependencies, "
                    "skipping".format(req, package.name, package.version),
                    level="debug",
                )
                continue

            if dependency.in_extras:
                for extra in dependency.in_extras:
                    if extra not in package.extras:
                        package.extras[extra] = []

                    package.extras[extra].append(dependency)

            if not dependency.is_optional():
                package.requires.append(dependency)

        # Adding description
        package.description = release_info.get("summary", "")

        if release_info["requires_python"]:
            package.python_versions = release_info["requires_python"]

        if release_info["platform"]:
            package.platform = release_info["platform"]

        # Adding hashes information
        package.hashes = release_info["digests"]

        # Activate extra dependencies
        for extra in extras:
            if extra in package.extras:
                for dep in package.extras[extra]:
                    dep.activate()

                package.requires += package.extras[extra]

        return package
예제 #23
0
    def __init__(
            self,
            path,  # type: Path
            category='main',  # type: str
            optional=False,  # type: bool
            base=None,  # type: Path
            develop=False  # type: bool
    ):
        from . import dependency_from_pep_508

        self._path = path
        self._base = base
        self._full_path = path
        self._develop = develop

        if self._base and not self._path.is_absolute():
            self._full_path = self._base / self._path

        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 dertermine actions
        setup = self._full_path / 'setup.py'
        pyproject = TomlFile(self._full_path / 'pyproject.toml')
        has_poetry = False
        if pyproject.exists():
            pyproject_content = pyproject.read(True)
            has_poetry = ('tool' in pyproject_content
                          and 'poetry' in pyproject_content['tool'])

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

        if has_poetry:
            from poetry.masonry.builders import SdistBuilder
            from poetry.poetry import Poetry

            poetry = Poetry.create(self._full_path)
            builder = SdistBuilder(poetry, NullVenv(), NullIO())

            with setup.open('w') as f:
                f.write(decode(builder.build_setup()))

            self._package = poetry.package
        else:
            from poetry.packages import Package
            # Execute egg_info
            current_dir = os.getcwd()
            os.chdir(str(self._full_path))

            try:
                cwd = base
                venv = Venv.create(NullIO(), cwd=cwd)
                venv.run('python', 'setup.py', 'egg_info')
            finally:
                os.chdir(current_dir)

            egg_info = list(self._full_path.glob('*.egg-info'))[0]

            meta = pkginfo.UnpackedSDist(str(egg_info))

            if meta.requires_dist:
                reqs = list(meta.requires_dist)
            else:
                reqs = []
                requires = egg_info / 'requires.txt'
                if requires.exists():
                    with requires.open() as f:
                        reqs = parse_requires(f.read())

            package = Package(meta.name, meta.version)
            package.description = meta.summary

            for req in reqs:
                package.requires.append(dependency_from_pep_508(req))

            if meta.requires_python:
                package.python_versions = meta.requires_python

            if meta.platforms:
                platforms = [
                    p for p in meta.platforms if p.lower() != 'unknown'
                ]
                if platforms:
                    package.platform = ' || '.join(platforms)

            self._package = package

        self._package.source_type = 'directory'
        self._package.source_reference = str(self._path)

        super(DirectoryDependency, self).__init__(self._package.name,
                                                  self._package.version,
                                                  category=category,
                                                  optional=optional,
                                                  allows_prereleases=True)