Skip to content

Commit

Permalink
Merge "Revert "Generate better validation error message when using na…
Browse files Browse the repository at this point in the history
…me regexes""
  • Loading branch information
Jenkins authored and openstack-gerrit committed Mar 4, 2016
2 parents 2c732aa + 09d27bd commit 4b47b5b
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 278 deletions.
50 changes: 17 additions & 33 deletions nova/api/validation/parameter_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@

import six

from nova.i18n import _


class ValidationRegex(object):
def __init__(self, regex, reason):
self.regex = regex
self.reason = reason


def _is_printable(char):
"""determine if a unicode code point is printable.
Expand Down Expand Up @@ -118,12 +110,10 @@ def valid_char(char):
valid_name_regex_base = '^(?![%s])[%s]*(?<![%s])$'


valid_name_regex = ValidationRegex(
valid_name_regex_base % (
_build_regex_range(ws=False, invert=True),
_build_regex_range(),
_build_regex_range(ws=False, invert=True)),
_("printable characters. Can not start or end with whitespace."))
valid_name_regex = valid_name_regex_base % (
_build_regex_range(ws=False, invert=True),
_build_regex_range(),
_build_regex_range(ws=False, invert=True))


# This regex allows leading/trailing whitespace
Expand All @@ -132,32 +122,26 @@ def valid_char(char):
"^[%(ws)s]*[%(no_ws)s][%(no_ws)s%(ws)s]+[%(no_ws)s][%(ws)s]*$")


valid_cell_name_regex = ValidationRegex(
valid_name_regex_base % (
_build_regex_range(ws=False, invert=True),
_build_regex_range(exclude=['!', '.', '@']),
_build_regex_range(ws=False, invert=True)),
_("printable characters except !, ., @. "
"Can not start or end with whitespace."))
valid_cell_name_regex = valid_name_regex_base % (
_build_regex_range(ws=False, invert=True),
_build_regex_range(exclude=['!', '.', '@']),
_build_regex_range(ws=False, invert=True))


# cell's name disallow '!', '.' and '@'.
valid_cell_name_leading_trailing_spaces_regex = ValidationRegex(
valid_cell_name_leading_trailing_spaces_regex = (
valid_name_leading_trailing_spaces_regex_base % {
'ws': _build_regex_range(exclude=['!', '.', '@']),
'no_ws': _build_regex_range(ws=False, exclude=['!', '.', '@'])},
_("printable characters except !, ., @, "
"with at least one non space character"))
'no_ws': _build_regex_range(ws=False, exclude=['!', '.', '@'])})


valid_name_leading_trailing_spaces_regex = ValidationRegex(
valid_name_leading_trailing_spaces_regex = (
valid_name_leading_trailing_spaces_regex_base % {
'ws': _build_regex_range(),
'no_ws': _build_regex_range(ws=False)},
_("printable characters with at least one non space character"))
'no_ws': _build_regex_range(ws=False)})


valid_name_regex_obj = re.compile(valid_name_regex.regex, re.UNICODE)
valid_name_regex_obj = re.compile(valid_name_regex, re.UNICODE)


valid_description_regex_base = '^[%s]*$'
Expand Down Expand Up @@ -217,25 +201,25 @@ def valid_char(char):
# stored in the DB and Nova specific parameters.
# This definition is used for all their parameters.
'type': 'string', 'minLength': 1, 'maxLength': 255,
'format': 'name'
'pattern': valid_name_regex,
}


cell_name = {
'type': 'string', 'minLength': 1, 'maxLength': 255,
'format': 'cell_name'
'pattern': valid_cell_name_regex,
}


cell_name_leading_trailing_spaces = {
'type': 'string', 'minLength': 1, 'maxLength': 255,
'format': 'cell_name_with_leading_trailing_spaces'
'pattern': valid_cell_name_leading_trailing_spaces_regex,
}


name_with_leading_trailing_spaces = {
'type': 'string', 'minLength': 1, 'maxLength': 255,
'format': 'name_with_leading_trailing_spaces'
'pattern': valid_name_leading_trailing_spaces_regex,
}


Expand Down
89 changes: 4 additions & 85 deletions nova/api/validation/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import rfc3986
import six

from nova.api.validation import parameter_types
from nova import exception
from nova.i18n import _

Expand Down Expand Up @@ -76,44 +75,6 @@ def _validate_uri(instance):
require_authority=True)


@jsonschema.FormatChecker.cls_checks('name_with_leading_trailing_spaces',
exception.InvalidName)
def _validate_name_with_leading_trailing_spaces(instance):
regex = parameter_types.valid_name_leading_trailing_spaces_regex
if re.search(regex.regex, instance):
return True
else:
raise exception.InvalidName(reason=regex.reason)


@jsonschema.FormatChecker.cls_checks('name', exception.InvalidName)
def _validate_name(instance):
regex = parameter_types.valid_name_regex
if re.search(regex.regex, instance):
return True
else:
raise exception.InvalidName(reason=regex.reason)


@jsonschema.FormatChecker.cls_checks('cell_name_with_leading_trailing_spaces',
exception.InvalidName)
def _validate_cell_name_with_leading_trailing_spaces(instance):
regex = parameter_types.valid_cell_name_leading_trailing_spaces_regex
if re.search(regex.regex, instance):
return True
else:
raise exception.InvalidName(reason=regex.reason)


@jsonschema.FormatChecker.cls_checks('cell_name', exception.InvalidName)
def _validate_cell_name(instance):
regex = parameter_types.valid_cell_name_regex
if re.search(regex.regex, instance):
return True
else:
raise exception.InvalidName(reason=regex.reason)


def _soft_validate_additional_properties(validator,
additional_properties_value,
instance,
Expand Down Expand Up @@ -171,44 +132,6 @@ def _soft_validate_additional_properties(validator,
del instance[prop]


class FormatChecker(jsonschema.FormatChecker):
"""A FormatChecker can output the message from cause exception
We need understandable validation errors messages for users. When a
custom checker has an exception, the FormatChecker will output a
readable message provided by the checker.
"""

def check(self, instance, format):
"""Check whether the instance conforms to the given format.
:argument instance: the instance to check
:type: any primitive type (str, number, bool)
:argument str format: the format that instance should conform to
:raises: :exc:`FormatError` if instance does not conform to format
"""

if format not in self.checkers:
return

# For safety reasons custom checkers can be registered with
# allowed exception types. Anything else will fall into the
# default formatter.
func, raises = self.checkers[format]
result, cause = None, None

try:
result = func(instance)
except raises as e:
if isinstance(e, exception.NovaException):
raise
else:
cause = e
if not result:
msg = "%r is not a %r" % (instance, format)
raise jsonschema_exc.FormatError(msg, cause=cause)


class _SchemaValidator(object):
"""A validator class
Expand All @@ -233,20 +156,16 @@ def __init__(self, schema, relax_additional_properties=False):

