Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

update bundled pytz

add to requirements.txt so that pip installs use that instead
add /usr/share/lib/zoneinfo to list of system tzdata dirs
  • Loading branch information...
commit 9beda6e2a87c70dab0b29f8e64cb0f85bb6dd4f5 1 parent 9899f7e
Michael Leinartas mleinart authored
1  requirements.txt
@@ -36,5 +36,6 @@ txAMQP==0.4
36 36 simplejson==2.1.6
37 37 django-tagging==0.3.1
38 38 gunicorn
  39 +pytz
39 40 http://cairographics.org/releases/py2cairo-1.8.10.tar.gz
40 41 ./whisper
267 webapp/graphite/thirdparty/pytz/__init__.py
@@ -9,7 +9,7 @@
9 9 '''
10 10
11 11 # The Olson database is updated several times a year.
12   -OLSON_VERSION = '2010b'
  12 +OLSON_VERSION = '2011n'
13 13 VERSION = OLSON_VERSION
14 14 # Version format for a patch release - only one so far.
15 15 #VERSION = OLSON_VERSION + '.2'
@@ -26,22 +26,59 @@
26 26 ]
27 27
28 28 import sys, datetime, os.path, gettext
29   -from UserDict import DictMixin
  29 +try:
  30 + from UserDict import DictMixin
  31 +except ImportError:
  32 + from collections import Mapping as DictMixin
30 33
31 34 try:
32 35 from pkg_resources import resource_stream
33 36 except ImportError:
34 37 resource_stream = None
35 38
36   -from tzinfo import AmbiguousTimeError, InvalidTimeError, NonExistentTimeError
37   -from tzinfo import unpickler
38   -from tzfile import build_tzinfo
  39 +from pytz.exceptions import AmbiguousTimeError
  40 +from pytz.exceptions import InvalidTimeError
  41 +from pytz.exceptions import NonExistentTimeError
  42 +from pytz.exceptions import UnknownTimeZoneError
  43 +from pytz.tzinfo import unpickler
  44 +from pytz.tzfile import build_tzinfo, _byte_string
  45 +
39 46
40   -# Use 2.3 sets module implementation if set builtin is not available
41 47 try:
42   - set
43   -except NameError:
44   - from sets import Set as set
  48 + unicode
  49 +
  50 +except NameError: # Python 3.x
  51 +
  52 + # Python 3.x doesn't have unicode(), making writing code
  53 + # for Python 2.3 and Python 3.x a pain.
  54 + unicode = str
  55 +
  56 + def ascii(s):
  57 + r"""
  58 + >>> ascii('Hello')
  59 + 'Hello'
  60 + >>> ascii('\N{TRADE MARK SIGN}') #doctest: +IGNORE_EXCEPTION_DETAIL
  61 + Traceback (most recent call last):
  62 + ...
  63 + UnicodeEncodeError: ...
  64 + """
  65 + s.encode('US-ASCII') # Raise an exception if not ASCII
  66 + return s # But return the original string - not a byte string.
  67 +
  68 +else: # Python 2.x
  69 +
  70 + def ascii(s):
  71 + r"""
  72 + >>> ascii('Hello')
  73 + 'Hello'
  74 + >>> ascii(u'Hello')
  75 + 'Hello'
  76 + >>> ascii(u'\N{TRADE MARK SIGN}') #doctest: +IGNORE_EXCEPTION_DETAIL
  77 + Traceback (most recent call last):
  78 + ...
  79 + UnicodeEncodeError: ...
  80 + """
  81 + return s.encode('US-ASCII')
45 82
46 83
47 84 def open_resource(name):
@@ -50,19 +87,24 @@ def open_resource(name):
50 87 Uses the pkg_resources module if available and no standard file
51 88 found at the calculated location.
52 89 """
53   - # Patched in Debian, use the system zoninfo from the tzdata package
  90 + # Patched in Debian, use the system zoneinfo from the tzdata package
54 91 name_parts = name.lstrip('/').split('/')
55 92 for part in name_parts:
56 93 if part == os.path.pardir or os.path.sep in part:
57 94 raise ValueError('Bad path segment: %r' % part)
58   - filename = os.path.join('/usr/share/zoneinfo', *name_parts)
  95 + for possible_path in [ '/usr/share/zoneinfo', '/usr/share/lib/zoneinfo' ]:
  96 + if os.path.exists(possible_path):
  97 + tz_path = possible_path
  98 + break
  99 +
  100 + filename = os.path.join(tz_path, *name_parts)
59 101 return open(filename, 'rb')
60 102
61 103
62 104 def resource_exists(name):
63 105 """Return true if the given resource exists"""
64 106 try:
65   - open_resource(name)
  107 + open_resource(name).close()
66 108 return True
67 109 except IOError:
68 110 return False
@@ -83,22 +125,6 @@ def resource_exists(name):
83 125 # return t.ugettext(timezone_name)
84 126
85 127
86   -class UnknownTimeZoneError(KeyError):
87   - '''Exception raised when pytz is passed an unknown timezone.
88   -
89   - >>> isinstance(UnknownTimeZoneError(), LookupError)
90   - True
91   -
92   - This class is actually a subclass of KeyError to provide backwards
93   - compatibility with code relying on the undocumented behavior of earlier
94   - pytz releases.
95   -
96   - >>> isinstance(UnknownTimeZoneError(), KeyError)
97   - True
98   - '''
99   - pass
100   -
101   -
102 128 _tzinfo_cache = {}
103 129
104 130 def timezone(zone):
@@ -109,7 +135,7 @@ def timezone(zone):
109 135 >>> eastern = timezone('US/Eastern')
110 136 >>> eastern.zone
111 137 'US/Eastern'
112   - >>> timezone(u'US/Eastern') is eastern
  138 + >>> timezone(unicode('US/Eastern')) is eastern
113 139 True
114 140 >>> utc_dt = datetime(2002, 10, 27, 6, 0, 0, tzinfo=utc)
115 141 >>> loc_dt = utc_dt.astimezone(eastern)
@@ -125,21 +151,24 @@ def timezone(zone):
125 151
126 152 Raises UnknownTimeZoneError if passed an unknown zone.
127 153
128   - >>> timezone('Asia/Shangri-La')
129   - Traceback (most recent call last):
130   - ...
131   - UnknownTimeZoneError: 'Asia/Shangri-La'
  154 + >>> try:
  155 + ... timezone('Asia/Shangri-La')
  156 + ... except UnknownTimeZoneError:
  157 + ... print('Unknown')
  158 + Unknown
  159 +
  160 + >>> try:
  161 + ... timezone(unicode('\N{TRADE MARK SIGN}'))
  162 + ... except UnknownTimeZoneError:
  163 + ... print('Unknown')
  164 + Unknown
132 165
133   - >>> timezone(u'\N{TRADE MARK SIGN}')
134   - Traceback (most recent call last):
135   - ...
136   - UnknownTimeZoneError: u'\u2122'
137 166 '''
138 167 if zone.upper() == 'UTC':
139 168 return utc
140 169
141 170 try:
142   - zone = zone.encode('US-ASCII')
  171 + zone = ascii(zone)
