Пример #1
0
    def test_find_dependencies_simple(self):
        """A simple scenario for finding dependencies."""
        pkgmgr = FakePackageManager(simple)

        # Given a simple top-level configuration (just "foo")...
        spec_set = SpecSet()
        spec_set.add_spec('foo')

        # ...let's see what this leads to
        resolver = Resolver(spec_set, pkgmgr)
        self.assertItemsEqual(
                ['foo==0.1', 'bar==1.2', 'qux==0.1', 'simplejson==2.4.0'],
                map(str, resolver.resolve()))
Пример #2
0
    def on_end(self, event):
        # Our config object
        python_config = event.config["python"]

        # Pip / PyPI
        pip_command = get_pip_command()
        pip_options, _ = pip_command.parse_args([])
        session = pip_command._build_session(pip_options)
        repository = PyPIRepository(pip_options, session)

        for extra in itertools.chain((None,), python_config.get_extras()):
            requirements_file = "requirements{}.txt".format("-" + extra if extra else "")

            if python_config.override_requirements or not os.path.exists(requirements_file):
                tmpfile = tempfile.NamedTemporaryFile(mode="wt", delete=False)
                if extra:
                    tmpfile.write("\n".join(python_config.get_requirements(extra=extra)))
                else:
                    tmpfile.write("\n".join(python_config.get_requirements()))
                tmpfile.flush()
                constraints = list(
                    parse_requirements(
                        tmpfile.name, finder=repository.finder, session=repository.session, options=pip_options
                    )
                )
                resolver = Resolver(constraints, repository, prereleases=False, clear_caches=False, allow_unsafe=False)

                self.render_file_inline(
                    requirements_file,
                    "\n".join(
                        (
                            "-e .{}".format("[" + extra + "]" if extra else ""),
                            *(("-r requirements.txt",) if extra else ()),
                            *python_config.get_vendors(extra=extra),
                            *sorted(
                                format_requirement(req)
                                for req in resolver.resolve(max_rounds=10)
                                if req.name != python_config.get("name")
                            ),
                        )
                    ),
                    override=python_config.override_requirements,
                )
Пример #3
0
def resolve_deps(deps, which, which_pip, project, sources=None, verbose=False, python=False, clear=False, pre=False):
    """Given a list of dependencies, return a resolved list of dependencies,
    using pip-tools -- and their hashes, using the warehouse API / pip.
    """

    index_lookup = {}
    markers_lookup = {}

    python_path = which('python')

    with HackedPythonVersion(python_version=python, python_path=python_path):

        class PipCommand(pip.basecommand.Command):
            """Needed for pip-tools."""
            name = 'PipCommand'

        constraints = []

        for dep in deps:
            t = tempfile.mkstemp(prefix='pipenv-', suffix='-requirement.txt')[1]
            with open(t, 'w') as f:
                f.write(dep)

            if dep.startswith('-e '):
                constraint = pip.req.InstallRequirement.from_editable(dep[len('-e '):])
            else:
                constraint = [c for c in pip.req.parse_requirements(t, session=pip._vendor.requests)][0]
                # extra_constraints = []

            if ' -i ' in dep:
                index_lookup[constraint.name] = project.get_source(url=dep.split(' -i ')[1]).get('name')

            if constraint.markers:
                markers_lookup[constraint.name] = str(constraint.markers).replace('"', "'")

            constraints.append(constraint)

        pip_command = get_pip_command()

        pip_args = []

        if sources:
            pip_args = prepare_pip_source_args(sources, pip_args)

        if verbose:
            print('Using pip: {0}'.format(' '.join(pip_args)))

        pip_options, _ = pip_command.parse_args(pip_args)

        session = pip_command._build_session(pip_options)
        pypi = PyPIRepository(pip_options=pip_options, session=session)

        if verbose:
            logging.log.verbose = True

        results = []
        resolved_tree = set()

        resolver = Resolver(constraints=constraints, repository=pypi, clear_caches=clear, prereleases=pre)
        # pre-resolve instead of iterating to avoid asking pypi for hashes of editable packages
        try:
            resolved_tree.update(resolver.resolve(max_rounds=PIPENV_MAX_ROUNDS))
        except (NoCandidateFound, DistributionNotFound, HTTPError) as e:
            click.echo(
                '{0}: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.\n  '
                'You can use {1} to bypass this mechanism, then run {2} to inspect the situation.'
                ''.format(
                    crayons.red('Warning', bold=True),
                    crayons.red('$ pipenv install --skip-lock'),
                    crayons.red('$ pipenv graph')
                ),
                err=True)

            click.echo(crayons.blue(e))

            if 'no version found at all' in str(e):
                click.echo(crayons.blue('Please check your version specifier and version number. See PEP440 for more information.'))

            sys.exit(1)

    for result in resolved_tree:
        if not result.editable:
            name = pep423_name(result.name)
            version = clean_pkg_version(result.specifier)
            index = index_lookup.get(result.name)

            if not markers_lookup.get(result.name):
                markers = str(result.markers) if result.markers and 'extra' not in str(result.markers) else None
            else:
                markers = markers_lookup.get(result.name)

            collected_hashes = []
            if 'python.org' in '|'.join([source['url'] for source in sources]):
                try:
                    # Grab the hashes from the new warehouse API.
                    r = requests.get('https://pypi.org/pypi/{0}/json'.format(name), timeout=10)
                    api_releases = r.json()['releases']

                    cleaned_releases = {}
                    for api_version, api_info in api_releases.items():
                        cleaned_releases[clean_pkg_version(api_version)] = api_info

                    for release in cleaned_releases[version]:
                        collected_hashes.append(release['digests']['sha256'])

                    collected_hashes = ['sha256:' + s for s in collected_hashes]

                    # Collect un-collectable hashes.
                    if not collected_hashes:
                        collected_hashes = list(list(resolver.resolve_hashes([result]).items())[0][1])

                except (ValueError, KeyError):
                    if verbose:
                        print('Error fetching {}'.format(name))

            d = {'name': name, 'version': version, 'hashes': collected_hashes}

            if index:
                d.update({'index': index})

            if markers:
                d.update({'markers': markers.replace('"', "'")})

            results.append(d)

    return results
