Repository: conan-io/conan
Pull request #16296 (2024-05-17 12:21:28)

Refactor/pkg cache
Changelog: Omit
Docs: Omit

Pure internal refactor, get rid of redundant ClientCache class in favor of PkgCache class


Patch:
diff --git a/conan/api/model.py b/conan/api/model.py
index 9e23cdfe1..025e20dd1 100644
--- a/conan/api/model.py
+++ b/conan/api/model.py
@@ -1,5 +1,6 @@
 import fnmatch
 import json
+import os
 
 from conans.client.graph.graph import RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_PLATFORM, \
     RECIPE_VIRTUAL, BINARY_SKIP, BINARY_MISSING, BINARY_INVALID
@@ -90,6 +91,8 @@ class MultiPackagesList:
 
     @staticmethod
     def load_graph(graphfile, graph_recipes=None, graph_binaries=None):
+        if not os.path.isfile(graphfile):
+            raise ConanException(f"Graph file not found: {graphfile}")
         graph = json.loads(load(graphfile))
         return MultiPackagesList._define_graph(graph, graph_recipes, graph_binaries)
 
diff --git a/conan/api/subapi/cache.py b/conan/api/subapi/cache.py
index 84f622014..77d8c6df8 100644
--- a/conan/api/subapi/cache.py
+++ b/conan/api/subapi/cache.py
@@ -6,10 +6,10 @@ from io import BytesIO
 
 from conan.api.model import PackagesList
 from conan.api.output import ConanOutput
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
 from conan.internal.conan_app import ConanApp
 from conan.internal.integrity_check import IntegrityChecker
-from conans.client.cache.cache import ClientCache
 from conans.client.downloaders.download_cache import DownloadCache
 from conans.errors import ConanException
 from conans.model.package_ref import PkgReference
@@ -119,7 +119,7 @@ class CacheAPI:
 
     def save(self, package_list, tgz_path):
         global_conf = self.conan_api.config.global_conf
-        cache = ClientCache(self.conan_api.cache_folder, global_conf)
+        cache = PkgCache(self.conan_api.cache_folder, global_conf)
         cache_folder = cache.store  # Note, this is not the home, but the actual package cache
         out = ConanOutput()
         mkdir(os.path.dirname(tgz_path))
@@ -161,7 +161,7 @@ class CacheAPI:
         if not os.path.isfile(path):
             raise ConanException(f"Restore archive doesn't exist in {path}")
 
-        cache = ClientCache(self.conan_api.cache_folder, self.conan_api.config.global_conf)
+        cache = PkgCache(self.conan_api.cache_folder, self.conan_api.config.global_conf)
         cache_folder = cache.store  # Note, this is not the home, but the actual package cache
 
         with open(path, mode='rb') as file_handler:
diff --git a/conan/internal/cache/cache.py b/conan/internal/cache/cache.py
index 2e42564e4..edb2bb94a 100644
--- a/conan/internal/cache/cache.py
+++ b/conan/internal/cache/cache.py
@@ -2,24 +2,51 @@ import hashlib
 import os
 import shutil
 import uuid
+from typing import List
 
 from conan.internal.cache.conan_reference_layout import RecipeLayout, PackageLayout
 # TODO: Random folders are no longer accessible, how to get rid of them asap?
-# TODO: Add timestamp for LRU
 # TODO: We need the workflow to remove existing references.
 from conan.internal.cache.db.cache_database import CacheDatabase
-from conans.errors import ConanReferenceAlreadyExistsInDB, ConanReferenceDoesNotExistInDB
+from conans.errors import ConanReferenceAlreadyExistsInDB, ConanReferenceDoesNotExistInDB, \
+    ConanException
 from conans.model.package_ref import PkgReference
 from conans.model.recipe_ref import RecipeReference
 from conans.util.dates import revision_timestamp_now
-from conans.util.files import rmdir, renamedir
+from conans.util.files import rmdir, renamedir, mkdir
 
 
-class DataCache:
+class PkgCache:
+    """ Class to represent the recipes and packages storage in disk
+    """
 
