From b8691f801004e3a690ae95c7c66f65a2b15e3224 Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Wed, 26 Jun 2024 08:03:28 +0000 Subject: [PATCH 1/7] Setup base of integration tests. --- tests/integration_helpers.py | 126 ++++++++++++++++++++++++++ tests/test_integration.py | 165 +++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 tests/integration_helpers.py create mode 100644 tests/test_integration.py diff --git a/tests/integration_helpers.py b/tests/integration_helpers.py new file mode 100644 index 0000000..b5fd245 --- /dev/null +++ b/tests/integration_helpers.py @@ -0,0 +1,126 @@ + +from datetime import date +from ProvenaInterfaces.RegistryModels import CollectionFormat, CollectionFormatAssociations, CollectionFormatApprovals, CollectionFormatDatasetInfo, OptionallyRequiredCheck, AccessInfo +from ProvenaInterfaces.RegistryAPI import * + +valid_collection_format_1 = CollectionFormat( + associations=CollectionFormatAssociations( + organisation_id="10378.1/1893860", + data_custodian_id="10378.1/1893843", + point_of_contact="contact1@example.com" + ), + approvals=CollectionFormatApprovals( + ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=True), + ethics_access=DatasetEthicsAccessCheck(relevant=True, obtained=False), + indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=False), + export_controls=ExportControls(relevant=True, obtained=False) + ), + dataset_info=CollectionFormatDatasetInfo( + name="Dataset Variation 1", + description="Integration test dataset variation 1", + access_info=AccessInfo(reposited=False, uri="http://example.com/variation1", description="Variation 1 dataset"), #type:ignore + publisher_id="10378.1/1893860", + published_date=date(2024, 6, 1), + license="https://opensource.org/licenses/Apache-2.0", # type:ignore + created_date=date(2024, 6, 1), + purpose="Testing variation 1", + rights_holder="Rights Holder 1", + usage_limitations="Limitations 1", + preferred_citation="Citation 1", + formats=["JSON", "YAML"], + keywords=["integration", "test", "variation1"], + user_metadata={"author": "Tester Variation 1"}, + version="1.1.0" + ) +) + +valid_collection_format_2 = CollectionFormat( + associations=CollectionFormatAssociations( + organisation_id="10378.1/1893860", + data_custodian_id="10378.1/1893843", + point_of_contact="contact2@example.com" + ), + approvals=CollectionFormatApprovals( + ethics_registration=DatasetEthicsRegistrationCheck(relevant=False, obtained=True), + ethics_access=DatasetEthicsAccessCheck(relevant=True, obtained=True), + indigenous_knowledge=IndigenousKnowledgeCheck(relevant=True, obtained=False), + export_controls=ExportControls(relevant=False, obtained=True) + ), + dataset_info=CollectionFormatDatasetInfo( + name="Dataset Variation 2", + description="Integration test dataset variation 2", + access_info=AccessInfo(reposited=True, uri="http://example.com/variation2", description="Variation 2 dataset"), + publisher_id="10378.1/1893860", + published_date=date(2024, 6, 2), + license="https://opensource.org/licenses/MIT", # type:ignore + created_date=date(2024, 6, 2), + purpose="Testing variation 2", + rights_holder="Rights Holder 2", + usage_limitations="No limitations", + preferred_citation="Citation 2", + formats=["CSV", "XML"], + keywords=["integration", "test", "variation2"], + user_metadata={"author": "Tester Variation 2"}, + version="2.0.1" + ) +) + + +valid_collection_format_3 = CollectionFormat( + associations=CollectionFormatAssociations( + organisation_id="10378.1/1893860", + data_custodian_id="10378.1/1893843", + point_of_contact="contact3@example.com" + ), + approvals=CollectionFormatApprovals( + ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=False), + ethics_access=DatasetEthicsAccessCheck(relevant=False, obtained=False), + indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=True), + export_controls=ExportControls(relevant=True, obtained=True) + ), + dataset_info=CollectionFormatDatasetInfo( + name="Dataset Variation 3", + description="Integration test dataset variation 3", + access_info=AccessInfo(reposited=True, uri="http://example.com/variation3", description="Variation 3 dataset"), #type:ignore + publisher_id="10378.1/1893860", + published_date=date(2024, 6, 3), + license="https://opensource.org/licenses/GPL-3.0", # type:ignore + created_date=date(2024, 6, 3), + purpose="Testing variation 3", + rights_holder="Rights Holder 3", + usage_limitations="No restrictions", + preferred_citation="Citation 3", + formats=["PDF", "DOCX"], + keywords=["integration", "test", "variation3"], + user_metadata={"author": "Tester Variation 3"}, + version="3.0.2" + ) +) + + +def get_item_subtype_route_params(item_subtype: ItemSubType) -> RouteParameters: + """Given an item subtype, will source a its RouteParmeters + Parameters + ---------- + item_subtype : ItemSubType + The desired Item subtype to source route parameters for + Returns + ------- + RouteParameters + the routeparametrs for the desired item subtype + """ + for item_route_params in route_params: + if item_route_params.subtype == item_subtype: + return item_route_params + + for item_route_params in non_test_route_params: + if item_route_params.subtype == item_subtype: + return item_route_params + + raise Exception( + f"Was not able to source route parameters for desired item_subtype = {item_subtype}") + + +def get_item_subtype_domain_info_example(item_subtype: ItemSubType) -> DomainInfoBase: + # may require re parsing of results with correct type outside of this to obtain full access to fields. + return get_item_subtype_route_params(item_subtype=item_subtype).model_examples.domain_info[0] diff --git a/tests/test_integration.py b/tests/test_integration.py new file mode 100644 index 0000000..1e5a4e9 --- /dev/null +++ b/tests/test_integration.py @@ -0,0 +1,165 @@ +''' +Created Date: Wednesday June 26th 2024 +0000 +Author: Parth Kuulkarni +----- +Last Modified: Wednesday June 26th 2024 3:16:19 PM +0000 +Modified By: Parth Kulkarni +----- +Description: TODO +----- +HISTORY: +Date By Comments +---------- --- --------------------------------------------------------- +''' + +from typing import Any, List +import pytest +import pytest_asyncio +import httpx + +from provenaclient.auth import DeviceFlow +from provenaclient.modules.provena_client import ProvenaClient +from provenaclient.utils.config import Config + +from ProvenaInterfaces.RegistryModels import * +from ProvenaInterfaces.RegistryAPI import * + +from integration_helpers import valid_collection_format_1, valid_collection_format_2, valid_collection_format_3 + +"""Pre-requiests before running unit tests: + + 1. You will need to setup token flow to be able to run these tests. + For now I will use my tokens through device flow. + 2. Creating various helper functions. + +""" + + +"""Registering and Finding Dataset""" + +@pytest.fixture +def mock_auth_manager() -> DeviceFlow: + + config = Config( + domain="dev.rrap-is.com", + realm_name="rrap" + ) + + return DeviceFlow(config=config, client_id="client-tools") + +@pytest.fixture +def client(auth_manager: DeviceFlow) -> ProvenaClient: + + config = Config( + domain="dev.rrap-is.com", + realm_name="rrap" + ) + + return ProvenaClient(config=config, auth=auth_manager) + +@pytest.mark.asyncio +async def test_register_dataset(client: ProvenaClient) -> None: + + clean_up_items: List[Any] = [] + + """ + 1. Need to find the dataset domain info, to get a dummy dataset + + """ + + valid_collection_formats: List[CollectionFormat] = [ + valid_collection_format_1, + valid_collection_format_2 + ] + + for valid_cf in valid_collection_formats: + mint_response = await client.datastore.mint_dataset(dataset_mint_info=valid_cf) + + assert mint_response.status.success, "Reported failure when minting dataset" + assert mint_response.handle, "Mint response does not contain a handle" + clean_up_items.append(mint_response.handle) + + + # Fetch dataset by created handle_id + dataset_fetch_response = await client.datastore.fetch_dataset(mint_response.handle) + dataset_fetch_item = dataset_fetch_response.item + + assert dataset_fetch_response.status.success, f"Reported failure when fetching dataset with id {mint_response.handle}" + assert dataset_fetch_item is not None, "Fetched Dataset is null/none" + assert dataset_fetch_item.id == mint_response.handle + + """So everytime some entity is registred for the first time, by default a create activity is created + which is launched through the job-api. + + 1. We will take the create_activity_session_id, and keep polling on it to see if its completed. + + This is currently TODO because registry fetch across all aspects needs to be completed. + + assert mint_response.register_create_activity_session_id + + create_activity_response = await client.job_api.await_successful_job_completion( + session_id=mint_response.register_create_activity_session_id + ) + + # Now we have to assert if the id exists + + assert create_activity_response.result is not None + + fetched_create_activity = + assert fetched_create_activity.created_item_id == dataset_fetch_item.id + + lodge_session_id = create_activity_response. + + """ + + + +@pytest.mark.asyncio +async def list_all_datasets(client: ProvenaClient) -> None: + + datasets = await client.datastore.list_all_datasets() + assert datasets is not None + assert len(datasets) > 0 + +"""Search-API related tests and finding newly related items.""" + +@pytest.mark.asyncio +async def searching_items_in_registry(client: ProvenaClient) -> None: + # Register datasets to be searched + clean_up_items: List[str] = [] + + valid_collection_formats: List[CollectionFormat] = [ + valid_collection_format_1, + valid_collection_format_2 + ] + + dataset_handles = [] + for valid_cf in valid_collection_formats: + mint_response = await client.datastore.mint_dataset(dataset_mint_info=valid_cf) + + assert mint_response.status.success, "Reported failure when minting dataset" + assert mint_response.handle, "Mint response does not contain a handle" + dataset_handles.append(mint_response.handle) + clean_up_items.append(mint_response.handle) + + # Fetch dataset by created handle_id + dataset_fetch_response = await client.datastore.fetch_dataset(mint_response.handle) + dataset_fetch_item = dataset_fetch_response.item + + assert dataset_fetch_response.status.success, f"Reported failure when fetching dataset with id {mint_response.handle}" + assert dataset_fetch_item is not None, "Fetched Dataset is null/none" + assert dataset_fetch_item.id == mint_response.handle + + # Perform search using the dataset handles + for dataset_handle in dataset_handles: + search_response = await client.search.search_registry(query=dataset_handle, subtype_filter=None, limit = None) + + assert search_response.status.success, f"Search failed for dataset handle {dataset_handle}" + + + + + + + + From 8bb943f83338d948ff4a4fc9fd092e6830c8c003 Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Thu, 27 Jun 2024 02:27:52 +0000 Subject: [PATCH 2/7] Lack of registry api completion is blocking me from completing remaning integration tests, so I am pivoting to complete that. --- src/provenaclient/clients/registry_client.py | 39 +++++ src/provenaclient/modules/prov.py | 2 +- src/provenaclient/modules/registry.py | 137 +++++++++++++++++ src/provenaclient/utils/registry_endpoints.py | 2 + tests/integration_helpers.py | 44 +++--- tests/test_integration.py | 139 ++++++++++++++++-- 6 files changed, 329 insertions(+), 34 deletions(-) diff --git a/src/provenaclient/clients/registry_client.py b/src/provenaclient/clients/registry_client.py index 6186c22..ffdfcaa 100644 --- a/src/provenaclient/clients/registry_client.py +++ b/src/provenaclient/clients/registry_client.py @@ -15,6 +15,7 @@ ''' from provenaclient.auth.manager import AuthManager +from provenaclient.models.general import HealthCheckResponse from provenaclient.utils.config import Config from enum import Enum from provenaclient.utils.helpers import * @@ -58,7 +59,27 @@ def __init__(self, auth: AuthManager, config: Config) -> None: def _build_endpoint(self, endpoint: RegistryAdminEndpoints) -> str: return f"{self._config.registry_api_endpoint}{endpoint.value}" + + def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubType) -> str: + return subtype_action_to_endpoint( + base=self._config.registry_api_endpoint, + action=action, + item_subtype=item_subtype + ) + + async def delete_item(self, id: str, item_subtype: ItemSubType) -> StatusResponse: + endpoint = self._build_subtype_endpoint( + action = RegistryAction.DELETE, item_subtype=item_subtype + ) + + return await parsed_delete_request_with_status( + client = self, + params = {'id': id}, + error_message = f"Failed to delete item with id {id} and subtype {item_subtype}", + model = StatusResponse, + url = endpoint + ) # L2 interface. class RegistryClient(ClientService): @@ -91,6 +112,22 @@ def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubT def _build_general_endpoint(self, endpoint: GenericRegistryEndpoints) -> str: return f"{self._config.registry_api_endpoint}{endpoint.value}" + + + async def get_health_check(self) -> HealthCheckResponse: + """ + Health check the API + + Returns: + HealthCheckResponse: Response + """ + return await parsed_get_request( + client=self, + url=self._build_general_endpoint(GenericRegistryEndpoints.GET_HEALTH_CHECK), + error_message="Health check failed!", + params={}, + model=HealthCheckResponse + ) async def fetch_item(self, id: str, item_subtype: ItemSubType, fetch_response_model: Type[BaseModelType], seed_allowed: Optional[bool] = None) -> BaseModelType: """ @@ -145,3 +182,5 @@ async def update_item(self, id: str, reason: Optional[str], item_subtype: ItemSu model=update_response_model, url=endpoint, ) + + \ No newline at end of file diff --git a/src/provenaclient/modules/prov.py b/src/provenaclient/modules/prov.py index 00f23ea..8f414bc 100644 --- a/src/provenaclient/modules/prov.py +++ b/src/provenaclient/modules/prov.py @@ -51,7 +51,7 @@ def __init__(self, auth: AuthManager, config: Config, prov_api_client: ProvClien self._auth = auth self._config = config - # Clients related to the datastore scoped as private. + # Clients related to the prov_api scoped as private. self._prov_api_client = prov_api_client async def generate_config_file(self, required_only: bool = True, file_path: Optional[str] = None, write_to_file: bool = False) -> str: diff --git a/src/provenaclient/modules/registry.py b/src/provenaclient/modules/registry.py index 91958f7..8e12b1b 100644 --- a/src/provenaclient/modules/registry.py +++ b/src/provenaclient/modules/registry.py @@ -15,6 +15,7 @@ ''' from provenaclient.auth.manager import AuthManager +from provenaclient.models.general import HealthCheckResponse from provenaclient.utils.config import Config from provenaclient.modules.module_helpers import * from provenaclient.clients import RegistryClient @@ -25,6 +26,38 @@ # L3 interface. +class RegistryAdminClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + Admin sub module of the Registry API providing functionality + for the admin endpoints. + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + auth_client: AuthClient + The instantiated auth client + """ + self._auth = auth + self._config = config + + # Clients related to the registry_api scoped as private. + self._registry_client = registry_client + + + async def delete(self, id: str, item_subtype: ItemSubType) -> StatusResponse: + + return await self._registry_client.admin.delete_item( + id = id, + item_subtype=item_subtype + ) class OrganisationClient(ModuleService): _registry_client: RegistryClient @@ -85,6 +118,90 @@ async def update(self, id: str, domain_info: OrganisationDomainInfo, reason: Opt reason=reason, update_response_model=StatusResponse, ) + + async def create(self, item_info: OrganisationDomainInfo) + + +class CreateActivityClient(ModuleService): + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: + """ + Fetches a create activity item from the registry + + Args: + id (str): The model ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + ModelFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.CREATE, + fetch_response_model=ModelFetchResponse, + seed_allowed=seed_allowed + ) + + +class VersionActivityClient(ModuleService): + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: + """ + Fetches a version item from the registry + + Args: + id (str): The model ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + ModelFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.VERSION, + fetch_response_model=ModelFetchResponse, + seed_allowed=seed_allowed + ) + + class ModelClient(ModuleService): @@ -155,6 +272,9 @@ class Registry(ModuleService): # Sub modules organisation: OrganisationClient model: ModelClient + create_activity: CreateActivityClient + version_acitvity: VersionActivityClient + admin: RegistryAdminClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ @@ -180,3 +300,20 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC auth=auth, config=config, registry_client=registry_client) self.model = ModelClient( auth=auth, config=config, registry_client=registry_client) + self.create_activity = CreateActivityClient( + auth=auth, config=config, registry_client=registry_client) + self.version_acitvity = VersionActivityClient( + auth=auth, config=config, registry_client=registry_client) + self.admin = RegistryAdminClient( + auth=auth, config=config, registry_client=registry_client + ) + + async def get_health_check(self) -> HealthCheckResponse: + """ + Health check the API + + Returns: + HealthCheckResponse: Response + """ + return await self._registry_client.get_health_check() + diff --git a/src/provenaclient/utils/registry_endpoints.py b/src/provenaclient/utils/registry_endpoints.py index d16b5af..c4d0aaa 100644 --- a/src/provenaclient/utils/registry_endpoints.py +++ b/src/provenaclient/utils/registry_endpoints.py @@ -33,6 +33,7 @@ class RegistryAction(str, Enum): UNLOCK = "UNLOCK" REVERT = "REVERT" LOCK_HISTORY = "LOCK_HISTORY" + DELETE = "DELETE" # Define the mappings action_postfixes: Dict[RegistryAction, str] = { @@ -52,6 +53,7 @@ class RegistryAction(str, Enum): RegistryAction.LOCK: "/locks/lock", RegistryAction.UNLOCK: "/locks/unlock", RegistryAction.LOCK_HISTORY: "/locks/history", + RegistryAction.DELETE: "/delete" } subtype_route_prefixes: Dict[ItemSubType, str] = { diff --git a/tests/integration_helpers.py b/tests/integration_helpers.py index b5fd245..cc2bb3b 100644 --- a/tests/integration_helpers.py +++ b/tests/integration_helpers.py @@ -3,6 +3,9 @@ from ProvenaInterfaces.RegistryModels import CollectionFormat, CollectionFormatAssociations, CollectionFormatApprovals, CollectionFormatDatasetInfo, OptionallyRequiredCheck, AccessInfo from ProvenaInterfaces.RegistryAPI import * +from provenaclient.utils.registry_endpoints import * +from provenaclient.modules import Registry + valid_collection_format_1 = CollectionFormat( associations=CollectionFormatAssociations( organisation_id="10378.1/1893860", @@ -11,14 +14,14 @@ ), approvals=CollectionFormatApprovals( ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=True), - ethics_access=DatasetEthicsAccessCheck(relevant=True, obtained=False), + ethics_access=DatasetEthicsAccessCheck(relevant=True, obtained=True), indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=False), - export_controls=ExportControls(relevant=True, obtained=False) + export_controls=ExportControls(relevant=True, obtained=True) ), dataset_info=CollectionFormatDatasetInfo( - name="Dataset Variation 1", + name="Integration Testing DiD I make it 1", description="Integration test dataset variation 1", - access_info=AccessInfo(reposited=False, uri="http://example.com/variation1", description="Variation 1 dataset"), #type:ignore + access_info=AccessInfo(reposited=True, uri=None, description=None), #type:ignore publisher_id="10378.1/1893860", published_date=date(2024, 6, 1), license="https://opensource.org/licenses/Apache-2.0", # type:ignore @@ -30,7 +33,7 @@ formats=["JSON", "YAML"], keywords=["integration", "test", "variation1"], user_metadata={"author": "Tester Variation 1"}, - version="1.1.0" + version=None ) ) @@ -41,15 +44,15 @@ point_of_contact="contact2@example.com" ), approvals=CollectionFormatApprovals( - ethics_registration=DatasetEthicsRegistrationCheck(relevant=False, obtained=True), - ethics_access=DatasetEthicsAccessCheck(relevant=True, obtained=True), - indigenous_knowledge=IndigenousKnowledgeCheck(relevant=True, obtained=False), - export_controls=ExportControls(relevant=False, obtained=True) + ethics_registration=DatasetEthicsRegistrationCheck(relevant=False, obtained=False), + ethics_access=DatasetEthicsAccessCheck(relevant=False, obtained=False), + indigenous_knowledge=IndigenousKnowledgeCheck(relevant=True, obtained=True), + export_controls=ExportControls(relevant=False, obtained=False) ), dataset_info=CollectionFormatDatasetInfo( name="Dataset Variation 2", description="Integration test dataset variation 2", - access_info=AccessInfo(reposited=True, uri="http://example.com/variation2", description="Variation 2 dataset"), + access_info=AccessInfo(reposited=False, uri="https://example.com.au", description="Example Integration Test"), #type:ignore publisher_id="10378.1/1893860", published_date=date(2024, 6, 2), license="https://opensource.org/licenses/MIT", # type:ignore @@ -61,7 +64,7 @@ formats=["CSV", "XML"], keywords=["integration", "test", "variation2"], user_metadata={"author": "Tester Variation 2"}, - version="2.0.1" + version=None ) ) @@ -73,15 +76,15 @@ point_of_contact="contact3@example.com" ), approvals=CollectionFormatApprovals( - ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=False), + ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=True), ethics_access=DatasetEthicsAccessCheck(relevant=False, obtained=False), - indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=True), + indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=False), export_controls=ExportControls(relevant=True, obtained=True) ), dataset_info=CollectionFormatDatasetInfo( name="Dataset Variation 3", description="Integration test dataset variation 3", - access_info=AccessInfo(reposited=True, uri="http://example.com/variation3", description="Variation 3 dataset"), #type:ignore + access_info=AccessInfo(reposited=True, uri=None, description=None), #type:ignore publisher_id="10378.1/1893860", published_date=date(2024, 6, 3), license="https://opensource.org/licenses/GPL-3.0", # type:ignore @@ -93,13 +96,16 @@ formats=["PDF", "DOCX"], keywords=["integration", "test", "variation3"], user_metadata={"author": "Tester Variation 3"}, - version="3.0.2" + version=None ) ) -def get_item_subtype_route_params(item_subtype: ItemSubType) -> RouteParameters: - """Given an item subtype, will source a its RouteParmeters +""" + +#def get_item_subtype_route_params(item_subtype: ItemSubType) -> RouteParameters: + + Given an item subtype, will source a its RouteParmeters Parameters ---------- item_subtype : ItemSubType @@ -108,7 +114,6 @@ def get_item_subtype_route_params(item_subtype: ItemSubType) -> RouteParameters: ------- RouteParameters the routeparametrs for the desired item subtype - """ for item_route_params in route_params: if item_route_params.subtype == item_subtype: return item_route_params @@ -119,8 +124,11 @@ def get_item_subtype_route_params(item_subtype: ItemSubType) -> RouteParameters: raise Exception( f"Was not able to source route parameters for desired item_subtype = {item_subtype}") + def get_item_subtype_domain_info_example(item_subtype: ItemSubType) -> DomainInfoBase: # may require re parsing of results with correct type outside of this to obtain full access to fields. return get_item_subtype_route_params(item_subtype=item_subtype).model_examples.domain_info[0] + +""" diff --git a/tests/test_integration.py b/tests/test_integration.py index 1e5a4e9..6a1f225 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -12,19 +12,22 @@ ---------- --- --------------------------------------------------------- ''' -from typing import Any, List +from typing import Any, AsyncGenerator, List, cast import pytest import pytest_asyncio import httpx from provenaclient.auth import DeviceFlow from provenaclient.modules.provena_client import ProvenaClient +from provenaclient.modules.registry import Registry from provenaclient.utils.config import Config from ProvenaInterfaces.RegistryModels import * from ProvenaInterfaces.RegistryAPI import * +from ProvenaInterfaces.AsyncJobModels import RegistryRegisterCreateActivityResult from integration_helpers import valid_collection_format_1, valid_collection_format_2, valid_collection_format_3 +from provenaclient.utils.exceptions import BadRequestException """Pre-requiests before running unit tests: @@ -38,7 +41,7 @@ """Registering and Finding Dataset""" @pytest.fixture -def mock_auth_manager() -> DeviceFlow: +def auth_manager() -> DeviceFlow: config = Config( domain="dev.rrap-is.com", @@ -57,10 +60,48 @@ def client(auth_manager: DeviceFlow) -> ProvenaClient: return ProvenaClient(config=config, auth=auth_manager) + + +async def _cleanup(client: ProvenaClient, list_of_handles: List[Tuple[ItemSubType, IdentifiedResource]]) -> None: + for item_sub_type, handle in list_of_handles: + delete_status_response = await client.registry.admin.delete(id=handle, item_subtype=item_sub_type) + assert delete_status_response.status.success, f"Delete request has failed with details {delete_status_response.status.details}." + + +async def health_check_of_all_apis(client: ProvenaClient) -> None: + + health_check_successful_message = "Health check successful." + + auth_api = await client.auth_api.get_health_check() + assert auth_api.message == health_check_successful_message + + datastore = await client.datastore.get_health_check() + assert datastore.message == health_check_successful_message + + prov = await client.prov_api.get_health_check() + assert prov.message == health_check_successful_message + + registry = await client.registry.get_health_check() + assert registry.message == health_check_successful_message + + job_api = await client.job_api.get_health_check() + assert job_api.message == health_check_successful_message + + +"""Datastore""" + +@pytest.mark.asyncio +async def test_invalid_handle_fetch_dataset(client: ProvenaClient) -> None: + + invalid_dataset_handle = "1234567890123" + + with pytest.raises(BadRequestException): + await client.datastore.fetch_dataset(id = invalid_dataset_handle) + @pytest.mark.asyncio async def test_register_dataset(client: ProvenaClient) -> None: - clean_up_items: List[Any] = [] + cleanup_items: List[Tuple[ItemSubType, IdentifiedResource]] """ 1. Need to find the dataset domain info, to get a dummy dataset @@ -77,7 +118,7 @@ async def test_register_dataset(client: ProvenaClient) -> None: assert mint_response.status.success, "Reported failure when minting dataset" assert mint_response.handle, "Mint response does not contain a handle" - clean_up_items.append(mint_response.handle) + cleanup_items.append((ItemSubType.DATASET, mint_response.handle)) # Fetch dataset by created handle_id @@ -95,6 +136,12 @@ async def test_register_dataset(client: ProvenaClient) -> None: This is currently TODO because registry fetch across all aspects needs to be completed. + """ + + # Ensure the workflow links were updated + assert dataset_fetch_item.workflow_links + assert dataset_fetch_item.workflow_links.create_activity_workflow_id + assert mint_response.register_create_activity_session_id create_activity_response = await client.job_api.await_successful_job_completion( @@ -104,15 +151,34 @@ async def test_register_dataset(client: ProvenaClient) -> None: # Now we have to assert if the id exists assert create_activity_response.result is not None + parsed_result = RegistryRegisterCreateActivityResult.parse_obj( + create_activity_response.result) + + lodge_session_id = parsed_result.lodge_session_id + creation_activity_id = parsed_result.creation_activity_id - fetched_create_activity = - assert fetched_create_activity.created_item_id == dataset_fetch_item.id + # Clean up dataset Create side effect + cleanup_items.append( + (ItemSubType.CREATE, creation_activity_id)) - lodge_session_id = create_activity_response. + # Wait for next step of lifecycle - step 2 + # no meaningful response from this - just check success + await client.job_api.await_successful_job_completion( + session_id=lodge_session_id + ) - """ + # - check the Create activity was produced and is accurate + fetched_create_activity_response = await client.registry.create_activity.fetch( + id = creation_activity_id + ) + + assert fetched_create_activity_response.item + assert fetched_create_activity_response.item.id == dataset_fetch_item + + await _cleanup(client = client, list_of_handles=cleanup_items) +"""Listing items that is present.""" @pytest.mark.asyncio async def list_all_datasets(client: ProvenaClient) -> None: @@ -120,27 +186,28 @@ async def list_all_datasets(client: ProvenaClient) -> None: datasets = await client.datastore.list_all_datasets() assert datasets is not None assert len(datasets) > 0 + """Search-API related tests and finding newly related items.""" + @pytest.mark.asyncio -async def searching_items_in_registry(client: ProvenaClient) -> None: - # Register datasets to be searched - clean_up_items: List[str] = [] +async def test_searching_items_in_registry(client: ProvenaClient) -> None: valid_collection_formats: List[CollectionFormat] = [ - valid_collection_format_1, - valid_collection_format_2 + valid_collection_format_1 ] + cleanup_items: List[Tuple[ItemSubType, IdentifiedResource]] = [] + dataset_handles = [] for valid_cf in valid_collection_formats: mint_response = await client.datastore.mint_dataset(dataset_mint_info=valid_cf) assert mint_response.status.success, "Reported failure when minting dataset" assert mint_response.handle, "Mint response does not contain a handle" + cleanup_items.append((ItemSubType.DATASET, mint_response.handle)) dataset_handles.append(mint_response.handle) - clean_up_items.append(mint_response.handle) # Fetch dataset by created handle_id dataset_fetch_response = await client.datastore.fetch_dataset(mint_response.handle) @@ -150,14 +217,56 @@ async def searching_items_in_registry(client: ProvenaClient) -> None: assert dataset_fetch_item is not None, "Fetched Dataset is null/none" assert dataset_fetch_item.id == mint_response.handle + # Ensure the workflow links were updated + assert dataset_fetch_item.workflow_links + assert dataset_fetch_item.workflow_links.create_activity_workflow_id + + assert mint_response.register_create_activity_session_id + + create_activity_response = await client.job_api.await_successful_job_completion( + session_id=mint_response.register_create_activity_session_id + ) + + # Now we have to assert if the id exists + + assert create_activity_response.result is not None + parsed_result = RegistryRegisterCreateActivityResult.parse_obj( + create_activity_response.result) + + lodge_session_id = parsed_result.lodge_session_id + creation_activity_id = parsed_result.creation_activity_id + + # Clean up dataset Create side effect + cleanup_items.append( + (ItemSubType.CREATE, creation_activity_id)) + + # Wait for next step of lifecycle - step 2 + # no meaningful response from this - just check success + await client.job_api.await_successful_job_completion( + session_id=lodge_session_id + ) + + # - check the Create activity was produced and is accurate + fetched_create_activity_response = await client.registry.create_activity.fetch( + id = creation_activity_id + ) + + assert fetched_create_activity_response.item + assert fetched_create_activity_response.item.id == dataset_fetch_item + # Perform search using the dataset handles for dataset_handle in dataset_handles: search_response = await client.search.search_registry(query=dataset_handle, subtype_filter=None, limit = None) assert search_response.status.success, f"Search failed for dataset handle {dataset_handle}" - + assert search_response.results + assert dataset_handle in search_response.results + + await _cleanup(client = client, list_of_handles=cleanup_items) + +"""Querying Provenance""" From 96089d745129723d5950939b7918010538823dd2 Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Thu, 27 Jun 2024 05:04:26 +0000 Subject: [PATCH 3/7] Completed all generic registry client methods. --- src/provenaclient/clients/registry_client.py | 250 +++++++++++++++++++ src/provenaclient/modules/registry.py | 29 ++- 2 files changed, 278 insertions(+), 1 deletion(-) diff --git a/src/provenaclient/clients/registry_client.py b/src/provenaclient/clients/registry_client.py index ffdfcaa..e927ef8 100644 --- a/src/provenaclient/clients/registry_client.py +++ b/src/provenaclient/clients/registry_client.py @@ -22,6 +22,7 @@ from provenaclient.clients.client_helpers import * from provenaclient.utils.registry_endpoints import * from ProvenaInterfaces.RegistryModels import * +from ProvenaInterfaces.RegistryAPI import * class GenericRegistryEndpoints(str, Enum): @@ -183,4 +184,253 @@ async def update_item(self, id: str, reason: Optional[str], item_subtype: ItemSu url=endpoint, ) + async def list_items(self, list_items_payload: GeneralListRequest, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.LIST, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_post_request_with_status( + client=self, + params=None, + json_body=py_to_dict(list_items_payload), + error_message=f"Failed to list items for {item_subtype}", + model=update_model_response, + url=endpoint + ) + + async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.SEED, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_post_request_with_status( + client=self, + params=None, + json_body=None, + error_message=f"Failed to seed items for {item_subtype}", + model=update_model_response, + url=endpoint + ) + + + async def revert_item(self, revert_request: ItemRevertRequest, item_subtype: ItemSubType) -> ItemRevertResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.REVERT, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_put_request_with_status( + client=self, + params=None, + json_body=py_to_dict(revert_request), + error_message=f"Failed to revert items for {item_subtype}", + model=ItemRevertResponse, + url=endpoint + ) + + async def create_item(self, create_item_request: DomainInfoBase, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.CREATE, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_post_request_with_status( + client=self, + params=None, + json_body=py_to_dict(create_item_request), + error_message=f"Failed to create items for {item_subtype}", + model=update_model_response, + url=endpoint + ) + + async def get_schema(self, item_subtype: ItemSubType) -> JsonSchemaResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.SCHEMA, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_get_request_with_status( + client=self, + params=None, + error_message=f"Failed to get schema for {item_subtype}", + model=JsonSchemaResponse, + url=endpoint + ) + + async def validate_item(self, validate_request: DomainInfoBase, item_subtype: ItemSubType) -> StatusResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.VALIDATE, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_post_request_with_status( + client=self, + params=None, + json_body=py_to_dict(validate_request), + error_message=f"Failed to validate item for {item_subtype}", + model=JsonSchemaResponse, + url=endpoint + ) + + async def evaluate_auth_access(self, id: str, item_subtype: ItemSubType) -> DescribeAccessResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.AUTH_EVALUATE, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_get_request( + client=self, + params={"id": id}, + error_message=f"Failed to evaluate auth access for {item_subtype}", + model=DescribeAccessResponse, + url=endpoint + ) + + async def get_auth_configuration(self, id: str, item_subtype: ItemSubType) -> AccessSettings: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.AUTH_CONFIGURATION, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_get_request( + client=self, + params={"id": id}, + error_message=f"Failed to get auth config for {item_subtype}", + model=AccessSettings, + url=endpoint + ) + + async def modify_auth_configuration(self, id:str, auth_change_request: AccessSettings, item_subtype: ItemSubType) -> StatusResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.AUTH_CONFIGURATION, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_put_request_with_status( + client=self, + params={"id": id}, + json_body=py_to_dict(auth_change_request), + error_message=f"Failed to modify auth config for {item_subtype}", + model=StatusResponse, + url=endpoint + ) + + async def get_auth_roles(self, item_subtype: ItemSubType) -> AuthRolesResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.AUTH_ROLES, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_get_request( + client=self, + params=None, + error_message=f"Failed to get auth roles for {item_subtype}", + model=AuthRolesResponse, + url=endpoint + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest, item_subtype: ItemSubType) -> StatusResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.LOCK, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_put_request_with_status( + client=self, + params=None, + json_body=py_to_dict(lock_resource_request), + error_message=f"Failed to lock resource for {item_subtype}", + model=StatusResponse, + url=endpoint + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest, item_subtype: ItemSubType) -> StatusResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.UNLOCK, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_put_request_with_status( + client=self, + params=None, + json_body=py_to_dict(unlock_resource_request), + error_message=f"Failed to unlock resource for {item_subtype}", + model=StatusResponse, + url=endpoint + ) + + async def get_lock_history(self, handle_id: str, item_subtype: ItemSubType) -> LockHistoryResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.LOCK_HISTORY, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_get_request_with_status( + client=self, + params={"id": handle_id}, + error_message=f"Failed to get lock history for id {id} for subtype {item_subtype}", + model=LockHistoryResponse, + url=endpoint + ) + + async def get_lock_status(self, id: str, item_subtype: ItemSubType) -> LockStatusResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.LOCK_HISTORY, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_get_request_with_status( + client=self, + params={"id": id}, + error_message=f"Failed to get lock status for id {id} with subtype {item_subtype}", + model=LockStatusResponse, + url=endpoint + ) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/provenaclient/modules/registry.py b/src/provenaclient/modules/registry.py index 8e12b1b..50e6cc2 100644 --- a/src/provenaclient/modules/registry.py +++ b/src/provenaclient/modules/registry.py @@ -119,7 +119,34 @@ async def update(self, id: str, domain_info: OrganisationDomainInfo, reason: Opt update_response_model=StatusResponse, ) - async def create(self, item_info: OrganisationDomainInfo) + async def list_items(self, list_items_payload: GeneralListRequest) -> OrganisationListResponse: + """Lists all orgainsations within registry based on filter + criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload contaning the filter/sort criteria + """ + + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.ORGANISATION, + update_model_response=OrganisationListResponse + ) + + async def seed_item(self) -> OrganisationSeedResponse: + + return await self._registry_client.seed_item( + item_subtype=ItemSubType.ORGANISATION, + update_model_response=OrganisationSeedResponse + ) + + + + # TODO: async def create(self, item_info: OrganisationDomainInfo) + + class CreateActivityClient(ModuleService): From 677d9210cd7eedbbd6fdcb4a12dc8b95d853ccf9 Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Thu, 27 Jun 2024 06:44:11 +0000 Subject: [PATCH 4/7] Completed L2 and L3 for registry client. --- src/provenaclient/clients/registry_client.py | 135 +- src/provenaclient/modules/registry.py | 2268 +++++++++++++++++- 2 files changed, 2302 insertions(+), 101 deletions(-) diff --git a/src/provenaclient/clients/registry_client.py b/src/provenaclient/clients/registry_client.py index e927ef8..5dacbda 100644 --- a/src/provenaclient/clients/registry_client.py +++ b/src/provenaclient/clients/registry_client.py @@ -67,6 +67,55 @@ def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubT action=action, item_subtype=item_subtype ) + + async def export_items(self) -> RegistryExportResponse: + + endpoint = self._build_endpoint(RegistryAdminEndpoints.GET_ADMIN_EXPORT) + + return await parsed_get_request_with_status( + client = self, + url = endpoint, + params = None, + error_message=f"Failed to export all items from the registry!", + model = RegistryExportResponse + ) + + async def import_items(self, registry_import_request: RegistryImportRequest) -> RegistryImportResponse: + + endpoint = self._build_endpoint(RegistryAdminEndpoints.POST_ADMIN_IMPORT) + + return await parsed_post_request_with_status( + client = self, + url = endpoint, + params = None, + json_body=py_to_dict(registry_import_request), + error_message=f"Failed to import items into the registry!", + model = RegistryImportResponse + ) + + async def restore_items_from_dynamo_table(self, restore_request: RegistryRestoreRequest) -> RegistryImportResponse: + + endpoint = self._build_endpoint(RegistryAdminEndpoints.POST_ADMIN_IMPORT) + + return await parsed_post_request_with_status( + client = self, + url = endpoint, + params = None, + json_body=py_to_dict(restore_request), + error_message=f"Failed to import items into the registry!", + model = RegistryImportResponse + ) + + async def generate_config_file(self, required_only: bool) -> str: + + response = await validated_get_request( + client=self, + url = self._build_endpoint(RegistryAdminEndpoints.GET_ADMIN_CONFIG), + error_message=f"Failed to generate config file", + params = {"required_only": required_only}, + ) + + return response.text async def delete_item(self, id: str, item_subtype: ItemSubType) -> StatusResponse: @@ -82,10 +131,74 @@ async def delete_item(self, id: str, item_subtype: ItemSubType) -> StatusRespons url = endpoint ) +class RegistryGeneralClient(ClientService): + + def __init__(self, auth: AuthManager, config: Config) -> None: + """Initialises the RegistryGeneralClient with authentication and configuration. + + Parameters + ---------- + auth: AuthManager + An abstract interface containing the user's requested auth flow method. + config: Config + A config object which contains information related to the Provena instance. + """ + self._auth = auth + self._config = config + + + def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubType) -> str: + return subtype_action_to_endpoint( + base=self._config.registry_api_endpoint, + action=action, + item_subtype=item_subtype + ) + + def _build_general_endpoint(self, endpoint: GenericRegistryEndpoints) -> str: + return f"{self._config.registry_api_endpoint}{endpoint.value}" + + async def list_general_registry_items(self, general_list_request: GeneralListRequest) -> PaginatedListResponse: + + endpoint = self._build_general_endpoint(endpoint=GenericRegistryEndpoints.POST_REGISTRY_GENERAL_LIST) + + return await parsed_post_request_with_status( + client = self, + url = endpoint, + params=None, + json_body=py_to_dict(general_list_request), + error_message=f"General list fetch failed!", + model = PaginatedListResponse + ) + + async def general_fetch_item(self, id: str) -> UntypedFetchResponse: + + endpoint = self._build_general_endpoint(endpoint=GenericRegistryEndpoints.GET_REGISTRY_GENERAL_FETCH) + + return await parsed_get_request_with_status( + client = self, + url = endpoint, + params = {"id": id}, + error_message=f"Failed to fetch item with id {id} from general registry!", + model = UntypedFetchResponse + ) + + async def get_current_provena_version(self) -> VersionResponse: + + endpoint = self._build_general_endpoint(endpoint=GenericRegistryEndpoints.GET_REGISTRY_GENERAL_ABOUT_VERSION) + + return await parsed_get_request( + client = self, + url = endpoint, + params = None, + error_message="Failed to fetch the current Provena version of your instance.", + model = VersionResponse + ) + # L2 interface. class RegistryClient(ClientService): # Sub clients admin: RegistryAdminClient + general: RegistryGeneralClient def __init__(self, auth: AuthManager, config: Config) -> None: """Initialises the RegistryClient with authentication and configuration. @@ -102,6 +215,7 @@ def __init__(self, auth: AuthManager, config: Config) -> None: # Sub clients self.admin = RegistryAdminClient(auth=auth, config=config) + self.general = RegistryGeneralClient(auth=auth, config=config) # Function to get the endpoint URL def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubType) -> str: @@ -282,7 +396,7 @@ async def validate_item(self, validate_request: DomainInfoBase, item_subtype: It params=None, json_body=py_to_dict(validate_request), error_message=f"Failed to validate item for {item_subtype}", - model=JsonSchemaResponse, + model=StatusResponse, url=endpoint ) @@ -416,6 +530,25 @@ async def get_lock_status(self, id: str, item_subtype: ItemSubType) -> LockStatu model=LockStatusResponse, url=endpoint ) + + async def version(self, version_request: VersionRequest, item_subtype: ItemSubType) -> VersionResponse: + + #determine endpoint + endpoint = self._build_subtype_endpoint( + action=RegistryAction.VERSION, item_subtype=item_subtype + ) + + #fetch item from the subtype specific endpoint + return await parsed_post_request( + client=self, + params=None, + json_body=py_to_dict(version_request), + error_message=f"Failed to complete versioning for subtype {item_subtype}", + model=VersionResponse, + url=endpoint + ) + + diff --git a/src/provenaclient/modules/registry.py b/src/provenaclient/modules/registry.py index 50e6cc2..056aea5 100644 --- a/src/provenaclient/modules/registry.py +++ b/src/provenaclient/modules/registry.py @@ -22,8 +22,12 @@ from ProvenaInterfaces.RegistryModels import * from ProvenaInterfaces.RegistryAPI import * from typing import Optional +from provenaclient.utils.helpers import read_file_helper, write_file_helper, get_and_validate_file_path + +DEFAULT_CONFIG_FILE_NAME = "registry-api.env" + # L3 interface. class RegistryAdminClient(ModuleService): @@ -52,12 +56,65 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC self._registry_client = registry_client + async def export_items(self) -> RegistryExportResponse: + + return await self._registry_client.admin.export_items() + + async def import_items(self, registry_import_request: RegistryImportRequest) -> RegistryImportResponse: + + return await self._registry_client.admin.import_items( + registry_import_request=registry_import_request + ) + + async def restore_items_from_dynamo_table(self, restore_request: RegistryRestoreRequest) -> RegistryImportResponse: + + return await self._registry_client.admin.restore_items_from_dynamo_table( + restore_request=restore_request + ) + + async def generate_config_file(self, required_only: bool = True, file_path: Optional[str] = None, write_to_file: bool = False) -> str: + """Generates a nicely formatted .env file of the current required/non supplied properties + Used to quickly bootstrap a local environment or to understand currently deployed API. + + Parameters + ---------- + required_only : bool, optional + By default True + file_path: str, optional + The path you want to save the config file at WITH the file name. If you don't specify a path + this will be saved in a relative directory. + write_to_file: bool, By default False + A boolean flag to indicate whether you want to save the config response to a file + or not. + + Returns + ---------- + str: Response containing the config text. + + """ + + file_path = get_and_validate_file_path(file_path=file_path, write_to_file=write_to_file, default_file_name=DEFAULT_CONFIG_FILE_NAME) + + config_text: str = await self._registry_client.admin.generate_config_file(required_only=required_only) + + if config_text is None: + raise ValueError(f"No data returned for generate config file endpoint.") + + # Write to file if config text is not None, write to file is True and file path is not None. + if write_to_file: + if file_path is None: + raise ValueError("File path is not set for writing the CSV.") + write_file_helper(file_path=file_path, content=config_text) + + return config_text + async def delete(self, id: str, item_subtype: ItemSubType) -> StatusResponse: return await self._registry_client.admin.delete_item( id = id, item_subtype=item_subtype ) + class OrganisationClient(ModuleService): _registry_client: RegistryClient @@ -141,16 +198,96 @@ async def seed_item(self) -> OrganisationSeedResponse: item_subtype=ItemSubType.ORGANISATION, update_model_response=OrganisationSeedResponse ) + + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + + return await self._registry_client.revert_item( + revert_request=revert_request, + item_subtype=ItemSubType.ORGANISATION + ) + + async def create_item(self, create_item_request: OrganisationDomainInfo) -> OrganisationCreateResponse: + + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.ORGANISATION, + update_model_response=OrganisationCreateResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + + return await self._registry_client.get_schema( + item_subtype=ItemSubType.ORGANISATION + ) + + async def validate_item(self, validate_request: OrganisationDomainInfo) -> StatusResponse: + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.ORGANISATION + ) + + async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.ORGANISATION + ) - # TODO: async def create(self, item_info: OrganisationDomainInfo) + async def get_auth_configuration(self, id:str) -> AccessSettings: + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.ORGANISATION + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.ORGANISATION + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.ORGANISATION + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: -class CreateActivityClient(ModuleService): + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.ORGANISATION + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.ORGANISATION + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.ORGANISATION + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.ORGANISATION + ) + + +class PersonClient(ModuleService): + _registry_client: RegistryClient + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ @@ -170,81 +307,164 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC # Clients related to the registry scoped as private. self._registry_client = registry_client - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> PersonFetchResponse: """ - Fetches a create activity item from the registry + Fetches a person from the registry Args: - id (str): The model ID + id (str): The person ID seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. Returns: - ModelFetchResponse: The fetch response + OrganisationFetchResponse: The fetch response """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.CREATE, - fetch_response_model=ModelFetchResponse, + item_subtype=ItemSubType.PERSON, + fetch_response_model=PersonFetchResponse, seed_allowed=seed_allowed ) + async def update(self, id: str, domain_info: PersonDomainInfo, reason: Optional[str]) -> StatusResponse: + """ + Updates a person in the registry -class VersionActivityClient(ModuleService): + Args: + id (str): The id of the organisation + domain_info (OrganisationDomainInfo): The new domain info + reason (Optional[str]): The reason if any - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + Returns: + StatusResponse: Status response """ + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.PERSON, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> PersonListResponse: + """Lists all person(s) within registry based on filter + criteria. Parameters ---------- - auth : AuthManager - An abstract interface containing the user's requested auth flow - method. - config : Config - A config object which contains information related to the Provena - instance. + list_items_payload : GeneralListRequest + Payload contaning the filter/sort criteria """ - # Module service - self._auth = auth - self._config = config - # Clients related to the registry scoped as private. - self._registry_client = registry_client + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.PERSON, + update_model_response=PersonListResponse + ) + + async def seed_item(self) -> PersonSeedResponse: - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: - """ - Fetches a version item from the registry + return await self._registry_client.seed_item( + item_subtype=ItemSubType.PERSON, + update_model_response=PersonSeedResponse + ) + + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: - Args: - id (str): The model ID - seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + return await self._registry_client.revert_item( + revert_request=revert_request, + item_subtype=ItemSubType.PERSON + ) + + async def create_item(self, create_item_request: PersonDomainInfo) -> PersonCreateResponse: - Returns: - ModelFetchResponse: The fetch response - """ - return await self._registry_client.fetch_item( + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.PERSON, + update_model_response=PersonCreateResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + + return await self._registry_client.get_schema( + item_subtype=ItemSubType.PERSON + ) + + async def validate_item(self, validate_request: PersonDomainInfo) -> StatusResponse: + + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.PERSON + ) + + async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: + + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.PERSON + ) + + async def get_auth_configuration(self, id:str) -> AccessSettings: + + return await self._registry_client.get_auth_configuration( id=id, - item_subtype=ItemSubType.VERSION, - fetch_response_model=ModelFetchResponse, - seed_allowed=seed_allowed + item_subtype=ItemSubType.PERSON + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.PERSON ) + + async def get_auth_roles(self) -> AuthRolesResponse: + + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.PERSON + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.PERSON + ) + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.PERSON + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: -class ModelClient(ModuleService): + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.PERSON + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.PERSON + ) + +class CreateActivityClient(ModuleService): _registry_client: RegistryClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ - Parameters ---------- auth : AuthManager - An abstract interface containing the user's requested auth flow - method. + An abstract interface containing the user's requested auth flow method. config : Config - A config object which contains information related to the Provena - instance. + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. """ # Module service self._auth = auth @@ -253,94 +473,1942 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC # Clients related to the registry scoped as private. self._registry_client = registry_client - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> CreateFetchResponse: """ - Fetches a model from the registry + Fetches a create activity item from the registry Args: - id (str): The model ID + id (str): The create activity item ID seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. Returns: - ModelFetchResponse: The fetch response + CreateFetchResponse: The fetch response """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.MODEL, - fetch_response_model=ModelFetchResponse, + item_subtype=ItemSubType.CREATE, + fetch_response_model=CreateFetchResponse, seed_allowed=seed_allowed ) - - async def update(self, id: str, domain_info: ModelDomainInfo, reason: Optional[str]) -> StatusResponse: + + async def list_items(self, list_items_payload: GeneralListRequest) -> CreateListResponse: """ - Updates a model in the registry + Lists all create activity items within the registry based on filter criteria. - Args: - id (str): The id of the model - domain_info (ModelDomainInfo): The new domain info - reason (Optional[str]): The reason if any + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria - Returns: - StatusResponse: Status response + Returns + ------- + CreateListResponse: The list response """ - return await self._registry_client.update_item( - id=id, - item_subtype=ItemSubType.MODEL, - domain_info=domain_info, - reason=reason, - update_response_model=StatusResponse, + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.CREATE, + update_model_response=CreateListResponse ) + async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for create activity items -class Registry(ModuleService): - # L2 clients used - _registry_client: RegistryClient + Returns + ------- + JsonSchemaResponse: The JSON schema response + """ + return await self._registry_client.get_schema( + item_subtype=ItemSubType.CREATE + ) - # Sub modules - organisation: OrganisationClient - model: ModelClient - create_activity: CreateActivityClient - version_acitvity: VersionActivityClient - admin: RegistryAdminClient + async def validate_item(self, validate_request: CreateDomainInfo) -> StatusResponse: + """ + Validates a create activity item in the registry - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + Parameters + ---------- + validate_request : CreateDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.CREATE + ) + + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: """ + Evaluates the auth access for a create activity item Parameters ---------- - auth : AuthManager - An abstract interface containing the user's requested auth flow - method. - config : Config - A config object which contains information related to the Provena - instance. + id : str + The create activity item ID + + Returns + ------- + DescribeAccessResponse: The describe access response """ - # Module service - self._auth = auth - self._config = config + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.CREATE + ) - # Clients related to the registry scoped as private. - self._registry_client = registry_client + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for a create activity item - # Sub modules - self.organisation = OrganisationClient( - auth=auth, config=config, registry_client=registry_client) - self.model = ModelClient( - auth=auth, config=config, registry_client=registry_client) - self.create_activity = CreateActivityClient( - auth=auth, config=config, registry_client=registry_client) - self.version_acitvity = VersionActivityClient( - auth=auth, config=config, registry_client=registry_client) - self.admin = RegistryAdminClient( - auth=auth, config=config, registry_client=registry_client + Parameters + ---------- + id : str + The create activity item ID + + Returns + ------- + AccessSettings: The access settings + """ + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.CREATE ) - - async def get_health_check(self) -> HealthCheckResponse: + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: """ - Health check the API + Modifies the auth configuration for a create activity item - Returns: - HealthCheckResponse: Response + Parameters + ---------- + id : str + The create activity item ID + auth_change_request : AccessSettings + The auth change request + + Returns + ------- + StatusResponse: The status response """ - return await self._registry_client.get_health_check() - + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.CREATE + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for create activity items + + Returns + ------- + AuthRolesResponse: The auth roles response + """ + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.CREATE + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a create activity item in the registry + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.CREATE + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a create activity item in the registry + + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.CREATE + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for a create activity item + + Parameters + ---------- + id : str + The create activity item ID + + Returns + ------- + LockHistoryResponse: The lock history response + """ + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.CREATE + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for a create activity item + + Parameters + ---------- + id : str + The create activity item ID + + Returns + ------- + LockStatusResponse: The lock status response + """ + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.CREATE + ) + + +class VersionActivityClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> VersionFetchResponse: + """ + Fetches a version activity item from the registry + + Args: + id (str): The version activity item ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + VersionFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.VERSION, + fetch_response_model=VersionFetchResponse, + seed_allowed=seed_allowed + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> VersionListResponse: + """ + Lists all version activity items within the registry based on filter criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria + + Returns + ------- + VersionListResponse: The list response + """ + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.VERSION, + update_model_response=VersionListResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for version activity items + + Returns + ------- + JsonSchemaResponse: The JSON schema response + """ + return await self._registry_client.get_schema( + item_subtype=ItemSubType.VERSION + ) + + async def validate_item(self, validate_request: VersionDomainInfo) -> StatusResponse: + """ + Validates a version activity item in the registry + + Parameters + ---------- + validate_request : VersionDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.VERSION + ) + + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + """ + Evaluates the auth access for a version activity item + + Parameters + ---------- + id : str + The version activity item ID + + Returns + ------- + DescribeAccessResponse: The describe access response + """ + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.VERSION + ) + + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for a version activity item + + Parameters + ---------- + id : str + The version activity item ID + + Returns + ------- + AccessSettings: The access settings + """ + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.VERSION + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + """ + Modifies the auth configuration for a version activity item + + Parameters + ---------- + id : str + The version activity item ID + auth_change_request : AccessSettings + The auth change request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.VERSION + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for version activity items + + Returns + ------- + AuthRolesResponse: The auth roles response + """ + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.VERSION + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a version activity item in the registry + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.VERSION + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a version activity item in the registry + + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.VERSION + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for a version activity item + + Parameters + ---------- + id : str + The version activity item ID + + Returns + ------- + LockHistoryResponse: The lock history response + """ + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.VERSION + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for a version activity item + + Parameters + ---------- + id : str + The version activity item ID + + Returns + ------- + LockStatusResponse: The lock status response + """ + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.VERSION + ) + + +class ModelRunActivityClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunFetchResponse: + """ + Fetches a model run activity item from the registry + + Args: + id (str): The model run activity item ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + ModelRunFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.MODEL_RUN, + fetch_response_model=ModelRunFetchResponse, + seed_allowed=seed_allowed + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunListResponse: + """ + Lists all model run activity items within the registry based on filter criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria + + Returns + ------- + ModelRunListResponse: The list response + """ + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.MODEL_RUN, + update_model_response=ModelRunListResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for model run activity items + + Returns + ------- + JsonSchemaResponse: The JSON schema response + """ + return await self._registry_client.get_schema( + item_subtype=ItemSubType.MODEL_RUN + ) + + async def validate_item(self, validate_request: ModelRunDomainInfo) -> StatusResponse: + """ + Validates a model run activity item in the registry + + Parameters + ---------- + validate_request : ModelRunDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + """ + Evaluates the auth access for a model run activity item + + Parameters + ---------- + id : str + The model run activity item ID + + Returns + ------- + DescribeAccessResponse: The describe access response + """ + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for a model run activity item + + Parameters + ---------- + id : str + The model run activity item ID + + Returns + ------- + AccessSettings: The access settings + """ + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + """ + Modifies the auth configuration for a model run activity item + + Parameters + ---------- + id : str + The model run activity item ID + auth_change_request : AccessSettings + The auth change request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for model run activity items + + Returns + ------- + AuthRolesResponse: The auth roles response + """ + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.MODEL_RUN + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a model run activity item in the registry + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a model run activity item in the registry + + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for a model run activity item + + Parameters + ---------- + id : str + The model run activity item ID + + Returns + ------- + LockHistoryResponse: The lock history response + """ + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.MODEL_RUN + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for a model run activity item + + Parameters + ---------- + id : str + The model run activity item ID + + Returns + ------- + LockStatusResponse: The lock status response + """ + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.MODEL_RUN + ) + + + + +class ModelClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: + """ + Fetches a model from the registry + + Args: + id (str): The model ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + ModelFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.MODEL, + fetch_response_model=ModelFetchResponse, + seed_allowed=seed_allowed + ) + + async def update(self, id: str, domain_info: ModelDomainInfo, reason: Optional[str]) -> StatusResponse: + """ + Updates a model in the registry + + Args: + id (str): The id of the model + domain_info (ModelDomainInfo): The new domain info + reason (Optional[str]): The reason if any + + Returns: + StatusResponse: Status response + """ + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.MODEL, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> ModelListResponse: + """Lists all model(s) within registry based on filter + criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload contaning the filter/sort criteria + """ + + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.MODEL, + update_model_response=ModelListResponse + ) + + async def seed_item(self) -> ModelSeedResponse: + + return await self._registry_client.seed_item( + item_subtype=ItemSubType.MODEL, + update_model_response=ModelSeedResponse + ) + + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + + return await self._registry_client.revert_item( + revert_request=revert_request, + item_subtype=ItemSubType.MODEL + ) + + async def create_item(self, create_item_request: ModelDomainInfo) -> ModelCreateResponse: + + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.MODEL, + update_model_response=ModelCreateResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + + return await self._registry_client.get_schema( + item_subtype=ItemSubType.MODEL + ) + + async def validate_item(self, validate_request: ModelDomainInfo) -> StatusResponse: + + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.MODEL + ) + + async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: + + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.MODEL + ) + + async def get_auth_configuration(self, id:str) -> AccessSettings: + + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.MODEL + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.MODEL + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.MODEL + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.MODEL + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.MODEL + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.MODEL + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.MODEL + ) + + async def version_item(self, version_request: VersionRequest) -> VersionResponse: + + return await self._registry_client.version( + version_request=version_request, + item_subtype=ItemSubType.MODEL + ) + +class ModelRunWorkFlowClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunWorkflowTemplateFetchResponse: + """ + Fetches a model run workflow template from the registry + + Args: + id (str): The model run workflow template ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + ModelFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + fetch_response_model=ModelRunWorkflowTemplateFetchResponse, + seed_allowed=seed_allowed + ) + + async def update(self, id: str, domain_info: ModelRunWorkflowTemplateDomainInfo, reason: Optional[str]) -> StatusResponse: + """ + Updates a model in the registry + + Args: + id (str): The id of the model + domain_info (ModelDomainInfo): The new domain info + reason (Optional[str]): The reason if any + + Returns: + StatusResponse: Status response + """ + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunWorkflowTemplateListResponse: + """Lists all model(s) within registry based on filter + criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload contaning the filter/sort criteria + """ + + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + update_model_response=ModelRunWorkflowTemplateListResponse + ) + + async def seed_item(self) -> ModelSeedResponse: + + return await self._registry_client.seed_item( + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + update_model_response=ModelSeedResponse + ) + + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + + return await self._registry_client.revert_item( + revert_request=revert_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def create_item(self, create_item_request: ModelRunWorkflowTemplateDomainInfo) -> ModelRunWorkflowTemplateCreateResponse: + + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + update_model_response=ModelRunWorkflowTemplateCreateResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + + return await self._registry_client.get_schema( + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def validate_item(self, validate_request: ModelRunWorkflowTemplateDomainInfo) -> StatusResponse: + + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: + + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def get_auth_configuration(self, id:str) -> AccessSettings: + + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + async def version_item(self, version_request: VersionRequest) -> VersionResponse: + + return await self._registry_client.version( + version_request=version_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + + +class DatasetTemplateClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetTemplateFetchResponse: + """ + Fetches a dataset template from the registry + + Args: + id (str): The dataset template ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + DatasetTemplateFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE, + fetch_response_model=DatasetTemplateFetchResponse, + seed_allowed=seed_allowed + ) + + async def update(self, id: str, domain_info: DatasetTemplateDomainInfo, reason: Optional[str]) -> StatusResponse: + """ + Updates a dataset template in the registry + + Args: + id (str): The id of the dataset template + domain_info (DatasetTemplateDomainInfo): The new domain info + reason (Optional[str]): The reason if any + + Returns: + StatusResponse: Status response + """ + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetTemplateListResponse: + """ + Lists all dataset templates within the registry based on filter + criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria + """ + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.DATASET_TEMPLATE, + update_model_response=DatasetTemplateListResponse + ) + + async def seed_item(self) -> DatasetTemplateSeedResponse: + """ + Seeds a dataset template in the registry + + Returns + ------- + DatasetTemplateSeedResponse: The seed response + """ + return await self._registry_client.seed_item( + item_subtype=ItemSubType.DATASET_TEMPLATE, + update_model_response=DatasetTemplateSeedResponse + ) + + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + """ + Reverts a dataset template in the registry + + Parameters + ---------- + revert_request : ItemRevertRequest + The revert request + + Returns + ------- + ItemRevertResponse: The revert response + """ + return await self._registry_client.revert_item( + revert_request=revert_request, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def create_item(self, create_item_request: DatasetTemplateDomainInfo) -> DatasetTemplateCreateResponse: + """ + Creates a dataset template in the registry + + Parameters + ---------- + create_item_request : DatasetTemplateDomainInfo + The create item request + + Returns + ------- + DatasetTemplateCreateResponse: The create response + """ + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.DATASET_TEMPLATE, + update_model_response=DatasetTemplateCreateResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for dataset templates + + Returns + ------- + JsonSchemaResponse: The JSON schema response + """ + return await self._registry_client.get_schema( + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def validate_item(self, validate_request: DatasetTemplateDomainInfo) -> StatusResponse: + """ + Validates a dataset template in the registry + + Parameters + ---------- + validate_request : DatasetTemplateDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + """ + Evaluates the auth access for a dataset template + + Parameters + ---------- + id : str + The dataset template ID + + Returns + ------- + DescribeAccessResponse: The describe access response + """ + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for a dataset template + + Parameters + ---------- + id : str + The dataset template ID + + Returns + ------- + AccessSettings: The access settings + """ + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + """ + Modifies the auth configuration for a dataset template + + Parameters + ---------- + id : str + The dataset template ID + auth_change_request : AccessSettings + The auth change request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for dataset templates + + Returns + ------- + AuthRolesResponse: The auth roles response + """ + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a dataset template in the registry + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a dataset template in the registry + + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for a dataset template + + Parameters + ---------- + id : str + The dataset template ID + + Returns + ------- + LockHistoryResponse: The lock history response + """ + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for a dataset template + + Parameters + ---------- + id : str + The dataset template ID + + Returns + ------- + LockStatusResponse: The lock status response + """ + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + async def version_item(self, version_request: VersionRequest) -> VersionResponse: + """ + Versions a dataset template in the registry + + Parameters + ---------- + version_request : VersionRequest + The version request + + Returns + ------- + VersionResponse: The version response + """ + return await self._registry_client.version( + version_request=version_request, + item_subtype=ItemSubType.DATASET_TEMPLATE + ) + + +class DatasetClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetFetchResponse: + """ + Fetches a dataset from the registry + + Args: + id (str): The dataset ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + DatasetFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.DATASET, + fetch_response_model=DatasetFetchResponse, + seed_allowed=seed_allowed + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetListResponse: + """ + Lists all datasets within the registry based on filter criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria + + Returns + ------- + DatasetListResponse: The list response + """ + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.DATASET, + update_model_response=DatasetListResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for datasets + + Returns + ------- + JsonSchemaResponse: The JSON schema response + """ + return await self._registry_client.get_schema( + item_subtype=ItemSubType.DATASET + ) + + async def validate_item(self, validate_request: DatasetDomainInfo) -> StatusResponse: + """ + Validates a dataset in the registry + + Parameters + ---------- + validate_request : DatasetDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.DATASET + ) + + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + """ + Evaluates the auth access for a dataset + + Parameters + ---------- + id : str + The dataset ID + + Returns + ------- + DescribeAccessResponse: The describe access response + """ + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.DATASET + ) + + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for a dataset + + Parameters + ---------- + id : str + The dataset ID + + Returns + ------- + AccessSettings: The access settings + """ + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.DATASET + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + """ + Modifies the auth configuration for a dataset + + Parameters + ---------- + id : str + The dataset ID + auth_change_request : AccessSettings + The auth change request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.DATASET + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for datasets + + Returns + ------- + AuthRolesResponse: The auth roles response + """ + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.DATASET + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a dataset in the registry + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.DATASET + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a dataset in the registry + + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.DATASET + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for a dataset + + Parameters + ---------- + id : str + The dataset ID + + Returns + ------- + LockHistoryResponse: The lock history response + """ + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.DATASET + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for a dataset + + Parameters + ---------- + id : str + The dataset ID + + Returns + ------- + LockStatusResponse: The lock status response + """ + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.DATASET + ) + +class StudyClient(ModuleService): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> StudyFetchResponse: + """ + Fetches a study from the registry + + Args: + id (str): The study ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + StudyFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.STUDY, + fetch_response_model=StudyFetchResponse, + seed_allowed=seed_allowed + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> StudyListResponse: + """ + Lists all studies within the registry based on filter criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria + + Returns + ------- + StudyListResponse: The list response + """ + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.STUDY, + update_model_response=StudyListResponse + ) + + async def seed_item(self) -> StudySeedResponse: + """ + Seeds a study in the registry + + Returns + ------- + StudySeedResponse: The seed response + """ + return await self._registry_client.seed_item( + item_subtype=ItemSubType.STUDY, + update_model_response=StudySeedResponse + ) + + async def update(self, id: str, domain_info: StudyDomainInfo, reason: Optional[str]) -> StatusResponse: + """ + Updates a study in the registry + + Parameters + ---------- + id : str + The id of the study + domain_info : StudyDomainInfo + The new domain info + reason : Optional[str] + The reason, if any + + Returns + ------- + StatusResponse: Status response + """ + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.STUDY, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + """ + Reverts a study in the registry + + Parameters + ---------- + revert_request : ItemRevertRequest + The revert request + + Returns + ------- + ItemRevertResponse: The revert response + """ + return await self._registry_client.revert_item( + revert_request=revert_request, + item_subtype=ItemSubType.STUDY + ) + + async def create_item(self, create_item_request: StudyDomainInfo) -> StudyCreateResponse: + """ + Creates a study in the registry + + Parameters + ---------- + create_item_request : StudyDomainInfo + The create item request + + Returns + ------- + StudyCreateResponse: The create response + """ + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.STUDY, + update_model_response=StudyCreateResponse + ) + + async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for studies + + Returns + ------- + JsonSchemaResponse: The JSON schema response + """ + return await self._registry_client.get_schema( + item_subtype=ItemSubType.STUDY + ) + + async def validate_item(self, validate_request: StudyDomainInfo) -> StatusResponse: + """ + Validates a study in the registry + + Parameters + ---------- + validate_request : StudyDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.STUDY + ) + + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + """ + Evaluates the auth access for a study + + Parameters + ---------- + id : str + The study ID + + Returns + ------- + DescribeAccessResponse: The describe access response + """ + return await self._registry_client.evaluate_auth_access( + id=id, + item_subtype=ItemSubType.STUDY + ) + + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for a study + + Parameters + ---------- + id : str + The study ID + + Returns + ------- + AccessSettings: The access settings + """ + return await self._registry_client.get_auth_configuration( + id=id, + item_subtype=ItemSubType.STUDY + ) + + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + """ + Modifies the auth configuration for a study + + Parameters + ---------- + id : str + The study ID + auth_change_request : AccessSettings + The auth change request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.modify_auth_configuration( + id=id, + auth_change_request=auth_change_request, + item_subtype=ItemSubType.STUDY + ) + + async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for studies + + Returns + ------- + AuthRolesResponse: The auth roles response + """ + return await self._registry_client.get_auth_roles( + item_subtype=ItemSubType.STUDY + ) + + async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a study in the registry + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.lock_resource( + lock_resource_request=lock_resource_request, + item_subtype=ItemSubType.STUDY + ) + + async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a study in the registry + + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse: The status response + """ + return await self._registry_client.unlock_resource( + unlock_resource_request=unlock_resource_request, + item_subtype=ItemSubType.STUDY + ) + + async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for a study + + Parameters + ---------- + id : str + The study ID + + Returns + ------- + LockHistoryResponse: The lock history response + """ + return await self._registry_client.get_lock_history( + handle_id=id, + item_subtype=ItemSubType.STUDY + ) + + async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for a study + + Parameters + ---------- + id : str + The study ID + + Returns + ------- + LockStatusResponse: The lock status response + """ + return await self._registry_client.get_lock_status( + id=id, + item_subtype=ItemSubType.STUDY + ) + + + + +class Registry(ModuleService): + # L2 clients used + _registry_client: RegistryClient + + # Sub modules + organisation: OrganisationClient + model: ModelClient + create_activity: CreateActivityClient + version_acitvity: VersionActivityClient + admin: RegistryAdminClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + # Module service + self._auth = auth + self._config = config + + # Clients related to the registry scoped as private. + self._registry_client = registry_client + + # Sub modules + self.organisation = OrganisationClient( + auth=auth, config=config, registry_client=registry_client) + self.model = ModelClient( + auth=auth, config=config, registry_client=registry_client) + self.create_activity = CreateActivityClient( + auth=auth, config=config, registry_client=registry_client) + self.version_acitvity = VersionActivityClient( + auth=auth, config=config, registry_client=registry_client) + self.admin = RegistryAdminClient( + auth=auth, config=config, registry_client=registry_client + ) + + async def get_health_check(self) -> HealthCheckResponse: + """ + Health check the API + + Returns: + HealthCheckResponse: Response + """ + return await self._registry_client.get_health_check() + + + async def list_general_registry_items(self, general_list_request: GeneralListRequest) -> PaginatedListResponse: + + return await self._registry_client.general.list_general_registry_items( + general_list_request=general_list_request + ) + + async def general_fetch_item(self, id: str) -> UntypedFetchResponse: + + return await self._registry_client.general.general_fetch_item( + id=id + ) + + async def get_current_provena_version(self) -> VersionResponse: + + return await self._registry_client.general.get_current_provena_version() From 11d4bd81c84b6db007a310d929053861e1119a31 Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Fri, 28 Jun 2024 02:47:40 +0000 Subject: [PATCH 5/7] Completion of Registry L2 and L3 registry with admin, general and other endpoints. --- src/provenaclient/clients/prov_client.py | 2 - src/provenaclient/clients/registry_client.py | 571 ++++- src/provenaclient/modules/registry.py | 2368 ++++++------------ tests/adhoc.py | 34 +- tests/integration_helpers.py | 134 - tests/test_integration.py | 274 -- 6 files changed, 1257 insertions(+), 2126 deletions(-) delete mode 100644 tests/integration_helpers.py delete mode 100644 tests/test_integration.py diff --git a/src/provenaclient/clients/prov_client.py b/src/provenaclient/clients/prov_client.py index b7e699d..cf285cf 100644 --- a/src/provenaclient/clients/prov_client.py +++ b/src/provenaclient/clients/prov_client.py @@ -85,8 +85,6 @@ async def generate_config_file(self, required_only: bool) -> str: ---------- required_only : bool, optional By default True - file_name : str, optional - The filename you want to have, by default DEFAULT_CONFIG_FILE_NAME (prov-api.env) """ response = await validated_get_request( diff --git a/src/provenaclient/clients/registry_client.py b/src/provenaclient/clients/registry_client.py index 5dacbda..171725a 100644 --- a/src/provenaclient/clients/registry_client.py +++ b/src/provenaclient/clients/registry_client.py @@ -11,6 +11,7 @@ Date By Comments ---------- --- --------------------------------------------------------- +28-06-2024 | Parth Kulkarni | Completion of L2 Interface of Registry with General, Admin and Other endpoints. 18-06-2024 | Peter Baker | Initial structure setup to help dispatch into the various sub types in the L3. ''' @@ -43,10 +44,9 @@ class RegistryAdminEndpoints(str, Enum): POST_ADMIN_IMPORT = "/admin/import" POST_ADMIN_RESTORE_FROM_TABLE = "/admin/restore_from_table" - class RegistryAdminClient(ClientService): def __init__(self, auth: AuthManager, config: Config) -> None: - """Initialises the RegistryClient with authentication and configuration. + """Initialises the RegistryAdminClient with authentication and configuration. Parameters ---------- @@ -69,68 +69,127 @@ def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubT ) async def export_items(self) -> RegistryExportResponse: + """ + Exports all items from the registry. + Returns + ------- + RegistryExportResponse + The response containing the exported items. + """ endpoint = self._build_endpoint(RegistryAdminEndpoints.GET_ADMIN_EXPORT) return await parsed_get_request_with_status( - client = self, - url = endpoint, - params = None, - error_message=f"Failed to export all items from the registry!", - model = RegistryExportResponse + client=self, + url=endpoint, + params=None, + error_message="Failed to export all items from the registry!", + model=RegistryExportResponse ) async def import_items(self, registry_import_request: RegistryImportRequest) -> RegistryImportResponse: + """ + Imports items into the registry. + + Parameters + ---------- + registry_import_request : RegistryImportRequest + The import request containing the items to import. + Returns + ------- + RegistryImportResponse + The response containing the result of the import operation. + """ endpoint = self._build_endpoint(RegistryAdminEndpoints.POST_ADMIN_IMPORT) return await parsed_post_request_with_status( - client = self, - url = endpoint, - params = None, + client=self, + url=endpoint, + params=None, json_body=py_to_dict(registry_import_request), - error_message=f"Failed to import items into the registry!", - model = RegistryImportResponse + error_message="Failed to import items into the registry!", + model=RegistryImportResponse ) async def restore_items_from_dynamo_table(self, restore_request: RegistryRestoreRequest) -> RegistryImportResponse: + """ + Restores items from a DynamoDB table into the registry. + + Parameters + ---------- + restore_request : RegistryRestoreRequest + The restore request containing the details for restoration. + Returns + ------- + RegistryImportResponse + The response containing the result of the restore operation. + """ endpoint = self._build_endpoint(RegistryAdminEndpoints.POST_ADMIN_IMPORT) return await parsed_post_request_with_status( - client = self, - url = endpoint, - params = None, + client=self, + url=endpoint, + params=None, json_body=py_to_dict(restore_request), - error_message=f"Failed to import items into the registry!", - model = RegistryImportResponse + error_message="Failed to restore items from DynamoDB table into the registry!", + model=RegistryImportResponse ) async def generate_config_file(self, required_only: bool) -> str: + """ + Generates a nicely formatted .env file of the current required/non-supplied properties. + Used to quickly bootstrap a local environment or to understand currently deployed API. + + Parameters + ---------- + required_only : bool + Whether to include only required properties. By default True. + + Returns + ------- + str + The generated .env file content. + """ response = await validated_get_request( - client=self, - url = self._build_endpoint(RegistryAdminEndpoints.GET_ADMIN_CONFIG), - error_message=f"Failed to generate config file", - params = {"required_only": required_only}, + client=self, + url=self._build_endpoint(RegistryAdminEndpoints.GET_ADMIN_CONFIG), + error_message="Failed to generate config file", + params={"required_only": required_only}, ) return response.text async def delete_item(self, id: str, item_subtype: ItemSubType) -> StatusResponse: + """ + Deletes an item from the registry. + Parameters + ---------- + id : str + The ID of the item to delete. + item_subtype : ItemSubType + The subtype of the item to delete. + + Returns + ------- + StatusResponse + The status response indicating the result of the deletion. + """ endpoint = self._build_subtype_endpoint( - action = RegistryAction.DELETE, item_subtype=item_subtype + action=RegistryAction.DELETE, item_subtype=item_subtype ) return await parsed_delete_request_with_status( - client = self, - params = {'id': id}, - error_message = f"Failed to delete item with id {id} and subtype {item_subtype}", - model = StatusResponse, - url = endpoint + client=self, + params={'id': id}, + error_message=f"Failed to delete item with id {id} and subtype {item_subtype}", + model=StatusResponse, + url=endpoint ) - + class RegistryGeneralClient(ClientService): def __init__(self, auth: AuthManager, config: Config) -> None: @@ -146,7 +205,6 @@ def __init__(self, auth: AuthManager, config: Config) -> None: self._auth = auth self._config = config - def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubType) -> str: return subtype_action_to_endpoint( base=self._config.registry_api_endpoint, @@ -158,43 +216,73 @@ def _build_general_endpoint(self, endpoint: GenericRegistryEndpoints) -> str: return f"{self._config.registry_api_endpoint}{endpoint.value}" async def list_general_registry_items(self, general_list_request: GeneralListRequest) -> PaginatedListResponse: + """ + Lists general registry items based on filter criteria. + + Parameters + ---------- + general_list_request : GeneralListRequest + The request containing filter and sort criteria. + Returns + ------- + PaginatedListResponse + The response containing the paginated list of registry items. + """ endpoint = self._build_general_endpoint(endpoint=GenericRegistryEndpoints.POST_REGISTRY_GENERAL_LIST) return await parsed_post_request_with_status( - client = self, - url = endpoint, + client=self, + url=endpoint, params=None, - json_body=py_to_dict(general_list_request), + json_body=py_to_dict(general_list_request), error_message=f"General list fetch failed!", - model = PaginatedListResponse + model=PaginatedListResponse ) async def general_fetch_item(self, id: str) -> UntypedFetchResponse: + """ + Fetches a general item from the registry. + Parameters + ---------- + id : str + The ID of the item to fetch. + + Returns + ------- + UntypedFetchResponse + The fetch response containing the item details. + """ endpoint = self._build_general_endpoint(endpoint=GenericRegistryEndpoints.GET_REGISTRY_GENERAL_FETCH) return await parsed_get_request_with_status( - client = self, - url = endpoint, - params = {"id": id}, - error_message=f"Failed to fetch item with id {id} from general registry!", - model = UntypedFetchResponse + client=self, + url=endpoint, + params={"id": id}, + error_message=f"Failed to fetch item with id {id} from general registry!", + model=UntypedFetchResponse ) async def get_current_provena_version(self) -> VersionResponse: + """ + Gets the current Provena version. + Returns + ------- + VersionResponse + The response containing the current Provena version. + """ endpoint = self._build_general_endpoint(endpoint=GenericRegistryEndpoints.GET_REGISTRY_GENERAL_ABOUT_VERSION) return await parsed_get_request( - client = self, - url = endpoint, - params = None, + client=self, + url=endpoint, + params=None, error_message="Failed to fetch the current Provena version of your instance.", - model = VersionResponse + model=VersionResponse ) -# L2 interface. class RegistryClient(ClientService): # Sub clients admin: RegistryAdminClient @@ -227,14 +315,15 @@ def _build_subtype_endpoint(self, action: RegistryAction, item_subtype: ItemSubT def _build_general_endpoint(self, endpoint: GenericRegistryEndpoints) -> str: return f"{self._config.registry_api_endpoint}{endpoint.value}" - async def get_health_check(self) -> HealthCheckResponse: """ Health check the API - Returns: - HealthCheckResponse: Response + Returns + ------- + HealthCheckResponse + Response """ return await parsed_get_request( client=self, @@ -248,14 +337,21 @@ async def fetch_item(self, id: str, item_subtype: ItemSubType, fetch_response_mo """ Ascertains the correct endpoint based on the subtype provided, then runs the fetch operation, parsing the data as the specified model. - Args: - id (str): The id of the item to fetch. - item_subtype (ItemSubType): The subtype of the item to fetch. - fetch_response_model (Type[BaseModelType]): The response pydantic model to parse as e.g. OrganisationFetchResponse - seed_allowed (Optional[bool], optional): Should the endpoint throw an error if the item is a seed item? Defaults to None. - - Returns: - BaseModelType: _description_ + Parameters + ---------- + id : str + The id of the item to fetch. + item_subtype : ItemSubType + The subtype of the item to fetch. + fetch_response_model : Type[BaseModelType] + The response pydantic model to parse as e.g. OrganisationFetchResponse + seed_allowed : Optional[bool], optional + Should the endpoint throw an error if the item is a seed item? Defaults to None. + + Returns + ------- + BaseModelType + The fetch response parsed as the specified model. """ # determine endpoint endpoint = self._build_subtype_endpoint( @@ -274,15 +370,23 @@ async def update_item(self, id: str, reason: Optional[str], item_subtype: ItemSu """ Ascertains the correct endpoint then runs the update operation on an existing item by providing new domain info. - Args: - id (str): The id of item to update. - reason (Optional[str]): The reason for updating, if any - item_subtype (ItemSubType): The subtype to update - domain_info (DomainInfoBase): The domain info to replace existing item with - update_response_model (Type[BaseModelType]): The response model to parse e.g. StatusResponse - - Returns: - BaseModelType: The response model parsed + Parameters + ---------- + id : str + The id of item to update. + reason : Optional[str] + The reason for updating, if any + item_subtype : ItemSubType + The subtype to update + domain_info : DomainInfoBase + The domain info to replace existing item with + update_response_model : Type[BaseModelType] + The response model to parse e.g. StatusResponse + + Returns + ------- + BaseModelType + The response model parsed """ # determine endpoint endpoint = self._build_subtype_endpoint( @@ -297,34 +401,64 @@ async def update_item(self, id: str, reason: Optional[str], item_subtype: ItemSu model=update_response_model, url=endpoint, ) - - async def list_items(self, list_items_payload: GeneralListRequest, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: - #determine endpoint + async def list_items(self, list_items_payload: GeneralListRequest, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + """ + Lists items within the registry based on filter criteria. + + Parameters + ---------- + list_items_payload : GeneralListRequest + The request containing filter and sort criteria. + item_subtype : ItemSubType + The subtype of the items to list. + update_model_response : Type[BaseModelType] + The response model to parse. + + Returns + ------- + BaseModelType + The response containing the list of items. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.LIST, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_post_request_with_status( - client=self, + client=self, params=None, json_body=py_to_dict(list_items_payload), error_message=f"Failed to list items for {item_subtype}", model=update_model_response, url=endpoint ) - - async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: - #determine endpoint + async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + """ + Seeds an item in the registry. + + Parameters + ---------- + item_subtype : ItemSubType + The subtype of the item to seed. + update_model_response : Type[BaseModelType] + The response model to parse. + + Returns + ------- + BaseModelType + The response containing the details of the seeded item. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.SEED, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_post_request_with_status( - client=self, + client=self, params=None, json_body=None, error_message=f"Failed to seed items for {item_subtype}", @@ -332,222 +466,403 @@ async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type url=endpoint ) - async def revert_item(self, revert_request: ItemRevertRequest, item_subtype: ItemSubType) -> ItemRevertResponse: + """ + Reverts an item in the registry. - #determine endpoint + Parameters + ---------- + revert_request : ItemRevertRequest + The revert request. + item_subtype : ItemSubType + The subtype of the item to revert. + + Returns + ------- + ItemRevertResponse + The revert response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.REVERT, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_put_request_with_status( - client=self, + client=self, params=None, json_body=py_to_dict(revert_request), error_message=f"Failed to revert items for {item_subtype}", model=ItemRevertResponse, url=endpoint ) - + async def create_item(self, create_item_request: DomainInfoBase, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + """ + Creates an item in the registry. - #determine endpoint + Parameters + ---------- + create_item_request : DomainInfoBase + The domain information required to create the item. + item_subtype : ItemSubType + The subtype of the item to create. + update_model_response : Type[BaseModelType] + The response model to parse. + + Returns + ------- + BaseModelType + The response containing the details of the created item. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.CREATE, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_post_request_with_status( - client=self, + client=self, params=None, json_body=py_to_dict(create_item_request), error_message=f"Failed to create items for {item_subtype}", model=update_model_response, url=endpoint ) - + async def get_schema(self, item_subtype: ItemSubType) -> JsonSchemaResponse: + """ + Gets the schema for the item subtype. - #determine endpoint + Parameters + ---------- + item_subtype : ItemSubType + The subtype of the item to get the schema for. + + Returns + ------- + JsonSchemaResponse + The JSON schema response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.SCHEMA, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_get_request_with_status( - client=self, + client=self, params=None, error_message=f"Failed to get schema for {item_subtype}", model=JsonSchemaResponse, url=endpoint ) - + async def validate_item(self, validate_request: DomainInfoBase, item_subtype: ItemSubType) -> StatusResponse: + """ + Validates an item in the registry. + + Parameters + ---------- + validate_request : DomainInfoBase + The domain information of the item to be validated. + item_subtype : ItemSubType + The subtype of the item to validate. + + Returns + ------- + StatusResponse + The status response indicating the result of the validation. + """ - #determine endpoint + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.VALIDATE, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_post_request_with_status( - client=self, + client=self, params=None, json_body=py_to_dict(validate_request), error_message=f"Failed to validate item for {item_subtype}", model=StatusResponse, url=endpoint ) - + async def evaluate_auth_access(self, id: str, item_subtype: ItemSubType) -> DescribeAccessResponse: + """ + Evaluates the auth access for an item. - #determine endpoint + Parameters + ---------- + id : str + The ID of the item to evaluate auth access for. + item_subtype : ItemSubType + The subtype of the item to evaluate auth access for. + + Returns + ------- + DescribeAccessResponse + The describe access response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.AUTH_EVALUATE, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_get_request( - client=self, + client=self, params={"id": id}, error_message=f"Failed to evaluate auth access for {item_subtype}", model=DescribeAccessResponse, url=endpoint ) - + async def get_auth_configuration(self, id: str, item_subtype: ItemSubType) -> AccessSettings: + """ + Gets the auth configuration for an item. - #determine endpoint + Parameters + ---------- + id : str + The ID of the item to get auth configuration for. + item_subtype : ItemSubType + The subtype of the item to get auth configuration for. + + Returns + ------- + AccessSettings + The access settings. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.AUTH_CONFIGURATION, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_get_request( - client=self, + client=self, params={"id": id}, error_message=f"Failed to get auth config for {item_subtype}", model=AccessSettings, url=endpoint ) - - async def modify_auth_configuration(self, id:str, auth_change_request: AccessSettings, item_subtype: ItemSubType) -> StatusResponse: - #determine endpoint + async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings, item_subtype: ItemSubType) -> StatusResponse: + """ + Modifies the auth configuration for an item. + + Parameters + ---------- + id : str + The ID of the item to modify auth configuration for. + auth_change_request : AccessSettings + The auth change request. + item_subtype : ItemSubType + The subtype of the item to modify auth configuration for. + + Returns + ------- + StatusResponse + The status response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.AUTH_CONFIGURATION, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_put_request_with_status( - client=self, + client=self, params={"id": id}, json_body=py_to_dict(auth_change_request), error_message=f"Failed to modify auth config for {item_subtype}", model=StatusResponse, url=endpoint ) - + async def get_auth_roles(self, item_subtype: ItemSubType) -> AuthRolesResponse: + """ + Gets the auth roles for the item subtype. - #determine endpoint + Parameters + ---------- + item_subtype : ItemSubType + The subtype of the item to get auth roles for. + + Returns + ------- + AuthRolesResponse + The auth roles response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.AUTH_ROLES, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_get_request( - client=self, + client=self, params=None, error_message=f"Failed to get auth roles for {item_subtype}", model=AuthRolesResponse, url=endpoint ) - + async def lock_resource(self, lock_resource_request: LockChangeRequest, item_subtype: ItemSubType) -> StatusResponse: + """ + Locks a resource in the registry. - #determine endpoint + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request. + item_subtype : ItemSubType + The subtype of the resource to lock. + + Returns + ------- + StatusResponse + The status response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.LOCK, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_put_request_with_status( - client=self, + client=self, params=None, json_body=py_to_dict(lock_resource_request), error_message=f"Failed to lock resource for {item_subtype}", model=StatusResponse, url=endpoint ) - + async def unlock_resource(self, unlock_resource_request: LockChangeRequest, item_subtype: ItemSubType) -> StatusResponse: + """ + Unlocks a resource in the registry. - #determine endpoint + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request. + item_subtype : ItemSubType + The subtype of the resource to unlock. + + Returns + ------- + StatusResponse + The status response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.UNLOCK, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_put_request_with_status( - client=self, + client=self, params=None, json_body=py_to_dict(unlock_resource_request), error_message=f"Failed to unlock resource for {item_subtype}", model=StatusResponse, url=endpoint ) - + async def get_lock_history(self, handle_id: str, item_subtype: ItemSubType) -> LockHistoryResponse: + """ + Gets the lock history for an item. - #determine endpoint + Parameters + ---------- + handle_id : str + The handle ID of the item to get lock history for. + item_subtype : ItemSubType + The subtype of the item to get lock history for. + + Returns + ------- + LockHistoryResponse + The lock history response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.LOCK_HISTORY, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_get_request_with_status( - client=self, + client=self, params={"id": handle_id}, - error_message=f"Failed to get lock history for id {id} for subtype {item_subtype}", + error_message=f"Failed to get lock history for id {handle_id} for subtype {item_subtype}", model=LockHistoryResponse, url=endpoint ) - + async def get_lock_status(self, id: str, item_subtype: ItemSubType) -> LockStatusResponse: + """ + Gets the lock status for an item. - #determine endpoint + Parameters + ---------- + id : str + The item ID. + item_subtype : ItemSubType + The subtype of the item to get lock status for. + + Returns + ------- + LockStatusResponse + The lock status response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.LOCK_HISTORY, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_get_request_with_status( - client=self, + client=self, params={"id": id}, error_message=f"Failed to get lock status for id {id} with subtype {item_subtype}", model=LockStatusResponse, url=endpoint ) - + async def version(self, version_request: VersionRequest, item_subtype: ItemSubType) -> VersionResponse: + """ + Versions an item in the registry. - #determine endpoint + Parameters + ---------- + version_request : VersionRequest + The version request containing the version details. + item_subtype : ItemSubType + The subtype of the item to version. + + Returns + ------- + VersionResponse + The version response. + """ + # determine endpoint endpoint = self._build_subtype_endpoint( action=RegistryAction.VERSION, item_subtype=item_subtype ) - #fetch item from the subtype specific endpoint + # fetch item from the subtype specific endpoint return await parsed_post_request( - client=self, + client=self, params=None, json_body=py_to_dict(version_request), error_message=f"Failed to complete versioning for subtype {item_subtype}", model=VersionResponse, url=endpoint ) - diff --git a/src/provenaclient/modules/registry.py b/src/provenaclient/modules/registry.py index 056aea5..de68b7f 100644 --- a/src/provenaclient/modules/registry.py +++ b/src/provenaclient/modules/registry.py @@ -10,8 +10,10 @@ HISTORY: Date By Comments ---------- --- --------------------------------------------------------- - +28-06-2024 | Parth Kulkarni | Completion of Registry L3 interface with General, Admin and Other endpoints. 18-06-2024 | Peter Baker | Initial proof of concept with fetch/update methods from L2. Sub Modules for each subtype. + + ''' from provenaclient.auth.manager import AuthManager @@ -57,16 +59,49 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC async def export_items(self) -> RegistryExportResponse: + """Provides a mechanism for admins to dump the current contents of the registry table without any validation/parsing. + + Returns + ------- + RegistryExportResponse + A status response including items in the payload + """ return await self._registry_client.admin.export_items() async def import_items(self, registry_import_request: RegistryImportRequest) -> RegistryImportResponse: + """This admin only endpoint enables rapid restoration of items in into the registry table. + + Parameters + ---------- + registry_import_request : RegistryImportRequest + Contains the import mode, more info can be found on API docs. + + Returns + ------- + RegistryImportResponse + Returns an import response which includes status + statistics. + """ return await self._registry_client.admin.import_items( registry_import_request=registry_import_request ) async def restore_items_from_dynamo_table(self, restore_request: RegistryRestoreRequest) -> RegistryImportResponse: + """Provides an admin only mechanism for copying/restoring the contents from another dynamoDB table into the currently active registry table. + This endpoint does not create any new tables - it just uses the items from a restored table (e.g. from a backup) as inputs to an import operation + against the current registry table. + + Parameters + ---------- + restore_request : RegistryRestoreRequest + The restore request settings - these will be used when propagating the items from the external table. + + Returns + ------- + RegistryImportResponse + Returns information about the import, including status and statistics. + """ return await self._registry_client.admin.restore_items_from_dynamo_table( restore_request=restore_request @@ -109,210 +144,252 @@ async def generate_config_file(self, required_only: bool = True, file_path: Opti return config_text async def delete(self, id: str, item_subtype: ItemSubType) -> StatusResponse: + """Admin only endpoint for deleting item from registry. USE CAREFULLY! + + Parameters + ---------- + id : str + ID of entity/item you want to delete. + item_subtype : ItemSubType + Subtype of item you want to delete (E.g ORGANISATION, PERSON, CREATE) + + Returns + ------- + StatusResponse + Response indicating the success/failure of your request. + """ return await self._registry_client.admin.delete_item( id = id, item_subtype=item_subtype ) - -class OrganisationClient(ModuleService): + +class RegistryBaseClass(ModuleService): _registry_client: RegistryClient - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient, item_subtype: ItemSubType) -> None: """ - Parameters ---------- auth : AuthManager - An abstract interface containing the user's requested auth flow - method. + An abstract interface containing the user's requested auth flow method. config : Config - A config object which contains information related to the Provena - instance. + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + item_subtype : ItemSubType + The subtype of the item (e.g., ORGANISATION, PERSON). """ - # Module service self._auth = auth self._config = config - - # Clients related to the registry scoped as private. self._registry_client = registry_client + self.item_subtype = item_subtype - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> OrganisationFetchResponse: - """ - Fetches an organisation from the registry - - Args: - id (str): The organisation ID - seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - - Returns: - OrganisationFetchResponse: The fetch response - """ - return await self._registry_client.fetch_item( - id=id, - item_subtype=ItemSubType.ORGANISATION, - fetch_response_model=OrganisationFetchResponse, - seed_allowed=seed_allowed - ) - - async def update(self, id: str, domain_info: OrganisationDomainInfo, reason: Optional[str]) -> StatusResponse: - """ - Updates an organisation in the registry - - Args: - id (str): The id of the organisation - domain_info (OrganisationDomainInfo): The new domain info - reason (Optional[str]): The reason if any - - Returns: - StatusResponse: Status response + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: """ - return await self._registry_client.update_item( - id=id, - item_subtype=ItemSubType.ORGANISATION, - domain_info=domain_info, - reason=reason, - update_response_model=StatusResponse, - ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> OrganisationListResponse: - """Lists all orgainsations within registry based on filter - criteria. + Reverts an item in the registry based on item subtype. Parameters ---------- - list_items_payload : GeneralListRequest - Payload contaning the filter/sort criteria - """ - - return await self._registry_client.list_items( - list_items_payload=list_items_payload, - item_subtype=ItemSubType.ORGANISATION, - update_model_response=OrganisationListResponse - ) - - async def seed_item(self) -> OrganisationSeedResponse: - - return await self._registry_client.seed_item( - item_subtype=ItemSubType.ORGANISATION, - update_model_response=OrganisationSeedResponse - ) - - async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + revert_request : ItemRevertRequest + The revert request + Returns + ------- + ItemRevertResponse + The revert response + """ return await self._registry_client.revert_item( revert_request=revert_request, - item_subtype=ItemSubType.ORGANISATION - ) - - async def create_item(self, create_item_request: OrganisationDomainInfo) -> OrganisationCreateResponse: - - return await self._registry_client.create_item( - create_item_request=create_item_request, - item_subtype=ItemSubType.ORGANISATION, - update_model_response=OrganisationCreateResponse + item_subtype=self.item_subtype ) async def get_schema(self) -> JsonSchemaResponse: + """ + Gets the schema for the item subtype + Returns + ------- + JsonSchemaResponse + The JSON schema response + """ return await self._registry_client.get_schema( - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) - async def validate_item(self, validate_request: OrganisationDomainInfo) -> StatusResponse: + async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + """ + Evaluates the auth access for an item based on item subtype. - return await self._registry_client.validate_item( - validate_request=validate_request, - item_subtype=ItemSubType.ORGANISATION - ) - - async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: + Parameters + ---------- + id : str + The item ID + Returns + ------- + DescribeAccessResponse + The describe access response + """ return await self._registry_client.evaluate_auth_access( id=id, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) - async def get_auth_configuration(self, id:str) -> AccessSettings: + async def get_auth_configuration(self, id: str) -> AccessSettings: + """ + Gets the auth configuration for an item based on item subtype. + + Parameters + ---------- + id : str + The item ID + Returns + ------- + AccessSettings + The access settings + """ return await self._registry_client.get_auth_configuration( id=id, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + """ + Modifies the auth configuration for an item based on item subtype. + + Parameters + ---------- + id : str + The item ID + auth_change_request : AccessSettings + The auth change request + Returns + ------- + StatusResponse + The status response + """ return await self._registry_client.modify_auth_configuration( id=id, auth_change_request=auth_change_request, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) async def get_auth_roles(self) -> AuthRolesResponse: + """ + Gets the auth roles for the item subtype. + Returns + ------- + AuthRolesResponse + The auth roles response + """ return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Locks a resource in the registry based on item subtype. + + Parameters + ---------- + lock_resource_request : LockChangeRequest + The lock resource request + Returns + ------- + StatusResponse + The status response + """ return await self._registry_client.lock_resource( lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + """ + Unlocks a resource in the registry based on item subtype. + Parameters + ---------- + unlock_resource_request : LockChangeRequest + The unlock resource request + + Returns + ------- + StatusResponse + The status response + """ return await self._registry_client.unlock_resource( unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) async def get_lock_history(self, id: str) -> LockHistoryResponse: + """ + Gets the lock history for an item based on item subtype. + + Parameters + ---------- + id : str + The item ID + Returns + ------- + LockHistoryResponse + The lock history response + """ return await self._registry_client.get_lock_history( handle_id=id, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) async def get_lock_status(self, id: str) -> LockStatusResponse: + """ + Gets the lock status for an item based on item subtype. + + Parameters + ---------- + id : str + The item ID + Returns + ------- + LockStatusResponse + The lock status response + """ return await self._registry_client.get_lock_status( id=id, - item_subtype=ItemSubType.ORGANISATION + item_subtype=self.item_subtype ) - - -class PersonClient(ModuleService): + +class OrganisationClient(RegistryBaseClass): _registry_client: RegistryClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ - Parameters ---------- auth : AuthManager - An abstract interface containing the user's requested auth flow - method. + An abstract interface containing the user's requested auth flow method. config : Config - A config object which contains information related to the Provena - instance. + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.ORGANISATION) - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> PersonFetchResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> OrganisationFetchResponse: """ - Fetches a person from the registry + Fetches an organisation from the registry Args: - id (str): The person ID + id (str): The organisation ID seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. Returns: @@ -320,14 +397,14 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> PersonFet """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.PERSON, - fetch_response_model=PersonFetchResponse, + item_subtype=self.item_subtype, + fetch_response_model=OrganisationFetchResponse, seed_allowed=seed_allowed ) - async def update(self, id: str, domain_info: PersonDomainInfo, reason: Optional[str]) -> StatusResponse: + async def update(self, id: str, domain_info: OrganisationDomainInfo, reason: Optional[str]) -> StatusResponse: """ - Updates a person in the registry + Updates an organisation in the registry Args: id (str): The id of the organisation @@ -339,120 +416,209 @@ async def update(self, id: str, domain_info: PersonDomainInfo, reason: Optional[ """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.PERSON, + item_subtype=self.item_subtype, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> PersonListResponse: - """Lists all person(s) within registry based on filter - criteria. + + async def list_items(self, list_items_payload: GeneralListRequest) -> OrganisationListResponse: + """ + Lists all organisations within the registry based on filter criteria. Parameters ---------- list_items_payload : GeneralListRequest - Payload contaning the filter/sort criteria - """ + Payload containing the filter/sort criteria + Returns + ------- + OrganisationListResponse: The list response + """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.PERSON, - update_model_response=PersonListResponse + item_subtype=self.item_subtype, + update_model_response=OrganisationListResponse ) - - async def seed_item(self) -> PersonSeedResponse: + async def seed_item(self) -> OrganisationSeedResponse: + """ + Seeds an organisation in the registry + + Returns + ------- + OrganisationSeedResponse: The seed response + """ return await self._registry_client.seed_item( - item_subtype=ItemSubType.PERSON, - update_model_response=PersonSeedResponse + item_subtype=self.item_subtype, + update_model_response=OrganisationSeedResponse ) - - async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: - return await self._registry_client.revert_item( - revert_request=revert_request, - item_subtype=ItemSubType.PERSON - ) - - async def create_item(self, create_item_request: PersonDomainInfo) -> PersonCreateResponse: + async def create_item(self, create_item_request: OrganisationDomainInfo) -> OrganisationCreateResponse: + """ + Creates an organisation in the registry - return await self._registry_client.create_item( - create_item_request=create_item_request, - item_subtype=ItemSubType.PERSON, - update_model_response=PersonCreateResponse - ) - - async def get_schema(self) -> JsonSchemaResponse: + Parameters + ---------- + create_item_request : OrganisationDomainInfo + The create item request - return await self._registry_client.get_schema( - item_subtype=ItemSubType.PERSON + Returns + ------- + OrganisationCreateResponse: The create response + """ + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=self.item_subtype, + update_model_response=OrganisationCreateResponse ) - - async def validate_item(self, validate_request: PersonDomainInfo) -> StatusResponse: + async def validate_item(self, validate_request: OrganisationDomainInfo) -> StatusResponse: + """ + Validates an organisation in the registry + + Parameters + ---------- + validate_request : OrganisationDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.PERSON + item_subtype=self.item_subtype ) - async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.PERSON - ) - - async def get_auth_configuration(self, id:str) -> AccessSettings: +class PersonClient(RegistryBaseClass): + _registry_client: RegistryClient - return await self._registry_client.get_auth_configuration( + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ + + Parameters + ---------- + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. + """ + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.PERSON) + + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> PersonFetchResponse: + """ + Fetches a person from the registry + + Args: + id (str): The person ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + PersonFetch: The fetch response + """ + return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.PERSON + item_subtype=ItemSubType.PERSON, + fetch_response_model=PersonFetchResponse, + seed_allowed=seed_allowed ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: - return await self._registry_client.modify_auth_configuration( + async def update(self, id: str, domain_info: PersonDomainInfo, reason: Optional[str]) -> StatusResponse: + """ + Updates a person in the registry + + Args: + id (str): The id of the organisation + domain_info (OrganisationDomainInfo): The new domain info + reason (Optional[str]): The reason if any + + Returns: + StatusResponse: Status response + """ + return await self._registry_client.update_item( id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.PERSON + item_subtype=ItemSubType.PERSON, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, ) - async def get_auth_roles(self) -> AuthRolesResponse: + async def list_items(self, list_items_payload: GeneralListRequest) -> PersonListResponse: + """Lists all person(s) within registry based on filter + criteria. - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.PERSON - ) - - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload contaning the filter/sort criteria + """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.PERSON + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.PERSON, + update_model_response=PersonListResponse ) + + async def seed_item(self) -> PersonSeedResponse: + """ + Seeds a person in the registry - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + Returns + ------- + PersonSeedResponse: The seed response + """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.PERSON + return await self._registry_client.seed_item( + item_subtype=ItemSubType.PERSON, + update_model_response=PersonSeedResponse ) - async def get_lock_history(self, id: str) -> LockHistoryResponse: + async def create_item(self, create_item_request: PersonDomainInfo) -> PersonCreateResponse: + """ + Creates a person in the registry - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.PERSON + Parameters + ---------- + create_item_request : OrganisationDomainInfo + The create item request + + Returns + ------- + PersonCreateResponse: The create response + """ + + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.PERSON, + update_model_response=PersonCreateResponse ) - async def get_lock_status(self, id: str) -> LockStatusResponse: + async def validate_item(self, validate_request: PersonDomainInfo) -> StatusResponse: + """ + Validates a person in the registry - return await self._registry_client.get_lock_status( - id=id, + Parameters + ---------- + validate_request : PersonDomainInfo + The validate request + + Returns + ------- + StatusResponse: The status response + """ + + return await self._registry_client.validate_item( + validate_request=validate_request, item_subtype=ItemSubType.PERSON ) + -class CreateActivityClient(ModuleService): +class CreateActivityClient(RegistryBaseClass): _registry_client: RegistryClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: @@ -466,12 +632,8 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC registry_client : RegistryClient The registry client to use for registry interactions. """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.CREATE) async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> CreateFetchResponse: """ @@ -509,22 +671,10 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> CreateList item_subtype=ItemSubType.CREATE, update_model_response=CreateListResponse ) - - async def get_schema(self) -> JsonSchemaResponse: - """ - Gets the schema for create activity items - - Returns - ------- - JsonSchemaResponse: The JSON schema response - """ - return await self._registry_client.get_schema( - item_subtype=ItemSubType.CREATE - ) - + async def validate_item(self, validate_request: CreateDomainInfo) -> StatusResponse: """ - Validates a create activity item in the registry + Validates a create-item activity in the registry Parameters ---------- @@ -535,969 +685,169 @@ async def validate_item(self, validate_request: CreateDomainInfo) -> StatusRespo ------- StatusResponse: The status response """ + return await self._registry_client.validate_item( validate_request=validate_request, item_subtype=ItemSubType.CREATE ) - async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: - """ - Evaluates the auth access for a create activity item + +class VersionActivityClient(RegistryBaseClass): + _registry_client: RegistryClient + + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ Parameters ---------- - id : str - The create activity item ID + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + """ + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.VERSION) - Returns - ------- - DescribeAccessResponse: The describe access response + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> VersionFetchResponse: """ - return await self._registry_client.evaluate_auth_access( + Fetches a version activity item from the registry + + Args: + id (str): The version activity item ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. + + Returns: + VersionFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.CREATE + item_subtype=ItemSubType.VERSION, + fetch_response_model=VersionFetchResponse, + seed_allowed=seed_allowed ) - async def get_auth_configuration(self, id: str) -> AccessSettings: + async def list_items(self, list_items_payload: GeneralListRequest) -> VersionListResponse: """ - Gets the auth configuration for a create activity item + Lists all version activity items within the registry based on filter criteria. Parameters ---------- - id : str - The create activity item ID + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria Returns ------- - AccessSettings: The access settings + VersionListResponse: The list response """ - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.CREATE + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.VERSION, + update_model_response=VersionListResponse ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + + async def validate_item(self, validate_request: VersionDomainInfo) -> StatusResponse: """ - Modifies the auth configuration for a create activity item + Validates a version activity in the registry Parameters ---------- - id : str - The create activity item ID - auth_change_request : AccessSettings - The auth change request + validate_request : VersionDomainInfo + The validate request Returns ------- StatusResponse: The status response """ - return await self._registry_client.modify_auth_configuration( - id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.CREATE - ) - - async def get_auth_roles(self) -> AuthRolesResponse: - """ - Gets the auth roles for create activity items - Returns - ------- - AuthRolesResponse: The auth roles response - """ - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.CREATE + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.VERSION ) + - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Locks a create activity item in the registry +class ModelRunActivityClient(RegistryBaseClass): + _registry_client: RegistryClient + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: + """ Parameters ---------- - lock_resource_request : LockChangeRequest - The lock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.CREATE - ) - - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Unlocks a create activity item in the registry - - Parameters - ---------- - unlock_resource_request : LockChangeRequest - The unlock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.CREATE - ) - - async def get_lock_history(self, id: str) -> LockHistoryResponse: - """ - Gets the lock history for a create activity item - - Parameters - ---------- - id : str - The create activity item ID - - Returns - ------- - LockHistoryResponse: The lock history response - """ - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.CREATE - ) - - async def get_lock_status(self, id: str) -> LockStatusResponse: - """ - Gets the lock status for a create activity item - - Parameters - ---------- - id : str - The create activity item ID - - Returns - ------- - LockStatusResponse: The lock status response - """ - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.CREATE - ) - - -class VersionActivityClient(ModuleService): - _registry_client: RegistryClient - - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: - """ - Parameters - ---------- - auth : AuthManager - An abstract interface containing the user's requested auth flow method. - config : Config - A config object which contains information related to the Provena instance. - registry_client : RegistryClient - The registry client to use for registry interactions. - """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client - - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> VersionFetchResponse: - """ - Fetches a version activity item from the registry - - Args: - id (str): The version activity item ID - seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - - Returns: - VersionFetchResponse: The fetch response - """ - return await self._registry_client.fetch_item( - id=id, - item_subtype=ItemSubType.VERSION, - fetch_response_model=VersionFetchResponse, - seed_allowed=seed_allowed - ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> VersionListResponse: - """ - Lists all version activity items within the registry based on filter criteria. - - Parameters - ---------- - list_items_payload : GeneralListRequest - Payload containing the filter/sort criteria - - Returns - ------- - VersionListResponse: The list response - """ - return await self._registry_client.list_items( - list_items_payload=list_items_payload, - item_subtype=ItemSubType.VERSION, - update_model_response=VersionListResponse - ) - - async def get_schema(self) -> JsonSchemaResponse: - """ - Gets the schema for version activity items - - Returns - ------- - JsonSchemaResponse: The JSON schema response - """ - return await self._registry_client.get_schema( - item_subtype=ItemSubType.VERSION - ) - - async def validate_item(self, validate_request: VersionDomainInfo) -> StatusResponse: - """ - Validates a version activity item in the registry - - Parameters - ---------- - validate_request : VersionDomainInfo - The validate request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.validate_item( - validate_request=validate_request, - item_subtype=ItemSubType.VERSION - ) - - async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: - """ - Evaluates the auth access for a version activity item - - Parameters - ---------- - id : str - The version activity item ID - - Returns - ------- - DescribeAccessResponse: The describe access response - """ - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.VERSION - ) - - async def get_auth_configuration(self, id: str) -> AccessSettings: - """ - Gets the auth configuration for a version activity item - - Parameters - ---------- - id : str - The version activity item ID - - Returns - ------- - AccessSettings: The access settings - """ - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.VERSION - ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: - """ - Modifies the auth configuration for a version activity item - - Parameters - ---------- - id : str - The version activity item ID - auth_change_request : AccessSettings - The auth change request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.modify_auth_configuration( - id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.VERSION - ) - - async def get_auth_roles(self) -> AuthRolesResponse: - """ - Gets the auth roles for version activity items - - Returns - ------- - AuthRolesResponse: The auth roles response - """ - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.VERSION - ) - - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Locks a version activity item in the registry - - Parameters - ---------- - lock_resource_request : LockChangeRequest - The lock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.VERSION - ) - - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Unlocks a version activity item in the registry - - Parameters - ---------- - unlock_resource_request : LockChangeRequest - The unlock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.VERSION - ) - - async def get_lock_history(self, id: str) -> LockHistoryResponse: - """ - Gets the lock history for a version activity item - - Parameters - ---------- - id : str - The version activity item ID - - Returns - ------- - LockHistoryResponse: The lock history response - """ - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.VERSION - ) - - async def get_lock_status(self, id: str) -> LockStatusResponse: - """ - Gets the lock status for a version activity item - - Parameters - ---------- - id : str - The version activity item ID - - Returns - ------- - LockStatusResponse: The lock status response - """ - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.VERSION - ) - - -class ModelRunActivityClient(ModuleService): - _registry_client: RegistryClient - - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: - """ - Parameters - ---------- - auth : AuthManager - An abstract interface containing the user's requested auth flow method. - config : Config - A config object which contains information related to the Provena instance. - registry_client : RegistryClient - The registry client to use for registry interactions. - """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client - - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunFetchResponse: - """ - Fetches a model run activity item from the registry - - Args: - id (str): The model run activity item ID - seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - - Returns: - ModelRunFetchResponse: The fetch response - """ - return await self._registry_client.fetch_item( - id=id, - item_subtype=ItemSubType.MODEL_RUN, - fetch_response_model=ModelRunFetchResponse, - seed_allowed=seed_allowed - ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunListResponse: - """ - Lists all model run activity items within the registry based on filter criteria. - - Parameters - ---------- - list_items_payload : GeneralListRequest - Payload containing the filter/sort criteria - - Returns - ------- - ModelRunListResponse: The list response - """ - return await self._registry_client.list_items( - list_items_payload=list_items_payload, - item_subtype=ItemSubType.MODEL_RUN, - update_model_response=ModelRunListResponse - ) - - async def get_schema(self) -> JsonSchemaResponse: - """ - Gets the schema for model run activity items - - Returns - ------- - JsonSchemaResponse: The JSON schema response - """ - return await self._registry_client.get_schema( - item_subtype=ItemSubType.MODEL_RUN - ) - - async def validate_item(self, validate_request: ModelRunDomainInfo) -> StatusResponse: - """ - Validates a model run activity item in the registry - - Parameters - ---------- - validate_request : ModelRunDomainInfo - The validate request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.validate_item( - validate_request=validate_request, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: - """ - Evaluates the auth access for a model run activity item - - Parameters - ---------- - id : str - The model run activity item ID - - Returns - ------- - DescribeAccessResponse: The describe access response - """ - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def get_auth_configuration(self, id: str) -> AccessSettings: - """ - Gets the auth configuration for a model run activity item - - Parameters - ---------- - id : str - The model run activity item ID - - Returns - ------- - AccessSettings: The access settings - """ - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: - """ - Modifies the auth configuration for a model run activity item - - Parameters - ---------- - id : str - The model run activity item ID - auth_change_request : AccessSettings - The auth change request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.modify_auth_configuration( - id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def get_auth_roles(self) -> AuthRolesResponse: - """ - Gets the auth roles for model run activity items - - Returns - ------- - AuthRolesResponse: The auth roles response - """ - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.MODEL_RUN - ) - - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Locks a model run activity item in the registry - - Parameters - ---------- - lock_resource_request : LockChangeRequest - The lock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Unlocks a model run activity item in the registry - - Parameters - ---------- - unlock_resource_request : LockChangeRequest - The unlock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def get_lock_history(self, id: str) -> LockHistoryResponse: - """ - Gets the lock history for a model run activity item - - Parameters - ---------- - id : str - The model run activity item ID - - Returns - ------- - LockHistoryResponse: The lock history response - """ - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.MODEL_RUN - ) - - async def get_lock_status(self, id: str) -> LockStatusResponse: - """ - Gets the lock status for a model run activity item - - Parameters - ---------- - id : str - The model run activity item ID - - Returns - ------- - LockStatusResponse: The lock status response - """ - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.MODEL_RUN - ) - - - - -class ModelClient(ModuleService): - _registry_client: RegistryClient - - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: - """ - - Parameters - ---------- - auth : AuthManager - An abstract interface containing the user's requested auth flow - method. - config : Config - A config object which contains information related to the Provena - instance. - """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client - - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: - """ - Fetches a model from the registry - - Args: - id (str): The model ID - seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - - Returns: - ModelFetchResponse: The fetch response - """ - return await self._registry_client.fetch_item( - id=id, - item_subtype=ItemSubType.MODEL, - fetch_response_model=ModelFetchResponse, - seed_allowed=seed_allowed - ) - - async def update(self, id: str, domain_info: ModelDomainInfo, reason: Optional[str]) -> StatusResponse: - """ - Updates a model in the registry - - Args: - id (str): The id of the model - domain_info (ModelDomainInfo): The new domain info - reason (Optional[str]): The reason if any - - Returns: - StatusResponse: Status response - """ - return await self._registry_client.update_item( - id=id, - item_subtype=ItemSubType.MODEL, - domain_info=domain_info, - reason=reason, - update_response_model=StatusResponse, - ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> ModelListResponse: - """Lists all model(s) within registry based on filter - criteria. - - Parameters - ---------- - list_items_payload : GeneralListRequest - Payload contaning the filter/sort criteria - """ - - return await self._registry_client.list_items( - list_items_payload=list_items_payload, - item_subtype=ItemSubType.MODEL, - update_model_response=ModelListResponse - ) - - async def seed_item(self) -> ModelSeedResponse: - - return await self._registry_client.seed_item( - item_subtype=ItemSubType.MODEL, - update_model_response=ModelSeedResponse - ) - - async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: - - return await self._registry_client.revert_item( - revert_request=revert_request, - item_subtype=ItemSubType.MODEL - ) - - async def create_item(self, create_item_request: ModelDomainInfo) -> ModelCreateResponse: - - return await self._registry_client.create_item( - create_item_request=create_item_request, - item_subtype=ItemSubType.MODEL, - update_model_response=ModelCreateResponse - ) - - async def get_schema(self) -> JsonSchemaResponse: - - return await self._registry_client.get_schema( - item_subtype=ItemSubType.MODEL - ) - - async def validate_item(self, validate_request: ModelDomainInfo) -> StatusResponse: - - return await self._registry_client.validate_item( - validate_request=validate_request, - item_subtype=ItemSubType.MODEL - ) - - async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: - - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.MODEL - ) - - async def get_auth_configuration(self, id:str) -> AccessSettings: - - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.MODEL - ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: - - return await self._registry_client.modify_auth_configuration( - id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.MODEL - ) - - async def get_auth_roles(self) -> AuthRolesResponse: - - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.MODEL - ) - - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: - - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.MODEL - ) - - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: - - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.MODEL - ) - - async def get_lock_history(self, id: str) -> LockHistoryResponse: - - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.MODEL - ) - - async def get_lock_status(self, id: str) -> LockStatusResponse: - - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.MODEL - ) - - async def version_item(self, version_request: VersionRequest) -> VersionResponse: - - return await self._registry_client.version( - version_request=version_request, - item_subtype=ItemSubType.MODEL - ) - -class ModelRunWorkFlowClient(ModuleService): - _registry_client: RegistryClient - - def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: - """ - - Parameters - ---------- - auth : AuthManager - An abstract interface containing the user's requested auth flow - method. - config : Config - A config object which contains information related to the Provena - instance. - """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client - - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunWorkflowTemplateFetchResponse: - """ - Fetches a model run workflow template from the registry - - Args: - id (str): The model run workflow template ID - seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - - Returns: - ModelFetchResponse: The fetch response - """ - return await self._registry_client.fetch_item( - id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - fetch_response_model=ModelRunWorkflowTemplateFetchResponse, - seed_allowed=seed_allowed - ) - - async def update(self, id: str, domain_info: ModelRunWorkflowTemplateDomainInfo, reason: Optional[str]) -> StatusResponse: - """ - Updates a model in the registry - - Args: - id (str): The id of the model - domain_info (ModelDomainInfo): The new domain info - reason (Optional[str]): The reason if any - - Returns: - StatusResponse: Status response - """ - return await self._registry_client.update_item( - id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - domain_info=domain_info, - reason=reason, - update_response_model=StatusResponse, - ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunWorkflowTemplateListResponse: - """Lists all model(s) within registry based on filter - criteria. - - Parameters - ---------- - list_items_payload : GeneralListRequest - Payload contaning the filter/sort criteria - """ - - return await self._registry_client.list_items( - list_items_payload=list_items_payload, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - update_model_response=ModelRunWorkflowTemplateListResponse - ) - - async def seed_item(self) -> ModelSeedResponse: - - return await self._registry_client.seed_item( - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - update_model_response=ModelSeedResponse - ) - - async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: - - return await self._registry_client.revert_item( - revert_request=revert_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def create_item(self, create_item_request: ModelRunWorkflowTemplateDomainInfo) -> ModelRunWorkflowTemplateCreateResponse: - - return await self._registry_client.create_item( - create_item_request=create_item_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - update_model_response=ModelRunWorkflowTemplateCreateResponse - ) - - async def get_schema(self) -> JsonSchemaResponse: - - return await self._registry_client.get_schema( - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def validate_item(self, validate_request: ModelRunWorkflowTemplateDomainInfo) -> StatusResponse: - - return await self._registry_client.validate_item( - validate_request=validate_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def evaluate_auth_access(self, id:str) -> DescribeAccessResponse: + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. + """ + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.MODEL_RUN) - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def get_auth_configuration(self, id:str) -> AccessSettings: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunFetchResponse: + """ + Fetches a model run activity item from the registry - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + Args: + id (str): The model run activity item ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - return await self._registry_client.modify_auth_configuration( + Returns: + ModelRunFetchResponse: The fetch response + """ + return await self._registry_client.fetch_item( id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def get_auth_roles(self) -> AuthRolesResponse: - - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + item_subtype=ItemSubType.MODEL_RUN, + fetch_response_model=ModelRunFetchResponse, + seed_allowed=seed_allowed ) - - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) + async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunListResponse: + """ + Lists all model run activity items within the registry based on filter criteria. - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + Parameters + ---------- + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + Returns + ------- + ModelRunListResponse: The list response + """ + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.MODEL_RUN, + update_model_response=ModelRunListResponse ) - async def get_lock_history(self, id: str) -> LockHistoryResponse: + async def validate_item(self, validate_request: ModelRunDomainInfo) -> StatusResponse: + """ + Validates a model run in the registry - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def get_lock_status(self, id: str) -> LockStatusResponse: + Parameters + ---------- + validate_request : ModelRunDomainInfo + The validate request - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE - ) - - async def version_item(self, version_request: VersionRequest) -> VersionResponse: + Returns + ------- + StatusResponse: The status response + """ - return await self._registry_client.version( - version_request=version_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.MODEL_RUN ) -class DatasetTemplateClient(ModuleService): + +class ModelClient(RegistryBaseClass): _registry_client: RegistryClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ + Parameters ---------- auth : AuthManager @@ -1507,38 +857,34 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC A config object which contains information related to the Provena instance. """ - # Module service - self._auth = auth - self._config = config - # Clients related to the registry scoped as private. - self._registry_client = registry_client + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.MODEL) - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetTemplateFetchResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetchResponse: """ - Fetches a dataset template from the registry + Fetches a model from the registry Args: - id (str): The dataset template ID + id (str): The model ID seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. Returns: - DatasetTemplateFetchResponse: The fetch response + ModelFetchResponse: The fetch response """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE, - fetch_response_model=DatasetTemplateFetchResponse, + item_subtype=ItemSubType.MODEL, + fetch_response_model=ModelFetchResponse, seed_allowed=seed_allowed ) - - async def update(self, id: str, domain_info: DatasetTemplateDomainInfo, reason: Optional[str]) -> StatusResponse: + + async def update(self, id: str, domain_info: ModelDomainInfo, reason: Optional[str]) -> StatusResponse: """ - Updates a dataset template in the registry + Updates a model in the registry Args: - id (str): The id of the dataset template - domain_info (DatasetTemplateDomainInfo): The new domain info + id (str): The id of the model + domain_info (ModelDomainInfo): The new domain info reason (Optional[str]): The reason if any Returns: @@ -1546,252 +892,231 @@ async def update(self, id: str, domain_info: DatasetTemplateDomainInfo, reason: """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE, + item_subtype=ItemSubType.MODEL, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, ) - - async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetTemplateListResponse: - """ - Lists all dataset templates within the registry based on filter + + async def list_items(self, list_items_payload: GeneralListRequest) -> ModelListResponse: + """Lists all model(s) within registry based on filter criteria. Parameters ---------- list_items_payload : GeneralListRequest - Payload containing the filter/sort criteria + Payload contaning the filter/sort criteria """ + return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.DATASET_TEMPLATE, - update_model_response=DatasetTemplateListResponse + item_subtype=ItemSubType.MODEL, + update_model_response=ModelListResponse ) - - async def seed_item(self) -> DatasetTemplateSeedResponse: + + async def seed_item(self) -> ModelSeedResponse: """ - Seeds a dataset template in the registry + Seeds a model in the registry Returns ------- - DatasetTemplateSeedResponse: The seed response - """ - return await self._registry_client.seed_item( - item_subtype=ItemSubType.DATASET_TEMPLATE, - update_model_response=DatasetTemplateSeedResponse - ) - - async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: + ModelSeedResponse: The seed response """ - Reverts a dataset template in the registry - - Parameters - ---------- - revert_request : ItemRevertRequest - The revert request - Returns - ------- - ItemRevertResponse: The revert response - """ - return await self._registry_client.revert_item( - revert_request=revert_request, - item_subtype=ItemSubType.DATASET_TEMPLATE + return await self._registry_client.seed_item( + item_subtype=ItemSubType.MODEL, + update_model_response=ModelSeedResponse ) - - async def create_item(self, create_item_request: DatasetTemplateDomainInfo) -> DatasetTemplateCreateResponse: + + + async def create_item(self, create_item_request: ModelDomainInfo) -> ModelCreateResponse: """ - Creates a dataset template in the registry + Creates a model in the registry Parameters ---------- - create_item_request : DatasetTemplateDomainInfo + create_item_request : ModelDomainInfo The create item request Returns ------- - DatasetTemplateCreateResponse: The create response + ModelCreateResponse: The create response """ + return await self._registry_client.create_item( create_item_request=create_item_request, - item_subtype=ItemSubType.DATASET_TEMPLATE, - update_model_response=DatasetTemplateCreateResponse - ) - - async def get_schema(self) -> JsonSchemaResponse: - """ - Gets the schema for dataset templates - - Returns - ------- - JsonSchemaResponse: The JSON schema response - """ - return await self._registry_client.get_schema( - item_subtype=ItemSubType.DATASET_TEMPLATE + item_subtype=ItemSubType.MODEL, + update_model_response=ModelCreateResponse ) - - async def validate_item(self, validate_request: DatasetTemplateDomainInfo) -> StatusResponse: + + async def validate_item(self, validate_request: ModelDomainInfo) -> StatusResponse: """ - Validates a dataset template in the registry + Validates a model item in the registry Parameters ---------- - validate_request : DatasetTemplateDomainInfo + validate_request : ModelDomainInfo The validate request Returns ------- StatusResponse: The status response """ + return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.DATASET_TEMPLATE + item_subtype=ItemSubType.MODEL ) - - async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + + + async def version_item(self, version_request: VersionRequest) -> VersionResponse: """ - Evaluates the auth access for a dataset template + Versions a model in the registry Parameters ---------- - id : str - The dataset template ID + version_request : VersionRequest + The version request Returns ------- - DescribeAccessResponse: The describe access response + VersionResponse: The version response """ - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE + + return await self._registry_client.version( + version_request=version_request, + item_subtype=ItemSubType.MODEL ) + +class ModelRunWorkFlowClient(RegistryBaseClass): + _registry_client: RegistryClient - async def get_auth_configuration(self, id: str) -> AccessSettings: + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ - Gets the auth configuration for a dataset template Parameters ---------- - id : str - The dataset template ID - - Returns - ------- - AccessSettings: The access settings + auth : AuthManager + An abstract interface containing the user's requested auth flow + method. + config : Config + A config object which contains information related to the Provena + instance. """ - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE - ) + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE) - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunWorkflowTemplateFetchResponse: """ - Modifies the auth configuration for a dataset template + Fetches a model run workflow template from the registry - Parameters - ---------- - id : str - The dataset template ID - auth_change_request : AccessSettings - The auth change request + Args: + id (str): The model run workflow template ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - Returns - ------- - StatusResponse: The status response + Returns: + ModelFetchResponse: The fetch response """ - return await self._registry_client.modify_auth_configuration( + return await self._registry_client.fetch_item( id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.DATASET_TEMPLATE + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + fetch_response_model=ModelRunWorkflowTemplateFetchResponse, + seed_allowed=seed_allowed ) - - async def get_auth_roles(self) -> AuthRolesResponse: + + async def update(self, id: str, domain_info: ModelRunWorkflowTemplateDomainInfo, reason: Optional[str]) -> StatusResponse: """ - Gets the auth roles for dataset templates + Updates a model in the registry - Returns - ------- - AuthRolesResponse: The auth roles response - """ - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.DATASET_TEMPLATE - ) + Args: + id (str): The id of the model + domain_info (ModelDomainInfo): The new domain info + reason (Optional[str]): The reason if any - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + Returns: + StatusResponse: Status response """ - Locks a dataset template in the registry + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunWorkflowTemplateListResponse: + """Lists all model(s) within registry based on filter + criteria. Parameters ---------- - lock_resource_request : LockChangeRequest - The lock resource request - - Returns - ------- - StatusResponse: The status response + list_items_payload : GeneralListRequest + Payload contaning the filter/sort criteria """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.DATASET_TEMPLATE - ) - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + update_model_response=ModelRunWorkflowTemplateListResponse + ) + + async def seed_item(self) -> ModelRunWorkflowTemplateSeedResponse: """ - Unlocks a dataset template in the registry - - Parameters - ---------- - unlock_resource_request : LockChangeRequest - The unlock resource request + Seeds a model run workflow template in the registry Returns ------- - StatusResponse: The status response + ModelRunWorkflowTemplateSeedResponse: The seed response """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.DATASET_TEMPLATE - ) - async def get_lock_history(self, id: str) -> LockHistoryResponse: + return await self._registry_client.seed_item( + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + update_model_response=ModelRunWorkflowTemplateSeedResponse + ) + + + async def create_item(self, create_item_request: ModelRunWorkflowTemplateDomainInfo) -> ModelRunWorkflowTemplateCreateResponse: """ - Gets the lock history for a dataset template + Creates a model run workflow template in the registry Parameters ---------- - id : str - The dataset template ID + create_item_request : ModelRunWorkflowTemplateDomainInfo + The create item request Returns ------- - LockHistoryResponse: The lock history response + ModelRunWorkflowTemplateCreateResponse: The create response """ - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE - ) - async def get_lock_status(self, id: str) -> LockStatusResponse: + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + update_model_response=ModelRunWorkflowTemplateCreateResponse + ) + + async def validate_item(self, validate_request: ModelRunWorkflowTemplateDomainInfo) -> StatusResponse: """ - Gets the lock status for a dataset template + Validates a model run workflow template item in the registry Parameters ---------- - id : str - The dataset template ID + validate_request : ModelRunWorkflowTemplateDomainInfo + The validate request Returns ------- - LockStatusResponse: The lock status response + StatusResponse: The status response """ - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE - ) + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + ) + async def version_item(self, version_request: VersionRequest) -> VersionResponse: """ - Versions a dataset template in the registry + Versions a model run workflow template in the registry Parameters ---------- @@ -1802,13 +1127,14 @@ async def version_item(self, version_request: VersionRequest) -> VersionResponse ------- VersionResponse: The version response """ + return await self._registry_client.version( version_request=version_request, - item_subtype=ItemSubType.DATASET_TEMPLATE + item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE ) + - -class DatasetClient(ModuleService): +class DatasetTemplateClient(RegistryBaseClass): _registry_client: RegistryClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: @@ -1816,228 +1142,215 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC Parameters ---------- auth : AuthManager - An abstract interface containing the user's requested auth flow method. + An abstract interface containing the user's requested auth flow + method. config : Config - A config object which contains information related to the Provena instance. - registry_client : RegistryClient - The registry client to use for registry interactions. + A config object which contains information related to the Provena + instance. """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.DATASET_TEMPLATE) - async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetFetchResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetTemplateFetchResponse: """ - Fetches a dataset from the registry + Fetches a dataset template from the registry Args: - id (str): The dataset ID + id (str): The dataset template ID seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. Returns: - DatasetFetchResponse: The fetch response + DatasetTemplateFetchResponse: The fetch response """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.DATASET, - fetch_response_model=DatasetFetchResponse, + item_subtype=ItemSubType.DATASET_TEMPLATE, + fetch_response_model=DatasetTemplateFetchResponse, seed_allowed=seed_allowed ) - async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetListResponse: + async def update(self, id: str, domain_info: DatasetTemplateDomainInfo, reason: Optional[str]) -> StatusResponse: """ - Lists all datasets within the registry based on filter criteria. + Updates a dataset template in the registry + + Args: + id (str): The id of the dataset template + domain_info (DatasetTemplateDomainInfo): The new domain info + reason (Optional[str]): The reason if any + + Returns: + StatusResponse: Status response + """ + return await self._registry_client.update_item( + id=id, + item_subtype=ItemSubType.DATASET_TEMPLATE, + domain_info=domain_info, + reason=reason, + update_response_model=StatusResponse, + ) + + async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetTemplateListResponse: + """ + Lists all dataset templates within the registry based on filter + criteria. Parameters ---------- list_items_payload : GeneralListRequest Payload containing the filter/sort criteria - - Returns - ------- - DatasetListResponse: The list response """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.DATASET, - update_model_response=DatasetListResponse + item_subtype=ItemSubType.DATASET_TEMPLATE, + update_model_response=DatasetTemplateListResponse ) - async def get_schema(self) -> JsonSchemaResponse: + async def seed_item(self) -> DatasetTemplateSeedResponse: """ - Gets the schema for datasets + Seeds a dataset template in the registry Returns ------- - JsonSchemaResponse: The JSON schema response + DatasetTemplateSeedResponse: The seed response """ - return await self._registry_client.get_schema( - item_subtype=ItemSubType.DATASET + return await self._registry_client.seed_item( + item_subtype=ItemSubType.DATASET_TEMPLATE, + update_model_response=DatasetTemplateSeedResponse ) - async def validate_item(self, validate_request: DatasetDomainInfo) -> StatusResponse: + async def create_item(self, create_item_request: DatasetTemplateDomainInfo) -> DatasetTemplateCreateResponse: """ - Validates a dataset in the registry + Creates a dataset template in the registry Parameters ---------- - validate_request : DatasetDomainInfo - The validate request + create_item_request : DatasetTemplateDomainInfo + The create item request Returns ------- - StatusResponse: The status response + DatasetTemplateCreateResponse: The create response """ - return await self._registry_client.validate_item( - validate_request=validate_request, - item_subtype=ItemSubType.DATASET + return await self._registry_client.create_item( + create_item_request=create_item_request, + item_subtype=ItemSubType.DATASET_TEMPLATE, + update_model_response=DatasetTemplateCreateResponse ) - - async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: + + async def validate_item(self, validate_request: DatasetTemplateDomainInfo) -> StatusResponse: """ - Evaluates the auth access for a dataset + Validates a dataset template item in the registry Parameters ---------- - id : str - The dataset ID + validate_request : DatasetTemplateDomainInfo + The validate request Returns ------- - DescribeAccessResponse: The describe access response - """ - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.DATASET - ) - - async def get_auth_configuration(self, id: str) -> AccessSettings: + StatusResponse: The status response """ - Gets the auth configuration for a dataset - - Parameters - ---------- - id : str - The dataset ID - Returns - ------- - AccessSettings: The access settings - """ - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.DATASET + return await self._registry_client.validate_item( + validate_request=validate_request, + item_subtype=ItemSubType.DATASET_TEMPLATE ) - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: + async def version_item(self, version_request: VersionRequest) -> VersionResponse: """ - Modifies the auth configuration for a dataset + Versions a dataset template in the registry Parameters ---------- - id : str - The dataset ID - auth_change_request : AccessSettings - The auth change request + version_request : VersionRequest + The version request Returns ------- - StatusResponse: The status response + VersionResponse: The version response """ - return await self._registry_client.modify_auth_configuration( - id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.DATASET + return await self._registry_client.version( + version_request=version_request, + item_subtype=ItemSubType.DATASET_TEMPLATE ) - async def get_auth_roles(self) -> AuthRolesResponse: - """ - Gets the auth roles for datasets - Returns - ------- - AuthRolesResponse: The auth roles response - """ - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.DATASET - ) +class DatasetClient(RegistryBaseClass): + _registry_client: RegistryClient - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ - Locks a dataset in the registry - Parameters ---------- - lock_resource_request : LockChangeRequest - The lock resource request - - Returns - ------- - StatusResponse: The status response + auth : AuthManager + An abstract interface containing the user's requested auth flow method. + config : Config + A config object which contains information related to the Provena instance. + registry_client : RegistryClient + The registry client to use for registry interactions. """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.DATASET - ) + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.DATASET) - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: + async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetFetchResponse: """ - Unlocks a dataset in the registry + Fetches a dataset from the registry - Parameters - ---------- - unlock_resource_request : LockChangeRequest - The unlock resource request + Args: + id (str): The dataset ID + seed_allowed (Optional[bool], optional): Allow seed items. Defaults to None. - Returns - ------- - StatusResponse: The status response + Returns: + DatasetFetchResponse: The fetch response """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.DATASET + return await self._registry_client.fetch_item( + id=id, + item_subtype=ItemSubType.DATASET, + fetch_response_model=DatasetFetchResponse, + seed_allowed=seed_allowed ) - async def get_lock_history(self, id: str) -> LockHistoryResponse: + async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetListResponse: """ - Gets the lock history for a dataset + Lists all datasets within the registry based on filter criteria. Parameters ---------- - id : str - The dataset ID + list_items_payload : GeneralListRequest + Payload containing the filter/sort criteria Returns ------- - LockHistoryResponse: The lock history response + DatasetListResponse: The list response """ - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.DATASET + return await self._registry_client.list_items( + list_items_payload=list_items_payload, + item_subtype=ItemSubType.DATASET, + update_model_response=DatasetListResponse ) + - async def get_lock_status(self, id: str) -> LockStatusResponse: + async def validate_item(self, validate_request: DatasetDomainInfo) -> StatusResponse: """ - Gets the lock status for a dataset + Validates a dataset item in the registry Parameters ---------- - id : str - The dataset ID + validate_request : DatasetDomainInfo + The validate request Returns ------- - LockStatusResponse: The lock status response + StatusResponse: The status response """ - return await self._registry_client.get_lock_status( - id=id, + + return await self._registry_client.validate_item( + validate_request=validate_request, item_subtype=ItemSubType.DATASET ) -class StudyClient(ModuleService): + +class StudyClient(RegistryBaseClass): _registry_client: RegistryClient def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: @@ -2051,12 +1364,8 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC registry_client : RegistryClient The registry client to use for registry interactions. """ - # Module service - self._auth = auth - self._config = config - - # Clients related to the registry scoped as private. - self._registry_client = registry_client + + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.STUDY) async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> StudyFetchResponse: """ @@ -2133,24 +1442,6 @@ async def update(self, id: str, domain_info: StudyDomainInfo, reason: Optional[s update_response_model=StatusResponse, ) - async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: - """ - Reverts a study in the registry - - Parameters - ---------- - revert_request : ItemRevertRequest - The revert request - - Returns - ------- - ItemRevertResponse: The revert response - """ - return await self._registry_client.revert_item( - revert_request=revert_request, - item_subtype=ItemSubType.STUDY - ) - async def create_item(self, create_item_request: StudyDomainInfo) -> StudyCreateResponse: """ Creates a study in the registry @@ -2169,22 +1460,10 @@ async def create_item(self, create_item_request: StudyDomainInfo) -> StudyCreate item_subtype=ItemSubType.STUDY, update_model_response=StudyCreateResponse ) - - async def get_schema(self) -> JsonSchemaResponse: - """ - Gets the schema for studies - - Returns - ------- - JsonSchemaResponse: The JSON schema response - """ - return await self._registry_client.get_schema( - item_subtype=ItemSubType.STUDY - ) - + async def validate_item(self, validate_request: StudyDomainInfo) -> StatusResponse: """ - Validates a study in the registry + Validates a study item in the registry Parameters ---------- @@ -2195,166 +1474,32 @@ async def validate_item(self, validate_request: StudyDomainInfo) -> StatusRespon ------- StatusResponse: The status response """ + return await self._registry_client.validate_item( validate_request=validate_request, item_subtype=ItemSubType.STUDY ) - async def evaluate_auth_access(self, id: str) -> DescribeAccessResponse: - """ - Evaluates the auth access for a study - - Parameters - ---------- - id : str - The study ID - - Returns - ------- - DescribeAccessResponse: The describe access response - """ - return await self._registry_client.evaluate_auth_access( - id=id, - item_subtype=ItemSubType.STUDY - ) - - async def get_auth_configuration(self, id: str) -> AccessSettings: - """ - Gets the auth configuration for a study - - Parameters - ---------- - id : str - The study ID - - Returns - ------- - AccessSettings: The access settings - """ - return await self._registry_client.get_auth_configuration( - id=id, - item_subtype=ItemSubType.STUDY - ) - - async def modify_auth_configuration(self, id: str, auth_change_request: AccessSettings) -> StatusResponse: - """ - Modifies the auth configuration for a study - - Parameters - ---------- - id : str - The study ID - auth_change_request : AccessSettings - The auth change request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.modify_auth_configuration( - id=id, - auth_change_request=auth_change_request, - item_subtype=ItemSubType.STUDY - ) - - async def get_auth_roles(self) -> AuthRolesResponse: - """ - Gets the auth roles for studies - - Returns - ------- - AuthRolesResponse: The auth roles response - """ - return await self._registry_client.get_auth_roles( - item_subtype=ItemSubType.STUDY - ) - - async def lock_resource(self, lock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Locks a study in the registry - - Parameters - ---------- - lock_resource_request : LockChangeRequest - The lock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.lock_resource( - lock_resource_request=lock_resource_request, - item_subtype=ItemSubType.STUDY - ) - - async def unlock_resource(self, unlock_resource_request: LockChangeRequest) -> StatusResponse: - """ - Unlocks a study in the registry - - Parameters - ---------- - unlock_resource_request : LockChangeRequest - The unlock resource request - - Returns - ------- - StatusResponse: The status response - """ - return await self._registry_client.unlock_resource( - unlock_resource_request=unlock_resource_request, - item_subtype=ItemSubType.STUDY - ) - - async def get_lock_history(self, id: str) -> LockHistoryResponse: - """ - Gets the lock history for a study - - Parameters - ---------- - id : str - The study ID - - Returns - ------- - LockHistoryResponse: The lock history response - """ - return await self._registry_client.get_lock_history( - handle_id=id, - item_subtype=ItemSubType.STUDY - ) - - async def get_lock_status(self, id: str) -> LockStatusResponse: - """ - Gets the lock status for a study - - Parameters - ---------- - id : str - The study ID - - Returns - ------- - LockStatusResponse: The lock status response - """ - return await self._registry_client.get_lock_status( - id=id, - item_subtype=ItemSubType.STUDY - ) - - - - + class Registry(ModuleService): # L2 clients used _registry_client: RegistryClient + # Admin sub module + admin: RegistryAdminClient + # Sub modules organisation: OrganisationClient + person: PersonClient model: ModelClient + model_run_workflow: ModelRunWorkFlowClient + dataset_template: DatasetTemplateClient + dataset: DatasetClient + study: StudyClient create_activity: CreateActivityClient version_acitvity: VersionActivityClient - admin: RegistryAdminClient - + model_run: ModelRunActivityClient + def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryClient) -> None: """ @@ -2374,16 +1519,33 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC # Clients related to the registry scoped as private. self._registry_client = registry_client + # Admin sub module + self.admin = RegistryAdminClient( + auth=auth, config=config, registry_client=registry_client + ) + # Sub modules self.organisation = OrganisationClient( - auth=auth, config=config, registry_client=registry_client) + auth=auth, config=config, registry_client=registry_client) + self.person = PersonClient( + auth=auth, config=config, registry_client=registry_client + ) self.model = ModelClient( auth=auth, config=config, registry_client=registry_client) + self.model_run_workflow = ModelRunWorkFlowClient( + auth=auth, config=config, registry_client=registry_client + ) + self.dataset_template = DatasetTemplateClient( + auth=auth, config=config, registry_client=registry_client + ) + self.study = StudyClient( + auth=auth, config=config, registry_client=registry_client + ) self.create_activity = CreateActivityClient( auth=auth, config=config, registry_client=registry_client) self.version_acitvity = VersionActivityClient( auth=auth, config=config, registry_client=registry_client) - self.admin = RegistryAdminClient( + self.model_run = ModelRunActivityClient( auth=auth, config=config, registry_client=registry_client ) @@ -2398,17 +1560,53 @@ async def get_health_check(self) -> HealthCheckResponse: async def list_general_registry_items(self, general_list_request: GeneralListRequest) -> PaginatedListResponse: + """ + Lists general registry items based on filter criteria. + + Parameters + ---------- + general_list_request : GeneralListRequest + The request containing filter and sort criteria. + + Returns + ------- + PaginatedListResponse + The response containing the paginated list of registry items. + """ return await self._registry_client.general.list_general_registry_items( general_list_request=general_list_request ) + async def general_fetch_item(self, id: str) -> UntypedFetchResponse: + """ + Fetches a general item from the registry. + + Parameters + ---------- + id : str + The ID of the item to fetch. + + Returns + ------- + UntypedFetchResponse + The fetch response containing the item details. + """ return await self._registry_client.general.general_fetch_item( id=id ) + async def get_current_provena_version(self) -> VersionResponse: + """ + Gets the current Provena version deployed on your domain. + + Returns + ------- + VersionResponse + The response containing the current Provena version. + """ return await self._registry_client.general.get_current_provena_version() diff --git a/tests/adhoc.py b/tests/adhoc.py index cf05462..5f1bcf9 100644 --- a/tests/adhoc.py +++ b/tests/adhoc.py @@ -2,9 +2,9 @@ from provenaclient import ProvenaClient, Config from provenaclient.auth import DeviceFlow from ProvenaInterfaces.RegistryModels import * -from ProvenaInterfaces.RegistryAPI import NoFilterSubtypeListRequest, SortOptions, SortType -from ProvenaInterfaces.ProvenanceAPI import ModelRunRecord, TemplatedDataset, RegisterBatchModelRunRequest -from ProvenaInterfaces.ProvenanceModels import DatasetType, AssociationInfo +from ProvenaInterfaces.RegistryAPI import * +from ProvenaInterfaces.ProvenanceAPI import * +from ProvenaInterfaces.ProvenanceModels import * import asyncio from provenaclient.auth.manager import Log from typing import List @@ -180,6 +180,8 @@ async def main() -> None: # res = await client.prov_api.admin.store_multiple_records(registry_record=list_of_model_runs) + """ + last: str = "" async for ds in client.datastore.for_all_datasets( list_dataset_request=NoFilterSubtypeListRequest( @@ -216,4 +218,30 @@ def random_num() -> int: return random.randint(100, 1000) print_list=True ) + """ + + general_list_request = GeneralListRequest( + filter_by=None, + sort_by=None, + pagination_key=None + ) + + response = await client.registry.model.list_items(list_items_payload=general_list_request) + print(response) + + + print(await client.registry.model.get_auth_configuration(id = "10378.1/1875946")) # Existing Model in DEV + + model_create_request = ModelDomainInfo( + display_name="Parth testing", + user_metadata=None, + name= "Parth adchoc model", + description="Parth testing adhoc model", + documentation_url= "https://example.com.au", #type:ignore + source_url= "https://example.com.au" #type:ignore + ) + + # res_two = await client.registry.model.create_item(create_item_request=model_create_request) - Disabled to avoid spamming create models. + #print(res_two) + asyncio.run(main()) diff --git a/tests/integration_helpers.py b/tests/integration_helpers.py deleted file mode 100644 index cc2bb3b..0000000 --- a/tests/integration_helpers.py +++ /dev/null @@ -1,134 +0,0 @@ - -from datetime import date -from ProvenaInterfaces.RegistryModels import CollectionFormat, CollectionFormatAssociations, CollectionFormatApprovals, CollectionFormatDatasetInfo, OptionallyRequiredCheck, AccessInfo -from ProvenaInterfaces.RegistryAPI import * - -from provenaclient.utils.registry_endpoints import * -from provenaclient.modules import Registry - -valid_collection_format_1 = CollectionFormat( - associations=CollectionFormatAssociations( - organisation_id="10378.1/1893860", - data_custodian_id="10378.1/1893843", - point_of_contact="contact1@example.com" - ), - approvals=CollectionFormatApprovals( - ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=True), - ethics_access=DatasetEthicsAccessCheck(relevant=True, obtained=True), - indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=False), - export_controls=ExportControls(relevant=True, obtained=True) - ), - dataset_info=CollectionFormatDatasetInfo( - name="Integration Testing DiD I make it 1", - description="Integration test dataset variation 1", - access_info=AccessInfo(reposited=True, uri=None, description=None), #type:ignore - publisher_id="10378.1/1893860", - published_date=date(2024, 6, 1), - license="https://opensource.org/licenses/Apache-2.0", # type:ignore - created_date=date(2024, 6, 1), - purpose="Testing variation 1", - rights_holder="Rights Holder 1", - usage_limitations="Limitations 1", - preferred_citation="Citation 1", - formats=["JSON", "YAML"], - keywords=["integration", "test", "variation1"], - user_metadata={"author": "Tester Variation 1"}, - version=None - ) -) - -valid_collection_format_2 = CollectionFormat( - associations=CollectionFormatAssociations( - organisation_id="10378.1/1893860", - data_custodian_id="10378.1/1893843", - point_of_contact="contact2@example.com" - ), - approvals=CollectionFormatApprovals( - ethics_registration=DatasetEthicsRegistrationCheck(relevant=False, obtained=False), - ethics_access=DatasetEthicsAccessCheck(relevant=False, obtained=False), - indigenous_knowledge=IndigenousKnowledgeCheck(relevant=True, obtained=True), - export_controls=ExportControls(relevant=False, obtained=False) - ), - dataset_info=CollectionFormatDatasetInfo( - name="Dataset Variation 2", - description="Integration test dataset variation 2", - access_info=AccessInfo(reposited=False, uri="https://example.com.au", description="Example Integration Test"), #type:ignore - publisher_id="10378.1/1893860", - published_date=date(2024, 6, 2), - license="https://opensource.org/licenses/MIT", # type:ignore - created_date=date(2024, 6, 2), - purpose="Testing variation 2", - rights_holder="Rights Holder 2", - usage_limitations="No limitations", - preferred_citation="Citation 2", - formats=["CSV", "XML"], - keywords=["integration", "test", "variation2"], - user_metadata={"author": "Tester Variation 2"}, - version=None - ) -) - - -valid_collection_format_3 = CollectionFormat( - associations=CollectionFormatAssociations( - organisation_id="10378.1/1893860", - data_custodian_id="10378.1/1893843", - point_of_contact="contact3@example.com" - ), - approvals=CollectionFormatApprovals( - ethics_registration=DatasetEthicsRegistrationCheck(relevant=True, obtained=True), - ethics_access=DatasetEthicsAccessCheck(relevant=False, obtained=False), - indigenous_knowledge=IndigenousKnowledgeCheck(relevant=False, obtained=False), - export_controls=ExportControls(relevant=True, obtained=True) - ), - dataset_info=CollectionFormatDatasetInfo( - name="Dataset Variation 3", - description="Integration test dataset variation 3", - access_info=AccessInfo(reposited=True, uri=None, description=None), #type:ignore - publisher_id="10378.1/1893860", - published_date=date(2024, 6, 3), - license="https://opensource.org/licenses/GPL-3.0", # type:ignore - created_date=date(2024, 6, 3), - purpose="Testing variation 3", - rights_holder="Rights Holder 3", - usage_limitations="No restrictions", - preferred_citation="Citation 3", - formats=["PDF", "DOCX"], - keywords=["integration", "test", "variation3"], - user_metadata={"author": "Tester Variation 3"}, - version=None - ) -) - - -""" - -#def get_item_subtype_route_params(item_subtype: ItemSubType) -> RouteParameters: - - Given an item subtype, will source a its RouteParmeters - Parameters - ---------- - item_subtype : ItemSubType - The desired Item subtype to source route parameters for - Returns - ------- - RouteParameters - the routeparametrs for the desired item subtype - for item_route_params in route_params: - if item_route_params.subtype == item_subtype: - return item_route_params - - for item_route_params in non_test_route_params: - if item_route_params.subtype == item_subtype: - return item_route_params - - raise Exception( - f"Was not able to source route parameters for desired item_subtype = {item_subtype}") - - - -def get_item_subtype_domain_info_example(item_subtype: ItemSubType) -> DomainInfoBase: - # may require re parsing of results with correct type outside of this to obtain full access to fields. - return get_item_subtype_route_params(item_subtype=item_subtype).model_examples.domain_info[0] - -""" diff --git a/tests/test_integration.py b/tests/test_integration.py deleted file mode 100644 index 6a1f225..0000000 --- a/tests/test_integration.py +++ /dev/null @@ -1,274 +0,0 @@ -''' -Created Date: Wednesday June 26th 2024 +0000 -Author: Parth Kuulkarni ------ -Last Modified: Wednesday June 26th 2024 3:16:19 PM +0000 -Modified By: Parth Kulkarni ------ -Description: TODO ------ -HISTORY: -Date By Comments ----------- --- --------------------------------------------------------- -''' - -from typing import Any, AsyncGenerator, List, cast -import pytest -import pytest_asyncio -import httpx - -from provenaclient.auth import DeviceFlow -from provenaclient.modules.provena_client import ProvenaClient -from provenaclient.modules.registry import Registry -from provenaclient.utils.config import Config - -from ProvenaInterfaces.RegistryModels import * -from ProvenaInterfaces.RegistryAPI import * -from ProvenaInterfaces.AsyncJobModels import RegistryRegisterCreateActivityResult - -from integration_helpers import valid_collection_format_1, valid_collection_format_2, valid_collection_format_3 -from provenaclient.utils.exceptions import BadRequestException - -"""Pre-requiests before running unit tests: - - 1. You will need to setup token flow to be able to run these tests. - For now I will use my tokens through device flow. - 2. Creating various helper functions. - -""" - - -"""Registering and Finding Dataset""" - -@pytest.fixture -def auth_manager() -> DeviceFlow: - - config = Config( - domain="dev.rrap-is.com", - realm_name="rrap" - ) - - return DeviceFlow(config=config, client_id="client-tools") - -@pytest.fixture -def client(auth_manager: DeviceFlow) -> ProvenaClient: - - config = Config( - domain="dev.rrap-is.com", - realm_name="rrap" - ) - - return ProvenaClient(config=config, auth=auth_manager) - - - -async def _cleanup(client: ProvenaClient, list_of_handles: List[Tuple[ItemSubType, IdentifiedResource]]) -> None: - for item_sub_type, handle in list_of_handles: - delete_status_response = await client.registry.admin.delete(id=handle, item_subtype=item_sub_type) - assert delete_status_response.status.success, f"Delete request has failed with details {delete_status_response.status.details}." - - -async def health_check_of_all_apis(client: ProvenaClient) -> None: - - health_check_successful_message = "Health check successful." - - auth_api = await client.auth_api.get_health_check() - assert auth_api.message == health_check_successful_message - - datastore = await client.datastore.get_health_check() - assert datastore.message == health_check_successful_message - - prov = await client.prov_api.get_health_check() - assert prov.message == health_check_successful_message - - registry = await client.registry.get_health_check() - assert registry.message == health_check_successful_message - - job_api = await client.job_api.get_health_check() - assert job_api.message == health_check_successful_message - - -"""Datastore""" - -@pytest.mark.asyncio -async def test_invalid_handle_fetch_dataset(client: ProvenaClient) -> None: - - invalid_dataset_handle = "1234567890123" - - with pytest.raises(BadRequestException): - await client.datastore.fetch_dataset(id = invalid_dataset_handle) - -@pytest.mark.asyncio -async def test_register_dataset(client: ProvenaClient) -> None: - - cleanup_items: List[Tuple[ItemSubType, IdentifiedResource]] - - """ - 1. Need to find the dataset domain info, to get a dummy dataset - - """ - - valid_collection_formats: List[CollectionFormat] = [ - valid_collection_format_1, - valid_collection_format_2 - ] - - for valid_cf in valid_collection_formats: - mint_response = await client.datastore.mint_dataset(dataset_mint_info=valid_cf) - - assert mint_response.status.success, "Reported failure when minting dataset" - assert mint_response.handle, "Mint response does not contain a handle" - cleanup_items.append((ItemSubType.DATASET, mint_response.handle)) - - - # Fetch dataset by created handle_id - dataset_fetch_response = await client.datastore.fetch_dataset(mint_response.handle) - dataset_fetch_item = dataset_fetch_response.item - - assert dataset_fetch_response.status.success, f"Reported failure when fetching dataset with id {mint_response.handle}" - assert dataset_fetch_item is not None, "Fetched Dataset is null/none" - assert dataset_fetch_item.id == mint_response.handle - - """So everytime some entity is registred for the first time, by default a create activity is created - which is launched through the job-api. - - 1. We will take the create_activity_session_id, and keep polling on it to see if its completed. - - This is currently TODO because registry fetch across all aspects needs to be completed. - - """ - - # Ensure the workflow links were updated - assert dataset_fetch_item.workflow_links - assert dataset_fetch_item.workflow_links.create_activity_workflow_id - - assert mint_response.register_create_activity_session_id - - create_activity_response = await client.job_api.await_successful_job_completion( - session_id=mint_response.register_create_activity_session_id - ) - - # Now we have to assert if the id exists - - assert create_activity_response.result is not None - parsed_result = RegistryRegisterCreateActivityResult.parse_obj( - create_activity_response.result) - - lodge_session_id = parsed_result.lodge_session_id - creation_activity_id = parsed_result.creation_activity_id - - # Clean up dataset Create side effect - cleanup_items.append( - (ItemSubType.CREATE, creation_activity_id)) - - # Wait for next step of lifecycle - step 2 - # no meaningful response from this - just check success - await client.job_api.await_successful_job_completion( - session_id=lodge_session_id - ) - - # - check the Create activity was produced and is accurate - fetched_create_activity_response = await client.registry.create_activity.fetch( - id = creation_activity_id - ) - - assert fetched_create_activity_response.item - assert fetched_create_activity_response.item.id == dataset_fetch_item - - await _cleanup(client = client, list_of_handles=cleanup_items) - - -"""Listing items that is present.""" - -@pytest.mark.asyncio -async def list_all_datasets(client: ProvenaClient) -> None: - - datasets = await client.datastore.list_all_datasets() - assert datasets is not None - assert len(datasets) > 0 - - -"""Search-API related tests and finding newly related items.""" - - -@pytest.mark.asyncio -async def test_searching_items_in_registry(client: ProvenaClient) -> None: - - valid_collection_formats: List[CollectionFormat] = [ - valid_collection_format_1 - ] - - cleanup_items: List[Tuple[ItemSubType, IdentifiedResource]] = [] - - dataset_handles = [] - for valid_cf in valid_collection_formats: - mint_response = await client.datastore.mint_dataset(dataset_mint_info=valid_cf) - - assert mint_response.status.success, "Reported failure when minting dataset" - assert mint_response.handle, "Mint response does not contain a handle" - cleanup_items.append((ItemSubType.DATASET, mint_response.handle)) - dataset_handles.append(mint_response.handle) - - # Fetch dataset by created handle_id - dataset_fetch_response = await client.datastore.fetch_dataset(mint_response.handle) - dataset_fetch_item = dataset_fetch_response.item - - assert dataset_fetch_response.status.success, f"Reported failure when fetching dataset with id {mint_response.handle}" - assert dataset_fetch_item is not None, "Fetched Dataset is null/none" - assert dataset_fetch_item.id == mint_response.handle - - # Ensure the workflow links were updated - assert dataset_fetch_item.workflow_links - assert dataset_fetch_item.workflow_links.create_activity_workflow_id - - assert mint_response.register_create_activity_session_id - - create_activity_response = await client.job_api.await_successful_job_completion( - session_id=mint_response.register_create_activity_session_id - ) - - # Now we have to assert if the id exists - - assert create_activity_response.result is not None - parsed_result = RegistryRegisterCreateActivityResult.parse_obj( - create_activity_response.result) - - lodge_session_id = parsed_result.lodge_session_id - creation_activity_id = parsed_result.creation_activity_id - - # Clean up dataset Create side effect - cleanup_items.append( - (ItemSubType.CREATE, creation_activity_id)) - - # Wait for next step of lifecycle - step 2 - # no meaningful response from this - just check success - await client.job_api.await_successful_job_completion( - session_id=lodge_session_id - ) - - # - check the Create activity was produced and is accurate - fetched_create_activity_response = await client.registry.create_activity.fetch( - id = creation_activity_id - ) - - assert fetched_create_activity_response.item - assert fetched_create_activity_response.item.id == dataset_fetch_item - - # Perform search using the dataset handles - for dataset_handle in dataset_handles: - search_response = await client.search.search_registry(query=dataset_handle, subtype_filter=None, limit = None) - - assert search_response.status.success, f"Search failed for dataset handle {dataset_handle}" - assert search_response.results - assert dataset_handle in search_response.results - - await _cleanup(client = client, list_of_handles=cleanup_items) - - - -"""Querying Provenance""" - - - - - From 749293799b442b07fadbb29724453b2d3535507b Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Fri, 28 Jun 2024 04:12:54 +0000 Subject: [PATCH 6/7] Updated according to pull request comments. --- src/provenaclient/clients/registry_client.py | 35 ++--- src/provenaclient/modules/registry.py | 128 ++++++++++--------- src/provenaclient/utils/helpers.py | 31 ++++- tests/adhoc.py | 6 +- 4 files changed, 111 insertions(+), 89 deletions(-) diff --git a/src/provenaclient/clients/registry_client.py b/src/provenaclient/clients/registry_client.py index 171725a..7502ee8 100644 --- a/src/provenaclient/clients/registry_client.py +++ b/src/provenaclient/clients/registry_client.py @@ -126,7 +126,7 @@ async def restore_items_from_dynamo_table(self, restore_request: RegistryRestore RegistryImportResponse The response containing the result of the restore operation. """ - endpoint = self._build_endpoint(RegistryAdminEndpoints.POST_ADMIN_IMPORT) + endpoint = self._build_endpoint(RegistryAdminEndpoints.POST_ADMIN_RESTORE_FROM_TABLE) return await parsed_post_request_with_status( client=self, @@ -435,7 +435,7 @@ async def list_items(self, list_items_payload: GeneralListRequest, item_subtype: url=endpoint ) - async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + async def seed_item(self, item_subtype: ItemSubType, seed_model_response: Type[BaseModelType]) -> BaseModelType: """ Seeds an item in the registry. @@ -443,7 +443,7 @@ async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type ---------- item_subtype : ItemSubType The subtype of the item to seed. - update_model_response : Type[BaseModelType] + seed_model_response : Type[BaseModelType] The response model to parse. Returns @@ -462,7 +462,7 @@ async def seed_item(self, item_subtype: ItemSubType, update_model_response: Type params=None, json_body=None, error_message=f"Failed to seed items for {item_subtype}", - model=update_model_response, + model=seed_model_response, url=endpoint ) @@ -497,7 +497,7 @@ async def revert_item(self, revert_request: ItemRevertRequest, item_subtype: Ite url=endpoint ) - async def create_item(self, create_item_request: DomainInfoBase, item_subtype: ItemSubType, update_model_response: Type[BaseModelType]) -> BaseModelType: + async def create_item(self, create_item_request: DomainInfoBase, item_subtype: ItemSubType, create_response_model: Type[BaseModelType]) -> BaseModelType: """ Creates an item in the registry. @@ -507,7 +507,7 @@ async def create_item(self, create_item_request: DomainInfoBase, item_subtype: I The domain information required to create the item. item_subtype : ItemSubType The subtype of the item to create. - update_model_response : Type[BaseModelType] + create_response_model : Type[BaseModelType] The response model to parse. Returns @@ -526,7 +526,7 @@ async def create_item(self, create_item_request: DomainInfoBase, item_subtype: I params=None, json_body=py_to_dict(create_item_request), error_message=f"Failed to create items for {item_subtype}", - model=update_model_response, + model=create_response_model, url=endpoint ) @@ -862,23 +862,4 @@ async def version(self, version_request: VersionRequest, item_subtype: ItemSubTy error_message=f"Failed to complete versioning for subtype {item_subtype}", model=VersionResponse, url=endpoint - ) - - - - - - - - - - - - - - - - - - - \ No newline at end of file + ) \ No newline at end of file diff --git a/src/provenaclient/modules/registry.py b/src/provenaclient/modules/registry.py index de68b7f..92f1e7b 100644 --- a/src/provenaclient/modules/registry.py +++ b/src/provenaclient/modules/registry.py @@ -24,7 +24,7 @@ from ProvenaInterfaces.RegistryModels import * from ProvenaInterfaces.RegistryAPI import * from typing import Optional -from provenaclient.utils.helpers import read_file_helper, write_file_helper, get_and_validate_file_path +from provenaclient.utils.helpers import convert_to_item_subtype, write_file_helper, get_and_validate_file_path @@ -143,7 +143,7 @@ async def generate_config_file(self, required_only: bool = True, file_path: Opti return config_text - async def delete(self, id: str, item_subtype: ItemSubType) -> StatusResponse: + async def delete(self, id: str) -> StatusResponse: """Admin only endpoint for deleting item from registry. USE CAREFULLY! Parameters @@ -159,6 +159,14 @@ async def delete(self, id: str, item_subtype: ItemSubType) -> StatusResponse: Response indicating the success/failure of your request. """ + fetch_item = await self._registry_client.general.general_fetch_item(id=id) + + if fetch_item.item: + item_subtype_str: Optional[str] = fetch_item.item.get("item_subtype") + item_subtype = convert_to_item_subtype(item_subtype_str) + else: + raise ValueError("Item not found") + return await self._registry_client.admin.delete_item( id = id, item_subtype=item_subtype @@ -451,7 +459,7 @@ async def seed_item(self) -> OrganisationSeedResponse: """ return await self._registry_client.seed_item( item_subtype=self.item_subtype, - update_model_response=OrganisationSeedResponse + seed_model_response=OrganisationSeedResponse ) async def create_item(self, create_item_request: OrganisationDomainInfo) -> OrganisationCreateResponse: @@ -470,7 +478,7 @@ async def create_item(self, create_item_request: OrganisationDomainInfo) -> Orga return await self._registry_client.create_item( create_item_request=create_item_request, item_subtype=self.item_subtype, - update_model_response=OrganisationCreateResponse + create_response_model=OrganisationCreateResponse ) async def validate_item(self, validate_request: OrganisationDomainInfo) -> StatusResponse: @@ -523,7 +531,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> PersonFet """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.PERSON, + item_subtype=self.item_subtype, fetch_response_model=PersonFetchResponse, seed_allowed=seed_allowed ) @@ -542,7 +550,7 @@ async def update(self, id: str, domain_info: PersonDomainInfo, reason: Optional[ """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.PERSON, + item_subtype=self.item_subtype, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, @@ -560,7 +568,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> PersonList return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.PERSON, + item_subtype=self.item_subtype, update_model_response=PersonListResponse ) @@ -574,8 +582,8 @@ async def seed_item(self) -> PersonSeedResponse: """ return await self._registry_client.seed_item( - item_subtype=ItemSubType.PERSON, - update_model_response=PersonSeedResponse + item_subtype=self.item_subtype, + seed_model_response=PersonSeedResponse ) async def create_item(self, create_item_request: PersonDomainInfo) -> PersonCreateResponse: @@ -594,8 +602,8 @@ async def create_item(self, create_item_request: PersonDomainInfo) -> PersonCrea return await self._registry_client.create_item( create_item_request=create_item_request, - item_subtype=ItemSubType.PERSON, - update_model_response=PersonCreateResponse + item_subtype=self.item_subtype, + create_response_model=PersonCreateResponse ) async def validate_item(self, validate_request: PersonDomainInfo) -> StatusResponse: @@ -614,7 +622,7 @@ async def validate_item(self, validate_request: PersonDomainInfo) -> StatusRespo return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.PERSON + item_subtype=self.item_subtype ) @@ -648,7 +656,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> CreateFet """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.CREATE, + item_subtype=self.item_subtype, fetch_response_model=CreateFetchResponse, seed_allowed=seed_allowed ) @@ -668,7 +676,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> CreateList """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.CREATE, + item_subtype=self.item_subtype, update_model_response=CreateListResponse ) @@ -688,7 +696,7 @@ async def validate_item(self, validate_request: CreateDomainInfo) -> StatusRespo return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.CREATE + item_subtype=self.item_subtype ) @@ -723,7 +731,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> VersionFe """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.VERSION, + item_subtype=self.item_subtype, fetch_response_model=VersionFetchResponse, seed_allowed=seed_allowed ) @@ -743,7 +751,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> VersionLis """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.VERSION, + item_subtype=self.item_subtype, update_model_response=VersionListResponse ) @@ -763,7 +771,7 @@ async def validate_item(self, validate_request: VersionDomainInfo) -> StatusResp return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.VERSION + item_subtype=self.item_subtype ) @@ -797,7 +805,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunF """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.MODEL_RUN, + item_subtype=self.item_subtype, fetch_response_model=ModelRunFetchResponse, seed_allowed=seed_allowed ) @@ -817,7 +825,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunLi """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.MODEL_RUN, + item_subtype=self.item_subtype, update_model_response=ModelRunListResponse ) @@ -837,7 +845,7 @@ async def validate_item(self, validate_request: ModelRunDomainInfo) -> StatusRes return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.MODEL_RUN + item_subtype=self.item_subtype ) @@ -873,7 +881,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelFetc """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.MODEL, + item_subtype=self.item_subtype, fetch_response_model=ModelFetchResponse, seed_allowed=seed_allowed ) @@ -892,7 +900,7 @@ async def update(self, id: str, domain_info: ModelDomainInfo, reason: Optional[s """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.MODEL, + item_subtype=self.item_subtype, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, @@ -910,7 +918,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> ModelListR return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.MODEL, + item_subtype=self.item_subtype, update_model_response=ModelListResponse ) @@ -924,8 +932,8 @@ async def seed_item(self) -> ModelSeedResponse: """ return await self._registry_client.seed_item( - item_subtype=ItemSubType.MODEL, - update_model_response=ModelSeedResponse + item_subtype=self.item_subtype, + seed_model_response=ModelSeedResponse ) @@ -945,8 +953,8 @@ async def create_item(self, create_item_request: ModelDomainInfo) -> ModelCreate return await self._registry_client.create_item( create_item_request=create_item_request, - item_subtype=ItemSubType.MODEL, - update_model_response=ModelCreateResponse + item_subtype=self.item_subtype, + create_response_model=ModelCreateResponse ) async def validate_item(self, validate_request: ModelDomainInfo) -> StatusResponse: @@ -965,7 +973,7 @@ async def validate_item(self, validate_request: ModelDomainInfo) -> StatusRespon return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.MODEL + item_subtype=self.item_subtype ) @@ -985,7 +993,7 @@ async def version_item(self, version_request: VersionRequest) -> VersionResponse return await self._registry_client.version( version_request=version_request, - item_subtype=ItemSubType.MODEL + item_subtype=self.item_subtype ) class ModelRunWorkFlowClient(RegistryBaseClass): @@ -1004,7 +1012,7 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC instance. """ - super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE) + super().__init__(auth=auth, config=config, registry_client=registry_client, item_subtype=ItemSubType.WORKFLOW_TEMPLATE) async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunWorkflowTemplateFetchResponse: """ @@ -1019,7 +1027,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> ModelRunW """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + item_subtype=self.item_subtype, fetch_response_model=ModelRunWorkflowTemplateFetchResponse, seed_allowed=seed_allowed ) @@ -1038,7 +1046,7 @@ async def update(self, id: str, domain_info: ModelRunWorkflowTemplateDomainInfo, """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + item_subtype=self.item_subtype, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, @@ -1056,7 +1064,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> ModelRunWo return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, + item_subtype=self.item_subtype, update_model_response=ModelRunWorkflowTemplateListResponse ) @@ -1070,8 +1078,8 @@ async def seed_item(self) -> ModelRunWorkflowTemplateSeedResponse: """ return await self._registry_client.seed_item( - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - update_model_response=ModelRunWorkflowTemplateSeedResponse + item_subtype=self.item_subtype, + seed_model_response=ModelRunWorkflowTemplateSeedResponse ) @@ -1091,8 +1099,8 @@ async def create_item(self, create_item_request: ModelRunWorkflowTemplateDomainI return await self._registry_client.create_item( create_item_request=create_item_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE, - update_model_response=ModelRunWorkflowTemplateCreateResponse + item_subtype=self.item_subtype, + create_response_model=ModelRunWorkflowTemplateCreateResponse ) async def validate_item(self, validate_request: ModelRunWorkflowTemplateDomainInfo) -> StatusResponse: @@ -1111,7 +1119,7 @@ async def validate_item(self, validate_request: ModelRunWorkflowTemplateDomainIn return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + item_subtype=self.item_subtype ) async def version_item(self, version_request: VersionRequest) -> VersionResponse: @@ -1130,7 +1138,7 @@ async def version_item(self, version_request: VersionRequest) -> VersionResponse return await self._registry_client.version( version_request=version_request, - item_subtype=ItemSubType.MODEL_RUN_WORKFLOW_TEMPLATE + item_subtype=self.item_subtype ) @@ -1164,7 +1172,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetTe """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE, + item_subtype=self.item_subtype, fetch_response_model=DatasetTemplateFetchResponse, seed_allowed=seed_allowed ) @@ -1183,7 +1191,7 @@ async def update(self, id: str, domain_info: DatasetTemplateDomainInfo, reason: """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.DATASET_TEMPLATE, + item_subtype=self.item_subtype, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, @@ -1201,7 +1209,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetTem """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.DATASET_TEMPLATE, + item_subtype=self.item_subtype, update_model_response=DatasetTemplateListResponse ) @@ -1214,8 +1222,8 @@ async def seed_item(self) -> DatasetTemplateSeedResponse: DatasetTemplateSeedResponse: The seed response """ return await self._registry_client.seed_item( - item_subtype=ItemSubType.DATASET_TEMPLATE, - update_model_response=DatasetTemplateSeedResponse + item_subtype=self.item_subtype, + seed_model_response=DatasetTemplateSeedResponse ) async def create_item(self, create_item_request: DatasetTemplateDomainInfo) -> DatasetTemplateCreateResponse: @@ -1233,8 +1241,8 @@ async def create_item(self, create_item_request: DatasetTemplateDomainInfo) -> D """ return await self._registry_client.create_item( create_item_request=create_item_request, - item_subtype=ItemSubType.DATASET_TEMPLATE, - update_model_response=DatasetTemplateCreateResponse + item_subtype=self.item_subtype, + create_response_model=DatasetTemplateCreateResponse ) async def validate_item(self, validate_request: DatasetTemplateDomainInfo) -> StatusResponse: @@ -1253,7 +1261,7 @@ async def validate_item(self, validate_request: DatasetTemplateDomainInfo) -> St return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.DATASET_TEMPLATE + item_subtype=self.item_subtype ) async def version_item(self, version_request: VersionRequest) -> VersionResponse: @@ -1271,7 +1279,7 @@ async def version_item(self, version_request: VersionRequest) -> VersionResponse """ return await self._registry_client.version( version_request=version_request, - item_subtype=ItemSubType.DATASET_TEMPLATE + item_subtype=self.item_subtype ) @@ -1305,7 +1313,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> DatasetFe """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.DATASET, + item_subtype=self.item_subtype, fetch_response_model=DatasetFetchResponse, seed_allowed=seed_allowed ) @@ -1325,7 +1333,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> DatasetLis """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.DATASET, + item_subtype=self.item_subtype, update_model_response=DatasetListResponse ) @@ -1346,7 +1354,7 @@ async def validate_item(self, validate_request: DatasetDomainInfo) -> StatusResp return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.DATASET + item_subtype=self.item_subtype ) @@ -1380,7 +1388,7 @@ async def fetch(self, id: str, seed_allowed: Optional[bool] = None) -> StudyFetc """ return await self._registry_client.fetch_item( id=id, - item_subtype=ItemSubType.STUDY, + item_subtype=self.item_subtype, fetch_response_model=StudyFetchResponse, seed_allowed=seed_allowed ) @@ -1400,7 +1408,7 @@ async def list_items(self, list_items_payload: GeneralListRequest) -> StudyListR """ return await self._registry_client.list_items( list_items_payload=list_items_payload, - item_subtype=ItemSubType.STUDY, + item_subtype=self.item_subtype, update_model_response=StudyListResponse ) @@ -1413,8 +1421,8 @@ async def seed_item(self) -> StudySeedResponse: StudySeedResponse: The seed response """ return await self._registry_client.seed_item( - item_subtype=ItemSubType.STUDY, - update_model_response=StudySeedResponse + item_subtype=self.item_subtype, + seed_model_response=StudySeedResponse ) async def update(self, id: str, domain_info: StudyDomainInfo, reason: Optional[str]) -> StatusResponse: @@ -1436,7 +1444,7 @@ async def update(self, id: str, domain_info: StudyDomainInfo, reason: Optional[s """ return await self._registry_client.update_item( id=id, - item_subtype=ItemSubType.STUDY, + item_subtype=self.item_subtype, domain_info=domain_info, reason=reason, update_response_model=StatusResponse, @@ -1457,8 +1465,8 @@ async def create_item(self, create_item_request: StudyDomainInfo) -> StudyCreate """ return await self._registry_client.create_item( create_item_request=create_item_request, - item_subtype=ItemSubType.STUDY, - update_model_response=StudyCreateResponse + item_subtype=self.item_subtype, + create_response_model=StudyCreateResponse ) async def validate_item(self, validate_request: StudyDomainInfo) -> StatusResponse: @@ -1477,7 +1485,7 @@ async def validate_item(self, validate_request: StudyDomainInfo) -> StatusRespon return await self._registry_client.validate_item( validate_request=validate_request, - item_subtype=ItemSubType.STUDY + item_subtype=self.item_subtype ) diff --git a/src/provenaclient/utils/helpers.py b/src/provenaclient/utils/helpers.py index 0edf482..ef6bee2 100644 --- a/src/provenaclient/utils/helpers.py +++ b/src/provenaclient/utils/helpers.py @@ -19,7 +19,7 @@ from provenaclient.utils.exceptions import AuthException, HTTPValidationException, ServerException, BadRequestException, ValidationException, NotFoundException from provenaclient.utils.exceptions import BaseException from ProvenaInterfaces.SharedTypes import StatusResponse -from ProvenaInterfaces.RegistryModels import ItemBase +from ProvenaInterfaces.RegistryModels import ItemBase, ItemSubType import os # Type var to refer to base models @@ -34,6 +34,35 @@ ParamTypes = Union[str, int, bool] +def convert_to_item_subtype(item_subtype_str: Optional[str]) -> ItemSubType: + """Converts a string into ItemSubType supported enum type. + + Parameters + ---------- + item_subtype_str : Optional[str] + Optional string containing similar enum text. + + Returns + ------- + ItemSubType + Enum type of ItemSubType. + + Raises + ------ + ValueError + Item subtype field was not present. + ValueError + Item subtype cannot be converted to ENUM. + """ + + if item_subtype_str is None: + raise ValueError("Item subtype field not found!") + + try: + return ItemSubType[item_subtype_str.upper()] + except KeyError as e: + raise ValueError(f"Invalid item_subtype: {item_subtype_str}") from e + def get_and_validate_file_path(file_path: Optional[str], write_to_file: bool, default_file_name: str) -> Optional[str]: """Determine and validate the file path for writing a file. diff --git a/tests/adhoc.py b/tests/adhoc.py index 5f1bcf9..351b098 100644 --- a/tests/adhoc.py +++ b/tests/adhoc.py @@ -230,7 +230,11 @@ def random_num() -> int: return random.randint(100, 1000) print(response) - print(await client.registry.model.get_auth_configuration(id = "10378.1/1875946")) # Existing Model in DEV + #res = await client.registry.admin.delete(id="10378.1/1913346") + + #print(res) + + #print(await client.registry.model.get_auth_configuration(id = "10378.1/1875946")) # Existing Model in DEV model_create_request = ModelDomainInfo( display_name="Parth testing", From 484837c17d1eaf4a121a9c93a35eb0d372ad9e92 Mon Sep 17 00:00:00 2001 From: parth-kulkarni1 Date: Fri, 28 Jun 2024 04:32:35 +0000 Subject: [PATCH 7/7] Added delete method to each client as well. --- src/provenaclient/modules/registry.py | 42 ++++++++++++++++++++------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/provenaclient/modules/registry.py b/src/provenaclient/modules/registry.py index 92f1e7b..2884b88 100644 --- a/src/provenaclient/modules/registry.py +++ b/src/provenaclient/modules/registry.py @@ -143,15 +143,16 @@ async def generate_config_file(self, required_only: bool = True, file_path: Opti return config_text - async def delete(self, id: str) -> StatusResponse: + async def delete(self, id: str, item_subtype: Optional[ItemSubType] = None) -> StatusResponse: """Admin only endpoint for deleting item from registry. USE CAREFULLY! Parameters ---------- id : str ID of entity/item you want to delete. - item_subtype : ItemSubType + item_subtype : Optional[ItemSubType] Subtype of item you want to delete (E.g ORGANISATION, PERSON, CREATE) + If not provided, it will be fetched from the registry. Returns ------- @@ -159,14 +160,15 @@ async def delete(self, id: str) -> StatusResponse: Response indicating the success/failure of your request. """ - fetch_item = await self._registry_client.general.general_fetch_item(id=id) - - if fetch_item.item: - item_subtype_str: Optional[str] = fetch_item.item.get("item_subtype") - item_subtype = convert_to_item_subtype(item_subtype_str) - else: - raise ValueError("Item not found") - + if item_subtype is None: + fetch_item = await self._registry_client.general.general_fetch_item(id=id) + + if fetch_item.item: + item_subtype_str: Optional[str] = fetch_item.item.get("item_subtype") + item_subtype = convert_to_item_subtype(item_subtype_str) + else: + raise ValueError("Item not found") + return await self._registry_client.admin.delete_item( id = id, item_subtype=item_subtype @@ -194,6 +196,26 @@ def __init__(self, auth: AuthManager, config: Config, registry_client: RegistryC self._registry_client = registry_client self.item_subtype = item_subtype + + async def admin_delete(self, id: str) -> StatusResponse: + """Admin only endpoint for deleting item from registry. USE CAREFULLY! + + Parameters + ---------- + id : str + ID of entity/item you want to delete. + + Returns + ------- + StatusResponse + Response indicating the success/failure of your request. + """ + + return await self._registry_client.admin.delete_item( + id = id, + item_subtype=self.item_subtype + ) + async def revert_item(self, revert_request: ItemRevertRequest) -> ItemRevertResponse: """ Reverts an item in the registry based on item subtype.