1 r"""
2 A collection of utilities easing the creation of command line scripts.
3
4 cliutils is pure Python with no dependencies.
5
6 At the moment, the module provides three disparate features: Process objects, a
7 command-line argument parsing decorator, a logging decoratory factory, and a
8 decorator factory that runs functions after changing to a given directory.
9
10 Process objects
11 ===============
12 Although it isn't very difficult to execute shell commands from a Python
13 script, there are several lines of overhead in the standard pattern.
14 Process objects reduce the entire pattern to a single line. In addition,
15 they are more flexible; they may be piped into each other, just as regular
16 processes may be on the bash command line.
17
18 >>> Process("echo 'spam and eggs'")
19 spam and eggs
20 >>> s = Process("echo 'spam and eggs'").stdout
21 >>> s
22 'spam and eggs'
23 >>> p = Process("echo 'spam and eggs'") | Process("wc -w")
24 >>> p.stdout
25 '3'
26
27 For convenience, a singleton object (L{sh}) is provided that is able to
28 create process objects from given attributes.
29
30 >>> sh.echo("spam and eggs") | sh.wc("-w") | sh.cat()
31 3
32
33 Arguments passed to Process objects are split using the C{shlex} module, so
34 most simple strings will work just fine. More complex arguments should be
35 passed in as lists:
36
37 >>> sh.echo(["spam", "and", "eggs"])
38 spam and eggs
39
40 The L{cliargs} decorator
41 ========================
42 A common pattern for shell scripts is::
43
44 def main():
45 parser = make_an_option_parser()
46 parser.parse(sys.argv[1:])
47 do_some_stuff_with_options()
48
49 if __name__=="__main__":
50 main()
51
52 Creation of shell scripts using C{setuptools}' C{entry_points} results in a
53 similar pattern; a function is called with no arguments, and must do its
54 own command-line argument parsing. This makes sense in some cases, where
55 complex argument parsing is required. In simple cases, however, where
56 parsing of a few arguments or keywords is required, the L{cliargs}
57 decorator will be of use. It does a simple parse of C{sys.argv}, using a
58 parsing algorithm based on some code in C{getopt}, and calls the decorated
59 function with the results::
60
61 @cliargs
62 def myScript(anarg, anotherarg, someval="default")
63 "Usage: myscript anarg anotherarg [--someval VALUE]"
64 print anarg anotherarg someval
65
66 When that function is called as a result of a command line script, such
67 as::
68
69 $ myscript val1 val2 --someflag somevalue
70
71 L{cliargs} will parse C{sys.argv} and pass the results into myScript. If
72 improper arguments are passed such that a C{TypeError} is raised, the
73 docstring of the function will be printed; this makes that an ideal place
74 to include a usage string.
75
76 L{cliargs} is of course limited to very simple cases. More complex argument
77 parsing will require the use of the C{getopt} or C{optparse} modules.
78
79 L{log_decorator}
80 ================
81 L{log_decorator} is an almost trivially simple decorator factory. When
82 called with a file-like object, it returns a decorator that redirects
83 C{sys.stdout} to that file for the duration of the execution of the
84 decorated function.
85
86 >>> from StringIO import StringIO
87 >>> logfile = StringIO()
88 >>> logger = log_decorator(logfile)
89 >>> @logger
90 ... def func():
91 ... print "ABCDEFGHIJK"
92 ...
93 >>> func()
94 >>> logfile.seek(0)
95 >>> logfile.read().strip()
96 'ABCDEFGHIJK'
97
98 L{indir}
99 ========
100 L{indir} is a decorator factory that runs the decorated function in a given
101 directory, changing back to the original directory on completion.
102
103 """
104 __version__="0.1.1"
105 __all__=["sh", "Process", "cliargs", "log_decorator"]
106
107 from process import sh, Process
108 from decorators import cliargs, log_decorator, indir
109