def test_resolvable_requirement(): req = 'foo[bar]==2.3.4' resolvable = ResolvableRequirement.from_string( req, ResolverOptionsBuilder(fetchers=[])) assert resolvable.requirement == pkg_resources.Requirement.parse( 'foo[bar]==2.3.4') assert resolvable.name == 'foo' assert resolvable.exact is True assert resolvable.extras() == ['bar'] assert resolvable.options._fetchers == [] assert resolvable.packages() == [] source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') mock_iterator = mock.create_autospec(Iterator, spec_set=True) mock_iterator.iter.return_value = iter([source_pkg]) assert resolvable.compatible(mock_iterator) == [source_pkg] assert mock_iterator.iter.mock_calls == [ mock.call(pkg_resources.Requirement.parse('foo[bar]==2.3.4')) ] # test non-exact resolvable = ResolvableRequirement.from_string('foo', ResolverOptionsBuilder()) assert resolvable.exact is False # test Resolvable.get, which should delegate to a ResolvableRequirement in this case assert Resolvable.get('foo') == ResolvableRequirement.from_string( 'foo', ResolverOptionsBuilder())
def test_resolvable_set_constraint_and_non_constraint(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() constraint = ResolvableRequirement.from_string('foo', builder) constraint.is_constraint = True package = SourcePackage.from_href('foo-2.3.4.tar.gz') rq = ResolvableRequirement.from_string('foo', builder) rs.merge(constraint, [package]) rs.merge(rq, [package]) assert rs.packages() == [(rq, set([package]), None, False)]
def test_resolver_with_constraint(): builder = ResolverOptionsBuilder() r = Resolver() rs = _ResolvableSet() constraint = ResolvableRequirement.from_string('foo', builder) constraint.is_constraint = True package = SourcePackage.from_href('foo-2.3.4.tar.gz') rq = ResolvableRequirement.from_string('foo', builder) rs.merge(constraint, [package]) rs.merge(rq, [package]) assert r.resolve([], resolvable_set=rs) == []
def test_constraints_range(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() req = ResolvableRequirement.from_string("foo>0.5", builder) constraint = ResolvableRequirement.from_string("foo<0.9", builder) constraint.is_constraint = True version_packages = [] for version in range(1, 10): version_string = "foo-0.{0}.tar.gz".format(version) package = SourcePackage.from_href(version_string) version_packages.append(package) rs.merge(req, version_packages[4:]) rs.merge(constraint, version_packages[:8]) assert rs.packages() == [(req, set(version_packages[4:8]), None, False)]
def test_resolvables_from_iterable(): builder = ResolverOptionsBuilder() reqs = [ 'foo', # string Package.from_href('foo-2.3.4.tar.gz'), # Package pkg_resources.Requirement.parse('foo==2.3.4'), ] resolved_reqs = list(resolvables_from_iterable(reqs, builder)) assert resolved_reqs == [ ResolvableRequirement.from_string('foo', builder), ResolvablePackage.from_string('foo-2.3.4.tar.gz', builder), ResolvableRequirement.from_string('foo==2.3.4', builder), ]
def test_deterministic_packages_from_multiple_crawlers(): req = 'protobuf==3.9.1' options_builder = ResolverOptionsBuilder(precedence=(WheelPackage, )) resolvable = ResolvableRequirement.from_string(req, options_builder) pypi_source = Package.from_href( 'https://pypi.org/simple/protobuf/protobuf-3.9.1.tar.gz') pypi_wheel = Package.from_href( 'https://pypi.org/simple/protobuf/protobuf-3.9.1-py2.py3-none-any.whl') internal_wheel = Package.from_href( 'https://packages.internal.example/simple/protobuf/protobuf-3.9.1-py2.py3-none-any.whl' ) # Multiple fetchers with equally-preferred packages should result in the same package every time, # regardless the order that crawlers returned them. mock_iterator = mock.create_autospec(Iterator, spec_set=True) mock_iterator.iter.return_value = iter( [pypi_source, pypi_wheel, internal_wheel]) url_order_one = [r.url for r in resolvable.compatible(mock_iterator)] mock_iterator.iter.return_value = iter( [pypi_source, internal_wheel, pypi_wheel]) url_order_two = [r.url for r in resolvable.compatible(mock_iterator)] assert url_order_one == url_order_two
def test_resolvable_set_is_constraint_only(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() c = ResolvableRequirement.from_string('foo', builder) c.is_constraint = True package = SourcePackage.from_href('foo-2.3.4.tar.gz') rs.merge(c, [package]) assert rs.packages() == [(c, set([package]), None, True)]
def test_resolvable_requirement(): req = 'foo[bar]==2.3.4' resolvable = ResolvableRequirement.from_string(req, ResolverOptionsBuilder(fetchers=[])) assert resolvable.requirement == pkg_resources.Requirement.parse('foo[bar]==2.3.4') assert resolvable.name == 'foo' assert resolvable.exact is True assert resolvable.extras() == ['bar'] assert resolvable.options._fetchers == [] assert resolvable.packages() == [] source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') mock_iterator = mock.create_autospec(Iterator, spec_set=True) mock_iterator.iter.return_value = iter([source_pkg]) assert resolvable.compatible(mock_iterator) == [source_pkg] assert mock_iterator.iter.mock_calls == [ mock.call(pkg_resources.Requirement.parse('foo[bar]==2.3.4'))] # test non-exact resolvable = ResolvableRequirement.from_string('foo', ResolverOptionsBuilder()) assert resolvable.exact is False # test Resolvable.get, which should delegate to a ResolvableRequirement in this case assert Resolvable.get('foo') == ResolvableRequirement.from_string( 'foo', ResolverOptionsBuilder())
def test_resolvable_set_built(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() rq = ResolvableRequirement.from_string('foo', builder) source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') binary_pkg = EggPackage.from_href('foo-2.3.4-py3.4.egg') rs.merge(rq, [source_pkg]) assert rs.get('foo') == set([source_pkg]) assert rs.packages() == [(rq, set([source_pkg]), None, False)] with pytest.raises(Unsatisfiable): rs.merge(rq, [binary_pkg]) updated_rs = rs.replace_built({source_pkg: binary_pkg}) updated_rs.merge(rq, [binary_pkg]) assert updated_rs.get('foo') == set([binary_pkg]) assert updated_rs.packages() == [(rq, set([binary_pkg]), None, False)]
def test_resolvable_set(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() rq = ResolvableRequirement.from_string('foo[ext]', builder) source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') binary_pkg = EggPackage.from_href('foo-2.3.4-py3.4.egg') rs.merge(rq, [source_pkg, binary_pkg]) assert rs.get('foo') == set([source_pkg, binary_pkg]) assert rs.packages() == [(rq, set([source_pkg, binary_pkg]), None)] # test methods assert rs.extras('foo') == set(['ext']) # test filtering rs.merge(rq, [source_pkg]) assert rs.get('foo') == set([source_pkg]) with pytest.raises(Unsatisfiable): rs.merge(rq, [binary_pkg])
def test_resolvable_set(): builder = ResolverOptionsBuilder() rs = _ResolvableSet() rq = ResolvableRequirement.from_string('foo[ext]', builder) source_pkg = SourcePackage.from_href('foo-2.3.4.tar.gz') binary_pkg = EggPackage.from_href('Foo-2.3.4-py3.4.egg') rs.merge(rq, [source_pkg, binary_pkg]) assert rs.get(source_pkg.name) == set([source_pkg, binary_pkg]) assert rs.get(binary_pkg.name) == set([source_pkg, binary_pkg]) assert rs.packages() == [(rq, set([source_pkg, binary_pkg]), None, False)] # test methods assert rs.extras('foo') == set(['ext']) assert rs.extras('Foo') == set(['ext']) # test filtering rs.merge(rq, [source_pkg]) assert rs.get('foo') == set([source_pkg]) assert rs.get('Foo') == set([source_pkg]) with pytest.raises(Unsatisfiable): rs.merge(rq, [binary_pkg])
def test_resolvable_is_constraint_getter_setter(): builder = ResolverOptionsBuilder() req = ResolvableRequirement.from_string('foo', builder) assert req.is_constraint is False req.is_constraint = True assert req.is_constraint is True
def rr(req): return ResolvableRequirement.from_string(req, ResolverOptionsBuilder())
def resolve(self, resolvables, resolvable_set=None): resolvables = [ (resolvable, None) for resolvable in resolvables if self.is_resolvable_in_target_interpreter_env(resolvable) ] resolvable_set = resolvable_set or _ResolvableSet() processed_resolvables = set() processed_packages = {} distributions = {} while resolvables: while resolvables: resolvable, parent = resolvables.pop(0) if resolvable in processed_resolvables: continue packages = self.package_iterator(resolvable, existing=resolvable_set.get( resolvable.name)) resolvable_set.merge(resolvable, packages, parent) processed_resolvables.add(resolvable) built_packages = {} for resolvable, packages, parent, constraint_only in resolvable_set.packages( ): if constraint_only: continue assert len( packages ) > 0, 'ResolvableSet.packages(%s) should not be empty' % resolvable package = next(iter(packages)) if resolvable.name in processed_packages: if package == processed_packages[resolvable.name]: continue if package not in distributions: dist = self.build(package, resolvable.options) built_package = Package.from_href(dist.location) built_packages[package] = built_package distributions[built_package] = dist package = built_package distribution = distributions[package] processed_packages[resolvable.name] = package new_parent = '%s->%s' % ( parent, resolvable) if parent else str(resolvable) # We patch packaging.markers.default_environment here so we find optional reqs for the # platform we're building the PEX for, rather than the one we're on. if self._transitive: with patched_packing_env(self._target_interpreter_env): resolvables.extend( (ResolvableRequirement(req, resolvable.options), new_parent) for req in distribution.requires( extras=resolvable_set.extras(resolvable.name))) resolvable_set = resolvable_set.replace_built(built_packages) # We may have built multiple distributions depending upon if we found transitive dependencies # for the same package. But ultimately, resolvable_set.packages() contains the correct version # for all packages. So loop through it and only return the package version in # resolvable_set.packages() that is found in distributions. dists = [] # No point in proceeding if distributions is empty if not distributions: return dists for resolvable, packages, parent, constraint_only in resolvable_set.packages( ): if constraint_only: continue assert len( packages ) > 0, 'ResolvableSet.packages(%s) should not be empty' % resolvable package = next(iter(packages)) distribution = distributions[package] if isinstance(resolvable, ResolvableRequirement): requirement = resolvable.requirement else: requirement = distribution.as_requirement() requirement.extras = tuple(resolvable.extras()) dists.append( ResolvedDistribution(requirement=requirement, distribution=distribution)) return dists