1# 2# Copyright (c), 2016-2020, SISSA (International School for Advanced Studies). 3# All rights reserved. 4# This file is distributed under the terms of the MIT License. 5# See the file 'LICENSE' in the root directory of the present 6# distribution, or http://opensource.org/licenses/MIT. 7# 8# @author Davide Brunato <brunato@sissa.it> 9# 10from decimal import Decimal 11from math import isinf, isnan 12from typing import Optional, Set, Union 13from xml.etree.ElementTree import Element 14from elementpath import datatypes 15 16from ..exceptions import XMLSchemaValueError 17from .exceptions import XMLSchemaValidationError 18 19XSD_FINAL_ATTRIBUTE_VALUES = {'restriction', 'extension', 'list', 'union'} 20 21 22def get_xsd_derivation_attribute(elem: Element, attribute: str, 23 values: Optional[Set[str]] = None) -> str: 24 """ 25 Get a derivation attribute (maybe 'block', 'blockDefault', 'final' or 'finalDefault') 26 checking the items with the values arguments. Returns a string. 27 28 :param elem: the Element instance. 29 :param attribute: the attribute name. 30 :param values: a set of admitted values when the attribute value is not '#all'. 31 """ 32 value = elem.get(attribute) 33 if value is None: 34 return '' 35 36 if values is None: 37 values = XSD_FINAL_ATTRIBUTE_VALUES 38 39 items = value.split() 40 if len(items) == 1 and items[0] == '#all': 41 return ' '.join(values) 42 elif not all(s in values for s in items): 43 raise ValueError("wrong value %r for attribute %r" % (value, attribute)) 44 return value 45 46 47# 48# XSD built-in types validator functions 49 50def decimal_validator(value: Union[Decimal, int, float, str]) -> None: 51 try: 52 if not isinstance(value, (Decimal, float)): 53 datatypes.DecimalProxy.validate(value) 54 elif isinf(value) or isnan(value): 55 raise ValueError() 56 except (ValueError, TypeError): 57 raise XMLSchemaValidationError(decimal_validator, value, 58 "value is not a valid xs:decimal") from None 59 60 61def qname_validator(value: str) -> None: 62 if datatypes.QName.pattern.match(value) is None: 63 raise XMLSchemaValidationError(qname_validator, value, 64 "value is not an xs:QName") 65 66 67def byte_validator(value: int) -> None: 68 if not (-2**7 <= value < 2 ** 7): 69 raise XMLSchemaValidationError(int_validator, value, 70 "value must be -128 <= x < 128") 71 72 73def short_validator(value: int) -> None: 74 if not (-2**15 <= value < 2 ** 15): 75 raise XMLSchemaValidationError(short_validator, value, 76 "value must be -2^15 <= x < 2^15") 77 78 79def int_validator(value: int) -> None: 80 if not (-2**31 <= value < 2 ** 31): 81 raise XMLSchemaValidationError(int_validator, value, 82 "value must be -2^31 <= x < 2^31") 83 84 85def long_validator(value: int) -> None: 86 if not (-2**63 <= value < 2 ** 63): 87 raise XMLSchemaValidationError(long_validator, value, 88 "value must be -2^63 <= x < 2^63") 89 90 91def unsigned_byte_validator(value: int) -> None: 92 if not (0 <= value < 2 ** 8): 93 raise XMLSchemaValidationError(unsigned_byte_validator, value, 94 "value must be 0 <= x < 256") 95 96 97def unsigned_short_validator(value: int) -> None: 98 if not (0 <= value < 2 ** 16): 99 raise XMLSchemaValidationError(unsigned_short_validator, value, 100 "value must be 0 <= x < 2^16") 101 102 103def unsigned_int_validator(value: int) -> None: 104 if not (0 <= value < 2 ** 32): 105 raise XMLSchemaValidationError(unsigned_int_validator, value, 106 "value must be 0 <= x < 2^32") 107 108 109def unsigned_long_validator(value: int) -> None: 110 if not (0 <= value < 2 ** 64): 111 raise XMLSchemaValidationError(unsigned_long_validator, value, 112 "value must be 0 <= x < 2^64") 113 114 115def negative_int_validator(value: int) -> None: 116 if value >= 0: 117 raise XMLSchemaValidationError(negative_int_validator, value, 118 "value must be negative") 119 120 121def positive_int_validator(value: int) -> None: 122 if value <= 0: 123 raise XMLSchemaValidationError(positive_int_validator, value, 124 "value must be positive") 125 126 127def non_positive_int_validator(value: int) -> None: 128 if value > 0: 129 raise XMLSchemaValidationError(non_positive_int_validator, value, 130 "value must be non positive") 131 132 133def non_negative_int_validator(value: int) -> None: 134 if value < 0: 135 raise XMLSchemaValidationError(non_negative_int_validator, value, 136 "value must be non negative") 137 138 139def hex_binary_validator(value: Union[str, datatypes.HexBinary]) -> None: 140 if not isinstance(value, datatypes.HexBinary) and \ 141 datatypes.HexBinary.pattern.match(value) is None: 142 raise XMLSchemaValidationError(hex_binary_validator, value, 143 "not an hexadecimal number") 144 145 146def base64_binary_validator(value: Union[str, datatypes.Base64Binary]) -> None: 147 if isinstance(value, datatypes.Base64Binary): 148 return 149 value = value.replace(' ', '') 150 if not value: 151 return 152 153 match = datatypes.Base64Binary.pattern.match(value) 154 if match is None or match.group(0) != value: 155 raise XMLSchemaValidationError(base64_binary_validator, value, 156 "not a base64 encoding") 157 158 159def error_type_validator(value: object) -> None: 160 raise XMLSchemaValidationError(error_type_validator, value, 161 "no value is allowed for xs:error type") 162 163 164# 165# XSD builtin decoding functions 166 167def boolean_to_python(value: str) -> bool: 168 if value in {'true', '1'}: 169 return True 170 elif value in {'false', '0'}: 171 return False 172 else: 173 raise XMLSchemaValueError('{!r} is not a boolean value'.format(value)) 174 175 176def python_to_boolean(value: object) -> str: 177 return str(value).lower() 178