143 172 except UnicodeEncodeError:
144 173 # All valid timezones are ASCII
145 174 raise UnknownTimeZoneError(zone)
@@ -147,7 +176,11 @@ def timezone(zone):
147 176 zone = _unmunge_zone(zone)
148 177 if zone not in _tzinfo_cache:
149 178 if zone in all_timezones_set:
150   - _tzinfo_cache[zone] = build_tzinfo(zone, open_resource(zone))
  179 + fp = open_resource(zone)
  180 + try:
  181 + _tzinfo_cache[zone] = build_tzinfo(zone, fp)
  182 + finally:
  183 + fp.close()
151 184 else:
152 185 raise UnknownTimeZoneError(zone)
153 186
@@ -175,6 +208,15 @@ class UTC(datetime.tzinfo):
175 208 """
176 209 zone = "UTC"
177 210
  211 + _utcoffset = ZERO
  212 + _dst = ZERO
  213 + _tzname = zone
  214 +
  215 + def fromutc(self, dt):
  216 + if dt.tzinfo is None:
  217 + return self.localize(dt)
  218 + return super(utc.__class__, self).fromutc(dt)
  219 +
178 220 def utcoffset(self, dt):
179 221 return ZERO
180 222
@@ -190,13 +232,13 @@ def __reduce__(self):
190 232 def localize(self, dt, is_dst=False):
191 233 '''Convert naive time to local time'''
192 234 if dt.tzinfo is not None:
193   - raise ValueError, 'Not naive datetime (tzinfo is already set)'
  235 + raise ValueError('Not naive datetime (tzinfo is already set)')
194 236 return dt.replace(tzinfo=self)
195 237
196 238 def normalize(self, dt, is_dst=False):
197 239 '''Correct the timezone information on the given datetime'''
198 240 if dt.tzinfo is None:
199   - raise ValueError, 'Naive time - no tzinfo set'
  241 + raise ValueError('Naive time - no tzinfo set')
200 242 return dt.replace(tzinfo=self)
201 243
202 244 def __repr__(self):
@@ -224,8 +266,8 @@ def _UTC():
224 266 >>> naive = dt.replace(tzinfo=None)
225 267 >>> p = pickle.dumps(dt, 1)
226 268 >>> naive_p = pickle.dumps(naive, 1)
227   - >>> len(p), len(naive_p), len(p) - len(naive_p)
228   - (60, 43, 17)
  269 + >>> len(p) - len(naive_p)
  270 + 17
229 271 >>> new = pickle.loads(p)
230 272 >>> new == dt
231 273 True
@@ -260,6 +302,21 @@ def __getitem__(self, key):
260 302 self._fill()
261 303 return self.data[key.upper()]
262 304
  305 + def __contains__(self, key):
  306 + if self.data is None:
  307 + self._fill()
  308 + return key in self.data
  309 +
  310 + def __iter__(self):
  311 + if self.data is None:
  312 + self._fill()
  313 + return iter(self.data)
  314 +
  315 + def __len__(self):
  316 + if self.data is None:
  317 + self._fill()
  318 + return len(self.data)
  319 +
263 320 def keys(self):
264 321 if self.data is None:
265 322 self._fill()
@@ -272,13 +329,21 @@ class _CountryTimezoneDict(_LazyDict):
272 329
273 330 iso3166_code is the two letter code used to identify the country.
274 331
275   - >>> country_timezones['ch']
276   - ['Europe/Zurich']
277   - >>> country_timezones['CH']
278   - ['Europe/Zurich']
279   - >>> country_timezones[u'ch']
280   - ['Europe/Zurich']
281   - >>> country_timezones['XXX']
  332 + >>> def print_list(list_of_strings):
  333 + ... 'We use a helper so doctests work under Python 2.3 -> 3.x'
  334 + ... for s in list_of_strings:
  335 + ... print(s)
  336 +
  337 + >>> print_list(country_timezones['nz'])
  338 + Pacific/Auckland
  339 + Pacific/Chatham
  340 + >>> print_list(country_timezones['ch'])
  341 + Europe/Zurich
  342 + >>> print_list(country_timezones['CH'])
  343 + Europe/Zurich
  344 + >>> print_list(country_timezones[unicode('ch')])
  345 + Europe/Zurich
  346 + >>> print_list(country_timezones['XXX'])
282 347 Traceback (most recent call last):
283 348 ...
284 349 KeyError: 'XXX'
@@ -286,8 +351,9 @@ class _CountryTimezoneDict(_LazyDict):
286 351 Previously, this information was exposed as a function rather than a
287 352 dictionary. This is still supported::
288 353
289   - >>> country_timezones('nz')
290   - ['Pacific/Auckland', 'Pacific/Chatham']
  354 + >>> print_list(country_timezones('nz'))
  355 + Pacific/Auckland
  356 + Pacific/Chatham
291 357 """
292 358 def __call__(self, iso3166_code):
293 359 """Backwards compatibility."""
@@ -296,17 +362,21 @@ def __call__(self, iso3166_code):
296 362 def _fill(self):
297 363 data = {}
298 364 zone_tab = open_resource('zone.tab')
299   - for line in zone_tab:
300   - if line.startswith('#'):
301   - continue
302   - code, coordinates, zone = line.split(None, 4)[:3]
303   - if zone not in all_timezones_set:
304   - continue
305   - try:
306   - data[code].append(zone)
307   - except KeyError:
308   - data[code] = [zone]
309   - self.data = data
  365 + try:
  366 + for line in zone_tab:
  367 + line = line.decode('US-ASCII')
  368 + if line.startswith('#'):
  369 + continue
  370 + code, coordinates, zone = line.split(None, 4)[:3]
  371 + if zone not in all_timezones_set:
  372 + continue
  373 + try:
  374 + data[code].append(zone)
  375 + except KeyError:
  376 + data[code] = [zone]
  377 + self.data = data
  378 + finally:
  379 + zone_tab.close()