Пример #4
0
def actually_resolve_reps(deps, index_lookup, markers_lookup, project, sources, verbose, clear, pre):

    class PipCommand(pip.basecommand.Command):
        """Needed for pip-tools."""
        name = 'PipCommand'

    constraints = []

    for dep in deps:
        t = tempfile.mkstemp(prefix='pipenv-', suffix='-requirement.txt')[1]
        with open(t, 'w') as f:
            f.write(dep)

        if dep.startswith('-e '):
            constraint = pip.req.InstallRequirement.from_editable(dep[len('-e '):])
        else:
            constraint = [c for c in pip.req.parse_requirements(t, session=pip._vendor.requests)][0]
            # extra_constraints = []

        if ' -i ' in dep:
            index_lookup[constraint.name] = project.get_source(url=dep.split(' -i ')[1]).get('name')

        if constraint.markers:
            markers_lookup[constraint.name] = str(constraint.markers).replace('"', "'")

        constraints.append(constraint)

    pip_command = get_pip_command()

    pip_args = []

    if sources:
        pip_args = prepare_pip_source_args(sources, pip_args)

    if verbose:
        print('Using pip: {0}'.format(' '.join(pip_args)))

    pip_options, _ = pip_command.parse_args(pip_args)

    session = pip_command._build_session(pip_options)
    pypi = PyPIRepository(pip_options=pip_options, session=session)

    if verbose:
        logging.log.verbose = True


    resolved_tree = set()

    resolver = Resolver(constraints=constraints, repository=pypi, clear_caches=clear, prereleases=pre)
    # pre-resolve instead of iterating to avoid asking pypi for hashes of editable packages
    try:
        resolved_tree.update(resolver.resolve(max_rounds=PIPENV_MAX_ROUNDS))
    except (NoCandidateFound, DistributionNotFound, HTTPError) as e:
        click.echo(
            '{0}: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.\n  '
            'You can use {1} to bypass this mechanism, then run {2} to inspect the situation.'
            ''.format(
                crayons.red('Warning', bold=True),
                crayons.red('$ pipenv install --skip-lock'),
                crayons.red('$ pipenv graph')
            ),
            err=True)

        click.echo(crayons.blue(e))

        if 'no version found at all' in str(e):
            click.echo(crayons.blue('Please check your version specifier and version number. See PEP440 for more information.'))

        raise RuntimeError

    return resolved_tree
Пример #5
0
def actually_resolve_reps(deps, index_lookup, markers_lookup, project, sources,
                          verbose, clear, pre):
    import pip

    class PipCommand(pip.basecommand.Command):
        """Needed for pip-tools."""
        name = 'PipCommand'

    constraints = []

    req_dir = tempfile.mkdtemp(prefix='pipenv-', suffix='-requirements')
    for dep in deps:
        if dep:
            if dep.startswith('-e '):
                constraint = pip.req.InstallRequirement.from_editable(
                    dep[len('-e '):])
            else:
                fd, t = tempfile.mkstemp(prefix='pipenv-',
                                         suffix='-requirement.txt',
                                         dir=req_dir)
                with os.fdopen(fd, 'w') as f:
                    f.write(dep)

                constraint = [
                    c for c in pip.req.parse_requirements(
                        t, session=pip._vendor.requests)
                ][0]

                # extra_constraints = []

            if ' -i ' in dep:
                index_lookup[constraint.name] = project.get_source(
                    url=dep.split(' -i ')[1]).get('name')

            if constraint.markers:
                markers_lookup[constraint.name] = str(
                    constraint.markers).replace('"', "'")

            constraints.append(constraint)

    rmtree(req_dir)

    pip_command = get_pip_command()

    pip_args = []

    if sources:
        pip_args = prepare_pip_source_args(sources, pip_args)

    if verbose:
        print('Using pip: {0}'.format(' '.join(pip_args)))

    pip_options, _ = pip_command.parse_args(pip_args)

    session = pip_command._build_session(pip_options)
    pypi = PyPIRepository(pip_options=pip_options,
                          use_json=True,
                          session=session)

    if verbose:
        logging.log.verbose = True
        piptools_logging.log.verbose = True

    resolved_tree = set()

    resolver = Resolver(constraints=constraints,
                        repository=pypi,
                        clear_caches=clear,
                        prereleases=pre)
    # pre-resolve instead of iterating to avoid asking pypi for hashes of editable packages
    try:
        resolved_tree.update(resolver.resolve(max_rounds=PIPENV_MAX_ROUNDS))
    except (NoCandidateFound, DistributionNotFound, HTTPError) as e:
        click.echo(
            '{0}: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.\n  '
            'You can use {1} to bypass this mechanism, then run {2} to inspect the situation.'
            ''.format(crayons.red('Warning', bold=True),
                      crayons.red('$ pipenv install --skip-lock'),
                      crayons.red('$ pipenv graph')),
            err=True)

        click.echo(crayons.blue(str(e)), err=True)

        if 'no version found at all' in str(e):
            click.echo(
                crayons.blue(
                    'Please check your version specifier and version number. See PEP440 for more information.'
                ))

        raise RuntimeError

    return resolved_tree, resolver