forked from loafle/openapi-generator-original
[python-experimental] Improve error message for regex matching, add unit tests. (#6226)
* Improve error message * Add unit tests for regular expressions
This commit is contained in:
@@ -405,14 +405,15 @@ def check_validations(validations, input_variable_path, input_values):
|
||||
if ('regex' in current_validations and
|
||||
not re.search(current_validations['regex']['pattern'],
|
||||
input_values, flags=flags)):
|
||||
raise ApiValueError(
|
||||
r"Invalid value for `%s`, must be a follow pattern or equal to "
|
||||
r"`%s` with flags=`%s`" % (
|
||||
input_variable_path[0],
|
||||
current_validations['regex']['pattern'],
|
||||
flags
|
||||
)
|
||||
)
|
||||
err_msg = r"Invalid value for `%s`, must match regular expression `%s`" % (
|
||||
input_variable_path[0],
|
||||
current_validations['regex']['pattern']
|
||||
)
|
||||
if flags != 0:
|
||||
# Don't print the regex flags if the flags are not
|
||||
# specified in the OAS document.
|
||||
err_msg = r"%s with flags=`%s`" % (err_msg, flags)
|
||||
raise ApiValueError(err_msg)
|
||||
|
||||
|
||||
def order_response_types(required_types):
|
||||
|
||||
@@ -1808,6 +1808,10 @@ components:
|
||||
properties:
|
||||
cultivar:
|
||||
type: string
|
||||
pattern: ^[a-zA-Z\s]*$
|
||||
origin:
|
||||
type: string
|
||||
pattern: /^[A-Z\s]*$/i
|
||||
banana:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -671,14 +671,15 @@ def check_validations(validations, input_variable_path, input_values):
|
||||
if ('regex' in current_validations and
|
||||
not re.search(current_validations['regex']['pattern'],
|
||||
input_values, flags=flags)):
|
||||
raise ApiValueError(
|
||||
r"Invalid value for `%s`, must be a follow pattern or equal to "
|
||||
r"`%s` with flags=`%s`" % (
|
||||
input_variable_path[0],
|
||||
current_validations['regex']['pattern'],
|
||||
flags
|
||||
)
|
||||
)
|
||||
err_msg = r"Invalid value for `%s`, must match regular expression `%s`" % (
|
||||
input_variable_path[0],
|
||||
current_validations['regex']['pattern']
|
||||
)
|
||||
if flags != 0:
|
||||
# Don't print the regex flags if the flags are not
|
||||
# specified in the OAS document.
|
||||
err_msg = r"%s with flags=`%s`" % (err_msg, flags)
|
||||
raise ApiValueError(err_msg)
|
||||
|
||||
|
||||
def order_response_types(required_types):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**cultivar** | **str** | | [optional]
|
||||
**origin** | **str** | | [optional]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**color** | **str** | | [optional]
|
||||
**cultivar** | **str** | | [optional]
|
||||
**origin** | **str** | | [optional]
|
||||
**length_cm** | **float** | | [optional]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
@@ -5,6 +5,7 @@ Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**color** | **str** | | [optional]
|
||||
**cultivar** | **str** | | [optional]
|
||||
**origin** | **str** | | [optional]
|
||||
**length_cm** | **float** | | [optional]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
@@ -671,14 +671,15 @@ def check_validations(validations, input_variable_path, input_values):
|
||||
if ('regex' in current_validations and
|
||||
not re.search(current_validations['regex']['pattern'],
|
||||
input_values, flags=flags)):
|
||||
raise ApiValueError(
|
||||
r"Invalid value for `%s`, must be a follow pattern or equal to "
|
||||
r"`%s` with flags=`%s`" % (
|
||||
input_variable_path[0],
|
||||
current_validations['regex']['pattern'],
|
||||
flags
|
||||
)
|
||||
)
|
||||
err_msg = r"Invalid value for `%s`, must match regular expression `%s`" % (
|
||||
input_variable_path[0],
|
||||
current_validations['regex']['pattern']
|
||||
)
|
||||
if flags != 0:
|
||||
# Don't print the regex flags if the flags are not
|
||||
# specified in the OAS document.
|
||||
err_msg = r"%s with flags=`%s`" % (err_msg, flags)
|
||||
raise ApiValueError(err_msg)
|
||||
|
||||
|
||||
def order_response_types(required_types):
|
||||
|
||||
@@ -62,6 +62,17 @@ class Apple(ModelNormal):
|
||||
}
|
||||
|
||||
validations = {
|
||||
('cultivar',): {
|
||||
'regex': {
|
||||
'pattern': r'^[a-zA-Z\s]*$', # noqa: E501
|
||||
},
|
||||
},
|
||||
('origin',): {
|
||||
'regex': {
|
||||
'pattern': r'^[A-Z\s]*$', # noqa: E501
|
||||
'flags': (re.IGNORECASE)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
additional_properties_type = None
|
||||
@@ -78,6 +89,7 @@ class Apple(ModelNormal):
|
||||
"""
|
||||
return {
|
||||
'cultivar': (str,), # noqa: E501
|
||||
'origin': (str,), # noqa: E501
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@@ -86,6 +98,7 @@ class Apple(ModelNormal):
|
||||
|
||||
attribute_map = {
|
||||
'cultivar': 'cultivar', # noqa: E501
|
||||
'origin': 'origin', # noqa: E501
|
||||
}
|
||||
|
||||
_composed_schemas = {}
|
||||
@@ -133,6 +146,7 @@ class Apple(ModelNormal):
|
||||
through its discriminator because we passed in
|
||||
_visited_composed_classes = (Animal,)
|
||||
cultivar (str): [optional] # noqa: E501
|
||||
origin (str): [optional] # noqa: E501
|
||||
"""
|
||||
|
||||
self._data_store = {}
|
||||
|
||||
@@ -72,6 +72,17 @@ class Fruit(ModelComposed):
|
||||
}
|
||||
|
||||
validations = {
|
||||
('cultivar',): {
|
||||
'regex': {
|
||||
'pattern': r'^[a-zA-Z\s]*$', # noqa: E501
|
||||
},
|
||||
},
|
||||
('origin',): {
|
||||
'regex': {
|
||||
'pattern': r'^[A-Z\s]*$', # noqa: E501
|
||||
'flags': (re.IGNORECASE)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
additional_properties_type = None
|
||||
@@ -89,6 +100,7 @@ class Fruit(ModelComposed):
|
||||
return {
|
||||
'color': (str,), # noqa: E501
|
||||
'cultivar': (str,), # noqa: E501
|
||||
'origin': (str,), # noqa: E501
|
||||
'length_cm': (float,), # noqa: E501
|
||||
}
|
||||
|
||||
@@ -99,6 +111,7 @@ class Fruit(ModelComposed):
|
||||
attribute_map = {
|
||||
'color': 'color', # noqa: E501
|
||||
'cultivar': 'cultivar', # noqa: E501
|
||||
'origin': 'origin', # noqa: E501
|
||||
'length_cm': 'lengthCm', # noqa: E501
|
||||
}
|
||||
|
||||
@@ -149,6 +162,7 @@ class Fruit(ModelComposed):
|
||||
_visited_composed_classes = (Animal,)
|
||||
color (str): [optional] # noqa: E501
|
||||
cultivar (str): [optional] # noqa: E501
|
||||
origin (str): [optional] # noqa: E501
|
||||
length_cm (float): [optional] # noqa: E501
|
||||
"""
|
||||
|
||||
|
||||
@@ -72,6 +72,17 @@ class GmFruit(ModelComposed):
|
||||
}
|
||||
|
||||
validations = {
|
||||
('cultivar',): {
|
||||
'regex': {
|
||||
'pattern': r'^[a-zA-Z\s]*$', # noqa: E501
|
||||
},
|
||||
},
|
||||
('origin',): {
|
||||
'regex': {
|
||||
'pattern': r'^[A-Z\s]*$', # noqa: E501
|
||||
'flags': (re.IGNORECASE)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
additional_properties_type = None
|
||||
@@ -89,6 +100,7 @@ class GmFruit(ModelComposed):
|
||||
return {
|
||||
'color': (str,), # noqa: E501
|
||||
'cultivar': (str,), # noqa: E501
|
||||
'origin': (str,), # noqa: E501
|
||||
'length_cm': (float,), # noqa: E501
|
||||
}
|
||||
|
||||
@@ -99,6 +111,7 @@ class GmFruit(ModelComposed):
|
||||
attribute_map = {
|
||||
'color': 'color', # noqa: E501
|
||||
'cultivar': 'cultivar', # noqa: E501
|
||||
'origin': 'origin', # noqa: E501
|
||||
'length_cm': 'lengthCm', # noqa: E501
|
||||
}
|
||||
|
||||
@@ -149,6 +162,7 @@ class GmFruit(ModelComposed):
|
||||
_visited_composed_classes = (Animal,)
|
||||
color (str): [optional] # noqa: E501
|
||||
cultivar (str): [optional] # noqa: E501
|
||||
origin (str): [optional] # noqa: E501
|
||||
length_cm (float): [optional] # noqa: E501
|
||||
"""
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ class TestFruit(unittest.TestCase):
|
||||
'color': [fruit],
|
||||
'length_cm': [fruit, banana_instance],
|
||||
'cultivar': [fruit],
|
||||
'origin': [fruit],
|
||||
}
|
||||
)
|
||||
# model._additional_properties_model_instances stores a list of
|
||||
@@ -179,6 +180,7 @@ class TestFruit(unittest.TestCase):
|
||||
'color': [fruit],
|
||||
'length_cm': [fruit],
|
||||
'cultivar': [fruit, apple_instance],
|
||||
'origin': [fruit, apple_instance],
|
||||
}
|
||||
)
|
||||
# model._additional_properties_model_instances stores a list of
|
||||
|
||||
@@ -97,6 +97,7 @@ class TestGmFruit(unittest.TestCase):
|
||||
'color': [fruit],
|
||||
'length_cm': [fruit, banana_instance],
|
||||
'cultivar': [fruit],
|
||||
'origin': [fruit],
|
||||
}
|
||||
)
|
||||
# model._additional_properties_model_instances stores a list of
|
||||
@@ -157,6 +158,7 @@ class TestGmFruit(unittest.TestCase):
|
||||
'color': [fruit],
|
||||
'length_cm': [fruit, banana_instance],
|
||||
'cultivar': [fruit, apple_instance],
|
||||
'origin': [fruit, apple_instance],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -164,7 +166,8 @@ class TestGmFruit(unittest.TestCase):
|
||||
# apple test
|
||||
color = 'red'
|
||||
cultivar = 'golden delicious'
|
||||
fruit = petstore_api.GmFruit(color=color, cultivar=cultivar)
|
||||
origin = 'California'
|
||||
fruit = petstore_api.GmFruit(color=color, cultivar=cultivar, origin=origin)
|
||||
# check its properties
|
||||
self.assertEqual(fruit.color, color)
|
||||
self.assertEqual(fruit['color'], color)
|
||||
@@ -172,12 +175,18 @@ class TestGmFruit(unittest.TestCase):
|
||||
self.assertEqual(fruit.cultivar, cultivar)
|
||||
self.assertEqual(fruit['cultivar'], cultivar)
|
||||
self.assertEqual(getattr(fruit, 'cultivar'), cultivar)
|
||||
|
||||
self.assertEqual(fruit.origin, origin)
|
||||
self.assertEqual(fruit['origin'], origin)
|
||||
self.assertEqual(getattr(fruit, 'origin'), origin)
|
||||
|
||||
# check the dict representation
|
||||
self.assertEqual(
|
||||
fruit.to_dict(),
|
||||
{
|
||||
'color': color,
|
||||
'cultivar': cultivar
|
||||
'cultivar': cultivar,
|
||||
'origin': origin,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -198,6 +207,7 @@ class TestGmFruit(unittest.TestCase):
|
||||
'color': [fruit],
|
||||
'length_cm': [fruit],
|
||||
'cultivar': [fruit, apple_instance],
|
||||
'origin': [fruit, apple_instance],
|
||||
}
|
||||
)
|
||||
# model._additional_properties_model_instances stores a list of
|
||||
|
||||
@@ -92,6 +92,41 @@ class DeserializationTests(unittest.TestCase):
|
||||
self.assertEqual(deserialized.color, color)
|
||||
self.assertEqual(deserialized.breed, breed)
|
||||
|
||||
def test_regex_constraint(self):
|
||||
"""
|
||||
Test regex pattern validation.
|
||||
"""
|
||||
|
||||
# Test with valid regex pattern.
|
||||
inst = petstore_api.Apple(
|
||||
cultivar="Akane"
|
||||
)
|
||||
assert isinstance(inst, petstore_api.Apple)
|
||||
|
||||
inst = petstore_api.Apple(
|
||||
origin="cHiLe"
|
||||
)
|
||||
assert isinstance(inst, petstore_api.Apple)
|
||||
|
||||
# Test with invalid regex pattern.
|
||||
err_msg = ("Invalid value for `{}`, must match regular expression `{}`$")
|
||||
with self.assertRaisesRegexp(
|
||||
petstore_api.ApiValueError,
|
||||
err_msg.format("cultivar", "[^`]*")
|
||||
):
|
||||
inst = petstore_api.Apple(
|
||||
cultivar="!@#%@$#Akane"
|
||||
)
|
||||
|
||||
err_msg = ("Invalid value for `{}`, must match regular expression `{}` with flags")
|
||||
with self.assertRaisesRegexp(
|
||||
petstore_api.ApiValueError,
|
||||
err_msg.format("origin", "[^`]*")
|
||||
):
|
||||
inst = petstore_api.Apple(
|
||||
origin="!@#%@$#Chile"
|
||||
)
|
||||
|
||||
def test_deserialize_mammal(self):
|
||||
"""
|
||||
deserialize mammal
|
||||
@@ -125,4 +160,4 @@ class DeserializationTests(unittest.TestCase):
|
||||
deserialized = self.deserialize(response, (petstore_api.Mammal,), True)
|
||||
self.assertTrue(isinstance(deserialized, petstore_api.Zebra))
|
||||
self.assertEqual(deserialized.type, zebra_type)
|
||||
self.assertEqual(deserialized.class_name, class_name)
|
||||
self.assertEqual(deserialized.class_name, class_name)
|
||||
|
||||
Reference in New Issue
Block a user