21
|
1 import warnings
|
|
2 import functools
|
|
3
|
|
4 from orpg.orpgCore import *
|
|
5
|
|
6 def deprecated(msg=None):
|
|
7 """
|
|
8 This is a decorator which can be used to mark functions
|
|
9 as deprecated. It will result in a warning being emitted
|
|
10 when the function is used.
|
|
11 """
|
|
12 def wrap(func):
|
|
13 @functools.wraps(func)
|
|
14 def new_func(*args, **kwargs):
|
|
15 out = msg
|
|
16 if not out:
|
|
17 out = "Call to deprecated function %s."
|
|
18 else:
|
|
19 out = "Call to deprecated function %s.\n" + out
|
|
20
|
|
21 warnings.warn_explicit(
|
|
22 out % (func.__name__),
|
|
23 category=DeprecationWarning,
|
|
24 filename=func.func_code.co_filename,
|
|
25 lineno=func.func_code.co_firstlineno + 1
|
|
26 )
|
|
27 return func(*args, **kwargs)
|
|
28 return new_func
|
|
29 return wrap
|
|
30
|
|
31 def pending_deprecation(msg=None):
|
|
32 """
|
|
33 This is a decorator which can be used to mark functions
|
|
34 as deprecated. It will result in a warning being emitted
|
|
35 when the function is used.
|
|
36 """
|
|
37 def wrap(func):
|
|
38 @functools.wraps(func)
|
|
39 def new_func(*args, **kwargs):
|
|
40 out = msg
|
|
41 if not out:
|
|
42 out = "%s is Pending Deprecation."
|
|
43 else:
|
|
44 out = "%s is Pending Deprecation.\n" + out
|
|
45
|
|
46 warnings.warn_explicit(
|
|
47 out % (func.__name__),
|
|
48 category=PendingDeprecationWarning,
|
|
49 filename=func.func_code.co_filename,
|
|
50 lineno=func.func_code.co_firstlineno + 1
|
|
51 )
|
|
52 return func(*args, **kwargs)
|
|
53 return new_func
|
|
54 return wrap
|
|
55
|
|
56 def synchronized(lock):
|
|
57 """
|
|
58 Synchronization decorator.
|
|
59 """
|
|
60
|
|
61 @functools.wraps(func)
|
|
62 def new_func(*args, **kwargs):
|
|
63 lock.acquire()
|
|
64 try:
|
|
65 return func(*args, **kwargs)
|
|
66 finally:
|
|
67 lock.release()
|
|
68 return new_func
|
|
69
|
|
70 class memoized(object):
|
|
71 """
|
|
72 Decorator that caches a function's return value each time it is called.
|
|
73 If called later with the same arguments, the cached value is returned, and
|
|
74 not re-evaluated.
|
|
75 """
|
|
76 def __init__(self, func):
|
|
77 self.func = func
|
|
78 self.cache = {}
|
|
79
|
|
80 def __call__(self, *args, **kwargs):
|
|
81 try:
|
|
82 return self.cache[args + kwargs.values()]
|
|
83 except KeyError:
|
|
84 self.cache[args] = value = self.func(*args, **kwargs)
|
|
85 return value
|
|
86 except TypeError:
|
|
87 # uncachable -- for instance, passing a list as an argument.
|
|
88 # Better to not cache than to blow up entirely.
|
|
89 return self.func(*args)
|
|
90 def __repr__(self):
|
|
91 """
|
|
92 Return the function's docstring.
|
|
93 """
|
|
94 return self.func.__doc__
|
|
95
|
|
96 def debugging(func):
|
|
97 """
|
|
98 Decorator to print Enter/Exit debugging info
|
|
99 """
|
|
100
|
|
101 @functools.wraps(func)
|
|
102 def new_func(*args, **kwargs):
|
|
103 from orpg_log import logger
|
|
104
|
|
105 if not ORPG_DEBUG & logger.log_level:
|
|
106 return func(*args, **kwargs)
|
|
107
|
|
108 if str(args[0].__class__).startswith('<class'):
|
|
109 cls = args[0].__class__.__name__
|
|
110 args_s = "self"
|
|
111 if len(args) > 1:
|
|
112 args_s += ', ' + ', '.join([str(attr) for attr in args[1:]])
|
|
113 kwargs_s = ""
|
|
114 for k,v in kwargs.iteritems():
|
|
115 kwargs_s += ', ' + k + '=' + str(v)
|
|
116
|
|
117 call_str = '%(cls)s->%(fnc)s(%(args)s%(kwargs)s)' % {
|
|
118 'cls':cls,
|
|
119 'fnc':func.__name__,
|
|
120 'args':args_s,
|
|
121 'kwargs':kwargs_s}
|
|
122 try:
|
|
123 logger.debug("Enter " + call_str)
|
|
124 return func(*args, **kwargs)
|
|
125 finally:
|
|
126 logger.debug("Exit " + call_str)
|
|
127 else:
|
|
128 try:
|
|
129 logger.debug("Enter " + func.__name__)
|
|
130 return func(*args, **kwargs)
|
|
131 finally:
|
|
132 logger.debug("Exit " + func.__name__)
|
|
133 return new_func
|
|
134
|
|
135 """
|
|
136 Cannot use this decorator till we stop supporting py2.5
|
|
137 as class decorators did not land till py2.6 I am just adding it here
|
|
138 So when we do we can convert all singleton classes to use it
|
|
139 """
|
|
140 def singleton(cls):
|
|
141 instances = {}
|
|
142 def getinstance():
|
|
143 if cls not in instances:
|
|
144 instances[cls] = cls()
|
|
145 return instances[cls]
|
|
146 return getinstance
|