-    def __init__(self, base_folder, db_filename):
-        self._base_folder = os.path.abspath(base_folder)
-        self._db = CacheDatabase(filename=db_filename)
+    def __init__(self, cache_folder, global_conf):
+        # paths
+        self._store_folder = global_conf.get("core.cache:storage_path") or \
+                             os.path.join(cache_folder, "p")
+
+        try:
+            mkdir(self._store_folder)
+            db_filename = os.path.join(self._store_folder, 'cache.sqlite3')
+            self._base_folder = os.path.abspath(self._store_folder)
+            self._db = CacheDatabase(filename=db_filename)
+        except Exception as e:
+            raise ConanException(f"Couldn't initialize storage in {self._store_folder}: {e}")
+
+    @property
+    def store(self):
+        return self._base_folder
+
+    @property
+    def temp_folder(self):
+        """ temporary folder where Conan puts exports and packages before the final revision
+        is computed"""
+        # TODO: Improve the path definitions, this is very hardcoded
+        return os.path.join(self._base_folder, "t")
+
+    @property
+    def builds_folder(self):
+        return os.path.join(self._base_folder, "b")
 
     def _create_path(self, relative_path, remove_contents=True):
         path = self._full_path(relative_path)
@@ -45,34 +72,24 @@ class DataCache:
         return sha_bytes[0:13]
 
     @staticmethod
-    def _get_tmp_path(ref: RecipeReference):
-        # The reference will not have revision, but it will be always constant
-        h = ref.name[:5] + DataCache._short_hash_path(ref.repr_notime())
-        return os.path.join("t", h)
-
-    @staticmethod
-    def _get_tmp_path_pref(pref):
-        # The reference will not have revision, but it will be always constant
-        assert pref.revision is None
-        assert pref.timestamp is None
-        random_id = str(uuid.uuid4())
-        h = pref.ref.name[:5] + DataCache._short_hash_path(pref.repr_notime() + random_id)
-        return os.path.join("b", h)
-
-    @staticmethod
-    def _get_path(ref: RecipeReference):
-        return ref.name[:5] + DataCache._short_hash_path(ref.repr_notime())
+    def _get_path(ref):
+        return ref.name[:5] + PkgCache._short_hash_path(ref.repr_notime())
 
     @staticmethod
     def _get_path_pref(pref):
-        return pref.ref.name[:5] + DataCache._short_hash_path(pref.repr_notime())
+        return pref.ref.name[:5] + PkgCache._short_hash_path(pref.repr_notime())
 
     def create_export_recipe_layout(self, ref: RecipeReference):
-        # This is a temporary layout while exporting a new recipe, because the revision is not
-        # computed yet, until it is. The entry is not added to DB, just a temp folder is created
+        """  This is a temporary layout while exporting a new recipe, because the revision is not
+        computed until later. The entry is not added to DB, just a temp folder is created
+
+        This temporary export folder will be moved to permanent when revision is computed by the
+        assign_rrev() method
+        """
         assert ref.revision is None, "Recipe revision should be None"
         assert ref.timestamp is None
-        reference_path = self._get_tmp_path(ref)
+        h = ref.name[:5] + PkgCache._short_hash_path(ref.repr_notime())
+        reference_path = os.path.join("t", h)
         self._create_path(reference_path)
         return RecipeLayout(ref, os.path.join(self._base_folder, reference_path))
 
@@ -82,11 +99,14 @@ class DataCache:
         assert pref.package_id, "Package id must be known to get or create the package layout"
         assert pref.revision is None, "Package revision should be None"
         assert pref.timestamp is None
-        package_path = self._get_tmp_path_pref(pref)
+
+        random_id = str(uuid.uuid4())
+        h = pref.ref.name[:5] + PkgCache._short_hash_path(pref.repr_notime() + random_id)
+        package_path = os.path.join("b", h)
         self._create_path(package_path)
         return PackageLayout(pref, os.path.join(self._base_folder, package_path))
 
-    def get_recipe_layout(self, ref: RecipeReference):
+    def recipe_layout(self, ref: RecipeReference):
         """ the revision must exists, the folder must exist
         """
         if ref.revision is None:  # Latest one
@@ -97,10 +117,17 @@ class DataCache:
         ref = ref_data.get("ref")  # new revision with timestamp
         return RecipeLayout(ref, os.path.join(self._base_folder, ref_path))
 
+    def get_latest_recipe_reference(self, ref: RecipeReference):
+        assert ref.revision is None
+        ref_data = self._db.get_latest_recipe(ref)
+        return ref_data.get("ref")
+
     def get_recipe_revisions_references(self, ref: RecipeReference):
