diff --git a/DashAI/back/credentials/kaggle_credential.py b/DashAI/back/credentials/kaggle_credential.py index b1e6bca34..b172cf544 100644 --- a/DashAI/back/credentials/kaggle_credential.py +++ b/DashAI/back/credentials/kaggle_credential.py @@ -2,6 +2,7 @@ import logging import os +import sys from typing import Final from DashAI.back.core.utils import MultilingualString @@ -9,11 +10,14 @@ logger = logging.getLogger(__name__) +_AUTH_METHOD_ACCESS_TOKEN: Final = "ACCESS_TOKEN" + class KaggleCredential(BaseCredential): """Credential for the Kaggle API. - The key is expected in the form ``"username:api_key"``. + The key is a single Kaggle API access token (e.g. ``"KGAT_..."``), generated + at ``https://www.kaggle.com/settings/api``. """ DISPLAY_NAME: Final = MultilingualString( @@ -24,65 +28,57 @@ class KaggleCredential(BaseCredential): zh="Kaggle", ) DESCRIPTION: Final = MultilingualString( - en="Kaggle API credential in the form 'username:key'.", - es="Credencial de la API de Kaggle en el formato 'usuario:clave'.", - pt="Credencial da API do Kaggle no formato 'usuario:chave'.", - de="Zugangsdaten für die Kaggle API im Format 'benutzername:schluessel'.", - zh="Kaggle API 凭证,格式为 'username:key'。", + en=( + "Kaggle API access token (e.g. 'KGAT_...'), generated at " + "https://www.kaggle.com/settings/api." + ), + es=( + "Token de acceso de la API de Kaggle (p. ej. 'KGAT_...'), generado " + "en https://www.kaggle.com/settings/api." + ), + pt=( + "Token de acesso da API do Kaggle (ex.: 'KGAT_...'), gerado em " + "https://www.kaggle.com/settings/api." + ), + de=( + "Kaggle-API-Zugriffstoken (z. B. 'KGAT_...'), erstellt unter " + "https://www.kaggle.com/settings/api." + ), + zh=( + "Kaggle API 访问令牌(例如 'KGAT_...'),在 " + "https://www.kaggle.com/settings/api 生成。" + ), ) ICON: str = "Key" - @staticmethod - def _split_key(key: str): - """Split a ``"username:api_key"`` credential into its parts. - - Parameters - ---------- - key : str - Kaggle credential in the form ``"username:api_key"``. - - Returns - ------- - tuple[str, str] or None - ``(username, api_key)`` if well formed, otherwise None. - """ - username, separator, api_key = key.partition(":") - if not separator or not username or not api_key: - return None - return username, api_key - def verify(self, key: str) -> bool: - """Validate a Kaggle credential with the official ``kaggle`` library. + """Validate a Kaggle access token with the official ``kaggle`` library. - The credentials are exported to the environment before importing - ``kaggle``, because the package authenticates at import time and - terminates the process when no credentials are available. + The token is exported to the environment before importing ``kaggle``, + because the package authenticates at import time. ``authenticate()`` + introspects the token against Kaggle, so a token that authenticates with + method ``ACCESS_TOKEN`` is valid. Parameters ---------- key : str - Kaggle credential in the form ``"username:api_key"``. + Kaggle API access token. Returns ------- bool - True if the credential authenticates successfully. + True if the token authenticates successfully. """ - parts = self._split_key(key) - if parts is None: + if not key or not key.strip(): return False - username, api_key = parts - os.environ["KAGGLE_USERNAME"] = username - os.environ["KAGGLE_KEY"] = api_key + os.environ["KAGGLE_API_TOKEN"] = key try: from kaggle.api.kaggle_api_extended import KaggleApi api = KaggleApi() api.authenticate() - # Perform an authenticated call to confirm the key is valid. - api.competitions_list() - return True + return api.config_values.get("auth_method") == _AUTH_METHOD_ACCESS_TOKEN except SystemExit: return False except Exception as exc: @@ -90,19 +86,24 @@ def verify(self, key: str) -> bool: return False def apply(self) -> None: - """Export the stored Kaggle credentials to the environment. + """Export the stored Kaggle token to the environment. - The official ``kaggle`` library reads ``KAGGLE_USERNAME`` and - ``KAGGLE_KEY`` from the environment, so exporting them makes any later - use of the library authenticated. No-op when nothing is stored. + The official ``kaggle`` library reads ``KAGGLE_API_TOKEN`` from the + environment. When the module was already imported (and therefore its + module-level ``kaggle.api`` instance was authenticated without the + token), re-authenticate it so later calls use the token. No-op when + nothing is stored. """ key = self.get_key() if not key: return None - parts = self._split_key(key) - if parts is None: - return None - username, api_key = parts - os.environ["KAGGLE_USERNAME"] = username - os.environ["KAGGLE_KEY"] = api_key + + os.environ["KAGGLE_API_TOKEN"] = key + if "kaggle" in sys.modules: + try: + import kaggle + + kaggle.api.authenticate() + except Exception: + logger.debug("Could not re-authenticate the kaggle module") return None diff --git a/DashAI/back/dataset_sources/kaggle_dataset_source.py b/DashAI/back/dataset_sources/kaggle_dataset_source.py new file mode 100644 index 000000000..d81dadce1 --- /dev/null +++ b/DashAI/back/dataset_sources/kaggle_dataset_source.py @@ -0,0 +1,264 @@ +"""Kaggle dataset source for DashAI.""" + +import io +import json +import logging +import tempfile +from contextlib import redirect_stdout +from typing import Any, Final + +from DashAI.back.core.utils import MultilingualString +from DashAI.back.dataset_sources.base_dataset_source import ( + BaseDatasetSource, + DatasetEntry, + SearchPage, +) + +log = logging.getLogger(__name__) + +# How many datasets Kaggle puts on one search page. It pages by number, ignores +# ``page_size`` and never fills ``next_page_token``, so the cursor is the page +# number, as in the Zenodo source, and a page shorter than this is the last one. +_KAGGLE_PAGE_SIZE: Final[int] = 20 + + +def _import_kaggle(): + """Import the ``kaggle`` module, suppressing its import time auth noise. + + ``kaggle`` authenticates at import time and prints an authentication help + block when no credentials are available; that output is not useful to DashAI + users, so it is suppressed. The module level ``kaggle.api`` instance is used + for all calls below. + """ + with redirect_stdout(io.StringIO()): + import kaggle + + return kaggle + + +class KaggleDatasetSource(BaseDatasetSource): + """Dataset source that fetches public datasets from Kaggle. + + Uses the official ``kaggle`` library (module level ``kaggle.api``). Public + datasets can be searched and downloaded without authentication; a stored + ``KaggleCredential`` is applied when downloading so private or consent gated + datasets work too. + """ + + OPTIONAL_CREDENTIALS = ["KaggleCredential"] + + DISPLAY_NAME: Final = MultilingualString( + en="Kaggle", + es="Kaggle", + zh="Kaggle", + de="Kaggle", + pt="Kaggle", + ) + DESCRIPTION: Final = MultilingualString( + en=( + "Kaggle is the world's largest data science community and hosts a " + "vast collection of public datasets across every domain: tabular, " + "NLP, computer vision, and more. Datasets are contributed by " + "companies, researchers, and community members, and many are " + "actively maintained with regular updates. Search by name, " + "download directly to DashAI, and start training in minutes. " + "[https://www.kaggle.com/datasets](https://www.kaggle.com/datasets)" + ), + es=( + "Kaggle es la comunidad de ciencia de datos más grande del mundo y " + "aloja una amplia colección de datasets públicos de todos los " + "dominios: tabulares, NLP, visión por computadora y más. Los " + "datasets son aportados por empresas, investigadores y miembros de " + "la comunidad, y muchos se mantienen activamente con actualizaciones " + "regulares. Busca por nombre, descarga directamente a DashAI y " + "comienza a entrenar en minutos. " + "[https://www.kaggle.com/datasets](https://www.kaggle.com/datasets)" + ), + zh=( + "Kaggle是全球最大的数据科学社区,托管着涵盖表格、NLP、计算机视觉等所有领域的大量公共数据集。" + "数据集由公司、研究者和社区成员贡献,许多数据集定期更新并积极维护。" + "按名称搜索,直接下载到DashAI,数分钟内开始训练。" + "[https://www.kaggle.com/datasets](https://www.kaggle.com/datasets)" + ), + de=( + "Kaggle ist die größte Data Science Community der Welt und hostet " + "eine riesige Sammlung öffentlicher Datensätze aus allen Bereichen: " + "tabellarisch, NLP, Computer Vision und mehr. Die Datensätze werden " + "von Unternehmen, Forschern und Community Mitgliedern beigetragen, " + "viele werden aktiv gepflegt und regelmäßig aktualisiert. Nach Name " + "suchen, direkt in DashAI herunterladen und in Minuten mit dem " + "Training beginnen. " + "[https://www.kaggle.com/datasets](https://www.kaggle.com/datasets)" + ), + pt=( + "Kaggle e a maior comunidade de ciencia de dados do mundo e hospeda " + "uma vasta colecao de conjuntos de dados publicos de todos os " + "dominios: tabulares, NLP, visao computacional e mais. Os conjuntos " + "de dados sao contribuidos por empresas, pesquisadores e membros da " + "comunidade, e muitos sao mantidos ativamente com atualizacoes " + "regulares. Pesquise por nome, baixe diretamente para o DashAI e " + "comece a treinar em minutos. " + "[https://www.kaggle.com/datasets](https://www.kaggle.com/datasets)" + ), + ) + + @staticmethod + def _tag_names(tags: Any) -> list[str]: + """Extract human readable tag names from a Kaggle tag list. + + Kaggle returns tags as a list of dicts with a ``name`` key; the helper + tolerates strings and objects with a ``name`` attribute as well. + """ + names: list[str] = [] + for tag in tags or []: + if isinstance(tag, dict): + name = tag.get("name") + else: + name = getattr(tag, "name", None) or str(tag) + if name: + names.append(str(name)) + return names + + @classmethod + def _to_entry(cls, item: Any) -> DatasetEntry: + """Map a kaggle ``ApiDataset`` object to a ``DatasetEntry``.""" + ref = item.ref or "" + slug = ref.split("/")[-1] + return DatasetEntry( + id=ref, + name=item.title or slug, + description=(item.description or "") or (item.subtitle or ""), + tags=cls._tag_names(item.tags), + size_bytes=item.total_bytes, + url=f"https://www.kaggle.com/datasets/{ref}", + source=cls.__name__, + ) + + def search( + self, + query: str, + limit: int = 20, + cursor: str | None = None, + **filters: Any, + ) -> SearchPage: + """Return Kaggle datasets matching a query. + + Parameters + ---------- + query : str + Free text search string. + limit : int, optional + Requested page size, by default 20. Passed to Kaggle, which today + serves ``_KAGGLE_PAGE_SIZE`` datasets a page whatever is asked. + cursor : str or None, optional + Page number returned by the previous call as ``next_cursor``. + ``None`` fetches the first page. + **filters : Any + Supported keys: + sort_by (str): Kaggle dataset sort (e.g. ``"hottest"``). + tags (list[str]): Comma-joined into Kaggle ``tag_ids``. + file_type (str): Filter by file type. + license_name (str): Filter by license. + user (str): Only datasets owned by this username. + + Returns + ------- + SearchPage + Matching datasets and a cursor for the next page (or ``None``). + """ + kaggle = _import_kaggle() + try: + page = int(cursor) if cursor else 1 + sort_by = filters.get("sort_by") or "hottest" + tag_ids = filters.get("tags") + if isinstance(tag_ids, list): + tag_ids = ",".join(tag_ids) + params: dict[str, Any] = { + "search": query or None, + "page": page, + "page_size": limit, + "sort_by": sort_by, + } + for key in ("tag_ids", "file_type", "license_name", "user"): + value = {"tag_ids": tag_ids}.get(key, filters.get(key)) + if value: + params[key] = value + response = kaggle.api.dataset_list_with_response(**params) + entries = [self._to_entry(item) for item in (response.datasets or [])] + # Kaggle answers with a full page or the tail of the results, never + # with a token, so a full page is the only sign of a next one. The + # entries are not trimmed to ``limit``: the next page starts where + # this one ended, so anything cut here would never be served again. + has_next = len(entries) >= min(limit, _KAGGLE_PAGE_SIZE) + next_cursor = str(page + 1) if has_next else None + return SearchPage(entries=entries, next_cursor=next_cursor) + except Exception: + log.exception("Error searching Kaggle datasets") + return SearchPage() + + def get_info(self, dataset_id: str) -> "DatasetEntry | None": + """Return full metadata for a single Kaggle dataset. + + Uses ``dataset_metadata`` (writes a JSON file into a temp dir) for the + description and keywords, and ``dataset_list_files`` for the total size. + + Parameters + ---------- + dataset_id : str + Kaggle dataset identifier in ``"owner/dataset-name"`` form. + + Returns + ------- + DatasetEntry or None + Full metadata entry, or None on error. + """ + kaggle = _import_kaggle() + try: + with tempfile.TemporaryDirectory() as tmp_dir: + meta_file = kaggle.api.dataset_metadata(dataset_id, tmp_dir) + with open(meta_file, encoding="utf-8") as f: + info = json.load(f).get("info", {}) or {} + files_response = kaggle.api.dataset_list_files(dataset_id) + size_bytes = sum( + int(file.total_bytes or 0) for file in (files_response.files or []) + ) + title = info.get("title") or dataset_id.split("/")[-1] + return DatasetEntry( + id=dataset_id, + name=title, + description=info.get("description") or "", + tags=list(info.get("keywords") or []), + size_bytes=size_bytes, + url=f"https://www.kaggle.com/datasets/{dataset_id}", + source=self.__class__.__name__, + ) + except Exception: + log.debug("Could not fetch info for Kaggle dataset %s", dataset_id) + return None + + def download_dataset(self, dataset_id: str, temp_path: str) -> str: + """Download a Kaggle dataset's files into ``temp_path``. + + Parameters + ---------- + dataset_id : str + Kaggle dataset identifier (e.g. ``"uciml/iris"``). + temp_path : str + Local directory to download into. + + Returns + ------- + str + Path to the directory containing the downloaded files. + """ + self.get_credential("KaggleCredential").apply() + + kaggle = _import_kaggle() + kaggle.api.dataset_download_files( + dataset_id, + path=temp_path, + force=True, + quiet=True, + unzip=True, + ) + return temp_path diff --git a/DashAI/back/initial_components.py b/DashAI/back/initial_components.py index 868c376d5..5a310d4c2 100644 --- a/DashAI/back/initial_components.py +++ b/DashAI/back/initial_components.py @@ -95,6 +95,7 @@ from DashAI.back.dataset_sources.huggingface_dataset_source import ( HuggingFaceDatasetSource, ) +from DashAI.back.dataset_sources.kaggle_dataset_source import KaggleDatasetSource from DashAI.back.dataset_sources.openml_dataset_source import OpenMLDatasetSource from DashAI.back.dataset_sources.zenodo_dataset_source import ZenodoDatasetSource @@ -645,6 +646,7 @@ def get_initial_components(): JSONDataLoader, # Dataset Sources HuggingFaceDatasetSource, + KaggleDatasetSource, OpenMLDatasetSource, ZenodoDatasetSource, # Credentials diff --git a/pyproject.toml b/pyproject.toml index 50b25b4a6..8c3ff12a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,7 +78,7 @@ dependencies = [ "openml", "oslo.concurrency", "cryptography>=49.0.0", - "kaggle>=1.7.4.5", + "kaggle>=2", "grad-cam>=1.5.5", "dice-ml>=0.12", "lime>=0.2.0.1", diff --git a/tests/back/credentials/test_concrete_credentials.py b/tests/back/credentials/test_concrete_credentials.py index fd193fc7d..29d603436 100644 --- a/tests/back/credentials/test_concrete_credentials.py +++ b/tests/back/credentials/test_concrete_credentials.py @@ -1,3 +1,4 @@ +import os import sys import types from contextlib import contextmanager @@ -14,12 +15,16 @@ def fake_kaggle(api_instance): The official ``kaggle`` package authenticates at import time and exits the process without credentials, so tests inject a fake module tree exposing a - ``KaggleApi`` that returns ``api_instance``. + ``KaggleApi`` that returns ``api_instance``. The module-level ``kaggle.api`` + singleton is set to ``api_instance`` so ``apply()`` can re-authenticate it. """ module_names = ("kaggle", "kaggle.api", "kaggle.api.kaggle_api_extended") saved = {name: sys.modules.get(name) for name in module_names} - sys.modules["kaggle"] = types.ModuleType("kaggle") - sys.modules["kaggle.api"] = types.ModuleType("kaggle.api") + kaggle_mod = types.ModuleType("kaggle") + kaggle_mod.api = api_instance + sys.modules["kaggle"] = kaggle_mod + api_mod = types.ModuleType("kaggle.api") + sys.modules["kaggle.api"] = api_mod extended = types.ModuleType("kaggle.api.kaggle_api_extended") extended.KaggleApi = MagicMock(return_value=api_instance) sys.modules["kaggle.api.kaggle_api_extended"] = extended @@ -31,6 +36,8 @@ def fake_kaggle(api_instance): sys.modules.pop(name, None) else: sys.modules[name] = module + for env_var in ("KAGGLE_API_TOKEN", "KAGGLE_USERNAME", "KAGGLE_KEY"): + os.environ.pop(env_var, None) def test_huggingface_verify_success(): @@ -64,20 +71,40 @@ def test_github_verify_failure(): def test_kaggle_verify_success(): cred = KaggleCredential() api = MagicMock() + api.config_values = {"auth_method": "ACCESS_TOKEN"} api.authenticate.return_value = None - api.competitions_list.return_value = [] with fake_kaggle(api): - assert cred.verify("user:key") is True + assert cred.verify("KGAT_good_token") is True + assert os.environ.get("KAGGLE_API_TOKEN") == "KGAT_good_token" def test_kaggle_verify_failure(): cred = KaggleCredential() api = MagicMock() - api.competitions_list.side_effect = Exception("401") + api.config_values = {"auth_method": "LEGACY_API_KEY"} + api.authenticate.return_value = None + with fake_kaggle(api): + assert cred.verify("KGAT_bad_token") is False + + +def test_kaggle_verify_invalid_token_exits(): + cred = KaggleCredential() + api = MagicMock() + api.authenticate.side_effect = SystemExit(1) with fake_kaggle(api): - assert cred.verify("user:badkey") is False + assert cred.verify("KGAT_expired_token") is False -def test_kaggle_verify_malformed_key(): +def test_kaggle_verify_empty_token(): cred = KaggleCredential() - assert cred.verify("no-separator") is False + assert cred.verify("") is False + + +def test_kaggle_apply_sets_token_and_reauths(): + cred = KaggleCredential() + api = MagicMock() + api.config_values = {"auth_method": "ACCESS_TOKEN"} + with fake_kaggle(api), patch.object(cred, "get_key", return_value="KGAT_stored"): + cred.apply() + assert os.environ.get("KAGGLE_API_TOKEN") == "KGAT_stored" + api.authenticate.assert_called() diff --git a/tests/back/dataset_sources/test_kaggle_dataset_source.py b/tests/back/dataset_sources/test_kaggle_dataset_source.py new file mode 100644 index 000000000..3fbe97a60 --- /dev/null +++ b/tests/back/dataset_sources/test_kaggle_dataset_source.py @@ -0,0 +1,229 @@ +"""Tests for KaggleDatasetSource.""" + +import json +import os +import sys +import types +from contextlib import contextmanager +from unittest.mock import MagicMock + +from DashAI.back.dataset_sources.base_dataset_source import SearchPage +from DashAI.back.dataset_sources.kaggle_dataset_source import KaggleDatasetSource + + +@contextmanager +def fake_kaggle(api): + """Install a stub ``kaggle`` module whose ``api`` attribute is ``api``.""" + saved = {name: sys.modules.get(name) for name in ("kaggle",)} + mod = types.ModuleType("kaggle") + mod.api = api + sys.modules["kaggle"] = mod + try: + yield + finally: + for name, module in saved.items(): + if module is None: + sys.modules.pop(name, None) + else: + sys.modules[name] = module + + +def _make_source(): + source = KaggleDatasetSource() + source.get_credential = MagicMock(return_value=MagicMock()) + return source + + +def _dataset(ref, title="Title", description="", tags=None, total_bytes=100): + item = MagicMock() + item.ref = ref + item.title = title + item.description = description + item.subtitle = "" + item.tags = tags if tags is not None else [] + item.total_bytes = total_bytes + return item + + +def test_kaggle_source_has_correct_type_and_credentials(): + assert KaggleDatasetSource.TYPE == "DatasetSource" + assert KaggleDatasetSource.OPTIONAL_CREDENTIALS == ["KaggleCredential"] + + +def test_search_returns_dataset_entries(): + api = MagicMock() + response = MagicMock() + response.datasets = [ + _dataset( + "uciml/iris", + title="Iris Species", + description="", + tags=[{"name": "biology"}, {"name": "tabular"}], + total_bytes=15347, + ) + ] + api.dataset_list_with_response.return_value = response + + with fake_kaggle(api): + source = _make_source() + page = source.search("iris", limit=5) + + api.dataset_list_with_response.assert_called_once_with( + search="iris", page=1, page_size=5, sort_by="hottest" + ) + assert isinstance(page, SearchPage) + assert len(page.entries) == 1 + entry = page.entries[0] + assert entry.id == "uciml/iris" + assert entry.name == "Iris Species" + assert entry.tags == ["biology", "tabular"] + assert entry.size_bytes == 15347 + assert entry.url == "https://www.kaggle.com/datasets/uciml/iris" + assert entry.source == "KaggleDatasetSource" + assert page.next_cursor is None + + +def test_search_reads_the_cursor_as_a_page_number_and_a_full_page_continues(): + # Kaggle pages by number and never fills next_page_token, so the cursor is + # the page and a full page is the only sign that another one follows. + api = MagicMock() + response = MagicMock() + response.datasets = [_dataset(f"owner/repo{i}") for i in range(20)] + api.dataset_list_with_response.return_value = response + + with fake_kaggle(api): + source = _make_source() + page = source.search("q", limit=20, cursor="2") + + api.dataset_list_with_response.assert_called_once_with( + search="q", page=2, page_size=20, sort_by="hottest" + ) + assert len(page.entries) == 20 + assert page.next_cursor == "3" + + +def test_search_treats_a_short_page_as_the_last_one(): + api = MagicMock() + response = MagicMock() + response.datasets = [_dataset(f"owner/repo{i}") for i in range(7)] + api.dataset_list_with_response.return_value = response + + with fake_kaggle(api): + source = _make_source() + page = source.search("q", limit=20, cursor="3") + + assert len(page.entries) == 7 + assert page.next_cursor is None + + +def test_search_does_not_trim_a_page_below_the_requested_limit(): + # Kaggle ignores page_size and the next page starts where this one ended, + # so cutting the page down to ``limit`` would lose rows for good. + api = MagicMock() + response = MagicMock() + response.datasets = [_dataset(f"owner/repo{i}") for i in range(20)] + api.dataset_list_with_response.return_value = response + + with fake_kaggle(api): + source = _make_source() + page = source.search("q", limit=3) + + assert len(page.entries) == 20 + assert page.next_cursor == "2" + + +def test_search_uses_slug_as_name_when_title_missing(): + api = MagicMock() + response = MagicMock() + response.datasets = [_dataset("uciml/iris", title="")] + api.dataset_list_with_response.return_value = response + + with fake_kaggle(api): + source = _make_source() + page = source.search("iris") + + assert page.entries[0].name == "iris" + + +def test_search_error_returns_empty_page(): + api = MagicMock() + api.dataset_list_with_response.side_effect = Exception("boom") + + with fake_kaggle(api): + source = _make_source() + page = source.search("anything") + + assert page.entries == [] + assert page.next_cursor is None + + +def test_get_info_returns_enriched_entry(): + api = MagicMock() + + def _write_metadata(dataset, path): + os.makedirs(path, exist_ok=True) + meta_path = os.path.join(path, "dataset-metadata.json") + with open(meta_path, "w") as f: + json.dump( + { + "info": { + "title": "Iris Species", + "description": "The classic iris dataset.", + "keywords": ["biology"], + } + }, + f, + ) + return meta_path + + api.dataset_metadata.side_effect = _write_metadata + files_response = MagicMock() + file_a = MagicMock() + file_a.name = "Iris.csv" + file_a.total_bytes = 5107 + file_b = MagicMock() + file_b.name = "database.sqlite" + file_b.total_bytes = 10240 + files_response.files = [file_a, file_b] + api.dataset_list_files.return_value = files_response + + with fake_kaggle(api): + source = _make_source() + entry = source.get_info("uciml/iris") + + assert entry is not None + assert entry.id == "uciml/iris" + assert entry.name == "Iris Species" + assert entry.description == "The classic iris dataset." + assert entry.tags == ["biology"] + assert entry.size_bytes == 15347 + assert entry.url == "https://www.kaggle.com/datasets/uciml/iris" + assert entry.source == "KaggleDatasetSource" + + +def test_get_info_returns_none_on_error(): + api = MagicMock() + api.dataset_metadata.side_effect = Exception("not found") + + with fake_kaggle(api): + source = _make_source() + entry = source.get_info("owner/repo") + + assert entry is None + + +def test_download_dataset_returns_path(tmp_path): + api = MagicMock() + api.dataset_download_files.return_value = None + + with fake_kaggle(api): + source = _make_source() + out = source.download_dataset("uciml/iris", str(tmp_path)) + + assert out == str(tmp_path) + kwargs = api.dataset_download_files.call_args.kwargs + assert kwargs["path"] == str(tmp_path) + assert kwargs["force"] is True + assert kwargs["unzip"] is True + api.dataset_download_files.assert_called_once_with("uciml/iris", **kwargs) + source.get_credential.return_value.apply.assert_called_once() diff --git a/uv.lock b/uv.lock index 6ff335923..29e353f0e 100644 --- a/uv.lock +++ b/uv.lock @@ -40,9 +40,9 @@ dependencies = [ { name = "pyyaml" }, { name = "safetensors" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/8d/75/94cd5d389649578aca399e5aa822637eec18319a1dadc400ffe2f9a7493f/accelerate-1.14.0.tar.gz", hash = "sha256:41b9c4377a54e0b460a959b0defa1b736e4ca0a2373252d9a539964c2afe3c8d", size = 412167, upload-time = "2026-06-11T13:45:52.326Z" } wheels = [ @@ -902,13 +902,13 @@ dependencies = [ { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "timm" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "torchvision", version = "0.26.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torchvision", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/14/ad/2eb8cd9a8e17e35b9e5d39ad29afdde8fe810bda85e6e59117050519955d/controlnet_aux-0.0.10.tar.gz", hash = "sha256:31dc265a54448bdcee033a130b47423c80587fa35ccac752113af1b4d48f5183", size = 215016, upload-time = "2025-05-08T10:38:30.845Z" } wheels = [ @@ -1106,7 +1106,7 @@ resolution-markers = [ "python_full_version < '3.12'", ] dependencies = [ - { name = "cuda-pathfinder", marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, + { name = "cuda-pathfinder", marker = "(python_full_version < '3.15' and extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/51/6b/457ca12dad3ee9bfcc9a545cfd6b64b359ba49de40f776f6e028e678f262/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5879712accf6e14bb01aa5e67440eb84998b8d104b509cc7a6dc0b8f656a474", size = 6053539, upload-time = "2026-05-29T23:11:43.19Z" }, @@ -1310,14 +1310,14 @@ dependencies = [ { name = "statsmodels" }, { name = "streaming-form-data" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "torchmetrics" }, { name = "torchvision", version = "0.26.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torchvision", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "transformers" }, { name = "typer" }, { name = "wordcloud" }, @@ -1328,10 +1328,10 @@ dependencies = [ cpu = [ { name = "llama-cpp-python", version = "0.3.29", source = { registry = "https://abetlen.github.io/llama-cpp-python/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "llama-cpp-python", version = "0.3.34", source = { registry = "https://abetlen.github.io/llama-cpp-python/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] cuda = [ { name = "llama-cpp-python", version = "0.3.34", source = { registry = "https://pypi.org/simple" } }, @@ -1375,7 +1375,7 @@ requires-dist = [ { name = "ijson" }, { name = "imblearn" }, { name = "joblib" }, - { name = "kaggle", specifier = ">=1.7.4.5" }, + { name = "kaggle", specifier = ">=2" }, { name = "kink" }, { name = "lime", specifier = ">=0.2.0.1" }, { name = "llama-cpp-python", marker = "sys_platform == 'darwin' and extra == 'cpu'", specifier = "==0.3.29", index = "https://abetlen.github.io/llama-cpp-python/whl/cpu", conflict = { package = "dashai", extra = "cpu" } }, @@ -2021,13 +2021,13 @@ dependencies = [ { name = "pillow" }, { name = "scikit-learn" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "torchvision", version = "0.26.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torchvision", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "tqdm" }, { name = "ttach" }, ] @@ -6035,9 +6035,9 @@ dependencies = [ { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12' or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "tokenizers" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "tqdm" }, { name = "transformers" }, { name = "typing-extensions" }, @@ -6626,13 +6626,13 @@ dependencies = [ { name = "pyyaml" }, { name = "safetensors" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, { name = "torchvision", version = "0.26.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torchvision", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torchvision", version = "0.28.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/35/03/e41389ac641747bfec48d016fde8be1eade1901e6f2c1aedcb0c8cb4b5d9/timm-1.0.28.tar.gz", hash = "sha256:3789d313fdd5541a327b60180d70dbb4bdec73db8ff0655e413db3c3d134a9a4", size = 2451413, upload-time = "2026-07-11T17:24:32.615Z" } wheels = [ @@ -6781,20 +6781,19 @@ name = "torch" version = "2.13.0" source = { registry = "https://download.pytorch.org/whl/cpu" } resolution-markers = [ - "python_full_version >= '3.15' and sys_platform == 'darwin'", "python_full_version == '3.14.*' and sys_platform == 'darwin'", "python_full_version == '3.13.*' and sys_platform == 'darwin'", "python_full_version == '3.12.*' and sys_platform == 'darwin'", "python_full_version < '3.12' and sys_platform == 'darwin'", ] dependencies = [ - { name = "filelock", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "fsspec", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "jinja2", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "networkx", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "setuptools", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "sympy", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "typing-extensions", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "filelock", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "fsspec", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "jinja2", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "networkx", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "setuptools", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "sympy", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torch-2.13.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:e76f9bcecc52b8ff711239a2f7547d5353df95878ab232f0773c1d95928b92f8", upload-time = "2026-07-08T12:26:13Z" }, @@ -6859,6 +6858,7 @@ name = "torch" version = "2.13.0+cpu" source = { registry = "https://download.pytorch.org/whl/cpu" } resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'darwin'", "python_full_version >= '3.15' and sys_platform != 'darwin'", "python_full_version == '3.14.*' and sys_platform != 'darwin'", "python_full_version == '3.13.*' and sys_platform != 'darwin'", @@ -6866,13 +6866,13 @@ resolution-markers = [ "python_full_version < '3.12' and sys_platform != 'darwin'", ] dependencies = [ - { name = "filelock", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "fsspec", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "jinja2", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "networkx", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "setuptools", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "sympy", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "typing-extensions", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "filelock", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "fsspec", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "jinja2", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "networkx", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "setuptools", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "sympy", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "typing-extensions", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torch-2.13.0%2Bcpu-cp311-cp311-linux_s390x.whl", hash = "sha256:6e9817dbdf5ea76789babd46e457eac5bf14ff566cf85f8addbfdff2d56601ce", upload-time = "2026-07-08T19:27:52Z" }, @@ -6913,9 +6913,9 @@ dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "extra == 'extra-6-dashai-cuda'" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, { name = "torch", version = "2.13.0", source = { registry = "https://pypi.org/simple" }, marker = "(extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (extra != 'extra-6-dashai-cpu' and extra != 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/81/34/39b8b749333db56c0585d7a11fa62a283c087bb1dfc897d69fb8cedbefb1/torchmetrics-1.9.0.tar.gz", hash = "sha256:a488609948600df52d3db4fcdab02e62aab2a85ef34da67037dc3e65b8512faa", size = 581765, upload-time = "2026-03-09T17:41:22.443Z" } wheels = [ @@ -6964,16 +6964,15 @@ name = "torchvision" version = "0.28.0" source = { registry = "https://download.pytorch.org/whl/cpu" } resolution-markers = [ - "python_full_version >= '3.15' and sys_platform == 'darwin'", "python_full_version == '3.14.*' and sys_platform == 'darwin'", "python_full_version == '3.13.*' and sys_platform == 'darwin'", "python_full_version == '3.12.*' and sys_platform == 'darwin'", "python_full_version < '3.12' and sys_platform == 'darwin'", ] dependencies = [ - { name = "numpy", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "pillow", marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "numpy", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "pillow", marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "torch", version = "2.13.0", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version < '3.15' and sys_platform == 'darwin' and extra == 'extra-6-dashai-cpu') or (python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torchvision-0.28.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:83fe6c020866a85acd7d97deccc45ff11d66daf42916d04396a4309c66c0ccb8", upload-time = "2026-07-08T12:26:40Z" }, @@ -7027,6 +7026,7 @@ name = "torchvision" version = "0.28.0+cpu" source = { registry = "https://download.pytorch.org/whl/cpu" } resolution-markers = [ + "python_full_version >= '3.15' and sys_platform == 'darwin'", "python_full_version >= '3.15' and sys_platform != 'darwin'", "python_full_version == '3.14.*' and sys_platform != 'darwin'", "python_full_version == '3.13.*' and sys_platform != 'darwin'", @@ -7034,9 +7034,9 @@ resolution-markers = [ "python_full_version < '3.12' and sys_platform != 'darwin'", ] dependencies = [ - { name = "numpy", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "pillow", marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, - { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu') or (extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda')" }, + { name = "numpy", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "pillow", marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, + { name = "torch", version = "2.13.0+cpu", source = { registry = "https://download.pytorch.org/whl/cpu" }, marker = "(python_full_version >= '3.15' and extra == 'extra-6-dashai-cpu') or (python_full_version < '3.15' and extra == 'extra-6-dashai-cpu' and extra == 'extra-6-dashai-cuda') or (sys_platform != 'darwin' and extra == 'extra-6-dashai-cpu')" }, ] wheels = [ { url = "https://download-r2.pytorch.org/whl/cpu/torchvision-0.28.0%2Bcpu-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:22958193d72444ed7cbcc665ba4821a31e5279f9c4d1ad08520918b30896b78a", upload-time = "2026-07-08T12:26:39Z" },