import os import random import string import tarfile from pathlib import Path from tempfile import ( mkdtemp, NamedTemporaryFile, ) from typing import ( Any, Optional, ) from galaxy.security.idencoding import IdEncodingHelper from galaxy.util import safe_makedirs from tool_shed.context import ProvidesRepositoriesContext from tool_shed.managers.model_cache import ModelCache from tool_shed.managers.repositories import upload_tar_and_set_metadata from tool_shed.managers.users import create_user from tool_shed.repository_types import util as rt_util from tool_shed.repository_types.registry import Registry as RepositoryTypesRegistry from tool_shed.structured_app import ToolShedApp from tool_shed.test.base.populators import ( repo_tars, TEST_DATA_REPO_FILES, ) from tool_shed.util.hgweb_config import hgweb_config_manager from tool_shed.util.repository_util import create_repository from tool_shed.webapp.model import ( Category, mapping, Repository, RepositoryCategoryAssociation, User, ) from tool_shed_client.schema import CreateCategoryRequest TEST_DATA_FILES = TEST_DATA_REPO_FILES TEST_HOST = "localhost" TEST_COMMIT_MESSAGE = "Test Commit Message" class TestToolShedConfig: user_activation_on = False file_path: str id_secret: str = "thisistheshedunittestsecret" smtp_server: Optional[str] = None tool_shed_url: Optional[str] = "shed_unit_test://localhost" hgweb_repo_prefix = "repos/" config_hg_for_dev = False def __init__(self, temp_directory): files_path = os.path.join(temp_directory, "files") safe_makedirs(files_path) self.file_path = files_path def get(self, key, default): assert key == "admin_users" return "admin@galaxyproject.org" class TestToolShedApp(ToolShedApp): repository_types_registry = RepositoryTypesRegistry() config: TestToolShedConfig hgweb_config_manager = hgweb_config_manager security: IdEncodingHelper name: str = "ToolShed" def __init__(self, temp_directory=None): self.model = mapping.init( "sqlite:///:memory:", create_tables=True, ) temp_directory = temp_directory or mkdtemp() hgweb_config_dir = os.path.join(temp_directory, "hgweb") safe_makedirs(hgweb_config_dir) self.hgweb_config_manager.hgweb_config_dir = hgweb_config_dir self.hgweb_config_manager.hgweb_repo_prefix = "repos/" self.config = TestToolShedConfig(temp_directory) self.security = IdEncodingHelper(id_secret=self.config.id_secret) self.model_cache = ModelCache(os.path.join(temp_directory, "model_cache")) self.security_agent = self.model.security_agent def user_fixture(app: ToolShedApp, username: str, password: str = "testpassword", email: Optional[str] = None) -> User: email = email or f"{username}@galaxyproject.org" return create_user( app, email, username, password, ) class ProvidesRepositoriesImpl(ProvidesRepositoriesContext): def __init__(self, app: TestToolShedApp, user: User): self._app = app self._user = user @property def app(self) -> ToolShedApp: return self._app @property def user(self) -> User: return self._user @property def repositories_hostname(self) -> str: return "shed_unit_test://localhost" def provides_repositories_fixture( app: TestToolShedApp, user: User, ): return ProvidesRepositoriesImpl(app, user) def repository_fixture(app: ToolShedApp, user: User, name: str, category: Optional[Category] = None) -> Repository: type = rt_util.UNRESTRICTED description = f"test repo named {name}" long_description = f"test repo named {name} a longer description" category_ids = [] if category: category_ids.append(app.security.encode_id(category.id)) repository, message = create_repository( app, name, type, description, long_description, user, category_ids=category_ids, remote_repository_url=None, homepage_url=None, ) assert "created" in message return repository def _mock_url_for(x, qualified: bool = False): return "shed_unit_test://localhost/" from unittest import mock patch_url_for = mock.patch("galaxy.util.tool_shed.common_util.url_for", _mock_url_for) def upload( provides_repositories: ProvidesRepositoriesContext, repository: Repository, path: Path, arcname: Optional[str] = None, ): if path.is_dir(): tf = NamedTemporaryFile(delete=False) with tarfile.open(tf.name, "w:gz") as tar: print(path.name) print(str(path)) tar.add(str(path), arcname=arcname or path.name) tar_path = tf.name else: tar_path = str(path) return upload_tar_and_set_metadata( provides_repositories, TEST_HOST, repository, tar_path, commit_message=TEST_COMMIT_MESSAGE, ) def upload_directories_to_repository( provides_repositories: ProvidesRepositoriesContext, repository: Repository, test_data_path: str ): paths = repo_tars(test_data_path) for path in paths: upload(provides_repositories, repository, Path(path), arcname=test_data_path) def random_name(len: int = 10) -> str: return "".join(random.choice(string.ascii_lowercase + string.digits) for _ in range(len)) def create_category(provides_repositories: ProvidesRepositoriesContext, create: dict[str, Any]) -> Category: from tool_shed.managers.categories import CategoryManager request = CreateCategoryRequest(**create) return CategoryManager(provides_repositories.app).create(provides_repositories, request) def attach_category(provides_repositories: ProvidesRepositoriesContext, repository: Repository, category: Category): assoc = RepositoryCategoryAssociation( repository=repository, category=category, ) provides_repositories.sa_session.add(assoc) provides_repositories.sa_session.flush()