""" py lib's basic logging/tracing functionality EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL (especially the dispatching) WARNING: this module is not allowed to contain any 'py' imports, Instead, it is very self-contained and should not depend on CPython/stdlib versions, either. One reason for these restrictions is that this module should be sendable via py.execnet across the network in an very early phase. """ class Message(object): def __init__(self, keywords, args): self.keywords = keywords self.args = args def content(self): return " ".join(map(str, self.args)) def prefix(self): return "[%s] " % (":".join(self.keywords)) def __str__(self): return self.prefix() + self.content() class Producer(object): """ Log producer API which sends messages to be logged to a 'consumer' object, which then prints them to stdout, stderr, files, etc. """ Message = Message # to allow later customization keywords2consumer = {} def __init__(self, keywords): if isinstance(keywords, str): keywords = tuple(keywords.split()) self.keywords = keywords def __repr__(self): return "" % ":".join(self.keywords) def __getattr__(self, name): if '_' in name: raise AttributeError, name producer = self.__class__(self.keywords + (name,)) setattr(self, name, producer) return producer def __call__(self, *args): """ write a message to the appropriate consumer(s) """ func = self.get_consumer(self.keywords) if func is not None: func(self.Message(self.keywords, args)) def get_consumer(self, keywords): """ return a consumer matching keywords tries to find the most suitable consumer by walking, starting from the back, the list of keywords, the first consumer matching a keyword is returned (falling back to py.log.default) """ for i in range(len(self.keywords), 0, -1): try: return self.keywords2consumer[self.keywords[:i]] except KeyError: continue return self.keywords2consumer.get('default', default_consumer) def set_consumer(self, consumer): """ register a consumer matching our own keywords """ self.keywords2consumer[self.keywords] = consumer default = Producer('default') def _getstate(): return Producer.keywords2consumer.copy() def _setstate(state): Producer.keywords2consumer.clear() Producer.keywords2consumer.update(state) def default_consumer(msg): """ the default consumer, prints the message to stdout (using 'print') """ print str(msg) Producer.keywords2consumer['default'] = default_consumer