class XMLSchemaValueError(XMLSchemaException, ValueError):
    pass XSD_LENGTH = _XSD_TEMPLATE % 'length' XSD_MIN_LENGTH = _XSD_TEMPLATE % 'minLength' XSD_MAX_LENGTH = _XSD_TEMPLATE % 'maxLength' XSD_ENUMERATION = _XSD_TEMPLATE % 'enumeration' XSD_PATTERN = _XSD_TEMPLATE % 'pattern'              # lexical facet XSD_WHITE_SPACE = _XSD_TEMPLATE % 'whiteSpace'       # pre-lexical facet XSD_MIN_INCLUSIVE = _XSD_TEMPLATE % 'minInclusive' XSD_MIN_EXCLUSIVE = _XSD_TEMPLATE % 'minExclusive' XSD_MAX_INCLUSIVE = _XSD_TEMPLATE % 'maxInclusive' XSD_MAX_EXCLUSIVE = _XSD_TEMPLATE % 'maxExclusive' XSD_TOTAL_DIGITS = _XSD_TEMPLATE % 'totalDigits' XSD_FRACTION_DIGITS = _XSD_TEMPLATE % 'fractionDigits' XSD_EXPLICIT_TIMEZONE = _XSD_TEMPLATE % 'explicitTimezone' XSD_STRING = _XSD_TEMPLATE % 'string' XSD_NORMALIZED_STRING = _XSD_TEMPLATE % 'normalizedString' XSD_NAME = _XSD_TEMPLATE % 'Name' XSD_NCNAME = _XSD_TEMPLATE % 'NCName' XSD_QNAME = _XSD_TEMPLATE % 'QName' XSD_TOKEN = _XSD_TEMPLATE % 'token' XSD_NMTOKEN = _XSD_TEMPLATE % 'NMTOKEN' XSD_ID = _XSD_TEMPLATE % 'ID' XSD_IDREF = _XSD_TEMPLATE % 'IDREF' XSD_LANGUAGE = _XSD_TEMPLATE % 'language' XSD_DECIMAL = _XSD_TEMPLATE % 'decimal' XSD_DOUBLE = _XSD_TEMPLATE % 'double' XSD_FLOAT = _XSD_TEMPLATE % 'float' XSD_INTEGER = _XSD_TEMPLATE % 'integer' XSD_BYTE = _XSD_TEMPLATE % 'byte' XSD_SHORT = _XSD_TEMPLATE % 'short' XSD_INT = _XSD_TEMPLATE % 'int' XSD_LONG = _XSD_TEMPLATE % 'long' XSD_UNSIGNED_BYTE = _XSD_TEMPLATE % 'unsignedByte' XSD_UNSIGNED_SHORT = _XSD_TEMPLATE % 'unsignedShort' XSD_UNSIGNED_INT = _XSD_TEMPLATE % 'unsignedInt' XSD_UNSIGNED_LONG = _XSD_TEMPLATE % 'unsignedLong' XSD_POSITIVE_INTEGER = _XSD_TEMPLATE % 'positiveInteger' XSD_NEGATIVE_INTEGER = _XSD_TEMPLATE % 'negativeInteger' XSD_NON_NEGATIVE_INTEGER = _XSD_TEMPLATE % 'nonNegativeInteger' XSD_NON_POSITIVE_INTEGER = _XSD_TEMPLATE % 'nonPositiveInteger' XSD_GDAY = _XSD_TEMPLATE % 'gDay' XSD_GMONTH = _XSD_TEMPLATE % 'gMonth' XSD_GMONTH_DAY = _XSD_TEMPLATE % 'gMonthDay' XSD_GYEAR = _XSD_TEMPLATE % 'gYear' XSD_GYEAR_MONTH = _XSD_TEMPLATE % 'gYearMonth' XSD_TIME = _XSD_TEMPLATE % 'time' XSD_DATE = _XSD_TEMPLATE % 'date' XSD_DATETIME = _XSD_TEMPLATE % 'dateTime' XSD_DATE_TIME_STAMP = _XSD_TEMPLATE % 'dateTimeStamp' XSD_ENTITY = _XSD_TEMPLATE % 'ENTITY' XSD_ANY_URI = _XSD_TEMPLATE % 'anyURI' XSD_BOOLEAN = _XSD_TEMPLATE % 'boolean' XSD_DURATION = _XSD_TEMPLATE % 'duration' XSD_DAY_TIME_DURATION = _XSD_TEMPLATE % 'dayTimeDuration' XSD_YEAR_MONTH_DURATION = _XSD_TEMPLATE % 'yearMonthDuration' XSD_BASE64_BINARY = _XSD_TEMPLATE % 'base64Binary' XSD_HEX_BINARY = _XSD_TEMPLATE % 'hexBinary' XSD_NOTATION_TYPE = _XSD_TEMPLATE % 'NOTATION' XSD_ERROR = _XSD_TEMPLATE % 'error' XSD_ASSERTION = _XSD_TEMPLATE % 'assertion'                      # facets XSD_SIMPLE_TYPE = _XSD_TEMPLATE % 'simpleType' XSD_ANY_TYPE = _XSD_TEMPLATE % 'anyType' XSD_ANY_ATOMIC_TYPE = _XSD_TEMPLATE % 'anyAtomicType' XSD_ANY_SIMPLE_TYPE = _XSD_TEMPLATE % 'anySimpleType' _REGEX_NS_PREFIX = re.compile(r'ns\d+$')
