🐛 fix(clearcache): fix single model cache path (#1724)

* 🐛 fix(clearcache): fix single model cache path

- Add 'models' subdirectory under 'hub' for single model cache paths
- Align dataset and model path structures for consistency

* 🐛 fix(clearcache): use cache root helpers to handle MODELSCOPE_CACHE correctly

Unconditionally prepending `hub/` broke `$MODELSCOPE_CACHE`-set users,
since the cache root has no `hub/` segment in that case. Reuse
get_model_cache_root() / get_dataset_cache_root() from file_utils,
which already handle both default and env-set layouts. Add tests
covering both scenarios.

---------

Co-authored-by: Yunnglin <mao.looper@qq.com>
This commit is contained in:
AAAkater
2026-06-03 18:39:39 +08:00
committed by GitHub
parent 8bab4b9bc1
commit 2719754beb
2 changed files with 55 additions and 9 deletions

View File

@@ -2,11 +2,13 @@
import os
import shutil
from argparse import ArgumentParser
from pathlib import Path
from modelscope.cli.base import CLICommand
from modelscope.hub.constants import TEMPORARY_FOLDER_NAME
from modelscope.hub.utils.utils import get_model_masked_directory
from modelscope.utils.file_utils import (get_dataset_cache_root,
get_model_cache_root,
get_modelscope_cache_dir)
def subparser_func(args):
@@ -20,9 +22,7 @@ class ClearCacheCMD(CLICommand):
def __init__(self, args):
self.args = args
self.cache_dir = os.getenv(
'MODELSCOPE_CACHE',
Path.home().joinpath('.cache', 'modelscope'))
self.cache_dir = get_modelscope_cache_dir()
@staticmethod
def define_args(parsers: ArgumentParser):
@@ -76,11 +76,11 @@ class ClearCacheCMD(CLICommand):
self._remove_directory(self.cache_dir)
print('Cache cleared.')
else:
entity_directory = os.path.join(
self.cache_dir, 'hub' if single_model else 'datasets', id)
temp_directory = os.path.join(
self.cache_dir, 'hub' if single_model else 'datasets',
TEMPORARY_FOLDER_NAME, id)
entity_root = get_model_cache_root(
) if single_model else get_dataset_cache_root()
entity_directory = os.path.join(entity_root, id)
temp_directory = os.path.join(entity_root,
TEMPORARY_FOLDER_NAME, id)
entity_removed = self._remove_directory(entity_directory)
temp_removed = self._remove_directory(temp_directory)
if (not entity_removed) and (not temp_removed):

View File

@@ -1,8 +1,12 @@
import os
import subprocess
import sys
import tempfile
import unittest
from argparse import Namespace
from unittest import mock
from modelscope.hub.constants import TEMPORARY_FOLDER_NAME
from modelscope.utils.file_utils import get_modelscope_cache_dir
@@ -36,5 +40,47 @@ class TestScanCacheCommand(unittest.TestCase):
self.assertIn('not found', output)
class TestClearCacheCommand(unittest.TestCase):
"""clear-cache must resolve the right cache root in both scenarios:
* MODELSCOPE_CACHE set -> $MODELSCOPE_CACHE/{models,datasets}/<id>
* MODELSCOPE_CACHE unset -> ~/.cache/modelscope/hub/{models,datasets}/<id>
"""
def _clear_and_assert(self, root, kind, entity_id):
from modelscope.cli.clearcache import ClearCacheCMD
sub = {'model': 'models', 'dataset': 'datasets'}[kind]
entity_dir = os.path.join(root, sub, entity_id)
temp_dir = os.path.join(root, sub, TEMPORARY_FOLDER_NAME, entity_id)
os.makedirs(entity_dir)
os.makedirs(temp_dir)
args = Namespace(
model=entity_id if kind == 'model' else None,
dataset=entity_id if kind == 'dataset' else None)
with mock.patch('builtins.input', return_value='Y'):
ClearCacheCMD(args).execute()
self.assertFalse(os.path.exists(entity_dir))
self.assertFalse(os.path.exists(temp_dir))
def test_env_cache(self):
with tempfile.TemporaryDirectory() as tmp, \
mock.patch.dict(os.environ,
{'MODELSCOPE_CACHE': tmp}, clear=False):
for kind in ('model', 'dataset'):
with self.subTest(kind=kind):
self._clear_and_assert(tmp, kind, f'org/{kind}')
def test_default_cache(self):
with tempfile.TemporaryDirectory() as tmp:
env = {
k: v
for k, v in os.environ.items() if k != 'MODELSCOPE_CACHE'
}
env['HOME'] = tmp
with mock.patch.dict(os.environ, env, clear=True):
self._clear_and_assert(
os.path.join(tmp, '.cache', 'modelscope', 'hub'), 'model',
'org/repo')
if __name__ == '__main__':
unittest.main()