예제 #1
0
    def populate_requirement_set(requirement_set, args, options, finder,
                                 session, name, wheel_cache):
        """
        Marshal cmd line args into a requirement set.
        """
        for filename in options.constraints:
            for req in parse_requirements(filename,
                                          constraint=True,
                                          finder=finder,
                                          options=options,
                                          session=session,
                                          wheel_cache=wheel_cache):
                requirement_set.add_requirement(req)

        for req in args:
            requirement_set.add_requirement(
                InstallRequirement.from_line(req,
                                             None,
                                             isolated=options.isolated_mode,
                                             wheel_cache=wheel_cache))

        for req in options.editables:
            requirement_set.add_requirement(
                InstallRequirement.from_editable(
                    req,
                    default_vcs=options.default_vcs,
                    isolated=options.isolated_mode,
                    wheel_cache=wheel_cache))

        found_req_in_file = False
        for filename in options.requirements:
            for req in parse_requirements(filename,
                                          finder=finder,
                                          options=options,
                                          session=session,
                                          wheel_cache=wheel_cache):
                found_req_in_file = True
                requirement_set.add_requirement(req)
        # If --require-hashes was a line in a requirements file, tell
        # RequirementSet about it:
        requirement_set.require_hashes = options.require_hashes

        if not (args or options.editables or found_req_in_file):
            opts = {'name': name}
            if options.find_links:
                msg = ('You must give at least one requirement to '
                       '%(name)s (maybe you meant "pip %(name)s '
                       '%(links)s"?)' %
                       dict(opts, links=' '.join(options.find_links)))
            else:
                msg = ('You must give at least one requirement '
                       'to %(name)s (see "pip help %(name)s")' % opts)
            logger.warning(msg)
예제 #2
0
 def run(self, options, args):
     with self._build_session(options) as session:
         format_control = pip9.index.FormatControl(set(), set())
         wheel_cache = WheelCache(options.cache_dir, format_control)
         requirement_set = RequirementSet(
             build_dir=None,
             src_dir=None,
             download_dir=None,
             isolated=options.isolated_mode,
             session=session,
             wheel_cache=wheel_cache,
         )
         for name in args:
             requirement_set.add_requirement(
                 InstallRequirement.from_line(
                     name, isolated=options.isolated_mode,
                     wheel_cache=wheel_cache
                 )
             )
         for filename in options.requirements:
             for req in parse_requirements(
                     filename,
                     options=options,
                     session=session,
                     wheel_cache=wheel_cache):
                 requirement_set.add_requirement(req)
         if not requirement_set.has_requirements:
             raise InstallationError(
                 'You must give at least one requirement to %(name)s (see '
                 '"pip help %(name)s")' % dict(name=self.name)
             )
         requirement_set.uninstall(auto_confirm=options.yes)
