def test_create(self, allow_all_prereleases: bool, prefer_binary: bool) -> None: target_python = TargetPython() target_python._valid_tags = [Tag("py36", "none", "any")] specifier = SpecifierSet() evaluator = CandidateEvaluator.create( project_name="my-project", target_python=target_python, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, specifier=specifier, ) assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._specifier is specifier assert evaluator._supported_tags == [Tag("py36", "none", "any")]
def test_create(self, allow_all_prereleases, prefer_binary): target_python = TargetPython() target_python._valid_tags = [('py36', 'none', 'any')] specifier = SpecifierSet() evaluator = CandidateEvaluator.create( project_name='my-project', target_python=target_python, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, specifier=specifier, ) assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._specifier is specifier assert evaluator._supported_tags == [('py36', 'none', 'any')]
def test_not_find_wheel_not_supported(self, data, monkeypatch): """ Test not finding an unsupported wheel. """ req = install_req_from_line("simple.dist") target_python = TargetPython() # Make sure no tags will match. target_python._valid_tags = [] finder = make_test_finder( find_links=[data.find_links], target_python=target_python, ) with pytest.raises(DistributionNotFound): finder.find_requirement(req, True)
def run(self, options, args): options.timeout = TIMEOUT options.retries = RETRIES options.ignore_installed = True options.editables = [] with self._build_session(options) as session: finder = self._build_package_finder( options=options, session=session, target_python=TargetPython( platform=options.platform, py_version_info=options.python_version, abi=options.abi, implementation=options.implementation, ), ) requirement_set = self.get_requirements( args, options, finder, session, ) candidates = [] for req in requirement_set: # extract from finder.find_requirement all_candidates = finder.find_all_candidates(req.name) candidates.extend(all_candidates) self.candidates = candidates return SUCCESS
def __init__( self, target_python=None, # type: Optional[TargetPython] prefer_binary=False, # type: bool allow_all_prereleases=False, # type: bool ignore_requires_python=None, # type: Optional[bool] ): # type: (...) -> None """ :param target_python: The target Python interpreter to use to check both the Python version embedded in the filename and the package's "Requires-Python" metadata. If None (the default), then a TargetPython object will be constructed from the running Python. :param allow_all_prereleases: Whether to allow all pre-releases. :param ignore_requires_python: Whether to ignore incompatible "Requires-Python" values in links. Defaults to False. """ if target_python is None: target_python = TargetPython() if ignore_requires_python is None: ignore_requires_python = False self._ignore_requires_python = ignore_requires_python self._prefer_binary = prefer_binary self._target_python = target_python # We compile the regex here instead of as a class attribute so as # not to impact pip start-up time. This is also okay because # CandidateEvaluator is generally instantiated only once per pip # invocation (when PackageFinder is instantiated). self._py_version_re = re.compile(r'-py([123]\.?[0-9]?)$') self.allow_all_prereleases = allow_all_prereleases
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 _get_finder(): try: return PackageFinder(find_links=[], index_urls=[], session=PipSession()) except TypeError: pass # pip 19.3 from pip._internal.models.search_scope import SearchScope from pip._internal.models.selection_prefs import SelectionPreferences try: return PackageFinder.create( search_scope=SearchScope(find_links=[], index_urls=[]), selection_prefs=SelectionPreferences(allow_yanked=False), session=PipSession(), ) except TypeError: pass from pip._internal.models.target_python import TargetPython try: # pip 19.3.1 from pip._internal.collector import LinkCollector except ImportError: from pip._internal.index.collector import LinkCollector return PackageFinder.create( link_collector=LinkCollector( search_scope=SearchScope(find_links=[], index_urls=[]), session=PipSession(), ), selection_prefs=SelectionPreferences(allow_yanked=False), target_python=TargetPython(), )
def create( cls, link_collector, # type: LinkCollector selection_prefs, # type: SelectionPreferences target_python=None, # type: Optional[TargetPython] ): # type: (...) -> PackageFinder """Create a PackageFinder. :param selection_prefs: The candidate selection preferences, as a SelectionPreferences object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. """ if target_python is None: target_python = TargetPython() candidate_prefs = CandidatePreferences( prefer_binary=selection_prefs.prefer_binary, allow_all_prereleases=selection_prefs.allow_all_prereleases, ) return cls( candidate_prefs=candidate_prefs, link_collector=link_collector, target_python=target_python, allow_yanked=selection_prefs.allow_yanked, format_control=selection_prefs.format_control, ignore_requires_python=selection_prefs.ignore_requires_python, )
def create( cls, project_name: str, target_python: Optional[TargetPython] = None, prefer_binary: bool = False, allow_all_prereleases: bool = False, specifier: Optional[specifiers.BaseSpecifier] = None, hashes: Optional[Hashes] = None, ) -> "CandidateEvaluator": """Create a CandidateEvaluator object. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. :param specifier: An optional object implementing `filter` (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable versions. :param hashes: An optional collection of allowed hashes. """ if target_python is None: target_python = TargetPython() if specifier is None: specifier = specifiers.SpecifierSet() supported_tags = target_python.get_tags() return cls( project_name=project_name, supported_tags=supported_tags, specifier=specifier, prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, hashes=hashes, )
def test_init__target_python(self): """ Test the target_python argument. """ target_python = TargetPython(py_version_info=(3, 7, 3)) evaluator = CandidateEvaluator(target_python=target_python) # The target_python attribute should be set as is. assert evaluator._target_python is target_python
def test_get_tags( self, mock_get_supported, py_version_info, expected_version, ): mock_get_supported.return_value = ['tag-1', 'tag-2'] target_python = TargetPython(py_version_info=py_version_info) actual = target_python.get_tags() assert actual == ['tag-1', 'tag-2'] actual = mock_get_supported.call_args[1]['version'] assert actual == expected_version # Check that the value was cached. assert target_python._valid_tags == ['tag-1', 'tag-2']
def make_target_python(options): # type: (Values) -> TargetPython target_python = TargetPython( platform=options.platform, py_version_info=options.python_version, abi=options.abi, implementation=options.implementation, )
def test_get_tags( self, mock_get_supported: mock.Mock, py_version_info: Optional[Tuple[int, ...]], expected_version: Optional[str], ) -> None: mock_get_supported.return_value = ["tag-1", "tag-2"] target_python = TargetPython(py_version_info=py_version_info) actual = target_python.get_tags() assert actual == ["tag-1", "tag-2"] actual = mock_get_supported.call_args[1]["version"] assert actual == expected_version # Check that the value was cached. assert target_python._valid_tags == ["tag-1", "tag-2"]
def make_target_python(options: Values) -> TargetPython: target_python = TargetPython( platforms=options.platforms, py_version_info=options.python_version, abis=options.abis, implementation=options.implementation, ) return target_python
def make_test_link_evaluator(self, formats): target_python = TargetPython() return LinkEvaluator( project_name='pytest', canonical_name='pytest', formats=formats, target_python=target_python, allow_yanked=True, )
def make_test_link_evaluator(self, formats: Iterable[str]) -> LinkEvaluator: target_python = TargetPython() return LinkEvaluator( project_name="pytest", canonical_name="pytest", formats=frozenset(formats), target_python=target_python, allow_yanked=True, )
def create( cls, search_scope, # type: SearchScope selection_prefs, # type: SelectionPreferences trusted_hosts=None, # type: Optional[List[str]] session=None, # type: Optional[PipSession] target_python=None, # type: Optional[TargetPython] ): # type: (...) -> PackageFinder """Create a PackageFinder. :param selection_prefs: The candidate selection preferences, as a SelectionPreferences object. :param trusted_hosts: Domains not to emit warnings for when not using HTTPS. :param session: The Session to use to make requests. :param target_python: The target Python interpreter to use when checking compatibility. If None (the default), a TargetPython object will be constructed from the running Python. """ if session is None: raise TypeError( "PackageFinder.create() missing 1 required keyword argument: " "'session'") if target_python is None: target_python = TargetPython() supported_tags = target_python.get_tags() candidate_evaluator = CandidateEvaluator( supported_tags=supported_tags, prefer_binary=selection_prefs.prefer_binary, allow_all_prereleases=selection_prefs.allow_all_prereleases, ) return cls( candidate_evaluator=candidate_evaluator, search_scope=search_scope, session=session, target_python=target_python, allow_yanked=selection_prefs.allow_yanked, format_control=selection_prefs.format_control, trusted_hosts=trusted_hosts, ignore_requires_python=selection_prefs.ignore_requires_python, )
def test_init__py_version_info_none(self): """ Test passing py_version_info=None. """ target_python = TargetPython(py_version_info=None) assert target_python._given_py_version_info is None assert target_python.py_version_info == CURRENT_PY_VERSION_INFO assert target_python.py_version == pyversion
def test_evaluate_link__incompatible_wheel(self): """ Test an incompatible wheel. """ target_python = TargetPython(py_version_info=(3, 6, 4)) # Set the valid tags to an empty list to make sure nothing matches. target_python._valid_tags = [] evaluator = CandidateEvaluator(target_python=target_python) link = Link('https://example.com/sample-1.0-py2.py3-none-any.whl') search = Search( supplied='sample', canonical='sample', formats=['binary'], ) actual = evaluator.evaluate_link(link, search=search) expected = ( False, "none of the wheel's tags match: py2-none-any, py3-none-any") assert actual == expected
def test_link_sorting(self): """ Test link sorting """ links = [ InstallationCandidate("simple", "2.0", Link('simple-2.0.tar.gz')), InstallationCandidate( "simple", "1.0", Link('simple-1.0-pyT-none-TEST.whl'), ), InstallationCandidate( "simple", '1.0', Link('simple-1.0-pyT-TEST-any.whl'), ), InstallationCandidate( "simple", '1.0', Link('simple-1.0-pyT-none-any.whl'), ), InstallationCandidate( "simple", '1.0', Link('simple-1.0.tar.gz'), ), ] valid_tags = [ ('pyT', 'none', 'TEST'), ('pyT', 'TEST', 'any'), ('pyT', 'none', 'any'), ] target_python = TargetPython() target_python._valid_tags = valid_tags evaluator = CandidateEvaluator( allow_yanked=True, target_python=target_python, ) sort_key = evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) results2 = sorted(reversed(links), key=sort_key, reverse=True) assert links == results == results2, results2
def test_evaluate_link__incompatible_wheel(self): """ Test an incompatible wheel. """ target_python = TargetPython(py_version_info=(3, 6, 4)) # Set the valid tags to an empty list to make sure nothing matches. target_python._valid_tags = [] evaluator = LinkEvaluator( project_name='sample', canonical_name='sample', formats={'binary'}, target_python=target_python, allow_yanked=True, ) link = Link('https://example.com/sample-1.0-py2.py3-none-any.whl') actual = evaluator.evaluate_link(link) expected = ( False, "none of the wheel's tags match: py2-none-any, py3-none-any") assert actual == expected
def __init__( self, supported_tags=None, # type: Optional[List[Pep425Tag]] prefer_binary=False, # type: bool allow_all_prereleases=False, # type: bool ): # type: (...) -> None """ :param supported_tags: The PEP 425 tags supported by the target Python in order of preference (most preferred first). If None, then the list will be generated from the running Python. :param allow_all_prereleases: Whether to allow all pre-releases. """ if supported_tags is None: target_python = TargetPython() supported_tags = target_python.get_tags() self._prefer_binary = prefer_binary self._supported_tags = supported_tags self.allow_all_prereleases = allow_all_prereleases
def test_make_candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): target_python = TargetPython() target_python._valid_tags = [('py36', 'none', 'any')] candidate_prefs = CandidatePreferences( prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, ) finder = PackageFinder( search_scope=SearchScope([], []), session=PipSession(), target_python=target_python, allow_yanked=True, candidate_prefs=candidate_prefs, ) evaluator = finder.make_candidate_evaluator() assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._supported_tags == [('py36', 'none', 'any')]
def test_init__py_version_info(self, py_version_info, expected): """ Test passing the py_version_info argument. """ expected_py_version_info, expected_py_version = expected target_python = TargetPython(py_version_info=py_version_info) # The _given_py_version_info attribute should be set as is. assert target_python._given_py_version_info == py_version_info assert target_python.py_version_info == expected_py_version_info assert target_python.py_version == expected_py_version
def test_evaluate_link__incompatible_wheel(self) -> None: """ Test an incompatible wheel. """ target_python = TargetPython(py_version_info=(3, 6, 4)) # Set the valid tags to an empty list to make sure nothing matches. target_python._valid_tags = [] evaluator = LinkEvaluator( project_name="sample", canonical_name="sample", formats=frozenset(["binary"]), target_python=target_python, allow_yanked=True, ) link = Link("https://example.com/sample-1.0-py2.py3-none-any.whl") actual = evaluator.evaluate_link(link) expected = ( False, "none of the wheel's tags (py2-none-any, py3-none-any) are compatible " "(run pip debug --verbose to show compatible tags)", ) assert actual == expected
def test_init__py_version_info_none(self): """ Test passing py_version_info=None. """ # Get the index of the second dot. index = sys.version.find('.', 2) current_major_minor = sys.version[:index] # e.g. "3.6" target_python = TargetPython(py_version_info=None) assert target_python._given_py_version_info is None assert target_python.py_version_info == CURRENT_PY_VERSION_INFO assert target_python.py_version == current_major_minor
def test_create__candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): """ Test that the candidate_evaluator attribute is set correctly. """ selection_prefs = SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, ) target_python = TargetPython(py_version_info=(3, 7, 3)) target_python._valid_tags = ['tag1', 'tag2'] finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), target_python=target_python, ) evaluator = finder.candidate_evaluator assert evaluator.allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._supported_tags == ['tag1', 'tag2']
def test_make_candidate_evaluator( self, allow_all_prereleases: bool, prefer_binary: bool, ) -> None: target_python = TargetPython() target_python._valid_tags = [Tag("py36", "none", "any")] candidate_prefs = CandidatePreferences( prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, ) link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) finder = PackageFinder( link_collector=link_collector, target_python=target_python, allow_yanked=True, candidate_prefs=candidate_prefs, use_deprecated_html5lib=False, ) specifier = SpecifierSet() # Pass hashes to check that _hashes is set. hashes = Hashes({"sha256": [64 * "a"]}) evaluator = finder.make_candidate_evaluator( "my-project", specifier=specifier, hashes=hashes, ) assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._hashes == hashes assert evaluator._prefer_binary == prefer_binary assert evaluator._project_name == "my-project" assert evaluator._specifier is specifier assert evaluator._supported_tags == [Tag("py36", "none", "any")]
def test_make_candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): target_python = TargetPython() target_python._valid_tags = [('py36', 'none', 'any')] candidate_prefs = CandidatePreferences( prefer_binary=prefer_binary, allow_all_prereleases=allow_all_prereleases, ) link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) finder = PackageFinder( link_collector=link_collector, target_python=target_python, allow_yanked=True, candidate_prefs=candidate_prefs, ) specifier = SpecifierSet() # Pass hashes to check that _hashes is set. hashes = Hashes({'sha256': [64 * 'a']}) evaluator = finder.make_candidate_evaluator( 'my-project', specifier=specifier, hashes=hashes, ) assert evaluator._allow_all_prereleases == allow_all_prereleases assert evaluator._hashes == hashes assert evaluator._prefer_binary == prefer_binary assert evaluator._project_name == 'my-project' assert evaluator._specifier is specifier assert evaluator._supported_tags == [('py36', 'none', 'any')]
def test_create__target_python(self): """ Test that target_python is passed to CandidateEvaluator as is. """ target_python = TargetPython(py_version_info=(3, 7, 3)) finder = PackageFinder.create( [], [], session=object(), target_python=target_python, ) evaluator = finder.candidate_evaluator actual_target_python = evaluator._target_python assert actual_target_python is target_python assert actual_target_python.py_version_info == (3, 7, 3)