Пример #1
0
    def test_find_var(self):
        ctx = XmlContext()
        meta = ctx.build(BookForm)

        self.assertTrue(meta.find_var("author").element)
        self.assertIsNone(meta.find_var("author", FindMode.ATTRIBUTE))
        self.assertIsNone(meta.find_var("nope"))
Пример #2
0
    def test_bind_returns_best_matching_dataclass(self):
        @dataclass
        class Item:
            value: str = field()
            a: int = attribute()
            b: int = attribute()

        @dataclass
        class Item2:
            a: int = attribute()

        @dataclass
        class Root:
            item: Union[str, int, Item2, Item] = element()

        ctx = XmlContext()
        meta = ctx.build(Root)
        var = meta.vars[0]
        attrs = {"a": "1", "b": 2}
        ns_map = {}
        node = UnionNode(position=0, var=var, context=ctx, attrs=attrs, ns_map=ns_map)
        objects = []

        self.assertTrue(node.bind("item", "foo", None, objects))
        self.assertIsInstance(objects[-1][1], Item)
        self.assertEqual(1, objects[-1][1].a)
        self.assertEqual(2, objects[-1][1].b)
        self.assertEqual("foo", objects[-1][1].value)
        self.assertEqual("item", objects[-1][0])

        self.assertEqual(2, len(node.events))
        self.assertEqual(("start", "item", attrs, ns_map), node.events[0])
        self.assertEqual(("end", "item", "foo", None), node.events[1])
        self.assertIsNot(node.attrs, node.events[0][2])
        self.assertIs(node.ns_map, node.events[0][3])
Пример #3
0
    def test_bind_objects(self):
        @dataclass
        class A:
            x: int
            y: int = field(init=False)
            w: object = field(metadata=dict(type=XmlType.WILDCARD))

        ctx = XmlContext()
        meta = ctx.build(A)
        x = meta.find_var("x")
        y = meta.find_var("y")
        w = meta.find_var("wild")
        wild_element = AnyElement(qname="foo")

        objects = [
            ("foo", 0),
            (x.qname, 1),
            (y.qname, 2),
            (w.qname, None),
            (w.qname, wild_element),
        ]

        params = {}
        ParserUtils.bind_objects(params, meta, 1, objects)
        expected = {
            "x": 1,
            "w": AnyElement(
                children=[AnyElement(qname="w", text=""), AnyElement(qname="foo")]
            ),
        }

        self.assertEqual(expected, params)
Пример #4
0
 def test_next_node_return_self_on_root_element(self):
     ele = Element("foo")
     ctx = XmlContext()
     cfg = ParserConfig()
     meta = ctx.build(Foo)
     node = RootNode(position=0, meta=meta, config=cfg)
     self.assertIs(node, node.next_node(ele, 0, ctx))
Пример #5
0
    def test_find_var(self):
        ctx = XmlContext()
        meta = ctx.build(BookForm)
        author = QName("author")
        excluded = set()
        excluded.add("author")

        self.assertIsInstance(meta.find_var(author), XmlElement)
        self.assertIsNone(meta.find_var(author, FindMode.ATTRIBUTE))
        self.assertIsNone(meta.find_var(QName("nope")))
Пример #6
0
    def test_find_var_uses_cache(self):
        ctx = XmlContext()
        meta = ctx.build(BookForm)

        self.assertEqual("author", meta.find_var("author").name)
        self.assertEqual(1, len(meta.cache))
        key = tuple(meta.cache.keys())[0]

        meta.cache[key] = 1
        self.assertEqual("title", meta.find_var("author").name)
Пример #7
0
 def setUp(self) -> None:
     super().setUp()
     self.context = XmlContext()
     self.meta = XmlMeta(clazz=Foo, qname="foo", source_qname="foo", nillable=False)
     self.node = ElementNode(
         position=0,
         meta=self.meta,
         context=self.context,
         config=ParserConfig(),
         attrs={},
         ns_map={},
     )
Пример #8
0
    def test_next_node_return_next_node(self):
        root = Element("a")
        ele = SubElement(root, "b")

        ctx = XmlContext()
        cfg = ParserConfig()
        meta = ctx.build(Foo)
        node = RootNode(position=0, meta=meta, config=cfg)
        actual = node.next_node(ele, 0, ctx)

        self.assertIsInstance(actual, PrimitiveNode)
        self.assertIsNot(actual, node)