예제 #3
0
파일: utils.py 프로젝트: cnmade/pipenv
def actually_resolve_reps(deps, index_lookup, markers_lookup, project, sources,
                          verbose, clear, pre):
    from pip9 import basecommand, req
    from pip9._vendor import requests as pip_requests

    class PipCommand(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 = 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 req.parse_requirements(t, session=pip_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
예제 #4
0
def cli(verbose, dry_run, pre, rebuild, find_links, index_url, extra_index_url,
        cert, client_cert, trusted_host, header, index, emit_trusted_host,
        annotate, upgrade, upgrade_packages, output_file, allow_unsafe,
        generate_hashes, src_files, max_rounds):
    """Compiles requirements.txt from requirements.in specs."""
    log.verbose = verbose

    if len(src_files) == 0:
        if os.path.exists(DEFAULT_REQUIREMENTS_FILE):
            src_files = (DEFAULT_REQUIREMENTS_FILE, )
        elif os.path.exists('setup.py'):
            src_files = ('setup.py', )
            if not output_file:
                output_file = 'requirements.txt'
        else:
            raise click.BadParameter(("If you do not specify an input file, "
                                      "the default is {} or setup.py"
                                      ).format(DEFAULT_REQUIREMENTS_FILE))

    if len(src_files) == 1 and src_files[0] == '-':
        if not output_file:
            raise click.BadParameter(
                '--output-file is required if input is from stdin')

    if len(src_files) > 1 and not output_file:
        raise click.BadParameter(
            '--output-file is required if two or more input files are given.')

    if output_file:
        dst_file = output_file
    else:
        base_name = src_files[0].rsplit('.', 1)[0]
        dst_file = base_name + '.txt'

    if upgrade and upgrade_packages:
        raise click.BadParameter(
            'Only one of --upgrade or --upgrade-package can be provided as an argument.'
        )

    ###
    # Setup
    ###

    pip_command = get_pip_command()

    pip_args = []
    if find_links:
        for link in find_links:
            pip_args.extend(['-f', link])
    if index_url:
        pip_args.extend(['-i', index_url])
    if extra_index_url:
        for extra_index in extra_index_url:
            pip_args.extend(['--extra-index-url', extra_index])
    if cert:
        pip_args.extend(['--cert', cert])
    if client_cert:
        pip_args.extend(['--client-cert', client_cert])
    if pre:
        pip_args.extend(['--pre'])
    if trusted_host:
        for host in trusted_host:
            pip_args.extend(['--trusted-host', host])

    pip_options, _ = pip_command.parse_args(pip_args)

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

    # Proxy with a LocalRequirementsRepository if --upgrade is not specified
    # (= default invocation)
    if not upgrade and os.path.exists(dst_file):
        ireqs = parse_requirements(dst_file,
                                   finder=repository.finder,
                                   session=repository.session,
                                   options=pip_options)
        # Exclude packages from --upgrade-package/-P from the existing pins: We want to upgrade.
        upgrade_pkgs_key = {
            key_from_req(InstallRequirement.from_line(pkg).req)
            for pkg in upgrade_packages
        }
        existing_pins = {
            key_from_req(ireq.req): ireq
            for ireq in ireqs if is_pinned_requirement(ireq)
            and key_from_req(ireq.req) not in upgrade_pkgs_key
        }
        repository = LocalRequirementsRepository(existing_pins, repository)

    log.debug('Using indexes:')
    # remove duplicate index urls before processing
    repository.finder.index_urls = list(dedup(repository.finder.index_urls))
    for index_url in repository.finder.index_urls:
        log.debug('  {}'.format(index_url))

    if repository.finder.find_links:
        log.debug('')
        log.debug('Configuration:')
        for find_link in repository.finder.find_links:
            log.debug('  -f {}'.format(find_link))

    ###
    # Parsing/collecting initial requirements
    ###

    constraints = []
    for src_file in src_files:
        is_setup_file = os.path.basename(src_file) == 'setup.py'
        if is_setup_file or src_file == '-':
            # pip requires filenames and not files. Since we want to support
            # piping from stdin, we need to briefly save the input from stdin
            # to a temporary file and have pip read that.  also used for
            # reading requirements from install_requires in setup.py.
            tmpfile = tempfile.NamedTemporaryFile(mode='wt', delete=False)
            if is_setup_file:
                from distutils.core import run_setup
                dist = run_setup(src_file)
                tmpfile.write('\n'.join(dist.install_requires))
            else:
                tmpfile.write(sys.stdin.read())
            tmpfile.flush()
            constraints.extend(
                parse_requirements(tmpfile.name,
                                   finder=repository.finder,
                                   session=repository.session,
                                   options=pip_options))
        else:
            constraints.extend(
                parse_requirements(src_file,
                                   finder=repository.finder,
                                   session=repository.session,
                                   options=pip_options))

    # Filter out pip environment markers which do not match (PEP496)
    constraints = [
        req for req in constraints
        if req.markers is None or req.markers.evaluate()
    ]

    # Check the given base set of constraints first
    Resolver.check_constraints(constraints)

    try:
        resolver = Resolver(constraints,
                            repository,
                            prereleases=pre,
                            clear_caches=rebuild,
                            allow_unsafe=allow_unsafe)
        results = resolver.resolve(max_rounds=max_rounds)
        if generate_hashes:
            hashes = resolver.resolve_hashes(results)
        else:
            hashes = None
    except PipToolsError as e:
        log.error(str(e))
        sys.exit(2)

    log.debug('')

    ##
    # Output
    ##

    # Compute reverse dependency annotations statically, from the
    # dependency cache that the resolver has populated by now.
    #
    # TODO (1a): reverse deps for any editable package are lost
    #            what SHOULD happen is that they are cached in memory, just
    #            not persisted to disk!
    #
    # TODO (1b): perhaps it's easiest if the dependency cache has an API
    #            that could take InstallRequirements directly, like:
    #
    #                cache.set(ireq, ...)
    #
    #            then, when ireq is editable, it would store in
    #
    #              editables[egg_name][link_without_fragment] = deps
    #              editables['pip-tools']['git+...ols.git@future'] = {'click>=3.0', 'six'}
    #
    #            otherwise:
    #
    #              self[as_name_version_tuple(ireq)] = {'click>=3.0', 'six'}
    #
    reverse_dependencies = None
    if annotate:
        reverse_dependencies = resolver.reverse_dependencies(results)

    writer = OutputWriter(src_files,
                          dst_file,
                          dry_run=dry_run,
                          emit_header=header,
                          emit_index=index,
                          emit_trusted_host=emit_trusted_host,
                          annotate=annotate,
                          generate_hashes=generate_hashes,
                          default_index_url=repository.DEFAULT_INDEX_URL,
                          index_urls=repository.finder.index_urls,
                          trusted_hosts=pip_options.trusted_hosts,
                          format_control=repository.finder.format_control)
    writer.write(results=results,
                 unsafe_requirements=resolver.unsafe_constraints,
                 reverse_dependencies=reverse_dependencies,
                 primary_packages={
                     key_from_req(ireq.req)
                     for ireq in constraints if not ireq.constraint
                 },
                 markers={
                     key_from_req(ireq.req): ireq.markers
                     for ireq in constraints if ireq.markers
                 },
                 hashes=hashes,
                 allow_unsafe=allow_unsafe)

    if dry_run:
        log.warning('Dry-run, so nothing updated.')