89 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
	
	
| """
 | |
| 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 "<py.log.Producer %s>" % ":".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 
 |