Loading src/srm/api/errors.py +19 −19 Changes for src/srm/api/errors.py: 19 added lines, 19 removed lines. Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ from srm.domain.models.common import DomainModel PROBLEM_BASE = "https://etsi.org/sdg/oop/problems" PROBLEM_JSON = "application/problem+json" INVALID_REQUEST = f"{PROBLEM_BASE}/invalid-request" _MAX_DETAIL = 512 class ProblemDetails(DomainModel): Loading @@ -35,6 +38,7 @@ class ProblemDetails(DomainModel): def _title_for_status(status_code: int) -> str: return { 400: "Bad Request", 404: "Not Found", 409: "Conflict", 422: "Unprocessable Entity", Loading Loading @@ -78,6 +82,15 @@ def _is_unrouted_path(request: Request, exc: StarletteHTTPException) -> bool: return exc.status_code == status.HTTP_404_NOT_FOUND and request.scope.get("route") is None def _detail(exc: RequestValidationError) -> str: # `loc` opens with "body"/"query"; the useful part is the canonical field path after it. parts = [ f"{'.'.join(str(segment) for segment in error['loc'][1:]) or 'body'}: {error['msg']}" for error in exc.errors() ] return "; ".join(parts)[:_MAX_DETAIL] async def http_exception_handler( request: Request, exc: Exception, Loading Loading @@ -110,26 +123,13 @@ async def validation_exception_handler( ) -> JSONResponse: if not isinstance(exc, RequestValidationError): raise exc problem = ProblemDetails( type="about:blank", title=_title_for_status(422), status=422, detail="Request validation failed.", instance=str(request.url.path), errors=[ { "loc": list(error["loc"]), "msg": str(error["msg"]), "type": str(error["type"]), } for error in exc.errors() ], return problem_response( status_code=status.HTTP_400_BAD_REQUEST, type_uri=INVALID_REQUEST, title="Request failed validation.", detail=_detail(exc), correlator=request.headers.get("x-correlator"), ) response = _problem_response(problem) correlator = request.headers.get("x-correlator") if correlator is not None: response.headers["x-correlator"] = correlator return response async def unhandled_exception_handler( Loading src/srm/domain/ports/__init__.py +0 −4 Changes for src/srm/domain/ports/__init__.py: 0 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ from srm.domain.ports.transformation_functions import ( BackendOperationInProgress, BindingUnavailable, CapabilityConflict, CapabilityExecutionPort, CapabilityLifecycleRequest, CapabilityLifecycleResult, CapabilityQueryRequest, Loading @@ -27,7 +26,6 @@ from srm.domain.ports.transformation_functions import ( ResourceNotFound, TemporaryDomainFailure, TFSDKError, TopologyDiscoveryPort, TransformationFunctionCapability, TransformationFunctionControlPathBinding, TransformationFunctionDiscoveryPort, Loading @@ -46,7 +44,6 @@ __all__ = [ "BackendOperationInProgress", "BindingUnavailable", "CapabilityConflict", "CapabilityExecutionPort", "CapabilityLifecycleRequest", "CapabilityLifecycleResult", "CapabilityQueryRequest", Loading @@ -66,7 +63,6 @@ __all__ = [ "ResourceNotFound", "TFSDKError", "TemporaryDomainFailure", "TopologyDiscoveryPort", "TransformationFunctionCapability", "TransformationFunctionControlPathBinding", "TransformationFunctionDiscoveryPort", Loading src/srm/domain/ports/transformation_functions/__init__.py +0 −5 Changes for src/srm/domain/ports/transformation_functions/__init__.py: 0 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -53,8 +53,6 @@ from srm.domain.ports.transformation_functions.models import ( TransformationFunctionZone, ) from srm.domain.ports.transformation_functions.ports import ( CapabilityExecutionPort, TopologyDiscoveryPort, TransformationFunctionDiscoveryPort, TransformationFunctionExecutionPort, ) Loading @@ -72,7 +70,6 @@ __all__ = [ "BackendOperationInProgress", "BindingUnavailable", "CapabilityConflict", "CapabilityExecutionPort", "CapabilityLifecycleRequest", "CapabilityLifecycleResult", "CapabilityQueryRequest", Loading Loading @@ -106,9 +103,7 @@ __all__ = [ "TargetServeability", "TargetServeabilityRequest", "TemporaryDomainFailure", "TopologyDiscoveryPort", "TransformationFunctionAdapterFactory", "TransformationFunctionCapability", "TransformationFunctionControlPathBinding", "TransformationFunctionDiscoveryPort", Loading tests/api/rest/test_catalog.py +7 −7 Changes for tests/api/rest/test_catalog.py: 7 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -187,13 +187,13 @@ async def test_create_unknown_deployment_unit_ref_returns_400(client_with_db: As response = await client_with_db.post("/internal/catalog/service-specifications", json=payload) _assert_problem( response, status_code=422, title="Unprocessable Entity", detail="Request validation failed.", ) assert "errors" in response.json() assert response.status_code == 400 assert response.headers["content-type"].startswith("application/problem+json") body = response.json() assert body["type"] == "https://etsi.org/sdg/oop/problems/invalid-request" assert body["title"] == "Request failed validation." assert body["status"] == 400 assert body["detail"] @pytest.mark.integration Loading tests/integration/test_databus_command_flow.py +4 −4 Changes for tests/integration/test_databus_command_flow.py: 4 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -175,7 +175,7 @@ async def _seed_deploy_catalog( service_specification_id=specification.id, deployment_unit_id=deployment_unit.id, ref="deploy-workload", capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, domain_kind=DomainKind.COMPUTE, parameters=_parameters("service.deploy"), ) Loading Loading @@ -392,7 +392,7 @@ async def test_service_deploy_command_flow_persists_runtime_rows_and_publishes_e zone, domain, _capability, _binding = await _seed_capability_surface( session, domain_kind=DomainKind.COMPUTE, capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, supported_actions=["deploy"], supported_runtime_kinds=[RuntimeKind.HELM], ) Loading Loading @@ -576,7 +576,7 @@ async def test_service_deploy_with_unknown_service_specification_publishes_faile zone, domain, _capability, _binding = await _seed_capability_surface( session, domain_kind=DomainKind.COMPUTE, capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, supported_actions=["deploy"], supported_runtime_kinds=[RuntimeKind.HELM], ) Loading Loading @@ -654,7 +654,7 @@ async def test_service_deploy_with_invalid_target_pins_publishes_failed_before_s await _seed_capability_surface( session, domain_kind=DomainKind.COMPUTE, capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, supported_actions=["deploy"], supported_runtime_kinds=[RuntimeKind.HELM], ) Loading Loading
src/srm/api/errors.py +19 −19 Changes for src/srm/api/errors.py: 19 added lines, 19 removed lines. Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ from srm.domain.models.common import DomainModel PROBLEM_BASE = "https://etsi.org/sdg/oop/problems" PROBLEM_JSON = "application/problem+json" INVALID_REQUEST = f"{PROBLEM_BASE}/invalid-request" _MAX_DETAIL = 512 class ProblemDetails(DomainModel): Loading @@ -35,6 +38,7 @@ class ProblemDetails(DomainModel): def _title_for_status(status_code: int) -> str: return { 400: "Bad Request", 404: "Not Found", 409: "Conflict", 422: "Unprocessable Entity", Loading Loading @@ -78,6 +82,15 @@ def _is_unrouted_path(request: Request, exc: StarletteHTTPException) -> bool: return exc.status_code == status.HTTP_404_NOT_FOUND and request.scope.get("route") is None def _detail(exc: RequestValidationError) -> str: # `loc` opens with "body"/"query"; the useful part is the canonical field path after it. parts = [ f"{'.'.join(str(segment) for segment in error['loc'][1:]) or 'body'}: {error['msg']}" for error in exc.errors() ] return "; ".join(parts)[:_MAX_DETAIL] async def http_exception_handler( request: Request, exc: Exception, Loading Loading @@ -110,26 +123,13 @@ async def validation_exception_handler( ) -> JSONResponse: if not isinstance(exc, RequestValidationError): raise exc problem = ProblemDetails( type="about:blank", title=_title_for_status(422), status=422, detail="Request validation failed.", instance=str(request.url.path), errors=[ { "loc": list(error["loc"]), "msg": str(error["msg"]), "type": str(error["type"]), } for error in exc.errors() ], return problem_response( status_code=status.HTTP_400_BAD_REQUEST, type_uri=INVALID_REQUEST, title="Request failed validation.", detail=_detail(exc), correlator=request.headers.get("x-correlator"), ) response = _problem_response(problem) correlator = request.headers.get("x-correlator") if correlator is not None: response.headers["x-correlator"] = correlator return response async def unhandled_exception_handler( Loading
src/srm/domain/ports/__init__.py +0 −4 Changes for src/srm/domain/ports/__init__.py: 0 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ from srm.domain.ports.transformation_functions import ( BackendOperationInProgress, BindingUnavailable, CapabilityConflict, CapabilityExecutionPort, CapabilityLifecycleRequest, CapabilityLifecycleResult, CapabilityQueryRequest, Loading @@ -27,7 +26,6 @@ from srm.domain.ports.transformation_functions import ( ResourceNotFound, TemporaryDomainFailure, TFSDKError, TopologyDiscoveryPort, TransformationFunctionCapability, TransformationFunctionControlPathBinding, TransformationFunctionDiscoveryPort, Loading @@ -46,7 +44,6 @@ __all__ = [ "BackendOperationInProgress", "BindingUnavailable", "CapabilityConflict", "CapabilityExecutionPort", "CapabilityLifecycleRequest", "CapabilityLifecycleResult", "CapabilityQueryRequest", Loading @@ -66,7 +63,6 @@ __all__ = [ "ResourceNotFound", "TFSDKError", "TemporaryDomainFailure", "TopologyDiscoveryPort", "TransformationFunctionCapability", "TransformationFunctionControlPathBinding", "TransformationFunctionDiscoveryPort", Loading
src/srm/domain/ports/transformation_functions/__init__.py +0 −5 Changes for src/srm/domain/ports/transformation_functions/__init__.py: 0 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -53,8 +53,6 @@ from srm.domain.ports.transformation_functions.models import ( TransformationFunctionZone, ) from srm.domain.ports.transformation_functions.ports import ( CapabilityExecutionPort, TopologyDiscoveryPort, TransformationFunctionDiscoveryPort, TransformationFunctionExecutionPort, ) Loading @@ -72,7 +70,6 @@ __all__ = [ "BackendOperationInProgress", "BindingUnavailable", "CapabilityConflict", "CapabilityExecutionPort", "CapabilityLifecycleRequest", "CapabilityLifecycleResult", "CapabilityQueryRequest", Loading Loading @@ -106,9 +103,7 @@ __all__ = [ "TargetServeability", "TargetServeabilityRequest", "TemporaryDomainFailure", "TopologyDiscoveryPort", "TransformationFunctionAdapterFactory", "TransformationFunctionCapability", "TransformationFunctionControlPathBinding", "TransformationFunctionDiscoveryPort", Loading
tests/api/rest/test_catalog.py +7 −7 Changes for tests/api/rest/test_catalog.py: 7 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -187,13 +187,13 @@ async def test_create_unknown_deployment_unit_ref_returns_400(client_with_db: As response = await client_with_db.post("/internal/catalog/service-specifications", json=payload) _assert_problem( response, status_code=422, title="Unprocessable Entity", detail="Request validation failed.", ) assert "errors" in response.json() assert response.status_code == 400 assert response.headers["content-type"].startswith("application/problem+json") body = response.json() assert body["type"] == "https://etsi.org/sdg/oop/problems/invalid-request" assert body["title"] == "Request failed validation." assert body["status"] == 400 assert body["detail"] @pytest.mark.integration Loading
tests/integration/test_databus_command_flow.py +4 −4 Changes for tests/integration/test_databus_command_flow.py: 4 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -175,7 +175,7 @@ async def _seed_deploy_catalog( service_specification_id=specification.id, deployment_unit_id=deployment_unit.id, ref="deploy-workload", capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, domain_kind=DomainKind.COMPUTE, parameters=_parameters("service.deploy"), ) Loading Loading @@ -392,7 +392,7 @@ async def test_service_deploy_command_flow_persists_runtime_rows_and_publishes_e zone, domain, _capability, _binding = await _seed_capability_surface( session, domain_kind=DomainKind.COMPUTE, capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, supported_actions=["deploy"], supported_runtime_kinds=[RuntimeKind.HELM], ) Loading Loading @@ -576,7 +576,7 @@ async def test_service_deploy_with_unknown_service_specification_publishes_faile zone, domain, _capability, _binding = await _seed_capability_surface( session, domain_kind=DomainKind.COMPUTE, capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, supported_actions=["deploy"], supported_runtime_kinds=[RuntimeKind.HELM], ) Loading Loading @@ -654,7 +654,7 @@ async def test_service_deploy_with_invalid_target_pins_publishes_failed_before_s await _seed_capability_surface( session, domain_kind=DomainKind.COMPUTE, capability_kind=CapabilityKind.DEPLOY_WORKLOAD, capability_kind=CapabilityKind.WORKLOAD, supported_actions=["deploy"], supported_runtime_kinds=[RuntimeKind.HELM], ) Loading