laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/42043?usp=email )
Change subject: esim/http_json_api: add alternative API interface ......................................................................
esim/http_json_api: add alternative API interface
unfortunately the API changes introduced in change
I277aa90fddb5171c4bf6c3436259aa371d30d092
broke the API interface of http_json_api.py. This was taken into account and necessary to introduce add the server functionality next to the already existing client functionality. The changes to the API were minimal and all code locations that use http_json_api.py were re-aligned.
Unfortunately it was not clear at this point in time that there are out-of-tree projects that could be affected by API changes in http_json_api.py
To mitigate the problem this patch introduces an alternative API interface to the JsonHttpApiFunction base class. This alternative API interface works like the old API interface when the class is instantiated in the original way. To make use of the revised client the API use has to pass an additional keyword argument that defines the role.
Related: SYS#7866 Change-Id: I2a5d4b59b12e08d5eae7a1215814d3a69c8921f6 --- M pySim/esim/http_json_api.py 1 file changed, 51 insertions(+), 3 deletions(-)
Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified
diff --git a/pySim/esim/http_json_api.py b/pySim/esim/http_json_api.py index 28022ff..94e60cb 100644 --- a/pySim/esim/http_json_api.py +++ b/pySim/esim/http_json_api.py @@ -19,6 +19,7 @@ import requests import logging import json +from re import match from typing import Optional import base64 from twisted.web.server import Request @@ -210,18 +211,65 @@ # additional custom HTTP headers (server responses) extra_http_res_headers = {}
+ def __new__(cls, *args, role = None, **kwargs): + """ + Args: + args: (see JsonHttpApiClient and JsonHttpApiServer) + role: role ('server' or 'client') in which the JsonHttpApiFunction should be created. + kwargs: (see JsonHttpApiClient and JsonHttpApiServer) + """ + + # Create a dictionary with the class attributes of this class (the properties listed above and the encode_ + # decode_ methods below). The dictionary will not include any dunder/magic methods + cls_attr = { attr_name: getattr(cls, attr_name) for attr_name in dir(cls) if not match("__.*__", attr_name) } + + # Normal instantiation as JsonHttpApiFunction: + if len(args) == 0: + return type(cls.__name__, (abc.ABC,), cls_attr)() + + # Instantiation as as JsonHttpApiFunction with a JsonHttpApiClient or JsonHttpApiServer base + role = kwargs.get('role', 'legacy_client') + if role == 'legacy_client': + # Deprecated: With the advent of the server role (JsonHttpApiServer) the API had to be changed. To maintain + # compatibility with existing code (out-of-tree) the original behaviour and API interface and behaviour had + # to be preserved. Already existing JsonHttpApiFunction definitions will still work and the related objects + # may still be created on the original way: my_api_func = MyApiFunc(url_prefix, func_req_id, self.session) + logger.warning('implicit role (falling back to legacy JsonHttpApiClient) is deprecated, please specify role explcitly') + result = type(cls.__name__, (JsonHttpApiClient,), cls_attr)(None, *args, **kwargs) + result.api_func = result + result.legacy = True + return result + elif role == 'client': + # Create a JsonHttpApiFunction in client role + # Example: my_api_func = MyApiFunc(url_prefix, func_req_id, self.session, role='client') + result = type(cls.__name__, (JsonHttpApiClient,), cls_attr)(None, *args, **kwargs) + result.api_func = result + return result + elif role == 'server': + # Create a JsonHttpApiFunction in server role + # Example: my_api_func = MyApiFunc(url_prefix, func_req_id, self.session, role='server') + result = type(cls.__name__, (JsonHttpApiServer,), cls_attr)(None, *args, **kwargs) + result.api_func = result + return result + else: + raise ValueError('Invalid role '%s' specified' % role) + def encode_client(self, data: dict) -> dict: """Validate an encode input dict into JSON-serializable dict for request body.""" output = {} - for p in self.input_mandatory: if not p in data: raise ValueError('Mandatory input parameter %s missing' % p) for p, v in data.items(): p_class = self.input_params.get(p) if not p_class: - logger.warning('Unexpected/unsupported input parameter %s=%s', p, v) - output[p] = v + # pySim/esim/http_json_api.py:269:47: E1101: Instance of 'JsonHttpApiFunction' has no 'legacy' member (no-member) + # pylint: disable=no-member + if hasattr(self, 'legacy') and self.legacy: + output[p] = JsonRequestHeader.encode(v) + else: + logger.warning('Unexpected/unsupported input parameter %s=%s', p, v) + output[p] = v else: output[p] = p_class.encode(v) return output