diff --git a/pyms/flask/services/requests.py b/pyms/flask/services/requests.py index f0de651..27ee419 100644 --- a/pyms/flask/services/requests.py +++ b/pyms/flask/services/requests.py @@ -271,6 +271,50 @@ def put_for_object(self, url, path_params=None, data=None, headers=None, **kwarg response = self.put(url, path_params=path_params, data=data, headers=headers, **kwargs) return self.parse_response(response) + @retry + def patch(self, url, path_params=None, data=None, headers=None, **kwargs): + """Sends a PATCH request. + + :param url: URL for the new :class:`Request` object. Could contain path parameters + :param path_params: (optional) Dictionary, list of tuples with path parameters values to compose url + :param data: (optional) Dictionary, list of tuples, bytes, or file-like + object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. + :param kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response ` object + :rtype: requests.Response + """ + + full_url = self._build_url(url, path_params) + headers = self._get_headers(headers) + headers = self.insert_trace_headers(headers) + logger.debug("Patch with url {}, data {}, headers {}, kwargs {}".format(full_url, data, headers, + kwargs)) + + session = requests.Session() + response = self.requests(session=session).patch(full_url, data, headers=headers, **kwargs) + logger.debug("Response {}".format(response)) + + return response + + def patch_for_object(self, url, path_params=None, data=None, headers=None, **kwargs): + """Sends a PATCH request and returns the json representation found in response's content data node. + + :param url: URL for the new :class:`Request` object. Could contain path parameters + :param path_params: (optional) Dictionary, list of tuples with path parameters values to compose url + :param data: (optional) Dictionary, list of tuples, bytes, or file-like + object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. + :param kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response ` object + :rtype: requests.Response + """ + + response = self.patch(url, path_params=path_params, data=data, headers=headers, **kwargs) + return self.parse_response(response) + @retry def delete(self, url, path_params=None, headers=None, **kwargs): """Sends a DELETE request. diff --git a/tests/test_requests.py b/tests/test_requests.py index 914e2d8..e9202be 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -222,6 +222,65 @@ def test_put_for_object_with_valid_data(self, mock_request): self.assertEqual(expected, response) + @requests_mock.Mocker() + def test_patch(self, mock_request): + url = "http://www.my-site.com/users/{user-id}" + path_params = {'user-id': 123} + full_url = "http://www.my-site.com/users/123" + user = {'name': 'Peter', 'email': 'peter@my-site.com'} + text = json.dumps({'data': {'id': 123, 'name': 'Peter', 'email': 'peter@my-site.com'}}) + + with self.app.app_context(): + mock_request.patch(full_url, text=text, status_code=200) + response = self.request.patch(url, path_params, json=user) + + self.assertEqual(200, response.status_code) + self.assertEqual(text, response.text) + + @requests_mock.Mocker() + def test_patch_for_object_without_json(self, mock_request): + url = "http://www.my-site.com/users/{user-id}" + path_params = {'user-id': 123} + full_url = "http://www.my-site.com/users/123" + user = {'name': 'Peter', 'email': 'peter@my-site.com'} + expected = {} + + with self.app.app_context(): + mock_request.patch(full_url, status_code=200) + response = self.request.patch_for_object(url, path_params, json=user) + + self.assertEqual(expected, response) + + @requests_mock.Mocker() + def test_patch_for_object_without_valid_json_data(self, mock_request): + url = "http://www.my-site.com/users/{user-id}" + path_params = {'user-id': 123} + full_url = "http://www.my-site.com/users/123" + user = {'name': 'Peter', 'email': 'peter@my-site.com'} + text = json.dumps({'another_data': {'id': 123, 'name': 'Peter', 'email': 'peter@my-site.com.com'}}) + expected = {} + + with self.app.app_context(): + mock_request.patch(full_url, text=text, status_code=200) + response = self.request.patch_for_object(url, path_params, json=user) + + self.assertEqual(expected, response) + + @requests_mock.Mocker() + def test_patch_for_object_with_valid_data(self, mock_request): + url = "http://www.my-site.com/users/{user-id}" + path_params = {'user-id': 123} + full_url = "http://www.my-site.com/users/123" + user = {'name': 'Peter', 'email': 'peter@my-site.com'} + text = json.dumps({'data': {'id': 123, 'name': 'Peter', 'email': 'peter@my-site.com.com'}}) + expected = {'id': 123, 'name': 'Peter', 'email': 'peter@my-site.com.com'} + + with self.app.app_context(): + mock_request.patch(full_url, text=text, status_code=200) + response = self.request.patch_for_object(url, path_params, json=user) + + self.assertEqual(expected, response) + @requests_mock.Mocker() def test_delete(self, mock_request): url = "http://www.my-site.com/users/{user-id}"