def _s_customize(cls, **kwargs): """This function duplicates and customizes the class it belongs to. The original class remains unchanged. Not meant to be overridden. """ cls_dict = odict({'__module__': cls.__module__}) if getattr(cls, '__orig__', None) is None: cls_dict['__orig__'] = cls class Attributes(cls.Attributes): pass if cls.Attributes.translations is None: Attributes.translations = {} if cls.Attributes.sqla_column_args is None: Attributes.sqla_column_args = (), {} cls_dict['Attributes'] = Attributes # as nillable is a property, it gets reset everytime a new class is # defined. So we need to reinitialize it explicitly. Attributes.nillable = cls.Attributes.nillable class Annotations(cls.Annotations): pass cls_dict['Annotations'] = Annotations for k, v in kwargs.items(): if k.startswith('_'): continue elif k in ("doc", "appinfo"): setattr(Annotations, k, v) elif k in ('primary_key', 'pk'): Attributes.sqla_column_args[-1]['primary_key'] = v elif k in ('prot_attrs', 'pa'): setattr(Attributes, 'prot_attrs', _decode_pa_dict(v)) elif k in ('foreign_key', 'fk'): from sqlalchemy.schema import ForeignKey t, d = Attributes.sqla_column_args fkt = (ForeignKey(v), ) Attributes.sqla_column_args = (t + fkt, d) elif k in ('autoincrement', 'onupdate', 'server_default'): Attributes.sqla_column_args[-1][k] = v elif k == 'max_occurs' and v in ('unbounded', 'inf', float('inf')): setattr(Attributes, k, Decimal('inf')) else: setattr(Attributes, k, v) return (cls.__name__, (cls, ), cls_dict)
def __init__(self, interface): InterfaceDocumentBase.__init__(self, interface) self.schema_dict = {} self.validation_schema = None self.namespaces = odict() self.complex_types = set()
class Fault(Tr069ComplexModel): _type_info = odict() _type_info["FaultCode"] = UnsignedInteger _type_info["FaultString"] = String _type_info["SetParameterValuesFault"] = SetParameterValuesFault.customize( max_occurs='unbounded', )
def _parse_qs(qs): pairs = (s2 for s1 in qs.split('&') for s2 in s1.split(';')) retval = odict() for name_value in pairs: if name_value is None or len(name_value) == 0: continue nv = name_value.split('=', 1) if len(nv) != 2: # Handle case of a control-name with no equal sign nv.append(None) name = unquote(nv[0].replace('+', ' ')) value = None if nv[1] is not None: value = unquote(nv[1].replace('+', ' ')) l = retval.get(name, None) if l is None: l = retval[name] = [] l.append(value) return retval
def map(self, django_model, exclude=None, **kwargs): """Prepare dict of model fields mapped to spyne models. :param django_model: Django model class. :param exclude: list of fields excluded from mapping. :param kwargs: extra kwargs are passed to all field mappers :returns: dict mapping attribute names to spyne models :raises: :exc:`UnknownFieldMapperException` """ field_map = odict() for field in self._get_fields(django_model, exclude): field_type = field.__class__.__name__ try: field_mapper = self._registry[field_type] except KeyError: # mapper for this field is not registered if not (field.has_default() or field.null): # field is required raise self.UnknownFieldMapperException( 'No mapper for field type {0}'.format(field_type)) else: # skip this field logger.info('Field {0} is skipped from mapping.') continue attr_name, spyne_model = field_mapper.map(field, **kwargs) field_map[attr_name] = spyne_model return field_map
class SetParameterAttributesStruct(Tr069ComplexModel): _type_info = odict() _type_info["Name"] = String(max_length=256) _type_info["NotificationChange"] = Boolean _type_info["Notification"] = Integer _type_info["AccessListChange"] = Boolean _type_info["AccessList"] = AccessList
def map(self, django_model, exclude=None, **kwargs): """Prepare dict of model fields mapped to spyne models. :param django_model: Django model class. :param exclude: list of fields excluded from mapping. :param kwargs: extra kwargs are passed to all field mappers :returns: dict mapping attribute names to spyne models :raises: :exc:`UnknownFieldMapperException` """ field_map = odict() for field in self._get_fields(django_model, exclude): field_type = field.get_internal_type() try: field_mapper = self._registry[field_type] except KeyError: # mapper for this field is not registered if not (field.has_default() or field.null): # field is required raise self.UnknownFieldMapperException( 'No mapper for field type {0}'.format(field_type)) else: # skip this field logger.info('Field {0} is skipped from mapping.') continue attr_name, spyne_model = field_mapper.map(field, **kwargs) field_map[attr_name] = spyne_model return field_map
class ID(Tr069ComplexModel): # Note: for some reason, XmlAttribute/XmlData pairs MUST be ordered, with # XmlAttribute coming first. This appears to be a spyne bug (something to do # with spyne.interface._base.add_class()) _type_info = odict() _type_info["mustUnderstand"] = XmlAttribute(String, ns=SOAP_ENV) _type_info["Data"] = XmlData(String)
def _s_customize(cls, **kwargs): """This function duplicates and customizes the class it belongs to. The original class remains unchanged. Not meant to be overridden. """ cls_dict = odict({'__module__': cls.__module__}) if getattr(cls, '__orig__', None) is None: cls_dict['__orig__'] = cls class Attributes(cls.Attributes): pass if cls.Attributes.translations is None: Attributes.translations = {} if cls.Attributes.sqla_column_args is None: Attributes.sqla_column_args = (), {} cls_dict['Attributes'] = Attributes # as nillable is a property, it gets reset everytime a new class is # defined. So we need to reinitialize it explicitly. Attributes.nillable = cls.Attributes.nillable class Annotations(cls.Annotations): pass cls_dict['Annotations'] = Annotations for k, v in kwargs.items(): if k.startswith('_'): continue elif k in ("doc", "appinfo"): setattr(Annotations, k, v) elif k in ('primary_key', 'pk'): Attributes.sqla_column_args[-1]['primary_key'] = v elif k in ('prot_attrs', 'pa'): setattr(Attributes, 'prot_attrs', _decode_pa_dict(v)) elif k in ('foreign_key', 'fk'): from sqlalchemy.schema import ForeignKey t, d = Attributes.sqla_column_args fkt = (ForeignKey(v),) Attributes.sqla_column_args = (t + fkt, d) elif k in ('autoincrement', 'onupdate', 'server_default'): Attributes.sqla_column_args[-1][k] = v elif k == 'max_occurs' and v in ('unbounded', 'inf', float('inf')): setattr(Attributes, k, Decimal('inf')) else: setattr(Attributes, k, v) return (cls.__name__, (cls,), cls_dict)
def produce(namespace, type_name, members): """Lets you create a class programmatically.""" return ComplexModelMeta(type_name, (ComplexModel,), odict({ '__namespace__': namespace, '__type_name__': type_name, '_type_info': TypeInfo(members), }))
def produce(namespace, type_name, members): """Lets you create a class programmatically.""" return ComplexModelMeta( type_name, (ComplexModel,), odict({"__namespace__": namespace, "__type_name__": type_name, "_type_info": TypeInfo(members)}), )
class Inform(Tr069ComplexModel): _type_info = odict() _type_info["DeviceId"] = DeviceIdStruct _type_info["Event"] = EventList _type_info["MaxEnvelopes"] = UnsignedInteger _type_info["CurrentTime"] = DateTime _type_info["RetryCount"] = UnsignedInteger _type_info["ParameterList"] = ParameterValueList
class Person(ComplexModel): __namespace__ = "http://xmlns.com/foaf/0.1/" _type_info = odict([ ('name', String), #TO-DO Add atrribute ('mbox', String), ])
class Release(ComplexModel): __namespace__ = "http://usefulinc.com/ns/doap#" _type_info = odict([ ('about', RdfAbout(String, ns="http://www.w3.org/1999/02/22-rdf-syntax-ns#")), ('Version', Version), ])
def __init__(self, interface): InterfaceDocumentBase.__init__(self, interface) self.schema_dict = {} self.validation_schema = None pref = self.interface.prefmap[self.interface.app.tns] self.namespaces = odict({pref: SchemaInfo()}) self.complex_types = set()
def __init__(self, interface): super(XmlSchema, self).__init__(interface) self.schema_dict = {} self.validation_schema = None pref = self.interface.prefmap[self.interface.app.tns] self.namespaces = odict({pref: SchemaInfo()}) self.complex_types = set()
class anySimpleType(Tr069ComplexModel): """ Type used to transfer simple data of various types. Data type is defined in 'type' XML attribute. Data is handled as a string. """ _type_info = odict() _type_info["type"] = XmlAttribute(String, ns=XSI_NS) _type_info["Data"] = XmlData(String) def __repr__(self): """For types we can't resolve only print the datum""" return self.Data
class Download(Tr069ComplexModel): _type_info = odict() _type_info["CommandKey"] = CommandKeyType _type_info["FileType"] = String(max_length=64) _type_info["URL"] = String(max_length=256) _type_info["Username"] = String(max_length=256) _type_info["Password"] = String(max_length=256) _type_info["FileSize"] = UnsignedInteger _type_info["TargetFileName"] = String(max_length=256) _type_info["DelaySeconds"] = UnsignedInteger _type_info["SuccessURL"] = String(max_length=256) _type_info["FailureURL"] = String(max_length=256)
class Project(ComplexModel): __namespace__ = "http://usefulinc.com/ns/doap#" _type_info = odict([ ('about', RdfAbout(String, ns="http://www.w3.org/1999/02/22-rdf-syntax-ns#")), ('name', String), ('created', Date), ('shortdesc', Unicode), ('homepage', String), ('developer', Developer), ('release', Release.customize(max_occurs=float('inf'))), ])
class ParameterListUnion(Tr069ComplexModel): """ Union of structures that get instantiated as 'ParameterList' in ACS->CPE messages. This is required because AcsToCpeRequests can only have one parameter named 'ParameterList', so that must also be a union """ _type_info = odict() # Fields from ParameterValueList _type_info["ParameterValueStruct"] = ParameterValueStruct.customize( max_occurs='unbounded') _type_info["arrayType"] = XmlAttribute(String, ns=SOAP_ENC) # Fields from SetParameterAttributesList _type_info["SetParameterAttributesStruct"] = \ SetParameterAttributesStruct.customize(max_occurs='unbounded')
class Version(ComplexModel): __namespace__ = "http://usefulinc.com/ns/doap#" _type_info = odict([ ('name', String), ('created', Date), ('revision', String), #ns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" #TO-DO Add path#md5 -> rdf:resource as atrribute ('file-release', String), ("resource", RdfResource(String, ns="http://www.w3.org/1999/02/22-rdf-syntax-ns#", attribute_of="file-release")), ])
class Download(Tr069ComplexModel): _type_info = odict() _type_info["CommandKey"] = CommandKeyType _type_info["FileType"] = String(max_length=64) _type_info["URL"] = String(max_length=256) _type_info["Username"] = String(max_length=256) _type_info["Password"] = String(max_length=256) _type_info["FileSize"] = UnsignedInteger _type_info["TargetFileName"] = String(max_length=256) _type_info["DelaySeconds"] = UnsignedInteger _type_info["SuccessURL"] = String(max_length=256) _type_info["FailureURL"] = String(max_length=256) # The following are extra aditions introduced for Baicells _type_info["Md5"] = String(max_length=32) _type_info["RawMode"] = Boolean
def etree_to_dict(element, iterable=(list, list.append)): """Takes an xml root element and returns the corresponding dict. The second argument is a pair of iterable type and the function used to add elements to the iterable. The xml attributes are ignored. """ if (element.text is None) or element.text.isspace(): retval = odict() for elt in element: if not (elt.tag in retval): retval[elt.tag] = iterable[0]() iterable[1](retval[elt.tag], etree_to_dict(elt, iterable)) else: retval = element.text return retval
class AcsToCpeRequests(Tr069ComplexModel): """ Union of all ACS->CPE requests. Only fields for one request is populated per message instance """ _type_info = odict() # Fields for SetParameterValues _type_info[ "ParameterList"] = ParameterListUnion # See ParameterListUnion for explanation _type_info["ParameterKey"] = ParameterKeyType # Fields for GetParameterValues # _type_info["ParameterList"] = ParameterValueList - Already covered above # Fields for GetParameterNames _type_info["ParameterPath"] = String.customize(max_length=256) _type_info["NextLevel"] = Boolean # Fields for SetParameterAttributes # _type_info["ParameterList"] = SetParameterAttributesList - Already covered above # Fields for GetParameterAttributes _type_info["ParameterNames"] = ParameterNames # Fields for AddObject _type_info["ObjectName"] = ObjectNameType _type_info["ParameterKey"] = ParameterKeyType # Fields for DeleteObject # _type_info["ObjectName"] = ObjectNameType - Already covered above # _type_info["ParameterKey"] = ParameterKeyType - Already covered above # Fields for Download _type_info["CommandKey"] = CommandKeyType _type_info["FileType"] = String(max_length=64) _type_info["URL"] = String(max_length=256) _type_info["Username"] = String(max_length=256) _type_info["Password"] = String(max_length=256) _type_info["FileSize"] = UnsignedInteger _type_info["TargetFileName"] = String(max_length=256) _type_info["DelaySeconds"] = UnsignedInteger _type_info["SuccessURL"] = String(max_length=256) _type_info["FailureURL"] = String(max_length=256) # Optional Baicells specific Download fields _type_info["Md5"] = String(max_length=32) _type_info["RawMode"] = Boolean
class DeviceIdStruct(Tr069ComplexModel): _type_info = odict() _type_info["Manufacturer"] = String(max_length=64) _type_info["OUI"] = String(length=6) _type_info["ProductClass"] = String(max_length=64) _type_info["SerialNumber"] = String(max_length=64) def as_dict(self): """ Overriding default implementation to fix memory leak. Can remove if or after https://github.com/arskom/spyne/pull/579 lands. Only patching it for this model because it's the only place in enodebd where we call this method. """ flat_type_info = self.get_flat_type_info(self.__class__) return dict(( (k, getattr(self, k)) for k in flat_type_info if getattr(self, k) is not None ))
def process_complex_type(self, c): def process_type(tn, name, wrapper=lambda x: x, element=None, attribute=None): t = self.get_type(tn) key = (c.name, name) if t is None: self.pending_types[key] = c self.debug2("not found: %r(%s)", key, tn) return if key in self.pending_types: del self.pending_types[key] assert name is not None, (key, e) kwargs = {} if element is not None: if e.min_occurs != "0": # spyne default kwargs['min_occurs'] = int(e.min_occurs) if e.max_occurs == "unbounded": kwargs['max_occurs'] = e.max_occurs elif e.max_occurs != "1": kwargs['max_occurs'] = int(e.max_occurs) if e.nillable != True: # spyne default kwargs['nillable'] = e.nillable if e.default is not None: kwargs['default'] = _prot.from_string(t, e.default) if len(kwargs) > 0: t = t.customize(**kwargs) if attribute is not None: if attribute.default is not None: kwargs['default'] = _prot.from_string(t, a.default) if len(kwargs) > 0: t = t.customize(**kwargs) ti.append((name, wrapper(t))) self.debug2(" found: %r(%s), c: %r", key, tn, kwargs) def process_element(e): if e.ref is not None: tn = e.ref name = e.ref.split(":", 1)[-1] elif e.name is not None: tn = e.type name = e.name else: raise Exception("dunno") process_type(tn, name, element=e) class L(list): def append(self, a): k, v = a assert isinstance(k, six.string_types), k super(L, self).append(a) ti = L() base = ComplexModelBase if c.name in self.retval[self.tns].types: self.debug1("modifying existing %r", c.name) else: self.debug1("adding complex type: %s", c.name) if c.sequence is not None: if c.sequence.elements is not None: for e in c.sequence.elements: process_element(e) if c.sequence.choices is not None: for ch in c.sequence.choices: if ch.elements is not None: for e in ch.elements: process_element(e) if c.choice is not None: if c.choice.elements is not None: for e in c.choice.elements: process_element(e) if c.attributes is not None: for a in c.attributes: if a.name is None: continue if a.type is None: continue process_type(a.type, a.name, XmlAttribute, attribute=a) if c.simple_content is not None: ext = c.simple_content.extension base_name = None if ext is not None: base_name = ext.base b = self.get_type(ext.base) if ext.attributes is not None: for a in ext.attributes: ti.append(self.process_attribute(a)) restr = c.simple_content.restriction if restr is not None: base_name = restr.base b = self.get_type(restr.base) if restr.attributes is not None: for a in restr.attributes: ti.append(self.process_attribute(a)) if issubclass(b, ComplexModelBase): base = b else: process_type(base_name, "_data", XmlData) if c.name in self.retval[self.tns].types: self.retval[self.tns].types[c.name]._type_info.update(ti) else: cls_dict = odict({ '__type_name__': c.name, '__namespace__': self.tns, '_type_info': ti, }) if self.repr is not None: cls_dict['__repr__'] = self.repr r = ComplexModelMeta(str(c.name), (base, ), cls_dict) self.retval[self.tns].types[c.name] = r
def parse_schema(ctx, elt): ctx.nsmap = nsmap = elt.nsmap ctx.prefmap = prefmap = dict([(v, k) for k, v in ctx.nsmap.items()]) ctx.schema = schema = _prot.from_element(XmlSchema10, elt) ctx.pending_types = {} ctx.pending_elements = {} ctx.tns = tns = schema.target_namespace if tns in ctx.retval: return ctx.retval[tns] = _Schema() ctx.debug0("1 %s processing includes", M(tns)) if schema.includes: for include in schema.includes: process_includes(ctx, include) if schema.elements: schema.elements = odict([(e.name, e) for e in schema.elements]) if schema.complex_types: schema.complex_types = odict([(c.name, c) for c in schema.complex_types]) if schema.simple_types: schema.simple_types = odict([(s.name, s) for s in schema.simple_types]) if schema.attributes: schema.attributes = odict([(a.name, a) for a in schema.attributes]) ctx.debug0("2 %s processing imports", R(tns)) if schema.imports: for imp in schema.imports: if not imp.namespace in ctx.retval: ctx.debug1("%s importing %s", tns, imp.namespace) file_name = ctx.files[imp.namespace] parse_schema_file(ctx.clone(2, dirname(file_name)), file_name) ctx.retval[tns].imports.add(imp.namespace) ctx.debug0("3 %s processing attributes", G(tns)) if schema.attributes: for s in schema.attributes.values(): n, t = process_attribute(ctx, s) ctx.retval[ctx.tns].types[n] = t ctx.debug0("4 %s processing simple_types", G(tns)) if schema.simple_types: for s in schema.simple_types.values(): st = process_simple_type(ctx, s) ctx.retval[ctx.tns].types[s.name] = st ctx.debug0("5 %s processing complex_types", B(tns)) if schema.complex_types: for c in schema.complex_types.values(): process_complex_type(ctx, c) ctx.debug0("6 %s processing elements", Y(tns)) if schema.elements: for e in schema.elements.values(): process_schema_element(ctx, e) process_pending(ctx) if ctx.parent is None: # for the top-most schema if ctx.children is not None: # if it uses <include> or <import> # This is needed for schemas with circular imports for c in chain([ctx], ctx.children): print_pending(c) ctx.debug0('') for c in chain([ctx], ctx.children): process_pending(c) for c in chain([ctx], ctx.children): process_pending(c) ctx.debug0('') for c in chain([ctx], ctx.children): print_pending(c, fail=True) return ctx.retval
class FaultStruct(Tr069ComplexModel): _type_info = odict() _type_info["FaultCode"] = Integer _type_info["FaultString"] = String(max_length=256)
class MethodList(Tr069ComplexModel): _type_info = odict() _type_info["MethodList"] = String(max_length=64, max_occurs='unbounded') _type_info["arrayType"] = XmlAttribute(String, ns=SOAP_ENC)
def __prepare__(mcs, name, bases, **kwds): return odict()
def parse_schema(self, elt): self.nsmap = dict(elt.nsmap.items()) self.prefmap = dict([(v, k) for k, v in self.nsmap.items()]) self.schema = schema = _prot.from_element(self, XmlSchema10, elt) self.pending_types = {} self.pending_elements = {} self.tns = tns = schema.target_namespace if self.tns is None: self.tns = tns = '__no_ns__' if tns in self.retval: return self.retval[tns] = _Schema() self.debug0("1 %s processing includes", MAG(tns)) if schema.includes: for include in schema.includes: self.process_includes(include) if schema.elements: schema.elements = odict([(e.name, e) for e in schema.elements]) if schema.complex_types: schema.complex_types = odict([(c.name, c) for c in schema.complex_types]) if schema.simple_types: schema.simple_types = odict([(s.name, s) for s in schema.simple_types]) if schema.attributes: schema.attributes = odict([(a.name, a) for a in schema.attributes]) self.debug0("2 %s processing imports", R(tns)) if schema.imports: for imp in schema.imports: if not imp.namespace in self.retval: self.debug1("%s importing %s", tns, imp.namespace) fname = self.files[imp.namespace] self.clone(2, dirname(fname)).parse_schema_file(fname) self.retval[tns].imports.add(imp.namespace) self.debug0("3 %s processing simple_types", G(tns)) if schema.simple_types: for s in schema.simple_types.values(): self.process_simple_type(s) # no simple types should have been left behind. assert sum((len(v) for v in self.pending_simple_types.values())) == 0, \ self.pending_simple_types.values() self.debug0("4 %s processing attributes", G(tns)) if schema.attributes: for s in schema.attributes.values(): n, t = self.process_attribute(s) self.retval[self.tns].types[n] = t self.debug0("5 %s processing complex_types", B(tns)) if schema.complex_types: for c in schema.complex_types.values(): self.process_complex_type(c) self.debug0("6 %s processing elements", YEL(tns)) if schema.elements: for e in schema.elements.values(): self.process_schema_element(e) self.process_pending() if self.parent is None: # for the top-most schema if self.children is not None: # if it uses <include> or <import> # This is needed for schemas with circular imports for c in chain([self], self.children): c.print_pending() self.debug0('') # FIXME: should put this in a while loop that loops until no # changes occur for c in chain([self], self.children): c.process_pending() for c in chain([self], self.children): c.process_pending() self.debug0('') for c in chain([self], self.children): c.print_pending(fail=(not self.skip_errors)) return self.retval
def _s_customize(cls, **kwargs): """This function duplicates and customizes the class it belongs to. The original class remains unchanged. Not meant to be overridden. """ cls_dict = odict({"__module__": cls.__module__, "__doc__": cls.__doc__}) if getattr(cls, "__orig__", None) is None: cls_dict["__orig__"] = cls else: cls_dict["__orig__"] = cls.__orig__ class Attributes(cls.Attributes): pass if cls.Attributes.translations is None: Attributes.translations = {} if cls.Attributes.sqla_column_args is None: Attributes.sqla_column_args = (), {} cls_dict["Attributes"] = Attributes # properties get reset everytime a new class is defined. So we need # to reinitialize them explicitly. for k in ("nillable", "_xml_cloth", "_xml_root_cloth", "_html_cloth", "_html_root_cloth"): v = getattr(cls.Attributes, k) if v is not None: setattr(Attributes, k, v) class Annotations(cls.Annotations): pass cls_dict["Annotations"] = Annotations # get protocol attrs prot = kwargs.get("protocol", None) if prot is None: prot = kwargs.get("prot", None) if prot is None: prot = kwargs.get("p", None) if prot is not None and len(prot.type_attrs) > 0: # if there is a class customization from protocol, do it type_attrs = prot.type_attrs.copy() type_attrs.update(kwargs) logger.debug("%r: kwargs %r => %r from prot typeattr %r", cls, kwargs, type_attrs, prot.type_attrs) kwargs = type_attrs for k, v in kwargs.items(): if k.startswith("_"): continue if k in ("protocol", "prot", "p"): setattr(Attributes, "prot", v) if k in ("doc", "appinfo"): setattr(Annotations, k, v) elif k in ("primary_key", "pk"): setattr(Attributes, "primary_key", v) Attributes.sqla_column_args[-1]["primary_key"] = v elif k in ("protocol_attrs", "prot_attrs", "pa"): setattr(Attributes, "prot_attrs", _decode_pa_dict(v)) elif k in ("foreign_key", "fk"): from sqlalchemy.schema import ForeignKey t, d = Attributes.sqla_column_args fkt = (ForeignKey(v),) Attributes.sqla_column_args = (t + fkt, d) elif k in ("autoincrement", "onupdate", "server_default"): Attributes.sqla_column_args[-1][k] = v elif k == "values_dict": assert not "values" in v, "`values` and `values_dict` can't be" "specified at the same time" Attributes.values = v.keys() Attributes.values_dict = v elif k == "max_occurs" and v in ("unbounded", "inf", float("inf")): setattr(Attributes, k, Decimal("inf")) else: setattr(Attributes, k, v) return (cls.__name__, (cls,), cls_dict)
def process_complex_type(self, c): def process_type(tn, name, wrapper=None, element=None, attribute=None): if wrapper is None: wrapper = lambda x: x else: assert issubclass(wrapper, XmlModifier), wrapper t = self.get_type(tn) key = (c.name, name) if t is None: self.pending_types[key] = c self.debug2("not found: %r(%s)", key, tn) return if key in self.pending_types: del self.pending_types[key] assert name is not None, (key, e) kwargs = {} if element is not None: if e.min_occurs != "0": # spyne default kwargs['min_occurs'] = int(e.min_occurs) if e.max_occurs == "unbounded": kwargs['max_occurs'] = e.max_occurs elif e.max_occurs != "1": kwargs['max_occurs'] = int(e.max_occurs) if e.nillable != True: # spyne default kwargs['nillable'] = e.nillable if e.default is not None: kwargs['default'] = _prot.from_string(t, e.default) if len(kwargs) > 0: t = t.customize(**kwargs) if attribute is not None: if attribute.default is not None: kwargs['default'] = _prot.from_string(t, a.default) if len(kwargs) > 0: t = t.customize(**kwargs) ti.append((name, wrapper(t))) self.debug2(" found: %r(%s), c: %r", key, tn, kwargs) def process_element(e): if e.ref is not None: tn = e.ref name = e.ref.split(":", 1)[-1] elif e.name is not None: tn = e.type name = e.name if tn is None: # According to http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-element # this means this element is now considered to be a # http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#ur-type-itself self.debug2(" skipped: %s ur-type", e.name) return else: raise Exception("dunno") process_type(tn, name, element=e) ti = [] base = ComplexModelBase if c.name in self.retval[self.tns].types: self.debug1("modifying existing %r", c.name) else: self.debug1("adding complex type: %s", c.name) if c.sequence is not None: if c.sequence.elements is not None: for e in c.sequence.elements: process_element(e) if c.sequence.choices is not None: for ch in c.sequence.choices: if ch.elements is not None: for e in ch.elements: process_element(e) if c.choice is not None: if c.choice.elements is not None: for e in c.choice.elements: process_element(e) if c.attributes is not None: for a in c.attributes: if a.name is None: continue if a.type is None: continue process_type(a.type, a.name, XmlAttribute, attribute=a) if c.simple_content is not None: sc = c.simple_content ext = sc.extension restr = sc.restriction if ext is not None: base_name = ext.base b = self.get_type(ext.base) if ext.attributes is not None: for a in ext.attributes: ti.append(self.process_attribute(a)) elif restr is not None: base_name = restr.base b = self.get_type(restr.base) if restr.attributes is not None: for a in restr.attributes: ti.append(self.process_attribute(a)) else: raise Exception("Invalid simpleContent tag: %r", sc) if issubclass(b, ComplexModelBase): base = b else: process_type(base_name, "_data", XmlData) if c.name in self.retval[self.tns].types: r = self.retval[self.tns].types[c.name] r._type_info.update(ti) else: cls_dict = odict({ '__type_name__': c.name, '__namespace__': self.tns, '_type_info': ti, }) if self.repr is not None: cls_dict['__repr__'] = self.repr r = ComplexModelMeta(str(c.name), (base, ), cls_dict) self.retval[self.tns].types[c.name] = r return r
def process_complex_type(self, c): def process_type(tn, name, wrapper=lambda x: x, element=None, attribute=None): t = self.get_type(tn) key = (c.name, name) if t is None: self.pending_types[key] = c self.debug2("not found: %r(%s)", key, tn) return if key in self.pending_types: del self.pending_types[key] assert name is not None, (key, e) kwargs = {} if element is not None: if e.min_occurs != "0": # spyne default kwargs['min_occurs'] = int(e.min_occurs) if e.max_occurs == "unbounded": kwargs['max_occurs'] = e.max_occurs elif e.max_occurs != "1": kwargs['max_occurs'] = int(e.max_occurs) if e.nillable != True: # spyne default kwargs['nillable'] = e.nillable if e.default is not None: kwargs['default'] = _prot.from_string(t, e.default) if len(kwargs) > 0: t = t.customize(**kwargs) if attribute is not None: if attribute.default is not None: kwargs['default'] = _prot.from_string(t, a.default) if len(kwargs) > 0: t = t.customize(**kwargs) ti.append( (name, wrapper(t)) ) self.debug2(" found: %r(%s), c: %r", key, tn, kwargs) def process_element(e): if e.ref is not None: tn = e.ref name = e.ref.split(":", 1)[-1] elif e.name is not None: tn = e.type name = e.name else: raise Exception("dunno") process_type(tn, name, element=e) class L(list): def append(self, a): k, v = a assert isinstance(k, six.string_types), k super(L, self).append(a) ti = L() base = ComplexModelBase if c.name in self.retval[self.tns].types: self.debug1("modifying existing %r", c.name) else: self.debug1("adding complex type: %s", c.name) if c.sequence is not None: if c.sequence.elements is not None: for e in c.sequence.elements: process_element(e) if c.sequence.choices is not None: for ch in c.sequence.choices: if ch.elements is not None: for e in ch.elements: process_element(e) if c.choice is not None: if c.choice.elements is not None: for e in c.choice.elements: process_element(e) if c.attributes is not None: for a in c.attributes: if a.name is None: continue if a.type is None: continue process_type(a.type, a.name, XmlAttribute, attribute=a) if c.simple_content is not None: ext = c.simple_content.extension base_name = None if ext is not None: base_name = ext.base b = self.get_type(ext.base) if ext.attributes is not None: for a in ext.attributes: ti.append(self.process_attribute(a)) restr = c.simple_content.restriction if restr is not None: base_name = restr.base b = self.get_type(restr.base) if restr.attributes is not None: for a in restr.attributes: ti.append(self.process_attribute(a)) if issubclass(b, ComplexModelBase): base = b else: process_type(base_name, "_data", XmlData) if c.name in self.retval[self.tns].types: self.retval[self.tns].types[c.name]._type_info.update(ti) else: cls_dict = odict({ '__type_name__': c.name, '__namespace__': self.tns, '_type_info': ti, }) if self.repr is not None: cls_dict['__repr__'] = self.repr r = ComplexModelMeta(str(c.name), (base,), cls_dict) self.retval[self.tns].types[c.name] = r
def _s_customize(cls, **kwargs): """This function duplicates and customizes the class it belongs to. The original class remains unchanged. Not meant to be overridden. """ cls_dict = odict({'__module__': cls.__module__, '__doc__': cls.__doc__}) if getattr(cls, '__orig__', None) is None: cls_dict['__orig__'] = cls class Attributes(cls.Attributes): pass if cls.Attributes.translations is None: Attributes.translations = {} if cls.Attributes.sqla_column_args is None: Attributes.sqla_column_args = (), {} cls_dict['Attributes'] = Attributes # properties get reset everytime a new class is defined. So we need # to reinitialize them explicitly. for k in ('nillable', '_xml_cloth', '_xml_root_cloth', '_html_cloth', '_html_root_cloth'): v = getattr(cls.Attributes, k) if v is not None: setattr(Attributes, k, v) class Annotations(cls.Annotations): pass cls_dict['Annotations'] = Annotations # get protocol attrs prot = kwargs.get('protocol', None) if prot is None: prot = kwargs.get('prot', None) if prot is None: prot = kwargs.get('p', None) if prot is not None and len(prot.type_attrs) > 0: # if there is a class customization from protocol, do it type_attrs = prot.type_attrs.copy() type_attrs.update(kwargs) logger.debug("%r: kwargs %r => %r from prot typeattr %r", cls, kwargs, type_attrs, prot.type_attrs) kwargs = type_attrs for k, v in kwargs.items(): if k.startswith('_'): continue if k in ('protocol', 'prot', 'p'): setattr(Attributes, 'prot', v) if k in ("doc", "appinfo"): setattr(Annotations, k, v) elif k in ('primary_key', 'pk'): setattr(Attributes, 'primary_key', v) Attributes.sqla_column_args[-1]['primary_key'] = v elif k in ('protocol_attrs', 'prot_attrs', 'pa'): setattr(Attributes, 'prot_attrs', _decode_pa_dict(v)) elif k in ('foreign_key', 'fk'): from sqlalchemy.schema import ForeignKey t, d = Attributes.sqla_column_args fkt = (ForeignKey(v),) Attributes.sqla_column_args = (t + fkt, d) elif k in ('autoincrement', 'onupdate', 'server_default'): Attributes.sqla_column_args[-1][k] = v elif k == 'values_dict': assert not 'values' in v, "`values` and `values_dict` can't be" \ "specified at the same time" Attributes.values = v.keys() Attributes.values_dict = v elif k == 'max_occurs' and v in ('unbounded', 'inf', float('inf')): setattr(Attributes, k, Decimal('inf')) else: setattr(Attributes, k, v) return (cls.__name__, (cls,), cls_dict)
def parse_schema(self, elt): self.nsmap = nsmap = elt.nsmap self.prefmap = prefmap = dict([(v,k) for k,v in self.nsmap.items()]) self.schema = schema = _prot.from_element(self, XmlSchema10, elt) self.pending_types = {} self.pending_elements = {} self.tns = tns = schema.target_namespace if self.tns is None: self.tns = tns = '__no_ns__' if tns in self.retval: return self.retval[tns] = _Schema() self.debug0("1 %s processing includes", M(tns)) if schema.includes: for include in schema.includes: self.process_includes(include) if schema.elements: schema.elements = odict([(e.name, e) for e in schema.elements]) if schema.complex_types: schema.complex_types = odict([(c.name, c) for c in schema.complex_types]) if schema.simple_types: schema.simple_types = odict([(s.name, s) for s in schema.simple_types]) if schema.attributes: schema.attributes = odict([(a.name, a) for a in schema.attributes]) self.debug0("2 %s processing imports", R(tns)) if schema.imports: for imp in schema.imports: if not imp.namespace in self.retval: self.debug1("%s importing %s", tns, imp.namespace) file_name = self.files[imp.namespace] self.clone(2, dirname(file_name)).parse_schema_file(file_name) self.retval[tns].imports.add(imp.namespace) self.debug0("3 %s processing attributes", G(tns)) if schema.attributes: for s in schema.attributes.values(): n, t = self.process_attribute(s) self.retval[self.tns].types[n] = t self.debug0("4 %s processing simple_types", G(tns)) if schema.simple_types: for s in schema.simple_types.values(): st = self.process_simple_type(s) self.retval[self.tns].types[s.name] = st self.debug0("5 %s processing complex_types", B(tns)) if schema.complex_types: for c in schema.complex_types.values(): self.process_complex_type(c) self.debug0("6 %s processing elements", Y(tns)) if schema.elements: for e in schema.elements.values(): self.process_schema_element(e) self.process_pending() if self.parent is None: # for the top-most schema if self.children is not None: # if it uses <include> or <import> # This is needed for schemas with circular imports for c in chain([self], self.children): c.print_pending() self.debug0('') # FIXME: This has no guarantee of working yet covers all the # schema files found in the wild so far. for c in chain([self], self.children): c.process_pending() for c in chain([self], self.children): c.process_pending() self.debug0('') for c in chain([self], self.children): c.print_pending(fail=True) return self.retval
def parse_schema(self, elt): self.nsmap = nsmap = elt.nsmap self.prefmap = prefmap = dict([(v, k) for k, v in self.nsmap.items()]) self.schema = schema = _prot.from_element(self, XmlSchema10, elt) self.pending_types = {} self.pending_elements = {} self.tns = tns = schema.target_namespace if self.tns is None: self.tns = tns = '__no_ns__' if tns in self.retval: return self.retval[tns] = _Schema() self.debug0("1 %s processing includes", M(tns)) if schema.includes: for include in schema.includes: self.process_includes(include) if schema.elements: schema.elements = odict([(e.name, e) for e in schema.elements]) if schema.complex_types: schema.complex_types = odict([(c.name, c) for c in schema.complex_types]) if schema.simple_types: schema.simple_types = odict([(s.name, s) for s in schema.simple_types]) if schema.attributes: schema.attributes = odict([(a.name, a) for a in schema.attributes]) self.debug0("2 %s processing imports", R(tns)) if schema.imports: for imp in schema.imports: if not imp.namespace in self.retval: self.debug1("%s importing %s", tns, imp.namespace) file_name = self.files[imp.namespace] self.clone(2, dirname(file_name)).parse_schema_file(file_name) self.retval[tns].imports.add(imp.namespace) self.debug0("3 %s processing attributes", G(tns)) if schema.attributes: for s in schema.attributes.values(): n, t = self.process_attribute(s) self.retval[self.tns].types[n] = t self.debug0("4 %s processing simple_types", G(tns)) if schema.simple_types: for s in schema.simple_types.values(): st = self.process_simple_type(s) self.retval[self.tns].types[s.name] = st self.debug0("5 %s processing complex_types", B(tns)) if schema.complex_types: for c in schema.complex_types.values(): self.process_complex_type(c) self.debug0("6 %s processing elements", Y(tns)) if schema.elements: for e in schema.elements.values(): self.process_schema_element(e) self.process_pending() if self.parent is None: # for the top-most schema if self.children is not None: # if it uses <include> or <import> # This is needed for schemas with circular imports for c in chain([self], self.children): c.print_pending() self.debug0('') # FIXME: This has no guarantee of working yet covers all the # schema files found in the wild so far. for c in chain([self], self.children): c.process_pending() for c in chain([self], self.children): c.process_pending() self.debug0('') for c in chain([self], self.children): c.print_pending(fail=True) return self.retval
def parse_schema(ctx, elt): ctx.nsmap = nsmap = elt.nsmap ctx.prefmap = prefmap = dict([(v,k) for k,v in ctx.nsmap.items()]) ctx.schema = schema = _prot.from_element(ctx, XmlSchema10, elt) ctx.pending_types = {} ctx.pending_elements = {} ctx.tns = tns = schema.target_namespace if tns in ctx.retval: return ctx.retval[tns] = _Schema() ctx.debug0("1 %s processing includes", M(tns)) if schema.includes: for include in schema.includes: process_includes(ctx, include) if schema.elements: schema.elements = odict([(e.name, e) for e in schema.elements]) if schema.complex_types: schema.complex_types = odict([(c.name, c) for c in schema.complex_types]) if schema.simple_types: schema.simple_types = odict([(s.name, s) for s in schema.simple_types]) if schema.attributes: schema.attributes = odict([(a.name, a) for a in schema.attributes]) ctx.debug0("2 %s processing imports", R(tns)) if schema.imports: for imp in schema.imports: if not imp.namespace in ctx.retval: ctx.debug1("%s importing %s", tns, imp.namespace) file_name = ctx.files[imp.namespace] parse_schema_file(ctx.clone(2, dirname(file_name)), file_name) ctx.retval[tns].imports.add(imp.namespace) ctx.debug0("3 %s processing attributes", G(tns)) if schema.attributes: for s in schema.attributes.values(): n, t= process_attribute(ctx, s) ctx.retval[ctx.tns].types[n] = t ctx.debug0("4 %s processing simple_types", G(tns)) if schema.simple_types: for s in schema.simple_types.values(): st = process_simple_type(ctx, s) ctx.retval[ctx.tns].types[s.name] = st ctx.debug0("5 %s processing complex_types", B(tns)) if schema.complex_types: for c in schema.complex_types.values(): process_complex_type(ctx, c) ctx.debug0("6 %s processing elements", Y(tns)) if schema.elements: for e in schema.elements.values(): process_schema_element(ctx, e) process_pending(ctx) if ctx.parent is None: # for the top-most schema if ctx.children is not None: # if it uses <include> or <import> # This is needed for schemas with circular imports for c in chain([ctx], ctx.children): print_pending(c) ctx.debug0('') for c in chain([ctx], ctx.children): process_pending(c) for c in chain([ctx], ctx.children): process_pending(c) ctx.debug0('') for c in chain([ctx], ctx.children): print_pending(c, fail=True) return ctx.retval
def _s_customize(cls, **kwargs): """This function duplicates and customizes the class it belongs to. The original class remains unchanged. Not meant to be overridden. """ def _log_debug(s, *args): logger.debug("\t%s: %s" % (cls.get_type_name(), s), *args) cls_dict = odict({'__module__': cls.__module__, '__doc__': cls.__doc__}) if getattr(cls, '__orig__', None) is None: cls_dict['__orig__'] = cls else: cls_dict['__orig__'] = cls.__orig__ class Attributes(cls.Attributes): _explicit_type_name = False if cls.Attributes.translations is None: Attributes.translations = {} if cls.Attributes.sqla_column_args is None: Attributes.sqla_column_args = (), {} else: Attributes.sqla_column_args = deepcopy( cls.Attributes.sqla_column_args) cls_dict['Attributes'] = Attributes # properties get reset every time a new class is defined. So we need # to reinitialize them explicitly. for k in ('nillable', '_xml_cloth', '_xml_root_cloth', '_html_cloth', '_html_root_cloth'): v = getattr(cls.Attributes, k) if v is not None: setattr(Attributes, k, v) class Annotations(cls.Annotations): pass cls_dict['Annotations'] = Annotations # get protocol attrs prot = kwargs.get('protocol', None) if prot is None: prot = kwargs.get('prot', None) if prot is None: prot = kwargs.get('p', None) if prot is not None and len(prot.type_attrs) > 0: # if there is a class customization from protocol, do it type_attrs = prot.type_attrs.copy() type_attrs.update(kwargs) _log_debug("kwargs %r => %r from prot typeattr %r", kwargs, type_attrs, prot.type_attrs) kwargs = type_attrs for k, v in kwargs.items(): if k.startswith('_'): _log_debug("ignoring '%s' because of leading underscore", k) continue if k in ('protocol', 'prot', 'p'): Attributes.prot = v _log_debug("setting prot=%r", v) elif k in ('voa', 'validate_on_assignment'): Attributes.validate_on_assignment = v _log_debug("setting voa=%r", v) elif k in ('parser', 'cast'): setattr(Attributes, k, staticmethod(v)) _log_debug("setting %s=%r", k, v) elif k in ("doc", "appinfo"): setattr(Annotations, k, v) _log_debug("setting Annotations.%s=%r", k, v) elif k in ('primary_key', 'pk'): setattr(Attributes, 'primary_key', v) Attributes.sqla_column_args[-1]['primary_key'] = v _log_debug("setting primary_key=%r", v) elif k in ('protocol_attrs', 'prot_attrs', 'pa'): setattr(Attributes, 'prot_attrs', _decode_pa_dict(v)) _log_debug("setting prot_attrs=%r", v) elif k in ('foreign_key', 'fk'): from sqlalchemy.schema import ForeignKey t, d = Attributes.sqla_column_args fkt = (ForeignKey(v),) new_v = (t + fkt, d) Attributes.sqla_column_args = new_v _log_debug("setting sqla_column_args=%r", new_v) elif k in ('autoincrement', 'onupdate', 'server_default'): Attributes.sqla_column_args[-1][k] = v _log_debug("adding %s=%r to Attributes.sqla_column_args", k, v) elif k == 'values_dict': assert not 'values' in v, "`values` and `values_dict` can't be" \ "specified at the same time" if not isinstance(v, dict): # our odict has one nasty implicit behaviour: setitem on # int keys is treated as array indexes, not dict keys. so # dicts with int indexes can't work with odict. so we use # the one from stdlib v = OrderedDict(v) Attributes.values = v.keys() Attributes.values_dict = v _log_debug("setting values=%r, values_dict=%r", Attributes.values, Attributes.values_dict) elif k == 'exc_table': Attributes.exc_table = v Attributes.exc_db = v _log_debug("setting exc_table=%r, exc_db=%r", v, v) elif k == 'max_occurs' and v in ('unbounded', 'inf', float('inf')): new_v = decimal.Decimal('inf') setattr(Attributes, k, new_v) _log_debug("setting max_occurs=%r", new_v) elif k == 'type_name': Attributes._explicit_type_name = True _log_debug("setting _explicit_type_name=True because " "we have 'type_name'") else: setattr(Attributes, k, v) _log_debug("setting %s=%r", k, v) return (cls.__name__, (cls,), cls_dict)
def __prepare__(mcs, name, bases, **kwds): return odict((("__class__", mcs),))
def process_complex_type(self, c): def process_type(tn, name, wrapper=None, element=None, attribute=None): if wrapper is None: wrapper = lambda x: x else: assert issubclass(wrapper, XmlModifier), wrapper t = self.get_type(tn) key = (c.name, name) if t is None: self.pending_types[key] = c self.debug2("not found: %r(%s)", key, tn) return if key in self.pending_types: del self.pending_types[key] assert name is not None, (key, e) kwargs = {} if element is not None: if e.min_occurs != "0": # spyne default kwargs['min_occurs'] = int(e.min_occurs) if e.max_occurs == "unbounded": kwargs['max_occurs'] = e.max_occurs elif e.max_occurs != "1": kwargs['max_occurs'] = int(e.max_occurs) if e.nillable != True: # spyne default kwargs['nillable'] = e.nillable if e.default is not None: kwargs['default'] = _prot.from_string(t, e.default) if len(kwargs) > 0: t = t.customize(**kwargs) if attribute is not None: if attribute.default is not None: kwargs['default'] = _prot.from_string(t, a.default) if len(kwargs) > 0: t = t.customize(**kwargs) ti.append( (name, wrapper(t)) ) self.debug2(" found: %r(%s), c: %r", key, tn, kwargs) def process_element(e): if e.ref is not None: tn = e.ref name = e.ref.split(":", 1)[-1] elif e.name is not None: tn = e.type name = e.name if tn is None: # According to http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#element-element # this means this element is now considered to be a # http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/structures.html#ur-type-itself self.debug2(" skipped: %s ur-type", e.name) return else: raise Exception("dunno") process_type(tn, name, element=e) ti = [] base = ComplexModelBase if c.name in self.retval[self.tns].types: self.debug1("modifying existing %r", c.name) else: self.debug1("adding complex type: %s", c.name) if c.sequence is not None: if c.sequence.elements is not None: for e in c.sequence.elements: process_element(e) if c.sequence.choices is not None: for ch in c.sequence.choices: if ch.elements is not None: for e in ch.elements: process_element(e) if c.choice is not None: if c.choice.elements is not None: for e in c.choice.elements: process_element(e) if c.attributes is not None: for a in c.attributes: if a.name is None: continue if a.type is None: continue process_type(a.type, a.name, XmlAttribute, attribute=a) if c.simple_content is not None: sc = c.simple_content ext = sc.extension restr = sc.restriction if ext is not None: base_name = ext.base b = self.get_type(ext.base) if ext.attributes is not None: for a in ext.attributes: ti.append(self.process_attribute(a)) elif restr is not None: base_name = restr.base b = self.get_type(restr.base) if restr.attributes is not None: for a in restr.attributes: ti.append(self.process_attribute(a)) else: raise Exception("Invalid simpleContent tag: %r", sc) if issubclass(b, ComplexModelBase): base = b else: process_type(base_name, "_data", XmlData) if c.name in self.retval[self.tns].types: r = self.retval[self.tns].types[c.name] r._type_info.update(ti) else: cls_dict = odict({ '__type_name__': c.name, '__namespace__': self.tns, '_type_info': ti, }) if self.repr is not None: cls_dict['__repr__'] = self.repr r = ComplexModelMeta(str(c.name), (base,), cls_dict) self.retval[self.tns].types[c.name] = r return r
def parse_schema(ctx, elt): ctx.nsmap = nsmap = elt.nsmap ctx.prefmap = prefmap = dict([(v,k) for k,v in ctx.nsmap.items()]) ctx.schema = schema = XmlDocument().from_element(XmlSchema, elt) ctx.pending_types = {} ctx.pending_elements = {} ctx.tns = tns = schema.target_namespace if tns in ctx.retval: return ctx.retval[tns] = _Schema() debug("%s1 %s processing includes", ctx.i0(), m(tns)) if schema.includes: for include in schema.includes: process_includes(ctx, include) if schema.elements: schema.elements = odict([(e.name, e) for e in schema.elements]) if schema.complex_types: schema.complex_types = odict([(c.name, c) for c in schema.complex_types]) if schema.simple_types: schema.simple_types = odict([(s.name, s) for s in schema.simple_types]) debug("%s2 %s processing imports", ctx.i0(), r(tns)) if schema.imports: for imp in schema.imports: if not imp.namespace in ctx.retval: debug("%s %s importing %s", ctx.i1(), tns, imp.namespace) file_name = ctx.files[imp.namespace] parse_schema_file(ctx.clone(2, dirname(file_name)), file_name) debug("%s3 %s processing simple_types", ctx.i0(), g(tns)) if schema.simple_types: for s in schema.simple_types.values(): process_simple_type(ctx, s) debug("%s4 %s processing complex_types", ctx.i0(), b(tns)) if schema.complex_types: for c in schema.complex_types.values(): process_complex_type(ctx, c) debug("%s5 %s processing elements", ctx.i0(), y(tns)) if schema.elements: for e in schema.elements.values(): process_element(ctx, e) process_pending(ctx) if ctx.parent is None: # for the top-most schema if ctx.children is not None: # # if it uses <include> or <import> # This is needed for schemas with circular imports for c in chain([ctx], ctx.children): print_pending(c) debug('') for c in chain([ctx], ctx.children): process_pending(c) for c in chain([ctx], ctx.children): process_pending(c) debug('') for c in chain([ctx], ctx.children): print_pending(c) return ctx.retval
def _s_customize(cls, **kwargs): """Sanitizes customization parameters of the class it belongs to. Doesn't perform any actual customization. """ def _log_debug(s, *args): logger.debug("\t%s: %s" % (cls.get_type_name(), s), *args) cls_dict = odict({ '__module__': cls.__module__, '__doc__': cls.__doc__ }) if getattr(cls, '__orig__', None) is None: cls_dict['__orig__'] = cls else: cls_dict['__orig__'] = cls.__orig__ class Attributes(cls.Attributes): _explicit_type_name = False if cls.Attributes.translations is None: Attributes.translations = {} if cls.Attributes.sqla_column_args is None: Attributes.sqla_column_args = (), {} else: Attributes.sqla_column_args = deepcopy( cls.Attributes.sqla_column_args) cls_dict['Attributes'] = Attributes # properties get reset every time a new class is defined. So we need # to reinitialize them explicitly. for k in ('nillable', '_xml_cloth', '_xml_root_cloth', '_html_cloth', '_html_root_cloth'): v = getattr(cls.Attributes, k) if v is not None: setattr(Attributes, k, v) class Annotations(cls.Annotations): pass cls_dict['Annotations'] = Annotations # get protocol attrs prot = kwargs.get('protocol', None) if prot is None: prot = kwargs.get('prot', None) if prot is None: prot = kwargs.get('p', None) if prot is not None and len(prot.type_attrs) > 0: # if there is a class customization from protocol, do it type_attrs = prot.type_attrs.copy() type_attrs.update(kwargs) _log_debug("kwargs %r => %r from prot typeattr %r", kwargs, type_attrs, prot.type_attrs) kwargs = type_attrs for k, v in kwargs.items(): if k.startswith('_'): _log_debug("ignoring '%s' because of leading underscore", k) continue if k in ('protocol', 'prot', 'p'): Attributes.prot = v _log_debug("setting prot=%r", v) elif k in ('voa', 'validate_on_assignment'): Attributes.validate_on_assignment = v _log_debug("setting voa=%r", v) elif k in ('parser', 'cast'): setattr(Attributes, k, staticmethod(v)) _log_debug("setting %s=%r", k, v) elif k in ('sanitize', 'sanitizer'): setattr(Attributes, 'sanitizer', staticmethod(v)) _log_debug("setting %s=%r as sanitizer=%r", k, v, v) elif k in ("doc", "appinfo"): setattr(Annotations, k, v) _log_debug("setting Annotations.%s=%r", k, v) elif k in ('primary_key', 'pk'): setattr(Attributes, 'primary_key', v) Attributes.sqla_column_args[-1]['primary_key'] = v _log_debug("setting primary_key=%r", v) elif k in ('protocol_attrs', 'prot_attrs', 'pa'): setattr(Attributes, 'prot_attrs', _decode_pa_dict(v)) _log_debug("setting prot_attrs=%r", v) elif k in ('foreign_key', 'fk'): from sqlalchemy.schema import ForeignKey t, d = Attributes.sqla_column_args fkt = (ForeignKey(v), ) new_v = (t + fkt, d) Attributes.sqla_column_args = new_v _log_debug("setting sqla_column_args=%r", new_v) elif k in ('autoincrement', 'onupdate', 'server_default'): Attributes.sqla_column_args[-1][k] = v _log_debug("adding %s=%r to Attributes.sqla_column_args", k, v) elif k == 'values_dict': assert not 'values' in v, "`values` and `values_dict` can't be" \ "specified at the same time" if not isinstance(v, dict): # our odict has one nasty implicit behaviour: setitem on # int keys is treated as array indexes, not dict keys. so # dicts with int indexes can't work with odict. so we use # the one from stdlib v = OrderedDict(v) Attributes.values = v.keys() Attributes.values_dict = v _log_debug("setting values=%r, values_dict=%r", Attributes.values, Attributes.values_dict) elif k == 'exc_table': Attributes.exc_table = v Attributes.exc_db = v _log_debug("setting exc_table=%r, exc_db=%r", v, v) elif k == 'max_occurs' and v in ('unbounded', 'inf', float('inf')): new_v = decimal.Decimal('inf') setattr(Attributes, k, new_v) _log_debug("setting max_occurs=%r", new_v) elif k == 'type_name': Attributes._explicit_type_name = True _log_debug("setting _explicit_type_name=True because " "we have 'type_name'") else: setattr(Attributes, k, v) _log_debug("setting %s=%r", k, v) return (cls.__name__, (cls, ), cls_dict)
def __init__(self): self.elements = odict() self.types = odict()