diff --git a/CHANGELOG.md b/CHANGELOG.md index b75fef6..b7f64f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ## [4.1.0] - 2024-07-01 +### Added +- support for bulk create and bulk update for Affects (OSIDB-3124) ## [4.0.0] - 2024-06-17 ### Added diff --git a/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_create.py b/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_create.py index c6dac36..9c0bf7d 100644 --- a/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_create.py +++ b/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_create.py @@ -10,6 +10,7 @@ from ...types import UNSET, Response, Unset QUERY_PARAMS = {} +REQUEST_BODY_TYPE = List[AffectPost] def _get_kwargs( @@ -47,7 +48,7 @@ def _get_kwargs( return { "url": url, "headers": headers, - "json": form_data.to_dict(), + "json": json_json_body, } diff --git a/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_update.py b/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_update.py index b84920e..e67ccfe 100644 --- a/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_update.py +++ b/osidb_bindings/bindings/python_client/api/osidb/osidb_api_v1_affects_bulk_update.py @@ -10,6 +10,7 @@ from ...types import UNSET, Response, Unset QUERY_PARAMS = {} +REQUEST_BODY_TYPE = List[AffectBulkPut] def _get_kwargs( @@ -47,7 +48,7 @@ def _get_kwargs( return { "url": url, "headers": headers, - "json": form_data.to_dict(), + "json": json_json_body, } diff --git a/osidb_bindings/session.py b/osidb_bindings/session.py index 736d457..c2fefbd 100644 --- a/osidb_bindings/session.py +++ b/osidb_bindings/session.py @@ -6,7 +6,7 @@ import importlib import types from types import ModuleType -from typing import Any, Callable, Dict, List, Optional, Tuple +from typing import Any, Callable, Dict, List, Optional, Tuple, get_args, get_origin import aiohttp import requests @@ -27,7 +27,11 @@ OSIDB_BINDINGS_PLACEHOLDER_FIELD, OSIDB_BINDINGS_USERAGENT, ) -from .exceptions import OperationUnsupported, UndefinedRequestBody +from .exceptions import ( + OperationUnsupported, + OSIDBBindingsException, + UndefinedRequestBody, +) from .helpers import get_env from .iterators import Paginator @@ -108,6 +112,19 @@ def get_async_function(api_module: ModuleType) -> Callable: ) +def serialize_data(data, model): + """ + Serialize data into bindings model or list of bindings models + """ + if hasattr(model, "from_dict"): + return model.from_dict(data) + elif get_origin(model) is list: + inner_model = get_args(model)[0] + return [serialize_data(item, inner_model) for item in data] + else: + raise OSIDBBindingsException(f"Unserializable model '{model}'") + + def new_session( osidb_server_uri, password=None, @@ -207,6 +224,10 @@ def __init__(self, base_url, auth=None, verify_ssl=True): "list", "create", "destroy", + "bulk_create", + "bulk_update", + # TODO: currently blocked by OSIDB-2996 + # "bulk_delete", ), subresources={ "cvss_scores": { @@ -389,12 +410,12 @@ def create(self, form_data: Dict[str, Any], *args, **kwargs): if model is None: self.__raise_undefined_request_body("create") - transformed_data = model.from_dict(form_data) + serialized_data = serialize_data(form_data, model) sync_fn = get_sync_function(method_module) return sync_fn( *args, client=self.client(), - form_data=transformed_data, + form_data=serialized_data, multipart_data=UNSET, json_body=UNSET, **kwargs, @@ -402,6 +423,27 @@ def create(self, form_data: Dict[str, Any], *args, **kwargs): else: self.__raise_operation_unsupported("create") + def bulk_create(self, form_data: Dict[str, Any], *args, **kwargs): + if "bulk_create" in self.allowed_operations: + method_module = self.__get_method_module( + resource_name=self.resource_name, method="bulk_create" + ) + model = getattr(method_module, "REQUEST_BODY_TYPE", None) + if model is None: + self.__raise_undefined_request_body("bulk_create") + + serialized_data = serialize_data(form_data, model) + sync_fn = get_sync_function(method_module) + return sync_fn( + *args, + client=self.client(), + json_body=serialized_data, + multipart_data=UNSET, + **kwargs, + ) + else: + self.__raise_operation_unsupported("bulk_create") + def update(self, id, form_data: Dict[str, Any], *args, **kwargs): if "update" in self.allowed_operations: method_module = self.__get_method_module( @@ -411,13 +453,13 @@ def update(self, id, form_data: Dict[str, Any], *args, **kwargs): if model is None: self.__raise_undefined_request_body("update") - transformed_data = model.from_dict(form_data) + serialized_data = serialize_data(form_data, model) sync_fn = get_sync_function(method_module) return sync_fn( id, *args, client=self.client(), - form_data=transformed_data, + form_data=serialized_data, multipart_data=UNSET, json_body=UNSET, **kwargs, @@ -425,6 +467,27 @@ def update(self, id, form_data: Dict[str, Any], *args, **kwargs): else: self.__raise_operation_unsupported("update") + def bulk_update(self, form_data: Dict[str, Any], *args, **kwargs): + if "bulk_update" in self.allowed_operations: + method_module = self.__get_method_module( + resource_name=self.resource_name, method="bulk_update" + ) + model = getattr(method_module, "REQUEST_BODY_TYPE", None) + if model is None: + self.__raise_undefined_request_body("bulk_update") + + serialized_data = serialize_data(form_data, model) + sync_fn = get_sync_function(method_module) + return sync_fn( + *args, + client=self.client(), + json_body=serialized_data, + multipart_data=UNSET, + **kwargs, + ) + else: + self.__raise_operation_unsupported("bulk_update") + def delete(self, id, *args, **kwargs): if "destroy" in self.allowed_operations: method_module = self.__get_method_module( @@ -440,6 +503,27 @@ def delete(self, id, *args, **kwargs): else: self.__raise_operation_unsupported("delete") + def bulk_delete(self, form_data: Dict[str, Any], *args, **kwargs): + if "bulk_delete" in self.allowed_operations: + method_module = self.__get_method_module( + resource_name=self.resource_name, method="bulk_destroy" + ) + model = getattr(method_module, "REQUEST_BODY_TYPE", None) + if model is None: + self.__raise_undefined_request_body("bulk_delete") + + serialized_data = serialize_data(form_data, model) + sync_fn = get_sync_function(method_module) + return sync_fn( + *args, + client=self.client(), + json_body=serialized_data, + multipart_data=UNSET, + **kwargs, + ) + else: + self.__raise_operation_unsupported("bulk_delete") + # Extra operations def count(self, *args, **kwargs): diff --git a/osidb_bindings/templates/endpoint_module.py.jinja b/osidb_bindings/templates/endpoint_module.py.jinja index a87179f..6c382b5 100644 --- a/osidb_bindings/templates/endpoint_module.py.jinja +++ b/osidb_bindings/templates/endpoint_module.py.jinja @@ -26,6 +26,8 @@ QUERY_PARAMS = { } {% if endpoint.form_body_class %} REQUEST_BODY_TYPE = {{ endpoint.form_body_class.name }} +{% elif endpoint.json_body %} +REQUEST_BODY_TYPE = {{ endpoint.json_body.get_type_string() }} {% endif %} def _get_kwargs( @@ -58,10 +60,10 @@ def _get_kwargs( {% elif endpoint.json_body %} "json": {{ "json_" + endpoint.json_body.python_name }}, {% endif %} #} - {% if endpoint.json_body %} + {% if endpoint.form_body_class %} "json": form_data.to_dict(), - {% elif endpoint.form_body_class %} - "data": form_data.to_dict(), + {% elif endpoint.json_body %} + "json": {{ "json_" + endpoint.json_body.python_name }}, {% elif endpoint.multipart_body %} "files": {{ "multipart_" + endpoint.multipart_body.python_name }}, {% endif %}