diff orpg/tools/decorators.py @ 72:8bc955faf819 ornery-dev

Fixing a few mistakes from the last update. When Controls is finished I will be happy because users won't miss an file change due to these small updates.
author sirebral
date Thu, 20 Aug 2009 03:45:45 -0500
parents
children 37a11fea3304
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/orpg/tools/decorators.py	Thu Aug 20 03:45:45 2009 -0500
@@ -0,0 +1,146 @@
+import warnings
+import functools
+
+from orpg.orpgCore import *
+
+def deprecated(msg=None):
+    """
+    This is a decorator which can be used to mark functions
+    as deprecated. It will result in a warning being emitted
+    when the function is used.
+    """
+    def wrap(func):
+        @functools.wraps(func)
+        def new_func(*args, **kwargs):
+            out = msg
+            if not out:
+                out = "Call to deprecated function %s."
+            else:
+                out = "Call to deprecated function %s.\n" + out
+
+            warnings.warn_explicit(
+                out % (func.__name__),
+                category=DeprecationWarning,
+                filename=func.func_code.co_filename,
+                lineno=func.func_code.co_firstlineno + 1
+            )
+            return func(*args, **kwargs)
+        return new_func
+    return wrap
+
+def pending_deprecation(msg=None):
+    """
+    This is a decorator which can be used to mark functions
+    as deprecated. It will result in a warning being emitted
+    when the function is used.
+    """
+    def wrap(func):
+        @functools.wraps(func)
+        def new_func(*args, **kwargs):
+            out = msg
+            if not out:
+                out = "%s is Pending Deprecation."
+            else:
+                out = "%s is Pending Deprecation.\n" + out
+
+            warnings.warn_explicit(
+                out % (func.__name__),
+                category=PendingDeprecationWarning,
+                filename=func.func_code.co_filename,
+                lineno=func.func_code.co_firstlineno + 1
+            )
+            return func(*args, **kwargs)
+        return new_func
+    return wrap
+
+def synchronized(lock):
+    """
+    Synchronization decorator.
+    """
+
+    @functools.wraps(func)
+    def new_func(*args, **kwargs):
+        lock.acquire()
+        try:
+            return func(*args, **kwargs)
+        finally:
+            lock.release()
+    return new_func
+
+class memoized(object):
+    """
+    Decorator that caches a function's return value each time it is called.
+    If called later with the same arguments, the cached value is returned, and
+    not re-evaluated.
+    """
+    def __init__(self, func):
+        self.func = func
+        self.cache = {}
+
+    def __call__(self, *args, **kwargs):
+        try:
+            return self.cache[args + kwargs.values()]
+        except KeyError:
+            self.cache[args] = value = self.func(*args, **kwargs)
+            return value
+        except TypeError:
+            # uncachable -- for instance, passing a list as an argument.
+            # Better to not cache than to blow up entirely.
+            return self.func(*args)
+    def __repr__(self):
+        """
+        Return the function's docstring.
+        """
+        return self.func.__doc__
+
+def debugging(func):
+    """
+    Decorator to print Enter/Exit debugging info
+    """
+
+    @functools.wraps(func)
+    def new_func(*args, **kwargs):
+        from orpg.tools.orpg_log import logger
+
+        if not ORPG_DEBUG & logger.log_level:
+            return func(*args, **kwargs)
+
+        if str(args[0].__class__).startswith('<class'):
+            cls = args[0].__class__.__name__
+            args_s = "self"
+            if len(args) > 1:
+                args_s += ', ' + ', '.join([str(attr) for attr in args[1:]])
+            kwargs_s = ""
+            for k,v in kwargs.iteritems():
+                kwargs_s += ', ' + k + '=' + str(v)
+
+            call_str = '%(cls)s->%(fnc)s(%(args)s%(kwargs)s)' % {
+                'cls':cls,
+                'fnc':func.__name__,
+                'args':args_s,
+                'kwargs':kwargs_s}
+            try:
+                logger.debug("Enter " + call_str)
+                return func(*args, **kwargs)
+            finally:
+                logger.debug("Exit " + call_str)
+        else:
+            try:
+                logger.debug("Enter " + func.__name__)
+                return func(*args, **kwargs)
+            finally:
+                logger.debug("Exit " + func.__name__)
+    return new_func
+
+"""
+Cannot use this decorator till we stop supporting py2.5
+as class decorators did not land till py2.6 I am just adding it here
+So when we do we can convert all singleton classes to use it
+"""
+def singleton(cls):
+    instances = {}
+    def getinstance():
+        if cls not in instances:
+            instances[cls] = cls()
+        return instances[cls]
+    return getinstance