Exemple #1
0
    def test_unknown_converter(self):
        class A:
            pass

        class B(A):
            pass

        with warnings.catch_warnings(record=True) as w:
            converter.serialize(B())

        self.assertEqual(f"No converter registered for `{B}`",
                         str(w[-1].message))
Exemple #2
0
 def test_serialize(self):
     self.assertEqual(None, converter.serialize(None))
     self.assertEqual("1", converter.serialize(1))
     self.assertEqual("1 2 3", converter.serialize([1, "2", 3]))
     self.assertEqual(None, converter.serialize(None))
     self.assertEqual("1", converter.serialize(1))
     self.assertEqual("1.5", converter.serialize(1.5))
     self.assertEqual("true", converter.serialize(True))
     self.assertEqual("optional", converter.serialize(UseType.OPTIONAL))
     self.assertEqual("8.77683E-8",
                      converter.serialize(Decimal("8.77683E-8")))
     self.assertEqual("8.77683E-08",
                      converter.serialize(float("8.77683E-8")))
Exemple #3
0
    def encode_data(self, data: Any) -> Optional[str]:
        """Encode data for xml rendering."""
        if data is None or isinstance(data, str):
            return data

        if isinstance(data, list) and not data:
            return None

        return converter.serialize(data, ns_map=self.ns_map)
Exemple #4
0
    def prepare_generic_value(cls, qname: str, value: Any) -> Any:
        """Prepare parsed value before binding to a wildcard field."""

        if not is_dataclass(value):
            value = AnyElement(qname=qname, text=converter.serialize(value))
        elif not isinstance(value, (AnyElement, DerivedElement)):
            value = DerivedElement(qname=qname, value=value)

        return value
Exemple #5
0
    def test_serialize(self):
        with warnings.catch_warnings(record=True):
            self.assertEqual(None, converter.deserialize(None, [int]))

        self.assertEqual("1", converter.serialize(1))
        self.assertEqual("1 2 3", converter.serialize([1, "2", 3]))
        self.assertEqual(None, converter.serialize(None))
        self.assertEqual("1", converter.serialize(1))
        self.assertEqual("1.5", converter.serialize(1.5))
        self.assertEqual("true", converter.serialize(True))
        self.assertEqual("optional", converter.serialize(UseType.OPTIONAL))
        self.assertEqual("8.77683E-8",
                         converter.serialize(Decimal("8.77683E-8")))
        self.assertEqual("8.77683E-08",
                         converter.serialize(float("8.77683E-8")))
Exemple #6
0
    def convert(self, obj: Any, var: Optional[XmlVar] = None) -> Any:
        if var is None or is_dataclass(obj):
            return self.dict_factory([
                (var.lname, self.convert(getattr(obj, var.name), var))
                for var in self.context.build(obj.__class__).vars
            ])

        if isinstance(obj, (list, tuple)):
            return type(obj)(self.convert(v, var) for v in obj)

        if isinstance(obj, (dict, int, float, str, bool)):
            return obj

        if isinstance(obj, Enum):
            return self.convert(obj.value, var)

        return converter.serialize(obj, format=var.format)
Exemple #7
0
    def test_register_converter(self):
        class MinusOneInt(int):
            pass

        class MinusOneIntConverter(Converter):
            def deserialize(self, value: str, **kwargs: Any) -> Any:
                return int(value) - 1

            def serialize(self, value: Any, **kwargs: Any) -> str:
                return str(value)

        self.assertEqual(1, converter.deserialize("1", [MinusOneInt]))

        converter.register_converter(MinusOneInt, MinusOneIntConverter())
        self.assertEqual(1, converter.deserialize("2", [MinusOneInt]))
        self.assertEqual(2, converter.deserialize("3", [MinusOneInt]))
        self.assertEqual("3", converter.serialize(MinusOneInt("3")))
        converter.unregister_converter(MinusOneInt)
Exemple #8
0
    def test_register_converter(self):
        class MinusOneInt(int):
            pass

        class MinusOneIntConverter(Converter):
            def deserialize(self, value: str, **kwargs: Any) -> Any:
                return int(value) - 1

            def serialize(self, value: Any, **kwargs: Any) -> str:
                return str(value)

        with warnings.catch_warnings(record=True) as w:
            self.assertEqual("1", converter.deserialize("1", [MinusOneInt]))

        self.assertEqual(f"No converter registered for `{MinusOneInt}`",
                         str(w[-1].message))

        converter.register_converter(MinusOneInt, MinusOneIntConverter())
        self.assertEqual(1, converter.deserialize("2", [MinusOneInt]))
        self.assertEqual(2, converter.deserialize("3", [MinusOneInt]))
        self.assertEqual("3", converter.serialize(MinusOneInt("3")))
        converter.unregister_converter(MinusOneInt)
Exemple #9
0
    def set_data(self, data: Any):
        """
        Set data notification receiver.

        The receiver will convert the data to string, flush any previous pending
        start element and send it to the handler for generation.

        If the text content of the tag has already been generated then treat the
        current data as element tail content and queue it to be generated when the
        tag ends.

        :param data: Element text or tail content
        """
        value = converter.serialize(data, ns_map=self.ns_map)
        self.flush_start(is_nil=value is None or value == "")

        if value:
            if not self.in_tail:
                self.handler.characters(value)
            else:
                self.tail = value

        self.in_tail = True
Exemple #10
0
    def add_attribute(self, key: str, value: Any, check_pending: bool = True):
        """
        Add attribute notification receiver.

        The receiver will convert the key to a namespace, name tuple
        and convert the value to string. Internally the converter will
        also generate any missing namespace prefixes.

        :param key: Attribute name
        :param value: Attribute value
        :param check_pending: Raise exception if not no element is
            pending start
        """

        if not self.pending_tag and check_pending:
            raise XmlWriterError("Empty pending tag.")

        if self.is_xsi_type(key, value):
            value = QName(value)

        name = split_qname(key)
        value = converter.serialize(value, ns_map=self.ns_map)
        self.attrs[name] = value
Exemple #11
0
    def encode_value(cls, value: Any, var: XmlVar) -> Any:
        """
        Encode values for xml serialization.

        Converts values to strings. QName instances is an exception,
        those values need to wait until the XmlWriter assigns prefixes
        to namespaces per element node. Enums and Tokens may contain
        QName(s) so they also get a special treatment.

        We can't do all the conversions in the writer because we would
        need to carry the xml vars inside the writer. Instead of that
        we do the easy encoding here and leave the qualified names for
        later.
        """
        if isinstance(value, (str, QName)) or var is None:
            return value

        if isinstance(value, (tuple, list)):
            return [cls.encode_value(v, var) for v in value]

        if isinstance(value, Enum):
            return cls.encode_value(value.value, var)

        return converter.serialize(value, format=var.format)