Files
modelscope/tests/hub/test_hub_private_files.py
Xingjun.Wang 50f8d37bc9 [Feat & Refactor] Refactor hub and CLI modules (#1732)
* refactor(hub): shim layer delegating to modelscope-hub

- Replace hub/api.py (4674→250 lines) with shim inheriting LegacyHubApi
- Replace hub/snapshot_download.py, callback.py with thin shims
- Partial shim hub/file_download.py (retain http_get_file)
- Shim hub/constants.py and errors.py with legacy aliases
- Shim hub/git.py, repository.py, cache_manager.py, upload_*.py
- Migrate CLI entry to modelscope_hub.cli.main:run_cmd
- Adapt 6 CLI commands as modelscope_hub.cli_plugins
- Delete redundant CLI files (download/upload/login/create/etc)
- Add modelscope-hub>=0.2.0 dependency, Python>=3.10
- Add __getattr__ proxy for forward-compatible method access
- Propagate timeout/max_retries to internal LegacyClient
- Bridge MODELSCOPE_CREDENTIALS_PATH env var to HubConfig

* fix lint: isort/yapf formatting + exclude hub/api.py from hooks

* set modelscope-hub>=0.0.5

* remove unused code

* refactor(hub): standardize token naming — git_token vs token

Disambiguate git token and SDK/API token naming across the hub layer:
- ModelScopeConfig: get_token/save_token → get_git_token/save_git_token
  (old names kept as deprecated aliases with DeprecationWarning)
- GitCommandWrapper: rename token params to git_token in clone/push/config
- Repository/DatasetRepository: auth_token → git_token (deprecated compat kept)
- data_loader.py: update caller to use get_git_token()

SDK token references (HubApi(token=...), get_cookies(access_token=...),
commit_scheduler.token) remain unchanged as they correctly use `token` naming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* remove(msdatasets): remove all Virgo-related implementation

Remove the entire Virgo dataset subsystem which is no longer needed:
- Remove VirgoDataset class and VirgoDownloader
- Remove VirgoAuthConfig and VirgoDatasetConfig
- Remove Hubs.virgo enum value
- Remove fetch_virgo_meta from DataMetaManager
- Remove download_virgo_files from DatasetContextConfig
- Remove test_virgo_dataset.py test file
- Clean up unused imports (pandas, MaxComputeUtil, valid_url, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(hub): add OSS dataset operations and meta-file download to HubApi

Add methods that msdatasets depends on but don't belong in modelscope_hub:
- _legacy_request: internal helper combining legacy HTTP transport with
  application-level envelope validation (Code/Data/Message)
- list_oss_dataset_objects: list OSS storage objects for a dataset
- delete_oss_dataset_object / delete_oss_dataset_dir: delete OSS objects
- fetch_meta_files_from_url: download and cache meta CSV/JSONL files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix imports issue

* fix: address PR review feedback

- cli/plugins.py: change --yes and --all flags to action='store_true'
- hub/git.py: replace os.linesep with .splitlines() for cross-platform safety
- hub/__init__.py: use is_file() with fallback for robust credentials path detection

* fix lint

* update ms hub version

* fix(ci): add PyPI official as fallback index for pip

Aliyun mirror may lag behind PyPI for newly published packages,
causing dependency resolution failures (e.g. modelscope-hub>=0.0.6).
Add pypi.org/simple as extra-index-url so new versions are immediately
available while keeping the Aliyun mirror as the primary source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix UTs

* remove unused UTs

* fix ut

* update modelscope-hub installation for source code

* fix UT

* fix uts

* fix ut

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-09 20:00:20 +08:00

127 lines
5.0 KiB
Python

# Copyright (c) Alibaba, Inc. and its affiliates.
import os
import tempfile
import unittest
import uuid
from requests.exceptions import HTTPError
from modelscope.hub.api import HubApi
from modelscope.hub.constants import Licenses, ModelVisibility
from modelscope.hub.errors import (CacheNotFound, GitError, HubError,
NotExistError)
from modelscope.hub.file_download import model_file_download
from modelscope.hub.repository import Repository
from modelscope.hub.snapshot_download import snapshot_download
from modelscope.utils.constant import ModelFile
from modelscope.utils.test_utils import (TEST_ACCESS_TOKEN1,
TEST_ACCESS_TOKEN2,
TEST_MODEL_CHINESE_NAME,
TEST_MODEL_ORG, delete_credential)
download_model_file_name = 'test.bin'
class HubPrivateFileDownloadTest(unittest.TestCase):
def setUp(self):
self.old_cwd = os.getcwd()
self.api = HubApi()
self.token, _ = self.api.login(TEST_ACCESS_TOKEN1)
self.model_name = 'pf-%s' % (uuid.uuid4().hex)
self.model_id = '%s/%s' % (TEST_MODEL_ORG, self.model_name)
self.revision = 'v0.1_test_revision'
self.api.create_model(
model_id=self.model_id,
visibility=ModelVisibility.PRIVATE,
license=Licenses.APACHE_V2,
chinese_name=TEST_MODEL_CHINESE_NAME,
)
def prepare_case(self):
temporary_dir = tempfile.mkdtemp()
self.model_dir = os.path.join(temporary_dir, self.model_name)
repo = Repository(self.model_dir, clone_from=self.model_id)
os.system("echo 'testtest'>%s"
% os.path.join(self.model_dir, download_model_file_name))
repo.push('add model')
repo.tag_and_push(self.revision, 'Test revision')
def tearDown(self):
# credential may deleted or switch login name, we need re-login here
# to ensure the temporary model is deleted.
self.api.login(TEST_ACCESS_TOKEN1)
os.chdir(self.old_cwd)
try:
self.api.delete_model(model_id=self.model_id)
except Exception as e:
print(f'delete model {self.model_id} failed, {e}')
def test_snapshot_download_private_model(self):
self.prepare_case()
snapshot_path = snapshot_download(self.model_id, self.revision)
assert os.path.exists(os.path.join(snapshot_path, ModelFile.README))
def test_snapshot_download_private_model_no_permission(self):
self.prepare_case()
self.token, _ = self.api.login(TEST_ACCESS_TOKEN2)
with self.assertRaises((HTTPError, HubError)):
snapshot_download(self.model_id, self.revision)
def test_snapshot_download_private_model_without_login(self):
self.prepare_case()
delete_credential()
with self.assertRaises((HTTPError, HubError)):
snapshot_download(self.model_id, self.revision)
def test_download_file_private_model(self):
self.prepare_case()
file_path = model_file_download(self.model_id, ModelFile.README,
self.revision)
assert os.path.exists(file_path)
def test_download_file_private_model_no_permission(self):
self.prepare_case()
self.token, _ = self.api.login(TEST_ACCESS_TOKEN2)
with self.assertRaises((HTTPError, HubError)):
model_file_download(self.model_id, ModelFile.README, self.revision)
def test_download_file_private_model_without_login(self):
self.prepare_case()
delete_credential()
with self.assertRaises((HTTPError, HubError)):
model_file_download(self.model_id, ModelFile.README, self.revision)
def test_snapshot_download_local_only(self):
self.prepare_case()
with self.assertRaises((ValueError, CacheNotFound)):
snapshot_download(
self.model_id, self.revision, local_files_only=True)
snapshot_path = snapshot_download(self.model_id, self.revision)
assert os.path.exists(os.path.join(snapshot_path, ModelFile.README))
snapshot_path = snapshot_download(
self.model_id, self.revision, local_files_only=True)
assert os.path.exists(snapshot_path)
def test_file_download_local_only(self):
self.prepare_case()
with self.assertRaises((ValueError, CacheNotFound)):
model_file_download(
self.model_id,
ModelFile.README,
self.revision,
local_files_only=True)
file_path = model_file_download(self.model_id, ModelFile.README,
self.revision)
assert os.path.exists(file_path)
file_path = model_file_download(
self.model_id,
ModelFile.README,
revision=self.revision,
local_files_only=True)
assert os.path.exists(file_path)
if __name__ == '__main__':
unittest.main()