class SafeXMLParser(PyElementTree.XMLParser):
    def __init__(self, target: Optional[Any] = None, encoding: Optional[str] = None) -> None:
    def entity_declaration(self, entity_name, is_parameter_entity, value, base,  # type: ignore
                           system_id, public_id, notation_name):
    def unparsed_entity_declaration(self, entity_name, base, system_id,  # type: ignore
                                    public_id, notation_name):
    def external_entity_reference(self, context, base, system_id, public_id):  # type: ignore
def is_etree_element(obj: Any) -> bool:
def etree_tostring(elem: etree_element,
                   namespaces: Optional[MutableMapping[str, str]] = None,
                   indent: str = '',
                   max_lines: Optional[int] = None,
                   spaces_for_tab: Optional[int] = None,
                   xml_declaration: Optional[bool] = None,
                   encoding: str = 'unicode',
                   method: str = 'xml') -> Union[str, bytes]:
    def reindent(line: str) -> str: C = TypeVar('C')
D = TypeVar('D')
E = TypeVar('E')
T = TypeVar('T') def decimal_validator(value: Union[Decimal, int, float, str]) -> None:
    try:
        if not isinstance(value, (Decimal, float)):
            datatypes.DecimalProxy.validate(value)
        elif isinf(value) or isnan(value):
            raise ValueError()
    except (ValueError, TypeError):
        raise XMLSchemaValidationError(decimal_validator, value,
                                       "value is not a valid xs:decimal") from None def qname_validator(value: str) -> None:
    if datatypes.QName.pattern.match(value) is None:
        raise XMLSchemaValidationError(qname_validator, value,
                                       "value is not an xs:QName") def byte_validator(value: int) -> None:
    if not (-2**7 <= value < 2 ** 7):
        raise XMLSchemaValidationError(int_validator, value,
                                       "value must be -128 <= x < 128") def short_validator(value: int) -> None:
    if not (-2**15 <= value < 2 ** 15):
        raise XMLSchemaValidationError(short_validator, value,
                                       "value must be -2^15 <= x < 2^15") def int_validator(value: int) -> None:
    if not (-2**31 <= value < 2 ** 31):
        raise XMLSchemaValidationError(int_validator, value,
                                       "value must be -2^31 <= x < 2^31") def long_validator(value: int) -> None:
    if not (-2**63 <= value < 2 ** 63):
        raise XMLSchemaValidationError(long_validator, value,
                                       "value must be -2^63 <= x < 2^63") def unsigned_byte_validator(value: int) -> None:
    if not (0 <= value < 2 ** 8):
        raise XMLSchemaValidationError(unsigned_byte_validator, value,
                                       "value must be 0 <= x < 256") def unsigned_short_validator(value: int) -> None:
    if not (0 <= value < 2 ** 16):
        raise XMLSchemaValidationError(unsigned_short_validator, value,
                                       "value must be 0 <= x < 2^16") def unsigned_int_validator(value: int) -> None:
    if not (0 <= value < 2 ** 32):
        raise XMLSchemaValidationError(unsigned_int_validator, value,
                                       "value must be 0 <= x < 2^32") def unsigned_long_validator(value: int) -> None:
    if not (0 <= value < 2 ** 64):
        raise XMLSchemaValidationError(unsigned_long_validator, value,
                                       "value must be 0 <= x < 2^64") def negative_int_validator(value: int) -> None:
    if value >= 0:
        raise XMLSchemaValidationError(negative_int_validator, value,
                                       "value must be negative") def positive_int_validator(value: int) -> None:
    if value <= 0:
        raise XMLSchemaValidationError(positive_int_validator, value,
                                       "value must be positive") def non_positive_int_validator(value: int) -> None:
    if value > 0:
        raise XMLSchemaValidationError(non_positive_int_validator, value,
                                       "value must be non positive") def non_negative_int_validator(value: int) -> None:
    if value < 0:
        raise XMLSchemaValidationError(non_negative_int_validator, value,
                                       "value must be non negative") def hex_binary_validator(value: Union[str, datatypes.HexBinary]) -> None:
    if not isinstance(value, datatypes.HexBinary) and \
            datatypes.HexBinary.pattern.match(value) is None:
        raise XMLSchemaValidationError(hex_binary_validator, value,
                                       "not an hexadecimal number") def base64_binary_validator(value: Union[str, datatypes.Base64Binary]) -> None:
    if isinstance(value, datatypes.Base64Binary):
        return
    value = value.replace(' ', '')
    if not value:
        return

    match = datatypes.Base64Binary.pattern.match(value)
    if match is None or match.group(0) != value:
        raise XMLSchemaValidationError(base64_binary_validator, value,
                                       "not a base64 encoding") def error_type_validator(value: object) -> None:
    raise XMLSchemaValidationError(error_type_validator, value,
                                   "no value is allowed for xs:error type") def boolean_to_python(value: str) -> bool:
    if value in {'true', '1'}:
        return True
    elif value in {'false', '0'}:
        return False
    else:
        raise XMLSchemaValueError('{!r} is not a boolean value'.format(value)) def python_to_boolean(value: object) -> str:
    return str(value).lower() XSD_10_FACETS_BUILDERS = {
    XSD_WHITE_SPACE: XsdWhiteSpaceFacet,
    XSD_LENGTH: XsdLengthFacet,
    XSD_MIN_LENGTH: XsdMinLengthFacet,
    XSD_MAX_LENGTH: XsdMaxLengthFacet,
    XSD_MIN_INCLUSIVE: XsdMinInclusiveFacet,
    XSD_MIN_EXCLUSIVE: XsdMinExclusiveFacet,
    XSD_MAX_INCLUSIVE: XsdMaxInclusiveFacet,
    XSD_MAX_EXCLUSIVE: XsdMaxExclusiveFacet,
    XSD_TOTAL_DIGITS: XsdTotalDigitsFacet,
    XSD_FRACTION_DIGITS: XsdFractionDigitsFacet,
    XSD_ENUMERATION: XsdEnumerationFacets,
    XSD_PATTERN: XsdPatternFacets
} XSD_11_FACETS_BUILDERS = XSD_10_FACETS_BUILDERS.copy() class XsdSimpleType(XsdType, ValidationMixin[Union[str, bytes], DecodedValueType]):
    """
    Base class for simpleTypes definitions. Generally used only for
    instances of xs:anySimpleType.

    ..  <simpleType
          final = (#all | List of (list | union | restriction | extension))
          id = ID
          name = NCName
          {any attributes with non-schema namespace . . .}>
          Content: (annotation?, (restriction | list | union))
        </simpleType>
    """
    _special_types = {XSD_ANY_TYPE, XSD_ANY_SIMPLE_TYPE}
    _ADMITTED_TAGS = {XSD_SIMPLE_TYPE}
    copy: Callable[['XsdSimpleType'], 'XsdSimpleType']

    block: str = ''
    min_length: Optional[int] = None
    max_length: Optional[int] = None
    white_space: Optional[str] = None
    patterns = None
    validators: Union[Tuple[()], List[Union[XsdFacet, Callable[[Any], None]]]] = ()
    allow_empty = True
    facets: Dict[Optional[str], FacetsValueType]

    python_type: PythonTypeClasses
    instance_types: Union[PythonTypeClasses, Tuple[PythonTypeClasses]]

    # Unicode string as default datatype for XSD simple types
    python_type = instance_types = to_python = from_python = str

    def __init__(self, elem: ElementType,
                 schema: SchemaType,
                 parent: Optional[XsdComponent] = None,
                 name: Optional[str] = None,
                 facets: Optional[Dict[Optional[str], FacetsValueType]] = None) -> None:

        super(XsdSimpleType, self).__init__(elem, schema, parent, name)
        if not hasattr(self, 'facets'):
            self.facets = facets if facets is not None else {}

    def __setattr__(self, name: str, value: Any) -> None:
        super(XsdSimpleType, self).__setattr__(name, value)
        if name == 'facets':
            if not isinstance(self, XsdAtomicBuiltin):
                self._parse_facets(value)

            if self.min_length:
                self.allow_empty = False

            white_space = getattr(self.get_facet(XSD_WHITE_SPACE), 'value', None)
            if white_space is not None:
                self.white_space = white_space

            patterns = self.get_facet(XSD_PATTERN)
            if isinstance(patterns, XsdPatternFacets):
                self.patterns = patterns
                if all(p.match('') is None for p in patterns.patterns):
                    self.allow_empty = False

            enumeration = self.get_facet(XSD_ENUMERATION)
            if isinstance(enumeration, XsdEnumerationFacets) \
                    and '' not in enumeration.enumeration:
                self.allow_empty = False

            if value:
                validators: List[Union[XsdFacet, Callable[[Any], None]]]
                if None in value:
                    validators = [value[None]]  # Use only the validator function!
                else:
                    validators = [v for k, v in value.items()
                                  if k not in {XSD_WHITE_SPACE, XSD_PATTERN, XSD_ASSERTION}]
                if XSD_ASSERTION in value:
                    assertions: Union[XsdAssertionFacet, List[XsdAssertionFacet]]
                    assertions = value[XSD_ASSERTION]
                    if isinstance(assertions, list):
                        validators.extend(assertions)
                    else:
                        validators.append(assertions)
                if validators:
                    self.validators = validators

    def _parse_facets(self, facets: Any) -> None:
        base_type: Any

        if facets and self.base_type is not None:
            if isinstance(self.base_type, XsdSimpleType):
                if self.base_type.name == XSD_ANY_SIMPLE_TYPE:
                    self.parse_error(
                        "facets not allowed for a direct derivation of xs:anySimpleType"
                    )
            elif self.base_type.has_simple_content():
                if self.base_type.content.name == XSD_ANY_SIMPLE_TYPE:
                    self.parse_error(
                        "facets not allowed for a direct content derivation of xs:anySimpleType"
                    )

        # Checks the applicability of the facets
        if any(k not in self.admitted_facets for k in facets if k is not None):
            reason = "one or more facets are not applicable, admitted set is %r:"
            self.parse_error(reason % {local_name(e) for e in self.admitted_facets if e})

        # Check group base_type
        base_type = {t.base_type for t in facets.values() if isinstance(t, XsdFacet)}
        if len(base_type) > 1:
            self.parse_error("facet group must have the same base_type: %r" % base_type)
        base_type = base_type.pop() if base_type else None

        # Checks length based facets
        length = getattr(facets.get(XSD_LENGTH), 'value', None)
        min_length = getattr(facets.get(XSD_MIN_LENGTH), 'value', None)
        max_length = getattr(facets.get(XSD_MAX_LENGTH), 'value', None)
        if length is not None:
            if length < 0:
                self.parse_error("'length' value must be non negative integer")
            if min_length is not None:
                if min_length > length:
                    self.parse_error("'minLength' value must be less or equal to 'length'")
                min_length_facet = base_type.get_facet(XSD_MIN_LENGTH)
                length_facet = base_type.get_facet(XSD_LENGTH)
                if (min_length_facet is None
                        or (length_facet is not None
                            and length_facet.base_type == min_length_facet.base_type)):
                    self.parse_error("cannot specify both 'length' and 'minLength'")
            if max_length is not None:
                if max_length < length:
                    self.parse_error("'maxLength' value must be greater or equal to 'length'")
                max_length_facet = base_type.get_facet(XSD_MAX_LENGTH)
                length_facet = base_type.get_facet(XSD_LENGTH)
                if max_length_facet is None \
                        or (length_facet is not None
                            and length_facet.base_type == max_length_facet.base_type):
                    self.parse_error("cannot specify both 'length' and 'maxLength'")
            min_length = max_length = length
        elif min_length is not None or max_length is not None:
            min_length_facet = base_type.get_facet(XSD_MIN_LENGTH)
            max_length_facet = base_type.get_facet(XSD_MAX_LENGTH)
            if min_length is not None:
                if min_length < 0:
                    self.parse_error("'minLength' value must be non negative integer")
                if max_length is not None and max_length < min_length:
                    self.parse_error("'maxLength' value is lesser than 'minLength'")
                if min_length_facet is not None and min_length_facet.value > min_length:
                    self.parse_error("'minLength' has a lesser value than parent")
                if max_length_facet is not None and min_length > max_length_facet.value:
                    self.parse_error("'minLength' has a greater value than parent 'maxLength'")

            if max_length is not None:
                if max_length < 0:
                    self.parse_error("'maxLength' value mu  st be non negative integer")
                if min_length_facet is not None and min_length_facet.value > max_length:
                    self.parse_error("'maxLength' has a lesser value than parent 'minLength'")
                if max_length_facet is not None and max_length > max_length_facet.value:
                    self.parse_error("'maxLength' has a greater value than parent")

        # Checks min/max values
        min_inclusive = getattr(facets.get(XSD_MIN_INCLUSIVE), 'value', None)
        min_exclusive = getattr(facets.get(XSD_MIN_EXCLUSIVE), 'value', None)
        max_inclusive = getattr(facets.get(XSD_MAX_INCLUSIVE), 'value', None)
        max_exclusive = getattr(facets.get(XSD_MAX_EXCLUSIVE), 'value', None)

        if min_inclusive is not None:
            if min_exclusive is not None:
                self.parse_error("cannot specify both 'minInclusive' and 'minExclusive")
            if max_inclusive is not None and min_inclusive > max_inclusive:
                self.parse_error("'minInclusive' must be less or equal to 'maxInclusive'")
            elif max_exclusive is not None and min_inclusive >= max_exclusive:
                self.parse_error("'minInclusive' must be lesser than 'maxExclusive'")

        elif min_exclusive is not None:
            if max_inclusive is not None and min_exclusive >= max_inclusive:
                self.parse_error("'minExclusive' must be lesser than 'maxInclusive'")
            elif max_exclusive is not None and min_exclusive > max_exclusive:
                self.parse_error("'minExclusive' must be less or equal to 'maxExclusive'")

        if max_inclusive is not None and max_exclusive is not None:
            self.parse_error("cannot specify both 'maxInclusive' and 'maxExclusive")

        # Checks fraction digits
        if XSD_TOTAL_DIGITS in facets:
            if XSD_FRACTION_DIGITS in facets and \
                    facets[XSD_TOTAL_DIGITS].value < facets[XSD_FRACTION_DIGITS].value:
                self.parse_error("fractionDigits facet value cannot be lesser than the "
                                 "value of totalDigits facet")
            total_digits = base_type.get_facet(XSD_TOTAL_DIGITS)
            if total_digits is not None and total_digits.value < facets[XSD_TOTAL_DIGITS].value:
                self.parse_error("totalDigits facet value cannot be greater than "
                                 "the value of the same facet in the base type")

        # Checks XSD 1.1 facets
        if XSD_EXPLICIT_TIMEZONE in facets:
            explicit_tz_facet = base_type.get_facet(XSD_EXPLICIT_TIMEZONE)
            if explicit_tz_facet and explicit_tz_facet.value in ('prohibited', 'required') \
                    and facets[XSD_EXPLICIT_TIMEZONE].value != explicit_tz_facet.value:
                self.parse_error("the explicitTimezone facet value cannot be changed if the base "
                                 "type has the same facet with value %r" % explicit_tz_facet.value)

        self.min_length = min_length
        self.max_length = max_length

    @property
    def variety(self) -> Optional[str]:
        return None

    @property
    def simple_type(self) -> 'XsdSimpleType':
        return self

    @property
    def min_value(self) -> Optional[AtomicValueType]:
        min_exclusive: Optional['AtomicValueType']
        min_inclusive: Optional['AtomicValueType']
        min_exclusive = cast(
            Optional['AtomicValueType'],
            getattr(self.get_facet(XSD_MIN_EXCLUSIVE), 'value', None)
        )
        min_inclusive = cast(
            Optional['AtomicValueType'],
            getattr(self.get_facet(XSD_MIN_INCLUSIVE), 'value', None)
        )

        if min_exclusive is None:
            return min_inclusive
        elif min_inclusive is None:
            return min_exclusive
        elif min_inclusive <= min_exclusive:  # type: ignore[operator]
            return min_exclusive
        else:
            return min_inclusive

    @property
    def max_value(self) -> Optional[AtomicValueType]:
        max_exclusive: Optional['AtomicValueType']
        max_inclusive: Optional['AtomicValueType']
        max_exclusive = cast(
            Optional['AtomicValueType'],
            getattr(self.get_facet(XSD_MAX_EXCLUSIVE), 'value', None)
        )
        max_inclusive = cast(
            Optional['AtomicValueType'],
            getattr(self.get_facet(XSD_MAX_INCLUSIVE), 'value', None)
        )

        if max_exclusive is None:
            return max_inclusive
        elif max_inclusive is None:
            return max_exclusive
        elif max_inclusive >= max_exclusive:  # type: ignore[operator]
            return max_exclusive
        else:
            return max_inclusive

    @property
    def enumeration(self) -> Optional[List[Optional[AtomicValueType]]]:
        enumeration = self.get_facet(XSD_ENUMERATION)
        if isinstance(enumeration, XsdEnumerationFacets):
            return enumeration.enumeration
        return None

    @property
    def admitted_facets(self) -> Set[str]:
        return XSD_10_FACETS if self.xsd_version == '1.0' else XSD_11_FACETS

    @property
    def built(self) -> bool:
        return True

    @staticmethod
    def is_simple() -> bool:
        return True

    @staticmethod
    def is_complex() -> bool:
        return False

    @property
    def content_type_label(self) -> str:
        return 'empty' if self.max_length == 0 else 'simple'

    @property
    def sequence_type(self) -> str:
        if self.is_empty():
            return 'empty-sequence()'

        root_type = self.root_type
        if root_type.name is not None:
            sequence_type = cast(str, root_type.prefixed_name)
        else:
            sequence_type = get_prefixed_qname(XSD_UNTYPED_ATOMIC, self.namespaces)

        if not self.is_list():
            return sequence_type
        elif self.is_emptiable():
            return '{}*'.format(sequence_type)
        else:
            return '{}+'.format(sequence_type)

    def is_empty(self) -> bool:
        return self.max_length == 0 or \
            self.enumeration is not None and all(v == '' for v in self.enumeration)

    def is_emptiable(self) -> bool:
        return self.allow_empty

    def has_simple_content(self) -> bool:
        return self.max_length != 0

    def has_complex_content(self) -> bool:
        return False

    def has_mixed_content(self) -> bool:
        return False

    def is_element_only(self) -> bool:
        return False

    def is_derived(self, other: Union[BaseXsdType, Tuple[ElementType, SchemaType]],
                   derivation: Optional[str] = None) -> bool:
        if self is other:
            return True
        elif isinstance(other, tuple):
            other[1].parse_error(f"global type {other[0].tag!r} is not built")
            return False
        elif derivation and self.derivation and derivation != self.derivation:
            return False
        elif other.name in self._special_types:
            return derivation != 'extension'
        elif self.base_type is other:
            return True
        elif self.base_type is None:
            if isinstance(other, XsdUnion):
                return any(self.is_derived(m, derivation) for m in other.member_types)
            return False
        elif self.base_type.is_complex():
            if not self.base_type.has_simple_content():
                return False
            return self.base_type.content.is_derived(other, derivation)  # type: ignore
        elif isinstance(other, XsdUnion):
            return any(self.is_derived(m, derivation) for m in other.member_types)
        else:
            return self.base_type.is_derived(other, derivation)

    def is_dynamic_consistent(self, other: BaseXsdType) -> bool:
        return other.name in {XSD_ANY_TYPE, XSD_ANY_SIMPLE_TYPE} or self.is_derived(other) or \
            isinstance(other, XsdUnion) and any(self.is_derived(mt) for mt in other.member_types)

    def normalize(self, text: Union[str, bytes]) -> str:
        """
        Normalize and restrict value-space with pre-lexical and lexical facets.

        :param text: text string encoded value.
        :return: a normalized string.
        """
        if isinstance(text, bytes):
            text = text.decode('utf-8')
        elif not isinstance(text, str):
            raise XMLSchemaValueError('argument is not a string: %r' % text)

        if self.white_space == 'replace':
            return self._REGEX_SPACE.sub(' ', text)
        elif self.white_space == 'collapse':
            return self._REGEX_SPACES.sub(' ', text).strip()
        else:
            return text

    def text_decode(self, text: str) -> AtomicValueType:
        return cast(AtomicValueType, self.decode(text, validation='skip'))

    def iter_decode(self, obj: Union[str, bytes], validation: str = 'lax',
                    **kwargs: Any) -> IterDecodeType[DecodedValueType]:
        if obj is None:
            yield obj
        else:
            text = self.normalize(obj)
            if self.patterns is not None:
                try:
                    self.patterns(text)
                except XMLSchemaValidationError as err:
                    yield err

            for validator in self.validators:
                try:
                    validator(text)
                except XMLSchemaValidationError as err:
                    yield err

            yield text

    def iter_encode(self, obj: Any, validation: str = 'lax', **kwargs: Any) \
            -> IterEncodeType[EncodedValueType]:
        if not isinstance(obj, (str, bytes)):
            reason = "a {!r} or {!r} object required".format(str, bytes)
            yield XMLSchemaEncodeError(self, obj, str, reason)
        else:
            text = self.normalize(obj)
            if self.patterns is not None:
                try:
                    self.patterns(text)
                except XMLSchemaValidationError as err:
                    yield err

            for validator in self.validators:
                try:
                    validator(text)
                except XMLSchemaValidationError as err:
                    yield err

            yield text

    def get_facet(self, tag: str) -> Optional[FacetsValueType]:
        return self.facets.get(tag) class XsdAtomicBuiltin(XsdAtomic):
    """
    Class for defining XML Schema built-in simpleType atomic datatypes. An instance
    contains a Python's type transformation and a list of validator functions. The
    'base_type' is not used for validation, but only for reference to the XML Schema
    restriction hierarchy.

    Type conversion methods:
      - to_python(value): Decoding from XML
      - from_python(value): Encoding to XML
    """
    def __init__(self, elem: ElementType,
                 schema: SchemaType,
                 name: str,
                 python_type: Type[Any],
                 base_type: Optional['XsdAtomicBuiltin'] = None,
                 admitted_facets: Optional[Set[str]] = None,
                 facets: Optional[Dict[Optional[str], FacetsValueType]] = None,
                 to_python: Any = None,
                 from_python: Any = None) -> None:
        """
        :param name: the XSD type's qualified name.
        :param python_type: the correspondent Python's type. If a tuple of types \
        is provided uses the first and consider the others as compatible types.
        :param base_type: the reference base type, None if it's a primitive type.
        :param admitted_facets: admitted facets tags for type (required for primitive types).
        :param facets: optional facets validators.
        :param to_python: optional decode function.
        :param from_python: optional encode function.
        """
        if isinstance(python_type, tuple):
            self.instance_types, python_type = python_type, python_type[0]
        else:
            self.instance_types = python_type
        if not callable(python_type):
            raise XMLSchemaTypeError("%r object is not callable" % python_type.__class__)

        if base_type is None and not admitted_facets and name != XSD_ERROR:
            raise XMLSchemaValueError("argument 'admitted_facets' must be "
                                      "a not empty set of a primitive type")
        self._admitted_facets = admitted_facets

        super(XsdAtomicBuiltin, self).__init__(elem, schema, None, name, facets, base_type)
        self.python_type = python_type
        self.to_python = to_python if to_python is not None else python_type
        self.from_python = from_python if from_python is not None else str

    def __repr__(self) -> str:
        return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)

    @property
    def admitted_facets(self) -> Set[str]:
        return self._admitted_facets or self.primitive_type.admitted_facets

    def iter_decode(self, obj: Union[str, bytes], validation: str = 'lax', **kwargs: Any) \
            -> IterDecodeType[DecodedValueType]:
        if isinstance(obj, (str, bytes)):
            obj = self.normalize(obj)
        elif obj is not None and not isinstance(obj, self.instance_types):
            reason = "value is not an instance of {!r}".format(self.instance_types)
            yield XMLSchemaDecodeError(self, obj, self.to_python, reason)

        if validation == 'skip':
            try:
                yield self.to_python(obj)
            except (ValueError, DecimalException):
                yield str(obj)
            return

        if self.patterns is not None:
            try:
                self.patterns(obj)
            except XMLSchemaValidationError as err:
                yield err

        try:
            result = self.to_python(obj)
        except (ValueError, DecimalException) as err:
            yield XMLSchemaDecodeError(self, obj, self.to_python, reason=str(err))
            yield None
            return
        except TypeError:
            # xs:error type (eg. an XSD 1.1 type alternative used to catch invalid values)
            reason = "invalid value {!r}".format(obj)
            yield self.validation_error(validation, error=reason, obj=obj)
            yield None
            return

        for validator in self.validators:
            try:
                validator(result)
            except XMLSchemaValidationError as err:
                yield err

        if self.name not in {XSD_QNAME, XSD_IDREF, XSD_ID}:
            pass
        elif self.name == XSD_QNAME:
            if ':' in obj:
                try:
                    prefix, name = obj.split(':')
                except ValueError:
                    pass
                else:
                    try:
                        result = '{%s}%s' % (kwargs['namespaces'][prefix], name)
                    except (TypeError, KeyError):
                        try:
                            if kwargs['source'].namespace != XSD_NAMESPACE:
                                reason = "unmapped prefix %r on QName" % prefix
                                yield self.validation_error(validation, error=reason, obj=obj)
                        except KeyError:
                            pass
            else:
                try:
                    default_namespace = kwargs['namespaces']['']
                except (TypeError, KeyError):
                    pass
                else:
                    if default_namespace:
                        result = '{%s}%s' % (default_namespace, obj)

        elif self.name == XSD_IDREF:
            try:
                id_map = kwargs['id_map']
            except KeyError:
                pass
            else:
                if obj not in id_map:
                    id_map[obj] = 0

        elif kwargs.get('level') != 0:
            try:
                id_map = kwargs['id_map']
            except KeyError:
                pass
            else:
                try:
                    id_list = kwargs['id_list']
                except KeyError:
                    if not id_map[obj]:
                        id_map[obj] = 1
                    else:
                        reason = "duplicated xs:ID value {!r}".format(obj)
                        yield self.validation_error(validation, error=reason, obj=obj)
                else:
                    if not id_map[obj]:
                        id_map[obj] = 1
                        id_list.append(obj)
                        if len(id_list) > 1 and self.xsd_version == '1.0':
                            reason = "no more than one attribute of type ID should " \
                                     "be present in an element"
                            yield self.validation_error(validation, reason, obj, **kwargs)

                    elif obj not in id_list or self.xsd_version == '1.0':
                        reason = "duplicated xs:ID value {!r}".format(obj)
                        yield self.validation_error(validation, error=reason, obj=obj)

        yield result

    def iter_encode(self, obj: Any, validation: str = 'lax', **kwargs: Any) \
            -> IterEncodeType[EncodedValueType]:
        if isinstance(obj, (str, bytes)):
            obj = self.normalize(obj)

        if validation == 'skip':
            try:
                yield self.from_python(obj)
            except ValueError:
                yield str(obj)
            return

        elif isinstance(obj, bool):
            types_: Any = self.instance_types
            if types_ is not bool or (isinstance(types_, tuple) and bool in types_):
                reason = "boolean value {!r} requires a {!r} decoder".format(obj, bool)
                yield XMLSchemaEncodeError(self, obj, self.from_python, reason)
                obj = self.python_type(obj)

        elif not isinstance(obj, self.instance_types):
            reason = "{!r} is not an instance of {!r}".format(obj, self.instance_types)
            yield XMLSchemaEncodeError(self, obj, self.from_python, reason)

            try:
                value = self.python_type(obj)
                if value != obj and not isinstance(value, str) \
                        and not isinstance(obj, (str, bytes)):
                    raise ValueError()
                obj = value
            except (ValueError, TypeError) as err:
                yield XMLSchemaEncodeError(self, obj, self.from_python, reason=str(err))
                yield None
                return
            else:
                if value == obj or str(value) == str(obj):
                    obj = value
                else:
                    reason = "Invalid value {!r}".format(obj)
                    yield XMLSchemaEncodeError(self, obj, self.from_python, reason)
                    yield None
                    return

        for validator in self.validators:
            try:
                validator(obj)
            except XMLSchemaValidationError as err:
                yield err

        try:
            text = self.from_python(obj)
        except ValueError as err:
            yield XMLSchemaEncodeError(self, obj, self.from_python, reason=str(err))
            yield None
        else:
            if self.patterns is not None:
                try:
                    self.patterns(text)
                except XMLSchemaValidationError as err:
                    yield err
            yield text
