| 
									
										
										
										
											2010-11-08 11:40:41 +01:00
										 |  |  | '''Appy allows you to create easily complete applications in Python.''' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------------------------------------------------------ | 
					
						
							| 
									
										
										
										
											2009-10-18 14:52:27 +02:00
										 |  |  | import os.path | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-08 11:40:41 +01:00
										 |  |  | # ------------------------------------------------------------------------------ | 
					
						
							| 
									
										
										
										
											2009-10-18 14:52:27 +02:00
										 |  |  | def getPath(): return os.path.dirname(__file__) | 
					
						
							| 
									
										
										
										
											2010-02-01 11:09:26 +01:00
										 |  |  | def versionIsGreaterThanOrEquals(version): | 
					
						
							|  |  |  |     '''This method returns True if the current Appy version is greater than or
 | 
					
						
							|  |  |  |        equals p_version. p_version must have a format like "0.5.0".'''
 | 
					
						
							|  |  |  |     import appy.version | 
					
						
							|  |  |  |     if appy.version.short == 'dev': | 
					
						
							|  |  |  |         # We suppose that a developer knows what he is doing, so we return True. | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         paramVersion = [int(i) for i in version.split('.')] | 
					
						
							| 
									
										
										
										
											2010-02-04 14:41:51 +01:00
										 |  |  |         currentVersion = [int(i) for i in appy.version.short.split('.')] | 
					
						
							| 
									
										
										
										
											2010-02-01 11:09:26 +01:00
										 |  |  |         return currentVersion >= paramVersion | 
					
						
							| 
									
										
										
										
											2010-11-08 11:40:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------------------------------------------------------ | 
					
						
							|  |  |  | class Object: | 
					
						
							|  |  |  |     '''At every place we need an object, but without any requirement on its
 | 
					
						
							|  |  |  |        class (methods, attributes,...) we will use this minimalist class.'''
 | 
					
						
							|  |  |  |     def __init__(self, **fields): | 
					
						
							|  |  |  |         for k, v in fields.iteritems(): | 
					
						
							|  |  |  |             setattr(self, k, v) | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         res = u'<Object ' | 
					
						
							|  |  |  |         for attrName, attrValue in self.__dict__.iteritems(): | 
					
						
							|  |  |  |             v = attrValue | 
					
						
							|  |  |  |             if hasattr(v, '__repr__'): | 
					
						
							|  |  |  |                 v = v.__repr__() | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 res += u'%s=%s ' % (attrName, v) | 
					
						
							|  |  |  |             except UnicodeDecodeError: | 
					
						
							|  |  |  |                 res += u'%s=<encoding problem> ' % attrName | 
					
						
							|  |  |  |         res  = res.strip() + '>' | 
					
						
							|  |  |  |         return res.encode('utf-8') | 
					
						
							| 
									
										
										
										
											2014-11-20 09:47:37 +01:00
										 |  |  |     def __nonzero__(self): return bool(self.__dict__) | 
					
						
							| 
									
										
										
										
											2013-05-10 12:16:57 +02:00
										 |  |  |     def get(self, name, default=None): return getattr(self, name, default) | 
					
						
							| 
									
										
										
										
											2014-11-20 09:47:37 +01:00
										 |  |  |     def __getitem__(self, k): return getattr(self, k) | 
					
						
							| 
									
										
										
										
											2013-08-21 12:35:30 +02:00
										 |  |  |     def update(self, other): | 
					
						
							|  |  |  |         '''Includes information from p_other into p_self.''' | 
					
						
							|  |  |  |         for k, v in other.__dict__.iteritems(): | 
					
						
							|  |  |  |             setattr(self, k, v) | 
					
						
							| 
									
										
										
										
											2014-03-25 22:59:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------------------------------------------------------ | 
					
						
							|  |  |  | class Hack: | 
					
						
							|  |  |  |     '''This class proposes methods for patching some existing code with
 | 
					
						
							|  |  |  |        alternative methods.'''
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2014-05-03 15:18:41 +02:00
										 |  |  |     def patch(method, replacement, klass=None): | 
					
						
							| 
									
										
										
										
											2014-03-25 22:59:06 +01:00
										 |  |  |         '''This method replaces m_method with a p_replacement method, but
 | 
					
						
							|  |  |  |            keeps p_method on its class under name | 
					
						
							|  |  |  |            "_base_<initial_method_name>_". In the patched method, one may use | 
					
						
							| 
									
										
										
										
											2014-05-03 15:18:41 +02:00
										 |  |  |            Hack.base to call the base method. If p_method is static, you must | 
					
						
							|  |  |  |            specify its class in p_klass.'''
 | 
					
						
							| 
									
										
										
										
											2014-03-25 22:59:06 +01:00
										 |  |  |         # Get the class on which the surgery will take place. | 
					
						
							| 
									
										
										
										
											2014-05-03 15:18:41 +02:00
										 |  |  |         isStatic = klass | 
					
						
							|  |  |  |         klass = klass or method.im_class | 
					
						
							| 
									
										
										
										
											2014-03-25 22:59:06 +01:00
										 |  |  |         # On this class, store m_method under its "base" name. | 
					
						
							| 
									
										
										
										
											2014-05-03 15:18:41 +02:00
										 |  |  |         name = isStatic and method.func_name or method.im_func.__name__ | 
					
						
							| 
									
										
										
										
											2014-03-25 22:59:06 +01:00
										 |  |  |         baseName = '_base_%s_' % name | 
					
						
							|  |  |  |         setattr(klass, baseName, method) | 
					
						
							| 
									
										
										
										
											2014-05-03 15:18:41 +02:00
										 |  |  |         # Store the replacement method on klass. When doing so, even when | 
					
						
							|  |  |  |         # m_method is static, it is wrapped in a method. This is why, in | 
					
						
							|  |  |  |         # m_base below, when the method is static, we return method.im_func to | 
					
						
							|  |  |  |         # retrieve the original static method. | 
					
						
							| 
									
										
										
										
											2014-03-25 22:59:06 +01:00
										 |  |  |         setattr(klass, name, replacement) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							| 
									
										
										
										
											2014-05-03 15:18:41 +02:00
										 |  |  |     def base(method, klass=None): | 
					
						
							|  |  |  |         '''Allows to call the base (replaced) method. If p_method is static,
 | 
					
						
							|  |  |  |            you must specify its p_klass.'''
 | 
					
						
							|  |  |  |         isStatic = klass | 
					
						
							|  |  |  |         klass = klass or method.im_class | 
					
						
							|  |  |  |         name = isStatic and method.func_name or method.im_func.__name__ | 
					
						
							|  |  |  |         res = getattr(klass, '_base_%s_' % name) | 
					
						
							|  |  |  |         if isStatic: res = res.im_func | 
					
						
							|  |  |  |         return res | 
					
						
							| 
									
										
										
										
											2010-11-08 11:40:41 +01:00
										 |  |  | # ------------------------------------------------------------------------------ |