コード例 #1
0
    def bind_element_children(
        cls, params: Dict, meta: XmlMeta, position: int, objects: List,
    ):
        """Return a dictionary of qualified object names and their values for
        the given queue item."""

        while len(objects) > position:
            qname, value = objects.pop(position)
            arg = meta.find_var(qname, FindMode.NOT_WILDCARD) or meta.find_var(
                qname, FindMode.WILDCARD
            )

            if not arg:
                raise ParserError("Impossible exception!")

            if not arg.init:
                continue

            if value is None:
                value = ""

            if not cls.bind_element_param(params, arg, value):
                lookup = QName(value.qname) if isinstance(value, AnyElement) else qname
                wild = cls.find_eligible_wildcard(meta, lookup, params)

                if not wild:
                    logger.warning("Unassigned parsed object %s", qname)
                else:
                    cls.bind_element_wildcard_param(params, wild, qname, value)
コード例 #2
0
    def bind_element_wild_text(cls, params: Dict, meta: XmlMeta, element: Element):
        """
        Extract the text and tail content and bind it accordingly in the params
        dictionary.

        - var is a list prepend the text and append the tail.
        - var is present in the params assign the text and tail to the generic object.
        - Otherwise bind the given element to a new generic object.
        """
        var = meta.find_var(mode=FindMode.WILDCARD)
        if not var:
            return

        txt, tail = cls.element_text_and_tail(element)
        if not txt and not tail:
            return

        if var.is_list:
            if var.name not in params:
                params[var.name] = []
            if txt:
                params[var.name].insert(0, txt)
            if tail:
                params[var.name].append(tail)
        elif var.name in params:
            params[var.name].text = txt
            params[var.name].tail = tail
        else:
            params[var.name] = cls.parse_any_element(element, False)
コード例 #3
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)
コード例 #4
0
    def build(self, clazz: Type, parent_ns: Optional[str] = None) -> XmlMeta:
        """Fetch from cache or build the metadata object for the given class
        and parent namespace."""

        if clazz not in self.cache:

            # Ensure the given type is a dataclass.
            if not is_dataclass(clazz):
                raise XmlContextError(f"Object {clazz} is not a dataclass.")

            # Fetch the dataclass meta settings and make sure we don't inherit
            # the parent class meta.
            meta = getattr(clazz, "Meta", None)
            if meta and meta.__qualname__ != f"{clazz.__name__}.Meta":
                meta = None

            name = getattr(meta, "name", self.name_generator(clazz.__name__))
            nillable = getattr(meta, "nillable", False)
            namespace = getattr(meta, "namespace", parent_ns)
            module = sys.modules[clazz.__module__]
            source_namespace = getattr(module, "__NAMESPACE__", None)

            self.cache[clazz] = XmlMeta(
                name=name,
                clazz=clazz,
                qname=QName(namespace, name),
                source_qname=QName(source_namespace, name),
                nillable=nillable,
                vars=list(self.get_type_hints(clazz, namespace)),
            )
        return self.cache[clazz]
コード例 #5
0
    def build(self, clazz: Type, parent_ns: Optional[str] = None) -> XmlMeta:
        """
        Fetch from cache or build the binding metadata for the given class and
        parent namespace.

        :param clazz: A dataclass type
        :param parent_ns: The inherited parent namespace
        """

        if clazz not in self.cache:

            # Ensure the given type is a dataclass.
            if not is_dataclass(clazz):
                raise XmlContextError(f"Object {clazz} is not a dataclass.")

            # Fetch the dataclass meta settings and make sure we don't inherit
            # the parent class meta.
            meta = clazz.Meta if "Meta" in clazz.__dict__ else None
            name = getattr(meta, "name", None) or self.local_name(
                clazz.__name__)
            nillable = getattr(meta, "nillable", False)
            namespace = getattr(meta, "namespace", parent_ns)
            module = sys.modules[clazz.__module__]
            source_namespace = getattr(module, "__NAMESPACE__", None)

            self.cache[clazz] = XmlMeta(
                clazz=clazz,
                qname=build_qname(namespace, name),
                source_qname=build_qname(source_namespace, name),
                nillable=nillable,
                vars=list(self.get_type_hints(clazz, namespace)),
            )
        return self.cache[clazz]
