diff --git a/openprocurement_client/clients.py b/openprocurement_client/clients.py index 4478d3d..039c375 100755 --- a/openprocurement_client/clients.py +++ b/openprocurement_client/clients.py @@ -87,7 +87,13 @@ def _get_resource_item(self, url, headers=None): _headers.update(headers or {}) response_item = self.request('GET', url, headers=_headers) if response_item.status_code == 200: - return munchify(loads(response_item.text)) + data = loads(response_item.text) + if hasattr(response_item, "headers") and response_item.headers is not None: + if "x-revision-n" in response_item.headers: + data["x_revision_n"] = response_item.headers["x-revision-n"] + if "x-revision-date" in response_item.headers: + data["x_revision_date"] = response_item.headers["x-revision-date"] + return munchify(data) raise InvalidResponse(response_item) @retry(stop_max_attempt_number=5) @@ -177,6 +183,13 @@ def get_resource_item(self, id, headers=None): "from 'openprocurement_client.clients'.") return self._get_resource_item('{}/{}'.format(self.prefix_path, id), headers=headers) + def get_resource_item_historical(self, id, revision="", date="", headers=None): + if headers is None: + headers = {} + headers["x-revision-n"] = str(revision) + headers["x-revision-date"] = str(date) + return self._get_resource_item('{}/{}/historical'.format(self.prefix_path, id), headers=headers) + def patch_credentials(self, id, access_token): LOGGER.warn("'pat' method is deprecated use APIResoucreClient.pat from " "from 'openprocurement_client.clients'.") diff --git a/openprocurement_client/tests/main.py b/openprocurement_client/tests/main.py index a6e892f..dc83d2d 100644 --- a/openprocurement_client/tests/main.py +++ b/openprocurement_client/tests/main.py @@ -3,7 +3,8 @@ from openprocurement_client.tests import ( tests_resources, tests_sync, - test_registry_client + test_registry_client, + test_api_base_client ) @@ -12,6 +13,7 @@ def suite(): suite.addTest(tests_sync.suite()) suite.addTest(test_registry_client.suite()) suite.addTest(tests_resources.suite()) + suite.addTest(test_api_base_client.suite()) return suite diff --git a/openprocurement_client/tests/test_api_base_client.py b/openprocurement_client/tests/test_api_base_client.py new file mode 100644 index 0000000..7765317 --- /dev/null +++ b/openprocurement_client/tests/test_api_base_client.py @@ -0,0 +1,65 @@ +import unittest +import uuid +import mock +from json import dumps +from copy import deepcopy + +from openprocurement_client.exceptions import InvalidResponse +from test_registry_client import BaseTestClass +from openprocurement_client.clients import APIBaseClient + + +class APIBaseClientTestCase(BaseTestClass): + def setUp(self): + self.setting_up(client=APIBaseClient) + + def test_get_resource_item_historical(self): + class Response(object): + def __init__(self, status_code, text=None, headers=None): + self.status_code = status_code + self.text = text + self.headers = headers + + revisions_limit = 42 + response_text = { + "id": uuid.uuid4().hex, + "rev": 24 + } + + side_effect = [ + Response(200, dumps(response_text), {"x-revision-n": str(revisions_limit)}), + Response(200, dumps(response_text), {"x-revision-n": str(revisions_limit)}), + Response(200, dumps(response_text), {"x-revision-n": str(revisions_limit - 1)}), + Response(404), + Response(404), + Response(404), + ] + + self.client.request = mock.MagicMock(side_effect=side_effect) + + actual_response = deepcopy(response_text) + actual_response["x_revision_n"] = str(revisions_limit) + item_id = response_text["id"] + self.assertEqual(self.client.get_resource_item_historical(item_id, revision=""), actual_response) + self.assertEqual(self.client.get_resource_item_historical(item_id, revision=revisions_limit), actual_response) + actual_response["x_revision_n"] = str(revisions_limit - 1) + self.assertEqual(self.client.get_resource_item_historical( + item_id, revision=revisions_limit - 1), actual_response) + + for revision in (0, revisions_limit + 1, None): + with self.assertRaises(InvalidResponse) as e: + self.client.get_resource_item_historical(item_id, revision=revision) + self.assertEqual(e.exception.status_code, 404) + + def tearDown(self): + self.server.stop() + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(APIBaseClientTestCase)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='suite')