310 380
311 381 country_timezones = _CountryTimezoneDict()
312 382
@@ -314,18 +384,22 @@ def _fill(self):
314 384 class _CountryNameDict(_LazyDict):
315 385 '''Dictionary proving ISO3166 code -> English name.
316 386
317   - >>> country_names['au']
318   - 'Australia'
  387 + >>> print(country_names['au'])
  388 + Australia
319 389 '''
320 390 def _fill(self):
321 391 data = {}
322 392 zone_tab = open_resource('iso3166.tab')
323   - for line in zone_tab.readlines():
324   - if line.startswith('#'):
325   - continue
326   - code, name = line.split(None, 1)
327   - data[code] = name.strip()
328   - self.data = data
  393 + try:
  394 + for line in zone_tab.readlines():
  395 + line = line.decode('US-ASCII')
  396 + if line.startswith('#'):
  397 + continue
  398 + code, name = line.split(None, 1)
  399 + data[code] = name.strip()
  400 + self.data = data
  401 + finally:
  402 + zone_tab.close()
329 403
330 404 country_names = _CountryNameDict()
331 405
@@ -349,7 +423,7 @@ def __reduce__(self):
349 423 return FixedOffset, (self._minutes, )
350 424
351 425 def dst(self, dt):
352   - return None
  426 + return ZERO
353 427
354 428 def tzname(self, dt):
355 429 return None
@@ -360,13 +434,13 @@ def __repr__(self):
360 434 def localize(self, dt, is_dst=False):
361 435 '''Convert naive time to local time'''
362 436 if dt.tzinfo is not None:
363   - raise ValueError, 'Not naive datetime (tzinfo is already set)'
  437 + raise ValueError('Not naive datetime (tzinfo is already set)')
364 438 return dt.replace(tzinfo=self)
365 439
366 440 def normalize(self, dt, is_dst=False):
367 441 '''Correct the timezone information on the given datetime'''
368 442 if dt.tzinfo is None:
369   - raise ValueError, 'Naive time - no tzinfo set'
  443 + raise ValueError('Naive time - no tzinfo set')
370 444 return dt.replace(tzinfo=self)
371 445
372 446
@@ -378,12 +452,16 @@ def FixedOffset(offset, _tzinfos = {}):
378 452 pytz.FixedOffset(-330)
379 453 >>> one.utcoffset(datetime.datetime.now())
380 454 datetime.timedelta(-1, 66600)
  455 + >>> one.dst(datetime.datetime.now())
  456 + datetime.timedelta(0)
381 457
382 458 >>> two = FixedOffset(1380)
383 459 >>> two
384 460 pytz.FixedOffset(1380)
385 461 >>> two.utcoffset(datetime.datetime.now())
386 462 datetime.timedelta(0, 82800)
  463 + >>> two.dst(datetime.datetime.now())
  464 + datetime.timedelta(0)
387 465
388 466 The datetime.timedelta must be between the range of -1 and 1 day,
389 467 non-inclusive.
@@ -471,6 +549,7 @@ def _test():
471 549 'Africa/Gaborone',
472 550 'Africa/Harare',
473 551 'Africa/Johannesburg',
  552 + 'Africa/Juba',
474 553 'Africa/Kampala',
475 554 'Africa/Khartoum',
476 555 'Africa/Kigali',
@@ -521,6 +600,7 @@ def _test():
521 600 'America/Atikokan',
522 601 'America/Atka',
523 602 'America/Bahia',
  603 + 'America/Bahia_Banderas',
524 604 'America/Barbados',
525 605 'America/Belem',
526 606 'America/Belize',
@@ -584,10 +664,12 @@ def _test():
584 664 'America/Kentucky/Louisville',
585 665 'America/Kentucky/Monticello',
586 666 'America/Knox_IN',
  667 + 'America/Kralendijk',
587 668 'America/La_Paz',
588 669 'America/Lima',
589 670 'America/Los_Angeles',
590 671 'America/Louisville',
  672 + 'America/Lower_Princes',
591 673 'America/Maceio',
592 674 'America/Managua',
593 675 'America/Manaus',
@@ -598,6 +680,7 @@ def _test():
598 680 'America/Mendoza',
599 681 'America/Menominee',
600 682 'America/Merida',
  683 + 'America/Metlakatla',
