import logging import inspect import json import time logger = logging.getLogger(__name__) class Message(object): """ Message generic class """ def __init__(self, timestamp=None, *args, **kwargs): self.timestamp = timestamp or time.time() def __str__(self): """ Overrides the str() operator and converts the message into a UTF-8 JSON string """ return json.dumps({ attr: getattr(self, attr) for attr in self.__dir__() if (attr != '_timestamp' or not attr.startswith('_')) and not inspect.ismethod(getattr(self, attr)) }).replace('\n', ' ') def __bytes__(self): """ Overrides the bytes() operator, converts the message into its JSON-serialized UTF-8-encoded representation """ return str(self).encode('utf-8') @classmethod def parse(cls, msg): """ Parse a generic message into a key-value dictionary Params: msg -- Original message - can be a dictionary, a Message, or a string/bytearray, as long as it's valid UTF-8 JSON """ if isinstance(msg, cls): msg = str(msg) if isinstance(msg, bytes) or isinstance(msg, bytearray): msg = msg.decode('utf-8') if isinstance(msg, str): # noinspection PyBroadException try: msg = json.loads(msg.strip()) except: logger.warning('Invalid JSON message: {}'.format(msg)) assert isinstance(msg, dict) if '_timestamp' not in msg: msg['_timestamp'] = time.time() return msg @classmethod def build(cls, msg): """ Builds a Message object from a dictionary. Params: msg -- The message as a key-value dictionary, Message object or JSON string """ from platypush.utils import get_message_class_by_type msg = cls.parse(msg) msgtype = get_message_class_by_type(msg['type']) if msgtype != cls: return msgtype.build(msg) class Mapping(dict): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def __setitem__(self, key, item): self.__dict__[key] = item def __getitem__(self, key): return self.__dict__[key] def __repr__(self): return repr(self.__dict__) def __len__(self): return len(self.__dict__) def __delitem__(self, key): del self.__dict__[key] def clear(self): return self.__dict__.clear() def copy(self): return self.__dict__.copy() def has_key(self, k): return k in self.__dict__ def update(self, *args, **kwargs): return self.__dict__.update(*args, **kwargs) def keys(self): return self.__dict__.keys() def values(self): return self.__dict__.values() def items(self): return self.__dict__.items() def pop(self, *args): return self.__dict__.pop(*args) def __cmp__(self, dict_): return self.__cmp__(dict_) def __contains__(self, item): return item in self.__dict__ def __iter__(self): return iter(self.__dict__) def __str__(self): return str(self.__dict__) # vim:sw=4:ts=4:et: