def test_check_import_frequencies(python_file_imports, constraints_file_package_disallowed, package_name): requirements = parse_requirements(constraints_file_package_disallowed) assert check_import_frequencies(python_file_imports, requirements) == { 'os': (SpecifierSet('<6'), 9), 'os.path': (SpecifierSet('<6'), 6), package_name: (SpecifierSet('==0'), 3), }
def _check_plugin_version(plugin_module, plugin_name): if hasattr(plugin_module, "pyb_version") and plugin_module.pyb_version: required_pyb_version = SpecifierSet(plugin_module.pyb_version, True) if not required_pyb_version.contains(PYB_VERSION): raise IncompatiblePluginException(plugin_name, required_pyb_version, PYB_VERSION)
def test_new_resolver_candidates_match_requirement(test_cases, factory): """Candidates returned from find_matches should satisfy the requirement""" for spec, name, matches in test_cases: req = factory.make_requirement_from_spec(spec, comes_from=None) for c in req.find_matches(SpecifierSet()): assert isinstance(c, Candidate) assert req.is_satisfied_by(c)
def test_create__specifier_none(self): """ Test passing specifier=None. """ evaluator = CandidateEvaluator.create('my-project') expected_specifier = SpecifierSet() assert evaluator._specifier == expected_specifier
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, ) 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_wheel_metadata_works() -> None: name = "simple" version = "0.1.0" require_a = "a==1.0" require_b = 'b==1.1; extra == "also_b"' requires = [require_a, require_b, 'c==1.2; extra == "also_c"'] extras = ["also_b", "also_c"] requires_python = ">=3" metadata = email.message.Message() metadata["Name"] = name metadata["Version"] = version for require in requires: metadata["Requires-Dist"] = require for extra in extras: metadata["Provides-Extra"] = extra metadata["Requires-Python"] = requires_python dist = Distribution( pkg_resources.DistInfoDistribution( location="<in-memory>", metadata=WheelMetadata({"METADATA": metadata.as_bytes()}, "<in-memory>"), project_name=name, ), ) assert name == dist.canonical_name == dist.raw_name assert parse_version(version) == dist.version assert set(extras) == set(dist.iter_provided_extras()) assert [require_a] == [str(r) for r in dist.iter_dependencies()] assert [require_a, require_b] == [ str(r) for r in dist.iter_dependencies(["also_b"]) ] assert metadata.as_string() == dist.metadata.as_string() assert SpecifierSet(requires_python) == dist.requires_python
def requires_python(self) -> SpecifierSet: """Value of "Requires-Python:" in distribution metadata. If the key does not exist or contains an invalid value, an empty SpecifierSet should be returned. """ value = self.metadata.get("Requires-Python") if value is None: return SpecifierSet() try: # Convert to str to satisfy the type checker; this can be a Header object. spec = SpecifierSet(str(value)) except InvalidSpecifier as e: message = "Package %r has an invalid Requires-Python: %s" logger.warning(message, self.raw_name, e) return SpecifierSet() return spec
def find_matches(self, requirements): # type: (Sequence[Requirement]) -> Iterable[Candidate] if not requirements: return [] constraint = self._constraints.get( requirements[0].name, SpecifierSet(), ) candidates = self._factory.find_candidates(requirements, constraint) return reversed(self._sort_matches(candidates))
def version_satisfies_spec(spec, version): if not spec: return True if not version: return False if not isinstance(spec, SpecifierSet): spec = SpecifierSet(spec) if not isinstance(version, Version): version = Version(version) return spec.contains(version)
def format_specifier(ireq: InstallRequirement) -> str: """ Generic formatter for pretty printing the specifier part of InstallRequirements to the terminal. """ # TODO: Ideally, this is carried over to the pip library itself specs = ireq.specifier if ireq.req is not None else SpecifierSet() # FIXME: remove ignore type marker once the following issue get fixed # https://github.com/python/mypy/issues/9656 specs = sorted(specs, key=lambda x: x.version) # type: ignore return ",".join(str(s) for s in specs) or "<any>"
def _get_requires_python_dependency(self) -> Optional[Requirement]: requires_python = get_requires_python(self.dist) if requires_python is None: return None try: spec = SpecifierSet(requires_python) except InvalidSpecifier as e: message = "Package %r has an invalid Requires-Python: %s" logger.warning(message, self.name, e) return None return self._factory.make_requires_python_requirement(spec)
def _get_requires_python_specifier(self): # type: () -> Optional[SpecifierSet] requires_python = get_requires_python(self.dist) if requires_python is None: return None try: spec = SpecifierSet(requires_python) except InvalidSpecifier as e: logger.warning( "Package %r has an invalid Requires-Python: %s", self.name, e, ) return None return spec
def identify_vulnerable_packages(environment): vulns = get_vulnerability_db() for pkg in environment['packages'].values(): if pkg['key'] in vulns: for advisory in vulns[pkg['key']]: for spec in advisory['specs']: if pkg['version'] in SpecifierSet(spec): pkg['issues'].append({ 'type': 'VULNERABLE', 'id': advisory['cve'] or advisory['id'], 'description': advisory['advisory'], 'affected_versions': advisory['v'], })
def test_get_applicable_candidates(self): specifier = SpecifierSet('<= 1.11') versions = ['1.10', '1.11', '1.12'] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create( 'my-project', specifier=specifier, ) actual = evaluator.get_applicable_candidates(candidates) expected_applicable = candidates[:2] assert [str(c.version) for c in expected_applicable] == [ '1.10', '1.11', ] assert actual == expected_applicable
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_get_applicable_candidates(self) -> None: specifier = SpecifierSet("<= 1.11") versions = ["1.10", "1.11", "1.12"] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create( "my-project", specifier=specifier, ) actual = evaluator.get_applicable_candidates(candidates) expected_applicable = candidates[:2] assert [str(c.version) for c in expected_applicable] == [ "1.10", "1.11", ] assert actual == expected_applicable
def build_dependency_version_string(mixed): if isinstance(mixed, Dependency): version = mixed.version else: version = mixed if not version: return "" try: return ">=%s" % Version(version) except InvalidVersion: try: return str(SpecifierSet(version)) except InvalidSpecifier: raise ValueError("'%s' must be either PEP 0440 version or a version specifier set")
def test_compute_best_candidate__none_best(self) -> None: """ Test returning a None best candidate. """ specifier = SpecifierSet("<= 1.10") versions = ["1.11", "1.12"] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create( "my-project", specifier=specifier, ) result = evaluator.compute_best_candidate(candidates) assert result._candidates == candidates assert result._applicable_candidates == [] assert result.best_candidate is None
def test_compute_best_candidate__none_best(self): """ Test returning a None best candidate. """ specifier = SpecifierSet('<= 1.10') versions = ['1.11', '1.12'] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create( 'my-project', specifier=specifier, ) result = evaluator.compute_best_candidate(candidates) assert result._candidates == candidates assert result._applicable_candidates == [] assert result.best_candidate is None
def test_SpecifierRequirement_single_specifier(mocker): pkg_src = PackageSource(PipProvider, None) pkg_name = 'numpy' expected_range = Range(Version(1, 0, 0), None, True, False) expected_constraint = Constraint(Package(pkg_name), Union.of(expected_range)) mocker.patch('src.package_source.PackageSource.parse_specifier', return_value=[expected_range]) test_spififerset = SpecifierSet(">=1.0.0", None) test_ireq = my_ireq(my_req(test_spififerset, pkg_name)) test_requirement = my_SpecifierRequirement(test_ireq, None) result = pkg_src.convert_requirement(test_requirement) assert result == expected_constraint
def clean_requires_python(candidates): """Get a cleaned list of all the candidates with valid specifiers in the `requires_python` attributes.""" all_candidates = [] for c in candidates: if c.requires_python: # Old specifications had people setting this to single digits # which is effectively the same as '>=digit,<digit+1' if c.requires_python.isdigit(): c.requires_python = '>={0},<{1}'.format( c.requires_python, int(c.requires_python) + 1) try: SpecifierSet(c.requires_python) except InvalidSpecifier: continue all_candidates.append(c) return all_candidates
def test_none_requires_python(self, caplog: pytest.LogCaptureFixture) -> None: """ Test a dist with Requires-Python None. """ caplog.set_level(logging.DEBUG) dist = make_fake_dist() # Make sure our test setup is correct. assert dist.requires_python == SpecifierSet() assert len(caplog.records) == 0 # Then there is no exception and no log message. _check_dist_requires_python( dist, version_info=(3, 6, 5), ignore_requires_python=False, ) assert len(caplog.records) == 0
def test_make_found_candidates(self): specifier = SpecifierSet('<= 1.11') versions = ['1.10', '1.11', '1.12'] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create('my-project') found_candidates = evaluator.make_found_candidates( candidates, specifier=specifier, ) assert found_candidates._candidates == candidates assert found_candidates._evaluator is evaluator expected_applicable = candidates[:2] assert [str(c.version) for c in expected_applicable] == [ '1.10', '1.11', ] assert found_candidates._applicable_candidates == expected_applicable
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 = [ Tag('pyT', 'none', 'TEST'), Tag('pyT', 'TEST', 'any'), Tag('pyT', 'none', 'any'), ] specifier = SpecifierSet() evaluator = CandidateEvaluator( 'my-project', supported_tags=valid_tags, specifier=specifier, ) 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, results assert links == results2, results2
def test_link_sorting(self) -> None: """ 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 = [ Tag("pyT", "none", "TEST"), Tag("pyT", "TEST", "any"), Tag("pyT", "none", "any"), ] specifier = SpecifierSet() evaluator = CandidateEvaluator( "my-project", supported_tags=valid_tags, specifier=specifier, ) 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, results assert links == results2, results2
def test_compute_best_candidate(self) -> None: specifier = SpecifierSet("<= 1.11") versions = ["1.10", "1.11", "1.12"] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create( "my-project", specifier=specifier, ) result = evaluator.compute_best_candidate(candidates) assert result._candidates == candidates expected_applicable = candidates[:2] assert [str(c.version) for c in expected_applicable] == [ "1.10", "1.11", ] assert result._applicable_candidates == expected_applicable assert result.best_candidate is expected_applicable[1]
def identify_requirement_conflicts(environment): packages = environment['packages'] for pkg in packages.values(): for key, version in pkg['requirements'].items(): if key in packages: if version: if packages[key]['version'] not in SpecifierSet(version): pkg['issues'].append({ 'type': 'REQ_INVALID', 'key': key, 'requirement': version, 'installed': packages[key]['version'], }) else: pkg['issues'].append({ 'type': 'REQ_MISSING', 'key': key, 'requirement': version, })
def test_compute_best_candidate(self): specifier = SpecifierSet('<= 1.11') versions = ['1.10', '1.11', '1.12'] candidates = [make_mock_candidate(version) for version in versions] evaluator = CandidateEvaluator.create( 'my-project', specifier=specifier, ) result = evaluator.compute_best_candidate(candidates) assert result._candidates == candidates expected_applicable = candidates[:2] assert [str(c.version) for c in expected_applicable] == [ '1.10', '1.11', ] assert result._applicable_candidates == expected_applicable assert result.best_candidate is expected_applicable[1]
def add_requirements(user_reqs, env=None): """ create/update setup.cfg file Args: user_reqs (RequirementSet): list of user requirements file_obj: file object to write to """ config = _read_config() reqs = {} for req in user_reqs.requirements.values(): # type: InstallRequirement if not req.comes_from: # add only top-level dependencies if not req.req.specifier and req.installed_version: req.req.specifier = SpecifierSet("~=" + str(req.installed_version)) reqs[req.req.name] = str(req.req) if reqs: update_config(config, env, reqs) _write_to_file(config) return config