[python-experimental] Raise builtin AttributeError instead of custom ApiKeyError (#6229)

* Use AttributeError instead of ApiKeyError because that's what the hasattr builtin function uses

* Use AttributeError instead of ApiKeyError because that's what the hasattr builtin function uses

* fix unit tests

* create ApiAttributeError exception

* fix formatting

* run samples scripts
This commit is contained in:
Sebastien Rosset 2020-05-10 19:02:41 -07:00 committed by GitHub
parent 44b51a136f
commit fa37a696a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 237 additions and 55 deletions

View File

@ -18,6 +18,7 @@ from {{packageName}}.exceptions import OpenApiException
from {{packageName}}.exceptions import ApiTypeError
from {{packageName}}.exceptions import ApiValueError
from {{packageName}}.exceptions import ApiKeyError
from {{packageName}}.exceptions import ApiAttributeError
from {{packageName}}.exceptions import ApiException
# import models into sdk package
{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}

View File

@ -56,6 +56,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""

View File

@ -9,8 +9,9 @@
if name in self.openapi_types:
required_types_mixed = self.openapi_types[name]
elif self.additional_properties_type is None:
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
elif self.additional_properties_type is not None:

View File

@ -24,8 +24,9 @@
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
@ -54,8 +55,9 @@
values.append(v)
len_values = len(values)
if len_values == 0:
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
elif len_values == 1:

View File

@ -18,7 +18,8 @@
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
[name]
)

View File

@ -14,6 +14,7 @@ import six
from {{packageName}}.exceptions import (
ApiKeyError,
ApiAttributeError,
ApiTypeError,
ApiValueError,
)

View File

@ -31,6 +31,7 @@ from petstore_api.exceptions import OpenApiException
from petstore_api.exceptions import ApiTypeError
from petstore_api.exceptions import ApiValueError
from petstore_api.exceptions import ApiKeyError
from petstore_api.exceptions import ApiAttributeError
from petstore_api.exceptions import ApiException
# import models into sdk package
from petstore_api.models.additional_properties_any_type import AdditionalPropertiesAnyType

View File

@ -64,6 +64,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""

View File

@ -64,6 +64,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""

View File

@ -22,6 +22,7 @@ import six
from petstore_api.exceptions import (
ApiKeyError,
ApiAttributeError,
ApiTypeError,
ApiValueError,
)
@ -75,8 +76,9 @@ class OpenApiModel(object):
if name in self.openapi_types:
required_types_mixed = self.openapi_types[name]
elif self.additional_properties_type is None:
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
elif self.additional_properties_type is not None:
@ -204,8 +206,9 @@ class ModelSimple(OpenApiModel):
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
[name]
)
@ -257,8 +260,9 @@ class ModelNormal(OpenApiModel):
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
[name]
)
@ -323,8 +327,9 @@ class ModelComposed(OpenApiModel):
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
@ -353,8 +358,9 @@ class ModelComposed(OpenApiModel):
values.append(v)
len_values = len(values)
if len_values == 0:
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
elif len_values == 1:

View File

@ -64,19 +64,24 @@ class TestChild(unittest.TestCase):
# setting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
child['invalid_variable'] = 'some value'
# with setattr
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
setattr(child, 'invalid_variable', 'some value')
# with hasattr
self.assertFalse(hasattr(child, 'invalid_variable'))
# getting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
invalid_variable = child['invalid_variable']
# with getattr
with self.assertRaises(petstore_api.ApiKeyError):
invalid_variable = getattr(child, 'invalid_variable', 'some value')
self.assertEquals(getattr(child, 'invalid_variable', 'some value'), 'some value')
with self.assertRaises(AttributeError):
invalid_variable = getattr(child, 'invalid_variable')
# make sure that the ModelComposed class properties are correct
# model.composed_schemas() stores the anyOf/allOf/oneOf info

View File

@ -64,19 +64,21 @@ class TestDog(unittest.TestCase):
# setting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
dog['invalid_variable'] = 'some value'
# with setattr
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
setattr(dog, 'invalid_variable', 'some value')
# getting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
invalid_variable = dog['invalid_variable']
# with getattr
with self.assertRaises(petstore_api.ApiKeyError):
invalid_variable = getattr(dog, 'invalid_variable', 'some value')
self.assertEquals(getattr(dog, 'invalid_variable', 'some value'), 'some value')
with self.assertRaises(AttributeError):
invalid_variable = getattr(dog, 'invalid_variable')
# make sure that the ModelComposed class properties are correct
# model.composed_schemas() stores the anyOf/allOf/oneOf info

View File

@ -30,7 +30,7 @@ class EnumArraysTests(unittest.TestCase):
fish_or_crab = petstore_api.EnumArrays(just_symbol=">=")
self.assertEqual(fish_or_crab.just_symbol, ">=")
# if optional property is unset we raise an exception
with self.assertRaises(ApiKeyError) as exc:
with self.assertRaises(AttributeError) as exc:
self.assertEqual(fish_or_crab.array_enum, None)
fish_or_crab = petstore_api.EnumArrays(just_symbol="$", array_enum=["fish"])
@ -152,4 +152,4 @@ class EnumArraysTests(unittest.TestCase):
dollar = petstore_api.EnumArrays(just_symbol="$")
greater = petstore_api.EnumArrays(just_symbol=">=")
self.assertNotEqual(dollar, greater)
self.assertNotEqual(dollar, greater)

View File

