Package xmlschema_acue :: Package validators :: Module simple_types

Source Code for Module xmlschema_acue.validators.simple_types

   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 classes for XML Schema simple data types. 
  13  """ 
  14  from __future__ import unicode_literals 
  15  from decimal import DecimalException 
  16   
  17  from xmlschema_acue.compat import string_base_type, unicode_type 
  18  from xmlschema_acue.etree import etree_element 
  19  from xmlschema_acue.exceptions import XMLSchemaTypeError, XMLSchemaValueError 
  20  from xmlschema_acue.qnames import ( 
  21      XSD_ANY_TYPE, XSD_SIMPLE_TYPE, XSD_ANY_ATOMIC_TYPE, XSD_ATTRIBUTE, XSD_ATTRIBUTE_GROUP, 
  22      XSD_ANY_ATTRIBUTE, XSD_PATTERN, XSD_MIN_INCLUSIVE, XSD_MIN_EXCLUSIVE, XSD_MAX_INCLUSIVE, 
  23      XSD_MAX_EXCLUSIVE, XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_WHITE_SPACE, XSD_LIST, 
  24      XSD_ANY_SIMPLE_TYPE, XSD_UNION, XSD_RESTRICTION, XSD_ANNOTATION, XSD_ASSERTION, XSD_ID, 
  25      XSD_FRACTION_DIGITS, XSD_TOTAL_DIGITS 
  26  ) 
  27  from xmlschema_acue.helpers import get_qname, local_name, get_xsd_derivation_attribute 
  28   
  29  from xmlschema_acue.validators.exceptions import XMLSchemaValidationError, XMLSchemaEncodeError, XMLSchemaDecodeError, XMLSchemaParseError 
  30  from xmlschema_acue.validators.xsdbase import XsdAnnotation, XsdType, ValidationMixin 
  31  from xmlschema_acue.validators.facets import XsdFacet, XsdWhiteSpaceFacet, XSD_10_FACETS_BUILDERS, XSD_11_FACETS_BUILDERS, XSD_10_FACETS, \ 
  32      XSD_11_FACETS, XSD_10_LIST_FACETS, XSD_11_LIST_FACETS, XSD_10_UNION_FACETS, XSD_11_UNION_FACETS, MULTIPLE_FACETS 
33 34 35 -def xsd_simple_type_factory(elem, schema, parent):
36 try: 37 name = get_qname(schema.target_namespace, elem.attrib['name']) 38 except KeyError: 39 name = None 40 else: 41 if name == XSD_ANY_SIMPLE_TYPE: 42 return 43 44 annotation = None 45 try: 46 child = elem[0] 47 except IndexError: 48 return schema.maps.types[XSD_ANY_SIMPLE_TYPE] 49 else: 50 if child.tag == XSD_ANNOTATION: 51 try: 52 child = elem[1] 53 annotation = XsdAnnotation(elem[0], schema, child) 54 except IndexError: 55 return schema.maps.types[XSD_ANY_SIMPLE_TYPE] 56 57 if child.tag == XSD_RESTRICTION: 58 result = schema.BUILDERS.restriction_class(child, schema, parent, name=name) 59 elif child.tag == XSD_LIST: 60 result = XsdList(child, schema, parent, name=name) 61 elif child.tag == XSD_UNION: 62 result = schema.BUILDERS.union_class(child, schema, parent, name=name) 63 else: 64 result = schema.maps.types[XSD_ANY_SIMPLE_TYPE] 65 66 if annotation is not None: 67 result.annotation = annotation 68 69 if 'final' in elem.attrib: 70 try: 71 result._final = get_xsd_derivation_attribute(elem, 'final') 72 except ValueError as err: 73 result.parse_error(err, elem) 74 75 return result
76
77 78 -class XsdSimpleType(XsdType, ValidationMixin):
79 """ 80 Base class for simpleTypes definitions. Generally used only for 81 instances of xs:anySimpleType. 82 83 <simpleType 84 final = (#all | List of (list | union | restriction | extension)) 85 id = ID 86 name = NCName 87 {any attributes with non-schema namespace . . .}> 88 Content: (annotation?, (restriction | list | union)) 89 </simpleType> 90 """ 91 _special_types = {XSD_ANY_TYPE, XSD_ANY_SIMPLE_TYPE} 92 _admitted_tags = {XSD_SIMPLE_TYPE} 93 94 min_length = None 95 max_length = None 96 white_space = None 97 patterns = None 98 validators = () 99
100 - def __init__(self, elem, schema, parent, name=None, facets=None):
101 super(XsdSimpleType, self).__init__(elem, schema, parent, name) 102 if not hasattr(self, 'facets'): 103 self.facets = facets or {}
104
105 - def __setattr__(self, name, value):
106 super(XsdSimpleType, self).__setattr__(name, value) 107 if name == 'facets': 108 if not isinstance(self, XsdAtomicBuiltin): 109 self._parse_facets(value) 110 111 white_space = getattr(self.get_facet(XSD_WHITE_SPACE), 'value', None) 112 if white_space is not None: 113 self.white_space = white_space 114 115 patterns = self.get_facet(XSD_PATTERN) 116 if patterns is not None: 117 self.patterns = patterns 118 119 if value: 120 if None in value: 121 validators = [value[None]] # Use only the validator function! 122 else: 123 validators = [v for k, v in value.items() 124 if k not in {XSD_WHITE_SPACE, XSD_PATTERN, XSD_ASSERTION}] 125 if XSD_ASSERTION in value: 126 assertions = value[XSD_ASSERTION] 127 if isinstance(assertions, list): 128 validators.extend(assertions) 129 else: 130 validators.append(assertions) 131 if validators: 132 self.validators = validators
133
134 - def _parse_facets(self, facets):
135 if facets and self.base_type is not None: 136 if self.base_type.is_simple(): 137 if self.base_type.name == XSD_ANY_SIMPLE_TYPE: 138 self.parse_error("facets not allowed for a direct derivation of xs:anySimpleType") 139 elif self.base_type.has_simple_content(): 140 if self.base_type.content_type.name == XSD_ANY_SIMPLE_TYPE: 141 self.parse_error("facets not allowed for a direct content derivation of xs:anySimpleType") 142 143 # Checks the applicability of the facets 144 if any(k not in self.admitted_facets for k in facets if k is not None): 145 reason = "one or more facets are not applicable, admitted set is %r:" 146 self.parse_error(reason % {local_name(e) for e in self.admitted_facets if e}) 147 148 # Check group base_type 149 base_type = {t.base_type for t in facets.values() if isinstance(t, XsdFacet)} 150 if len(base_type) > 1: 151 self.parse_error("facet group must have the same base_type: %r" % base_type) 152 base_type = base_type.pop() if base_type else None 153 154 # Checks length based facets 155 length = getattr(facets.get(XSD_LENGTH), 'value', None) 156 min_length = getattr(facets.get(XSD_MIN_LENGTH), 'value', None) 157 max_length = getattr(facets.get(XSD_MAX_LENGTH), 'value', None) 158 if length is not None: 159 if length < 0: 160 self.parse_error("'length' value must be non negative integer") 161 if min_length is not None: 162 if min_length > length: 163 self.parse_error("'minLength' value must be less or equal to 'length'") 164 min_length_facet = base_type.get_facet(XSD_MIN_LENGTH) 165 length_facet = base_type.get_facet(XSD_LENGTH) 166 if min_length_facet is None or \ 167 (length_facet is not None and length_facet.base_type == min_length_facet.base_type): 168 self.parse_error("cannot specify both 'length' and 'minLength'") 169 if max_length is not None: 170 if max_length < length: 171 self.parse_error("'maxLength' value must be greater or equal to 'length'") 172 max_length_facet = base_type.get_facet(XSD_MAX_LENGTH) 173 length_facet = base_type.get_facet(XSD_LENGTH) 174 if max_length_facet is None or \ 175 (length_facet is not None and length_facet.base_type == max_length_facet.base_type): 176 self.parse_error("cannot specify both 'length' and 'maxLength'") 177 min_length = max_length = length 178 elif min_length is not None or max_length is not None: 179 min_length_facet = base_type.get_facet(XSD_MIN_LENGTH) 180 max_length_facet = base_type.get_facet(XSD_MAX_LENGTH) 181 if min_length is not None: 182 if min_length < 0: 183 self.parse_error("'minLength' value must be non negative integer") 184 if max_length is not None and max_length < min_length: 185 self.parse_error("'maxLength' value is lesser than 'minLength'") 186 if min_length_facet is not None and min_length_facet.value > min_length: 187 self.parse_error("'minLength' has a lesser value than parent") 188 if max_length_facet is not None and min_length > max_length_facet.value: 189 self.parse_error("'minLength' has a greater value than parent 'maxLength'") 190 191 if max_length is not None: 192 if max_length < 0: 193 self.parse_error("'maxLength' value mu st be non negative integer") 194 if min_length_facet is not None and min_length_facet.value > max_length: 195 self.parse_error("'maxLength' has a lesser value than parent 'minLength'") 196 if max_length_facet is not None and max_length > max_length_facet.value: 197 self.parse_error("'maxLength' has a greater value than parent") 198 199 # Checks min/max values 200 min_inclusive = getattr(facets.get(XSD_MIN_INCLUSIVE), 'value', None) 201 min_exclusive = getattr(facets.get(XSD_MIN_EXCLUSIVE), 'value', None) 202 max_inclusive = getattr(facets.get(XSD_MAX_INCLUSIVE), 'value', None) 203 max_exclusive = getattr(facets.get(XSD_MAX_EXCLUSIVE), 'value', None) 204 205 if min_inclusive is not None: 206 if min_exclusive is not None: 207 self.parse_error("cannot specify both 'minInclusive' and 'minExclusive") 208 if max_inclusive is not None and min_inclusive > max_inclusive: 209 self.parse_error("'minInclusive' must be less or equal to 'maxInclusive'") 210 elif max_exclusive is not None and min_inclusive >= max_exclusive: 211 self.parse_error("'minInclusive' must be lesser than 'maxExclusive'") 212 213 elif min_exclusive is not None: 214 if max_inclusive is not None and min_exclusive >= max_inclusive: 215 self.parse_error("'minExclusive' must be lesser than 'maxInclusive'") 216 elif max_exclusive is not None and min_exclusive > max_exclusive: 217 self.parse_error("'minExclusive' must be less or equal to 'maxExclusive'") 218 219 if max_inclusive is not None and max_exclusive is not None: 220 self.parse_error("cannot specify both 'maxInclusive' and 'maxExclusive") 221 222 # Checks fraction digits 223 if XSD_TOTAL_DIGITS in facets: 224 if XSD_FRACTION_DIGITS in facets and facets[XSD_TOTAL_DIGITS].value < facets[XSD_FRACTION_DIGITS].value: 225 self.parse_error("fractionDigits facet value cannot be lesser than the value of totalDigits") 226 total_digits = base_type.get_facet(XSD_TOTAL_DIGITS) 227 if total_digits is not None and total_digits.value < facets[XSD_TOTAL_DIGITS].value: 228 self.parse_error("totalDigits facet value cannot be greater than those on the base type") 229 230 self.min_length = min_length 231 self.max_length = max_length
232 233 @property
234 - def min_value(self):
235 min_exclusive_facet = self.get_facet(XSD_MIN_EXCLUSIVE) 236 if min_exclusive_facet is None: 237 return getattr(self.get_facet(XSD_MIN_INCLUSIVE), 'value', None) 238 239 min_inclusive_facet = self.get_facet(XSD_MIN_INCLUSIVE) 240 if min_inclusive_facet is None or min_inclusive_facet.value <= min_exclusive_facet.value: 241 return min_exclusive_facet.value 242 else: 243 return min_inclusive_facet.value
244 245 @property
246 - def max_value(self):
247 max_exclusive_facet = self.get_facet(XSD_MAX_EXCLUSIVE) 248 if max_exclusive_facet is None: 249 return getattr(self.get_facet(XSD_MAX_INCLUSIVE), 'value', None) 250 251 max_inclusive_facet = self.get_facet(XSD_MAX_INCLUSIVE) 252 if max_inclusive_facet is None or max_inclusive_facet.value >= max_exclusive_facet.value: 253 return max_exclusive_facet.value 254 else: 255 return max_inclusive_facet.value
256 257 @property
258 - def admitted_facets(self):
259 return XSD_10_FACETS if self.schema.XSD_VERSION == '1.0' else XSD_11_FACETS
260 261 @property
262 - def built(self):
263 return True
264 265 @staticmethod
266 - def is_simple():
267 return True
268 269 @staticmethod
270 - def is_complex():
271 return False
272
273 - def is_empty(self):
274 return self.max_length == 0
275
276 - def is_emptiable(self):
277 return self.min_length is None or self.min_length == 0
278
279 - def has_simple_content(self):
280 return True
281
282 - def has_mixed_content(self):
283 return False
284
285 - def is_element_only(self):
286 return False
287
288 - def is_derived(self, other, derivation=None):
289 if self is other: 290 return True 291 elif derivation and self.derivation and derivation != self.derivation: 292 return False 293 elif other.name in self._special_types: 294 return True 295 elif self.base_type is other: 296 return True 297 elif self.base_type is None: 298 if hasattr(other, 'member_types'): 299 return any(self.is_derived(m, derivation) for m in other.member_types) 300 return False 301 elif self.base_type.is_complex(): 302 if not self.base_type.has_simple_content(): 303 return False 304 return self.base_type.content_type.is_derived(other, derivation) 305 elif hasattr(other, 'member_types'): 306 return any(self.is_derived(m, derivation) for m in other.member_types) 307 else: 308 return self.base_type.is_derived(other, derivation)
309
310 - def normalize(self, text):
311 """ 312 Normalize and restrict value-space with pre-lexical and lexical facets. 313 The normalized string is returned. Returns the argument if it isn't a string. 314 315 :param text: text string encoded value. 316 :return: normalized string. 317 """ 318 if isinstance(text, bytes): 319 text = text.decode('utf-8') 320 elif not isinstance(text, string_base_type): 321 raise XMLSchemaValueError('argument is not a string: %r' % text) 322 323 if self.white_space == 'replace': 324 return self._REGEX_SPACE.sub(' ', text) 325 elif self.white_space == 'collapse': 326 return self._REGEX_SPACES.sub(' ', text).strip() 327 else: 328 return text
329
330 - def iter_decode(self, obj, validation='lax', **kwargs):
331 if isinstance(obj, (string_base_type, bytes)): 332 obj = self.normalize(obj) 333 334 if validation != 'skip': 335 if self.patterns is not None: 336 for error in self.patterns(obj): 337 if validation == 'strict': 338 raise error 339 yield error 340 341 for validator in self.validators: 342 for error in validator(obj): 343 if validation == 'strict': 344 raise error 345 yield error 346 yield obj
347
348 - def iter_encode(self, obj, validation='lax', **kwargs):
349 if isinstance(obj, (string_base_type, bytes)): 350 obj = self.normalize(obj) 351 elif validation != 'skip': 352 yield self.encode_error(validation, obj, unicode_type) 353 354 if validation != 'skip': 355 if self.patterns is not None: 356 for error in self.patterns(obj): 357 if validation == 'strict': 358 raise error 359 yield error 360 361 for validator in self.validators: 362 for error in validator(obj): 363 if validation == 'strict': 364 raise error 365 yield error 366 367 yield obj
368
369 - def get_facet(self, tag):
370 return self.facets.get(tag)
371
372 373 # 374 # simpleType's derived classes: 375 -class XsdAtomic(XsdSimpleType):
376 """ 377 Class for atomic simpleType definitions. An atomic definition has 378 a base_type attribute that refers to primitive or derived atomic 379 built-in type or another derived simpleType. 380 """ 381 _special_types = {XSD_ANY_TYPE, XSD_ANY_SIMPLE_TYPE, XSD_ANY_ATOMIC_TYPE} 382 _admitted_tags = {XSD_RESTRICTION, XSD_SIMPLE_TYPE} 383
384 - def __init__(self, elem, schema, parent, name=None, facets=None, base_type=None):
385 self.base_type = base_type 386 super(XsdAtomic, self).__init__(elem, schema, parent, name, facets)
387
388 - def __repr__(self):
389 if self.name is None: 390 return '%s(primitive_type=%r)' % (self.__class__.__name__, self.primitive_type.local_name) 391 else: 392 return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)
393
394 - def __setattr__(self, name, value):
395 if name == 'base_type' and value is not None and not isinstance(value, XsdType): 396 raise XMLSchemaValueError("%r attribute must be an XsdType instance or None: %r" % (name, value)) 397 super(XsdAtomic, self).__setattr__(name, value) 398 if name in ('base_type', 'white_space'): 399 if getattr(self, 'white_space', None) is None: 400 try: 401 white_space = self.base_type.white_space 402 except AttributeError: 403 return 404 else: 405 if white_space is not None: 406 self.white_space = white_space
407 408 @property
409 - def built(self):
410 if self.base_type is None: 411 return True 412 else: 413 return self.base_type.is_global or self.base_type.built
414 415 @property
416 - def validation_attempted(self):
417 if self.built: 418 return 'full' 419 else: 420 return self.base_type.validation_attempted
421 422 @property
423 - def admitted_facets(self):
428 429 @property
430 - def primitive_type(self):
431 if self.base_type is None: 432 return self 433 try: 434 if self.base_type.is_simple(): 435 return self.base_type.primitive_type 436 else: 437 return self.base_type.content_type.primitive_type 438 except AttributeError: 439 # The base_type is XsdList or XsdUnion. 440 return self.base_type
441
442 - def get_facet(self, tag):
443 try: 444 return self.facets[tag] 445 except KeyError: 446 try: 447 return self.base_type.get_facet(tag) 448 except AttributeError: 449 return
450 451 @staticmethod
452 - def is_atomic():
453 return True
454 455 @staticmethod
456 - def is_list():
457 return False
458
459 460 -class XsdAtomicBuiltin(XsdAtomic):
461 """ 462 Class for defining XML Schema built-in simpleType atomic datatypes. An instance 463 contains a Python's type transformation and a list of validator functions. The 464 'base_type' is not used for validation, but only for reference to the XML Schema 465 restriction hierarchy. 466 467 Type conversion methods: 468 - to_python(value): Decoding from XML 469 - from_python(value): Encoding to XML 470 """
471 - def __init__(self, elem, schema, name, python_type, base_type=None, admitted_facets=None, facets=None, 472 to_python=None, from_python=None):
473 """ 474 :param name: the XSD type's qualified name. 475 :param python_type: the correspondent Python's type. If a tuple or list of types \ 476 is provided uses the first and consider the others as compatible types. 477 :param base_type: the reference base type, None if it's a primitive type. 478 :param admitted_facets: admitted facets tags for type (required for primitive types). 479 :param facets: optional facets validators. 480 :param to_python: optional decode function. 481 :param from_python: optional encode function. 482 """ 483 if isinstance(python_type, (tuple, list)): 484 self.instance_types, python_type = python_type, python_type[0] 485 else: 486 self.instance_types = python_type 487 if not callable(python_type): 488 raise XMLSchemaTypeError("%r object is not callable" % python_type.__class__) 489 490 if base_type is None and not admitted_facets: 491 raise XMLSchemaValueError("argument 'admitted_facets' must be a not empty set of a primitive type") 492 self._admitted_facets = admitted_facets 493 494 super(XsdAtomicBuiltin, self).__init__(elem, schema, None, name, facets, base_type) 495 self.python_type = python_type 496 self.to_python = to_python or python_type 497 self.from_python = from_python or unicode_type
498
499 - def __repr__(self):
500 return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)
501
502 - def _parse(self):
503 pass
504 505 @property
506 - def admitted_facets(self):
507 return self._admitted_facets or self.primitive_type.admitted_facets
508
509 - def iter_decode(self, obj, validation='lax', **kwargs):
510 if isinstance(obj, (string_base_type, bytes)): 511 obj = self.normalize(obj) 512 elif validation != 'skip' and obj is not None and not isinstance(obj, self.instance_types): 513 yield self.decode_error(validation, obj, self.to_python, 514 reason="value is not an instance of {!r}".format(self.instance_types)) 515 516 if 'id_map' in kwargs: 517 if self.name == XSD_ID: 518 kwargs['id_map'][obj] += 1 519 520 if validation == 'skip': 521 try: 522 yield self.to_python(obj) 523 except (ValueError, DecimalException): 524 yield unicode_type(obj) 525 return 526 527 if self.patterns is not None: 528 for error in self.patterns(obj): 529 if validation == 'strict': 530 raise error 531 yield error 532 533 try: 534 result = self.to_python(obj) 535 except (ValueError, DecimalException) as err: 536 yield self.decode_error(validation, obj, self.to_python, reason=str(err)) 537 yield None 538 return 539 540 for validator in self.validators: 541 for error in validator(result): 542 if validation == 'strict': 543 raise error 544 yield error 545 546 yield result
547
548 - def iter_encode(self, obj, validation='lax', **kwargs):
549 if isinstance(obj, (string_base_type, bytes)): 550 obj = self.normalize(obj) 551 552 if validation == 'skip': 553 try: 554 yield self.from_python(obj) 555 except ValueError: 556 yield unicode_type(obj) 557 return 558 559 elif isinstance(obj, bool): 560 types_ = self.instance_types 561 if types_ is not bool or (isinstance(types_, tuple) and bool in types_): 562 reason = "boolean value {!r} requires a {!r} decoder.".format(obj, bool) 563 yield self.encode_error(validation, obj, self.from_python, reason) 564 obj = self.python_type(obj) 565 566 elif not isinstance(obj, self.instance_types): 567 reason = "{!r} is not an instance of {!r}.".format(obj, self.instance_types) 568 yield self.encode_error(validation, obj, self.from_python, reason) 569 try: 570 value = self.python_type(obj) 571 if value != obj: 572 raise ValueError() 573 else: 574 obj = value 575 except ValueError: 576 yield self.encode_error(validation, obj, self.from_python) 577 yield None 578 return 579 580 for validator in self.validators: 581 for error in validator(obj): 582 if validation == 'strict': 583 raise error 584 yield error 585 586 try: 587 text = self.from_python(obj) 588 except ValueError: 589 yield self.encode_error(validation, obj, self.from_python) 590 yield None 591 else: 592 if self.patterns is not None: 593 for error in self.patterns(text): 594 if validation == 'strict': 595 raise error 596 yield error 597 yield text
598
599 600 -class XsdList(XsdSimpleType):
601 """ 602 Class for 'list' definitions. A list definition has an item_type attribute 603 that refers to an atomic or union simpleType definition. 604 605 <list 606 id = ID 607 itemType = QName 608 {any attributes with non-schema namespace ...}> 609 Content: (annotation?, simpleType?) 610 </list> 611 """ 612 _admitted_tags = {XSD_LIST} 613 _white_space_elem = etree_element(XSD_WHITE_SPACE, attrib={'value': 'collapse', 'fixed': 'true'}) 614
615 - def __init__(self, elem, schema, parent, name=None):
616 facets = {XSD_WHITE_SPACE: XsdWhiteSpaceFacet(self._white_space_elem, schema, self, self)} 617 super(XsdList, self).__init__(elem, schema, parent, name, facets)
618
619 - def __repr__(self):
620 if self.name is None: 621 return '%s(item_type=%r)' % (self.__class__.__name__, self.base_type) 622 else: 623 return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)
624
625 - def __setattr__(self, name, value):
626 if name == 'elem' and value is not None and value.tag != XSD_LIST: 627 if value.tag == XSD_SIMPLE_TYPE: 628 for child in value: 629 if child.tag == XSD_LIST: 630 super(XsdList, self).__setattr__(name, child) 631 return 632 raise XMLSchemaValueError("a %r definition required for %r." % (XSD_LIST, self)) 633 elif name == 'base_type': 634 if not value.is_atomic(): 635 raise XMLSchemaValueError("%r: a list must be based on atomic data types." % self) 636 elif name == 'white_space' and value is None: 637 value = 'collapse' 638 super(XsdList, self).__setattr__(name, value)
639
640 - def _parse(self):
641 super(XsdList, self)._parse() 642 elem = self.elem 643 644 child = self._parse_component(elem, required=False) 645 if child is not None: 646 # Case of a local simpleType declaration inside the list tag 647 try: 648 base_type = xsd_simple_type_factory(child, self.schema, self) 649 except XMLSchemaParseError as err: 650 self.parse_error(err, elem) 651 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 652 653 if 'itemType' in elem.attrib: 654 self.parse_error("ambiguous list type declaration", self) 655 656 else: 657 # List tag with itemType attribute that refers to a global type 658 try: 659 item_qname = self.schema.resolve_qname(elem.attrib['itemType']) 660 except KeyError: 661 self.parse_error("missing list type declaration", elem) 662 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 663 except ValueError as err: 664 self.parse_error(err, elem) 665 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 666 else: 667 try: 668 base_type = self.maps.lookup_type(item_qname) 669 except LookupError: 670 self.parse_error("unknown itemType %r" % elem.attrib['itemType'], elem) 671 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 672 673 if base_type.final == '#all' or 'list' in base_type.final: 674 self.parse_error("'final' value of the itemType %r forbids derivation by list" % base_type) 675 676 try: 677 self.base_type = base_type 678 except XMLSchemaValueError as err: 679 self.parse_error(str(err), elem) 680 self.base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE]
681 682 @property
683 - def admitted_facets(self):
684 return XSD_10_LIST_FACETS if self.schema.XSD_VERSION == '1.0' else XSD_11_LIST_FACETS
685 686 @property
687 - def item_type(self):
688 return self.base_type
689 690 @property
691 - def built(self):
692 return self.base_type.is_global or self.base_type.built
693 694 @property
695 - def validation_attempted(self):
696 if self.built: 697 return 'full' 698 else: 699 return self.base_type.validation_attempted
700 701 @staticmethod
702 - def is_atomic():
703 return False
704 705 @staticmethod
706 - def is_list():
707 return True
708
709 - def is_derived(self, other, derivation=None):
710 if self is other: 711 return True 712 elif derivation and self.derivation and derivation != self.derivation: 713 return False 714 elif other.name in self._special_types: 715 return True 716 elif self.base_type is other: 717 return True 718 else: 719 return False
720
721 - def iter_components(self, xsd_classes=None):
722 if xsd_classes is None or isinstance(self, xsd_classes): 723 yield self 724 if not self.base_type.is_global: 725 for obj in self.base_type.iter_components(xsd_classes): 726 yield obj
727
728 - def iter_decode(self, obj, validation='lax', **kwargs):
729 if isinstance(obj, (string_base_type, bytes)): 730 obj = self.normalize(obj) 731 732 if validation != 'skip' and self.patterns: 733 for error in self.patterns(obj): 734 if validation == 'strict': 735 raise error 736 yield error 737 738 items = [] 739 for chunk in obj.split(): 740 for result in self.base_type.iter_decode(chunk, validation, **kwargs): 741 if isinstance(result, XMLSchemaValidationError): 742 yield result 743 else: 744 items.append(result) 745 746 if validation != 'skip': 747 for validator in self.validators: 748 for error in validator(items): 749 if validation == 'strict': 750 raise error 751 yield error 752 753 yield items
754
755 - def iter_encode(self, obj, validation='lax', **kwargs):
756 if not hasattr(obj, '__iter__') or isinstance(obj, (str, unicode_type, bytes)): 757 obj = [obj] 758 759 if validation != 'skip': 760 for validator in self.validators: 761 for error in validator(obj): 762 if validation == 'strict': 763 raise error 764 yield error 765 766 encoded_items = [] 767 for item in obj: 768 for result in self.base_type.iter_encode(item, validation, **kwargs): 769 if isinstance(result, XMLSchemaValidationError): 770 yield result 771 else: 772 encoded_items.append(result) 773 774 yield ' '.join(item for item in encoded_items if item is not None)
775
776 777 -class XsdUnion(XsdSimpleType):
778 """ 779 Class for 'union' definitions. A union definition has a member_types 780 attribute that refers to a 'simpleType' definition. 781 782 <union 783 id = ID 784 memberTypes = List of QName 785 {any attributes with non-schema namespace ...}> 786 Content: (annotation?, simpleType*) 787 </union> 788 """ 789 _admitted_types = XsdSimpleType 790 _admitted_tags = {XSD_UNION} 791 792 member_types = None 793
794 - def __init__(self, elem, schema, parent, name=None):
795 super(XsdUnion, self).__init__(elem, schema, parent, name, facets=None)
796
797 - def __repr__(self):
798 if self.name is None: 799 return '%s(member_types=%r)' % (self.__class__.__name__, self.member_types) 800 else: 801 return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)
802
803 - def __setattr__(self, name, value):
804 if name == 'elem' and value is not None and value.tag != XSD_UNION: 805 if value.tag == XSD_SIMPLE_TYPE: 806 for child in value: 807 if child.tag == XSD_UNION: 808 super(XsdUnion, self).__setattr__(name, child) 809 return 810 raise XMLSchemaValueError("a %r definition required for %r." % (XSD_UNION, self)) 811 812 elif name == 'white_space': 813 if not (value is None or value == 'collapse'): 814 raise XMLSchemaValueError("Wrong value % for attribute 'white_space'." % value) 815 value = 'collapse' 816 super(XsdUnion, self).__setattr__(name, value)
817
818 - def _parse(self):
819 super(XsdUnion, self)._parse() 820 elem = self.elem 821 member_types = [] 822 823 for child in self._iterparse_components(elem): 824 mt = xsd_simple_type_factory(child, self.schema, self) 825 if isinstance(mt, XMLSchemaParseError): 826 self.parse_error(mt) 827 else: 828 member_types.append(mt) 829 830 if 'memberTypes' in elem.attrib: 831 for name in elem.attrib['memberTypes'].split(): 832 try: 833 type_qname = self.schema.resolve_qname(name) 834 except ValueError as err: 835 self.parse_error(err) 836 continue 837 838 try: 839 mt = self.maps.lookup_type(type_qname) 840 except LookupError: 841 self.parse_error("unknown member type %r" % type_qname) 842 mt = self.maps.types[XSD_ANY_ATOMIC_TYPE] 843 except XMLSchemaParseError as err: 844 self.parse_error(err) 845 mt = self.maps.types[XSD_ANY_ATOMIC_TYPE] 846 847 if isinstance(mt, tuple): 848 self.parse_error("circular definition found on xs:union type {!r}".format(self.name)) 849 continue 850 elif not isinstance(mt, self._admitted_types): 851 self.parse_error("a {!r} required, not {!r}".format(self._admitted_types, mt)) 852 continue 853 elif mt.final == '#all' or 'union' in mt.final: 854 self.parse_error("'final' value of the memberTypes %r forbids derivation by union" % member_types) 855 856 member_types.append(mt) 857 858 if member_types: 859 self.member_types = member_types 860 else: 861 self.parse_error("missing xs:union type declarations", elem) 862 self.member_types = [self.maps.types[XSD_ANY_ATOMIC_TYPE]]
863 864 @property
865 - def admitted_facets(self):
866 return XSD_10_UNION_FACETS if self.schema.XSD_VERSION == '1.0' else XSD_11_UNION_FACETS
867 868 @property
869 - def built(self):
870 return all([mt.is_global or mt.built for mt in self.member_types])
871 872 @property
873 - def validation_attempted(self):
874 if self.built: 875 return 'full' 876 elif any([mt.validation_attempted == 'partial' for mt in self.member_types]): 877 return 'partial' 878 else: 879 return 'none'
880
881 - def is_atomic(self):
882 return all(mt.is_atomic() for mt in self.member_types)
883
884 - def is_list(self):
885 return all(mt.is_list() for mt in self.member_types)
886
887 - def iter_components(self, xsd_classes=None):
888 if xsd_classes is None or isinstance(self, xsd_classes): 889 yield self 890 for mt in self.member_types: 891 if not mt.is_global: 892 for obj in mt.iter_components(xsd_classes): 893 yield obj
894
895 - def iter_decode(self, obj, validation='lax', **kwargs):
896 if isinstance(obj, (string_base_type, bytes)): 897 obj = self.normalize(obj) 898 899 if validation != 'skip' and self.patterns: 900 for error in self.patterns(obj): 901 if validation == 'strict': 902 raise error 903 yield error 904 905 # Try the text as a whole 906 for member_type in self.member_types: 907 for result in member_type.iter_decode(obj, validation='lax', **kwargs): 908 if not isinstance(result, XMLSchemaValidationError): 909 if validation != 'skip': 910 for validator in self.validators: 911 for error in validator(result): 912 if validation == 'strict': 913 raise error 914 yield error 915 916 yield result 917 return 918 break 919 920 if validation != 'skip' and ' ' not in obj.strip(): 921 reason = "no type suitable for decoding %r." % obj 922 yield self.decode_error(validation, obj, self.member_types, reason) 923 924 items = [] 925 not_decodable = [] 926 for chunk in obj.split(): 927 for member_type in self.member_types: 928 for result in member_type.iter_decode(chunk, validation='lax', **kwargs): 929 if isinstance(result, XMLSchemaValidationError): 930 break 931 else: 932 items.append(result) 933 else: 934 break 935 else: 936 if validation != 'skip': 937 not_decodable.append(chunk) 938 else: 939 items.append(unicode_type(chunk)) 940 941 if validation != 'skip': 942 if not_decodable: 943 reason = "no type suitable for decoding the values %r." % not_decodable 944 yield self.decode_error(validation, obj, self.member_types, reason) 945 946 for validator in self.validators: 947 for error in validator(items): 948 if validation == 'strict': 949 raise error 950 yield error 951 952 yield items if len(items) > 1 else items[0] if items else None
953
954 - def iter_encode(self, obj, validation='lax', **kwargs):
955 for member_type in self.member_types: 956 for result in member_type.iter_encode(obj, validation='lax', **kwargs): 957 if result is not None and not isinstance(result, XMLSchemaValidationError): 958 if validation != 'skip': 959 for validator in self.validators: 960 for error in validator(obj): 961 if validation == 'strict': 962 raise error 963 yield error 964 if self.patterns is not None: 965 for error in self.patterns(result): 966 if validation == 'strict': 967 raise error 968 yield error 969 970 yield result 971 return 972 elif validation == 'strict': 973 # In 'strict' mode avoid lax encoding by similar types (eg. float encoded by int) 974 break 975 976 if hasattr(obj, '__iter__') and not isinstance(obj, (str, unicode_type, bytes)): 977 for member_type in self.member_types: 978 results = [] 979 for item in obj: 980 for result in member_type.iter_encode(item, validation='lax', **kwargs): 981 if result is not None and not isinstance(result, XMLSchemaValidationError): 982 if validation != 'skip': 983 for validator in self.validators: 984 for error in validator(result): 985 if validation == 'strict': 986 raise error 987 yield error 988 if self.patterns is not None: 989 for error in self.patterns(result): 990 if validation == 'strict': 991 raise error 992 yield error 993 994 results.append(result) 995 break 996 elif validation == 'strict': 997 break 998 999 if len(results) == len(obj): 1000 yield results 1001 break 1002 1003 if validation != 'skip': 1004 reason = "no type suitable for encoding the object." 1005 yield self.encode_error(validation, obj, self.member_types, reason) 1006 yield None 1007 else: 1008 yield unicode_type(obj)
1009
1010 1011 -class Xsd11Union(XsdUnion):
1012 1013 _admitted_types = XsdAtomic, XsdList, XsdUnion
1014
1015 1016 -class XsdAtomicRestriction(XsdAtomic):
1017 """ 1018 Class for XSD 1.0 atomic simpleType and complexType's simpleContent restrictions. 1019 1020 <restriction 1021 base = QName 1022 id = ID 1023 {any attributes with non-schema namespace . . .}> 1024 Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | 1025 maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | 1026 enumeration | whiteSpace | pattern)*)) 1027 </restriction> 1028 """ 1029 FACETS_BUILDERS = XSD_10_FACETS_BUILDERS 1030 derivation = 'restriction' 1031
1032 - def __setattr__(self, name, value):
1033 if name == 'elem' and value is not None: 1034 if self.name != XSD_ANY_ATOMIC_TYPE and value.tag != XSD_RESTRICTION: 1035 if not (value.tag == XSD_SIMPLE_TYPE and value.get('name') is not None): 1036 raise XMLSchemaValueError("an xs:restriction definition required for %r." % self) 1037 super(XsdAtomicRestriction, self).__setattr__(name, value)
1038
1039 - def _parse(self):
1040 super(XsdAtomicRestriction, self)._parse() 1041 elem = self.elem 1042 if elem.get('name') == XSD_ANY_ATOMIC_TYPE: 1043 return # skip special type xs:anyAtomicType 1044 elif elem.tag == XSD_SIMPLE_TYPE and elem.get('name') is not None: 1045 elem = self._parse_component(elem) # Global simpleType with internal restriction 1046 1047 if self.name is not None and self.parent is not None: 1048 self.parse_error("'name' attribute in a local simpleType definition", elem) 1049 1050 base_type = None 1051 facets = {} 1052 has_attributes = False 1053 has_simple_type_child = False 1054 1055 if 'base' in elem.attrib: 1056 try: 1057 base_qname = self.schema.resolve_qname(elem.attrib['base']) 1058 except ValueError as err: 1059 self.parse_error(err, elem) 1060 base_type = self.maps.type[XSD_ANY_ATOMIC_TYPE] 1061 else: 1062 if base_qname == self.name: 1063 if self.redefine is None: 1064 self.parse_error("wrong definition with self-reference", elem) 1065 base_type = self.maps.type[XSD_ANY_ATOMIC_TYPE] 1066 else: 1067 base_type = self.base_type 1068 else: 1069 if self.redefine is not None: 1070 self.parse_error("wrong redefinition without self-reference", elem) 1071 1072 try: 1073 base_type = self.maps.lookup_type(base_qname) 1074 except LookupError: 1075 self.parse_error("unknown type %r." % elem.attrib['base']) 1076 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 1077 except XMLSchemaParseError as err: 1078 self.parse_error(err) 1079 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 1080 else: 1081 if isinstance(base_type, tuple): 1082 self.parse_error("circularity definition between %r and %r" % (self, base_qname), elem) 1083 base_type = self.maps.types[XSD_ANY_ATOMIC_TYPE] 1084 1085 if base_type.is_simple() and base_type.name == XSD_ANY_SIMPLE_TYPE: 1086 self.parse_error("wrong base type {!r}, an atomic type required") 1087 elif base_type.is_complex(): 1088 if base_type.mixed and base_type.is_emptiable(): 1089 if self._parse_component(elem, strict=False).tag != XSD_SIMPLE_TYPE: 1090 # See: "http://www.w3.org/TR/xmlschema-2/#element-restriction" 1091 self.parse_error( 1092 "when a complexType with simpleContent restricts a complexType " 1093 "with mixed and with emptiable content then a simpleType child " 1094 "declaration is required.", elem 1095 ) 1096 elif self.parent is None or self.parent.is_simple(): 1097 self.parse_error("simpleType restriction of %r is not allowed" % base_type, elem) 1098 1099 for child in self._iterparse_components(elem): 1100 if child.tag in {XSD_ATTRIBUTE, XSD_ATTRIBUTE_GROUP, XSD_ANY_ATTRIBUTE}: 1101 has_attributes = True # only if it's a complexType restriction 1102 elif has_attributes: 1103 self.parse_error("unexpected tag after attribute declarations", child) 1104 elif child.tag == XSD_SIMPLE_TYPE: 1105 # Case of simpleType declaration inside a restriction 1106 if has_simple_type_child: 1107 self.parse_error("duplicated simpleType declaration", child) 1108 1109 if base_type is None: 1110 try: 1111 base_type = xsd_simple_type_factory(child, self.schema, self) 1112 except XMLSchemaParseError as err: 1113 self.parse_error(err) 1114 base_type = self.maps.types[XSD_ANY_SIMPLE_TYPE] 1115 elif base_type.is_complex(): 1116 if base_type.admit_simple_restriction(): 1117 base_type = self.schema.BUILDERS.complex_type_class( 1118 elem=elem, 1119 schema=self.schema, 1120 parent=self, 1121 content_type=xsd_simple_type_factory(child, self.schema, self), 1122 attributes=base_type.attributes, 1123 mixed=base_type.mixed, 1124 block=base_type.block, 1125 final=base_type.final, 1126 ) 1127 elif 'base' in elem.attrib: 1128 self.parse_error("restriction with 'base' attribute and simpleType declaration", child) 1129 1130 has_simple_type_child = True 1131 else: 1132 try: 1133 facet_class = self.FACETS_BUILDERS[child.tag] 1134 except KeyError: 1135 self.parse_error("unexpected tag %r in restriction:" % child.tag) 1136 continue 1137 1138 if child.tag not in facets: 1139 facets[child.tag] = facet_class(child, self.schema, self, base_type) 1140 elif child.tag not in MULTIPLE_FACETS: 1141 self.parse_error("multiple %r constraint facet" % local_name(child.tag)) 1142 elif child.tag != XSD_ASSERTION: 1143 facets[child.tag].append(child) 1144 else: 1145 assertion = facet_class(child, self.schema, self, base_type) 1146 try: 1147 facets[child.tag].append(assertion) 1148 except AttributeError: 1149 facets[child.tag] = [facets[child.tag], assertion] 1150 1151 if base_type is None: 1152 self.parse_error("missing base type in restriction:", self) 1153 elif base_type.final == '#all' or 'restriction' in base_type.final: 1154 self.parse_error("'final' value of the baseType %r forbids derivation by restriction" % base_type) 1155 1156 self.base_type = base_type 1157 self.facets = facets
1158
1159 - def iter_components(self, xsd_classes=None):
1160 if xsd_classes is None or isinstance(self, xsd_classes): 1161 yield self 1162 if not self.base_type.is_global: 1163 for obj in self.base_type.iter_components(xsd_classes): 1164 yield obj
1165
1166 - def iter_decode(self, obj, validation='lax', **kwargs):
1167 if isinstance(obj, (string_base_type, bytes)): 1168 obj = self.normalize(obj) 1169 1170 if validation != 'skip' and self.patterns: 1171 for error in self.patterns(obj): 1172 if validation == 'strict': 1173 raise error 1174 yield error 1175 1176 if self.base_type.is_simple(): 1177 base_type = self.base_type 1178 elif self.base_type.has_simple_content(): 1179 base_type = self.base_type.content_type 1180 elif self.base_type.mixed: 1181 yield obj 1182 return 1183 else: 1184 raise XMLSchemaValueError("wrong base type %r: a simpleType or a complexType with " 1185 "simple or mixed content required." % self.base_type) 1186 1187 for result in base_type.iter_decode(obj, validation, **kwargs): 1188 if isinstance(result, XMLSchemaValidationError): 1189 yield result 1190 if isinstance(result, XMLSchemaDecodeError): 1191 yield unicode_type(obj) if validation == 'skip' else None 1192 else: 1193 if validation != 'skip': 1194 for validator in self.validators: 1195 for error in validator(result): 1196 if validation == 'strict': 1197 raise error 1198 yield error 1199 1200 yield result 1201 return
1202
1203 - def iter_encode(self, obj, validation='lax', **kwargs):
1204 if self.is_list(): 1205 if not hasattr(obj, '__iter__') or isinstance(obj, (str, unicode_type, bytes)): 1206 obj = [] if obj is None or obj == '' else [obj] 1207 1208 if validation != 'skip': 1209 for validator in self.validators: 1210 for error in validator(obj): 1211 if validation == 'strict': 1212 raise error 1213 yield error 1214 1215 for result in self.base_type.iter_encode(obj, validation): 1216 if isinstance(result, XMLSchemaValidationError): 1217 if validation == 'strict': 1218 raise result 1219 yield result 1220 if isinstance(result, XMLSchemaEncodeError): 1221 yield unicode_type(obj) if validation == 'skip' else None 1222 return 1223 else: 1224 yield result 1225 return 1226 1227 if isinstance(obj, (string_base_type, bytes)): 1228 obj = self.normalize(obj) 1229 1230 if self.base_type.is_simple(): 1231 base_type = self.base_type 1232 elif self.base_type.has_simple_content(): 1233 base_type = self.base_type.content_type 1234 elif self.base_type.mixed: 1235 yield unicode_type(obj) 1236 return 1237 else: 1238 raise XMLSchemaValueError("wrong base type %r: a simpleType or a complexType with " 1239 "simple or mixed content required." % self.base_type) 1240 1241 for result in base_type.iter_encode(obj, validation): 1242 if isinstance(result, XMLSchemaValidationError): 1243 if validation == 'strict': 1244 raise result 1245 yield result 1246 if isinstance(result, XMLSchemaEncodeError): 1247 yield unicode_type(obj) if validation == 'skip' else None 1248 return 1249 else: 1250 if validation != 'skip': 1251 for validator in self.validators: 1252 for error in validator(obj): 1253 if validation == 'strict': 1254 raise error 1255 yield error 1256 1257 yield result 1258 return
1259
1260 - def is_list(self):
1261 return self.primitive_type.is_list()
1262
1263 1264 -class Xsd11AtomicRestriction(XsdAtomicRestriction):
1265 """ 1266 Class for XSD 1.1 atomic simpleType and complexType's simpleContent restrictions. 1267 1268 <restriction 1269 base = QName 1270 id = ID 1271 {any attributes with non-schema namespace . . .}> 1272 Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | 1273 maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | 1274 enumeration | whiteSpace | pattern | assertion | explicitTimezone | 1275 {any with namespace: ##other})*)) 1276 </restriction> 1277 """ 1278 FACETS_BUILDERS = XSD_11_FACETS_BUILDERS
1279