gcloud 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data.tar.gz.sig +2 -3
  2. data/CHANGELOG +4 -0
  3. data/LICENSE +674 -0
  4. data/Manifest +111 -0
  5. data/README.md +4 -3
  6. data/bin/gcutil +53 -0
  7. data/gcloud.gemspec +4 -3
  8. data/packages/gcutil-1.7.1/CHANGELOG +197 -0
  9. data/packages/gcutil-1.7.1/LICENSE +202 -0
  10. data/packages/gcutil-1.7.1/VERSION +1 -0
  11. data/packages/gcutil-1.7.1/gcutil +53 -0
  12. data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
  13. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
  14. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
  15. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
  16. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
  17. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
  18. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
  19. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
  20. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
  21. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
  22. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
  23. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
  24. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
  25. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
  26. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
  27. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
  28. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
  29. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
  30. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
  31. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
  32. data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
  33. data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
  34. data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
  35. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
  36. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
  37. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
  38. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
  39. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
  40. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
  41. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
  42. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
  43. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
  44. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
  45. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
  46. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
  47. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
  48. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
  49. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
  50. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
  51. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
  52. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
  53. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
  54. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
  55. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
  56. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
  57. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
  58. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
  59. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
  60. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
  61. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
  62. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
  63. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
  64. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
  65. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
  66. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
  67. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
  68. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
  69. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
  70. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
  71. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
  72. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
  73. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
  74. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
  75. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
  76. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
  77. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
  78. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
  79. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
  80. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
  81. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
  82. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
  83. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
  84. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
  85. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
  86. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
  87. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
  88. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
  89. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
  90. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
  91. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
  92. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
  93. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
  94. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
  95. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
  96. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
  97. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
  98. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
  99. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
  100. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
  101. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
  102. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
  103. data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
  104. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
  105. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
  106. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
  107. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
  108. data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
  109. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
  110. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
  111. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
  112. data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
  113. data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
  114. data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
  115. data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
  116. data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
  117. metadata +118 -5
  118. metadata.gz.sig +0 -0