+        # For listing multiple revisions only
+        assert ref.revision is None
         return self._db.get_recipe_revisions_references(ref)
 
-    def get_package_layout(self, pref: PkgReference):
+    def pkg_layout(self, pref: PkgReference):
         """ the revision must exists, the folder must exist
         """
         assert pref.ref.revision, "Recipe revision must be known to get the package layout"
@@ -115,7 +142,7 @@ class DataCache:
         """ called by RemoteManager.get_recipe()
         """
         try:
-            return self.get_recipe_layout(ref)
+            return self.recipe_layout(ref)
         except ConanReferenceDoesNotExistInDB:
             assert ref.revision, "Recipe revision must be known to create the package layout"
             reference_path = self._get_path(ref)
@@ -127,7 +154,7 @@ class DataCache:
         """ called by RemoteManager.get_package() and  BinaryInstaller
         """
         try:
-            return self.get_package_layout(pref)
+            return self.pkg_layout(pref)
         except ConanReferenceDoesNotExistInDB:
             assert pref.ref.revision, "Recipe revision must be known to create the package layout"
             assert pref.package_id, "Package id must be known to create the package layout"
@@ -138,20 +165,25 @@ class DataCache:
             return PackageLayout(pref, os.path.join(self._base_folder, package_path))
 
     def update_recipe_timestamp(self, ref: RecipeReference):
+        """ when the recipe already exists in cache, but we get a new timestamp from a server
+        that would affect its order in our cache """
         assert ref.revision
         assert ref.timestamp
         self._db.update_recipe_timestamp(ref)
 
-    def list_references(self):
+    def all_refs(self):
         return self._db.list_references()
 
     def exists_prev(self, pref):
+        # Used just by download to skip downloads if prev already exists in cache
         return self._db.exists_prev(pref)
 
     def get_latest_package_reference(self, pref):
         return self._db.get_latest_package_reference(pref)
 
-    def get_package_references(self, ref: RecipeReference, only_latest_prev=True):
+    def get_package_references(self, ref: RecipeReference,
+                               only_latest_prev=True) -> List[PkgReference]:
+        """Get the latest package references"""
         return self._db.get_package_references(ref, only_latest_prev)
 
     def get_package_revisions_references(self, pref: PkgReference, only_latest_prev=False):
@@ -160,12 +192,12 @@ class DataCache:
     def get_matching_build_id(self, ref, build_id):
         return self._db.get_matching_build_id(ref, build_id)
 
-    def remove_recipe(self, layout: RecipeLayout):
+    def remove_recipe_layout(self, layout: RecipeLayout):
         layout.remove()
         # FIXME: This is clearing package binaries from DB, but not from disk/layout
         self._db.remove_recipe(layout.reference)
 
-    def remove_package(self, layout: PackageLayout):
+    def remove_package_layout(self, layout: PackageLayout):
         layout.remove()
         self._db.remove_package(layout.reference)
 
@@ -185,7 +217,7 @@ class DataCache:
         except ConanReferenceAlreadyExistsInDB:
             # TODO: Optimize this into 1 single UPSERT operation
             # There was a previous package folder for this same package reference (and prev)
-            pkg_layout = self.get_package_layout(pref)
+            pkg_layout = self.pkg_layout(pref)
             # We remove the old one and move the new one to the path of the previous one
             # this can be necessary in case of new metadata or build-folder because of "build_id()"
             pkg_layout.remove()
diff --git a/conan/internal/conan_app.py b/conan/internal/conan_app.py
index 41c6d204c..0f92e3eb2 100644
--- a/conan/internal/conan_app.py
+++ b/conan/internal/conan_app.py
@@ -1,8 +1,8 @@
 import os
 
 from conan.api.output import ConanOutput
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
-from conans.client.cache.cache import ClientCache
 from conans.client.graph.proxy import ConanProxy
 from conans.client.graph.python_requires import PyRequireLoader
 from conans.client.graph.range_resolver import RangeResolver
@@ -44,7 +44,7 @@ class ConanApp:
         cache_folder = conan_api.home_folder
         self._configure(global_conf)
         self.cache_folder = cache_folder
-        self.cache = ClientCache(self.cache_folder, global_conf)
+        self.cache = PkgCache(self.cache_folder, global_conf)
 
         home_paths = HomePaths(self.cache_folder)
         self.hook_manager = HookManager(home_paths.hooks_path)
