Package xmlschema_acue :: Package validators :: Module exceptions

Source Code for Module xmlschema_acue.validators.exceptions

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright (c), 2016-2019, SISSA (International School for Advanced Studies). 
  4  # All rights reserved. 
  5  # This file is distributed under the terms of the MIT License. 
  6  # See the file 'LICENSE' in the root directory of the present 
  7  # distribution, or http://opensource.org/licenses/MIT. 
  8  # 
  9  # @author Davide Brunato <brunato@sissa.it> 
 10  # 
 11  """ 
 12  This module contains exception and warning classes for the 'xmlschema_acue.validators' subpackage. 
 13  """ 
 14  from __future__ import unicode_literals 
 15   
 16  from xmlschema_acue.compat import PY3 
 17  from xmlschema_acue.exceptions import XMLSchemaException, XMLSchemaWarning, XMLSchemaValueError 
 18  from xmlschema_acue.etree import etree_tostring, is_etree_element, etree_getpath 
 19  from xmlschema_acue.helpers import qname_to_prefixed 
 20  from xmlschema_acue.resources import XMLResource 
21 22 23 -class XMLSchemaValidatorError(XMLSchemaException):
24 """ 25 Base class for XSD validator errors. 26 27 :param validator: the XSD validator. 28 :type validator: XsdValidator or function 29 :param message: the error message. 30 :type message: str or unicode 31 :param elem: the element that contains the error. 32 :type elem: Element 33 :param source: the XML resource that contains the error. 34 :type source: XMLResource 35 :param namespaces: is an optional mapping from namespace prefix to URI. 36 :type namespaces: dict 37 :ivar path: the XPath of the element, calculated when the element is set or the XML resource is set. 38 """
39 - def __init__(self, validator, message, elem=None, source=None, namespaces=None):
40 self.validator = validator 41 self.message = message[:-1] if message[-1] in ('.', ':') else message 42 self.namespaces = namespaces 43 self.elem = elem 44 self.source = source
45
46 - def __str__(self):
47 return unicode(self).encode("utf-8")
48
49 - def __unicode__(self):
50 if self.elem is None: 51 return '%s.' % self.message 52 else: 53 msg = ['%s:\n' % self.message] 54 if self.elem is not None: 55 elem_as_string = etree_tostring(self.elem, self.namespaces, ' ', 20) 56 if hasattr(self.elem, 'sourceline'): 57 msg.append("Schema (line %r):\n\n%s\n" % (self.elem.sourceline, elem_as_string)) 58 else: 59 msg.append("Schema:\n\n%s\n" % elem_as_string) 60 if self.path is not None: 61 msg.append("Path: %s\n" % self.path) 62 if self.schema_url is not None: 63 msg.append("Schema URL: %s\n" % self.schema_url) 64 if self.origin_url not in (None, self.schema_url): 65 msg.append("Origin URL: %s\n" % self.origin_url) 66 return '\n'.join(msg)
67 68 if PY3: 69 __str__ = __unicode__ 70 71 @property
72 - def msg(self):
73 return self.__unicode__()
74
75 - def __setattr__(self, name, value):
76 if name == 'elem' and value is not None and not is_etree_element(value): 77 raise XMLSchemaValueError("'elem' attribute requires an Element, not %r." % type(value)) 78 super(XMLSchemaValidatorError, self).__setattr__(name, value) 79 80 # Calculate and set the element's path: have to be calculated asap because is the 81 # XML resource is lazy the intermediate nodes could be deleted. 82 if name in ('elem', 'source'): 83 elem, root = self.elem, self.root 84 if not is_etree_element(elem) or not is_etree_element(root): 85 self.path = None 86 else: 87 self.path = etree_getpath(elem, root, self.namespaces, relative=False, add_position=True)
88 89 @property
90 - def sourceline(self):
91 return getattr(self.elem, 'sourceline', None)
92 93 @property
94 - def root(self):
95 try: 96 return self.source.root 97 except AttributeError: 98 return
99 100 @property
101 - def schema_url(self):
102 try: 103 return self.validator.schema.source.url 104 except AttributeError: 105 return
106 107 @property
108 - def origin_url(self):
109 try: 110 return self.validator.maps.validator.source.url 111 except AttributeError: 112 return
113
114 115 -class XMLSchemaNotBuiltError(XMLSchemaValidatorError, RuntimeError):
116 """ 117 Raised when there is an improper usage attempt of a not built XSD validator. 118 119 :param validator: the XSD validator. 120 :type validator: XsdValidator 121 :param message: the error message. 122 :type message: str or unicode 123 """
124 - def __init__(self, validator, message):
125 super(XMLSchemaNotBuiltError, self).__init__( 126 validator=validator, 127 message=message, 128 elem=getattr(validator, 'elem', None), 129 source=getattr(validator, 'source', None), 130 namespaces=getattr(validator, 'namespaces', None) 131 )
132
133 134 -class XMLSchemaParseError(XMLSchemaValidatorError, SyntaxError):
135 """ 136 Raised when an error is found during the building of an XSD validator. 137 138 :param validator: the XSD validator. 139 :type validator: XsdValidator or function 140 :param message: the error message. 141 :type message: str or unicode 142 :param elem: the element that contains the error. 143 :type elem: Element 144 """
145 - def __init__(self, validator, message, elem=None):
146 super(XMLSchemaParseError, self).__init__( 147 validator=validator, 148 message=message, 149 elem=elem if elem is not None else getattr(validator, 'elem', None), 150 source=getattr(validator, 'source', None), 151 namespaces=getattr(validator, 'namespaces', None), 152 )
153
154 155 -class XMLSchemaModelError(XMLSchemaValidatorError, ValueError):
156 """ 157 Raised when a model error is found during the checking of a model group. 158 159 :param group: the XSD model group. 160 :type group: XsdGroup 161 :param message: the error message. 162 :type message: str or unicode 163 """
164 - def __init__(self, group, message):
165 super(XMLSchemaModelError, self).__init__( 166 validator=group, 167 message=message, 168 elem=group.elem, 169 source=getattr(group, 'source', None), 170 namespaces=group.namespaces 171 )
172
173 174 -class XMLSchemaModelDepthError(XMLSchemaModelError):
175 """Raised when recursion depth is exceeded while iterating a model group."""
176 - def __init__(self, group):
177 msg = "maximum model recursion depth exceeded while iterating group %r" % group 178 super(XMLSchemaModelDepthError, self).__init__(group, message=msg)
179
180 181 -class XMLSchemaValidationError(XMLSchemaValidatorError, ValueError):
182 """ 183 Raised when the XML data is not validated with the XSD component or schema. 184 It's used by decoding and encoding methods. Encoding validation errors do 185 not include XML data element and source, so the error is limited to a message 186 containing object representation and a reason. 187 188 :param validator: the XSD validator. 189 :type validator: XsdValidator or function 190 :param obj: the not validated XML data. 191 :type obj: Element or tuple or str or list or int or float or bool 192 :param reason: the detailed reason of failed validation. 193 :type reason: str or unicode 194 :param source: the XML resource that contains the error. 195 :type source: XMLResource 196 :param namespaces: is an optional mapping from namespace prefix to URI. 197 :type namespaces: dict 198 """
199 - def __init__(self, validator, obj, reason=None, source=None, namespaces=None):
200 super(XMLSchemaValidationError, self).__init__( 201 validator=validator, 202 message="failed validating {!r} with {!r}".format(obj, validator), 203 elem=obj if is_etree_element(obj) else None, 204 source=source, 205 namespaces=namespaces, 206 ) 207 self.obj = obj 208 self.reason = reason
209
210 - def __str__(self):
211 # noinspection PyCompatibility,PyUnresolvedReferences 212 return unicode(self).encode("utf-8")
213
214 - def __unicode__(self):
215 msg = ['%s:\n' % self.message] 216 if self.reason is not None: 217 msg.append('Reason: %s\n' % self.reason) 218 if hasattr(self.validator, 'tostring'): 219 msg.append("Schema:\n\n%s\n" % self.validator.tostring(' ', 20)) 220 if self.elem is not None: 221 elem_as_string = etree_tostring(self.elem, self.namespaces, ' ', 20) 222 if hasattr(self.elem, 'sourceline'): 223 msg.append("Instance (line %r):\n\n%s\n" % (self.elem.sourceline, elem_as_string)) 224 else: 225 msg.append("Instance:\n\n%s\n" % elem_as_string) 226 if self.path is not None: 227 msg.append("Path: %s\n" % self.path) 228 return '\n'.join(msg)
229 230 if PY3: 231 __str__ = __unicode__
232
233 234 -class XMLSchemaDecodeError(XMLSchemaValidationError):
235 """ 236 Raised when an XML data string is not decodable to a Python object. 237 238 :param validator: the XSD validator. 239 :type validator: XsdValidator or function 240 :param obj: the not validated XML data. 241 :type obj: Element or tuple or str or list or int or float or bool 242 :param decoder: the XML data decoder. 243 :type decoder: type or function 244 :param reason: the detailed reason of failed validation. 245 :type reason: str or unicode 246 :param source: the XML resource that contains the error. 247 :type source: XMLResource 248 :param namespaces: is an optional mapping from namespace prefix to URI. 249 :type namespaces: dict 250 """ 251 message = "failed decoding {!r} with {!r}.\n" 252
253 - def __init__(self, validator, obj, decoder, reason=None, source=None, namespaces=None):
254 super(XMLSchemaDecodeError, self).__init__(validator, obj, reason, source, namespaces) 255 self.decoder = decoder
256
257 258 -class XMLSchemaEncodeError(XMLSchemaValidationError):
259 """ 260 Raised when an object is not encodable to an XML data string. 261 262 :param validator: the XSD validator. 263 :type validator: XsdValidator or function 264 :param obj: the not validated XML data. 265 :type obj: Element or tuple or str or list or int or float or bool 266 :param encoder: the XML encoder. 267 :type encoder: type or function 268 :param reason: the detailed reason of failed validation. 269 :type reason: str or unicode 270 :param source: the XML resource that contains the error. 271 :type source: XMLResource 272 :param namespaces: is an optional mapping from namespace prefix to URI. 273 :type namespaces: dict 274 """ 275 message = "failed encoding {!r} with {!r}.\n" 276
277 - def __init__(self, validator, obj, encoder, reason=None, source=None, namespaces=None):
278 super(XMLSchemaEncodeError, self).__init__(validator, obj, reason, source, namespaces) 279 self.encoder = encoder
280
281 282 -class XMLSchemaChildrenValidationError(XMLSchemaValidationError):
283 """ 284 Raised when a child element is not validated. 285 286 :param validator: the XSD validator. 287 :type validator: XsdValidator or function 288 :param elem: the not validated XML element. 289 :type elem: Element or ElementData 290 :param index: the child index. 291 :type index: int 292 :param particle: the validator particle that generated the error. Maybe the validator itself. 293 :type particle: ParticleMixin 294 :param occurs: the particle occurrences. 295 :type occurs: int 296 :param expected: the expected element tags/object names. 297 :type expected: str or list or tuple 298 :param source: the XML resource that contains the error. 299 :type source: XMLResource 300 :param namespaces: is an optional mapping from namespace prefix to URI. 301 :type namespaces: dict 302 """
303 - def __init__(self, validator, elem, index, particle, occurs=0, expected=None, source=None, namespaces=None):
304 self.index = index 305 self.particle = particle 306 self.occurs = occurs 307 self.expected = expected 308 309 tag = qname_to_prefixed(elem.tag, validator.namespaces) 310 if index >= len(elem): 311 reason = "The content of element %r is not complete." % tag 312 else: 313 child_tag = qname_to_prefixed(elem[index].tag, validator.namespaces) 314 reason = "Unexpected child with tag %r at position %d." % (child_tag, index + 1) 315 316 if occurs and particle.is_missing(occurs): 317 reason += " The particle %r occurs %d times but the minimum is %d." % ( 318 particle, occurs, particle.min_occurs 319 ) 320 elif particle.is_over(occurs): 321 reason += " The particle %r occurs %d times but the maximum is %d." % ( 322 particle, occurs, particle.max_occurs 323 ) 324 325 if expected is None: 326 pass 327 else: 328 expected_tags = [] 329 for xsd_element in expected: 330 if xsd_element.name is not None: 331 expected_tags.append(repr(xsd_element.prefixed_name)) 332 elif xsd_element.process_contents == 'strict': 333 expected_tags.append('from %r namespace/s' % xsd_element.namespace) 334 335 if not expected_tags: 336 reason += " No child element is expected at this point." 337 elif len(expected_tags) > 1: 338 reason += " Tags %s are expected." % expected_tags 339 else: 340 reason += " Tag %s expected." % expected_tags[0] 341 342 super(XMLSchemaChildrenValidationError, self).__init__(validator, elem, reason, source, namespaces)
343
344 345 -class XMLSchemaIncludeWarning(XMLSchemaWarning):
346 """A schema include fails."""
347
348 349 -class XMLSchemaImportWarning(XMLSchemaWarning):
350 """A schema namespace import fails."""
351