@@ -0,0 +1,544 @@
1
+ #!/usr/bin/env python
2
+
3
+ # Copyright (c) 2006, Google Inc.
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are
8
+ # met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ # * Redistributions in binary form must reproduce the above
13
+ # copyright notice, this list of conditions and the following disclaimer
14
+ # in the documentation and/or other materials provided with the
15
+ # distribution.
16
+ # * Neither the name of Google Inc. nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
32
+
33
+ """gflags2man runs a Google flags base program and generates a man page.
34
+
35
+ Run the program, parse the output, and then format that into a man
36
+ page.
37
+
38
+ Usage:
39
+ gflags2man <program> [program] ...
40
+ """
41
+
42
+ # TODO(user): work with windows paths (\) as well as unix (/)
43
+
44
+ # This may seem a bit of an end run, but it: doesn't bloat flags, can
45
+ # support python/java/C++, supports older executables, and can be
46
+ # extended to other document formats.
47
+ # Inspired by help2man.
48
+
49
+
50
+
51
+ import os
52
+ import re
53
+ import sys
54
+ import stat
55
+ import time
56
+
57
+ import gflags
58
+
59
+ _VERSION = '0.1'
60
+
61
+
62
+ def _GetDefaultDestDir():
63
+ home = os.environ.get('HOME', '')
64
+ homeman = os.path.join(home, 'man', 'man1')
65
+ if home and os.path.exists(homeman):
66
+ return homeman
67
+ else:
68
+ return os.environ.get('TMPDIR', '/tmp')
69
+
70
+ FLAGS = gflags.FLAGS
71
+ gflags.DEFINE_string('dest_dir', _GetDefaultDestDir(),
72
+ 'Directory to write resulting manpage to.'
73
+ ' Specify \'-\' for stdout')
74
+ gflags.DEFINE_string('help_flag', '--help',
75
+ 'Option to pass to target program in to get help')
76
+ gflags.DEFINE_integer('v', 0, 'verbosity level to use for output')
77
+
78
+
79
+ _MIN_VALID_USAGE_MSG = 9 # if fewer lines than this, help is suspect
80
+
81
+
82
+ class Logging:
83
+ """A super-simple logging class"""
84
+ def error(self, msg): print >>sys.stderr, "ERROR: ", msg
85
+ def warn(self, msg): print >>sys.stderr, "WARNING: ", msg
86
+ def info(self, msg): print msg
87
+ def debug(self, msg): self.vlog(1, msg)
88
+ def vlog(self, level, msg):
89
+ if FLAGS.v >= level: print msg
90
+ logging = Logging()
91
+ class App:
92
+ def usage(self, shorthelp=0):
93
+ print >>sys.stderr, __doc__
94
+ print >>sys.stderr, "flags:"
95
+ print >>sys.stderr, str(FLAGS)
96
+ def run(self):
97
+ main(sys.argv)
98
+ app = App()
99
+
100
+
101
+ def GetRealPath(filename):
102
+ """Given an executable filename, find in the PATH or find absolute path.
103
+ Args:
104
+ filename An executable filename (string)
105
+ Returns:
106
+ Absolute version of filename.
107
+ None if filename could not be found locally, absolutely, or in PATH
108
+ """
109
+ if os.path.isabs(filename): # already absolute
110
+ return filename
111
+
112
+ if filename.startswith('./') or filename.startswith('../'): # relative
113
+ return os.path.abspath(filename)
114
+
115
+ path = os.getenv('PATH', '')
116
+ for directory in path.split(':'):
117
+ tryname = os.path.join(directory, filename)
118
+ if os.path.exists(tryname):
119
+ if not os.path.isabs(directory): # relative directory
120
+ return os.path.abspath(tryname)
121
+ return tryname
122
+ if os.path.exists(filename):
123
+ return os.path.abspath(filename)
124
+ return None # could not determine
125
+
126
+ class Flag(object):
127
+ """The information about a single flag."""
128
+
129
+ def __init__(self, flag_desc, help):
130
+ """Create the flag object.
131
+ Args:
132
+ flag_desc The command line forms this could take. (string)
133
+ help The help text (string)
134
+ """
135
+ self.desc = flag_desc # the command line forms
136
+ self.help = help # the help text
137
+ self.default = '' # default value
138
+ self.tips = '' # parsing/syntax tips
139
+
140
+
141
+ class ProgramInfo(object):
142
+ """All the information gleaned from running a program with --help."""
143
+
144
+ # Match a module block start, for python scripts --help
145
+ # "goopy.logging:"
146
+ module_py_re = re.compile(r'(\S.+):$')
147
+ # match the start of a flag listing
148
+ # " -v,--verbosity: Logging verbosity"
149
+ flag_py_re = re.compile(r'\s+(-\S+):\s+(.*)$')
150
+ # " (default: '0')"
151
+ flag_default_py_re = re.compile(r'\s+\(default:\s+\'(.*)\'\)$')
152
+ # " (an integer)"
153
+ flag_tips_py_re = re.compile(r'\s+\((.*)\)$')
154
+
155
+ # Match a module block start, for c++ programs --help
156
+ # "google/base/commandlineflags":
157
+ module_c_re = re.compile(r'\s+Flags from (\S.+):$')
158
+ # match the start of a flag listing
159
+ # " -v,--verbosity: Logging verbosity"
160
+ flag_c_re = re.compile(r'\s+(-\S+)\s+(.*)$')
161
+
162
+ # Match a module block start, for java programs --help
163
+ # "com.google.common.flags"
164
+ module_java_re = re.compile(r'\s+Flags for (\S.+):$')
165
+ # match the start of a flag listing
166
+ # " -v,--verbosity: Logging verbosity"
167
+ flag_java_re = re.compile(r'\s+(-\S+)\s+(.*)$')
168
+
169
+ def __init__(self, executable):
170
+ """Create object with executable.
171
+ Args:
172
+ executable Program to execute (string)
173
+ """
174
+ self.long_name = executable
175
+ self.name = os.path.basename(executable) # name
176
+ # Get name without extension (PAR files)
177
+ (self.short_name, self.ext) = os.path.splitext(self.name)
178
+ self.executable = GetRealPath(executable) # name of the program
179
+ self.output = [] # output from the program. List of lines.
180
+ self.desc = [] # top level description. List of lines
181
+ self.modules = {} # { section_name(string), [ flags ] }
182
+ self.module_list = [] # list of module names in their original order
183
+ self.date = time.localtime(time.time()) # default date info
184
+
185
+ def Run(self):
186
+ """Run it and collect output.
187
+
188
+ Returns:
189
+ 1 (true) If everything went well.
190
+ 0 (false) If there were problems.
191
+ """
192
+ if not self.executable:
193
+ logging.error('Could not locate "%s"' % self.long_name)
194
+ return 0
195
+
196
+ finfo = os.stat(self.executable)
197
+ self.date = time.localtime(finfo[stat.ST_MTIME])
198
+
199
+ logging.info('Running: %s %s </dev/null 2>&1'
200
+ % (self.executable, FLAGS.help_flag))
201
+ # --help output is often routed to stderr, so we combine with stdout.
202
+ # Re-direct stdin to /dev/null to encourage programs that
203
+ # don't understand --help to exit.
204
+ (child_stdin, child_stdout_and_stderr) = os.popen4(
205
+ [self.executable, FLAGS.help_flag])
206
+ child_stdin.close() # '</dev/null'
207
+ self.output = child_stdout_and_stderr.readlines()
208
+ child_stdout_and_stderr.close()
209
+ if len(self.output) < _MIN_VALID_USAGE_MSG:
210
+ logging.error('Error: "%s %s" returned only %d lines: %s'
211
+ % (self.name, FLAGS.help_flag,
212
+ len(self.output), self.output))
213
+ return 0
214
+ return 1
215
+
216
+ def Parse(self):
217
+ """Parse program output."""
218
+ (start_line, lang) = self.ParseDesc()
219
+ if start_line < 0:
220
+ return
221
+ if 'python' == lang:
222
+ self.ParsePythonFlags(start_line)
223
+ elif 'c' == lang:
224
+ self.ParseCFlags(start_line)
225
+ elif 'java' == lang:
226
+ self.ParseJavaFlags(start_line)
227
+
228
+ def ParseDesc(self, start_line=0):
229
+ """Parse the initial description.
230
+
231
+ This could be Python or C++.
232
+
233
+ Returns:
234
+ (start_line, lang_type)
235
+ start_line Line to start parsing flags on (int)
236
+ lang_type Either 'python' or 'c'
237
+ (-1, '') if the flags start could not be found
238
+ """
239
+ exec_mod_start = self.executable + ':'
240
+
241
+ after_blank = 0
242
+ start_line = 0 # ignore the passed-in arg for now (?)
243
+ for start_line in range(start_line, len(self.output)): # collect top description
244
+ line = self.output[start_line].rstrip()
245
+ # Python flags start with 'flags:\n'
246
+ if ('flags:' == line
247
+ and len(self.output) > start_line+1
248
+ and '' == self.output[start_line+1].rstrip()):
249
+ start_line += 2
250
+ logging.debug('Flags start (python): %s' % line)
251
+ return (start_line, 'python')
252
+ # SWIG flags just have the module name followed by colon.
253
+ if exec_mod_start == line:
254
+ logging.debug('Flags start (swig): %s' % line)
255
+ return (start_line, 'python')
256
+ # C++ flags begin after a blank line and with a constant string
257
+ if after_blank and line.startswith(' Flags from '):
258
+ logging.debug('Flags start (c): %s' % line)
259
+ return (start_line, 'c')
260
+ # java flags begin with a constant string
261
+ if line == 'where flags are':
262
+ logging.debug('Flags start (java): %s' % line)
263
+ start_line += 2 # skip "Standard flags:"
264
+ return (start_line, 'java')
265
+
266
+ logging.debug('Desc: %s' % line)
267
+ self.desc.append(line)
268
+ after_blank = (line == '')
269
+ else:
270
+ logging.warn('Never found the start of the flags section for "%s"!'
271
+ % self.long_name)
272
+ return (-1, '')
273
+
274
+ def ParsePythonFlags(self, start_line=0):
275
+ """Parse python/swig style flags."""
276
+ modname = None # name of current module
277
+ modlist = []
278
+ flag = None
279
+ for line_num in range(start_line, len(self.output)): # collect flags
280
+ line = self.output[line_num].rstrip()
281
+ if not line: # blank
282
+ continue
283
+
284
+ mobj = self.module_py_re.match(line)
285
+ if mobj: # start of a new module
286
+ modname = mobj.group(1)
287
+ logging.debug('Module: %s' % line)
288
+ if flag:
289
+ modlist.append(flag)
290
+ self.module_list.append(modname)
291
+ self.modules.setdefault(modname, [])
292
+ modlist = self.modules[modname]
293
+ flag = None
294
+ continue
295
+
296
+ mobj = self.flag_py_re.match(line)
297
+ if mobj: # start of a new flag
298
+ if flag:
299
+ modlist.append(flag)
300
+ logging.debug('Flag: %s' % line)
301
+ flag = Flag(mobj.group(1), mobj.group(2))
302
+ continue
303
+
304
+ if not flag: # continuation of a flag
305
+ logging.error('Flag info, but no current flag "%s"' % line)
306
+ mobj = self.flag_default_py_re.match(line)
307
+ if mobj: # (default: '...')
308
+ flag.default = mobj.group(1)
309
+ logging.debug('Fdef: %s' % line)
310
+ continue
311
+ mobj = self.flag_tips_py_re.match(line)
312
+ if mobj: # (tips)
313
+ flag.tips = mobj.group(1)
314
+ logging.debug('Ftip: %s' % line)
315
+ continue
316
+ if flag and flag.help:
317
+ flag.help += line # multiflags tack on an extra line
318
+ else:
319
+ logging.info('Extra: %s' % line)
320
+ if flag:
321
+ modlist.append(flag)
322
+
323
+ def ParseCFlags(self, start_line=0):
324
+ """Parse C style flags."""
325
+ modname = None # name of current module
326
+ modlist = []
327
+ flag = None
328
+ for line_num in range(start_line, len(self.output)): # collect flags
329
+ line = self.output[line_num].rstrip()
330
+ if not line: # blank lines terminate flags
331
+ if flag: # save last flag
332
+ modlist.append(flag)
333
+ flag = None
334
+ continue
335
+
336
+ mobj = self.module_c_re.match(line)
337
+ if mobj: # start of a new module
338
+ modname = mobj.group(1)
339
+ logging.debug('Module: %s' % line)
340
+ if flag:
341
+ modlist.append(flag)
342
+ self.module_list.append(modname)
343
+ self.modules.setdefault(modname, [])
344
+ modlist = self.modules[modname]
345
+ flag = None
346
+ continue
347
+
348
+ mobj = self.flag_c_re.match(line)
349
+ if mobj: # start of a new flag
350
+ if flag: # save last flag
351
+ modlist.append(flag)
352
+ logging.debug('Flag: %s' % line)
353
+ flag = Flag(mobj.group(1), mobj.group(2))
354
+ continue
355
+
356
+ # append to flag help. type and default are part of the main text
357
+ if flag:
358
+ flag.help += ' ' + line.strip()
359
+ else:
360
+ logging.info('Extra: %s' % line)
361
+ if flag:
362
+ modlist.append(flag)
363
+
364
+ def ParseJavaFlags(self, start_line=0):
365
+ """Parse Java style flags (com.google.common.flags)."""
366
+ # The java flags prints starts with a "Standard flags" "module"
367
+ # that doesn't follow the standard module syntax.
368
+ modname = 'Standard flags' # name of current module
369
+ self.module_list.append(modname)
370
+ self.modules.setdefault(modname, [])
371
+ modlist = self.modules[modname]
372
+ flag = None
373
+
374
+ for line_num in range(start_line, len(self.output)): # collect flags
375
+ line = self.output[line_num].rstrip()
376
+ logging.vlog(2, 'Line: "%s"' % line)
377
+ if not line: # blank lines terminate module
378
+ if flag: # save last flag
379
+ modlist.append(flag)
380
+ flag = None
381
+ continue
382
+
383
+ mobj = self.module_java_re.match(line)
384
+ if mobj: # start of a new module
385
+ modname = mobj.group(1)
386
+ logging.debug('Module: %s' % line)
387
+ if flag:
388
+ modlist.append(flag)
389
+ self.module_list.append(modname)
390
+ self.modules.setdefault(modname, [])
391
+ modlist = self.modules[modname]
392
+ flag = None
393
+ continue
394
+
395
+ mobj = self.flag_java_re.match(line)
396
+ if mobj: # start of a new flag
397
+ if flag: # save last flag
398
+ modlist.append(flag)
399
+ logging.debug('Flag: %s' % line)
400
+ flag = Flag(mobj.group(1), mobj.group(2))
401
+ continue
402
+
403
+ # append to flag help. type and default are part of the main text
404
+ if flag:
405
+ flag.help += ' ' + line.strip()
406
+ else:
407
+ logging.info('Extra: %s' % line)
408
+ if flag:
409
+ modlist.append(flag)
410
+
411
+ def Filter(self):
412
+ """Filter parsed data to create derived fields."""
413
+ if not self.desc:
414
+ self.short_desc = ''
415
+ return
416
+
417
+ for i in range(len(self.desc)): # replace full path with name
418
+ if self.desc[i].find(self.executable) >= 0:
419
+ self.desc[i] = self.desc[i].replace(self.executable, self.name)
420
+
421
+ self.short_desc = self.desc[0]
422
+ word_list = self.short_desc.split(' ')
423
+ all_names = [ self.name, self.short_name, ]
424
+ # Since the short_desc is always listed right after the name,
425
+ # trim it from the short_desc
426
+ while word_list and (word_list[0] in all_names
427
+ or word_list[0].lower() in all_names):
428
+ del word_list[0]
429
+ self.short_desc = '' # signal need to reconstruct
430
+ if not self.short_desc and word_list:
431
+ self.short_desc = ' '.join(word_list)
432
+
433
+
434
+ class GenerateDoc(object):
435
+ """Base class to output flags information."""
436
+
437
+ def __init__(self, proginfo, directory='.'):
438
+ """Create base object.
439
+ Args:
440
+ proginfo A ProgramInfo object
441
+ directory Directory to write output into
442
+ """
443
+ self.info = proginfo
444
+ self.dirname = directory
445
+
446
+ def Output(self):
447
+ """Output all sections of the page."""
448
+ self.Open()
449
+ self.Header()
450
+ self.Body()
451
+ self.Footer()
452
+
453
+ def Open(self): raise NotImplementedError # define in subclass
454
+ def Header(self): raise NotImplementedError # define in subclass
455
+ def Body(self): raise NotImplementedError # define in subclass
456
+ def Footer(self): raise NotImplementedError # define in subclass
457
+
458
+
459
+ class GenerateMan(GenerateDoc):
460
+ """Output a man page."""
461
+
462
+ def __init__(self, proginfo, directory='.'):
463
+ """Create base object.
464
+ Args:
465
+ proginfo A ProgramInfo object
466
+ directory Directory to write output into
467
+ """
468
+ GenerateDoc.__init__(self, proginfo, directory)
469
+
470
+ def Open(self):
471
+ if self.dirname == '-':
472
+ logging.info('Writing to stdout')
473
+ self.fp = sys.stdout
474
+ else:
475
+ self.file_path = '%s.1' % os.path.join(self.dirname, self.info.name)
476
+ logging.info('Writing: %s' % self.file_path)
477
+ self.fp = open(self.file_path, 'w')
478
+
479
+ def Header(self):
480
+ self.fp.write(
481
+ '.\\" DO NOT MODIFY THIS FILE! It was generated by gflags2man %s\n'
482
+ % _VERSION)
483
+ self.fp.write(
484
+ '.TH %s "1" "%s" "%s" "User Commands"\n'
485
+ % (self.info.name, time.strftime('%x', self.info.date), self.info.name))
486
+ self.fp.write(
487
+ '.SH NAME\n%s \\- %s\n' % (self.info.name, self.info.short_desc))
488
+ self.fp.write(
489
+ '.SH SYNOPSIS\n.B %s\n[\\fIFLAGS\\fR]...\n' % self.info.name)
490
+
491
+ def Body(self):
492
+ self.fp.write(
493
+ '.SH DESCRIPTION\n.\\" Add any additional description here\n.PP\n')
494
+ for ln in self.info.desc:
495
+ self.fp.write('%s\n' % ln)
496
+ self.fp.write(
497
+ '.SH OPTIONS\n')
498
+ # This shows flags in the original order
499
+ for modname in self.info.module_list:
500
+ if modname.find(self.info.executable) >= 0:
501
+ mod = modname.replace(self.info.executable, self.info.name)
502
+ else:
503
+ mod = modname
504
+ self.fp.write('\n.P\n.I %s\n' % mod)
505
+ for flag in self.info.modules[modname]:
506
+ help_string = flag.help
507
+ if flag.default or flag.tips:
508
+ help_string += '\n.br\n'
509
+ if flag.default:
510
+ help_string += ' (default: \'%s\')' % flag.default
511
+ if flag.tips:
512
+ help_string += ' (%s)' % flag.tips
513
+ self.fp.write(
514
+ '.TP\n%s\n%s\n' % (flag.desc, help_string))
515
+
516
+ def Footer(self):
517
+ self.fp.write(
518
+ '.SH COPYRIGHT\nCopyright \(co %s Google.\n'
519
+ % time.strftime('%Y', self.info.date))
520
+ self.fp.write('Gflags2man created this page from "%s %s" output.\n'
521
+ % (self.info.name, FLAGS.help_flag))
522
+ self.fp.write('\nGflags2man was written by Dan Christian. '
523
+ ' Note that the date on this'
524
+ ' page is the modification date of %s.\n' % self.info.name)
525
+
526
+
527
+ def main(argv):
528
+ argv = FLAGS(argv) # handles help as well
529
+ if len(argv) <= 1:
530
+ app.usage(shorthelp=1)
531
+ return 1
532
+
533
+ for arg in argv[1:]:
534
+ prog = ProgramInfo(arg)
535
+ if not prog.Run():
536
+ continue
537
+ prog.Parse()
538
+ prog.Filter()
539
+ doc = GenerateMan(prog, FLAGS.dest_dir)
540
+ doc.Output()
541
+ return 0
542
+
543
+ if __name__ == '__main__':
544
+ app.run()