Ejemplo n.º 1
0
 def serialize(self, value: Union[date, time], **kwargs: Any) -> str:
     try:
         return value.strftime(kwargs["format"])
     except KeyError:
         raise ConverterError("Missing format keyword argument")
     except Exception as e:
         raise ConverterError(e)
Ejemplo n.º 2
0
 def parse(cls, value: Any, **kwargs: Any) -> datetime:
     try:
         return datetime.strptime(value, kwargs["format"])
     except KeyError:
         raise ConverterError("Missing format keyword argument")
     except Exception as e:
         raise ConverterError(e)
Ejemplo n.º 3
0
    def deserialize(self, value: Any, **kwargs: Any) -> bytes:
        self.validate_input_type(value, str)

        try:
            fmt = kwargs.get("format")

            if fmt == "base16":
                return binascii.unhexlify(value)

            if fmt == "base64":
                return base64.b64decode(value)

            raise ConverterError(f"Unknown format '{fmt}'")
        except ValueError as e:
            raise ConverterError(e)
Ejemplo n.º 4
0
def to_bool(value: Any) -> bool:
    val = value.strip()
    if val in ("true", "1"):
        return True
    if val in ("false", "0"):
        return False

    raise ConverterError(f"Invalid bool literal '{value}'")
Ejemplo n.º 5
0
    def resolve(value: str, ns_map: Optional[Dict]) -> Tuple:
        if not value:
            raise ConverterError("Invalid QName")

        if value[0] == "{":
            return value, None

        if ns_map is None:
            raise ConverterError(
                "QName converter needs ns_map to support prefixes")

        prefix, suffix = text.split(value.strip())
        namespace = ns_map.get(prefix)

        if prefix and not namespace:
            raise ConverterError(f"Unknown namespace prefix: `{prefix}`")

        return namespace, suffix
Ejemplo n.º 6
0
def to_class(clazz: Any, value: Any, ns_map: Optional[Dict]) -> Any:
    if clazz is QName:
        return to_qname(value, ns_map)
    if issubclass(clazz, Enum):
        return to_enum(clazz, value, ns_map)
    if is_dataclass(clazz):
        return clazz(value)

    raise ConverterError(f"Unhandled class type {clazz.__name__}")
Ejemplo n.º 7
0
    def serialize(self, value: bytes, **kwargs: Any) -> str:
        fmt = kwargs.get("format")

        if isinstance(value, XmlHexBinary) or fmt == "base16":
            return base64.b16encode(value).decode()

        if isinstance(value, XmlBase64Binary) or fmt == "base64":
            return base64.b64encode(value).decode()

        raise ConverterError(f"Unknown format '{fmt}'")
Ejemplo n.º 8
0
    def deserialize(self,
                    value: Any,
                    data_type: Optional[EnumMeta] = None,
                    **kwargs: Any) -> Enum:
        if data_type is None or not isinstance(data_type, EnumMeta):
            raise ConverterError(f"'{data_type}' is not an enum")

        if isinstance(value, (list, tuple)):
            values = value
        elif isinstance(value, str):
            value = value.strip()
            values = value.split()
        else:
            values = [value]

        length = len(values)
        for member in cast(Type[Enum], data_type):
            if self.match(value, values, length, member.value, **kwargs):
                return member

        raise ConverterError()
Ejemplo n.º 9
0
    def resolve(value: str, ns_map: Optional[Dict]) -> Tuple:
        value = value.strip()

        if not value:
            raise ConverterError()

        if value[0] == "{":
            uri, name = text.split(value[1:], "}")

            if not namespaces.is_uri(uri):
                raise ConverterError()
        else:
            prefix, name = text.split(value, ":")
            uri = ns_map.get(prefix) if ns_map else None
            if prefix and not uri:
                raise ConverterError(f"Unknown namespace prefix: `{prefix}`")

        if " " in name or not namespaces.is_ncname(name):
            raise ConverterError()

        return uri, name
