From 7806de5f05bbc153b8405f1e693e1ae202e2a54c Mon Sep 17 00:00:00 2001 From: Scott Bahling Date: Wed, 12 Feb 2020 18:38:33 +0100 Subject: Implement sub-api callbackso When an api object makes an API request to the OBS server, in addition to returning the results, it sends a reference to itself to the registered callback function (if set). We use this to track the last api object called so we can access the last raw request response. --- obsapi/core.py | 19 +++++++++++++++++-- obsapi/httpapi.py | 30 +++++++++++++++++++++++++++++- test/test_api.py | 16 ++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/obsapi/core.py b/obsapi/core.py index c81f699..209aab2 100644 --- a/obsapi/core.py +++ b/obsapi/core.py @@ -8,6 +8,7 @@ from obsapi.sourceapi import ObsSourceApi from obsapi.buildapi import ObsBuildApi from obsapi.repoflags import RepoFlags from obsapi.fileinfo import FileInfo +from .null import Null LSItem = namedtuple('LSItem', 'name md5 size mtime') @@ -34,13 +35,27 @@ class ObsApi(object): def __init__(self, apiurl=None): self.apiurl = apiurl or DEFAULTAPIURL + self.lastapi = Null + self._response = Null + + # init the source api self.source = ObsSourceApi(self.apiurl) - self.build = ObsBuildApi(self.apiurl) self.source.retries = 0 self.source.verify_ssl = True + self.source.set_callback(self._api_callback) + + # init the build api + self.build = ObsBuildApi(self.apiurl) self.build.retries = 0 self.build.verify_ssl = True - self.lastapi = None + self.build.set_callback(self._api_callback) + + def _api_callback(self, api_instance): + self.lastapi = api_instance + + @property + def response(self): + return self.lastapi.response def get_meta(self, prj, pkg=None): return self.source.get_meta(prj, pkg=pkg) diff --git a/obsapi/httpapi.py b/obsapi/httpapi.py index db52050..b73b547 100644 --- a/obsapi/httpapi.py +++ b/obsapi/httpapi.py @@ -2,9 +2,11 @@ # import requests import re +import types +from functools import wraps +from obsapi.null import Null from obsapi.logger import logger from requests.auth import HTTPBasicAuth -from .null import Null try: import osc.conf as osc_conf @@ -33,6 +35,29 @@ class ObsHttpApi(object): self._response = Null() self.retries = 0 self.verify_ssl = True + self._callback_function = None + + def _with_callback(func): + @wraps(func) + def wrapper(inst, *args, **kwargs): + r = func(inst, *args, **kwargs) + inst._do_callback() + return r + return wrapper + + def _do_callback(self): + if self._callback_function is not None: + try: + self._callback_function(self) + except Exception as e: + raise e + + def set_callback(self, func): + if isinstance(func, (types.FunctionType, types.MethodType)): + self._callback_function = func + else: + raise ValueError('Callback expects function or method type, ' + 'got {}'.format(type(func))) @property def __auth(self): @@ -57,6 +82,7 @@ class ObsHttpApi(object): return self._auth[self.apiurl] + @_with_callback def __api_get(self, api, params=None): url = '{0}{1}{2}'.format(self.apiurl, self.rootapi, api) @@ -79,6 +105,7 @@ class ObsHttpApi(object): return r + @_with_callback def __api_put(self, api, data, params=None): url = '{0}{1}{2}'.format(self.apiurl, self.rootapi, api) @@ -91,6 +118,7 @@ class ObsHttpApi(object): return r + @_with_callback def __api_post(self, api, data, params=None): url = '{0}{1}{2}'.format(self.apiurl, self.rootapi, api) diff --git a/test/test_api.py b/test/test_api.py index 50afeca..09b2806 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -1,7 +1,9 @@ import re import pytest import os +import requests_mock as rmock from . import test_dir +from obsapi.null import Null from obsapi import ObsApi from lxml import etree try: @@ -202,6 +204,20 @@ def locked_package_meta(): """ +def test_callback(requests_mock): + """ + Test that api callback works and returns a reference to + the sub-api instance + """ + text = '' + requests_mock.get(rmock.ANY, text=text) + assert isinstance(api.lastapi, type(Null)) + api.build.get(prj=prj) + assert api.lastapi is api.build + api.source.get(prj=prj) + assert api.lastapi is api.source + + def test_get_project_meta(requests_mock): matcher = prj_meta_re text = '' -- cgit v1.2.3