diff --git a/conans/client/cache/cache.py b/conans/client/cache/cache.py
deleted file mode 100644
index 5fea2ccac..000000000
--- a/conans/client/cache/cache.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import os
-from typing import List
-
-from conan.internal.cache.cache import DataCache, RecipeLayout, PackageLayout
-from conans.errors import ConanException
-from conans.model.package_ref import PkgReference
-from conans.model.recipe_ref import RecipeReference
-from conans.util.files import mkdir
-
-
-# TODO: Rename this to ClientHome
-class ClientCache:
-    """ Class to represent/store/compute all the paths involved in the execution
-    of conans commands. Accesses to real disk and reads/write things. (OLD client ConanPaths)
-    """
-
-    def __init__(self, cache_folder, global_conf):
-        # paths
-        self._store_folder = global_conf.get("core.cache:storage_path") or \
-                             os.path.join(cache_folder, "p")
-
-        try:
-            mkdir(self._store_folder)
-            db_filename = os.path.join(self._store_folder, 'cache.sqlite3')
-            self._data_cache = DataCache(self._store_folder, db_filename)
-        except Exception as e:
-            raise ConanException(f"Couldn't initialize storage in {self._store_folder}: {e}")
-
-    @property
-    def temp_folder(self):
-        """ temporary folder where Conan puts exports and packages before the final revision
-        is computed"""
-        # TODO: Improve the path definitions, this is very hardcoded
-        return os.path.join(self._store_folder, "t")
-
-    @property
-    def builds_folder(self):
-        return os.path.join(self._store_folder, "b")
-
-    def create_export_recipe_layout(self, ref: RecipeReference):
-        return self._data_cache.create_export_recipe_layout(ref)
-
-    def assign_rrev(self, layout: RecipeLayout):
-        return self._data_cache.assign_rrev(layout)
-
-    def create_build_pkg_layout(self, ref):
-        return self._data_cache.create_build_pkg_layout(ref)
-
-    def assign_prev(self, layout: PackageLayout):
-        return self._data_cache.assign_prev(layout)
-
-    # Recipe methods
-    def recipe_layout(self, ref: RecipeReference):
-        return self._data_cache.get_recipe_layout(ref)
-
-    def get_latest_recipe_reference(self, ref):
-        # TODO: We keep this for testing only, to be removed
-        assert ref.revision is None
-        return self._data_cache.get_recipe_layout(ref).reference
-
-    def get_recipe_revisions_references(self, ref):
-        # For listing multiple revisions only
-        assert ref.revision is None
-        return self._data_cache.get_recipe_revisions_references(ref)
-
-    def pkg_layout(self, ref: PkgReference):
-        return self._data_cache.get_package_layout(ref)
-
-    def get_or_create_ref_layout(self, ref: RecipeReference):
-        return self._data_cache.get_or_create_ref_layout(ref)
-
-    def get_or_create_pkg_layout(self, ref: PkgReference):
-        return self._data_cache.get_or_create_pkg_layout(ref)
-
-    def remove_recipe_layout(self, layout):
-        self._data_cache.remove_recipe(layout)
-
-    def remove_package_layout(self, layout):
-        self._data_cache.remove_package(layout)
-
-    def remove_build_id(self, pref):
-        self._data_cache.remove_build_id(pref)
-
-    def update_recipe_timestamp(self, ref):
-        """ when the recipe already exists in cache, but we get a new timestamp from a server
-        that would affect its order in our cache """
-        return self._data_cache.update_recipe_timestamp(ref)
-
-    def all_refs(self):
-        return self._data_cache.list_references()
-
-    def exists_prev(self, pref):
-        # Used just by download to skip downloads if prev already exists in cache
-        return self._data_cache.exists_prev(pref)
-
-    def get_package_revisions_references(self, pref: PkgReference, only_latest_prev=False):
-        return self._data_cache.get_package_revisions_references(pref, only_latest_prev)
-
-    def get_package_references(self, ref: RecipeReference,
-                               only_latest_prev=True) -> List[PkgReference]:
-        """Get the latest package references"""
-        return self._data_cache.get_package_references(ref, only_latest_prev)
-
-    def get_matching_build_id(self, ref, build_id):
-        return self._data_cache.get_matching_build_id(ref, build_id)
-
-    def get_latest_package_reference(self, pref):
-        return self._data_cache.get_latest_package_reference(pref)
-
-    def get_recipe_lru(self, ref):
-        return self._data_cache.get_recipe_lru(ref)
-
-    def update_recipe_lru(self, ref):
-        self._data_cache.update_recipe_lru(ref)
-
-    def get_package_lru(self, pref):
-        return self._data_cache.get_package_lru(pref)
-
-    def update_package_lru(self, pref):
-        self._data_cache.update_package_lru(pref)
-
-    @property
-    def store(self):
-        return self._store_folder


