| 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) |
|---|