def test_should_use_ephemeral_cache__disallow_binaries_and_vcs_checkout( disallow_binaries, expected, ): """ Test that disallowing binaries (e.g. from passing --global-option) causes should_use_ephemeral_cache() to return None for VCS checkouts. """ req = Requirement('pendulum') # Passing a VCS url causes link.is_artifact to return False. link = Link(url='git+https://git.example.com/pendulum.git') req = InstallRequirement( req=req, comes_from=None, constraint=False, editable=False, link=link, source_dir='/tmp/pip-install-9py5m2z1/pendulum', ) assert not req.is_wheel assert not req.link.is_artifact format_control = FormatControl() if disallow_binaries: format_control.disallow_binaries() # The cache_available value doesn't matter for this test. ephem_cache = wheel.should_use_ephemeral_cache( req, format_control=format_control, autobuilding=True, cache_available=True, ) assert ephem_cache is expected
def test_fmt_ctl_matches(): fmt = FormatControl(set(), set()) assert fmt_ctl_formats(fmt, "fred") == frozenset(["source", "binary"]) fmt = FormatControl(set(["fred"]), set()) assert fmt_ctl_formats(fmt, "fred") == frozenset(["source"]) fmt = FormatControl(set(["fred"]), set([":all:"])) assert fmt_ctl_formats(fmt, "fred") == frozenset(["source"]) fmt = FormatControl(set(), set(["fred"])) assert fmt_ctl_formats(fmt, "fred") == frozenset(["binary"]) fmt = FormatControl(set([":all:"]), set(["fred"])) assert fmt_ctl_formats(fmt, "fred") == frozenset(["binary"])
def test_make_link_evaluator( self, allow_yanked, ignore_requires_python, only_binary, expected_formats, ): # Create a test TargetPython that we can check for. target_python = TargetPython(py_version_info=(3, 7)) format_control = FormatControl(set(), only_binary) finder = PackageFinder( search_scope=SearchScope([], []), session=PipSession(), target_python=target_python, allow_yanked=allow_yanked, format_control=format_control, ignore_requires_python=ignore_requires_python, ) # Pass a project_name that will be different from canonical_name. link_evaluator = finder.make_link_evaluator('Twine') assert link_evaluator.project_name == 'Twine' assert link_evaluator._canonical_name == 'twine' assert link_evaluator._allow_yanked == allow_yanked assert link_evaluator._ignore_requires_python == ignore_requires_python assert link_evaluator._formats == expected_formats # Test the _target_python attribute. actual_target_python = link_evaluator._target_python # The target_python attribute should be set as is. assert actual_target_python is target_python # For good measure, check that the attributes weren't reset. assert actual_target_python._given_py_version_info == (3, 7) assert actual_target_python.py_version_info == (3, 7, 0)
def check_dist_restriction(options, check_target=False): """Function for determining if custom platform options are allowed. :param options: The OptionParser options. :param check_target: Whether or not to check if --target is being used. """ dist_restriction_set = any([ options.python_version, options.platform, options.abi, options.implementation, ]) binary_only = FormatControl(set(), {':all:'}) sdist_dependencies_allowed = (options.format_control != binary_only and not options.ignore_dependencies) # Installations or downloads using dist restrictions must not combine # source distributions and dist-specific wheels, as they are not # gauranteed to be locally compatible. if dist_restriction_set and sdist_dependencies_allowed: raise CommandError( "When restricting platform and interpreter constraints using " "--python-version, --platform, --abi, or --implementation, " "either --no-deps must be set, or --only-binary=:all: must be " "set and --no-binary must not be set (or must be set to " ":none:).") if check_target: if dist_restriction_set and not options.target_dir: raise CommandError( "Can not use any platform or abi specific options unless " "installing via '--target'")
def only_binary(): return Option( "--only-binary", dest="format_control", action="callback", callback=_handle_only_binary, type="str", default=FormatControl(set(), set()), help="Do not use source packages. Can be supplied multiple times, and " "each time adds to the existing value. Accepts either :all: to " "disable all source packages, :none: to empty the set, or one or " "more package names with commas between them. Packages without " "binary distributions will fail to install when this option is " "used on them.", )
def no_binary(): return Option( "--no-binary", dest="format_control", action="callback", callback=_handle_no_binary, type="str", default=FormatControl(set(), set()), help="Do not use binary packages. Can be supplied multiple times, and " "each time adds to the existing value. Accepts either :all: to " "disable all binary packages, :none: to empty the set, or one or " "more package names with commas between them. Note that some " "packages are tricky to compile and may fail to install when " "this option is used on them.", )
def test_should_use_ephemeral_cache__issue_6197( base_name, autobuilding, cache_available, expected, ): """ Regression test for: https://github.com/pypa/pip/issues/6197 """ req = make_test_install_req(base_name=base_name) assert not req.is_wheel assert req.link.is_artifact format_control = FormatControl() ephem_cache = wheel.should_use_ephemeral_cache( req, format_control=format_control, autobuilding=autobuilding, cache_available=cache_available, ) assert ephem_cache is expected
def _install_build_reqs(finder, prefix, build_requirements): # NOTE: What follows is not a very good thing. # Eventually, this should move into the BuildEnvironment class and # that should handle all the isolation and sub-process invocation. finder = copy(finder) finder.format_control = FormatControl(set(), set([":all:"])) urls = [ finder.find_requirement( InstallRequirement.from_line(r), upgrade=False).url for r in build_requirements ] args = [ sys.executable, '-m', 'pip', 'install', '--ignore-installed', '--no-user', '--prefix', prefix, ] + list(urls) with open_spinner("Installing build dependencies") as spinner: call_subprocess(args, show_stdout=False, spinner=spinner)
def test_create__format_control(self): """ Test that the format_control attribute is set correctly. """ format_control = FormatControl(set(), {':all:'}) selection_prefs = SelectionPreferences( allow_yanked=True, format_control=format_control, ) finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), ) actual_format_control = finder.format_control assert actual_format_control is format_control # Check that the attributes weren't reset. assert actual_format_control.only_binary == {':all:'}
def _install_build_reqs(self, reqs, prefix): # Local import to avoid circular import (wheel <-> req_install) from pip._internal.req.req_install import InstallRequirement from pip._internal.index import FormatControl # Ignore the --no-binary option when installing the build system, so # we don't recurse trying to build a self-hosting build system. finder = copy.copy(self.finder) finder.format_control = FormatControl(set(), set()) urls = [ finder.find_requirement(InstallRequirement.from_line(r), upgrade=False).url for r in reqs ] args = [ sys.executable, '-m', 'pip', 'install', '--ignore-installed', '--prefix', prefix ] + list(urls) with open_spinner("Installing build dependencies") as spinner: call_subprocess(args, show_stdout=False, spinner=spinner)
def test_should_use_ephemeral_cache__issue_6197( base_name, autobuilding, cache_available, expected, ): """ Regression test for: https://github.com/pypa/pip/issues/6197 """ req = Requirement('pendulum') link_url = ( 'https://files.pythonhosted.org/packages/aa/{base_name}.tar.gz' '#sha256=cf535d36c063575d4752af36df928882b2e0e31541b4482c97d637527' '85f9fcb').format(base_name=base_name) link = Link( url=link_url, comes_from='https://pypi.org/simple/pendulum/', requires_python='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', ) req = InstallRequirement( req=req, comes_from=None, constraint=False, editable=False, link=link, source_dir='/tmp/pip-install-9py5m2z1/pendulum', ) assert not req.is_wheel assert req.link.is_artifact format_control = FormatControl() ephem_cache = wheel.should_use_ephemeral_cache( req, format_control=format_control, autobuilding=autobuilding, cache_available=cache_available, ) assert ephem_cache is expected
def run(self, options, args): options.ignore_installed = True # editable doesn't really make sense for `pip download`, but the bowels # of the RequirementSet code require that property. options.editables = [] if options.python_version: python_versions = [options.python_version] else: python_versions = None dist_restriction_set = any([ options.python_version, options.platform, options.abi, options.implementation, ]) binary_only = FormatControl(set(), {':all:'}) if dist_restriction_set and options.format_control != binary_only: raise CommandError( "--only-binary=:all: must be set and --no-binary must not " "be set (or must be set to :none:) when restricting platform " "and interpreter constraints using --python-version, " "--platform, --abi, or --implementation.") options.src_dir = os.path.abspath(options.src_dir) options.download_dir = normalize_path(options.download_dir) ensure_dir(options.download_dir) with self._build_session(options) as session: finder = self._build_package_finder( options=options, session=session, platform=options.platform, python_versions=python_versions, abi=options.abi, implementation=options.implementation, ) build_delete = (not (options.no_clean or options.build_dir)) if options.cache_dir and not check_path_owner(options.cache_dir): logger.warning( "The directory '%s' or its parent directory is not owned " "by the current user and caching wheels has been " "disabled. check the permissions and owner of that " "directory. If executing pip with sudo, you may want " "sudo's -H flag.", options.cache_dir, ) options.cache_dir = None with TempDirectory(options.build_dir, delete=build_delete, kind="download") as directory: requirement_set = RequirementSet( require_hashes=options.require_hashes, ) self.populate_requirement_set(requirement_set, args, options, finder, session, self.name, None) preparer = RequirementPreparer( build_dir=directory.path, src_dir=options.src_dir, download_dir=options.download_dir, wheel_download_dir=None, progress_bar=options.progress_bar, ) resolver = Resolver( preparer=preparer, finder=finder, session=session, wheel_cache=None, use_user_site=False, upgrade_strategy="to-satisfy-only", force_reinstall=False, ignore_dependencies=options.ignore_dependencies, ignore_requires_python=False, ignore_installed=True, isolated=options.isolated_mode, ) resolver.resolve(requirement_set) downloaded = ' '.join([ req.name for req in requirement_set.successfully_downloaded ]) if downloaded: logger.info('Successfully downloaded %s', downloaded) # Clean up if not options.no_clean: requirement_set.cleanup_files() return requirement_set