def add_type_from_schema(path_to_schema, **kwargs): r"""Add a type from a schema in a file. Args: path_to_schema (string): Full path to the location of a schema file that can be loaded. target_globals (dict, optional): Globals dictionary for module where the fixed class should be added. If None, the new class is returned. Defaults to local globals. **kwargs: Additional keyword arguments are assumed to be attributes for the new class. """ from yggdrasil.metaschema.datatypes.FixedMetaschemaType import ( create_fixed_type_class) if 'target_globals' not in kwargs: kwargs['target_globals'] = globals() if not os.path.isfile(path_to_schema): raise ValueError("The 'path_to_schema' attribute is not a valid path: " + "'%s'" % path_to_schema) with open(path_to_schema, 'r') as fd: out = decode_json(fd) jsonschema.validate(out, {'type': 'object', 'required': ['title', 'description', 'type']}) name = out['title'] if _type_registry.has_entry(name): assert(kwargs['target_globals'] is not None) return name description = out['description'] base = get_type_class(out['type']) fixed_properties = out return create_fixed_type_class(name, description, base, fixed_properties, loaded_schema_file=path_to_schema, **kwargs)
def func_deserialize(self, msg): r"""Deserialize a message. Args: msg (str, bytes): Message to be deserialized. Returns: obj: Deserialized Python object. """ return decode_json(msg)
def get_schema(): r"""Return the Obj schema, initializing it if necessary. Returns: dict: Obj schema. """ if not os.path.isfile(_schema_file): create_schema() with open(_schema_file, 'r') as fd: out = decode_json(fd) return out
def func_deserialize(self, msg): r"""Deserialize a message. Args: msg (str, bytes): Message to be deserialized. Returns: obj: Deserialized Python object. """ out = decode_json(msg) if backwards.PY2: # pragma: Python 2 out = backwards.as_str(out, recurse=True, allow_pass=True) return out
def decode(msg): r"""Decode an object from a message. Args: msg (bytes): Bytes encoded message. Returns: object: Decoded Python object. """ cls = guess_type_from_msg(msg) metadata = decode_json(msg.split(YGG_MSG_HEAD, 2)[1]) typedef = cls.extract_typedef(metadata.get('datatype', {})) cls_inst = cls(**typedef) obj = cls_inst.deserialize(msg)[0] return obj
def guess_type_from_msg(msg): r"""Guess the type class from a message. Args: msg (str, bytes): Message containing metadata. Raises: ValueError: If a type class cannot be determined. Returns: MetaschemaType: Instance of the appropriate type class. """ try: if YGG_MSG_HEAD in msg: _, metadata, data = msg.split(YGG_MSG_HEAD, 2) metadata = decode_json(metadata) cls = _type_registry[metadata['datatype']['type']] else: raise Exception return cls except BaseException: raise ValueError("Could not guess type.")
def deserialize(self, msg, no_data=False, metadata=None, dont_decode=False, dont_check=False): r"""Deserialize a message. Args: msg (str, bytes): Message to be deserialized. no_data (bool, optional): If True, only the metadata is returned. Defaults to False. metadata (dict, optional): Metadata that should be used to deserialize the message instead of the current header content. Defaults to None and is not used. dont_decode (bool, optional): If True, type specific and JSON decoding will not be used to decode the message. Defaults to False. dont_check (bool, optional): If True, the metadata will not be checked against the type definition. Defaults to False. Returns: tuple(obj, dict): Deserialized message and header information. Raises: TypeError: If msg is not bytes type (str on Python 2). ValueError: If msg does not contain the header separator. """ if not isinstance(msg, bytes): raise TypeError("Message to be deserialized is not bytes type.") # Check for header if msg.startswith(constants.YGG_MSG_HEAD): if metadata is not None: raise ValueError("Metadata in header and provided by keyword.") _, metadata, data = msg.split(constants.YGG_MSG_HEAD, 2) if len(metadata) == 0: metadata = dict(size=len(data)) else: metadata = encoder.decode_json(metadata) elif isinstance(metadata, dict) and metadata.get( 'type_in_data', False): assert (msg.count(constants.YGG_MSG_HEAD) == 1) typedef, data = msg.split(constants.YGG_MSG_HEAD, 1) if len(typedef) > 0: metadata.update(encoder.decode_json(typedef)) metadata.pop('type_in_data') metadata['size'] = len(data) else: data = msg if metadata is None: metadata = dict(size=len(msg)) if (((len(msg) > 0) and (msg != constants.YGG_MSG_EOF) and (not is_default_typedef(self._typedef)) and (not dont_decode))): raise ValueError("Header marker not in message.") # Set flags based on data metadata['incomplete'] = (len(data) < metadata['size']) if (data == constants.YGG_MSG_EOF): metadata['raw'] = True # Return based on flags if no_data: return metadata elif len(data) == 0: return self._empty_msg, metadata elif (metadata['incomplete'] or metadata.get('raw', False) or (metadata.get('type', None) == 'direct') or dont_decode): return data, metadata else: data = encoder.decode_json(data) obj = self.decode(metadata['datatype'], data, self._typedef, typedef_validated=True, dont_check=dont_check) return obj, metadata
import yggdrasil from yggdrasil import constants, units from yggdrasil.metaschema.encoder import encode_json, decode_json from yggdrasil.metaschema.properties import get_registered_properties from yggdrasil.metaschema.datatypes import get_registered_types _metaschema_fbase = '.ygg_metaschema.json' _metaschema_fname = os.path.abspath( os.path.join(os.path.dirname(yggdrasil.__file__), _metaschema_fbase)) _metaschema = None _validator = None _base_schema = {u'$schema': u'http://json-schema.org/draft-04/schema'} if os.path.isfile(_metaschema_fname): with open(_metaschema_fname, 'r') as fd: _metaschema = decode_json(fd) schema_id = _metaschema.get('id', _metaschema.get('$id', None)) assert (schema_id is not None) _metaschema.setdefault('$schema', schema_id) _base_schema['$schema'] = _metaschema.get('$schema', schema_id) _base_validator = jsonschema.validators.validator_for(_base_schema) class MetaschemaTypeError(TypeError): r"""Error that should be raised when a class encounters a type it cannot handle.""" pass def create_metaschema(overwrite=False): r"""Create the meta schema for validating ygg schema.