1010import pytest
1111
1212from cleo .io .null_io import NullIO
13+ from packaging .utils import NormalizedName
1314from packaging .utils import canonicalize_name
1415from poetry .core .packages .dependency import Dependency
1516from poetry .core .packages .directory_dependency import DirectoryDependency
2425from poetry .packages import DependencyPackage
2526from poetry .puzzle .provider import IncompatibleConstraintsError
2627from poetry .puzzle .provider import Provider
28+ from poetry .repositories .cached_repository import CachedRepository
2729from poetry .repositories .exceptions import PackageNotFoundError
2830from poetry .repositories .repository import Repository
2931from poetry .repositories .repository_pool import Priority
3638if TYPE_CHECKING :
3739 from pathlib import Path
3840
41+ from poetry .core .constraints .version import Version
3942 from pytest_mock import MockerFixture
4043
4144 from tests .types import FixtureDirGetter
@@ -49,6 +52,18 @@ def run(self, bin: str, *args: str, **kwargs: Any) -> str:
4952 raise EnvCommandError (CalledProcessError (1 , "python" , output = "" ))
5053
5154
55+ class MockCachedRepository (CachedRepository ):
56+ def _get_release_info (
57+ self , name : NormalizedName , version : Version
58+ ) -> dict [str , Any ]:
59+ raise NotImplementedError
60+
61+ def package (self , name : str , version : Version ) -> Package :
62+ package = super ().package (name , version )
63+ package ._source_reference = self .name
64+ return package
65+
66+
5267@pytest .fixture
5368def root () -> ProjectPackage :
5469 return ProjectPackage ("root" , "1.2.3" )
@@ -72,6 +87,46 @@ def provider(root: ProjectPackage, pool: RepositoryPool) -> Provider:
7287 return Provider (root , pool , NullIO ())
7388
7489
90+ @pytest .fixture
91+ def release_info () -> PackageInfo :
92+ return PackageInfo (
93+ name = "mylib" ,
94+ version = "1.0" ,
95+ summary = "" ,
96+ requires_dist = [],
97+ requires_python = ">=3.9" ,
98+ files = [
99+ {
100+ "file" : "mylib-1.0-py3-none-any.whl" ,
101+ "hash" : "sha256:dummyhashvalue1234567890abcdef" ,
102+ },
103+ {
104+ "file" : "mylib-1.0.tar.gz" ,
105+ "hash" : "sha256:anotherdummyhashvalueabcdef1234567890" ,
106+ },
107+ ],
108+ cache_version = str (CachedRepository .CACHE_VERSION ),
109+ )
110+
111+
112+ @pytest .fixture
113+ def outdated_release_info () -> PackageInfo :
114+ return PackageInfo (
115+ name = "mylib" ,
116+ version = "1.0" ,
117+ summary = "" ,
118+ requires_dist = [],
119+ requires_python = ">=3.9" ,
120+ files = [
121+ {
122+ "file" : "mylib-1.0-py3-none-any.whl" ,
123+ "hash" : "sha256:dummyhashvalue1234567890abcdef" ,
124+ }
125+ ],
126+ cache_version = str (CachedRepository .CACHE_VERSION ),
127+ )
128+
129+
75130@pytest .mark .parametrize (
76131 "dependency, expected" ,
77132 [
@@ -856,6 +911,43 @@ def test_complete_package_raises_packagenotfound_if_locked_source_not_available(
856911 provider .complete_package (locked )
857912
858913
914+ def test_complete_package_outdated_cache (
915+ root : ProjectPackage ,
916+ release_info : PackageInfo ,
917+ outdated_release_info : PackageInfo ,
918+ mocker : MockerFixture ,
919+ ) -> None :
920+ repo = MockCachedRepository ("repo" )
921+ pool = RepositoryPool ()
922+ pool .add_repository (repo )
923+ provider = Provider (root , pool , NullIO ())
924+ pool_refresh_spy = mocker .spy (provider .pool , "refresh" )
925+
926+ assert release_info .name is not None
927+ assert release_info .version is not None
928+ package = Package (release_info .name , release_info .version )
929+ package .files = release_info .files # up-to-date files from lock
930+
931+ # trigger caching of outdated info
932+ repo ._get_release_info = lambda name , version : outdated_release_info .asdict () # type: ignore[method-assign]
933+ assert len (repo .package (package .name , package .version ).files ) == 1
934+
935+ # additional files uploaded -> refresh needed
936+ repo ._get_release_info = lambda name , version : release_info .asdict () # type: ignore[method-assign]
937+ complete_package = provider .complete_package (
938+ DependencyPackage (package .to_dependency (), package )
939+ )
940+ assert len (complete_package .package .files ) == 2
941+ assert pool_refresh_spy .call_count == 1
942+
943+ # cache should have been updated -> no additional refresh needed
944+ complete_package = provider .complete_package (
945+ DependencyPackage (package .to_dependency (), package )
946+ )
947+ assert len (complete_package .package .files ) == 2
948+ assert pool_refresh_spy .call_count == 1
949+
950+
859951def test_source_dependency_is_satisfied_by_direct_origin (
860952 provider : Provider , repository : Repository
861953) -> None :
0 commit comments