Пример #9
0
    def next_node(self, element: Element, position: int,
                  ctx: XmlContext) -> XmlNode:
        qname = QName(element.tag)
        var = self.meta.find_var(qname, FindMode.NOT_WILDCARD)
        if not var:
            var = self.meta.find_var(qname, FindMode.WILDCARD)

        if not var:
            if self.config.fail_on_unknown_properties:
                raise XmlContextError(
                    f"{self.meta.qname} does not support mixed content: {qname}"
                )
            return SkipNode(position=position)

        if var.clazz:
            xsi_type = ParserUtils.parse_xsi_type(element)
            meta = ctx.fetch(var.clazz, self.meta.qname.namespace, xsi_type)
            return ElementNode(position=position,
                               meta=meta,
                               default=var.default,
                               config=self.config)

        if var.is_any_type:
            return WildcardNode(position=position, qname=var.qname)

        return PrimitiveNode(
            position=position,
            types=var.types,
            default=var.default,
            tokens=var.is_tokens,
        )
Пример #10
0
    def next_node(self, element: Element, position: int,
                  ctx: XmlContext) -> XmlNode:
        """
        Initialize the next node to be queued for the given starting element.

        Search by the given element tag for a matching variable and create the next
        node by the variable type.

        :return: The next node to be queued.
        :raises: XmlContextError if the element is unknown and parser config is strict.
        """
        qname = QName(element.tag)
        var = self.meta.find_var(qname, FindMode.NOT_WILDCARD)
        if not var:
            var = self.meta.find_var(qname, FindMode.WILDCARD)

        if not var:
            if self.config.fail_on_unknown_properties:
                raise XmlContextError(
                    f"{self.meta.qname} does not support mixed content: {qname}"
                )
            return SkipNode(position=position)

        if var.clazz:
            xsi_type = ParserUtils.parse_xsi_type(element)
            meta = ctx.fetch(var.clazz, self.meta.qname.namespace, xsi_type)
            return ElementNode(position=position,
                               meta=meta,
                               config=self.config)

        if var.is_any_type:
            return WildcardNode(position=position, qname=var.qname)

        return PrimitiveNode(position=position, var=var)
Пример #11
0
    def test_next_node_when_given_qname_matches_dataclass_var(
            self, mock_ctx_fetch, mock_element_xsi_type):
        ele = Element("a")
        ctx = XmlContext()
        cfg = ParserConfig()
        var = XmlElement(name="a",
                         qname=QName("a"),
                         types=[Foo],
                         dataclass=True)
        meta = XmlMeta(
            name="foo",
            clazz=None,
            qname=QName("foo"),
            source_qname=QName("foo"),
            nillable=False,
            vars=[var],
        )
        xsi_type = QName("foo")
        namespace = meta.qname.namespace
        mock_ctx_fetch.return_value = replace(meta)
        mock_element_xsi_type.return_value = xsi_type
        node = ElementNode(position=0, meta=meta, config=cfg)

        actual = node.next_node(ele, 10, ctx)
        self.assertIsInstance(actual, ElementNode)
        self.assertEqual(10, actual.position)
        self.assertIs(mock_ctx_fetch.return_value, actual.meta)
        mock_ctx_fetch.assert_called_once_with(var.clazz, namespace, xsi_type)
Пример #12
0
    def test_next_node(self):
        ele = Element("foo")
        node = PrimitiveNode(position=0,
                             var=XmlText(name="foo", qname=QName("foo")))

        with self.assertRaises(XmlContextError):
            node.next_node(ele, 10, XmlContext())