コード例 #6
0
 def bind_element_text(cls, params: Dict, metadata: XmlMeta, element: Element):
     """Add the given element's text content if any to the params dictionary
     with the text var name as key."""
     var = metadata.find_var(mode=FindMode.TEXT)
     if var and element.text is not None and var.init:
         params[var.name] = cls.parse_value(
             var.types, element.text, var.default, element.nsmap, var.is_tokens
         )
コード例 #7
0
ファイル: utils.py プロジェクト: neriusmika/xsdata
    def bind_objects(cls, params: Dict, meta: XmlMeta, position: int,
                     objects: List):
        """Return a dictionary of qualified object names and their values for
        the given queue item."""

        while len(objects) > position:
            qname, value = objects.pop(position)

            arg = meta.find_var(qname, FindMode.ELEMENT)
            if arg and cls.bind_var(params, arg, value):
                continue

            arg = meta.find_var(qname, FindMode.WILDCARD)
            if arg and cls.bind_wild_var(params, arg, qname, value):
                continue

            logger.warning("Unassigned parsed object %s", qname)
コード例 #8
0
ファイル: test_context.py プロジェクト: igieon/xsdata
 def test_fetch(self, mock_build, mock_find_subclass):
     meta = XmlMeta(
         clazz=ItemsType,
         qname="ItemsType",
         source_qname="ItemsType",
         nillable=False,
     )
     mock_build.return_value = meta
     actual = self.ctx.fetch(ItemsType, "foo")
     self.assertEqual(meta, actual)
     self.assertEqual(0, mock_find_subclass.call_count)
     mock_build.assert_called_once_with(ItemsType, "foo")
コード例 #9
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={},
     )
コード例 #10
0
    def bind_element_attrs(cls, params: Dict, metadata: XmlMeta, element: Element):
        """Parse the given element's attributes and any text content and return
        a dictionary of field names and values based on the given class
        metadata."""

        if not element.attrib:
            return

        wildcard = metadata.find_var(mode=FindMode.ATTRIBUTES)
        for key, value in element.attrib.items():
            var = metadata.find_var(QName(key), FindMode.ATTRIBUTE)

            if var and var.name not in params:
                if var.init:
                    params[var.name] = cls.parse_value(
                        var.types, value, var.default, element.nsmap, var.is_tokens
                    )
            elif wildcard:
                if wildcard.name not in params:
                    params[wildcard.name] = {}
                params[wildcard.name][key] = value
コード例 #11
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)
コード例 #12
0
ファイル: utils.py プロジェクト: neriusmika/xsdata
    def bind_attrs(cls, params: Dict, metadata: XmlMeta, attrs: Dict,
                   ns_map: Dict):
        """Parse the given element's attributes and any text content and return
        a dictionary of field names and values based on the given class
        metadata."""

        if not attrs:
            return

        wildcard = metadata.find_var(mode=FindMode.ATTRIBUTES)
        if wildcard:
            params[wildcard.name] = {}

        for qname, value in attrs.items():
            var = metadata.find_var(qname, FindMode.ATTRIBUTE)
            if var and var.name not in params:
                if var.init:
                    params[var.name] = cls.parse_value(value, var.types,
                                                       var.default, ns_map,
                                                       var.tokens, var.format)
            elif wildcard:
                params[wildcard.name][qname] = cls.parse_any_attribute(
                    value, ns_map)
コード例 #13
0
ファイル: test_context.py プロジェクト: igieon/xsdata
    def test_fetch_with_xsi_type_and_subclass_not_found(
            self, mock_build, mock_find_subclass):
        meta = XmlMeta(
            clazz=ItemsType,
            qname="ItemsType",
            source_qname="ItemsType",
            nillable=False,
        )

        mock_build.return_value = meta
        mock_find_subclass.return_value = None
        actual = self.ctx.fetch(ItemsType, xsi_type="foo")
        self.assertEqual(meta, actual)
        mock_find_subclass.assert_called_once_with(ItemsType, "foo")
コード例 #14
0
ファイル: test_context.py プロジェクト: igieon/xsdata
    def test_fetch_with_xsi_type_and_subclass_found(self, mock_build,
                                                    mock_find_subclass):
        meta = XmlMeta(
            clazz=ItemsType,
            qname="ItemsType",
            source_qname="ItemsType",
            nillable=False,
        )
        xsi_meta = replace(meta, qname="XsiType")

        mock_build.side_effect = [meta, xsi_meta]
        mock_find_subclass.return_value = xsi_meta
        actual = self.ctx.fetch(ItemsType, xsi_type="foo")
        self.assertEqual(xsi_meta, actual)
        mock_find_subclass.assert_called_once_with(ItemsType, "foo")
