def _prepare_step_context() -> StepContext: """Prepare step context for test scenarios.""" direct_dependencies = {} paths = {} source = Source("https://pypi.org/simple") for version_identifier in ("0.12.1", "1.0.1"): package_tuple = ("flask", version_identifier, source.url) direct_dependencies[package_tuple] = PackageVersion( name="flask", version="==" + version_identifier, index=source.url, develop=False, ) paths[package_tuple] = [ (package_tuple, ("werkzeug", "0.13", "https://pypi.org/simple")), (package_tuple, ("werkzeug", "0.14", "https://pypi.org/simple")), (("werkzeug", "0.13", "https://pypi.org/simple"), ("six", "1.7.0", "https://pypi.org/simple")), (("werkzeug", "0.13", "https://pypi.org/simple"), ("six", "1.8.0", "https://pypi.org/simple")), (("werkzeug", "0.14", "https://pypi.org/simple"), ("six", "1.7.0", "https://pypi.org/simple")), (("werkzeug", "0.14", "https://pypi.org/simple"), ("six", "1.8.0", "https://pypi.org/simple")), ] return StepContext.from_paths(direct_dependencies, paths)
def test_not_resolved(self) -> None: direct_dependencies = { ("flask", "1.12.0", "https://pypi.org/simple"): PackageVersion( name="flask", version="==1.12.0", index="https://pypi.org/simple", develop=False, ) } paths = { ("flask", "1.12.0", "https://pypi.org/simple"): [(("flask", "1.12.0", "https://pypi.org/simple"), ("werkzeug", "0.13", None))] } step_context = StepContext.from_paths(direct_dependencies, paths) assert ("werkzeug", "0.13", None) in step_context.iter_transitive_dependencies_tuple() assert ("werkzeug", "0.13", None) in step_context.unsolved_packages assert step_context.unsolved_packages.get( ("werkzeug", "0.13", None)) is not None assert len( list(step_context.iter_transitive_dependencies(develop=None))) == 1 assert len( list( step_context.iter_transitive_dependencies(develop=False))) == 1 assert len( list(step_context.iter_transitive_dependencies(develop=True))) == 0 direct_dependencies = list(step_context.iter_direct_dependencies()) assert len(direct_dependencies) == 1 assert direct_dependencies[0].name == "flask"
def test_remove_package_tuple_transitive_error(self) -> None: """Remove a transitive dependency which will cause error during removal.""" direct_dependencies = { ("flask", "0.12.1", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12.1", index=Source("https://pypi.org/simple"), develop=False, ) } paths = { ("flask", "0.12.1", "https://pypi.org/simple"): [ (("flask", "0.12.1", "https://pypi.org/simple"), ("werkzeug", "0.13", "https://pypi.org/simple")), (("werkzeug", "0.13", "https://pypi.org/simple"), ("six", "1.0.0", "https://pypi.org/simple")), ] } step_context = StepContext.from_paths(direct_dependencies, paths=paths) with pytest.raises(CannotRemovePackage): with step_context.remove_package_tuples( ("six", "1.0.0", "https://pypi.org/simple")): pass
def test_remove_package_tuple_transitive_with_direct_diamond_error( self) -> None: """Test removal of a package which does not have any candidate of direct dependency.""" direct_dependencies = { ("flask", "0.12.1", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12.1", index=Source("https://pypi.org/simple"), develop=False, ) } paths = { ("flask", "0.12.1", "https://pypi.org/simple"): [ (("flask", "0.12.1", "https://pypi.org/simple"), ("werkzeug", "0.13", "https://pypi.org/simple")), (("werkzeug", "0.13", "https://pypi.org/simple"), ("six", "1.0.0", "https://pypi.org/simple")), (("flask", "0.12.1", "https://pypi.org/simple"), ("werkzeug", "0.14", "https://pypi.org/simple")), (("werkzeug", "0.14", "https://pypi.org/simple"), ("six", "1.0.0", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths) with pytest.raises(CannotRemovePackage): with step_context.remove_package_tuples( ("six", "1.0.0", "https://pypi.org/simple")): pass
def test_no_remove(self): """Make sure packages which are not toolchain do not get removed.""" direct_dependencies = { ("goblinoid", "1.0.0", "https://pypi.org/simple"): PackageVersion( name="goblinoid", version="==1.0.0", index=Source("https://pypi.org/simple"), develop=False, ) } paths = { ("goblinoid", "1.0.0", "https://pypi.org/simple"): [ (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("foo", "1.0.0", "https://pypi.org/simple")), ] } step_context = StepContext.from_paths(direct_dependencies, paths) cut_toolchain = CutToolchain( graph=None, project=None, library_usage=None, ) cut_toolchain.run(step_context) assert step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs() == [ (0.0, (None, ('goblinoid', '1.0.0', 'https://pypi.org/simple'))), (0.0, (('goblinoid', '1.0.0', 'https://pypi.org/simple'), ('foo', '1.0.0', 'https://pypi.org/simple'))), ]
def test_remove_package_tuple_transitive_with_direct_error(self) -> None: """Test removal of a package which does not have any candidate of direct dependency.""" paths = {} direct_dependencies = {} source = Source("https://pypi.org/simple") for version_identifier in ("0.12.1", "1.0.1"): package_tuple = ("flask", version_identifier, source.url) direct_dependencies[package_tuple] = PackageVersion( name="flask", version="==" + version_identifier, index=source.url, develop=False, ) paths[package_tuple] = [ (package_tuple, ("werkzeug", "0.13", "https://pypi.org/simple")), (package_tuple, ("werkzeug", "0.14", "https://pypi.org/simple")), (("werkzeug", "0.13", "https://pypi.org/simple"), ("six", "1.0.0", "https://pypi.org/simple")), (("werkzeug", "0.14", "https://pypi.org/simple"), ("six", "1.0.0", "https://pypi.org/simple")), ] step_context = StepContext.from_paths(direct_dependencies, paths) with pytest.raises(CannotRemovePackage): with step_context.remove_package_tuples( ("six", "1.0.0", "https://pypi.org/simple")): pass
def test_remove_all_transitive_error(self): """Test raising of an error if all the transitive deps of a type were removed.""" source = Source("https://pypi.org/simple") direct_dependencies = { ("tensorflow", "2.0.0", source.url): PackageVersion( name="tensorflow", version="==2.0.0", index=source, develop=False, ) } paths = { ("tensorflow", "2.0.0", "https://pypi.org/simple"): [ (("tensorflow", "2.0.0", "https://pypi.org/simple"), ("numpy", "1.0.0rc1", "https://thoth-station.ninja/simple")), ] } step_context = StepContext.from_paths(direct_dependencies, paths) project = Project.from_strings(self._CASE_PIPFILE) restrict_indexes = CutPreReleases( graph=None, project=project, library_usage=None, ) with pytest.raises(CannotRemovePackage): restrict_indexes.run(step_context)
def test_limit_transitive(self): """Test cutting of latest versions for transitive dependencies.""" direct_dependencies = { ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"): PackageVersion( name="tensorflow", version="==2.0.0", index=Source("https://thoth-station.ninja/simple"), develop=False, ) } paths = { ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"): [ (("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), ("numpy", "1.0.0", "https://pypi.org/simple")), ], ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"): [ (("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), ("numpy", "2.0.0", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths) limit_latest_versions = LimitLatestVersions( graph=None, project=None, library_usage=None, ) limit_latest_versions.update_parameters({"limit_latest_versions": 1}) limit_latest_versions.run(step_context) pairs = list( sorted(step_context.dependency_graph_adaptation. to_scored_package_tuple_pairs(), key=operator.itemgetter(0))) assert pairs == [( 0.0, ( None, ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), ), ), ( 0.0, ( ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), ("numpy", "2.0.0", "https://pypi.org/simple"), ), )] assert list(pv.to_tuple() for pv in step_context.iter_direct_dependencies()) == [ ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple") ]
def test_one_observation(self): """Test one observation and subsequent correct reduction.""" source = Source("https://pypi.org/simple") direct_dependencies = { ("a", "2.0.0", source.url): PackageVersion( name="a", version="==2.0.0", index=source, develop=False, ), ("a", "1.0.0", source.url): PackageVersion( name="a", version="==1.0.0", index=source, develop=False, ), } paths = { ("a", "2.0.0", "https://pypi.org/simple"): [ (("a", "2.0.0", "https://pypi.org/simple"), ("b", "2.0.0", "https://pypi.org/simple")), (("a", "2.0.0", "https://pypi.org/simple"), ("b", "1.0.0", "https://pypi.org/simple")), ], ("a", "1.0.0", "https://pypi.org/simple"): [ (("a", "1.0.0", "https://pypi.org/simple"), ("b", "2.0.0", "https://pypi.org/simple")), (("a", "1.0.0", "https://pypi.org/simple"), ("b", "1.0.0", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths=paths) step_context.score_package_tuple( ("a", "1.0.0", "https://pypi.org/simple"), 2.0) observation_reduction = ObservationReduction( graph=None, project=None, library_usage=None, ) observation_reduction.run(step_context) observation_reduced = step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs( ) assert set(observation_reduced) == { (2.0, (None, ('a', '1.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '1.0.0', 'https://pypi.org/simple'), ('b', '2.0.0', 'https://pypi.org/simple'))), }
def test_no_observation_latest(self): """Test that we always end up with the latest version possible if no observations are found.""" source = Source("https://pypi.org/simple") direct_dependencies = { ("tensorflow", "2.0.0", source.url): PackageVersion( name="tensorflow", version="==2.0.0", index=Source("https://pypi.org/simple"), develop=False, ), ("tensorflow", "1.9.0", source.url): PackageVersion( name="tensorflow", version="==1.9.0", index=Source("https://pypi.org/simple"), develop=False, ), } paths = { ("tensorflow", "1.9.0", "https://pypi.org/simple"): [ (("tensorflow", "1.9.0", "https://pypi.org/simple"), ("numpy", "1.0.0", "https://pypi.org/simple")), (("tensorflow", "1.9.0", "https://pypi.org/simple"), ("numpy", "2.0.0", "https://pypi.org/simple")), ], ("tensorflow", "2.0.0", "https://pypi.org/simple"): [ (("tensorflow", "2.0.0", "https://pypi.org/simple"), ("numpy", "2.0.0", "https://pypi.org/simple")), (("tensorflow", "2.0.0", "https://pypi.org/simple"), ("numpy", "1.0.0", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths=paths) observation_reduction = ObservationReduction( graph=None, project=None, library_usage=None, ) observation_reduction.run(step_context) observation_reduced = step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs( ) assert set(observation_reduced) == { (0.0, (None, ('tensorflow', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('tensorflow', '2.0.0', 'https://pypi.org/simple'), ('numpy', '2.0.0', 'https://pypi.org/simple'))) }
def test_remove_direct(self): """Test removal of direct dependencies which is not a pre-release.""" source = Source("https://pypi.org/simple") direct_dependencies = { ("tensorflow", "2.0.0rc1", source.url): PackageVersion( name="tensorflow", version="==2.0.0rc1", index=source, develop=False, ), ("tensorflow", "2.0.0", source.url): PackageVersion( name="tensorflow", version="==2.0.0", index=source, develop=False, ), } paths = { ("tensorflow", "2.0.0", "https://pypi.org/simple"): [ (("tensorflow", "2.0.0", "https://pypi.org/simple"), ("numpy", "1.0.0", "https://pypi.org/simple")), (("tensorflow", "2.0.0", "https://pypi.org/simple"), ("numpy", "2.0.0", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths) project = Project.from_strings(self._CASE_PIPFILE) restrict_indexes = CutPreReleases( graph=None, project=project, library_usage=None, ) restrict_indexes.run(step_context) assert step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs( ) == [(0.0, (None, ('tensorflow', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('tensorflow', '2.0.0', 'https://pypi.org/simple'), ('numpy', '1.0.0', 'https://pypi.org/simple'))), (0.0, (('tensorflow', '2.0.0', 'https://pypi.org/simple'), ('numpy', '2.0.0', 'https://pypi.org/simple')))] assert (len(list(step_context.iter_direct_dependencies())) == 1 ), "Wrong number of direct dependencies"
def test_remove_single22(self): """Test removing one single dependency from dependency paths, keep paths with same package of a type. In other words - always keep latest toolchain. """ direct_dependencies = { ("flask", "0.12", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12", index=Source("https://pypi.org/simple"), develop=False, ) } paths = { ("flask", "0.12", "https://pypi.org/simple"): [ (("flask", "0.12", "https://pypi.org/simple"), ("werkzeug", "0.15.1", "https://pypi.org/simple")), (("werkzeug", "0.15.1", "https://pypi.org/simple"), ("wheel", "1.12.0", "https://pypi.org/simple")), (("werkzeug", "0.15.1", "https://pypi.org/simple"), ("six", "1.12.1", "https://pypi.org/simple")), (("werkzeug", "0.15.1", "https://pypi.org/simple"), ("wheel", "1.12.1", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths) cut_toolchain = CutToolchain( graph=None, project=None, library_usage=None, ) cut_toolchain.run(step_context) # We always expect the latest one to be present. assert step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs() == [ (0.0, (None, ('flask', '0.12', 'https://pypi.org/simple'))), (0.0, (('flask', '0.12', 'https://pypi.org/simple'), ('werkzeug', '0.15.1', 'https://pypi.org/simple'))), (0.0, (('werkzeug', '0.15.1', 'https://pypi.org/simple'), ('six', '1.12.1', 'https://pypi.org/simple'))), (0.0, (('werkzeug', '0.15.1', 'https://pypi.org/simple'), ('wheel', '1.12.1', 'https://pypi.org/simple'))) ]
def test_remove_multi(self): """Check all types of "toolchain" packages get removed.""" direct_dependencies = { ("goblinoid", "1.0.0", "https://pypi.org/simple"): PackageVersion( name="goblinoid", version="==1.0.0", index=Source("https://pypi.org/simple"), develop=False, ) } paths = { ("goblinoid", "1.0.0", "https://pypi.org/simple"): [ (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("wheel", "1.0.0", "https://pypi.org/simple")), (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("wheel", "2.0.0", "https://pypi.org/simple")), (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("setuptools", "1.0.0", "https://pypi.org/simple")), (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("setuptools", "2.0.0", "https://pypi.org/simple")), (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("pip", "1.0.0", "https://pypi.org/simple")), (("goblinoid", "1.0.0", "https://pypi.org/simple"), ("pip", "2.0.0", "https://pypi.org/simple")), ] } step_context = StepContext.from_paths(direct_dependencies, paths) cut_toolchain = CutToolchain( graph=None, project=None, library_usage=None, ) cut_toolchain.run(step_context) assert step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs() == [ (0.0, (None, ('goblinoid', '1.0.0', 'https://pypi.org/simple'))), (0.0, (('goblinoid', '1.0.0', 'https://pypi.org/simple'), ('wheel', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('goblinoid', '1.0.0', 'https://pypi.org/simple'), ('setuptools', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('goblinoid', '1.0.0', 'https://pypi.org/simple'), ('pip', '2.0.0', 'https://pypi.org/simple'))) ]
def test_cyclic(self): """Test cyclic dependencies - test we actually break cycles.""" direct_dependencies = { ("a", "2.0.0", "https://pypi.org/simple"): PackageVersion( name="a", version="==2.0.0", index=Source("https://pypi.org/simple"), develop=False, ), } paths = { ("a", "2.0.0", "https://pypi.org/simple"): [ (("a", "2.0.0", "https://pypi.org/simple"), ("b", "2.0.0", "https://pypi.org/simple")), (("b", "2.0.0", "https://pypi.org/simple"), ("c", "2.0.0", "https://pypi.org/simple")), (("c", "2.0.0", "https://pypi.org/simple"), ("b", "2.0.0", "https://pypi.org/simple")), (("a", "2.0.0", "https://pypi.org/simple"), ("b", "1.0.0", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths=paths) observation_reduction = ObservationReduction( graph=None, project=None, library_usage=None, ) observation_reduction.run(step_context) observation_reduced = step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs( ) assert set(observation_reduced) == { (0.0, (None, ('a', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '2.0.0', 'https://pypi.org/simple'), ('b', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('b', '2.0.0', 'https://pypi.org/simple'), ('c', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('c', '2.0.0', 'https://pypi.org/simple'), ('b', '2.0.0', 'https://pypi.org/simple'))) }
def _get_prepared_context(): direct_dependencies = { ("flask", "0.12.0", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12.0", index=Source("https://pypi.org/simple"), develop=False, ) } paths = { ("flask", "0.12.0", "https://pypi.org/simple"): [ (("flask", "0.12.0", "https://pypi.org/simple"), ("click", "2.0", "https://pypi.org/simple")), (("flask", "0.12.0", "https://pypi.org/simple"), ("click", "2.1", "https://pypi.org/simple")), ], } return StepContext.from_paths(direct_dependencies, paths)
def test_remove_package_tuple_direct_error(self) -> None: """Test removal of a package which is a direct dependency and causes issues.""" direct_dependencies = { ("flask", "0.12.1", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12.1", index=Source("https://pypi.org/simple"), develop=False, ) } step_context = StepContext.from_paths( direct_dependencies, paths={("flask", "0.12.1", "https://pypi.org/simple"): []}) with pytest.raises(CannotRemovePackage): with step_context.remove_package_tuples( ("flask", "0.12.1", "https://pypi.org/simple")): pass
def test_remove_package_tuple_transitive_with_direct_change(self) -> None: """Test removal of a transitive dependency which leads to removal of a direct dependency candidate.""" paths = {} direct_dependencies = {} source = Source("https://pypi.org/simple") for version_identifier in ("0.12.1", "1.0.1"): package_tuple = ("flask", version_identifier, source.url) direct_dependencies[package_tuple] = PackageVersion( name="flask", version="==" + version_identifier, index=Source("https://pypi.org/simple"), develop=False, ) paths[("flask", "0.12.1", "https://pypi.org/simple")] = [ (("flask", "0.12.1", "https://pypi.org/simple"), ("werkzeug", "0.13", "https://pypi.org/simple")) ] paths[("flask", "1.0.1", "https://pypi.org/simple")] = [ (("flask", "1.0.1", "https://pypi.org/simple"), ("werkzeug", "0.14", "https://pypi.org/simple")) ] step_context = StepContext.from_paths(direct_dependencies, paths) # Now remove werkzeug 0.14 which will lead to removal of flask 1.0.1. to_remove = ("werkzeug", "0.14", "https://pypi.org/simple") with step_context.remove_package_tuples(to_remove) as txn: txn.commit() assert len(list(step_context.iter_direct_dependencies())) == 1 assert len(list( step_context.iter_transitive_dependencies_tuple())) == 1 assert len(list( step_context.iter_transitive_dependencies_tuple())) == len( list(step_context.iter_transitive_dependencies())) assert to_remove not in list( step_context.iter_transitive_dependencies_tuple())
def _get_prepared_step_context() -> StepContext: source = Source("https://pypi.org/simple") direct_dependencies = { ("flask", "0.12.0", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12.0", index=source, develop=False, ), ("flask", "0.13.0", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.13.0", index=source, develop=False, ), } paths = { ("flask", "0.12.0", "https://pypi.org/simple"): [ (("flask", "0.12.0", "https://pypi.org/simple"), ("click", "2.0", "https://pypi.org/simple")), (("click", "2.0", "https://pypi.org/simple"), ("pyyaml", "3.12", "https://pypi.org/simple")), ], ("flask", "0.13.0", "https://pypi.org/simple"): [ (("flask", "0.13.0", "https://pypi.org/simple"), ("click", "2.0", "https://pypi.org/simple")), (("click", "2.0", "https://pypi.org/simple"), ("pyyaml", "3.12", "https://pypi.org/simple")), (("click", "2.0", "https://pypi.org/simple"), ("pyyaml", "4.0", "https://pypi.org/simple")), ], } return StepContext.from_paths(direct_dependencies, paths)
def test_limit_no_change(self): """Test cutting off latest versions without any change.""" source = Source("https://thoth-station.ninja/simple") direct_dependencies = { ("tensorflow", "1.9.0", source.url): PackageVersion( name="tensorflow", version="==1.9.0", index=source, develop=False, ), ("tensorflow", "2.0.0", source.url): PackageVersion( name="tensorflow", version="==2.0.0", index=source, develop=False, ), } paths = { ("tensorflow", "1.9.0", "https://thoth-station.ninja/simple"): [ (("tensorflow", "1.9.0", "https://thoth-station.ninja/simple"), ("numpy", "1.0.0", "https://pypi.org/simple")), (("tensorflow", "1.9.0", "https://thoth-station.ninja/simple"), ("numpy", "2.0.0", "https://pypi.org/simple")), ], ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"): { (("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), ("numpy", "1.0.0", "https://pypi.org/simple")), (("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), ("numpy", "2.0.0", "https://pypi.org/simple")), } } step_context = StepContext.from_paths(direct_dependencies, paths) limit_latest_versions = LimitLatestVersions( graph=None, project=None, library_usage=None, ) limit_latest_versions.update_parameters({"limit_latest_versions": 2}) limit_latest_versions.run(step_context) pairs = step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs( ) assert set(pairs) == { (0.0, (None, ('tensorflow', '1.9.0', 'https://thoth-station.ninja/simple'))), (0.0, (None, ('tensorflow', '2.0.0', 'https://thoth-station.ninja/simple'))), (0.0, (('tensorflow', '1.9.0', 'https://thoth-station.ninja/simple'), ('numpy', '1.0.0', 'https://pypi.org/simple'))), (0.0, (('tensorflow', '1.9.0', 'https://thoth-station.ninja/simple'), ('numpy', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('tensorflow', '2.0.0', 'https://thoth-station.ninja/simple'), ('numpy', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('tensorflow', '2.0.0', 'https://thoth-station.ninja/simple'), ('numpy', '1.0.0', 'https://pypi.org/simple'))), } assert set(pv.to_tuple() for pv in step_context.iter_direct_dependencies()) == { ("tensorflow", "1.9.0", "https://thoth-station.ninja/simple"), ("tensorflow", "2.0.0", "https://thoth-station.ninja/simple"), }
def test_multiple_observation(self): """Test adjustment based on multiple observations..""" source = Source("https://pypi.org/simple") direct_dependencies = { ("a", "2.0.0", source.url): PackageVersion( name="a", version="==2.0.0", index=source, develop=False, ), ("a", "3.0.0", source.url): PackageVersion( name="a", version="==3.0.0", index=source, develop=False, ), ("a", "1.0.0", source.url): PackageVersion( name="a", version="==1.0.0", index=source, develop=False, ), } from itertools import product paths_long = list( product( ( ("a", "3.0.0", "https://pypi.org/simple"), ("a", "2.0.0", "https://pypi.org/simple"), ("a", "1.0.0", "https://pypi.org/simple"), ), ( ("b", "3.0.0", "https://pypi.org/simple"), ("b", "2.0.0", "https://pypi.org/simple"), ("b", "1.0.0", "https://pypi.org/simple"), ), ( ("c", "3.0.0", "https://pypi.org/simple"), ("c", "2.0.0", "https://pypi.org/simple"), ("c", "1.0.0", "https://pypi.org/simple"), ), )) paths = {} for item in paths_long: if item[0] not in paths: paths[item[0]] = [] for idx in range(len(item) - 1): paths[item[0]].append((item[idx], item[idx + 1])) step_context = StepContext.from_paths(direct_dependencies, paths=paths) # Possibly resolved | Score | A B C | # =========================|=============|================|======================================== # A1 a==1, b==1, c==1 | -1.0 | - | Removed - no positive observations. # A2 a==1, b==1, c==2 | -0.5 | - + | Kept because of c. # A3 a==1, b==1, c==3 | -1.0 | - | Removed - no positive observations. # A4 a==1, b==2, c==1 | 1.0 | - + | Removed - c==2 is better. # A5 a==1, b==2, c==2 | 1.5 | - + + | Kept because of b and c. # A6 a==1, b==2, c==3 | 1.0 | - + | Removed because c==2 is better. # A7 a==1, b==3, c==1 | -1.0 | - | Removed - no positive observations. # A8 a==1, b==3, c==2 | -0.5 | - + | Kept because of c. # A9 a==1, b==3, c==3 | -1.0 | - | Removed - c==2 is better. # # B1 a==2, b==1, c==1 | | | See A1. # B2 a==2, b==1, c==2 | 0.5 | + | See A2. # B3 a==2, b==1, c==3 | | | See A3. # B4 a==2, b==2, c==1 | 2.0 | + | See A4. # B5 a==2, b==2, c==2 | 2.5 | + + | See A5. # B6 a==2, b==2, c==3 | 2.0 | + | See A6. # B7 a==2, b==3, c==1 | | | See A7. # B8 a==2, b==3, c==2 | 0.5 | + | See A8. # B9 a==2, b==3, c==3 | | | See A9. # # C1 a==3, b==1, c==1 | | + | See B1. # C2 a==3, b==1, c==2 | 0.5 | + + | See B2. # C3 a==3, b==1, c==3 | | + | See B3. # C4 a==3, b==2, c==1 | 2.0 | + + | See B4. # C5 a==3, b==2, c==2 | 2.5 | + + + | See B5. # C6 a==3, b==2, c==3 | 2.0 | + + | See B6. # C7 a==3, b==3, c==1 | | + | See B7. # C8 a==3, b==3, c==2 | 0.5 | + + | See B8. # C9 a==3, b==3, c==3 | | + | See B9. # # # Note sub-graphs are shared so B1-9 and C1-9 share reasoning with A1-9. # step_context.score_package_tuple( ("a", "1.0.0", "https://pypi.org/simple"), -1.0) step_context.score_package_tuple( ("a", "3.0.0", "https://pypi.org/simple"), 5.0) step_context.score_package_tuple( ("b", "2.0.0", "https://pypi.org/simple"), 2.0) step_context.score_package_tuple( ("c", "2.0.0", "https://pypi.org/simple"), 0.5) observation_reduction = ObservationReduction( graph=None, project=None, library_usage=None, ) observation_reduction.run(step_context) observation_reduced = step_context.dependency_graph_adaptation.to_scored_package_tuple_pairs( ) assert set(observation_reduced) == { (-1.0, (None, ('a', '1.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '1.0.0', 'https://pypi.org/simple'), ('b', '1.0.0', 'https://pypi.org/simple'))), (2.0, (('a', '1.0.0', 'https://pypi.org/simple'), ('b', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '1.0.0', 'https://pypi.org/simple'), ('b', '3.0.0', 'https://pypi.org/simple'))), (0.0, (None, ('a', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '2.0.0', 'https://pypi.org/simple'), ('b', '1.0.0', 'https://pypi.org/simple'))), (2.0, (('a', '2.0.0', 'https://pypi.org/simple'), ('b', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '2.0.0', 'https://pypi.org/simple'), ('b', '3.0.0', 'https://pypi.org/simple'))), (5.0, (None, ('a', '3.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '3.0.0', 'https://pypi.org/simple'), ('b', '3.0.0', 'https://pypi.org/simple'))), (2.0, (('a', '3.0.0', 'https://pypi.org/simple'), ('b', '2.0.0', 'https://pypi.org/simple'))), (0.0, (('a', '3.0.0', 'https://pypi.org/simple'), ('b', '1.0.0', 'https://pypi.org/simple'))), (0.5, (('b', '2.0.0', 'https://pypi.org/simple'), ('c', '2.0.0', 'https://pypi.org/simple'))), (0.5, (('b', '3.0.0', 'https://pypi.org/simple'), ('c', '2.0.0', 'https://pypi.org/simple'))), (0.5, (('b', '1.0.0', 'https://pypi.org/simple'), ('c', '2.0.0', 'https://pypi.org/simple'))), }
def test_iter_dependencies(self) -> None: source = Source("https://pypi.org/simple") direct_dependencies = { ("flask", "0.12.1", "https://pypi.org/simple"): PackageVersion( name="flask", version="==0.12.1", index=source, develop=False, ), ("pytest", "5.0.1", "https://pypi.org/simple"): PackageVersion( name="pytest", version="==5.0.1", index=source, develop=True, ), ("flask", "1.0.2", "https://pypi.org/simple"): PackageVersion( name="flask", version="==1.0.2", index=source, develop=False, ), } paths = { ("flask", "0.12.1", "https://pypi.org/simple"): [ (("flask", "0.12.1", "https://pypi.org/simple"), ("werkzeug", "0.15.5", "https://pypi.org/simple")), ], ("flask", "1.0.2", "https://pypi.org/simple"): [ (("flask", "1.0.2", "https://pypi.org/simple"), ("werkzeug", "0.15.5", "https://pypi.org/simple")), ], ("pytest", "5.0.1", "https://pypi.org/simple"): [ (("pytest", "5.0.1", "https://pypi.org/simple"), ("pytest-cov", "2.7.1", "https://pypi.org/simple")), ], } step_context = StepContext.from_paths(direct_dependencies, paths=paths) all_dependencies = set( pv.to_tuple() for pv in step_context.iter_all_dependencies(develop=None)) assert len(all_dependencies) == 5 assert all_dependencies == { ("flask", "0.12.1", "https://pypi.org/simple"), ("pytest", "5.0.1", "https://pypi.org/simple"), ("flask", "1.0.2", "https://pypi.org/simple"), ("werkzeug", "0.15.5", "https://pypi.org/simple"), ("pytest-cov", "2.7.1", "https://pypi.org/simple"), } all_develop_dependencies = set( pv.to_tuple() for pv in step_context.iter_all_dependencies(develop=True)) assert all_develop_dependencies == { ("pytest", "5.0.1", "https://pypi.org/simple"), ("pytest-cov", "2.7.1", "https://pypi.org/simple"), } all_nondevelop_dependencies = set( pv.to_tuple() for pv in step_context.iter_all_dependencies(develop=False)) assert all_nondevelop_dependencies == { ("flask", "0.12.1", "https://pypi.org/simple"), ("flask", "1.0.2", "https://pypi.org/simple"), ("werkzeug", "0.15.5", "https://pypi.org/simple"), } transitive_nondevelop_dependencies = set( pv.to_tuple() for pv in step_context.iter_transitive_dependencies(develop=False)) assert transitive_nondevelop_dependencies == { ("werkzeug", "0.15.5", "https://pypi.org/simple"), } transitive_develop_dependencies = set( pv.to_tuple() for pv in step_context.iter_transitive_dependencies(develop=True)) assert transitive_develop_dependencies == { ("pytest-cov", "2.7.1", "https://pypi.org/simple"), } direct_develop_dependencies = set( pv.to_tuple() for pv in step_context.iter_direct_dependencies(develop=True)) assert direct_develop_dependencies == { ("pytest", "5.0.1", "https://pypi.org/simple"), } direct_nondevelop_dependencies = set( pv.to_tuple() for pv in step_context.iter_direct_dependencies(develop=False)) assert direct_nondevelop_dependencies == { ("flask", "0.12.1", "https://pypi.org/simple"), ("flask", "1.0.2", "https://pypi.org/simple"), }