Пример #13
0
def validate_bindings(schema: Path, clazz: Type, output_format: str):
    __tracebackhide__ = True

    chapter = schema.stem.replace("chapter", "")

    sample = here.joinpath(f"samples/chapter{chapter}.xml")
    output_xml = here.joinpath(f"output/chapter{chapter}.xsdata.xml")
    output_json = here.joinpath(f"output/chapter{chapter}.xsdata.json")

    context = XmlContext(class_type=output_format)
    obj = XmlParser(context=context).from_path(sample, clazz)
    config = SerializerConfig(pretty_print=True)

    actual_json = JsonSerializer(context=context, config=config).render(obj)
    actual_xml = XmlSerializer(context=context, config=config).render(obj)

    if output_json.exists() and chapter != "13":
        assert output_json.read_text() == actual_json
        assert obj == JsonParser(context=context).from_string(
            actual_json, clazz)
    else:
        output_json.write_text(actual_json, encoding="utf-8")

    if output_xml.exists():
        assert output_xml.read_text() == actual_xml
    else:
        output_xml.write_text(actual_xml, encoding="utf-8")

    validator = etree.XMLSchema(etree.parse(str(schema)))
    validator.assertValid(etree.fromstring(actual_xml.encode()))
Пример #14
0
    def test_bind_elements(
        self,
        mock_bind_element_param,
        mock_find_eligible_wildcard,
        mock_bind_element_wildcard_param,
    ):
        @dataclass
        class A:
            x: int
            y: int = field(init=False)
            w: object = field(metadata=dict(type=XmlType.WILDCARD))

        ctx = XmlContext()
        meta = ctx.build(A)
        x = meta.find_var(QName("x"))
        y = meta.find_var(QName("y"))
        w = meta.find_var(QName("wild"))
        wild_element = AnyElement(qname="foo")

        objects = [
            ("foo", 0),
            (x.qname, 1),
            (y.qname, 2),
            (w.qname, None),
            (w.qname, wild_element),
        ]

        mock_bind_element_param.side_effect = [True, False, False]
        mock_find_eligible_wildcard.side_effect = [None, w]

        params = {}
        ParserUtils.bind_element_children(params, meta, 1, objects)

        mock_bind_element_param.assert_has_calls(
            [
                mock.call(params, x, 1),
                mock.call(params, w, ""),
                mock.call(params, w, wild_element),
            ]
        )
        mock_find_eligible_wildcard.assert_has_calls(
            [mock.call(meta, w.qname, params), mock.call(meta, QName("foo"), params)]
        )

        mock_bind_element_wildcard_param.assert_called_once_with(
            params, w, w.qname, wild_element
        )
Пример #15
0
    def test_next_node(self):
        ele = Element("foo")
        node = WildcardNode(position=0, qname="a")
        actual = node.next_node(ele, 10, XmlContext())

        self.assertIsInstance(actual, WildcardNode)
        self.assertEqual(10, actual.position)
        self.assertEqual("a", actual.qname)
Пример #16
0
 def read(cls, path: Path) -> "GeneratorConfig":
     ctx = XmlContext(
         element_name_generator=text.pascal_case,
         attribute_name_generator=text.camel_case,
     )
     config = ParserConfig(fail_on_unknown_properties=False)
     parser = XmlParser(context=ctx, config=config)
     return parser.from_path(path, cls)
Пример #17
0
    def test_parse_element(
        self,
        mock_bind_element_attrs,
        mock_bind_element_text,
        mock_bind_element_children,
        mock_bind_element_wild_text,
    ):
        def add_attr(x, *args):
            x["a"] = 1

        def add_text(x, *args):
            x["b"] = 2

        def add_child(x, *args):
            x["c"] = 3

        def add_wild_text(x, *args):
            x["d"] = 4

        mock_bind_element_attrs.side_effect = add_attr
        mock_bind_element_text.side_effect = add_text
        mock_bind_element_children.side_effect = add_child
        mock_bind_element_wild_text.side_effect = add_wild_text

        ctx = XmlContext()
        meta = ctx.build(Foo)

        ele = Element("foo")
        pool = [1, 2, 3]

        node = ElementNode(position=0,
                           meta=meta,
                           default=None,
                           config=ParserConfig())
        qname, obj = node.parse_element(ele, pool)

        self.assertEqual(QName(ele.tag), qname)
        self.assertEqual(Foo(1, 2, 3, 4), obj)

        mock_bind_element_attrs.assert_called_once_with(mock.ANY, meta, ele)
        mock_bind_element_text.assert_called_once_with(mock.ANY, meta, ele)
        mock_bind_element_children.assert_called_once_with(
            mock.ANY, meta, 0, pool)
        mock_bind_element_wild_text.assert_called_once_with(
            mock.ANY, meta, ele)
