gcloud 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +2 -3
- data/CHANGELOG +4 -0
- data/LICENSE +674 -0
- data/Manifest +111 -0
- data/README.md +4 -3
- data/bin/gcutil +53 -0
- data/gcloud.gemspec +4 -3
- data/packages/gcutil-1.7.1/CHANGELOG +197 -0
- data/packages/gcutil-1.7.1/LICENSE +202 -0
- data/packages/gcutil-1.7.1/VERSION +1 -0
- data/packages/gcutil-1.7.1/gcutil +53 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
- data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
- data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
- data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
- data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
- data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
- data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
- data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
- data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
- metadata +118 -5
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright 2007 Google Inc. All Rights Reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""Simple file system utilities."""
|
|
17
|
+
|
|
18
|
+
__author__ = ('elaforge@google.com (Evan LaForge)',
|
|
19
|
+
'matthewb@google.com (Matthew Blecker)')
|
|
20
|
+
|
|
21
|
+
import errno
|
|
22
|
+
import os
|
|
23
|
+
import pwd
|
|
24
|
+
import shutil
|
|
25
|
+
import stat
|
|
26
|
+
import tempfile
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PasswdError(Exception):
|
|
30
|
+
"""Exception class for errors loading a password from a file."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def ListDirPath(dir_name):
|
|
34
|
+
"""Like os.listdir with prepended dir_name, which is often more convenient."""
|
|
35
|
+
return [os.path.join(dir_name, fn) for fn in os.listdir(dir_name)]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def Read(filename):
|
|
39
|
+
"""Read entire contents of file with name 'filename'."""
|
|
40
|
+
fp = open(filename)
|
|
41
|
+
try:
|
|
42
|
+
return fp.read()
|
|
43
|
+
finally:
|
|
44
|
+
fp.close()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def Write(filename, contents, overwrite_existing=True, mode=0666):
|
|
48
|
+
"""Create a file 'filename' with 'contents', with the mode given in 'mode'.
|
|
49
|
+
|
|
50
|
+
The 'mode' is modified by the umask, as in open(2). If
|
|
51
|
+
'overwrite_existing' is False, the file will be opened in O_EXCL mode.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
filename: str; the name of the file
|
|
55
|
+
contents: str; the data to write to the file
|
|
56
|
+
overwrite_existing: bool; whether or not to allow the write if the file
|
|
57
|
+
already exists
|
|
58
|
+
mode: int; permissions with which to create the file (default is 0666 octal)
|
|
59
|
+
"""
|
|
60
|
+
flags = os.O_WRONLY | os.O_TRUNC | os.O_CREAT
|
|
61
|
+
if not overwrite_existing:
|
|
62
|
+
flags |= os.O_EXCL
|
|
63
|
+
fd = os.open(filename, flags, mode)
|
|
64
|
+
try:
|
|
65
|
+
os.write(fd, contents)
|
|
66
|
+
finally:
|
|
67
|
+
os.close(fd)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def AtomicWrite(filename, contents, mode=0666):
|
|
71
|
+
"""Create a file 'filename' with 'contents' atomically.
|
|
72
|
+
|
|
73
|
+
As in Write, 'mode' is modified by the umask. This creates and moves
|
|
74
|
+
a temporary file, and errors doing the above will be propagated normally,
|
|
75
|
+
though it will try to clean up the temporary file in that case.
|
|
76
|
+
|
|
77
|
+
This is very similar to the prodlib function with the same name.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
filename: str; the name of the file
|
|
81
|
+
contents: str; the data to write to the file
|
|
82
|
+
mode: int; permissions with which to create the file (default is 0666 octal)
|
|
83
|
+
"""
|
|
84
|
+
(fd, tmp_filename) = tempfile.mkstemp(dir=os.path.dirname(filename))
|
|
85
|
+
try:
|
|
86
|
+
os.write(fd, contents)
|
|
87
|
+
finally:
|
|
88
|
+
os.close(fd)
|
|
89
|
+
try:
|
|
90
|
+
os.chmod(tmp_filename, mode)
|
|
91
|
+
os.rename(tmp_filename, filename)
|
|
92
|
+
except OSError, exc:
|
|
93
|
+
try:
|
|
94
|
+
os.remove(tmp_filename)
|
|
95
|
+
except OSError, e:
|
|
96
|
+
exc = OSError('%s. Additional errors cleaning up: %s' % (exc, e))
|
|
97
|
+
raise exc
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def MkDirs(directory, force_mode=None):
|
|
101
|
+
"""Makes a directory including its parent directories.
|
|
102
|
+
|
|
103
|
+
This function is equivalent to os.makedirs() but it avoids a race
|
|
104
|
+
condition that os.makedirs() has. The race is between os.mkdir() and
|
|
105
|
+
os.path.exists() which fail with errors when run in parallel.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
directory: str; the directory to make
|
|
109
|
+
force_mode: optional octal, chmod dir to get rid of umask interaction
|
|
110
|
+
Raises:
|
|
111
|
+
Whatever os.mkdir() raises when it fails for any reason EXCLUDING
|
|
112
|
+
"dir already exists". If a directory already exists, it does not
|
|
113
|
+
raise anything. This behaviour is different than os.makedirs()
|
|
114
|
+
"""
|
|
115
|
+
name = os.path.normpath(directory)
|
|
116
|
+
dirs = name.split(os.path.sep)
|
|
117
|
+
for i in range(0, len(dirs)):
|
|
118
|
+
path = os.path.sep.join(dirs[:i+1])
|
|
119
|
+
try:
|
|
120
|
+
if path:
|
|
121
|
+
os.mkdir(path)
|
|
122
|
+
# only chmod if we created
|
|
123
|
+
if force_mode is not None:
|
|
124
|
+
os.chmod(path, force_mode)
|
|
125
|
+
except OSError, exc:
|
|
126
|
+
if not (exc.errno == errno.EEXIST and os.path.isdir(path)):
|
|
127
|
+
raise
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def RmDirs(dir_name):
|
|
131
|
+
"""Removes dir_name and every non-empty directory in dir_name.
|
|
132
|
+
|
|
133
|
+
Unlike os.removedirs and shutil.rmtree, this function doesn't raise an error
|
|
134
|
+
if the directory does not exist.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
dir_name: Directory to be removed.
|
|
138
|
+
"""
|
|
139
|
+
try:
|
|
140
|
+
shutil.rmtree(dir_name)
|
|
141
|
+
except OSError, err:
|
|
142
|
+
if err.errno != errno.ENOENT:
|
|
143
|
+
raise
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
parent_directory = os.path.dirname(dir_name)
|
|
147
|
+
while parent_directory:
|
|
148
|
+
try:
|
|
149
|
+
os.rmdir(parent_directory)
|
|
150
|
+
except OSError, err:
|
|
151
|
+
if err.errno != errno.ENOENT:
|
|
152
|
+
raise
|
|
153
|
+
|
|
154
|
+
parent_directory = os.path.dirname(parent_directory)
|
|
155
|
+
except OSError, err:
|
|
156
|
+
if err.errno not in (errno.EACCES, errno.ENOTEMPTY):
|
|
157
|
+
raise
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def HomeDir(user=None):
|
|
161
|
+
"""Find the home directory of a user.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
user: int, str, or None - the uid or login of the user to query for,
|
|
165
|
+
or None (the default) to query for the current process' effective user
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
str - the user's home directory
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
TypeError: if user is not int, str, or None.
|
|
172
|
+
"""
|
|
173
|
+
if user is None:
|
|
174
|
+
pw_struct = pwd.getpwuid(os.geteuid())
|
|
175
|
+
elif isinstance(user, int):
|
|
176
|
+
pw_struct = pwd.getpwuid(user)
|
|
177
|
+
elif isinstance(user, str):
|
|
178
|
+
pw_struct = pwd.getpwnam(user)
|
|
179
|
+
else:
|
|
180
|
+
raise TypeError('user must be None or an instance of int or str')
|
|
181
|
+
return pw_struct.pw_dir
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright 2010 Google Inc. All Rights Reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""Wrapper around setuptools' pkg_resources with more Google-like names.
|
|
17
|
+
|
|
18
|
+
This module is not very useful on its own, but many Google open-source projects
|
|
19
|
+
are used to a different naming scheme, and this module makes the transition
|
|
20
|
+
easier.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
__author__ = 'dborowitz@google.com (Dave Borowitz)'
|
|
24
|
+
|
|
25
|
+
import atexit
|
|
26
|
+
|
|
27
|
+
import pkg_resources
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _Call(func, name):
|
|
31
|
+
"""Call a pkg_resources function.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
func: A function from pkg_resources that takes the arguments
|
|
35
|
+
(package_or_requirement, resource_name); for more info,
|
|
36
|
+
see http://peak.telecommunity.com/DevCenter/PkgResources
|
|
37
|
+
name: A name of the form 'module.name:path/to/resource'; this should
|
|
38
|
+
generally be built from __name__ in the calling module.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
The result of calling the function on the split resource name.
|
|
42
|
+
"""
|
|
43
|
+
pkg_name, resource_name = name.split(':', 1)
|
|
44
|
+
return func(pkg_name, resource_name)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def GetResource(name):
|
|
48
|
+
"""Get a resource as a string; see _Call."""
|
|
49
|
+
return _Call(pkg_resources.resource_string, name)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def GetResourceAsFile(name):
|
|
53
|
+
"""Get a resource as a file-like object; see _Call."""
|
|
54
|
+
return _Call(pkg_resources.resource_stream, name)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
_extracted_files = False
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def GetResourceFilename(name):
|
|
61
|
+
"""Get a filename for a resource; see _Call."""
|
|
62
|
+
global _extracted_files # pylint: disable-msg=W0603
|
|
63
|
+
if not _extracted_files:
|
|
64
|
+
atexit.register(pkg_resources.cleanup_resources)
|
|
65
|
+
_extracted_files = True
|
|
66
|
+
|
|
67
|
+
return _Call(pkg_resources.resource_filename, name)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright 2010 Google Inc. All Rights Reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS-IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""Script for running Google-style applications.
|
|
17
|
+
|
|
18
|
+
Unlike normal scripts run through setuptools console_script entry points,
|
|
19
|
+
Google-style applications must be run as top-level scripts.
|
|
20
|
+
|
|
21
|
+
Given an already-imported module, users can use the RunScriptModule function to
|
|
22
|
+
set up the appropriate executable environment to spawn a new Python process to
|
|
23
|
+
run the module as a script.
|
|
24
|
+
|
|
25
|
+
To use this technique in your project, first create a module called e.g.
|
|
26
|
+
stubs.py with contents like:
|
|
27
|
+
|
|
28
|
+
from google.apputils import run_script_module
|
|
29
|
+
|
|
30
|
+
def RunMyScript():
|
|
31
|
+
import my.script
|
|
32
|
+
run_script_module.RunScriptModule(my.script)
|
|
33
|
+
|
|
34
|
+
def RunMyOtherScript():
|
|
35
|
+
import my.other_script
|
|
36
|
+
run_script_module.RunScriptModule(my.other_script)
|
|
37
|
+
|
|
38
|
+
Then, set up entry points in your setup.py that point to the functions in your
|
|
39
|
+
stubs module:
|
|
40
|
+
|
|
41
|
+
setup(
|
|
42
|
+
...
|
|
43
|
+
entry_points = {
|
|
44
|
+
'console_scripts': [
|
|
45
|
+
'my_script = my.stubs:RunMyScript',
|
|
46
|
+
'my_other_script = my.stubs.RunMyOtherScript',
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
When your project is installed, setuptools will generate minimal wrapper scripts
|
|
52
|
+
to call your stub functions, which in turn execv your script modules. That's it!
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
__author__ = 'dborowitz@google.com (Dave Borowitz)'
|
|
56
|
+
|
|
57
|
+
import os
|
|
58
|
+
import re
|
|
59
|
+
import sys
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def FindEnv(progname):
|
|
63
|
+
"""Find the program in the system path.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
progname: The name of the program.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The full pathname of the program.
|
|
70
|
+
|
|
71
|
+
Raises:
|
|
72
|
+
AssertionError: if the program was not found.
|
|
73
|
+
"""
|
|
74
|
+
for path in os.environ['PATH'].split(':'):
|
|
75
|
+
fullname = os.path.join(path, progname)
|
|
76
|
+
if os.access(fullname, os.X_OK):
|
|
77
|
+
return fullname
|
|
78
|
+
raise AssertionError(
|
|
79
|
+
"Could not find an executable named '%s' in the system path" % progname)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def GetPdbArgs(python):
|
|
83
|
+
"""Try to get the path to pdb.py and return it in a list.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
python: The full path to a Python executable.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
A list of strings. If a relevant pdb.py was found, this will be
|
|
90
|
+
['/path/to/pdb.py']; if not, return ['-m', 'pdb'] and hope for the best.
|
|
91
|
+
(This latter technique will fail for Python 2.2.)
|
|
92
|
+
"""
|
|
93
|
+
# Usually, python is /usr/bin/pythonxx and pdb is /usr/lib/pythonxx/pdb.py
|
|
94
|
+
components = python.split('/')
|
|
95
|
+
if len(components) >= 2:
|
|
96
|
+
pdb_path = '/'.join(components[0:-2] + ['lib'] +
|
|
97
|
+
components[-1:] + ['pdb.py'])
|
|
98
|
+
if os.access(pdb_path, os.R_OK):
|
|
99
|
+
return [pdb_path]
|
|
100
|
+
|
|
101
|
+
# No pdb module found in the python path, default to -m pdb
|
|
102
|
+
return ['-m', 'pdb']
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def StripDelimiters(s, beg, end):
|
|
106
|
+
if s[0] == beg:
|
|
107
|
+
assert s[-1] == end
|
|
108
|
+
return (s[1:-1], True)
|
|
109
|
+
else:
|
|
110
|
+
return (s, False)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def StripQuotes(s):
|
|
114
|
+
(s, stripped) = StripDelimiters(s, '"', '"')
|
|
115
|
+
if not stripped:
|
|
116
|
+
(s, stripped) = StripDelimiters(s, "'", "'")
|
|
117
|
+
return s
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def PrintOurUsage():
|
|
121
|
+
"""Print usage for the stub script."""
|
|
122
|
+
print 'Stub script %s (auto-generated). Options:' % sys.argv[0]
|
|
123
|
+
print ('--helpstub '
|
|
124
|
+
'Show help for stub script.')
|
|
125
|
+
print ('--debug_binary '
|
|
126
|
+
'Run python under debugger specified by --debugger.')
|
|
127
|
+
print ('--debugger=<debugger> '
|
|
128
|
+
"Debugger for --debug_binary. Default: 'gdb --args'.")
|
|
129
|
+
print ('--debug_script '
|
|
130
|
+
'Run wrapped script with python debugger module (pdb).')
|
|
131
|
+
print ('--show_command_and_exit '
|
|
132
|
+
'Print command which would be executed and exit.')
|
|
133
|
+
print ('These options must appear first in the command line, all others will '
|
|
134
|
+
'be passed to the wrapped script.')
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def RunScriptModule(module):
|
|
138
|
+
"""Run a module as a script.
|
|
139
|
+
|
|
140
|
+
Locates the module's file and runs it in the current interpreter, or
|
|
141
|
+
optionally a debugger.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
module: The module object to run.
|
|
145
|
+
"""
|
|
146
|
+
args = sys.argv[1:]
|
|
147
|
+
|
|
148
|
+
debug_binary = False
|
|
149
|
+
debugger = 'gdb --args'
|
|
150
|
+
debug_script = False
|
|
151
|
+
show_command_and_exit = False
|
|
152
|
+
|
|
153
|
+
while args:
|
|
154
|
+
if args[0] == '--helpstub':
|
|
155
|
+
PrintOurUsage()
|
|
156
|
+
sys.exit(0)
|
|
157
|
+
if args[0] == '--debug_binary':
|
|
158
|
+
debug_binary = True
|
|
159
|
+
args = args[1:]
|
|
160
|
+
continue
|
|
161
|
+
if args[0] == '--debug_script':
|
|
162
|
+
debug_script = True
|
|
163
|
+
args = args[1:]
|
|
164
|
+
continue
|
|
165
|
+
if args[0] == '--show_command_and_exit':
|
|
166
|
+
show_command_and_exit = True
|
|
167
|
+
args = args[1:]
|
|
168
|
+
continue
|
|
169
|
+
matchobj = re.match('--debugger=(.+)', args[0])
|
|
170
|
+
if matchobj is not None:
|
|
171
|
+
debugger = StripQuotes(matchobj.group(1))
|
|
172
|
+
args = args[1:]
|
|
173
|
+
continue
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
# Now look for my main python source file
|
|
177
|
+
# TODO(dborowitz): This will fail if the module was zipimported, which means
|
|
178
|
+
# no egg depending on this script runner can be zip_safe.
|
|
179
|
+
main_filename = module.__file__
|
|
180
|
+
assert os.path.exists(main_filename), ('Cannot exec() %r: file not found.' %
|
|
181
|
+
main_filename)
|
|
182
|
+
assert os.access(main_filename, os.R_OK), ('Cannot exec() %r: file not'
|
|
183
|
+
' readable.' % main_filename)
|
|
184
|
+
|
|
185
|
+
args = [main_filename] + args
|
|
186
|
+
|
|
187
|
+
if debug_binary:
|
|
188
|
+
debugger_args = debugger.split()
|
|
189
|
+
program = debugger_args[0]
|
|
190
|
+
# If pathname is not absolute, determine full path using PATH
|
|
191
|
+
if not os.path.isabs(program):
|
|
192
|
+
program = FindEnv(program)
|
|
193
|
+
python_path = sys.executable
|
|
194
|
+
command_vec = [python_path]
|
|
195
|
+
if debug_script:
|
|
196
|
+
command_vec.extend(GetPdbArgs(python_path))
|
|
197
|
+
args = [program] + debugger_args[1:] + command_vec + args
|
|
198
|
+
|
|
199
|
+
elif debug_script:
|
|
200
|
+
args = [sys.executable] + GetPdbArgs(program) + args
|
|
201
|
+
|
|
202
|
+
else:
|
|
203
|
+
program = sys.executable
|
|
204
|
+
args = [sys.executable] + args
|
|
205
|
+
|
|
206
|
+
if show_command_and_exit:
|
|
207
|
+
print 'program: "%s"' % program
|
|
208
|
+
print 'args:', args
|
|
209
|
+
sys.exit(0)
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
sys.stdout.flush()
|
|
213
|
+
os.execv(program, args)
|
|
214
|
+
except EnvironmentError, e:
|
|
215
|
+
if not getattr(e, 'filename', None):
|
|
216
|
+
e.filename = program # Add info to error message
|
|
217
|
+
raise
|