googlecloud 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 +0 -0
  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/googlecloud.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,421 @@
1
+ #!/usr/bin/env python
2
+ # Copyright 2002 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
+ """Set of classes and functions for dealing with dates and timestamps.
17
+
18
+ The BaseTimestamp and Timestamp are timezone-aware wrappers around Python
19
+ datetime.datetime class.
20
+ """
21
+
22
+
23
+
24
+ import calendar
25
+ import copy
26
+ import datetime
27
+ import re
28
+ import sys
29
+ import time
30
+ import types
31
+
32
+ from dateutil import parser
33
+ import pytz
34
+
35
+
36
+ _MICROSECONDS_PER_SECOND = 1000000
37
+ _MICROSECONDS_PER_SECOND_F = float(_MICROSECONDS_PER_SECOND)
38
+
39
+
40
+ def SecondsToMicroseconds(seconds):
41
+ """Convert seconds to microseconds.
42
+
43
+ Args:
44
+ seconds: number
45
+ Returns:
46
+ microseconds
47
+ """
48
+ return seconds * _MICROSECONDS_PER_SECOND
49
+
50
+
51
+ def _GetCurrentTimeMicros():
52
+ """Get the current time in microseconds, in UTC.
53
+
54
+ Returns:
55
+ The number of microseconds since the epoch.
56
+ """
57
+ return int(SecondsToMicroseconds(time.time()))
58
+
59
+
60
+ def GetSecondsSinceEpoch(time_tuple):
61
+ """Convert time_tuple (in UTC) to seconds (also in UTC).
62
+
63
+ Args:
64
+ time_tuple: tuple with at least 6 items.
65
+ Returns:
66
+ seconds.
67
+ """
68
+ return calendar.timegm(time_tuple[:6] + (0, 0, 0))
69
+
70
+
71
+ def GetTimeMicros(time_tuple):
72
+ """Get a time in microseconds.
73
+
74
+ Arguments:
75
+ time_tuple: A (year, month, day, hour, minute, second) tuple (the python
76
+ time tuple format) in the UTC time zone.
77
+
78
+ Returns:
79
+ The number of microseconds since the epoch represented by the input tuple.
80
+ """
81
+ return int(SecondsToMicroseconds(GetSecondsSinceEpoch(time_tuple)))
82
+
83
+
84
+ UTC = pytz.UTC
85
+ US_PACIFIC = pytz.timezone('US/Pacific')
86
+
87
+
88
+ class TimestampError(ValueError):
89
+ """Generic timestamp-related error."""
90
+ pass
91
+
92
+
93
+ class TimezoneNotSpecifiedError(TimestampError):
94
+ """This error is raised when timezone is not specified."""
95
+ pass
96
+
97
+
98
+ class TimeParseError(TimestampError):
99
+ """This error is raised when we can't parse the input."""
100
+ pass
101
+
102
+
103
+ # TODO(user): this class needs to handle daylight better
104
+
105
+
106
+ class LocalTimezoneClass(datetime.tzinfo):
107
+ """This class defines local timezone."""
108
+
109
+ ZERO = datetime.timedelta(0)
110
+ HOUR = datetime.timedelta(hours=1)
111
+
112
+ STDOFFSET = datetime.timedelta(seconds=-time.timezone)
113
+ if time.daylight:
114
+ DSTOFFSET = datetime.timedelta(seconds=-time.altzone)
115
+ else:
116
+ DSTOFFSET = STDOFFSET
117
+
118
+ DSTDIFF = DSTOFFSET - STDOFFSET
119
+
120
+ def utcoffset(self, dt):
121
+ """datetime -> minutes east of UTC (negative for west of UTC)."""
122
+ if self._isdst(dt):
123
+ return self.DSTOFFSET
124
+ else:
125
+ return self.STDOFFSET
126
+
127
+ def dst(self, dt):
128
+ """datetime -> DST offset in minutes east of UTC."""
129
+ if self._isdst(dt):
130
+ return self.DSTDIFF
131
+ else:
132
+ return self.ZERO
133
+
134
+ def tzname(self, dt):
135
+ """datetime -> string name of time zone."""
136
+ return time.tzname[self._isdst(dt)]
137
+
138
+ def _isdst(self, dt):
139
+ """Return true if given datetime is within local DST."""
140
+ tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second,
141
+ dt.weekday(), 0, -1)
142
+ stamp = time.mktime(tt)
143
+ tt = time.localtime(stamp)
144
+ return tt.tm_isdst > 0
145
+
146
+ def __repr__(self):
147
+ """Return string '<Local>'."""
148
+ return '<Local>'
149
+
150
+ def localize(self, dt, unused_is_dst=False):
151
+ """Convert naive time to local time."""
152
+ if dt.tzinfo is not None:
153
+ raise ValueError('Not naive datetime (tzinfo is already set)')
154
+ return dt.replace(tzinfo=self)
155
+
156
+ def normalize(self, dt, unused_is_dst=False):
157
+ """Correct the timezone information on the given datetime."""
158
+ if dt.tzinfo is None:
159
+ raise ValueError('Naive time - no tzinfo set')
160
+ return dt.replace(tzinfo=self)
161
+
162
+
163
+ LocalTimezone = LocalTimezoneClass()
164
+
165
+
166
+ class BaseTimestamp(datetime.datetime):
167
+ """Our kind of wrapper over datetime.datetime.
168
+
169
+ The objects produced by methods now, today, fromtimestamp, utcnow,
170
+ utcfromtimestamp are timezone-aware (with correct timezone).
171
+ We also overload __add__ and __sub__ method, to fix the result of arithmetic
172
+ operations.
173
+ """
174
+
175
+ LocalTimezone = LocalTimezone
176
+
177
+ @classmethod
178
+ def AddLocalTimezone(cls, obj):
179
+ """If obj is naive, add local timezone to it."""
180
+ if not obj.tzinfo:
181
+ return obj.replace(tzinfo=cls.LocalTimezone)
182
+ return obj
183
+
184
+ @classmethod
185
+ def Localize(cls, obj):
186
+ """If obj is naive, localize it to cls.LocalTimezone."""
187
+ if not obj.tzinfo:
188
+ return cls.LocalTimezone.localize(obj)
189
+ return obj
190
+
191
+ def __add__(self, *args, **kwargs):
192
+ """x.__add__(y) <==> x+y."""
193
+ r = super(BaseTimestamp, self).__add__(*args, **kwargs)
194
+ return type(self)(r.year, r.month, r.day, r.hour, r.minute, r.second,
195
+ r.microsecond, r.tzinfo)
196
+
197
+ def __sub__(self, *args, **kwargs):
198
+ """x.__add__(y) <==> x-y."""
199
+ r = super(BaseTimestamp, self).__sub__(*args, **kwargs)
200
+ if isinstance(r, datetime.datetime):
201
+ return type(self)(r.year, r.month, r.day, r.hour, r.minute, r.second,
202
+ r.microsecond, r.tzinfo)
203
+ return r
204
+
205
+ @classmethod
206
+ def now(cls, *args, **kwargs):
207
+ """Get a timestamp corresponding to right now.
208
+
209
+ Args:
210
+ args: Positional arguments to pass to datetime.datetime.now().
211
+ kwargs: Keyword arguments to pass to datetime.datetime.now(). If tz is not
212
+ specified, local timezone is assumed.
213
+
214
+ Returns:
215
+ A new BaseTimestamp with tz's local day and time.
216
+ """
217
+ return cls.AddLocalTimezone(
218
+ super(BaseTimestamp, cls).now(*args, **kwargs))
219
+
220
+ @classmethod
221
+ def today(cls):
222
+ """Current BaseTimestamp.
223
+
224
+ Same as self.__class__.fromtimestamp(time.time()).
225
+ Returns:
226
+ New self.__class__.
227
+ """
228
+ return cls.AddLocalTimezone(super(BaseTimestamp, cls).today())
229
+
230
+ @classmethod
231
+ def fromtimestamp(cls, *args, **kwargs):
232
+ """Get a new localized timestamp from a POSIX timestamp.
233
+
234
+ Args:
235
+ args: Positional arguments to pass to datetime.datetime.fromtimestamp().
236
+ kwargs: Keyword arguments to pass to datetime.datetime.fromtimestamp().
237
+ If tz is not specified, local timezone is assumed.
238
+
239
+ Returns:
240
+ A new BaseTimestamp with tz's local day and time.
241
+ """
242
+ return cls.Localize(
243
+ super(BaseTimestamp, cls).fromtimestamp(*args, **kwargs))
244
+
245
+ @classmethod
246
+ def utcnow(cls):
247
+ """Return a new BaseTimestamp representing UTC day and time."""
248
+ return super(BaseTimestamp, cls).utcnow().replace(tzinfo=pytz.utc)
249
+
250
+ @classmethod
251
+ def utcfromtimestamp(cls, *args, **kwargs):
252
+ """timestamp -> UTC datetime from a POSIX timestamp (like time.time())."""
253
+ return super(BaseTimestamp, cls).utcfromtimestamp(
254
+ *args, **kwargs).replace(tzinfo=pytz.utc)
255
+
256
+ @classmethod
257
+ def strptime(cls, date_string, format, tz=None):
258
+ """Parse date_string according to format and construct BaseTimestamp.
259
+
260
+ Args:
261
+ date_string: string passed to time.strptime.
262
+ format: format string passed to time.strptime.
263
+ tz: if not specified, local timezone assumed.
264
+ Returns:
265
+ New BaseTimestamp.
266
+ """
267
+ if tz is None:
268
+ return cls.Localize(cls(*(time.strptime(date_string, format)[:6])))
269
+ return tz.localize(cls(*(time.strptime(date_string, format)[:6])))
270
+
271
+ def astimezone(self, *args, **kwargs):
272
+ """tz -> convert to time in new timezone tz."""
273
+ r = super(BaseTimestamp, self).astimezone(*args, **kwargs)
274
+ return type(self)(r.year, r.month, r.day, r.hour, r.minute, r.second,
275
+ r.microsecond, r.tzinfo)
276
+
277
+ @classmethod
278
+ def FromMicroTimestamp(cls, ts):
279
+ """Create new Timestamp object from microsecond UTC timestamp value.
280
+
281
+ Args:
282
+ ts: integer microsecond UTC timestamp
283
+ Returns:
284
+ New cls()
285
+ """
286
+ return cls.utcfromtimestamp(ts/_MICROSECONDS_PER_SECOND_F)
287
+
288
+ def AsSecondsSinceEpoch(self):
289
+ """Return number of seconds since epoch (timestamp in seconds)."""
290
+ return GetSecondsSinceEpoch(self.utctimetuple())
291
+
292
+ def AsMicroTimestamp(self):
293
+ """Return microsecond timestamp constructed from this object."""
294
+ return (SecondsToMicroseconds(self.AsSecondsSinceEpoch()) +
295
+ self.microsecond)
296
+
297
+ @classmethod
298
+ def combine(cls, datepart, timepart, tz=None):
299
+ """Combine date and time into timestamp, timezone-aware.
300
+
301
+ Args:
302
+ datepart: datetime.date
303
+ timepart: datetime.time
304
+ tz: timezone or None
305
+ Returns:
306
+ timestamp object
307
+ """
308
+ result = super(BaseTimestamp, cls).combine(datepart, timepart)
309
+ if tz:
310
+ result = tz.localize(result)
311
+ return result
312
+
313
+
314
+ # Conversions from interval suffixes to number of seconds.
315
+ # (m => 60s, d => 86400s, etc)
316
+ _INTERVAL_CONV_DICT = {'s': 1}
317
+ _INTERVAL_CONV_DICT['m'] = 60 * _INTERVAL_CONV_DICT['s']
318
+ _INTERVAL_CONV_DICT['h'] = 60 * _INTERVAL_CONV_DICT['m']
319
+ _INTERVAL_CONV_DICT['d'] = 24 * _INTERVAL_CONV_DICT['h']
320
+ _INTERVAL_CONV_DICT['D'] = _INTERVAL_CONV_DICT['d']
321
+ _INTERVAL_CONV_DICT['w'] = 7 * _INTERVAL_CONV_DICT['d']
322
+ _INTERVAL_CONV_DICT['W'] = _INTERVAL_CONV_DICT['w']
323
+ _INTERVAL_CONV_DICT['M'] = 30 * _INTERVAL_CONV_DICT['d']
324
+ _INTERVAL_CONV_DICT['Y'] = 365 * _INTERVAL_CONV_DICT['d']
325
+ _INTERVAL_REGEXP = re.compile('^([0-9]+)([%s])?' % ''.join(_INTERVAL_CONV_DICT))
326
+
327
+
328
+ def ConvertIntervalToSeconds(interval):
329
+ """Convert a formatted string representing an interval into seconds.
330
+
331
+ Args:
332
+ interval: String to interpret as an interval. A basic interval looks like
333
+ "<number><suffix>". Complex intervals consisting of a chain of basic
334
+ intervals are also allowed.
335
+
336
+ Returns:
337
+ An integer representing the number of seconds represented by the interval
338
+ string, or None if the interval string could not be decoded.
339
+ """
340
+ total = 0
341
+ while interval:
342
+ match = _INTERVAL_REGEXP.match(interval)
343
+ if not match:
344
+ return None
345
+
346
+ try:
347
+ num = int(match.group(1))
348
+ except ValueError:
349
+ return None
350
+
351
+ suffix = match.group(2)
352
+ if suffix:
353
+ multiplier = _INTERVAL_CONV_DICT.get(suffix)
354
+ if not multiplier:
355
+ return None
356
+ num *= multiplier
357
+
358
+ total += num
359
+ interval = interval[match.end(0):]
360
+ return total
361
+
362
+
363
+ class Timestamp(BaseTimestamp):
364
+ """This subclass contains methods to parse W3C and interval date spec.
365
+
366
+ The interval date specification is in the form "1D", where "D" can be
367
+ "s"econds "m"inutes "h"ours "D"ays "W"eeks "M"onths "Y"ears.
368
+ """
369
+ INTERVAL_CONV_DICT = _INTERVAL_CONV_DICT
370
+ INTERVAL_REGEXP = _INTERVAL_REGEXP
371
+
372
+ @classmethod
373
+ def _StringToTime(cls, timestring, tz=None):
374
+ """Use dateutil.parser to convert string into timestamp.
375
+
376
+ dateutil.parser understands ISO8601 which is really handy.
377
+
378
+ Args:
379
+ timestring: string with datetime
380
+ tz: optional timezone, if timezone is omitted from timestring.
381
+ Returns:
382
+ New Timestamp.
383
+ """
384
+ r = parser.parse(timestring)
385
+ if not r.tzinfo:
386
+ r = (tz or cls.LocalTimezone).localize(r)
387
+ result = cls(r.year, r.month, r.day, r.hour, r.minute, r.second,
388
+ r.microsecond, r.tzinfo)
389
+
390
+ return result
391
+
392
+ @classmethod
393
+ def _IntStringToInterval(cls, timestring):
394
+ """Parse interval date specification and create a timedelta object."""
395
+ return datetime.timedelta(seconds=ConvertIntervalToSeconds(timestring))
396
+
397
+ @classmethod
398
+ def FromString(cls, value, tz=None):
399
+ """Try to create a Timestamp from a string."""
400
+ val = cls._StringToTime(value, tz)
401
+ if val:
402
+ return val
403
+
404
+ val = cls._IntStringToInterval(value)
405
+ if val:
406
+ return cls.utcnow() - val
407
+
408
+ raise TimeParseError(value)
409
+
410
+
411
+ # What's written below is a clear python bug. I mean, okay, I can apply
412
+ # negative timezone to it and end result will be inconversible.
413
+
414
+ MAXIMUM_PYTHON_TIMESTAMP = Timestamp(
415
+ 9999, 12, 31, 23, 59, 59, 999999, UTC)
416
+
417
+ # This is also a bug. It is called 32bit time_t. I hate it.
418
+ # This is fixed in 2.5, btw.
419
+
420
+ MAXIMUM_MICROSECOND_TIMESTAMP = 0x80000000 * _MICROSECONDS_PER_SECOND - 1
421
+ MAXIMUM_MICROSECOND_TIMESTAMP_AS_TS = Timestamp(2038, 1, 19, 3, 14, 7, 999999)
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env python
2
+ # Copyright 2004 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
+ """Import this module to add a hook to call pdb on uncaught exceptions.
17
+
18
+ To enable this, do the following in your top-level application:
19
+
20
+ import google.apputils.debug
21
+
22
+ and then in your main():
23
+
24
+ google.apputils.debug.Init()
25
+
26
+ Then run your program with --pdb.
27
+ """
28
+
29
+
30
+
31
+ import sys
32
+
33
+ import gflags as flags
34
+
35
+ flags.DEFINE_boolean('pdb', 0, 'Drop into pdb on uncaught exceptions')
36
+
37
+ old_excepthook = None
38
+
39
+
40
+ def _DebugHandler(exc_class, value, tb):
41
+ if not flags.FLAGS.pdb or hasattr(sys, 'ps1') or not sys.stderr.isatty():
42
+ # we aren't in interactive mode or we don't have a tty-like
43
+ # device, so we call the default hook
44
+ old_excepthook(exc_class, value, tb)
45
+ else:
46
+ # Don't impose import overhead on apps that never raise an exception.
47
+ import traceback
48
+ import pdb
49
+ # we are in interactive mode, print the exception...
50
+ traceback.print_exception(exc_class, value, tb)
51
+ print
52
+ # ...then start the debugger in post-mortem mode.
53
+ pdb.pm()
54
+
55
+
56
+ def Init():
57
+ # Must back up old excepthook.
58
+ global old_excepthook # pylint: disable-msg=W0603
59
+ old_excepthook = sys.excepthook
60
+ sys.excepthook = _DebugHandler