601 684 'America/Mexico_City',
602 685 'America/Miquelon',
603 686 'America/Moncton',
@@ -610,6 +693,7 @@ def _test():
610 693 'America/Nipigon',
611 694 'America/Nome',
612 695 'America/Noronha',
  696 + 'America/North_Dakota/Beulah',
613 697 'America/North_Dakota/Center',
614 698 'America/North_Dakota/New_Salem',
615 699 'America/Ojinaga',
@@ -636,6 +720,7 @@ def _test():
636 720 'America/Sao_Paulo',
637 721 'America/Scoresbysund',
638 722 'America/Shiprock',
  723 + 'America/Sitka',
639 724 'America/St_Barthelemy',
640 725 'America/St_Johns',
641 726 'America/St_Kitts',
@@ -658,6 +743,7 @@ def _test():
658 743 'Antarctica/Casey',
659 744 'Antarctica/Davis',
660 745 'Antarctica/DumontDUrville',
  746 + 'Antarctica/Macquarie',
661 747 'Antarctica/Mawson',
662 748 'Antarctica/McMurdo',
663 749 'Antarctica/Palmer',
@@ -694,6 +780,7 @@ def _test():
694 780 'Asia/Dushanbe',
695 781 'Asia/Gaza',
696 782 'Asia/Harbin',
  783 + 'Asia/Hebron',
697 784 'Asia/Ho_Chi_Minh',
698 785 'Asia/Hong_Kong',
699 786 'Asia/Hovd',
@@ -946,6 +1033,7 @@ def _test():
946 1033 'Pacific/Apia',
947 1034 'Pacific/Auckland',
948 1035 'Pacific/Chatham',
  1036 + 'Pacific/Chuuk',
949 1037 'Pacific/Easter',
950 1038 'Pacific/Efate',
951 1039 'Pacific/Enderbury',
@@ -971,6 +1059,7 @@ def _test():
971 1059 'Pacific/Pago_Pago',
972 1060 'Pacific/Palau',
973 1061 'Pacific/Pitcairn',
  1062 + 'Pacific/Pohnpei',
974 1063 'Pacific/Ponape',
975 1064 'Pacific/Port_Moresby',
976 1065 'Pacific/Rarotonga',
@@ -1038,6 +1127,7 @@ def _test():
1038 1127 'Africa/Gaborone',
1039 1128 'Africa/Harare',
1040 1129 'Africa/Johannesburg',
  1130 + 'Africa/Juba',
1041 1131 'Africa/Kampala',
1042 1132 'Africa/Khartoum',
1043 1133 'Africa/Kigali',
@@ -1085,6 +1175,7 @@ def _test():
1085 1175 'America/Asuncion',
1086 1176 'America/Atikokan',
1087 1177 'America/Bahia',
  1178 + 'America/Bahia_Banderas',
1088 1179 'America/Barbados',
1089 1180 'America/Belem',
1090 1181 'America/Belize',
@@ -1139,17 +1230,21 @@ def _test():
1139 1230 'America/Juneau',
1140 1231 'America/Kentucky/Louisville',
1141 1232 'America/Kentucky/Monticello',
  1233 + 'America/Kralendijk',
1142 1234 'America/La_Paz',
1143 1235 'America/Lima',
1144 1236 'America/Los_Angeles',
  1237 + 'America/Lower_Princes',
1145 1238 'America/Maceio',
1146 1239 'America/Managua',
1147 1240 'America/Manaus',
  1241 + 'America/Marigot',
1148 1242 'America/Martinique',
1149 1243 'America/Matamoros',
1150 1244 'America/Mazatlan',
1151 1245 'America/Menominee',
1152 1246 'America/Merida',
  1247 + 'America/Metlakatla',
1153 1248 'America/Mexico_City',
1154 1249 'America/Miquelon',
1155 1250 'America/Moncton',
@@ -1162,6 +1257,7 @@ def _test():
1162 1257 'America/Nipigon',
1163 1258 'America/Nome',
1164 1259 'America/Noronha',
  1260 + 'America/North_Dakota/Beulah',
1165 1261 'America/North_Dakota/Center',
1166 1262 'America/North_Dakota/New_Salem',
1167 1263 'America/Ojinaga',
@@ -1185,6 +1281,9 @@ def _test():
1185 1281 'America/Santo_Domingo',
1186 1282 'America/Sao_Paulo',
1187 1283 'America/Scoresbysund',
  1284 + 'America/Shiprock',
  1285 + 'America/Sitka',
  1286 + 'America/St_Barthelemy',
1188 1287 'America/St_Johns',
1189 1288 'America/St_Kitts',
1190 1289 'America/St_Lucia',
@@ -1205,12 +1304,15 @@ def _test():
1205 1304 'Antarctica/Casey',
1206 1305 'Antarctica/Davis',
1207 1306 'Antarctica/DumontDUrville',
  1307 + 'Antarctica/Macquarie',
1208 1308 'Antarctica/Mawson',
1209 1309 'Antarctica/McMurdo',
1210 1310 'Antarctica/Palmer',
1211 1311 'Antarctica/Rothera',
  1312 + 'Antarctica/South_Pole',
1212 1313 'Antarctica/Syowa',
1213 1314 'Antarctica/Vostok',
  1315 + 'Arctic/Longyearbyen',
1214 1316 'Asia/Aden',
1215 1317 'Asia/Almaty',
1216 1318 'Asia/Amman',
@@ -1235,6 +1337,7 @@ def _test():
1235 1337 'Asia/Dushanbe',
1236 1338 'Asia/Gaza',
1237 1339 'Asia/Harbin',
  1340 + 'Asia/Hebron',
1238 1341 'Asia/Ho_Chi_Minh',
1239 1342 'Asia/Hong_Kong',
1240 1343 'Asia/Hovd',
@@ -1320,6 +1423,7 @@ def _test():
1320 1423 'Europe/Athens',
1321 1424 'Europe/Belgrade',
1322 1425 'Europe/Berlin',
  1426 + 'Europe/Bratislava',
