googlecloud 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +4 -0
- data/LICENSE +674 -0
- data/Manifest +111 -0
- data/README.md +4 -3
- data/bin/gcutil +53 -0
- data/googlecloud.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,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
|