diff --git a/CHANGELOG.md b/CHANGELOG.md index 96ece1aa44f9de095d728d182baba1113ca9cee7..e92e0d9ce45664b6883d0efb62805a0ae6ad2006 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 () - Rotation property lost during saving a mutable attribute () - Server micro version support check in SDK/CLI () +- \[SDK\] Compatibility with upcoming urllib 2.1.0 + () ### Security - TDB diff --git a/cvat-sdk/cvat_sdk/core/downloading.py b/cvat-sdk/cvat_sdk/core/downloading.py index a7ba9a1391ca56a1e7f09ac2222591d2d505f46d..3dc338f1468a10727700b4c644f1662d4f0a1403 100644 --- a/cvat-sdk/cvat_sdk/core/downloading.py +++ b/cvat-sdk/cvat_sdk/core/downloading.py @@ -49,7 +49,7 @@ class Downloader: ) 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 2bc4838ff864be73bff22cbaedb13c23c7d202b3..436bd26f2d546c447773279aab03318e9c773ed6 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 0000000000000000000000000000000000000000..63344c45440405a6af7475599cddc639e63a7004 --- /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