From b8b6477d41121730c8696234e1d9abc76d701519 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 10 Apr 2023 21:26:12 +0300 Subject: [PATCH] SDK: fix urllib3 deprecation warnings (#6002) `HTTPResponse.getheader` and `getheaders` are slated to be removed in urllib3 2.1.0. --- CHANGELOG.md | 5 + cvat-sdk/cvat_sdk/core/downloading.py | 2 +- .../openapi-generator/api_client.mustache | 6 +- .../openapi-generator/exceptions.mustache | 150 ++++++++++++++++++ 4 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 cvat-sdk/gen/templates/openapi-generator/exceptions.mustache diff --git a/CHANGELOG.md b/CHANGELOG.md index a61d11d46cc..532b548f05f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Incorrect calculation of working time in analytics () ======= - Server micro version support check in SDK/CLI () +<<<<<<< HEAD >>>>>>> 0c853b15b (Fix version checks in SDK (#5991)) +======= +- \[SDK\] Compatibility with upcoming urllib 2.1.0 + () +>>>>>>> 2505b314f (SDK: fix urllib3 deprecation warnings (#6002)) ### Security - TDB diff --git a/cvat-sdk/cvat_sdk/core/downloading.py b/cvat-sdk/cvat_sdk/core/downloading.py index a7ba9a1391c..3dc338f1468 100644 --- a/cvat-sdk/cvat_sdk/core/downloading.py +++ b/cvat-sdk/cvat_sdk/core/downloading.py @@ -49,7 +49,7 @@ def download_file( ) with closing(response): try: - file_size = int(response.getheader("Content-Length", 0)) + file_size = int(response.headers.get("Content-Length", 0)) except ValueError: file_size = None diff --git a/cvat-sdk/gen/templates/openapi-generator/api_client.mustache b/cvat-sdk/gen/templates/openapi-generator/api_client.mustache index 2bc4838ff86..436bd26f2d5 100644 --- a/cvat-sdk/gen/templates/openapi-generator/api_client.mustache +++ b/cvat-sdk/gen/templates/openapi-generator/api_client.mustache @@ -283,7 +283,7 @@ class ApiClient(object): return headers def _update_cookies_from_response(self, response: HTTPResponse): - self.cookies.update(SimpleCookie(response.getheader("Set-Cookie"))) + self.cookies.update(SimpleCookie(response.headers.get("Set-Cookie"))) def parameters_to_multipart(self, params, collection_types): """Get parameters as list of tuples, formatting as json if value is collection_types @@ -350,12 +350,12 @@ class ApiClient(object): # handle file downloading # save response body into a tmp file and return the instance - content_disposition = response.getheader("Content-Disposition") + content_disposition = response.headers.get("Content-Disposition") return deserialize_file(response.data, self.configuration, content_disposition=content_disposition) encoding = "utf-8" - content_type = response.getheader('content-type') + content_type = response.headers.get('content-type') if content_type is not None: match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) if match: diff --git a/cvat-sdk/gen/templates/openapi-generator/exceptions.mustache b/cvat-sdk/gen/templates/openapi-generator/exceptions.mustache new file mode 100644 index 00000000000..63344c45440 --- /dev/null +++ b/cvat-sdk/gen/templates/openapi-generator/exceptions.mustache @@ -0,0 +1,150 @@ +{{>partial_header}} + +class OpenApiException(Exception): + """The base exception class for all OpenAPIExceptions""" + + +class ApiTypeError(OpenApiException, TypeError): + def __init__(self, msg, path_to_item=None, valid_classes=None, + key_type=None): + """ Raises an exception for TypeErrors + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list): a list of keys an indices to get to the + current_item + None if unset + valid_classes (tuple): the primitive classes that current item + should be an instance of + None if unset + key_type (bool): False if our value is a value in a dict + True if it is a key in a dict + False if our item is an item in a list + None if unset + """ + self.path_to_item = path_to_item + self.valid_classes = valid_classes + self.key_type = key_type + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiTypeError, self).__init__(full_msg) + + +class ApiValueError(OpenApiException, ValueError): + def __init__(self, msg, path_to_item=None): + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list) the path to the exception in the + received_data dict. None if unset + """ + + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiValueError, self).__init__(full_msg) + + +class ApiAttributeError(OpenApiException, AttributeError): + def __init__(self, msg, path_to_item=None): + """ + Raised when an attribute reference or assignment fails. + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiAttributeError, self).__init__(full_msg) + + +class ApiKeyError(OpenApiException, KeyError): + def __init__(self, msg, path_to_item=None): + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiKeyError, self).__init__(full_msg) + + +class ApiException(OpenApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.headers + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "Status Code: {0}\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message + + +class NotFoundException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(NotFoundException, self).__init__(status, reason, http_resp) + + +class UnauthorizedException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(UnauthorizedException, self).__init__(status, reason, http_resp) + + +class ForbiddenException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(ForbiddenException, self).__init__(status, reason, http_resp) + + +class ServiceException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(ServiceException, self).__init__(status, reason, http_resp) + + +def render_path(path_to_item): + """Returns a string representation of a path""" + result = "" + for pth in path_to_item: + if isinstance(pth, int): + result += "[{0}]".format(pth) + else: + result += "['{0}']".format(pth) + return result