1 import sys
2 __all__ = ["cliargs", "logged", "log_decorator"]
5 """
6 Simple meta-decorator that makes decorators preserve the attributes of the
7 modified function.
8
9 Stolen from innumerable online recipes, but most directly from
10 U{http://wiki.python.org/moin/PythonDecoratorLibrary}.
11 """
12 def inner(f):
13 dec = callable(f)
14 dec.__name__ = f.__name__
15 dec.__doc__ = f.__doc__
16 dec.__module__ = f.__module__
17 dec.__dict__.update(f.__dict__)
18 return dec
19 inner.__name__ = callable.__name__
20 inner.__module__ = callable.__module__
21 inner.__doc__ = callable.__doc__
22 inner.__dict__.update(callable.__dict__)
23 return inner
24
25 @decorator
26 -def cliargs(callable):
27 """
28 Decorator that parses C{sys.argv} and passes the results into the function.
29
30 Meant for functions that are a target of setuptools' automatic script
31 creation (by default, nothing is passed in, and the function must handle
32 sys.argv parsing itself). If something very simple is all that is required,
33 this is the answer. Fancier arguments should use C{getopt} or C{optparse}.
34
35 If the wrong args/kwargs are passed in such that a TypeError is raised, the
36 docstring is printed, so that's an ideal place to put usage information.
37 """
38 def inner():
39 args = sys.argv[1:]
40 opts = {}
41 prog_args = []
42 while args:
43 if args[0].startswith('-'):
44 if args[1].startswith('-'):
45 opts[args[0].lstrip('-')] = True
46 args = args[1:]
47 else:
48 opts[args[0].lstrip('-')] = args[1]
49 args = args[2:]
50 else:
51 prog_args.append(args[0])
52 args = args[1:]
53 try: return callable(*prog_args, **opts)
54 except TypeError: print callable.__doc__
55 return inner
56
58 """
59 Factory for a decorator that redirects sys.stdout to a given file-like
60 object during function execution. Thus, C{print} statements can become
61 logged statements.
62 """
63 @decorator
64 def logdecorator(callable):
65 def inner(*args, **kwargs):
66 stdout_backup = sys.stdout
67 sys.stdout = fobj
68 result = callable(*args, **kwargs)
69 sys.stdout = stdout_backup
70 return result
71 return inner
72 return logdecorator
73
75 """
76 Create a L{logged} decorator for re-use.
77
78 >>> from StringIO import StringIO
79 >>> logfile = StringIO()
80 >>> logger = log_decorator(logfile)
81 >>> @logger
82 ... def func():
83 ... print "ABCDEFGHIJK"
84 ...
85 >>> func()
86 >>> logfile.seek(0)
87 >>> logfile.read().strip()
88 'ABCDEFGHIJK'
89
90 """
91 return logged(fobj)
92