|
| 1 | +from typing import ( |
| 2 | + Optional, |
| 3 | + Union, |
| 4 | +) |
| 5 | + |
| 6 | +from fsspec import AbstractFileSystem |
| 7 | + |
| 8 | +from galaxy.exceptions import AuthenticationRequired, MessageException |
| 9 | +from galaxy.files.models import AnyRemoteEntry, FilesSourceRuntimeContext |
| 10 | +from galaxy.files.sources._defaults import DEFAULT_SCHEME |
| 11 | +from galaxy.files.sources._fsspec import ( |
| 12 | + CacheOptionsDictType, |
| 13 | + FsspecBaseFileSourceConfiguration, |
| 14 | + FsspecBaseFileSourceTemplateConfiguration, |
| 15 | + FsspecFilesSource, |
| 16 | +) |
| 17 | +from galaxy.util.config_templates import TemplateExpansion |
| 18 | + |
| 19 | +try: |
| 20 | + from mavedb_fsspec import MaveDBFileSystem |
| 21 | + from mavedb_fsspec.client import DEFAULT_BASE_URL |
| 22 | +except ImportError: |
| 23 | + MaveDBFileSystem = None # type: ignore[misc, assignment] |
| 24 | + DEFAULT_BASE_URL = "https://api.mavedb.org/api/v1" |
| 25 | + |
| 26 | + |
| 27 | +class MaveDBFileSourceTemplateConfiguration(FsspecBaseFileSourceTemplateConfiguration): |
| 28 | + base_url: Union[str, TemplateExpansion] = DEFAULT_BASE_URL |
| 29 | + api_key: Union[str, TemplateExpansion, None] = None |
| 30 | + timeout: Union[float, TemplateExpansion] = 30.0 |
| 31 | + |
| 32 | + |
| 33 | +class MaveDBFileSourceConfiguration(FsspecBaseFileSourceConfiguration): |
| 34 | + base_url: str = DEFAULT_BASE_URL |
| 35 | + api_key: Optional[str] = None |
| 36 | + timeout: float = 30.0 |
| 37 | + |
| 38 | + |
| 39 | +class MaveDBFilesSource(FsspecFilesSource[MaveDBFileSourceTemplateConfiguration, MaveDBFileSourceConfiguration]): |
| 40 | + plugin_type = "mavedb" |
| 41 | + required_module = MaveDBFileSystem |
| 42 | + required_package = "mavedb-fsspec" |
| 43 | + |
| 44 | + template_config_class = MaveDBFileSourceTemplateConfiguration |
| 45 | + resolved_config_class = MaveDBFileSourceConfiguration |
| 46 | + |
| 47 | + def _open_fs( |
| 48 | + self, |
| 49 | + context: FilesSourceRuntimeContext[MaveDBFileSourceConfiguration], |
| 50 | + cache_options: CacheOptionsDictType, |
| 51 | + ) -> AbstractFileSystem: |
| 52 | + if MaveDBFileSystem is None: |
| 53 | + raise self.required_package_exception |
| 54 | + |
| 55 | + config = context.config |
| 56 | + return MaveDBFileSystem( |
| 57 | + base_url=config.base_url, |
| 58 | + api_key=config.api_key, |
| 59 | + timeout=config.timeout, |
| 60 | + **cache_options, |
| 61 | + ) |
| 62 | + |
| 63 | + def _list( |
| 64 | + self, |
| 65 | + context: FilesSourceRuntimeContext[MaveDBFileSourceConfiguration], |
| 66 | + path="/", |
| 67 | + recursive=False, |
| 68 | + write_intent: bool = False, |
| 69 | + limit: Optional[int] = None, |
| 70 | + offset: Optional[int] = None, |
| 71 | + query: Optional[str] = None, |
| 72 | + sort_by: Optional[str] = None, |
| 73 | + ) -> tuple[list[AnyRemoteEntry], int]: |
| 74 | + collection = path.strip("/") |
| 75 | + if recursive or collection not in {"score-sets", "my-score-sets"}: |
| 76 | + return super()._list(context, path, recursive, write_intent, limit, offset, query, sort_by) |
| 77 | + |
| 78 | + try: |
| 79 | + cache_options = self._get_cache_options(context.config) |
| 80 | + fs = self._open_fs(context, cache_options) |
| 81 | + entries, total_count = fs.list_score_sets( # type: ignore[attr-defined] |
| 82 | + collection=collection, |
| 83 | + limit=limit, |
| 84 | + offset=offset, |
| 85 | + query=query, |
| 86 | + ) |
| 87 | + return [self._info_to_entry(entry, context.config) for entry in entries], total_count |
| 88 | + except PermissionError as e: |
| 89 | + raise AuthenticationRequired( |
| 90 | + f"Permission Denied. Reason: {e}. Please check your credentials in your preferences for {self.label}." |
| 91 | + ) |
| 92 | + except Exception as e: |
| 93 | + raise MessageException(f"Problem listing file source path {path}. Reason: {e}") from e |
| 94 | + |
| 95 | + def _info_to_entry(self, info: dict, config: MaveDBFileSourceConfiguration) -> AnyRemoteEntry: |
| 96 | + entry = super()._info_to_entry(info, config) |
| 97 | + display_name = info.get("display_name") |
| 98 | + if display_name: |
| 99 | + entry.name = display_name |
| 100 | + return entry |
| 101 | + |
| 102 | + def _write_from( |
| 103 | + self, |
| 104 | + _target_path: str, |
| 105 | + _native_path: str, |
| 106 | + _context: FilesSourceRuntimeContext[MaveDBFileSourceConfiguration], |
| 107 | + ): |
| 108 | + raise MessageException("MaveDB file sources are read-only and do not support exporting files.") |
| 109 | + |
| 110 | + def get_scheme(self) -> str: |
| 111 | + return self.scheme if self.scheme and self.scheme != DEFAULT_SCHEME else "mavedb" |
| 112 | + |
| 113 | + |
| 114 | +__all__ = ("MaveDBFilesSource",) |
0 commit comments