def update_typedef(self, **kwargs): r"""Update the current typedef with new values. Args: **kwargs: All keyword arguments are considered to be new type definitions. If they are a valid definition property, they will be copied to the typedef associated with the instance. Returns: dict: A dictionary of keyword arguments that were not added to the type definition. Raises: MetaschemaTypeError: If the current type does not match the type being updated to. """ types = kwargs.pop('type', []) if self.type_instances: if set(types) != set(self.type_instances.keys()): raise MetaschemaTypeError( "New types (%s) do not match old (%s)." % (set(types), set(self.type_instances.keys()))) for tcls in self.type_instances.values(): tcls.update_typedef(**copy.deepcopy(kwargs)) else: if set(types) != set(self.type_classes.keys()): raise MetaschemaTypeError( "New types (%s) do not match class's (%s)." % (set(types), set(self.type_classes.keys()))) for t, tcls in self.type_classes.items(): self.type_instances[t] = tcls(**copy.deepcopy(kwargs)) return super(MultiMetaschemaType, self).update_typedef(type=types, **kwargs)
def update_typedef(self, **kwargs): r"""Update the current typedef with new values. Args: **kwargs: All keyword arguments are considered to be new type definitions. If they are a valid definition property, they will be copied to the typedef associated with the instance. Returns: dict: A dictionary of keyword arguments that were not added to the type definition. Raises: MetaschemaTypeError: If the current type does not match the type being updated to. """ typename0 = self._typedef.get('type', None) typename1 = kwargs.get('type', None) # Check typename to make sure this is possible if typename1 and typename0 and (typename1 != typename0): raise MetaschemaTypeError( "Cannot update typedef for type '%s' to be '%s'." % (typename0, typename1)) # pragma: debug # Copy over valid properties all_keys = [k for k in kwargs.keys()] # req_keys = self.definition_schema().get('required', []) for k in all_keys: # if k in req_keys: self._typedef[k] = kwargs.pop(k) # Validate self.validate_definition(self._typedef) return kwargs
def encode(cls, instance, typedef=None): r"""Encoder for the 'subtype' scalar property.""" dtype = data2dtype(instance) out = None for k, v in _valid_types.items(): if dtype.name.startswith(v): out = k break if out is None: raise MetaschemaTypeError( 'Cannot find subtype string for dtype %s' % dtype) return out
def get_type_class(cls, typedef=None, obj=None): r"""Get the type class from the provided typedef. """ if (typedef is not None) and isinstance(typedef['type'], (str, bytes)): type_name = typedef['type'] else: type_name = TypeMetaschemaProperty.encode(obj) if type_name not in cls.type_classes: raise MetaschemaTypeError( "Type '%s' not in set of supported types (%s)." % (type_name, list(cls.type_classes.keys()))) return cls.type_classes[type_name]
def instance2args(cls, instance): r"""Get input arguments from a class instance. Args: instance (object): Instance of a Python class. Returns: dict: Input arguments for re-creating the instance. """ for k in cls._instance_dict_attr: if hasattr(instance, k): return getattr(instance, k) elif hasattr(instance, 'get_' + k): return getattr(instance, 'get_' + k)() elif hasattr(instance, '_' + k): return getattr(instance, '_' + k) raise MetaschemaTypeError('Could not locate dictionary of arguments.')
def encode(cls, instance, typedef=None): r"""Method to encode the property given the object. Args: instance (object): Object to get property for. typedef (object, None): Template value in type definition to use for initializing encoding some cases. Defaults to None and is ignored. Returns: object: Encoded property for instance. """ type_registry = get_registered_types() for t, cls in sorted(type_registry.items(), key=_specificity_sort_key): if (t != 'any') and cls.validate(instance): return t raise MetaschemaTypeError( "Could not encode 'type' property for Python type: %s" % type(instance))
def instance2args(cls, instance): r"""Get input arguments from a class instance. Args: instance (object): Instance of a Python class. Returns: dict: Input arguments for re-creating the instance. """ out = None for k in cls._instance_dict_attr: if out is not None: break if hasattr(instance, k): out = getattr(instance, k) elif hasattr(instance, 'get_' + k): out = getattr(instance, 'get_' + k)() elif hasattr(instance, '_' + k): out = getattr(instance, '_' + k) if isinstance(out, (list, tuple)): out_real = [] for x in out: if isinstance(x, weakref.ReferenceType): out_real.append(x()) else: out_real.append(x) return out_real elif isinstance(out, dict): out_real = {} for k, v in out.items(): if isinstance(v, weakref.ReferenceType): out_real[k] = v() else: out_real[k] = v return out_real else: raise MetaschemaTypeError( 'Could not locate dictionary of arguments.')
def encode_type(cls, obj, typedef=None, is_validated=False, **kwargs): r"""Encode an object's type definition. Args: obj (object): Object to encode. typedef (dict, optional): Type properties that should be used to initialize the encoded type definition in certain cases. Defaults to None and is ignored. **kwargs: Additional keyword arguments are treated as additional schema properties. Raises: MetaschemaTypeError: If the object is not the correct type. Returns: dict: Encoded type definition. """ obj = cls.coerce_type(obj, typedef=typedef) if typedef is None: typedef = {} if not is_validated: if not cls.validate(obj): raise MetaschemaTypeError(("Object could not be encoded as " "'%s' type.") % cls.name) out = copy.deepcopy(kwargs) for x in cls.properties: itypedef = typedef.get(x, out.get(x, None)) if x == 'type': out['type'] = cls.name elif x == 'title': if itypedef is not None: out[x] = itypedef else: prop_cls = get_metaschema_property(x) out[x] = prop_cls.encode(obj, typedef=itypedef) return out