Ejemplo n.º 10
0
    def deserialize(self,
                    value: Any,
                    data_type: Optional[Type[Enum]] = None,
                    **kwargs: Any) -> Enum:
        if data_type is None or not issubclass(data_type, Enum):
            raise ConverterError("Provide a target data type enum class.")

        # Convert string value to the type of the first enum member first, otherwise
        # more complex types like QName, Decimals will fail.
        member: Enum = list(data_type)[0]
        value_type = type(member.value)

        # Suppress warnings
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            real_value = converter.deserialize(value, [value_type], **kwargs)

        # Raise exception if the real value doesn't match the expected type.
        if not isinstance(real_value, value_type):
            raise ConverterError()

        try:
            # Attempt no1 use the enum constructor
            return data_type(real_value)
        except ValueError:
            pass

        try:
            # Attempt no2 the enum might be derived from
            # xs:NMTOKENS or xs:list removing excess whitespace.
            if isinstance(real_value, str):
                return data_type(" ".join(real_value.split()))

            # Attempt #3 some values are never equal try to match
            # canonical representations.
            repr_value = repr(real_value)
            return next(x for x in data_type if repr(x.value) == repr_value)
        except (ValueError, StopIteration):
            raise ConverterError()
Ejemplo n.º 11
0
    def deserialize(self, value: Any, **kwargs: Any) -> bool:
        if isinstance(value, str):

            val = value.strip()

            if val in ("true", "1"):
                return True

            if val in ("false", "0"):
                return False

            raise ConverterError(f"Invalid bool literal '{value}'")

        return True if value else False
Ejemplo n.º 12
0
def to_xml(value: Any) -> Any:
    if value is None:
        return None
    if isinstance(value, bool):
        return "true" if value else "false"
    if isinstance(value, Enum):
        return str(value.value)
    if isinstance(value, float):
        return "NaN" if math.isnan(value) else str(value).upper()
    if isinstance(value, Decimal) and value.is_infinite():
        return str(value).replace("Infinity", "INF")
    if isinstance(value, QName):
        return value
    if is_dataclass(value):
        raise ConverterError("Text nodes can't be dataclasses!")

    return str(value)
Ejemplo n.º 13
0
    def deserialize(self,
                    value: str,
                    ns_map: Optional[Dict] = None,
                    **kwargs: Any) -> etree.QName:
        """
        Convert namespace prefixed strings, or fully qualified strings to
        QNames.

        examples:
            - xs:string -> QName("http://www.w3.org/2001/XMLSchema", "string")
            - {foo}bar -> QName("foo", "bar"
        """
        try:

            text_or_uri, tag = QNameConverter.resolve(value, ns_map)
            return etree.QName(text_or_uri, tag)
        except ValueError:
            raise ConverterError()
Ejemplo n.º 14
0
def to_xml(value: Any, namespaces: Optional[Namespaces] = None) -> Any:
    if value is None:
        return None
    if isinstance(value, list):
        return " ".join(map(lambda x: to_xml(x, namespaces), value))
    if isinstance(value, bool):
        return "true" if value else "false"
    if isinstance(value, Enum):
        return to_xml(value.value, namespaces)
    if isinstance(value, float):
        return "NaN" if math.isnan(value) else str(value).upper()
    if isinstance(value, Decimal) and value.is_infinite():
        return str(value).replace("Infinity", "INF")
    if isinstance(value, QName):
        return qname_to_xml(value, namespaces) if namespaces else value.text
    if is_dataclass(value):
        raise ConverterError("Text nodes can't be dataclasses!")
    return str(value)
Ejemplo n.º 15
0
 def deserialize(self, value: Any, **kwargs: Any) -> Decimal:
     try:
         return Decimal(value)
     except InvalidOperation:
         raise ConverterError()
Ejemplo n.º 16
0
 def deserialize(self, value: Any, **kwargs: Any) -> int:
     try:
         return int(value)
     except (ValueError, TypeError) as e:
         raise ConverterError(e)
Ejemplo n.º 17
0
 def validate_input_type(cls, value: Any, tp: Type):
     if not isinstance(value, tp):
         raise ConverterError(
             f"Input value must be '{tp.__name__}' got '{type(value).__name__}'"
         )
Ejemplo n.º 18
0
 def deserialize(self, value: Any, **kwargs: Any) -> float:
     try:
         return float(value)
     except ValueError as e:
         raise ConverterError(e)
Ejemplo n.º 19
0
 def deserialize(self, value: Any, **kwargs: Any) -> Any:
     try:
         return self.func(value)
     except ValueError as e:
         raise ConverterError(e)