validator_cls = jsonschema.validators.extend(self.validator_org,
validators)
format_checker = FormatChecker()
format_checker = jsonschema.FormatChecker()
self.validator = validator_cls(schema, format_checker=format_checker)

def validate(self, *args, **kwargs):
try:
self.validator.validate(*args, **kwargs)
except exception.InvalidName as ex:
raise exception.ValidationError(detail=ex.format_message())
except jsonschema.ValidationError as ex:
if isinstance(ex.cause, exception.InvalidName):
detail = ex.cause.format_message()
elif len(ex.path) > 0:
# NOTE: For whole OpenStack message consistency, this error
# message has been written as the similar format of WSME.
# NOTE: For whole OpenStack message consistency, this error
# message has been written as the similar format of WSME.
if len(ex.path) > 0:
detail = _("Invalid input for field/attribute %(path)s."
" Value: %(value)s. %(message)s") % {
'path': ex.path.pop(), 'value': ex.instance,
Expand Down
5 changes: 0 additions & 5 deletions nova/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,11 +420,6 @@ class InvalidStrTime(Invalid):
msg_fmt = _("Invalid datetime string: %(reason)s")


class InvalidName(Invalid):
msg_fmt = _("An invalid 'name' value was provided. "
"The name must be: %(reason)s")


class InstanceInvalidState(Invalid):
msg_fmt = _("Instance %(instance_uuid)s in %(attr)s %(state)s. Cannot "
"%(method)s while the instance is in this state.")
Expand Down

0 comments on commit 4b47b5b

Please sign in to comment.