1323 1427 'Europe/Brussels',
1324 1428 'Europe/Bucharest',
1325 1429 'Europe/Budapest',
@@ -1327,35 +1431,46 @@ def _test():
1327 1431 'Europe/Copenhagen',
1328 1432 'Europe/Dublin',
1329 1433 'Europe/Gibraltar',
  1434 + 'Europe/Guernsey',
1330 1435 'Europe/Helsinki',
  1436 + 'Europe/Isle_of_Man',
1331 1437 'Europe/Istanbul',
  1438 + 'Europe/Jersey',
1332 1439 'Europe/Kaliningrad',
1333 1440 'Europe/Kiev',
1334 1441 'Europe/Lisbon',
  1442 + 'Europe/Ljubljana',
1335 1443 'Europe/London',
1336 1444 'Europe/Luxembourg',
1337 1445 'Europe/Madrid',
1338 1446 'Europe/Malta',
  1447 + 'Europe/Mariehamn',
1339 1448 'Europe/Minsk',
1340 1449 'Europe/Monaco',
1341 1450 'Europe/Moscow',
1342 1451 'Europe/Oslo',
1343 1452 'Europe/Paris',
  1453 + 'Europe/Podgorica',
1344 1454 'Europe/Prague',
1345 1455 'Europe/Riga',
1346 1456 'Europe/Rome',
1347 1457 'Europe/Samara',
  1458 + 'Europe/San_Marino',
  1459 + 'Europe/Sarajevo',
1348 1460 'Europe/Simferopol',
  1461 + 'Europe/Skopje',
1349 1462 'Europe/Sofia',
1350 1463 'Europe/Stockholm',
1351 1464 'Europe/Tallinn',
1352 1465 'Europe/Tirane',
1353 1466 'Europe/Uzhgorod',
1354 1467 'Europe/Vaduz',
  1468 + 'Europe/Vatican',
1355 1469 'Europe/Vienna',
1356 1470 'Europe/Vilnius',
1357 1471 'Europe/Volgograd',
1358 1472 'Europe/Warsaw',
  1473 + 'Europe/Zagreb',
1359 1474 'Europe/Zaporozhye',
1360 1475 'Europe/Zurich',
1361 1476 'GMT',
@@ -1373,6 +1488,7 @@ def _test():
1373 1488 'Pacific/Apia',
1374 1489 'Pacific/Auckland',
1375 1490 'Pacific/Chatham',
  1491 + 'Pacific/Chuuk',
1376 1492 'Pacific/Easter',
1377 1493 'Pacific/Efate',
1378 1494 'Pacific/Enderbury',
@@ -1398,14 +1514,13 @@ def _test():
1398 1514 'Pacific/Pago_Pago',
1399 1515 'Pacific/Palau',
1400 1516 'Pacific/Pitcairn',
1401   - 'Pacific/Ponape',
  1517 + 'Pacific/Pohnpei',
1402 1518 'Pacific/Port_Moresby',
1403 1519 'Pacific/Rarotonga',
1404 1520 'Pacific/Saipan',
1405 1521 'Pacific/Tahiti',
1406 1522 'Pacific/Tarawa',
1407 1523 'Pacific/Tongatapu',
1408   - 'Pacific/Truk',
1409 1524 'Pacific/Wake',
1410 1525 'Pacific/Wallis',
1411 1526 'US/Alaska',
48 webapp/graphite/thirdparty/pytz/exceptions.py
... ... @@ -0,0 +1,48 @@
  1 +'''
  2 +Custom exceptions raised by pytz.
  3 +'''
  4 +
  5 +__all__ = [
  6 + 'UnknownTimeZoneError', 'InvalidTimeError', 'AmbiguousTimeError',
  7 + 'NonExistentTimeError',
  8 + ]
  9 +
  10 +
  11 +class UnknownTimeZoneError(KeyError):
  12 + '''Exception raised when pytz is passed an unknown timezone.
  13 +
  14 + >>> isinstance(UnknownTimeZoneError(), LookupError)
  15 + True
  16 +
  17 + This class is actually a subclass of KeyError to provide backwards
  18 + compatibility with code relying on the undocumented behavior of earlier
  19 + pytz releases.
  20 +
  21 + >>> isinstance(UnknownTimeZoneError(), KeyError)
  22 + True
  23 + '''
  24 + pass
  25 +
  26 +
  27 +class InvalidTimeError(Exception):
  28 + '''Base class for invalid time exceptions.'''
  29 +
  30 +
  31 +class AmbiguousTimeError(InvalidTimeError):
  32 + '''Exception raised when attempting to create an ambiguous wallclock time.
  33 +
  34 + At the end of a DST transition period, a particular wallclock time will
  35 + occur twice (once before the clocks are set back, once after). Both
  36 + possibilities may be correct, unless further information is supplied.
  37 +
  38 + See DstTzInfo.normalize() for more info
  39 + '''
  40 +
  41 +
  42 +class NonExistentTimeError(InvalidTimeError):
  43 + '''Exception raised when attempting to create a wallclock time that
  44 + cannot exist.
  45 +
  46 + At the start of a DST transition period, the wallclock time jumps forward.
  47 + The instants jumped over never occur.
  48 + '''