from decimal import Decimal
from elementpath import datatypes
from typing import cast, Any, Dict, Optional, Type, Tuple, Union
from ..exceptions import XMLSchemaValueError
from ..names import XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_ENUMERATION, \
    XSD_PATTERN, XSD_WHITE_SPACE, XSD_MIN_INCLUSIVE, XSD_MIN_EXCLUSIVE, XSD_MAX_INCLUSIVE, \
    XSD_MAX_EXCLUSIVE, XSD_TOTAL_DIGITS, XSD_FRACTION_DIGITS, XSD_EXPLICIT_TIMEZONE, \
    XSD_STRING, XSD_NORMALIZED_STRING, XSD_NAME, XSD_NCNAME, XSD_QNAME, XSD_TOKEN, \
    XSD_NMTOKEN, XSD_ID, XSD_IDREF, XSD_LANGUAGE, XSD_DECIMAL, XSD_DOUBLE, XSD_FLOAT, \
    XSD_INTEGER, XSD_BYTE, XSD_SHORT, XSD_INT, XSD_LONG, XSD_UNSIGNED_BYTE, \
    XSD_UNSIGNED_SHORT, XSD_UNSIGNED_INT, XSD_UNSIGNED_LONG, XSD_POSITIVE_INTEGER, \
    XSD_NEGATIVE_INTEGER, XSD_NON_NEGATIVE_INTEGER, XSD_NON_POSITIVE_INTEGER, \
    XSD_GDAY, XSD_GMONTH, XSD_GMONTH_DAY, XSD_GYEAR, XSD_GYEAR_MONTH, XSD_TIME, XSD_DATE, \
    XSD_DATETIME, XSD_DATE_TIME_STAMP, XSD_ENTITY, XSD_ANY_URI, XSD_BOOLEAN, \
    XSD_DURATION, XSD_DAY_TIME_DURATION, XSD_YEAR_MONTH_DURATION, XSD_BASE64_BINARY, \
    XSD_HEX_BINARY, XSD_NOTATION_TYPE, XSD_ERROR, XSD_ASSERTION, XSD_SIMPLE_TYPE, \
    XSD_ANY_TYPE, XSD_ANY_ATOMIC_TYPE, XSD_ANY_SIMPLE_TYPE
