diff --git a/README.md b/README.md index 53b0472..b6d314b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ This repository implements a minimal, Python-based MVP of GridVerse: a modular, - Core concepts: Objects, Morphisms, Functors - Lightweight Registry for contracts and adapters - Starter DER adapter and a small adapter marketplace scaffold +- Marketplace and Registry: lightweight in-process components for adapter discovery and contract validation. + - AdapterMarketplace (gridverse_open_low_code_platform_for_cro.marketplace) registers and lists adapters. + - ContractRegistry (gridverse_open_low_code_platform_for_cro.registry) validates and stores contract schemas. - End-to-end tests and packaging skeleton How to run diff --git a/gridverse_open_low_code_platform_for_cro/marketplace.py b/gridverse_open_low_code_platform_for_cro/marketplace.py new file mode 100644 index 0000000..54dfb6f --- /dev/null +++ b/gridverse_open_low_code_platform_for_cro/marketplace.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +from typing import Dict, List + +from .adapter import Adapter + + +class AdapterMarketplace: + """Minimal in-process marketplace for adapters. + + This lightweight scaffold allows registering adapters and querying them + by id. It is intentionally tiny to serve as a stepping stone toward a + fuller registry/marketplace without affecting the core MVP surface. + """ + + def __init__(self) -> None: + self._adapters: Dict[str, Adapter] = {} + + def register_adapter(self, adapter: Adapter) -> None: + if not isinstance(adapter, Adapter): # type: ignore[unreachable] + raise TypeError("adapter must be an instance of Adapter") + self._adapters[adapter.adapter_id] = adapter + + def list_adapters(self) -> List[str]: + return list(self._adapters.keys()) + + def get_adapter(self, adapter_id: str) -> Adapter: + return self._adapters[adapter_id] diff --git a/gridverse_open_low_code_platform_for_cro/marketplace/__init__.py b/gridverse_open_low_code_platform_for_cro/marketplace/__init__.py index c934244..d7340be 100644 --- a/gridverse_open_low_code_platform_for_cro/marketplace/__init__.py +++ b/gridverse_open_low_code_platform_for_cro/marketplace/__init__.py @@ -13,3 +13,22 @@ class Marketplace: def get_entry(self, adapter_id: str) -> Dict[str, Any]: return self.entries[adapter_id] + + +class AdapterMarketplace: + """Lightweight in-process adapter marketplace compatible with tests.""" + def __init__(self) -> None: + self._adapters: Dict[str, Any] = {} + + def register_adapter(self, adapter) -> None: + # Accept any object that provides an 'adapter_id' attribute + if not hasattr(adapter, "adapter_id"): + raise TypeError("adapter must expose an 'adapter_id' attribute") + self._adapters[adapter.adapter_id] = adapter + + def list_adapters(self) -> List[str]: # type: ignore[override] + from typing import List # local import to avoid top-level import in small file + return list(self._adapters.keys()) + + def get_adapter(self, adapter_id: str): # type: ignore[return-type] + return self._adapters[adapter_id] diff --git a/tests/test_marketplace.py b/tests/test_marketplace.py new file mode 100644 index 0000000..a1555c2 --- /dev/null +++ b/tests/test_marketplace.py @@ -0,0 +1,11 @@ +from gridverse_open_low_code_platform_for_cro.marketplace import AdapterMarketplace +from gridverse_open_low_code_platform_for_cro.adapters.starter_der_adapter import StarterDERAdapter + + +def test_marketplace_register_and_list_and_get(): + marketplace = AdapterMarketplace() + adapter = StarterDERAdapter() + marketplace.register_adapter(adapter) + assert marketplace.list_adapters() == [adapter.adapter_id] + retrieved = marketplace.get_adapter(adapter.adapter_id) + assert isinstance(retrieved, StarterDERAdapter)