29 webapp/graphite/thirdparty/pytz/tzfile.py
@@ -3,13 +3,25 @@
3 3 $Id: tzfile.py,v 1.8 2004/06/03 00:15:24 zenzen Exp $
4 4 '''
5 5
6   -from cStringIO import StringIO
  6 +try:
  7 + from cStringIO import StringIO
  8 +except ImportError:
  9 + from io import StringIO
7 10 from datetime import datetime, timedelta
8 11 from struct import unpack, calcsize
9 12
10 13 from pytz.tzinfo import StaticTzInfo, DstTzInfo, memorized_ttinfo
11 14 from pytz.tzinfo import memorized_datetime, memorized_timedelta
12 15
  16 +def _byte_string(s):
  17 + """Cast a string or byte string to an ASCII byte string."""
  18 + return s.encode('US-ASCII')
  19 +
  20 +_NULL = _byte_string('\0')
  21 +
  22 +def _std_string(s):
  23 + """Cast a string or byte string to an ASCII string."""
  24 + return str(s.decode('US-ASCII'))
13 25
14 26 def build_tzinfo(zone, fp):
15 27 head_fmt = '>4s c 15x 6l'
@@ -18,7 +30,7 @@ def build_tzinfo(zone, fp):
18 30 typecnt, charcnt) = unpack(head_fmt, fp.read(head_size))
19 31
20 32 # Make sure it is a tzfile(5) file
21   - assert magic == 'TZif'
  33 + assert magic == _byte_string('TZif'), 'Got magic %s' % repr(magic)
22 34
23 35 # Read out the transition times, localtime indices and ttinfo structures.
24 36 data_fmt = '>%(timecnt)dl %(timecnt)dB %(ttinfo)s %(charcnt)ds' % dict(
@@ -43,10 +55,11 @@ def build_tzinfo(zone, fp):
43 55 # have we looked up this timezone name yet?
44 56 tzname_offset = ttinfo_raw[i+2]
45 57 if tzname_offset not in tznames:
46   - nul = tznames_raw.find('\0', tzname_offset)
  58 + nul = tznames_raw.find(_NULL, tzname_offset)
47 59 if nul < 0:
48 60 nul = len(tznames_raw)
49   - tznames[tzname_offset] = tznames_raw[tzname_offset:nul]
  61 + tznames[tzname_offset] = _std_string(
  62 + tznames_raw[tzname_offset:nul])
50 63 ttinfo.append((ttinfo_raw[i],
51 64 bool(ttinfo_raw[i+1]),
52 65 tznames[tzname_offset]))
@@ -84,7 +97,9 @@ def build_tzinfo(zone, fp):
84 97 break
85 98 dst = inf[0] - prev_inf[0] # dst offset
86 99
87   - if dst <= 0: # Bad dst? Look further.
  100 + # Bad dst? Look further. DST > 24 hours happens when
  101 + # a timzone has moved across the international dateline.
  102 + if dst <= 0 or dst > 3600*3:
88 103 for j in range(i+1, len(transitions)):
89 104 stdinf = ttinfo[lindexes[j]]
90 105 if not stdinf[1]:
@@ -98,8 +113,8 @@ def build_tzinfo(zone, fp):
98 113 # datetime library will complain. Conversions to these timezones
99 114 # might be up to plus or minus 30 seconds out, but it is
100 115 # the best we can do.
101   - utcoffset = int((utcoffset + 30) / 60) * 60
102   - dst = int((dst + 30) / 60) * 60
  116 + utcoffset = int((utcoffset + 30) // 60) * 60
  117 + dst = int((dst + 30) // 60) * 60
103 118 transition_info.append(memorized_ttinfo(utcoffset, dst, tzname))
104 119
105 120 cls = type(zone, (DstTzInfo,), dict(
246 webapp/graphite/thirdparty/pytz/tzinfo.py
@@ -8,6 +8,7 @@
8 8 from sets import Set as set
9 9
10 10 import pytz
  11 +from pytz.exceptions import AmbiguousTimeError, NonExistentTimeError
11 12
12 13 __all__ = []
13 14
@@ -73,31 +74,68 @@ class StaticTzInfo(BaseTzInfo):
73 74 '''
74 75 def fromutc(self, dt):
75 76 '''See datetime.tzinfo.fromutc'''
  77 + if dt.tzinfo is not None and dt.tzinfo is not self:
  78 + raise ValueError('fromutc: dt.tzinfo is not self')
76 79 return (dt + self._utcoffset).replace(tzinfo=self)
77 80
78   - def utcoffset(self,dt):
79   - '''See datetime.tzinfo.utcoffset'''
  81 + def utcoffset(self, dt, is_dst=None):
  82 + '''See datetime.tzinfo.utcoffset
  83 +
  84 + is_dst is ignored for StaticTzInfo, and exists only to
  85 + retain compatibility with DstTzInfo.
  86 + '''
80 87 return self._utcoffset
81 88
82   - def dst(self,dt):
83   - '''See datetime.tzinfo.dst'''
  89 + def dst(self, dt, is_dst=None):
  90 + '''See datetime.tzinfo.dst
  91 +
  92 + is_dst is ignored for StaticTzInfo, and exists only to
  93 + retain compatibility with DstTzInfo.
  94 + '''
84 95 return _notime
85 96
86   - def tzname(self,dt):
87   - '''See datetime.tzinfo.tzname'''
  97 + def tzname(self, dt, is_dst=None):
  98 + '''See datetime.tzinfo.tzname
  99 +
  100 + is_dst is ignored for StaticTzInfo, and exists only to
  101 + retain compatibility with DstTzInfo.
  102 + '''
88 103 return self._tzname
89 104
90 105 def localize(self, dt, is_dst=False):
91 106 '''Convert naive time to local time'''
92 107 if dt.tzinfo is not None:
93   - raise ValueError, 'Not naive datetime (tzinfo is already set)'
  108 + raise ValueError('Not naive datetime (tzinfo is already set)')