from ..etree import etree_element
from ..aliases import ElementType, SchemaType, BaseXsdType
from .helpers import decimal_validator, qname_validator, byte_validator, \
    short_validator, int_validator, long_validator, unsigned_byte_validator, \
    unsigned_short_validator, unsigned_int_validator, unsigned_long_validator, \
    negative_int_validator, positive_int_validator, non_positive_int_validator, \
    non_negative_int_validator, hex_binary_validator, base64_binary_validator, \
    error_type_validator, boolean_to_python, python_to_boolean
from .facets import XSD_10_FACETS_BUILDERS, XSD_11_FACETS_BUILDERS
from .simple_types import XsdSimpleType, XsdAtomicBuiltin
#
# Copyright (c), 2016-2020, SISSA (International School for Advanced Studies).
# All rights reserved.
# This file is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present
# distribution, or http://opensource.org/licenses/MIT.
#
# @author Davide Brunato <brunato@sissa.it>
#
"""
This module contains definitions and a factory function for XSD builtin datatypes.

Only atomic builtins are created, the list builtins types ('NMTOKENS', 'ENTITIES', 'IDREFS')
are created using the XSD 1.0 meta-schema or with and additional base schema for XSD 1.1.
"""



#
# Admitted facets sets for XSD atomic types
STRING_FACETS = {
    XSD_LENGTH, XSD_MIN_LENGTH, XSD_MAX_LENGTH, XSD_PATTERN,
    XSD_ENUMERATION, XSD_WHITE_SPACE, XSD_ASSERTION
}

