diff --git a/api/specs/web-server/_auth_api_keys.py b/api/specs/web-server/_auth_api_keys.py index aa0a541a168f..664a5165977a 100644 --- a/api/specs/web-server/_auth_api_keys.py +++ b/api/specs/web-server/_auth_api_keys.py @@ -10,7 +10,9 @@ from models_library.rest_error import EnvelopedError from simcore_service_webserver._meta import API_VTAG from simcore_service_webserver.api_keys._controller_rest import ApiKeysPathParams -from simcore_service_webserver.api_keys._exceptions_handlers import _TO_HTTP_ERROR_MAP +from simcore_service_webserver.api_keys._controller_rest_exceptions import ( + _TO_HTTP_ERROR_MAP, +) router = APIRouter( prefix=f"/{API_VTAG}", diff --git a/api/specs/web-server/_catalog.py b/api/specs/web-server/_catalog.py index d861c44b0c6f..900a6018adf6 100644 --- a/api/specs/web-server/_catalog.py +++ b/api/specs/web-server/_catalog.py @@ -15,13 +15,13 @@ from models_library.generics import Envelope from models_library.rest_pagination import Page from simcore_service_webserver._meta import API_VTAG -from simcore_service_webserver.catalog._rest_controller import ( +from simcore_service_webserver.catalog._controller_rest_schemas import ( + FromServiceOutputQueryParams, ListServiceParams, + ServiceInputsPathParams, + ServiceOutputsPathParams, ServicePathParams, - _FromServiceOutputParams, - _ServiceInputsPathParams, - _ServiceOutputsPathParams, - _ToServiceInputsParams, + ToServiceInputsQueryParams, ) router = APIRouter( @@ -71,7 +71,7 @@ def list_service_inputs( response_model=Envelope[ServiceInputGet], ) def get_service_input( - _path: Annotated[_ServiceInputsPathParams, Depends()], + _path: Annotated[ServiceInputsPathParams, Depends()], ): ... @@ -81,7 +81,7 @@ def get_service_input( ) def get_compatible_inputs_given_source_output( _path: Annotated[ServicePathParams, Depends()], - _query: Annotated[_FromServiceOutputParams, Depends()], + _query: Annotated[FromServiceOutputQueryParams, Depends()], ): ... @@ -99,7 +99,7 @@ def list_service_outputs( response_model=Envelope[list[ServiceOutputGet]], ) def get_service_output( - _path: Annotated[_ServiceOutputsPathParams, Depends()], + _path: Annotated[ServiceOutputsPathParams, Depends()], ): ... @@ -109,7 +109,7 @@ def get_service_output( ) def get_compatible_outputs_given_target_input( _path: Annotated[ServicePathParams, Depends()], - _query: Annotated[_ToServiceInputsParams, Depends()], + _query: Annotated[ToServiceInputsQueryParams, Depends()], ): ... diff --git a/api/specs/web-server/_catalog_tags.py b/api/specs/web-server/_catalog_tags.py index bfecd6314fc6..9b66b92dfb23 100644 --- a/api/specs/web-server/_catalog_tags.py +++ b/api/specs/web-server/_catalog_tags.py @@ -10,7 +10,7 @@ from models_library.api_schemas_webserver.catalog import CatalogServiceGet from models_library.generics import Envelope from simcore_service_webserver._meta import API_VTAG -from simcore_service_webserver.catalog._rest_tags_controller import ( +from simcore_service_webserver.catalog._controller_rest_schemas import ( ServicePathParams, ServiceTagPathParams, ) diff --git a/packages/models-library/src/models_library/rest_pagination.py b/packages/models-library/src/models_library/rest_pagination.py index 5601a5968dab..0b7e68e52227 100644 --- a/packages/models-library/src/models_library/rest_pagination.py +++ b/packages/models-library/src/models_library/rest_pagination.py @@ -26,6 +26,8 @@ int, Field(ge=1, lt=MAXIMUM_NUMBER_OF_ITEMS_PER_PAGE) ] +PageOffsetInt: TypeAlias = NonNegativeInt + DEFAULT_NUMBER_OF_ITEMS_PER_PAGE: Final[PageLimitInt] = TypeAdapter( PageLimitInt ).validate_python(20) @@ -51,15 +53,19 @@ class CursorQueryParameters(RequestParameters): class PageQueryParameters(RequestParameters): """Use as pagination options in query parameters""" - limit: PageLimitInt = Field( - default=TypeAdapter(PageLimitInt).validate_python( - DEFAULT_NUMBER_OF_ITEMS_PER_PAGE + limit: Annotated[ + PageLimitInt, + Field( + default=TypeAdapter(PageLimitInt).validate_python( + DEFAULT_NUMBER_OF_ITEMS_PER_PAGE + ), + description="maximum number of items to return (pagination)", ), - description="maximum number of items to return (pagination)", - ) - offset: NonNegativeInt = Field( - default=0, description="index to the first item to return (pagination)" - ) + ] + offset: Annotated[ + PageOffsetInt, + Field(default=0, description="index to the first item to return (pagination)"), + ] class PageMetaInfoLimitOffset(BaseModel): @@ -120,8 +126,7 @@ class PageLinks( BeforeValidator(lambda x: str(TypeAdapter(AnyHttpUrl).validate_python(x))), ] ] -): - ... +): ... ItemT = TypeVar("ItemT") diff --git a/services/web/server/src/simcore_service_webserver/api_keys/_controller_rest.py b/services/web/server/src/simcore_service_webserver/api_keys/_controller_rest.py index 963b00bdf706..e85001b03a10 100644 --- a/services/web/server/src/simcore_service_webserver/api_keys/_controller_rest.py +++ b/services/web/server/src/simcore_service_webserver/api_keys/_controller_rest.py @@ -23,7 +23,7 @@ from ..security.decorators import permission_required from ..utils_aiohttp import envelope_json_response from . import _service -from ._exceptions_handlers import handle_plugin_requests_exceptions +from ._controller_rest_exceptions import handle_plugin_requests_exceptions from .models import ApiKey _logger = logging.getLogger(__name__) diff --git a/services/web/server/src/simcore_service_webserver/api_keys/_exceptions_handlers.py b/services/web/server/src/simcore_service_webserver/api_keys/_controller_rest_exceptions.py similarity index 100% rename from services/web/server/src/simcore_service_webserver/api_keys/_exceptions_handlers.py rename to services/web/server/src/simcore_service_webserver/api_keys/_controller_rest_exceptions.py diff --git a/services/web/server/src/simcore_service_webserver/catalog/_catalog_rest_client_service.py b/services/web/server/src/simcore_service_webserver/catalog/_catalog_rest_client_service.py index 58ee6a1f67bc..127cc1d53e50 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/_catalog_rest_client_service.py +++ b/services/web/server/src/simcore_service_webserver/catalog/_catalog_rest_client_service.py @@ -21,12 +21,11 @@ from servicelib.aiohttp import status from servicelib.aiohttp.client_session import get_client_session from servicelib.rest_constants import X_PRODUCT_NAME_HEADER -from settings_library.catalog import CatalogSettings from yarl import URL from .._meta import api_version_prefix from ._constants import MSG_CATALOG_SERVICE_NOT_FOUND, MSG_CATALOG_SERVICE_UNAVAILABLE -from .settings import get_plugin_settings +from .settings import CatalogSettings, get_plugin_settings _logger = logging.getLogger(__name__) diff --git a/services/web/server/src/simcore_service_webserver/catalog/_rest_controller.py b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py similarity index 84% rename from services/web/server/src/simcore_service_webserver/catalog/_rest_controller.py rename to services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py index 9a83748fd8cf..b4d14c41991e 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/_rest_controller.py +++ b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest.py @@ -14,18 +14,14 @@ from models_library.api_schemas_webserver.catalog import ( CatalogServiceGet, CatalogServiceUpdate, - ServiceInputKey, - ServiceOutputKey, ) from models_library.api_schemas_webserver.resource_usage import PricingPlanGet -from models_library.rest_pagination import Page, PageQueryParameters +from models_library.rest_pagination import Page from models_library.rest_pagination_utils import paginate_data -from models_library.services import ServiceKey, ServiceVersion from models_library.services_resources import ( ServiceResourcesDict, ServiceResourcesDictHelpers, ) -from pydantic import BaseModel, Field from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, @@ -39,14 +35,19 @@ from ..security.decorators import permission_required from ..utils_aiohttp import envelope_json_response from . import _catalog_rest_client_service, _service -from ._exceptions import ( +from ._controller_rest_exceptions import ( DefaultPricingUnitForServiceNotFoundError, handle_plugin_requests_exceptions, ) -from .controller_rest_schemas import ( +from ._controller_rest_schemas import ( CatalogRequestContext, + FromServiceOutputQueryParams, ListServiceParams, + ServiceInputsPathParams, + ServiceOutputsPathParams, ServicePathParams, + ServiceTagPathParams, + ToServiceInputsQueryParams, ) _logger = logging.getLogger(__name__) @@ -75,9 +76,8 @@ async def list_services_latest(request: Request): user_id=request_ctx.user_id, product_name=request_ctx.product_name, unit_registry=request_ctx.unit_registry, - page_params=PageQueryParameters.model_construct( - offset=query_params.offset, limit=query_params.limit - ), + offset=query_params.offset, + limit=query_params.limit, ) assert page_meta.limit == query_params.limit # nosec @@ -173,10 +173,6 @@ async def list_service_inputs(request: Request): ) -class _ServiceInputsPathParams(ServicePathParams): - input_key: ServiceInputKey - - @routes.get( f"{VTAG}/catalog/services/{{service_key}}/{{service_version}}/inputs/{{input_key}}", name="get_service_input", @@ -185,7 +181,7 @@ class _ServiceInputsPathParams(ServicePathParams): @permission_required("services.catalog.*") async def get_service_input(request: Request): ctx = CatalogRequestContext.create(request) - path_params = parse_request_path_parameters_as(_ServiceInputsPathParams, request) + path_params = parse_request_path_parameters_as(ServiceInputsPathParams, request) # Evaluate and return validated model response_model = await _service.get_service_input( @@ -201,12 +197,6 @@ async def get_service_input(request: Request): ) -class _FromServiceOutputParams(BaseModel): - from_service_key: ServiceKey = Field(..., alias="fromService") - from_service_version: ServiceVersion = Field(..., alias="fromVersion") - from_output_key: ServiceOutputKey = Field(..., alias="fromOutput") - - @routes.get( f"{VTAG}/catalog/services/{{service_key}}/{{service_version}}/inputs:match", name="get_compatible_inputs_given_source_output", @@ -216,8 +206,8 @@ class _FromServiceOutputParams(BaseModel): async def get_compatible_inputs_given_source_output(request: Request): ctx = CatalogRequestContext.create(request) path_params = parse_request_path_parameters_as(ServicePathParams, request) - query_params: _FromServiceOutputParams = parse_request_query_parameters_as( - _FromServiceOutputParams, request + query_params: FromServiceOutputQueryParams = parse_request_query_parameters_as( + FromServiceOutputQueryParams, request ) # Evaluate and return validated model @@ -256,10 +246,6 @@ async def list_service_outputs(request: Request): ) -class _ServiceOutputsPathParams(ServicePathParams): - output_key: ServiceOutputKey - - @routes.get( f"{VTAG}/catalog/services/{{service_key}}/{{service_version}}/outputs/{{output_key}}", name="get_service_output", @@ -268,7 +254,7 @@ class _ServiceOutputsPathParams(ServicePathParams): @permission_required("services.catalog.*") async def get_service_output(request: Request): ctx = CatalogRequestContext.create(request) - path_params = parse_request_path_parameters_as(_ServiceOutputsPathParams, request) + path_params = parse_request_path_parameters_as(ServiceOutputsPathParams, request) # Evaluate and return validated model response_model = await _service.get_service_output( @@ -284,12 +270,6 @@ async def get_service_output(request: Request): ) -class _ToServiceInputsParams(BaseModel): - to_service_key: ServiceKey = Field(..., alias="toService") - to_service_version: ServiceVersion = Field(..., alias="toVersion") - to_input_key: ServiceInputKey = Field(..., alias="toInput") - - @routes.get( f"{VTAG}/catalog/services/{{service_key}}/{{service_version}}/outputs:match", name="get_compatible_outputs_given_target_input", @@ -304,8 +284,8 @@ async def get_compatible_outputs_given_target_input(request: Request): """ ctx = CatalogRequestContext.create(request) path_params = parse_request_path_parameters_as(ServicePathParams, request) - query_params: _ToServiceInputsParams = parse_request_query_parameters_as( - _ToServiceInputsParams, request + query_params: ToServiceInputsQueryParams = parse_request_query_parameters_as( + ToServiceInputsQueryParams, request ) data = await _service.get_compatible_outputs_given_target_input( @@ -377,3 +357,43 @@ async def get_service_pricing_plan(request: Request): return envelope_json_response( PricingPlanGet.model_validate(pricing_plan.model_dump()) ) + + +@routes.get( + f"/{API_VTAG}/catalog/services/{{service_key}}/{{service_version}}/tags", + name="list_service_tags", +) +@login_required +@permission_required("service.tag.*") +async def list_service_tags(request: web.Request): + path_params = parse_request_path_parameters_as(ServicePathParams, request) + assert path_params # nosec + raise NotImplementedError + + +@routes.post( + f"/{API_VTAG}/catalog/services/{{service_key}}/{{service_version}}/tags/{{tag_id}}:add", + name="add_service_tag", +) +@login_required +@permission_required("service.tag.*") +async def add_service_tag(request: web.Request): + path_params = parse_request_path_parameters_as(ServiceTagPathParams, request) + assert path_params # nosec + + # responds with parent's resource to get the current state (as with patch/update) + raise NotImplementedError + + +@routes.post( + f"/{API_VTAG}/catalog/services/{{service_key}}/{{service_version}}/tags/{{tag_id}}:remove", + name="remove_service_tag", +) +@login_required +@permission_required("service.tag.*") +async def remove_service_tag(request: web.Request): + path_params = parse_request_path_parameters_as(ServiceTagPathParams, request) + assert path_params # nosec + + # responds with parent's resource to get the current state (as with patch/update) + raise NotImplementedError diff --git a/services/web/server/src/simcore_service_webserver/catalog/_exceptions.py b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest_exceptions.py similarity index 62% rename from services/web/server/src/simcore_service_webserver/catalog/_exceptions.py rename to services/web/server/src/simcore_service_webserver/catalog/_controller_rest_exceptions.py index 292bcb78d5e5..134ea554da52 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/_exceptions.py +++ b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest_exceptions.py @@ -6,7 +6,6 @@ CatalogItemNotFoundError, ) -from ..errors import WebServerBaseError from ..exception_handling import ( ExceptionToHttpErrorMap, HttpErrorInfo, @@ -14,29 +13,7 @@ to_exceptions_handlers_map, ) from ..resource_usage.errors import DefaultPricingPlanNotFoundError - - -class BaseCatalogError(WebServerBaseError): - msg_template = "Unexpected error occured in catalog submodule" - - def __init__(self, msg=None, **ctx): - super().__init__(**ctx) - if msg: - self.msg_template = msg - - def debug_message(self): - # Override in subclass - return f"{self.code}: {self}" - - -class DefaultPricingUnitForServiceNotFoundError(BaseCatalogError): - msg_template = "Default pricing unit not found for service key '{service_key}' and version '{service_version}'" - - def __init__(self, *, service_key: str, service_version: str, **ctxs): - super().__init__(**ctxs) - self.service_key = service_key - self.service_version = service_version - +from .errors import DefaultPricingUnitForServiceNotFoundError # mypy: disable-error-code=truthy-function assert CatalogForbiddenError # nosec diff --git a/services/web/server/src/simcore_service_webserver/catalog/controller_rest_schemas.py b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest_schemas.py similarity index 88% rename from services/web/server/src/simcore_service_webserver/catalog/controller_rest_schemas.py rename to services/web/server/src/simcore_service_webserver/catalog/_controller_rest_schemas.py index 9d594f8954aa..83c8dbe9fa4d 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/controller_rest_schemas.py +++ b/services/web/server/src/simcore_service_webserver/catalog/_controller_rest_schemas.py @@ -2,7 +2,7 @@ import urllib.parse from collections.abc import Callable from dataclasses import dataclass -from typing import Any, Final +from typing import Annotated, Any, Final from aiocache import cached # type: ignore[import-untyped] from aiohttp import web @@ -21,6 +21,7 @@ from pydantic import ( BaseModel, ConfigDict, + Field, field_validator, ) from servicelib.aiohttp.requests_validation import handle_validation_as_http_error @@ -180,7 +181,7 @@ class ServicePathParams(BaseModel): @field_validator("service_key", mode="before") @classmethod - def ensure_unquoted(cls, v): + def _ensure_unquoted(cls, v): # NOTE: this is needed as in pytest mode, the aiohttp server does not seem to unquote automatically if v is not None: return urllib.parse.unquote(v) @@ -192,3 +193,23 @@ class ListServiceParams(PageQueryParameters): ... class ServiceTagPathParams(ServicePathParams): tag_id: IdInt + + +class ServiceInputsPathParams(ServicePathParams): + input_key: ServiceInputKey + + +class FromServiceOutputQueryParams(BaseModel): + from_service_key: Annotated[ServiceKey, Field(alias="fromService")] + from_service_version: Annotated[ServiceVersion, Field(alias="fromVersion")] + from_output_key: Annotated[ServiceOutputKey, Field(alias="fromOutput")] + + +class ServiceOutputsPathParams(ServicePathParams): + output_key: ServiceOutputKey + + +class ToServiceInputsQueryParams(BaseModel): + to_service_key: Annotated[ServiceKey, Field(alias="toService")] + to_service_version: Annotated[ServiceVersion, Field(alias="toVersion")] + to_input_key: Annotated[ServiceInputKey, Field(alias="toInput")] diff --git a/services/web/server/src/simcore_service_webserver/catalog/_models.py b/services/web/server/src/simcore_service_webserver/catalog/_models.py new file mode 100644 index 000000000000..b589e629a9f5 --- /dev/null +++ b/services/web/server/src/simcore_service_webserver/catalog/_models.py @@ -0,0 +1 @@ +# NOTE: missing. @bisgaard-itis will follow up here diff --git a/services/web/server/src/simcore_service_webserver/catalog/_rest_tags_controller.py b/services/web/server/src/simcore_service_webserver/catalog/_rest_tags_controller.py deleted file mode 100644 index 199f8b4886fe..000000000000 --- a/services/web/server/src/simcore_service_webserver/catalog/_rest_tags_controller.py +++ /dev/null @@ -1,54 +0,0 @@ -import logging - -from aiohttp import web -from servicelib.aiohttp.requests_validation import parse_request_path_parameters_as - -from .._meta import API_VTAG -from ..login.decorators import login_required -from ..security.decorators import permission_required -from .controller_rest_schemas import ServicePathParams, ServiceTagPathParams - -_logger = logging.getLogger(__name__) - - -routes = web.RouteTableDef() - - -@routes.get( - f"/{API_VTAG}/catalog/services/{{service_key}}/{{service_version}}/tags", - name="list_service_tags", -) -@login_required -@permission_required("service.tag.*") -async def list_service_tags(request: web.Request): - path_params = parse_request_path_parameters_as(ServicePathParams, request) - assert path_params # nosec - raise NotImplementedError - - -@routes.post( - f"/{API_VTAG}/catalog/services/{{service_key}}/{{service_version}}/tags/{{tag_id}}:add", - name="add_service_tag", -) -@login_required -@permission_required("service.tag.*") -async def add_service_tag(request: web.Request): - path_params = parse_request_path_parameters_as(ServiceTagPathParams, request) - assert path_params # nosec - - # responds with parent's resource to get the current state (as with patch/update) - raise NotImplementedError - - -@routes.post( - f"/{API_VTAG}/catalog/services/{{service_key}}/{{service_version}}/tags/{{tag_id}}:remove", - name="remove_service_tag", -) -@login_required -@permission_required("service.tag.*") -async def remove_service_tag(request: web.Request): - path_params = parse_request_path_parameters_as(ServiceTagPathParams, request) - assert path_params # nosec - - # responds with parent's resource to get the current state (as with patch/update) - raise NotImplementedError diff --git a/services/web/server/src/simcore_service_webserver/catalog/_service.py b/services/web/server/src/simcore_service_webserver/catalog/_service.py index 823bf033b3a7..daa83c1e5d10 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/_service.py +++ b/services/web/server/src/simcore_service_webserver/catalog/_service.py @@ -11,7 +11,11 @@ ServiceOutputKey, ) from models_library.products import ProductName -from models_library.rest_pagination import PageMetaInfoLimitOffset, PageQueryParameters +from models_library.rest_pagination import ( + PageLimitInt, + PageMetaInfoLimitOffset, + PageOffsetInt, +) from models_library.services import ( ServiceInput, ServiceKey, @@ -28,12 +32,12 @@ from ..rabbitmq import get_rabbitmq_rpc_client from . import _catalog_rest_client_service -from ._units_service import can_connect, replace_service_input_outputs -from .controller_rest_schemas import ( +from ._controller_rest_schemas import ( CatalogRequestContext, ServiceInputGetFactory, ServiceOutputGetFactory, ) +from ._units_service import can_connect, replace_service_input_outputs _logger = logging.getLogger(__name__) @@ -61,16 +65,14 @@ async def _safe_replace_service_input_outputs( ) -# IMPLEMENTATION -------------------------------------------------------------------------------- - - async def list_latest_services( app: web.Application, *, user_id: UserID, product_name: ProductName, unit_registry: UnitRegistry, - page_params: PageQueryParameters, + limit: PageLimitInt, + offset: PageOffsetInt, ) -> tuple[list, PageMetaInfoLimitOffset]: # NOTE: will replace list_services @@ -78,8 +80,8 @@ async def list_latest_services( get_rabbitmq_rpc_client(app), product_name=product_name, user_id=user_id, - limit=page_params.limit, - offset=page_params.offset, + limit=limit, + offset=offset, ) page_data = jsonable_encoder(page.data, exclude_unset=True) diff --git a/services/web/server/src/simcore_service_webserver/catalog/_units_service.py b/services/web/server/src/simcore_service_webserver/catalog/_units_service.py index 9cb3c3269b04..0a0ddb641038 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/_units_service.py +++ b/services/web/server/src/simcore_service_webserver/catalog/_units_service.py @@ -3,7 +3,7 @@ from models_library.services import BaseServiceIOModel, ServiceInput, ServiceOutput from pint import PintError, UnitRegistry -from .controller_rest_schemas import ( +from ._controller_rest_schemas import ( ServiceInputGetFactory, ServiceOutputGetFactory, get_unit_name, diff --git a/services/web/server/src/simcore_service_webserver/catalog/catalog_service.py b/services/web/server/src/simcore_service_webserver/catalog/catalog_service.py index 33b92d864a38..d6e42b376dd5 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/catalog_service.py +++ b/services/web/server/src/simcore_service_webserver/catalog/catalog_service.py @@ -1,4 +1,4 @@ -from ._catalog_rest_client_service import ( # noqa +from ._catalog_rest_client_service import ( get_service, get_service_access_rights, get_service_resources, @@ -6,14 +6,15 @@ is_catalog_service_responsive, to_backend_service, ) -from ._service import batch_get_my_services # noqa +from ._service import batch_get_my_services __all__: tuple[str, ...] = ( - "is_catalog_service_responsive", - "to_backend_service", - "get_services_for_user_in_product", + "batch_get_my_services", "get_service", - "get_service_resources", "get_service_access_rights", - "batch_get_my_services", + "get_service_resources", + "get_services_for_user_in_product", + "is_catalog_service_responsive", + "to_backend_service", ) +# nopycln: file diff --git a/services/web/server/src/simcore_service_webserver/catalog/errors.py b/services/web/server/src/simcore_service_webserver/catalog/errors.py new file mode 100644 index 000000000000..23625d772b37 --- /dev/null +++ b/services/web/server/src/simcore_service_webserver/catalog/errors.py @@ -0,0 +1,25 @@ +"""Defines the different exceptions that may arise in the catalog subpackage""" + +from ..errors import WebServerBaseError + + +class BaseCatalogError(WebServerBaseError): + msg_template = "Unexpected error occured in catalog submodule" + + def __init__(self, msg=None, **ctx): + super().__init__(**ctx) + if msg: + self.msg_template = msg + + def debug_message(self): + # Override in subclass + return f"{self.code}: {self}" + + +class DefaultPricingUnitForServiceNotFoundError(BaseCatalogError): + msg_template = "Default pricing unit not found for service key '{service_key}' and version '{service_version}'" + + def __init__(self, *, service_key: str, service_version: str, **ctxs): + super().__init__(**ctxs) + self.service_key = service_key + self.service_version = service_version diff --git a/services/web/server/src/simcore_service_webserver/catalog/plugin.py b/services/web/server/src/simcore_service_webserver/catalog/plugin.py index 250b3810d73a..b8a5bbce743a 100644 --- a/services/web/server/src/simcore_service_webserver/catalog/plugin.py +++ b/services/web/server/src/simcore_service_webserver/catalog/plugin.py @@ -6,7 +6,7 @@ from pint import UnitRegistry from servicelib.aiohttp.application_setup import ModuleCategory, app_module_setup -from . import _rest_controller, _rest_tags_controller +from . import _controller_rest _logger = logging.getLogger(__name__) @@ -22,11 +22,10 @@ def setup_catalog(app: web.Application): # ensures routes are names that corresponds to function names assert all( # nosec route_def.kwargs["name"] == route_def.handler.__name__ # type: ignore[attr-defined] # route_def is a RouteDef not an Abstract - for route_def in _rest_controller.routes + for route_def in _controller_rest.routes ) - app.add_routes(_rest_controller.routes) - app.add_routes(_rest_tags_controller.routes) + app.add_routes(_controller_rest.routes) # prepares units registry app[UnitRegistry.__name__] = UnitRegistry() diff --git a/services/web/server/tests/unit/isolated/test_catalog_models.py b/services/web/server/tests/unit/isolated/test_catalog_models.py index d42ed45e6034..2a3fb5ad3d8b 100644 --- a/services/web/server/tests/unit/isolated/test_catalog_models.py +++ b/services/web/server/tests/unit/isolated/test_catalog_models.py @@ -9,7 +9,7 @@ import pytest from pint import UnitRegistry from pytest_benchmark.fixture import BenchmarkFixture -from simcore_service_webserver.catalog._rest_controller import RESPONSE_MODEL_POLICY +from simcore_service_webserver.catalog._controller_rest import RESPONSE_MODEL_POLICY from simcore_service_webserver.catalog._units_service import ( replace_service_input_outputs, ) diff --git a/services/web/server/tests/unit/isolated/test_catalog_api_units.py b/services/web/server/tests/unit/isolated/test_catalog_units_service.py similarity index 100% rename from services/web/server/tests/unit/isolated/test_catalog_api_units.py rename to services/web/server/tests/unit/isolated/test_catalog_units_service.py diff --git a/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py b/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py index b5ca8665c37e..171537099216 100644 --- a/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py +++ b/services/web/server/tests/unit/with_dbs/01/test_catalog_handlers__services.py @@ -30,7 +30,7 @@ from pytest_simcore.helpers.typing_env import EnvVarsDict from pytest_simcore.helpers.webserver_login import UserInfoDict from servicelib.aiohttp import status -from simcore_service_webserver.catalog.controller_rest_schemas import ( +from simcore_service_webserver.catalog._controller_rest_schemas import ( ServiceInputGet, ServiceOutputGet, ) diff --git a/services/web/server/tests/unit/with_dbs/01/test_catalog_rest_client.py b/services/web/server/tests/unit/with_dbs/01/test_catalog_rest_client.py index 386399824ec5..452ecfd76ec6 100644 --- a/services/web/server/tests/unit/with_dbs/01/test_catalog_rest_client.py +++ b/services/web/server/tests/unit/with_dbs/01/test_catalog_rest_client.py @@ -10,7 +10,7 @@ ) from pytest_simcore.helpers.webserver_login import UserInfoDict from servicelib.aiohttp import status -from simcore_service_webserver.catalog._exceptions import ( +from simcore_service_webserver.catalog._controller_rest_exceptions import ( DefaultPricingUnitForServiceNotFoundError, ) from simcore_service_webserver.catalog.catalog_service import (