Test patch:
diff --git a/conans/test/integration/command_v2/test_combined_pkglist_flows.py b/conans/test/integration/command_v2/test_combined_pkglist_flows.py
index fbd88317d..862400655 100644
--- a/conans/test/integration/command_v2/test_combined_pkglist_flows.py
+++ b/conans/test/integration/command_v2/test_combined_pkglist_flows.py
@@ -13,7 +13,7 @@ class TestListUpload:
 
     @pytest.fixture()
     def client(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({
             "zlib.py": GenConanfile("zlib"),
             "zli.py": GenConanfile("zli", "1.0.0")
@@ -54,7 +54,7 @@ class TestListUpload:
 
 class TestGraphCreatedUpload:
     def test_create_upload(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
         c.run("create zlib")
@@ -69,7 +69,7 @@ class TestGraphCreatedUpload:
 
 class TestExportUpload:
     def test_export_upload(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0")})
         c.run("export zlib --format=pkglist", redirect_stdout="pkglist.json")
         c.run("upload --list=pkglist.json -r=default -c")
@@ -77,29 +77,34 @@ class TestExportUpload:
 
 
 class TestCreateGraphToPkgList:
+    def test_graph_pkg_nonexistant(self):
+        c = TestClient(light=True)
+        c.run("list --graph=non-existent-file.json", assert_error=True)
+        assert "ERROR: Graph file not found" in c.out
+
     def test_graph_pkg_list_only_built(self):
-        c = TestClient()
+        c = TestClient(light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")
                                                               .with_settings("os")
                                                               .with_shared_option(False)})
         c.run("create zlib")
-        c.run("create app --format=json -s os=Windows", redirect_stdout="graph.json")
+        c.run("create app --format=json -s os=Linux", redirect_stdout="graph.json")
         c.run("list --graph=graph.json --graph-binaries=build --format=json")
         pkglist = json.loads(c.stdout)["Local Cache"]
         assert len(pkglist) == 1
         pkgs = pkglist["app/1.0"]["revisions"]["8263c3c32802e14a2f03a0b1fcce0d95"]["packages"]
         assert len(pkgs) == 1
-        pkg_app = pkgs["e0bcc80c3f095670b71e535c193114d0155426cb"]
+        pkg_app = pkgs["d8b3bdd894c3eb9bf2a3119ee0f8c70843ace0ac"]
         assert pkg_app["info"]["requires"] == ["zlib/1.0.Z"]
-        assert pkg_app["info"]["settings"] == {'os': 'Windows'}
+        assert pkg_app["info"]["settings"] == {'os': 'Linux'}
         assert pkg_app["info"]["options"] == {'shared': 'False'}
 
     def test_graph_pkg_list_all_recipes_only(self):
         """
         --graph-recipes=* selects all the recipes in the graph
         """
-        c = TestClient()
+        c = TestClient(light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
         c.run("create zlib")
@@ -114,7 +119,7 @@ class TestCreateGraphToPkgList:
         """
         include python_requires too
         """
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"pytool/conanfile.py": GenConanfile("pytool", "0.1"),
                 "zlib/conanfile.py": GenConanfile("zlib", "1.0").with_python_requires("pytool/0.1"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
@@ -135,7 +140,7 @@ class TestCreateGraphToPkgList:
         """
         include python_requires too
         """
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"conanfile.py": GenConanfile("pytool", "0.1").with_package_type("python-require")})
         c.run("create . --format=json", redirect_stdout="graph.json")
         c.run("list --graph=graph.json --format=json")
@@ -146,7 +151,7 @@ class TestCreateGraphToPkgList:
 
 class TestGraphInfoToPkgList:
     def test_graph_pkg_list_only_built(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({"zlib/conanfile.py": GenConanfile("zlib", "1.0"),
                 "app/conanfile.py": GenConanfile("app", "1.0").with_requires("zlib/1.0")})
         c.run("create zlib")
@@ -258,7 +263,7 @@ class TestPkgListMerge:
 class TestDownloadUpload:
     @pytest.fixture()
     def client(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({
             "zlib.py": GenConanfile("zlib"),
             "zli.py": GenConanfile("zli", "1.0.0")
@@ -315,7 +320,7 @@ class TestDownloadUpload:
 class TestListRemove:
     @pytest.fixture()
     def client(self):
-        c = TestClient(default_server_user=True)
+        c = TestClient(default_server_user=True, light=True)
         c.save({
             "zlib.py": GenConanfile("zlib"),
             "zli.py": GenConanfile("zli", "1.0.0")
diff --git a/conans/test/integration/graph/core/graph_manager_base.py b/conans/test/integration/graph/core/graph_manager_base.py
index 1889aacb2..a22e3245f 100644
--- a/conans/test/integration/graph/core/graph_manager_base.py
+++ b/conans/test/integration/graph/core/graph_manager_base.py
@@ -5,8 +5,8 @@ import unittest
 import yaml
 
 from conan.api.conan_api import ConanAPI
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
-from conans.client.cache.cache import ClientCache
 from conans.client.conf import default_settings_yml
 from conans.model.conf import ConfDefinition
 from conans.model.manifest import FileTreeManifest
@@ -24,7 +24,7 @@ class GraphManagerTest(unittest.TestCase):
 
     def setUp(self):
         cache_folder = temp_folder()
-        cache = ClientCache(cache_folder, ConfDefinition())
+        cache = PkgCache(cache_folder, ConfDefinition())
         home = HomePaths(cache_folder)
         save(os.path.join(home.profiles_path, "default"), "")
         save(home.settings_path, "os: [Windows, Linux]")
diff --git a/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py b/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py
index 1cd8ed1ba..360853968 100644
--- a/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py
+++ b/conans/test/unittests/client/profile_loader/compiler_cppstd_test.py
@@ -5,8 +5,8 @@ import unittest
 import yaml
 from jinja2 import Template
 
+from conan.internal.cache.cache import PkgCache
 from conan.internal.cache.home_paths import HomePaths
-from conans.client.cache.cache import ClientCache
 from conans.client.conf import default_settings_yml
 from conans.client.profile_loader import ProfileLoader
 from conans.errors import ConanException
@@ -20,7 +20,7 @@ class SettingsCppStdTests(unittest.TestCase):
 
     def setUp(self):
         self.cache_folder = temp_folder()
-        self.cache = ClientCache(self.cache_folder, ConfDefinition())
+        self.cache = PkgCache(self.cache_folder, ConfDefinition())
         self.home_paths = HomePaths(self.cache_folder)
         save(self.home_paths.profile_plugin_path, "")
 
diff --git a/conans/test/utils/tools.py b/conans/test/utils/tools.py
index 544b960f6..1ac1e4525 100644
--- a/conans/test/utils/tools.py
+++ b/conans/test/utils/tools.py
@@ -25,13 +25,12 @@ from requests.exceptions import HTTPError
 from webtest.app import TestApp
 
 from conan.cli.exit_codes import SUCCESS, ERROR_GENERAL
-from conan.internal.cache.cache import PackageLayout, RecipeLayout
+from conan.internal.cache.cache import PackageLayout, RecipeLayout, PkgCache
 from conan.internal.cache.home_paths import HomePaths
 from conans import REVISIONS
 from conan.api.conan_api import ConanAPI
 from conan.api.model import Remote
 from conan.cli.cli import Cli, _CONAN_INTERNAL_CUSTOM_COMMANDS_PATH
-from conans.client.cache.cache import ClientCache
 from conans.util.env import environment_update
 from conans.errors import NotFoundException, ConanException
 from conans.model.manifest import FileTreeManifest
@@ -442,9 +441,9 @@ class TestClient:
         api = ConanAPI(cache_folder=self.cache_folder)
         global_conf = api.config.global_conf
 
-        class MyCache(ClientCache, HomePaths):  # Temporary class to avoid breaking all tests
+        class MyCache(PkgCache, HomePaths):  # Temporary class to avoid breaking all tests
             def __init__(self, cache_folder):
-                ClientCache.__init__(self, cache_folder, global_conf)
+                PkgCache.__init__(self, cache_folder, global_conf)
                 HomePaths.__init__(self, cache_folder)
 
             @property