From 7ea90e3fba9eacd65332da4f890800bd4d599db8 Mon Sep 17 00:00:00 2001 From: Alexander Guschin <1aguschin@gmail.com> Date: Thu, 23 Jun 2022 20:05:56 +0600 Subject: [PATCH 1/2] add API to check whether it's a GTO repo --- gto/api.py | 10 +++++++++- gto/config.py | 9 +++++++++ gto/registry.py | 9 +++++++++ tests/test_api.py | 22 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/gto/api.py b/gto/api.py index 1b28c5ed..ce0651c0 100644 --- a/gto/api.py +++ b/gto/api.py @@ -5,7 +5,7 @@ from git import Repo from gto.constants import NAME, STAGE, VERSION -from gto.exceptions import WrongArgs +from gto.exceptions import NoRepo, WrongArgs from gto.ext import EnrichmentInfo from gto.index import ( EnrichmentManager, @@ -19,6 +19,14 @@ from gto.tag import parse_name_reference +def is_gto_repo(repo: Union[str, Repo]): + """Check if repo is a gto repo""" + try: + return GitRegistry.from_repo(repo).is_gto_repo() + except NoRepo: + return False + + def get_index(repo: Union[str, Repo], file=False): """Get index state""" if file: diff --git a/gto/config.py b/gto/config.py index adcace39..1eaa4b18 100644 --- a/gto/config.py +++ b/gto/config.py @@ -1,4 +1,5 @@ # pylint: disable=no-self-use, no-self-argument, inconsistent-return-statements, invalid-name, import-outside-toplevel +import pathlib import re from pathlib import Path from typing import Any, Dict, List, Optional @@ -86,6 +87,10 @@ def stages_are_valid(cls, v): assert_name_is_valid(name) return v + def check_index_exist(self, repo: str): + index = pathlib.Path(repo) / pathlib.Path(self.INDEX) + return index.exists() and index.is_file() + def _set_location_init_source(init_source: InitSettingsSource): def inner(settings: "RegistryConfig"): @@ -134,6 +139,10 @@ def customise_sources( file_secret_settings, ) + def config_file_exists(self): + config = pathlib.Path(self.CONFIG_FILE_NAME) + return config.exists() and config.is_file() + def read_registry_config(config_file_name): try: diff --git a/gto/registry.py b/gto/registry.py index 9dbb3308..b1fce823 100644 --- a/gto/registry.py +++ b/gto/registry.py @@ -54,6 +54,15 @@ def from_repo(cls, repo=Union[str, Repo], config: RegistryConfig = None): enrichment_manager=EnrichmentManager(repo=repo, config=config), ) + def is_gto_repo(self): + if self.config.config_file_exists(): + return True + if self.config.check_index_exist(self.repo.working_dir): + return True + if self.get_state() != BaseRegistryState(): + return True + return False + def get_state( self, all_branches=False, diff --git a/tests/test_api.py b/tests/test_api.py index bcb8d7c9..8c6c4e61 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -200,3 +200,25 @@ def test_check_ref(repo_with_artifact: Tuple[git.Repo, Callable]): }, skip_keys={"commit_hexsha", "created_at", "message"}, ) + + +def test_is_not_gto_repo(empty_git_repo): + repo, _ = empty_git_repo # pylint: disable=unused-variable + assert not gto.api.is_gto_repo(repo.working_dir) + + +def test_is_gto_repo_because_of_config(init_showcase_semver): + repo, _ = init_showcase_semver # pylint: disable=unused-variable + assert gto.api.is_gto_repo(repo.working_dir) + + +def test_is_gto_repo_because_of_registered_artifact(repo_with_commit): + repo, _ = repo_with_commit # pylint: disable=unused-variable + gto.api.register(repo, "model", "HEAD", "v1.0.0") + assert gto.api.is_gto_repo(repo) + + +def test_is_gto_repo_because_of_artifacts_yaml(empty_git_repo): + repo, write_file = empty_git_repo + write_file("artifacts.yaml", "{}") + assert gto.api.is_gto_repo(repo) From 50923a0b0634e04128fce30ebdff073a3f58f388 Mon Sep 17 00:00:00 2001 From: Alexander Guschin <1aguschin@gmail.com> Date: Wed, 29 Jun 2022 15:52:56 +0600 Subject: [PATCH 2/2] make method private --- gto/api.py | 4 ++-- gto/cli.py | 4 +++- tests/test_api.py | 35 ++++++++++++++++++----------------- tests/test_cli.py | 6 ++++-- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/gto/api.py b/gto/api.py index ce0651c0..26170418 100644 --- a/gto/api.py +++ b/gto/api.py @@ -19,7 +19,7 @@ from gto.tag import parse_name_reference -def is_gto_repo(repo: Union[str, Repo]): +def _is_gto_repo(repo: Union[str, Repo]): """Check if repo is a gto repo""" try: return GitRegistry.from_repo(repo).is_gto_repo() @@ -27,7 +27,7 @@ def is_gto_repo(repo: Union[str, Repo]): return False -def get_index(repo: Union[str, Repo], file=False): +def _get_index(repo: Union[str, Repo], file=False): """Get index state""" if file: return FileIndexManager.from_path( diff --git a/gto/cli.py b/gto/cli.py index a33aeb4f..c12c7a2b 100644 --- a/gto/cli.py +++ b/gto/cli.py @@ -782,7 +782,9 @@ def print_index(repo: str = option_repo): Examples: $ gto print-index """ - index = gto.api.get_index(repo).artifact_centric_representation() + index = gto.api._get_index( # pylint: disable=protected-access + repo + ).artifact_centric_representation() format_echo(index, "json") diff --git a/tests/test_api.py b/tests/test_api.py index 8c6c4e61..03402332 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,3 +1,4 @@ +# pylint: disable=unused-variable, protected-access """TODO: add more tests for API""" import os from contextlib import contextmanager @@ -13,32 +14,32 @@ def test_empty_index(empty_git_repo: Tuple[git.Repo, Callable]): - repo, write_file = empty_git_repo # pylint: disable=unused-variable - index = gto.api.get_index(repo.working_dir) + repo, write_file = empty_git_repo + index = gto.api._get_index(repo.working_dir) assert len(index.artifact_centric_representation()) == 0 def test_empty_state(empty_git_repo: Tuple[git.Repo, Callable]): - repo, write_file = empty_git_repo # pylint: disable=unused-variable - state = gto.api._get_state(repo.working_dir) # pylint: disable=protected-access + repo, write_file = empty_git_repo + state = gto.api._get_state(repo.working_dir) assert len(state.artifacts) == 0 def test_api_info_commands_empty_repo(empty_git_repo: Tuple[git.Repo, Callable]): - repo, write_file = empty_git_repo # pylint: disable=unused-variable + repo, write_file = empty_git_repo gto.api.show(repo.working_dir) gto.api.history(repo.working_dir) def test_add_remove(empty_git_repo: Tuple[git.Repo, Callable]): - repo, write_file = empty_git_repo # pylint: disable=unused-variable + repo, write_file = empty_git_repo name, type, path, must_exist = "new-artifact", "new-type", "new/path", False gto.api.annotate( repo.working_dir, name, type=type, path=path, must_exist=must_exist ) with pytest.raises(PathIsUsed): gto.api.annotate(repo.working_dir, "other-name", path=path) - index = gto.api.get_index(repo.working_dir).get_index() + index = gto.api._get_index(repo.working_dir).get_index() assert name in index _check_obj( index.state[name], @@ -52,14 +53,14 @@ def test_add_remove(empty_git_repo: Tuple[git.Repo, Callable]): [], ) gto.api.remove(repo.working_dir, name) - index = gto.api.get_index(repo.working_dir).get_index() + index = gto.api._get_index(repo.working_dir).get_index() assert name not in index @pytest.fixture def repo_with_artifact(init_showcase_semver): repo: git.Repo - repo, write_file = init_showcase_semver # pylint: disable=unused-variable + repo, write_file = init_showcase_semver name, type, path, must_exist = "new-artifact", "new-type", "new/path", False gto.api.annotate( repo.working_dir, name, type=type, path=path, must_exist=must_exist @@ -168,7 +169,7 @@ def environ(**overrides): def test_check_ref(repo_with_artifact: Tuple[git.Repo, Callable]): - repo, name = repo_with_artifact # pylint: disable=unused-variable + repo, name = repo_with_artifact NAME = "model" VERSION = "v1.2.3" @@ -203,22 +204,22 @@ def test_check_ref(repo_with_artifact: Tuple[git.Repo, Callable]): def test_is_not_gto_repo(empty_git_repo): - repo, _ = empty_git_repo # pylint: disable=unused-variable - assert not gto.api.is_gto_repo(repo.working_dir) + repo, _ = empty_git_repo + assert not gto.api._is_gto_repo(repo.working_dir) def test_is_gto_repo_because_of_config(init_showcase_semver): - repo, _ = init_showcase_semver # pylint: disable=unused-variable - assert gto.api.is_gto_repo(repo.working_dir) + repo, _ = init_showcase_semver + assert gto.api._is_gto_repo(repo.working_dir) def test_is_gto_repo_because_of_registered_artifact(repo_with_commit): - repo, _ = repo_with_commit # pylint: disable=unused-variable + repo, _ = repo_with_commit gto.api.register(repo, "model", "HEAD", "v1.0.0") - assert gto.api.is_gto_repo(repo) + assert gto.api._is_gto_repo(repo) def test_is_gto_repo_because_of_artifacts_yaml(empty_git_repo): repo, write_file = empty_git_repo write_file("artifacts.yaml", "{}") - assert gto.api.is_gto_repo(repo) + assert gto.api._is_gto_repo(repo) diff --git a/tests/test_cli.py b/tests/test_cli.py index 8fad266a..d49906e7 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -6,7 +6,7 @@ from typer.main import get_command_from_info from typer.testing import CliRunner -from gto.api import get_index +from gto.api import _get_index from gto.cli import app from .utils import _check_obj @@ -181,7 +181,9 @@ def test_annotate(empty_git_repo: Tuple[git.Repo, Callable]): ], "", ) - artifact = get_index(repo.working_dir, file=True).get_index().state[name] + artifact = ( + _get_index(repo.working_dir, file=True).get_index().state[name] + ) # pylint: disable=protected-access _check_obj( artifact, dict(