コード例 #15
0
ファイル: test_context.py プロジェクト: igieon/xsdata
    def test_build_build_vars(self, mock_get_type_hints):
        var = XmlVar(element=True, name="foo", qname="{foo}bar", types=[int])
        mock_get_type_hints.return_value = [var]

        result = self.ctx.build(ItemsType, None)
        expected = XmlMeta(
            clazz=ItemsType,
            qname="ItemsType",
            source_qname="ItemsType",
            nillable=False,
            vars=[var],
        )

        self.assertEqual(expected, result)
        mock_get_type_hints.assert_called_once_with(ItemsType, None)
コード例 #16
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))
コード例 #17
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)
コード例 #18
0
ファイル: utils.py プロジェクト: nimish/xsdata
    def bind_element_wild_text(cls, params: Dict, meta: XmlMeta, element: Element):
        var = meta.find_var(mode=FindMode.WILDCARD)
        if not var:
            return

        txt, tail = cls.element_text_and_tail(element)
        if not txt and not tail:
            return

        if var.is_list:
            if var.name not in params:
                params[var.name] = list()
            if txt:
                params[var.name].insert(0, txt)
            if tail:
                params[var.name].append(tail)
        elif var.name in params:
            params[var.name].text = txt
            params[var.name].tail = tail
        else:
            params[var.name] = cls.parse_any_element(element, False)
コード例 #19
0
    def bind_content(
        cls,
        params: Dict,
        metadata: XmlMeta,
        txt: Optional[str],
        ns_map: Dict,
    ) -> bool:
        """
        Add the given element's text content if any to the params dictionary
        with the text var name as key.

        Return if any data was bound.
        """

        if txt is not None:
            var = metadata.find_var(mode=FindMode.TEXT)
            if var and var.init:
                params[var.name] = cls.parse_value(txt, var.types, var.default,
                                                   ns_map, var.tokens)
                return True

        return False
コード例 #20
0
    def test_property_element_form(self):
        meta = XmlMeta(
            name="foo",
            clazz=BookForm,
            qname=QName("foo"),
            source_qname=QName("foo"),
            nillable=False,
        )
        self.assertEqual(FormType.UNQUALIFIED, meta.element_form)

        meta = replace(meta, qname=QName("bar", "foo"))
        self.assertEqual(FormType.QUALIFIED, meta.element_form)

        meta.vars.append(XmlElement(name="a", qname=QName("a")))
        self.assertEqual(FormType.UNQUALIFIED, meta.element_form)

        meta.vars.append(
            XmlElement(name="b", qname=QName("b"), namespaces=["bar"]))
        self.assertEqual(FormType.UNQUALIFIED, meta.element_form)

        meta.vars.pop(0)
        self.assertEqual(FormType.QUALIFIED, meta.element_form)
コード例 #21
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)
コード例 #22
0
ファイル: context.py プロジェクト: nimish/xsdata
    def build(self, clazz: Type, parent_ns: Optional[str] = None) -> XmlMeta:
        if clazz not in self.cache:
            if not is_dataclass(clazz):
                raise XmlContextError(f"Object {clazz} is not a dataclass.")

            meta = getattr(clazz, "Meta", None)
            if meta and meta.__qualname__ != f"{clazz.__name__}.Meta":
                meta = None

            name = getattr(meta, "name", self.name_generator(clazz.__name__))
            nillable = getattr(meta, "nillable", False)
            namespace = getattr(meta, "namespace", parent_ns)
            module = sys.modules[clazz.__module__]
            source_namespace = getattr(module, "__NAMESPACE__", None)

            self.cache[clazz] = XmlMeta(
                name=name,
                clazz=clazz,
                qname=QName(namespace, name),
                source_qname=QName(source_namespace, name),
                nillable=nillable,
                vars=list(self.get_type_hints(clazz, namespace)),
            )
        return self.cache[clazz]
コード例 #23
0
ファイル: utils.py プロジェクト: nimish/xsdata
 def bind_element_text(cls, params: Dict, metadata: XmlMeta, element: Element):
     var = metadata.find_var(mode=FindMode.TEXT)
     if var and element.text is not None and var.init:
         params[var.name] = cls.parse_value(
             var.types, element.text, var.default, element.nsmap, var.is_tokens
         )