94 109 return dt.replace(tzinfo=self)
95 110
96 111 def normalize(self, dt, is_dst=False):
97   - '''Correct the timezone information on the given datetime'''
  112 + '''Correct the timezone information on the given datetime.
  113 +
  114 + This is normally a no-op, as StaticTzInfo timezones never have
  115 + ambiguous cases to correct:
  116 +
  117 + >>> from pytz import timezone
  118 + >>> gmt = timezone('GMT')
  119 + >>> isinstance(gmt, StaticTzInfo)
  120 + True
  121 + >>> dt = datetime(2011, 5, 8, 1, 2, 3, tzinfo=gmt)
  122 + >>> gmt.normalize(dt) is dt
  123 + True
  124 +
  125 + The supported method of converting between timezones is to use
  126 + datetime.astimezone(). Currently normalize() also works:
  127 +
  128 + >>> la = timezone('America/Los_Angeles')
  129 + >>> dt = la.localize(datetime(2011, 5, 7, 1, 2, 3))
  130 + >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
  131 + >>> gmt.normalize(dt).strftime(fmt)
  132 + '2011-05-07 08:02:03 GMT (+0000)'
  133 + '''
  134 + if dt.tzinfo is self:
  135 + return dt
98 136 if dt.tzinfo is None:
99   - raise ValueError, 'Naive time - no tzinfo set'
100   - return dt.replace(tzinfo=self)
  137 + raise ValueError('Naive time - no tzinfo set')
  138 + return dt.astimezone(self)
101 139
102 140 def __repr__(self):
103 141 return '<StaticTzInfo %r>' % (self.zone,)
@@ -135,11 +173,13 @@ def __init__(self, _inf=None, _tzinfos=None):
135 173 self._utcoffset, self._dst, self._tzname = self._transition_info[0]
136 174 _tzinfos[self._transition_info[0]] = self
137 175 for inf in self._transition_info[1:]:
138   - if not _tzinfos.has_key(inf):
  176 + if inf not in _tzinfos:
139 177 _tzinfos[inf] = self.__class__(inf, _tzinfos)
140 178
141 179 def fromutc(self, dt):
142 180 '''See datetime.tzinfo.fromutc'''
  181 + if dt.tzinfo is not None and dt.tzinfo._tzinfos is not self._tzinfos:
  182 + raise ValueError('fromutc: dt.tzinfo is not self')
143 183 dt = dt.replace(tzinfo=None)
144 184 idx = max(0, bisect_right(self._utc_transition_times, dt) - 1)
145 185 inf = self._transition_info[idx]
@@ -179,9 +219,19 @@ def normalize(self, dt):
179 219 >>> before = eastern.normalize(before)
180 220 >>> before.strftime(fmt)
181 221 '2002-10-27 01:50:00 EDT (-0400)'
  222 +
  223 + The supported method of converting between timezones is to use
  224 + datetime.astimezone(). Currently, normalize() also works:
  225 +
  226 + >>> th = timezone('Asia/Bangkok')
  227 + >>> am = timezone('Europe/Amsterdam')
  228 + >>> dt = th.localize(datetime(2011, 5, 7, 1, 2, 3))
  229 + >>> fmt = '%Y-%m-%d %H:%M:%S %Z (%z)'
  230 + >>> am.normalize(dt).strftime(fmt)
  231 + '2011-05-06 20:02:03 CEST (+0200)'
182 232 '''
183 233 if dt.tzinfo is None:
184   - raise ValueError, 'Naive time - no tzinfo set'
  234 + raise ValueError('Naive time - no tzinfo set')
185 235
186 236 # Convert dt in localtime to UTC
187 237 offset = dt.tzinfo._utcoffset
@@ -215,10 +265,11 @@ def localize(self, dt, is_dst=False):
215 265 Use is_dst=None to raise an AmbiguousTimeError for ambiguous
216 266 times at the end of daylight savings
217 267
218   - >>> loc_dt1 = amdam.localize(dt, is_dst=None)
219   - Traceback (most recent call last):
220   - [...]
221   - AmbiguousTimeError: 2004-10-31 02:00:00
  268 + >>> try:
  269 + ... loc_dt1 = amdam.localize(dt, is_dst=None)
  270 + ... except AmbiguousTimeError:
  271 + ... print('Ambiguous')
  272 + Ambiguous
222 273
223 274 is_dst defaults to False
224 275
@@ -242,13 +293,14 @@ def localize(self, dt, is_dst=False):
242 293 Use is_dst=None to raise a NonExistentTimeError for these skipped
243 294 times.
244 295
245   - >>> loc_dt1 = pacific.localize(dt, is_dst=None)
246   - Traceback (most recent call last):
247   - [...]
248   - NonExistentTimeError: 2008-03-09 02:00:00
  296 + >>> try:
  297 + ... loc_dt1 = pacific.localize(dt, is_dst=None)
  298 + ... except NonExistentTimeError:
  299 + ... print('Non-existent')
  300 + Non-existent
249 301 '''
250 302 if dt.tzinfo is not None:
251   - raise ValueError, 'Not naive datetime (tzinfo is already set)'
  303 + raise ValueError('Not naive datetime (tzinfo is already set)')
252 304
253 305 # Find the two best possibilities.
254 306 possible_loc_dt = set()
@@ -317,25 +369,120 @@ def localize(self, dt, is_dst=False):
317 369 # but that is just getting silly.
318 370 #
319 371 # Choose the earliest (by UTC) applicable timezone.
320   - def mycmp(a,b):
321   - return cmp(
322   - a.replace(tzinfo=None) - a.tzinfo._utcoffset,
323   - b.replace(tzinfo=None) - b.tzinfo._utcoffset,
324   - )
325   - filtered_possible_loc_dt.sort(mycmp)
326   - return filtered_possible_loc_dt[0]
327   -
328   - def utcoffset(self, dt):
329   - '''See datetime.tzinfo.utcoffset'''
330   - return self._utcoffset
  372 + sorting_keys = {}
  373 + for local_dt in filtered_possible_loc_dt:
  374 + key = local_dt.replace(tzinfo=None) - local_dt.tzinfo._utcoffset
  375 + sorting_keys[key] = local_dt
  376 + first_key = sorted(sorting_keys)[0]
  377 + return sorting_keys[first_key]
