def match_type(val: Any) -> DataType: if not isinstance(val, str): return DataType.from_value(val) for tp in converter.explicit_types(): if converter.test(val, [tp]): return DataType.from_type(tp) return DataType.STRING
def test_from_value_period(self): g_day = XmlPeriod("---20-02:44") self.assertEqual(DataType.G_DAY, DataType.from_value(g_day)) g_month_day = XmlPeriod("--12-20-02:44") self.assertEqual(DataType.G_MONTH_DAY, DataType.from_value(g_month_day)) g_month = XmlPeriod("--12") self.assertEqual(DataType.G_MONTH, DataType.from_value(g_month)) g_year_month = XmlPeriod("2021-01") self.assertEqual(DataType.G_YEAR_MONTH, DataType.from_value(g_year_month)) g_year = XmlPeriod("2021") self.assertEqual(DataType.G_YEAR, DataType.from_value(g_year))
def data_type(cls, attrs: Dict, ns_map: Dict) -> DataType: """Convert the xsi:type attribute to a DataType, defaults to DataType.STRING.""" xsi_type = cls.xsi_type(attrs, ns_map) datatype = DataType.STRING if xsi_type: datatype = DataType.from_qname(xsi_type) or datatype return datatype
def test_from_value_simple(self): self.assertEqual(DataType.BOOLEAN, DataType.from_value(True)) self.assertEqual(DataType.DECIMAL, DataType.from_value(Decimal(1.1))) self.assertEqual(DataType.QNAME, DataType.from_value(QName("a"))) self.assertEqual(DataType.STRING, DataType.from_value("a")) self.assertEqual(DataType.DATE, DataType.from_value(XmlDate(2021, 1, 1))) self.assertEqual(DataType.TIME, DataType.from_value(XmlTime(12, 1, 1))) self.assertEqual( DataType.DATE_TIME, DataType.from_value(XmlDateTime(2002, 1, 1, 12, 1, 1)) ) self.assertEqual(DataType.STRING, DataType.from_value(self))
def test_from_value(self): self.assertEqual(DataType.BOOLEAN, DataType.from_value(True)) self.assertEqual(DataType.INT, DataType.from_value(1)) self.assertEqual(DataType.FLOAT, DataType.from_value(1.1)) self.assertEqual(DataType.DECIMAL, DataType.from_value(Decimal(1.1))) self.assertEqual(DataType.QNAME, DataType.from_value(QName("a"))) self.assertEqual(DataType.STRING, DataType.from_value("a"))
def build_data_type( cls, target: Class, name: str, index: int = 0, forward: bool = False ) -> AttrType: """Create an attribute type for the target class.""" prefix, suffix = text.split(name) native = False namespace = target.ns_map.get(prefix) if Namespace.get_enum(namespace) and DataType.get_enum(suffix): name = suffix native = True return AttrType(name=name, index=index, native=native, forward=forward,)
def is_xsi_type(cls, key: str, value: Any) -> bool: """ Return whether the value is an xsi:type or not based on the given attribute name/value. :param key: Attribute name :param value: Attribute value """ if isinstance(value, str) and value.startswith("{"): return key == QNames.XSI_TYPE or DataType.from_qname(value) is not None return False
def build_data_type( cls, target: Class, name: str, index: int = 0, forward: bool = False ) -> AttrType: """Create an attribute type for the target class.""" prefix, suffix = text.split(name) namespace = target.ns_map.get(prefix, target.qname.namespace) native = ( Namespace.get_enum(namespace) is not None and DataType.get_enum(suffix) is not None ) return AttrType( qname=QName(namespace, suffix), index=index, native=native, forward=forward, )
def write_element(cls, value: Any, var: XmlVar, namespace: NoneStr) -> Generator: """Produce an element events stream for the given simple type value.""" yield XmlWriterEvent.START, var.qname if var.nillable: yield XmlWriterEvent.ATTR, QNames.XSI_NIL, "true" if value is not None and var.any_type: datatype = DataType.from_value(value) if datatype != DataType.STRING: yield XmlWriterEvent.ATTR, QNames.XSI_TYPE, QName(str(datatype)) yield XmlWriterEvent.DATA, value yield XmlWriterEvent.END, var.qname
def build_data_type(cls, target: Class, name: str, forward: bool = False) -> AttrType: """Create an attribute type for the target class.""" prefix, suffix = text.split(name) namespace = target.ns_map.get(prefix, target.target_namespace) qname = build_qname(namespace, suffix) datatype = DataType.from_qname(qname) return AttrType( qname=qname, native=datatype is not None, forward=forward, )
def find_types(self, qname: str) -> List[Type[T]]: """ Find all classes that match the given xsi:type qname. - Ignores native schema types, xs:string, xs:float, xs:int, ... - Rebuild cache if new modules were imported since last run :param qname: Qualified name """ if not DataType.from_qname(qname): self.build_xsi_cache() if qname in self.xsi_cache: return self.xsi_cache[qname] return []
def build_node(self, var: XmlVar, attrs: Dict, ns_map: Dict, position: int) -> Optional[XmlNode]: if var.is_clazz_union: return UnionNode( var=var, attrs=attrs, ns_map=ns_map, context=self.context, position=position, ) xsi_type = ParserUtils.xsi_type(attrs, ns_map) if var.clazz: return self.build_element_node( var.clazz, attrs, ns_map, position, var.derived, xsi_type, ) if not var.any_type and not var.wildcard: return PrimitiveNode(var, ns_map) datatype = DataType.from_qname(xsi_type) if xsi_type else None derived = var.derived or var.wildcard if datatype: return StandardNode(datatype, ns_map, derived, var.nillable) node = None clazz = None if xsi_type: clazz = self.context.find_type(xsi_type) if clazz: node = self.build_element_node(clazz, attrs, ns_map, position, derived, xsi_type) if node: return node return WildcardNode(var=var, attrs=attrs, ns_map=ns_map, position=position)
def write_derived_element(self, value: DerivedElement, var: XmlVar, namespace: NoneStr) -> Generator: if is_dataclass(value.value): xsi_type = None if value.substituted: meta = self.context.build(value.value.__class__) xsi_type = QName(meta.source_qname) yield from self.write_dataclass(value.value, namespace, qname=value.qname, xsi_type=xsi_type) else: datatype = DataType.from_value(value.value) yield XmlWriterEvent.START, value.qname yield XmlWriterEvent.ATTR, QNames.XSI_TYPE, QName(str(datatype)) yield XmlWriterEvent.DATA, value.value yield XmlWriterEvent.END, value.qname
def build_data_type(self, target: Class, name: str, index: int = 0, forward_ref: bool = False) -> AttrType: prefix, suffix = text.split(name) native = False namespace = target.ns_map.get(prefix) if Namespace.get_enum(namespace) and DataType.get_enum(suffix): name = suffix native = True return AttrType( name=name, index=index, native=native, forward_ref=forward_ref, )
def test_from_value_int(self): self.assertEqual(DataType.SHORT, DataType.from_value(-32768)) self.assertEqual(DataType.SHORT, DataType.from_value(32767)) self.assertEqual(DataType.INT, DataType.from_value(-32769)) self.assertEqual(DataType.INT, DataType.from_value(32768)) self.assertEqual(DataType.INT, DataType.from_value(-2147483648)) self.assertEqual(DataType.INT, DataType.from_value(2147483647)) self.assertEqual(DataType.LONG, DataType.from_value(-2147483649)) self.assertEqual(DataType.LONG, DataType.from_value(2147483648)) self.assertEqual(DataType.LONG, DataType.from_value(-9223372036854775808)) self.assertEqual(DataType.LONG, DataType.from_value(9223372036854775807)) self.assertEqual(DataType.INTEGER, DataType.from_value(-9223372036854775809)) self.assertEqual(DataType.INTEGER, DataType.from_value(9223372036854775808))
def native_code(self) -> Optional[str]: data_type = DataType.get_enum(self.name) if self.native else None return data_type.code if data_type else None
def native_type(self) -> Any: data_type = DataType.get_enum(self.name) if self.native else None return data_type.local if data_type else None
def datatype(self) -> Optional[DataType]: return DataType.from_qname(self.qname) if self.native else None
def native_type(self) -> Any: """Return the python build-in type if it's a native type.""" data_type = DataType.get_enum(self.name) if self.native else None return data_type.local if data_type else None
def native_code(self) -> Optional[str]: """Return the xml data type if it's native type.""" data_type = DataType.get_enum(self.name) if self.native else None return data_type.code if data_type else None
def native_name(self) -> Optional[str]: """Return the python build-in type name: `'str'`, `'int'` if it's native type.""" data_type = DataType.get_enum(self.name) if self.native else None return data_type.local_name if data_type else None
def test_from_value_float(self): self.assertEqual(DataType.FLOAT, DataType.from_value(-1.175494351e-38)) self.assertEqual(DataType.FLOAT, DataType.from_value(3.402823466e38)) self.assertEqual(DataType.DOUBLE, DataType.from_value(-1.175494352e-38)) self.assertEqual(DataType.DOUBLE, DataType.from_value(3.402823467e38))