diff --git a/diracx-client/src/diracx/client/__init__.py b/diracx-client/src/diracx/client/__init__.py index cc37da18..591475aa 100644 --- a/diracx-client/src/diracx/client/__init__.py +++ b/diracx-client/src/diracx/client/__init__.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/_client.py b/diracx-client/src/diracx/client/_client.py index 962319fa..d85313aa 100644 --- a/diracx-client/src/diracx/client/_client.py +++ b/diracx-client/src/diracx/client/_client.py @@ -1,11 +1,12 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from copy import deepcopy from typing import Any +from typing_extensions import Self from azure.core import PipelineClient from azure.core.pipeline import policies @@ -112,7 +113,7 @@ def send_request( def close(self) -> None: self._client.close() - def __enter__(self) -> "Dirac": + def __enter__(self) -> Self: self._client.__enter__() return self diff --git a/diracx-client/src/diracx/client/_configuration.py b/diracx-client/src/diracx/client/_configuration.py index e1883c55..1e4856c5 100644 --- a/diracx-client/src/diracx/client/_configuration.py +++ b/diracx-client/src/diracx/client/_configuration.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/_patch.py b/diracx-client/src/diracx/client/_patch.py index d8772d2e..4122dd88 100644 --- a/diracx-client/src/diracx/client/_patch.py +++ b/diracx-client/src/diracx/client/_patch.py @@ -9,6 +9,7 @@ from __future__ import annotations from datetime import datetime, timezone +from importlib.metadata import PackageNotFoundError, distribution import json import jwt import requests @@ -148,6 +149,20 @@ def __init__( # Get .well-known configuration openid_configuration = get_openid_configuration(self._endpoint, verify=verify) + try: + self.client_version = distribution("diracx").version + except PackageNotFoundError: + try: + self.client_version = distribution("diracx-client").version + except PackageNotFoundError: + print("Error while getting client version") + self.client_version = "Unknown" + + # Setting default headers + kwargs.setdefault("base_headers", {})[ + "DiracX-Client-Version" + ] = self.client_version + # Initialize Dirac with a Dirac-specific token credential policy super().__init__( endpoint=self._endpoint, diff --git a/diracx-client/src/diracx/client/_serialization.py b/diracx-client/src/diracx/client/_serialization.py index 5e7b24dc..4ece2423 100644 --- a/diracx-client/src/diracx/client/_serialization.py +++ b/diracx-client/src/diracx/client/_serialization.py @@ -146,6 +146,8 @@ def _json_attemp(data): # context otherwise. _LOGGER.critical("Wasn't XML not JSON, failing") raise DeserializationError("XML is invalid") from err + elif content_type.startswith("text/"): + return data_as_str raise DeserializationError( "Cannot deserialize content-type: {}".format(content_type) ) diff --git a/diracx-client/src/diracx/client/_vendor.py b/diracx-client/src/diracx/client/_vendor.py index 2b77be83..e39220f8 100644 --- a/diracx-client/src/diracx/client/_vendor.py +++ b/diracx-client/src/diracx/client/_vendor.py @@ -1,5 +1,5 @@ # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/aio/__init__.py b/diracx-client/src/diracx/client/aio/__init__.py index cc37da18..591475aa 100644 --- a/diracx-client/src/diracx/client/aio/__init__.py +++ b/diracx-client/src/diracx/client/aio/__init__.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/aio/_client.py b/diracx-client/src/diracx/client/aio/_client.py index e0128831..ce00cbff 100644 --- a/diracx-client/src/diracx/client/aio/_client.py +++ b/diracx-client/src/diracx/client/aio/_client.py @@ -1,11 +1,12 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from copy import deepcopy from typing import Any, Awaitable +from typing_extensions import Self from azure.core import AsyncPipelineClient from azure.core.pipeline import policies @@ -112,7 +113,7 @@ def send_request( async def close(self) -> None: await self._client.close() - async def __aenter__(self) -> "Dirac": + async def __aenter__(self) -> Self: await self._client.__aenter__() return self diff --git a/diracx-client/src/diracx/client/aio/_configuration.py b/diracx-client/src/diracx/client/aio/_configuration.py index 3a48c2b6..1a7d2355 100644 --- a/diracx-client/src/diracx/client/aio/_configuration.py +++ b/diracx-client/src/diracx/client/aio/_configuration.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/aio/_patch.py b/diracx-client/src/diracx/client/aio/_patch.py index 1a70f1c4..3438055f 100644 --- a/diracx-client/src/diracx/client/aio/_patch.py +++ b/diracx-client/src/diracx/client/aio/_patch.py @@ -6,6 +6,7 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ +from importlib.metadata import PackageNotFoundError, distribution import json from types import TracebackType from pathlib import Path @@ -163,6 +164,20 @@ def __init__( # Get .well-known configuration openid_configuration = get_openid_configuration(self._endpoint, verify=verify) + try: + self.client_version = distribution("diracx").version + except PackageNotFoundError: + try: + self.client_version = distribution("diracx-client").version + except PackageNotFoundError: + print("Error while getting client version") + self.client_version = "Unknown" + + # Setting default headers + kwargs.setdefault("base_headers", {})[ + "DiracX-Client-Version" + ] = self.client_version + # Initialize Dirac with a Dirac-specific token credential policy super().__init__( endpoint=self._endpoint, diff --git a/diracx-client/src/diracx/client/aio/_vendor.py b/diracx-client/src/diracx/client/aio/_vendor.py index 2b77be83..e39220f8 100644 --- a/diracx-client/src/diracx/client/aio/_vendor.py +++ b/diracx-client/src/diracx/client/aio/_vendor.py @@ -1,5 +1,5 @@ # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/aio/operations/__init__.py b/diracx-client/src/diracx/client/aio/operations/__init__.py index eb877968..53c77f56 100644 --- a/diracx-client/src/diracx/client/aio/operations/__init__.py +++ b/diracx-client/src/diracx/client/aio/operations/__init__.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/aio/operations/_operations.py b/diracx-client/src/diracx/client/aio/operations/_operations.py index 8a2f0d53..a6efb82d 100644 --- a/diracx-client/src/diracx/client/aio/operations/_operations.py +++ b/diracx-client/src/diracx/client/aio/operations/_operations.py @@ -1,7 +1,7 @@ # pylint: disable=too-many-lines,too-many-statements # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from io import IOBase @@ -148,14 +148,12 @@ async def openid_configuration(self, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -201,14 +199,12 @@ async def installation_metadata(self, **kwargs: Any) -> _models.Metadata: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("Metadata", pipeline_response) + deserialized = self._deserialize("Metadata", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -253,7 +249,7 @@ async def initiate_device_flow( Initiate the device flow against DIRAC authorization Server. Scope must have exactly up to one ``group`` (otherwise default) and one or more ``property`` scope. - If no property, then get default one + If no property, then get default one. Offers the user to go with the browser to ``auth//device?user_code=XYZ``. @@ -297,15 +293,13 @@ async def initiate_device_flow( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) deserialized = self._deserialize( - "InitiateDeviceFlowResponse", pipeline_response + "InitiateDeviceFlowResponse", pipeline_response.http_response ) if cls: @@ -362,14 +356,12 @@ async def do_device_flow(self, *, user_code: str, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -425,14 +417,12 @@ async def finish_device_flow(self, *, code: str, state: str, **kwargs: Any) -> A response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -478,14 +468,12 @@ async def finished(self, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -532,14 +520,12 @@ async def get_refresh_tokens(self, **kwargs: Any) -> List[Any]: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize("[object]", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -589,14 +575,12 @@ async def revoke_refresh_token(self, jti: str, **kwargs: Any) -> str: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("str", pipeline_response) + deserialized = self._deserialize("str", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -642,14 +626,14 @@ async def userinfo(self, **kwargs: Any) -> _models.UserInfoResponse: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("UserInfoResponse", pipeline_response) + deserialized = self._deserialize( + "UserInfoResponse", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -733,14 +717,12 @@ async def authorization_flow( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -800,14 +782,12 @@ async def authorization_flow_complete( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -903,14 +883,12 @@ async def serve_config( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1054,14 +1032,14 @@ async def initiate_sandbox_upload( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("SandboxUploadResponse", pipeline_response) + deserialized = self._deserialize( + "SandboxUploadResponse", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1074,7 +1052,7 @@ async def get_sandbox_file( ) -> _models.SandboxDownloadResponse: """Get Sandbox File. - Get a presigned URL to download a sandbox file + Get a presigned URL to download a sandbox file. This route cannot use a redirect response most clients will also send the authorization header when following a redirect. This is not desirable as @@ -1118,14 +1096,14 @@ async def get_sandbox_file( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("SandboxDownloadResponse", pipeline_response) + deserialized = self._deserialize( + "SandboxDownloadResponse", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1176,14 +1154,12 @@ async def unassign_bulk_jobs_sandboxes( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1234,14 +1210,12 @@ async def get_job_sandboxes( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{[object]}", pipeline_response) + deserialized = self._deserialize("{[object]}", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1290,14 +1264,12 @@ async def unassign_job_sandboxes(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1351,14 +1323,12 @@ async def get_job_sandbox( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize("[object]", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1416,14 +1386,12 @@ async def assign_sandbox_to_job(self, job_id: int, body: str, **kwargs: Any) -> response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1523,14 +1491,14 @@ async def submit_bulk_jobs( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("[InsertedJob]", pipeline_response) + deserialized = self._deserialize( + "[InsertedJob]", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1579,14 +1547,12 @@ async def delete_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1635,14 +1601,12 @@ async def kill_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1695,14 +1659,12 @@ async def remove_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1755,14 +1717,14 @@ async def get_job_status_bulk( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{LimitedJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{LimitedJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1883,14 +1845,14 @@ async def set_job_status_bulk( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{SetJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{SetJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1941,14 +1903,14 @@ async def get_job_status_history_bulk( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{[JobStatusReturn]}", pipeline_response) + deserialized = self._deserialize( + "{[JobStatusReturn]}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1997,14 +1959,12 @@ async def reschedule_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> An response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2053,14 +2013,12 @@ async def reschedule_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2200,8 +2158,6 @@ async def search( response = pipeline_response.http_response if response.status_code not in [200, 206]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) @@ -2209,14 +2165,18 @@ async def search( response_headers = {} if response.status_code == 200: - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize( + "[object]", pipeline_response.http_response + ) if response.status_code == 206: response_headers["Content-Range"] = self._deserialize( "str", response.headers.get("Content-Range") ) - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize( + "[object]", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, response_headers) # type: ignore @@ -2320,14 +2280,12 @@ async def summary( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2376,14 +2334,12 @@ async def get_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2432,14 +2388,12 @@ async def delete_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2502,14 +2456,12 @@ async def set_single_job_properties( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2558,14 +2510,12 @@ async def kill_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2618,14 +2568,12 @@ async def remove_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2678,14 +2626,14 @@ async def get_single_job_status( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{LimitedJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{LimitedJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2816,14 +2764,14 @@ async def set_single_job_status( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{SetJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{SetJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2874,14 +2822,14 @@ async def get_single_job_status_history( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - await response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{[JobStatusReturn]}", pipeline_response) + deserialized = self._deserialize( + "{[JobStatusReturn]}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore diff --git a/diracx-client/src/diracx/client/models/__init__.py b/diracx-client/src/diracx/client/models/__init__.py index 7cd1643a..304a53ed 100644 --- a/diracx-client/src/diracx/client/models/__init__.py +++ b/diracx-client/src/diracx/client/models/__init__.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/models/_enums.py b/diracx-client/src/diracx/client/models/_enums.py index 935cbb17..9bc6d2ee 100644 --- a/diracx-client/src/diracx/client/models/_enums.py +++ b/diracx-client/src/diracx/client/models/_enums.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -99,5 +99,5 @@ class SortDirection(str, Enum, metaclass=CaseInsensitiveEnumMeta): class VectorSearchOperator(str, Enum, metaclass=CaseInsensitiveEnumMeta): """VectorSearchOperator.""" - IN_ENUM = "in" + IN = "in" NOT_IN = "not in" diff --git a/diracx-client/src/diracx/client/models/_models.py b/diracx-client/src/diracx/client/models/_models.py index 23833265..3e2a116e 100644 --- a/diracx-client/src/diracx/client/models/_models.py +++ b/diracx-client/src/diracx/client/models/_models.py @@ -1,7 +1,7 @@ # coding=utf-8 # pylint: disable=too-many-lines # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/operations/__init__.py b/diracx-client/src/diracx/client/operations/__init__.py index eb877968..53c77f56 100644 --- a/diracx-client/src/diracx/client/operations/__init__.py +++ b/diracx-client/src/diracx/client/operations/__init__.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/diracx-client/src/diracx/client/operations/_operations.py b/diracx-client/src/diracx/client/operations/_operations.py index 800996ab..9b365a0b 100644 --- a/diracx-client/src/diracx/client/operations/_operations.py +++ b/diracx-client/src/diracx/client/operations/_operations.py @@ -1,7 +1,7 @@ # pylint: disable=too-many-lines,too-many-statements # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.13.19) +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.10.2, generator: @autorest/python@6.15.0) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from io import IOBase @@ -972,14 +972,12 @@ def openid_configuration(self, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1025,14 +1023,12 @@ def installation_metadata(self, **kwargs: Any) -> _models.Metadata: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("Metadata", pipeline_response) + deserialized = self._deserialize("Metadata", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1077,7 +1073,7 @@ def initiate_device_flow( Initiate the device flow against DIRAC authorization Server. Scope must have exactly up to one ``group`` (otherwise default) and one or more ``property`` scope. - If no property, then get default one + If no property, then get default one. Offers the user to go with the browser to ``auth//device?user_code=XYZ``. @@ -1121,15 +1117,13 @@ def initiate_device_flow( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) deserialized = self._deserialize( - "InitiateDeviceFlowResponse", pipeline_response + "InitiateDeviceFlowResponse", pipeline_response.http_response ) if cls: @@ -1186,14 +1180,12 @@ def do_device_flow(self, *, user_code: str, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1249,14 +1241,12 @@ def finish_device_flow(self, *, code: str, state: str, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1302,14 +1292,12 @@ def finished(self, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1356,14 +1344,12 @@ def get_refresh_tokens(self, **kwargs: Any) -> List[Any]: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize("[object]", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1413,14 +1399,12 @@ def revoke_refresh_token(self, jti: str, **kwargs: Any) -> str: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("str", pipeline_response) + deserialized = self._deserialize("str", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1466,14 +1450,14 @@ def userinfo(self, **kwargs: Any) -> _models.UserInfoResponse: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("UserInfoResponse", pipeline_response) + deserialized = self._deserialize( + "UserInfoResponse", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1557,14 +1541,12 @@ def authorization_flow( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1624,14 +1606,12 @@ def authorization_flow_complete( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1727,14 +1707,12 @@ def serve_config( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1878,14 +1856,14 @@ def initiate_sandbox_upload( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("SandboxUploadResponse", pipeline_response) + deserialized = self._deserialize( + "SandboxUploadResponse", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -1898,7 +1876,7 @@ def get_sandbox_file( ) -> _models.SandboxDownloadResponse: """Get Sandbox File. - Get a presigned URL to download a sandbox file + Get a presigned URL to download a sandbox file. This route cannot use a redirect response most clients will also send the authorization header when following a redirect. This is not desirable as @@ -1942,14 +1920,14 @@ def get_sandbox_file( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("SandboxDownloadResponse", pipeline_response) + deserialized = self._deserialize( + "SandboxDownloadResponse", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2000,14 +1978,12 @@ def unassign_bulk_jobs_sandboxes( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2056,14 +2032,12 @@ def get_job_sandboxes(self, job_id: int, **kwargs: Any) -> Dict[str, List[Any]]: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{[object]}", pipeline_response) + deserialized = self._deserialize("{[object]}", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2112,14 +2086,12 @@ def unassign_job_sandboxes(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2173,14 +2145,12 @@ def get_job_sandbox( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize("[object]", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2238,14 +2208,12 @@ def assign_sandbox_to_job(self, job_id: int, body: str, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2345,14 +2313,14 @@ def submit_bulk_jobs( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("[InsertedJob]", pipeline_response) + deserialized = self._deserialize( + "[InsertedJob]", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2401,14 +2369,12 @@ def delete_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2457,14 +2423,12 @@ def kill_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2517,14 +2481,12 @@ def remove_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2577,14 +2539,14 @@ def get_job_status_bulk( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{LimitedJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{LimitedJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2705,14 +2667,14 @@ def set_job_status_bulk( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{SetJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{SetJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2763,14 +2725,14 @@ def get_job_status_history_bulk( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{[JobStatusReturn]}", pipeline_response) + deserialized = self._deserialize( + "{[JobStatusReturn]}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2819,14 +2781,12 @@ def reschedule_bulk_jobs(self, *, job_ids: List[int], **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -2875,14 +2835,12 @@ def reschedule_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3022,8 +2980,6 @@ def search( response = pipeline_response.http_response if response.status_code not in [200, 206]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) @@ -3031,14 +2987,18 @@ def search( response_headers = {} if response.status_code == 200: - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize( + "[object]", pipeline_response.http_response + ) if response.status_code == 206: response_headers["Content-Range"] = self._deserialize( "str", response.headers.get("Content-Range") ) - deserialized = self._deserialize("[object]", pipeline_response) + deserialized = self._deserialize( + "[object]", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, response_headers) # type: ignore @@ -3142,14 +3102,12 @@ def summary( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3198,14 +3156,12 @@ def get_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3254,14 +3210,12 @@ def delete_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3324,14 +3278,12 @@ def set_single_job_properties( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3380,14 +3332,12 @@ def kill_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3440,14 +3390,12 @@ def remove_single_job(self, job_id: int, **kwargs: Any) -> Any: response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("object", pipeline_response) + deserialized = self._deserialize("object", pipeline_response.http_response) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3500,14 +3448,14 @@ def get_single_job_status( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{LimitedJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{LimitedJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3638,14 +3586,14 @@ def set_single_job_status( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{SetJobStatusReturn}", pipeline_response) + deserialized = self._deserialize( + "{SetJobStatusReturn}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3696,14 +3644,14 @@ def get_single_job_status_history( response = pipeline_response.http_response if response.status_code not in [200]: - if _stream: - response.read() # Load the body in memory and close the socket map_error( status_code=response.status_code, response=response, error_map=error_map ) raise HttpResponseError(response=response) - deserialized = self._deserialize("{[JobStatusReturn]}", pipeline_response) + deserialized = self._deserialize( + "{[JobStatusReturn]}", pipeline_response.http_response + ) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore diff --git a/diracx-routers/pyproject.toml b/diracx-routers/pyproject.toml index 97fdccb3..886218fb 100644 --- a/diracx-routers/pyproject.toml +++ b/diracx-routers/pyproject.toml @@ -56,6 +56,8 @@ auth = "diracx.routers.auth:router" WMSAccessPolicy = "diracx.routers.job_manager.access_policies:WMSAccessPolicy" SandboxAccessPolicy = "diracx.routers.job_manager.access_policies:SandboxAccessPolicy" +[project.entry-points."diracx.min_client_version"] +diracx = "diracx.routers:DIRACX_MIN_CLIENT_VERSION" [tool.setuptools.packages.find] where = ["src"] diff --git a/diracx-routers/src/diracx/routers/__init__.py b/diracx-routers/src/diracx/routers/__init__.py index 2ff15cde..23f50ac9 100644 --- a/diracx-routers/src/diracx/routers/__init__.py +++ b/diracx-routers/src/diracx/routers/__init__.py @@ -12,19 +12,23 @@ import os from collections.abc import AsyncGenerator from functools import partial +from http import HTTPStatus +from importlib.metadata import EntryPoint, EntryPoints, entry_points from logging import Formatter, StreamHandler from typing import Any, Awaitable, Callable, Iterable, Sequence, TypeVar, cast import dotenv from cachetools import TTLCache -from fastapi import APIRouter, Depends, Request, status +from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request, status from fastapi.dependencies.models import Dependant from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, Response from fastapi.routing import APIRoute +from packaging.version import InvalidVersion, parse from pydantic import TypeAdapter # from starlette.types import ASGIApp +from starlette.middleware.base import BaseHTTPMiddleware from uvicorn.logging import AccessFormatter, DefaultFormatter from diracx.core.config import ConfigSource @@ -290,6 +294,8 @@ def create_app_inner( "http://localhost:8000", ] + app.add_middleware(ClientMinVersionCheckMiddleware) + app.add_middleware( CORSMiddleware, allow_origins=origins, @@ -437,3 +443,60 @@ async def db_transaction(db: T2) -> AsyncGenerator[T2, None]: if reason := await is_db_unavailable(db): raise DBUnavailable(reason) yield db + + +class ClientMinVersionCheckMiddleware(BaseHTTPMiddleware): + """Custom FastAPI middleware to verify that + the client has the required minimum version. + """ + + def __init__(self, app: FastAPI): + super().__init__(app) + self.min_client_version = get_min_client_version() + + async def dispatch(self, request: Request, call_next) -> Response: + client_version = request.headers.get("DiracX-Client-Version") + if not client_version: + logger.info("DiracX-Client-Version header is missing.") + # TODO: if the request comes from web or swagger (other?), + # the header will be missing > how to manage that? + # raise HTTPException( + # status_code=HTTPStatus.BAD_REQUEST, + # detail="Client version header is missing.", + # ) + elif self.is_version_too_old(client_version): + raise HTTPException( + status_code=HTTPStatus.UPGRADE_REQUIRED, + detail=f"Client version ({client_version}) not recent enough (>= {self.min_client_version}). Upgrade.", + ) + + response = await call_next(request) + return response + + def is_version_too_old(self, client_version: str) -> bool | None: + """Verify that client version is ge than min.""" + try: + return parse(client_version) < parse(self.min_client_version) + except InvalidVersion as iv_exc: + logger.info(iv_exc) + return None + + +# I'm not sure if this has to be define here: +DIRACX_MIN_CLIENT_VERSION = "0.0.1" + + +def get_min_client_version(): + """Extracting min client version from entry_points and seraching for extension.""" + matched_entry_points: EntryPoints = entry_points(group="diracx.min_client_version") + # Searching for an extension: + entry_points_dict: dict[str, EntryPoint] = { + ep.name: ep for ep in matched_entry_points + } + for ep_name, ep in entry_points_dict.items(): + if ep_name != "diracx": + return ep.load() + + # Taking diracx if no extension: + if "diracx" in entry_points_dict: + return entry_points_dict["diracx"].load() diff --git a/diracx-routers/tests/test_generic.py b/diracx-routers/tests/test_generic.py index 9f31064d..0b047359 100644 --- a/diracx-routers/tests/test_generic.py +++ b/diracx-routers/tests/test_generic.py @@ -1,4 +1,10 @@ +from http import HTTPStatus + import pytest +from fastapi import HTTPException +from packaging.version import Version, parse + +from diracx.routers import DIRACX_MIN_CLIENT_VERSION pytestmark = pytest.mark.enabled_dependencies( ["ConfigSource", "AuthSettings", "OpenAccessPolicy"] @@ -41,3 +47,27 @@ def test_unavailable_db(monkeypatch, test_client): r = test_client.get("/api/job/123") assert r.status_code == 503 assert r.json() + + +def test_min_client_version_lower_than_expected(test_client): + min_client_version: Version = parse(DIRACX_MIN_CLIENT_VERSION) + lower_version_than_min: Version = ( + f"{min_client_version.major}.{min_client_version.minor}.dev123" + ) + with pytest.raises(HTTPException) as response: + test_client.get("/", headers={"DiracX-Client-Version": lower_version_than_min}) + assert response.value.status_code == HTTPStatus.UPGRADE_REQUIRED + assert "not recent enough" in response.value.detail + + +def test_client_version_not_in_header(test_client, caplog: pytest.LogCaptureFixture): + test_client.get("/", headers={}) + assert "header is missing" in caplog.text + + test_client.get("/", headers={"DiracX-Client-Version": ""}) + assert "header is missing" in caplog.text + + +def test_wrong_client_version(test_client, caplog: pytest.LogCaptureFixture): + test_client.get("/", headers={"DiracX-Client-Version": "Unknown"}) + assert "Invalid version: 'Unknown'" in caplog.text