BOOLEAN_FACETS = {XSD_PATTERN, XSD_WHITE_SPACE, XSD_ASSERTION}

FLOAT_FACETS = {
    XSD_PATTERN, XSD_ENUMERATION, XSD_WHITE_SPACE, XSD_MAX_INCLUSIVE,
    XSD_MAX_EXCLUSIVE, XSD_MIN_INCLUSIVE, XSD_MIN_EXCLUSIVE, XSD_ASSERTION
}

DECIMAL_FACETS = {
    XSD_TOTAL_DIGITS, XSD_FRACTION_DIGITS, XSD_PATTERN, XSD_ENUMERATION,
    XSD_WHITE_SPACE, XSD_MAX_INCLUSIVE, XSD_MAX_EXCLUSIVE, XSD_MIN_INCLUSIVE,
    XSD_MIN_EXCLUSIVE, XSD_ASSERTION
}

DATETIME_FACETS = {
    XSD_PATTERN, XSD_ENUMERATION, XSD_WHITE_SPACE,
    XSD_MAX_INCLUSIVE, XSD_MAX_EXCLUSIVE, XSD_MIN_INCLUSIVE,
    XSD_MIN_EXCLUSIVE, XSD_ASSERTION, XSD_EXPLICIT_TIMEZONE
}


#
# Element facets instances for builtin types.

PRESERVE_WHITE_SPACE_ELEMENT = etree_element(XSD_WHITE_SPACE, value='preserve')