@ -31,6 +31,7 @@ from petstore_api.exceptions import OpenApiException
from petstore_api.exceptions import ApiTypeError
from petstore_api.exceptions import ApiValueError
from petstore_api.exceptions import ApiKeyError
from petstore_api.exceptions import ApiAttributeError
from petstore_api.exceptions import ApiException
# import models into sdk package
from petstore_api.models.additional_properties_any_type import AdditionalPropertiesAnyType

View File

@ -64,6 +64,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""

View File

@ -31,6 +31,7 @@ from petstore_api.exceptions import OpenApiException
from petstore_api.exceptions import ApiTypeError
from petstore_api.exceptions import ApiValueError
from petstore_api.exceptions import ApiKeyError
from petstore_api.exceptions import ApiAttributeError
from petstore_api.exceptions import ApiException
# import models into sdk package
from petstore_api.models.additional_properties_any_type import AdditionalPropertiesAnyType

View File

@ -64,6 +64,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""

View File

@ -64,6 +64,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""

View File

@ -22,6 +22,7 @@ import six
from petstore_api.exceptions import (
ApiKeyError,
ApiAttributeError,
ApiTypeError,
ApiValueError,
)
@ -75,8 +76,9 @@ class OpenApiModel(object):
if name in self.openapi_types:
required_types_mixed = self.openapi_types[name]
elif self.additional_properties_type is None:
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
elif self.additional_properties_type is not None:
@ -204,8 +206,9 @@ class ModelSimple(OpenApiModel):
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
[name]
)
@ -257,8 +260,9 @@ class ModelNormal(OpenApiModel):
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
[name]
)
@ -323,8 +327,9 @@ class ModelComposed(OpenApiModel):
if self._path_to_item:
path_to_item.extend(self._path_to_item)
path_to_item.append(name)
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
@ -353,8 +358,9 @@ class ModelComposed(OpenApiModel):
values.append(v)
len_values = len(values)
if len_values == 0:
raise ApiKeyError(
"{0} has no key '{1}'".format(type(self).__name__, name),
raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
path_to_item
)
elif len_values == 1:

View File

@ -51,19 +51,35 @@ class TestFruit(unittest.TestCase):
)
# setting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
fruit['invalid_variable'] = 'some value'
# Assert that we can call the builtin hasattr() function.
# hasattr should return False for non-existent attribute.
# Internally hasattr catches the AttributeError exception.
self.assertFalse(hasattr(fruit, 'invalid_variable'))
# Assert that we can call the builtin hasattr() function.
# hasattr should return True for existent attribute.
self.assertTrue(hasattr(fruit, 'color'))
# with setattr
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
setattr(fruit, 'invalid_variable', 'some value')
# getting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
invalid_variable = fruit['cultivar']
# with getattr
with self.assertRaises(petstore_api.ApiKeyError):
invalid_variable = getattr(fruit, 'cultivar', 'some value')
# Per Python doc, if the named attribute does not exist,
# default is returned if provided.
self.assertEquals(getattr(fruit, 'cultivar', 'some value'), 'some value')
# Per Python doc, if the named attribute does not exist,
# default is returned if provided, otherwise AttributeError is raised.
with self.assertRaises(AttributeError):
getattr(fruit, 'cultivar')
# make sure that the ModelComposed class properties are correct
# model._composed_schemas stores the anyOf/allOf/oneOf info

View File

@ -46,19 +46,21 @@ class TestFruitReq(unittest.TestCase):
)
# setting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
fruit['invalid_variable'] = 'some value'
# with setattr
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
setattr(fruit, 'invalid_variable', 'some value')
# getting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
invalid_variable = fruit['cultivar']
# with getattr
with self.assertRaises(petstore_api.ApiKeyError):
invalid_variable = getattr(fruit, 'cultivar', 'some value')
self.assertEquals(getattr(fruit, 'cultivar', 'some value'), 'some value')
with self.assertRaises(AttributeError):
getattr(fruit, 'cultivar')
# make sure that the ModelComposed class properties are correct
# model._composed_schemas stores the anyOf/allOf/oneOf info

View File

@ -51,19 +51,21 @@ class TestGmFruit(unittest.TestCase):
)
# setting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
fruit['invalid_variable'] = 'some value'
# with setattr
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
setattr(fruit, 'invalid_variable', 'some value')
# getting a value that doesn't exist raises an exception
# with a key
with self.assertRaises(petstore_api.ApiKeyError):
with self.assertRaises(AttributeError):
invalid_variable = fruit['cultivar']
# with getattr
with self.assertRaises(petstore_api.ApiKeyError):
invalid_variable = getattr(fruit, 'cultivar', 'some value')
self.assertTrue(getattr(fruit, 'cultivar', 'some value'), 'some value')
with self.assertRaises(AttributeError):
invalid_variable = getattr(fruit, 'cultivar')
# make sure that the ModelComposed class properties are correct
# model._composed_schemas stores the anyOf/allOf/oneOf info

View File

@ -32,6 +32,7 @@ from petstore_api.exceptions import OpenApiException
from petstore_api.exceptions import ApiTypeError
from petstore_api.exceptions import ApiValueError
from petstore_api.exceptions import ApiKeyError
from petstore_api.exceptions import ApiAttributeError
from petstore_api.exceptions import ApiException
# import models into sdk package
from petstore_api.models.additional_properties_class import AdditionalPropertiesClass

View File

@ -64,6 +64,25 @@ class ApiValueError(OpenApiException, ValueError):
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):
"""