331 378
332   - def dst(self, dt):
333   - '''See datetime.tzinfo.dst'''
334   - return self._dst
  379 + def utcoffset(self, dt, is_dst=None):
  380 + '''See datetime.tzinfo.utcoffset
335 381
336   - def tzname(self, dt):
337   - '''See datetime.tzinfo.tzname'''
338   - return self._tzname
  382 + The is_dst parameter may be used to remove ambiguity during DST
  383 + transitions.
  384 +
  385 + >>> from pytz import timezone
  386 + >>> tz = timezone('America/St_Johns')
  387 + >>> ambiguous = datetime(2009, 10, 31, 23, 30)
  388 +
  389 + >>> tz.utcoffset(ambiguous, is_dst=False)
  390 + datetime.timedelta(-1, 73800)
  391 +
  392 + >>> tz.utcoffset(ambiguous, is_dst=True)
  393 + datetime.timedelta(-1, 77400)
  394 +
  395 + >>> try:
  396 + ... tz.utcoffset(ambiguous)
  397 + ... except AmbiguousTimeError:
  398 + ... print('Ambiguous')
  399 + Ambiguous
  400 +
  401 + '''
  402 + if dt is None:
  403 + return None
  404 + elif dt.tzinfo is not self:
  405 + dt = self.localize(dt, is_dst)
  406 + return dt.tzinfo._utcoffset
  407 + else:
  408 + return self._utcoffset
  409 +
  410 + def dst(self, dt, is_dst=None):
  411 + '''See datetime.tzinfo.dst
  412 +
  413 + The is_dst parameter may be used to remove ambiguity during DST
  414 + transitions.
  415 +
  416 + >>> from pytz import timezone
  417 + >>> tz = timezone('America/St_Johns')
  418 +
  419 + >>> normal = datetime(2009, 9, 1)
  420 +
  421 + >>> tz.dst(normal)
  422 + datetime.timedelta(0, 3600)
  423 + >>> tz.dst(normal, is_dst=False)
  424 + datetime.timedelta(0, 3600)
  425 + >>> tz.dst(normal, is_dst=True)
  426 + datetime.timedelta(0, 3600)
  427 +
  428 + >>> ambiguous = datetime(2009, 10, 31, 23, 30)
  429 +
  430 + >>> tz.dst(ambiguous, is_dst=False)
  431 + datetime.timedelta(0)
  432 + >>> tz.dst(ambiguous, is_dst=True)
  433 + datetime.timedelta(0, 3600)
  434 + >>> try:
  435 + ... tz.dst(ambiguous)
  436 + ... except AmbiguousTimeError:
  437 + ... print('Ambiguous')
  438 + Ambiguous
  439 +
  440 + '''
  441 + if dt is None:
  442 + return None
  443 + elif dt.tzinfo is not self:
  444 + dt = self.localize(dt, is_dst)
  445 + return dt.tzinfo._dst
  446 + else:
  447 + return self._dst
  448 +
  449 + def tzname(self, dt, is_dst=None):
  450 + '''See datetime.tzinfo.tzname
  451 +
  452 + The is_dst parameter may be used to remove ambiguity during DST
  453 + transitions.
  454 +
  455 + >>> from pytz import timezone
  456 + >>> tz = timezone('America/St_Johns')
  457 +
  458 + >>> normal = datetime(2009, 9, 1)
  459 +
  460 + >>> tz.tzname(normal)
  461 + 'NDT'
  462 + >>> tz.tzname(normal, is_dst=False)
  463 + 'NDT'
  464 + >>> tz.tzname(normal, is_dst=True)
  465 + 'NDT'
  466 +
  467 + >>> ambiguous = datetime(2009, 10, 31, 23, 30)
  468 +
  469 + >>> tz.tzname(ambiguous, is_dst=False)
  470 + 'NST'
  471 + >>> tz.tzname(ambiguous, is_dst=True)
  472 + 'NDT'
  473 + >>> try:
  474 + ... tz.tzname(ambiguous)
  475 + ... except AmbiguousTimeError:
  476 + ... print('Ambiguous')
  477 + Ambiguous
  478 + '''
  479 + if dt is None:
  480 + return self.zone
  481 + elif dt.tzinfo is not self:
  482 + dt = self.localize(dt, is_dst)
  483 + return dt.tzinfo._tzname
  484 + else:
  485 + return self._tzname
339 486
340 487 def __repr__(self):
341 488 if self._dst:
@@ -362,29 +509,6 @@ def __reduce__(self):
362 509 )
363 510
364 511
365   -class InvalidTimeError(Exception):
366   - '''Base class for invalid time exceptions.'''
367   -
368   -
369   -class AmbiguousTimeError(InvalidTimeError):
370   - '''Exception raised when attempting to create an ambiguous wallclock time.
371   -
372   - At the end of a DST transition period, a particular wallclock time will
373   - occur twice (once before the clocks are set back, once after). Both
374   - possibilities may be correct, unless further information is supplied.
375   -
376   - See DstTzInfo.normalize() for more info
377   - '''
378   -
379   -
380   -class NonExistentTimeError(InvalidTimeError):
381   - '''Exception raised when attempting to create a wallclock time that
382   - cannot exist.
383   -
384   - At the start of a DST transition period, the wallclock time jumps forward.
385   - The instants jumped over never occur.
386   - '''
387   -
388 512
389 513 def unpickler(zone, utcoffset=None, dstoffset=None, tzname=None):
390 514 """Factory function for unpickling pytz tzinfo instances.

0 comments on commit 9beda6e

Please sign in to comment.
Something went wrong with that request. Please try again.