Пример #18
0
    def __init__(self, *, config: Configuration) -> None:
        self.config = config

        self.serializer = XmlSerializer(config=SerializerConfig(
            pretty_print=False))
        self.parser = XmlParser(context=XmlContext())
        self.requests: WeakValueDictionary[str,
                                           Future] = WeakValueDictionary({})
        super().__init__()
Пример #19
0
    def test_bind_raises_parser_error_on_failure(self):
        @dataclass
        class Item:
            value: str = field()

        @dataclass
        class Root:
            item: Union[int, Item] = element()

        ctx = XmlContext()
        meta = ctx.build(Root)
        meta.vars[0]

        node = UnionNode(position=0, var=meta.vars[0], context=ctx, attrs={}, ns_map={})

        with self.assertRaises(ParserError) as cm:
            node.bind("item", None, None, [])

        self.assertEqual("Failed to parse union node: item", str(cm.exception))
Пример #20
0
    def test_bind_objects_with_unassigned_object(self, mock_warning):
        a = make_dataclass("a", [("x", int)])
        meta = XmlContext().build(a)
        params = {}
        objects = [("x", 1), ("y", 2)]

        ParserUtils.bind_objects(params, meta, 0, objects)

        self.assertEqual({"x": 1}, params)
        mock_warning.assert_called_once_with("Unassigned parsed object %s", "y")
Пример #21
0
def serialize_xml_from_file(xml_file_path: pathlib.Path,
                            serialize_clazz: Optional[Type[T]]):
    """
    Method to serialize XML data from a file.
    :param xml_file_path: A pathlib.path path object that leads to the targeted XML file.
    :param serialize_clazz: A class Object.
    :return: the serialized object.
    """
    parser = XmlParser(context=XmlContext())
    return parser.from_path(xml_file_path, serialize_clazz)
Пример #22
0
    def test_bind_appends_end_event_when_level_not_zero(self):
        ctx = XmlContext()
        var = XmlVar(text=True, name="foo", qname="foo")
        node = UnionNode(position=0, var=var, context=ctx, attrs={}, ns_map={})
        node.level = 1
        objects = []

        self.assertFalse(node.bind("bar", "text", "tail", objects))
        self.assertEqual(0, len(objects))
        self.assertEqual(0, node.level)
        self.assertEqual([("end", "bar", "text", "tail")], node.events)
Пример #23
0
    def test_child(self):
        attrs = {"id": "1"}
        ns_map = {"ns0": "xsdata"}
        ctx = XmlContext()
        var = XmlVar(text=True, name="foo", qname="foo")
        node = UnionNode(position=0, var=var, context=ctx, attrs={}, ns_map={})
        self.assertEqual(node, node.child("foo", attrs, ns_map, 10))

        self.assertEqual(1, node.level)
        self.assertEqual([("start", "foo", attrs, ns_map)], node.events)
        self.assertIsNot(attrs, node.events[0][2])
Пример #24
0
def assert_bindings(
    schema: str,
    instance: str,
    class_name: str,
    version: str,
    mode: str,
    save_output: bool,
    output_format: str,
    structure_style: str,
):
    __tracebackhide__ = True

    if mode == "xml":
        instance_path = Path(instance)
        pck_arr = list(map(text.snake_case, instance_path.parts))
        package = f"output.xml_models.{'.'.join(pck_arr)}"
        instance_path = w3c.joinpath(instance_path)
        source = str(instance_path)
    else:
        schema_path = Path(schema)
        pck_arr = list(map(text.snake_case, schema_path.parts))
        package = f"output.models.{'.'.join(pck_arr)}"
        schema_path = w3c.joinpath(schema)
        source = str(schema_path)

    clazz = generate_models(source, package, class_name, output_format, structure_style)

    if mode == "build":
        return

    if isinstance(clazz, Exception):
        raise clazz

    try:
        instance_path = w3c.joinpath(instance)
        schema_path = w3c.joinpath(schema)
        context = XmlContext(class_type=output_format)
        parser = XmlParser(context=context)
        obj = parser.from_path(instance_path, clazz)
    except Exception as e:
        raise e

    save_path = None
    if save_output:
        save_path = output.joinpath(instance)
        save_path.parent.mkdir(parents=True, exist_ok=True)

    if mode == "json":
        assert_json_bindings(context, obj, save_path)
    else:
        assert_xml_bindings(
            context, obj, parser.ns_map, schema_path, instance_path, save_path, version
        )
