22
33from copy import deepcopy
44from typing import TYPE_CHECKING
5+ from unittest import mock
56
67from poetry .factory import Factory
78from poetry .mixology .version_solver import DependencyCache
@@ -32,14 +33,14 @@ def test_solver_dependency_cache_respects_source_type(
3233 cache .search_for .cache_clear ()
3334
3435 # ensure cache was never hit for both calls
35- cache .search_for (dependency_pypi )
36- cache .search_for (dependency_git )
36+ cache .search_for (dependency_pypi , 0 )
37+ cache .search_for (dependency_git , 0 )
3738 assert not cache .search_for .cache_info ().hits
3839
3940 # increase test coverage by searching for copies
4041 # (when searching for the exact same object, __eq__ is never called)
41- packages_pypi = cache .search_for (deepcopy (dependency_pypi ))
42- packages_git = cache .search_for (deepcopy (dependency_git ))
42+ packages_pypi = cache .search_for (deepcopy (dependency_pypi ), 0 )
43+ packages_git = cache .search_for (deepcopy (dependency_git ), 0 )
4344
4445 assert cache .search_for .cache_info ().hits == 2
4546 assert cache .search_for .cache_info ().currsize == 2
@@ -60,6 +61,44 @@ def test_solver_dependency_cache_respects_source_type(
6061 assert package_git .package .source_resolved_reference == MOCK_DEFAULT_GIT_REVISION
6162
6263
64+ def test_solver_dependency_cache_pulls_from_prior_level_cache (
65+ root : ProjectPackage , provider : Provider , repo : Repository
66+ ) -> None :
67+ dependency_pypi = Factory .create_dependency ("demo" , ">=0.1.0" )
68+ root .add_dependency (dependency_pypi )
69+ add_to_repo (repo , "demo" , "1.0.0" )
70+
71+ wrapped_provider = mock .Mock (wraps = provider )
72+ cache = DependencyCache (wrapped_provider )
73+ cache .search_for .cache_clear ()
74+
75+ # On first call, provider.search_for() should be called and the level-0
76+ # cache populated.
77+ cache .search_for (dependency_pypi , 0 )
78+ assert len (wrapped_provider .search_for .mock_calls ) == 1
79+ assert ("demo" , None , None , None , None ) in cache ._cache [0 ]
80+ assert cache .search_for .cache_info ().hits == 0
81+ assert cache .search_for .cache_info ().misses == 1
82+
83+ # On second call at level 1, provider.search_for() should not be called
84+ # again and the level-1 cache should be populated from the level-0 cache.
85+ cache .search_for (dependency_pypi , 1 )
86+ assert len (wrapped_provider .search_for .mock_calls ) == 1
87+ assert ("demo" , None , None , None , None ) in cache ._cache [1 ]
88+ assert cache ._cache [0 ] == cache ._cache [1 ]
89+ assert cache .search_for .cache_info ().hits == 0
90+ assert cache .search_for .cache_info ().misses == 2
91+
92+ # Clearing the level 1 cache should invalidate the lru_cache on
93+ # cache.search_for and wipe out the level 1 cache while preserving the
94+ # level 0 cache.
95+ cache .clear_level (1 )
96+ assert set (cache ._cache .keys ()) == {0 }
97+ assert ("demo" , None , None , None , None ) in cache ._cache [0 ]
98+ assert cache .search_for .cache_info ().hits == 0
99+ assert cache .search_for .cache_info ().misses == 0
100+
101+
63102def test_solver_dependency_cache_respects_subdirectories (
64103 root : ProjectPackage , provider : Provider , repo : Repository
65104) -> None :
@@ -87,14 +126,14 @@ def test_solver_dependency_cache_respects_subdirectories(
87126 cache .search_for .cache_clear ()
88127
89128 # ensure cache was never hit for both calls
90- cache .search_for (dependency_one )
91- cache .search_for (dependency_one_copy )
129+ cache .search_for (dependency_one , 0 )
130+ cache .search_for (dependency_one_copy , 0 )
92131 assert not cache .search_for .cache_info ().hits
93132
94133 # increase test coverage by searching for copies
95134 # (when searching for the exact same object, __eq__ is never called)
96- packages_one = cache .search_for (deepcopy (dependency_one ))
97- packages_one_copy = cache .search_for (deepcopy (dependency_one_copy ))
135+ packages_one = cache .search_for (deepcopy (dependency_one ), 0 )
136+ packages_one_copy = cache .search_for (deepcopy (dependency_one_copy ), 0 )
98137
99138 assert cache .search_for .cache_info ().hits == 2
100139 assert cache .search_for .cache_info ().currsize == 2
0 commit comments