示例#1
0
文件: resolver.py 项目: igieon/xsdata
 def resolve_imports(self):
     """Walk the import qualified names, check for naming collisions and add
     the necessary code generator import instance."""
     local_names = {
         split_qname(qname)[1]
         for qname in self.class_map.keys()
     }
     for qname in self.import_classes():
         package = self.find_package(qname)
         local_name = split_qname(qname)[1]
         exists = local_name in local_names
         local_names.add(local_name)
         self.add_import(qname=qname, package=package, exists=exists)
示例#2
0
    def serialize(self,
                  value: QName,
                  ns_map: Optional[Dict] = None,
                  **kwargs: Any) -> str:
        """
        Convert a QName instance to string either with a namespace prefix if a
        prefix-URI namespaces mapping is provided or to a fully qualified name
        with the namespace.

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

        if ns_map is None:
            return value.text

        namespace, tag = namespaces.split_qname(value.text)

        if not namespace:
            return tag

        prefix = namespaces.load_prefix(namespace, ns_map)

        return f"{prefix}:{tag}" if prefix else tag
示例#3
0
    def copy_inner_class(cls, source: Class, target: Class, attr: Attr,
                         attr_type: AttrType):
        """
        Check if the given attr type is a forward reference and copy its inner
        class from the source to the target class.

        Checks:
            1. Update type if inner class in a circular reference
            2. Copy inner class, rename it if source is a simple type.
        """
        if not attr_type.forward:
            return

        # This will fail if no inner class is found, too strict???
        inner = ClassUtils.find_inner(source, attr_type.qname)

        if inner is target:
            attr_type.circular = True
        else:
            clone = inner.clone()
            clone.package = target.package
            clone.module = target.module

            # Simple type, update the name
            if clone.name == "@value":
                namespace, _ = split_qname(clone.qname)
                clone.qname = attr_type.qname = build_qname(
                    namespace, attr.name)

            target.inner.append(clone)
示例#4
0
    def field_default_enum(self, attr: Attr) -> str:
        assert attr.default is not None

        qname, enumeration = attr.default[6:].split("::", 1)
        qname = next(x.alias or qname for x in attr.types if x.qname == qname)
        _, name = split_qname(qname)
        return f"{self.class_name(name)}.{self.constant_name(enumeration, name)}"
示例#5
0
    def write_dataclass(
        self,
        obj: Any,
        namespace: NoneStr = None,
        qname: NoneStr = None,
        nillable: bool = False,
        xsi_type: Optional[QName] = None,
    ) -> Generator:
        """
        Produce an events stream from a dataclass.

        Optionally override the qualified name and the xsi properties
        type and nil.
        """

        meta = self.context.build(obj.__class__, namespace)
        qname = qname or meta.qname
        nillable = nillable or meta.nillable
        namespace, tag = split_qname(qname)

        yield XmlWriterEvent.START, qname

        for key, value in self.next_attribute(obj, meta, nillable, xsi_type):
            yield XmlWriterEvent.ATTR, key, value

        for var, value in self.next_value(obj, meta):
            if value is not None or var.nillable:
                yield from self.write_value(value, var, namespace)

        yield XmlWriterEvent.END, qname
示例#6
0
 def attributes(cls, elements: Iterator[AnyElement]) -> Dict:
     """Return all attributes from all extended elements as a dictionary."""
     return {
         split_qname(qname)[1]: value
         for element in elements
         if isinstance(element, AnyElement)
         for qname, value in element.attributes.items()
     }
示例#7
0
    def map(cls, element: AnyElement) -> List[Class]:
        """Map schema children elements to classes."""

        assert element.qname is not None

        target_namespace, module = split_qname(element.qname)
        target = cls.build_class(element, target_namespace)

        return list(ClassUtils.flatten(target, module))
示例#8
0
def read_root_name(path: Path) -> str:
    try:
        recovering_parser = etree.XMLParser(
            recover=True, resolve_entities=False, no_network=True
        )
        tree = etree.parse(str(path), parser=recovering_parser)  # nosec
        _, local_name = split_qname(tree.getroot().tag)
        return text.pascal_case(utils.safe_snake(local_name, "Type"))
    except Exception:
        return ""
示例#9
0
    def matches_wildcard(self, qname: str) -> bool:
        """Match the given qname to the wildcard allowed namespaces."""

        if qname == "*":
            return True

        namespace, tag = split_qname(qname)
        if not self.namespaces and namespace is None:
            return True

        return any(
            self.match_namespace(ns, namespace) for ns in self.namespaces)
示例#10
0
文件: resolver.py 项目: igieon/xsdata
    def add_import(self, qname: str, package: str, exists: bool = False):
        """Append an import package to the list of imports with any if
        necessary aliases if the import name exists in the local module."""
        alias = None
        local_name = split_qname(qname)[1]
        if exists:
            module = package.split(".")[-1]
            alias = f"{module}:{local_name}"
            self.aliases[qname] = alias

        self.imports.append(
            Import(name=local_name, source=package, alias=alias))
示例#11
0
文件: sanitizer.py 项目: gramm/xsdata
    def rename_class(self, target: Class):
        """Find the next available class identifier, save the original name in
        the class metadata and update the class qualified name and all classes
        that depend on the target class."""

        qname = target.qname
        namespace, name = split_qname(target.qname)
        target.qname = self.next_qname(namespace, name)
        target.meta_name = name
        self.container.reset(target, qname)

        for item in self.container.iterate():
            self.rename_class_dependencies(item, qname, target.qname)
示例#12
0
    def test_split_qname(self):
        self.assertEqual(("a", "b"), split_qname("{a}b"))
        self.assertEqual((None, "b"), split_qname("b"))
        self.assertEqual((None, "{"), split_qname("{"))
        self.assertEqual((None, "{foobar"), split_qname("{foobar"))

        with self.assertRaises(IndexError):
            split_qname("")
示例#13
0
    def build_class(cls, element: AnyElement,
                    target_namespace: Optional[str]) -> Class:

        assert element.qname is not None

        namespace, name = split_qname(element.qname)
        target = Class(
            qname=build_qname(target_namespace, name),
            namespace=cls.select_namespace(namespace, target_namespace),
            tag=Tag.ELEMENT,
            module="",
        )
        children = [c for c in element.children if isinstance(c, AnyElement)]
        sequential_set = cls.sequential_names(children)

        for key, value in element.attributes.items():
            attr_type = cls.build_attribute_type(key, value)
            cls.build_attribute(target, key, attr_type, target_namespace,
                                Tag.ATTRIBUTE)

        for child in children:

            assert child.qname is not None

            if child.tail:
                target.mixed = True

            if child.attributes or child.children:
                inner = cls.build_class(child, target_namespace)
                attr_type = AttrType(qname=inner.qname, forward=True)
                target.inner.append(inner)
            else:
                attr_type = cls.build_attribute_type(child.qname, child.text)

            cls.build_attribute(
                target,
                child.qname,
                attr_type,
                target_namespace,
                Tag.ELEMENT,
                child.qname in sequential_set,
            )

        if element.text:
            attr_type = cls.build_attribute_type("value", element.text)
            cls.build_attribute(target, "value", attr_type, None,
                                Tag.SIMPLE_TYPE)

        return target
示例#14
0
    def start_tag(self, qname: str):
        """
        Start tag notification receiver.

        The receiver will flush the start of any pending element,
        create new namespaces context and queue the current tag
        for generation.

        :param qname: Tag qualified name
        """
        self.flush_start(False)

        self.ns_context.append(self.ns_map.copy())
        self.ns_map = self.ns_context[-1]

        self.pending_tag = split_qname(qname)
        self.add_namespace(self.pending_tag[0])
示例#15
0
    def build_attribute(
        cls,
        target: Class,
        qname: str,
        attr_type: AttrType,
        target_namespace: Optional[str] = None,
        tag: str = Tag.ELEMENT,
        sequential: bool = False,
    ):

        namespace, name = split_qname(qname)
        namespace = cls.select_namespace(namespace, target_namespace, tag)
        index = len(target.attrs)

        attr = Attr(index=index, name=name, tag=tag, namespace=namespace)
        attr.types.append(attr_type)
        attr.restrictions.sequential = sequential or None
        cls.add_attribute(target, attr)
示例#16
0
def __deserialize_complementos(obj: object) -> list:
    complementos = []
    if not obj or not hasattr(obj, 'complemento'):
        return complementos

    obj.complemento = obj.complemento[0] if isinstance(
        obj.complemento, list) else obj.complemento
    for complemento in getattr(obj.complemento, 'any_element', []):
        ns, tag = namespaces.split_qname(getattr(complemento, 'qname', ''))
        complemento_type = COMPLEMENTO_TYPES_MAP.get(ns)

        if not complemento_type:
            continue

        delattr(complemento, 'qname')
        complemento = deserialize(serialize(complemento), complemento_type)
        complementos.append(complemento)

    return complementos
示例#17
0
    def write_wildcard(self, value: AnyElement, var: XmlVar,
                       namespace: NoneStr) -> Generator:
        """Produce an element events stream for the given generic object."""
        if value.qname:
            namespace, tag = split_qname(value.qname)
            yield XmlWriterEvent.START, value.qname

        for key, val in value.attributes.items():
            yield XmlWriterEvent.ATTR, key, val

        yield XmlWriterEvent.DATA, value.text

        for child in value.children:
            yield from self.write_any_type(child, var, namespace)

        if value.qname:
            yield XmlWriterEvent.END, value.qname

        if value.tail:
            yield XmlWriterEvent.DATA, value.tail
示例#18
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)
        self.attrs[name] = self.encode_data(value)
示例#19
0
    def build_envelope_class(
        cls,
        definitions: Definitions,
        binding_message: BindingMessage,
        port_type_message: PortTypeMessage,
        name: str,
        style: str,
        namespace: Optional[str],
    ) -> Class:
        """Step 6.1: Build Envelope class for the given binding message with
        attributes from the port type message."""

        target = Class(
            qname=build_qname(definitions.target_namespace, name),
            meta_name="Envelope",
            type=type(binding_message),
            module=definitions.module,
            ns_map=binding_message.ns_map,
            namespace=namespace,
        )
        message = port_type_message.message

        for ext in binding_message.extended_elements:
            assert ext.qname is not None
            local_name = split_qname(ext.qname)[1].title()
            inner = cls.build_inner_class(target, local_name)

            if style == "rpc" and local_name == "Body":
                namespace = ext.attributes.get("namespace")
                attrs = cls.map_port_type_message(port_type_message, namespace)
            else:
                attrs = cls.map_binding_message_parts(
                    definitions, message, ext, inner.ns_map
                )

            inner.attrs.extend(attrs)

        return target
示例#20
0
    def map_binding_message_parts(
        cls, definitions: Definitions, message: str, extended: AnyElement, ns_map: Dict
    ) -> Iterator[Attr]:
        """Find a Message instance and map its parts to attributes according to
        the the extensible element.."""
        parts = []
        if "part" in extended.attributes:
            parts.append(extended.attributes["part"])
        elif "parts" in extended.attributes:
            parts.extend(extended.attributes["parts"].split())

        if "message" in extended.attributes:
            message_name = split_qname(extended.attributes["message"])[1]
        else:
            message_name = text.suffix(message)

        definition_message = definitions.find_message(message_name)
        message_parts = definition_message.parts

        if parts:
            message_parts = [part for part in message_parts if part.name in parts]

        yield from cls.build_parts_attributes(message_parts, ns_map)
示例#21
0
    def end_tag(self, qname: str):
        """
        End tag notification receiver.

        The receiver will flush if pending the start of the element, end
        the element, its tail content and its namespaces prefix mapping
        and current context.

        :param qname: Tag qualified name
        """
        self.flush_start(True)
        self.handler.endElementNS(split_qname(qname), None)

        if self.tail:
            self.handler.characters(self.tail)

        self.tail = None
        self.in_tail = False
        self.ns_context.pop()
        if self.ns_context:
            self.ns_map = self.ns_context[-1]

        for prefix in self.pending_prefixes.pop():
            self.handler.endPrefixMapping(prefix)
示例#22
0
 def lname(self) -> str:
     """Local name."""
     _, name = split_qname(self.qname)
     return name
示例#23
0
 def name(self) -> str:
     """Shortcut for qname local name."""
     return split_qname(self.qname)[1]
示例#24
0
 def target_namespace(self) -> Optional[str]:
     return split_qname(self.qname)[0]