Пример #25
0
 def write(cls, output: TextIO, obj: "GeneratorConfig"):
     ctx = XmlContext(
         element_name_generator=text.pascal_case,
         attribute_name_generator=text.camel_case,
     )
     config = SerializerConfig(pretty_print=True)
     serializer = XmlSerializer(context=ctx,
                                config=config,
                                writer=XmlEventWriter)
     serializer.write(output,
                      obj,
                      ns_map={None: "http://pypi.org/project/xsdata"})
Пример #26
0
 def test_next_node_when_config_fail_on_unknown_properties_is_false(self):
     ele = Element("nope")
     ctx = XmlContext()
     cfg = ParserConfig(fail_on_unknown_properties=False)
     meta = XmlMeta(
         name="foo",
         clazz=None,
         qname=QName("foo"),
         source_qname=QName("foo"),
         nillable=False,
     )
     node = ElementNode(position=0, meta=meta, config=cfg)
     actual = node.next_node(ele, 10, ctx)
     self.assertEqual(SkipNode(position=10), actual)
Пример #27
0
    def test_next_node_when_given_qname_does_not_match_any_var(self):
        ele = Element("nope")
        ctx = XmlContext()
        cfg = ParserConfig()
        meta = XmlMeta(
            name="foo",
            clazz=None,
            qname=QName("foo"),
            source_qname=QName("foo"),
            nillable=False,
        )
        node = ElementNode(position=0, meta=meta, config=cfg)

        with self.assertRaises(XmlContextError) as cm:
            node.next_node(ele, 10, ctx)

        self.assertEqual("foo does not support mixed content: nope",
                         str(cm.exception))
Пример #28
0
    def test_next_node_when_given_qname_matches_primitive_var(self):
        ele = Element("a")
        ctx = XmlContext()
        cfg = ParserConfig()
        var = XmlText(name="a", qname=QName("a"), types=[int], default=100)
        meta = XmlMeta(
            name="foo",
            clazz=None,
            qname=QName("foo"),
            source_qname=QName("foo"),
            nillable=False,
            vars=[var],
        )
        node = ElementNode(position=0, meta=meta, config=cfg)

        actual = node.next_node(ele, 10, ctx)
        self.assertIsInstance(actual, PrimitiveNode)
        self.assertEqual(10, actual.position)
        self.assertEqual(var, actual.var)
Пример #29
0
def deserialize(resource: Union[str, Path, bytes],
                target_class: Optional[Type[T]] = None) -> Optional[T]:
    parser = XmlParser(context=XmlContext())
    obj = None

    if os.path.isfile(resource):
        resource = Path(resource)

    if isinstance(resource, str):
        obj = parser.from_string(resource, target_class)
    if isinstance(resource, Path):
        obj = parser.from_path(resource, target_class)
    if isinstance(resource, bytes):
        obj = parser.from_bytes(resource, target_class)

    if obj and hasattr(obj, 'complemento') and obj.complemento:
        complementos = __deserialize_complementos(obj)
        setattr(obj.complemento, 'any_element', complementos)

    return obj
Пример #30
0
    def test_next_node_when_given_qname_matches_any_element_var(self):
        ele = Element("a")
        ctx = XmlContext()
        cfg = ParserConfig()
        var = XmlWildcard(name="a",
                          qname=QName("a"),
                          types=[],
                          dataclass=False)
        meta = XmlMeta(
            name="foo",
            clazz=None,
            qname=QName("foo"),
            source_qname=QName("foo"),
            nillable=False,
            vars=[var],
        )
        node = ElementNode(position=0, meta=meta, config=cfg)

        actual = node.next_node(ele, 10, ctx)
        self.assertIsInstance(actual, WildcardNode)
        self.assertEqual(10, actual.position)
        self.assertEqual(var.qname, actual.qname)