1 | # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) |
---|
2 | # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php |
---|
3 | import re |
---|
4 | import os |
---|
5 | import sys |
---|
6 | import shlex |
---|
7 | import pkg_resources |
---|
8 | import command |
---|
9 | |
---|
10 | class ExeCommand(command.Command): |
---|
11 | |
---|
12 | parser = command.Command.standard_parser(verbose=False) |
---|
13 | summary = "Run #! executable files" |
---|
14 | description = """\ |
---|
15 | Use this at the top of files like: |
---|
16 | |
---|
17 | #!/usr/bin/env /path/to/paster exe subcommand <command options> |
---|
18 | |
---|
19 | The rest of the file will be used as a config file for the given |
---|
20 | command, if it wants a config file. |
---|
21 | |
---|
22 | You can also include an [exe] section in the file, which looks |
---|
23 | like: |
---|
24 | |
---|
25 | [exe] |
---|
26 | command = serve |
---|
27 | log_file = /path/to/log |
---|
28 | add = /path/to/other/config.ini |
---|
29 | |
---|
30 | Which translates to: |
---|
31 | |
---|
32 | paster serve --log-file=/path/to/log /path/to/other/config.ini |
---|
33 | """ |
---|
34 | |
---|
35 | hidden = True |
---|
36 | |
---|
37 | _exe_section_re = re.compile(r'^\s*\[\s*exe\s*\]\s*$') |
---|
38 | _section_re = re.compile(r'^\s*\[') |
---|
39 | |
---|
40 | def run(self, argv): |
---|
41 | if argv and argv[0] in ('-h', '--help'): |
---|
42 | print self.description |
---|
43 | return |
---|
44 | |
---|
45 | if os.environ.get('REQUEST_METHOD'): |
---|
46 | # We're probably in a CGI environment |
---|
47 | sys.stdout = sys.stderr |
---|
48 | os.environ['PASTE_DEFAULT_QUIET'] = 'true' |
---|
49 | # Maybe import cgitb or something? |
---|
50 | |
---|
51 | if '_' not in os.environ: |
---|
52 | print "Warning: this command is intended to be run with a #! like:" |
---|
53 | print " #!/usr/bin/env paster exe" |
---|
54 | print "It only works with /usr/bin/env, and only as a #! line." |
---|
55 | # Should I actually shlex.split the args? |
---|
56 | filename = argv[-1] |
---|
57 | args = argv[:-1] |
---|
58 | extra_args = [] |
---|
59 | else: |
---|
60 | filename = os.environ['_'] |
---|
61 | extra_args = argv[:] |
---|
62 | args = [] |
---|
63 | while extra_args: |
---|
64 | if extra_args[0] == filename: |
---|
65 | extra_args.pop(0) |
---|
66 | break |
---|
67 | args.append(extra_args.pop(0)) |
---|
68 | vars = {'here': os.path.dirname(filename), |
---|
69 | '__file__': filename} |
---|
70 | f = open(filename) |
---|
71 | lines = f.readlines() |
---|
72 | f.close() |
---|
73 | options = {} |
---|
74 | lineno = 1 |
---|
75 | while lines: |
---|
76 | if self._exe_section_re.search(lines[0]): |
---|
77 | lines.pop(0) |
---|
78 | break |
---|
79 | lines.pop(0) |
---|
80 | lineno += 1 |
---|
81 | pre_options = [] |
---|
82 | options = args |
---|
83 | for line in lines: |
---|
84 | lineno += 1 |
---|
85 | line = line.strip() |
---|
86 | if not line or line.startswith('#'): |
---|
87 | continue |
---|
88 | if self._section_re.search(line): |
---|
89 | break |
---|
90 | if '=' not in line: |
---|
91 | raise command.BadCommand('Missing = in %s at %s: %r' |
---|
92 | % (filename, lineno, line)) |
---|
93 | name, value = line.split('=', 1) |
---|
94 | name = name.strip() |
---|
95 | value = value.strip() |
---|
96 | if name == 'require': |
---|
97 | pkg_resources.require(value) |
---|
98 | elif name == 'command' or name == 'add': |
---|
99 | options.extend(shlex.split(value)) |
---|
100 | elif name == 'plugin': |
---|
101 | options[:0] = ['--plugin', value] |
---|
102 | else: |
---|
103 | value = value % vars |
---|
104 | options.append('--%s=%s' % (name.replace('_', '-'), value)) |
---|
105 | os.environ['PASTE_CONFIG_FILE'] = filename |
---|
106 | options.extend(extra_args) |
---|
107 | command.run(options) |
---|