[CalendarServer-changes] [9843] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon Sep 24 08:52:07 PDT 2012
Revision: 9843
http://trac.calendarserver.org//changeset/9843
Author: cdaboo at apple.com
Date: 2012-09-24 08:52:07 -0700 (Mon, 24 Sep 2012)
Log Message:
-----------
Add option to update timezone data direct from IANA with conversion of Olson data to iCalendar.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/managetimezones.py
CalendarServer/trunk/support/build.sh
Modified: CalendarServer/trunk/calendarserver/tools/managetimezones.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/managetimezones.py 2012-09-23 03:36:01 UTC (rev 9842)
+++ CalendarServer/trunk/calendarserver/tools/managetimezones.py 2012-09-24 15:52:07 UTC (rev 9843)
@@ -15,7 +15,7 @@
# limitations under the License.
##
-from twistedcaldav.timezonestdservice import PrimaryTimezoneDatabase,\
+from twistedcaldav.timezonestdservice import PrimaryTimezoneDatabase, \
SecondaryTimezoneDatabase
from sys import stdout, stderr
import getopt
@@ -24,48 +24,147 @@
from twisted.python.log import addObserver, removeObserver
import sys
import os
+import urllib
+import tarfile
+import tempfile
+from pycalendar.calendar import PyCalendar
+from zonal.tzconvert import tzconvert
+from twisted.python.filepath import FilePath
+from pycalendar.datetime import PyCalendarDateTime
-def _doPrimaryActions(action, tzpath, xmlfile, changed):
+def _doPrimaryActions(action, tzpath, xmlfile, changed, tzvers):
+
tzdb = PrimaryTimezoneDatabase(tzpath, xmlfile)
- if action == "create":
- print "Creating new XML file at: %s" % (xmlfile, )
- tzdb.createNewDatabase()
- print "Current total: %d" % (len(tzdb.timezones), )
+ if action == "refresh":
+ _doRefresh(tzpath, xmlfile, tzdb, tzvers)
+ elif action == "create":
+ _doCreate(xmlfile, tzdb)
+
elif action == "update":
- print "Updating XML file at: %s" % (xmlfile, )
- tzdb.readDatabase()
- tzdb.updateDatabase()
- print "Current total: %d" % (len(tzdb.timezones), )
- print "Total Changed: %d" % (tzdb.changeCount, )
- if tzdb.changeCount:
- print "Changed:"
- for k in sorted(tzdb.changed):
- print " %s" % (k, )
-
+ _doUpdate(xmlfile, tzdb)
+
elif action == "list":
- print "Listing XML file at: %s" % (xmlfile, )
- tzdb.readDatabase()
- print "Current timestamp: %s" % (tzdb.dtstamp, )
- print "Timezones:"
- for k in sorted(tzdb.timezones.keys()):
- print " %s" % (k, )
-
+ _doList(xmlfile, tzdb)
+
elif action == "changed":
- print "Changes from XML file at: %s" % (xmlfile, )
- tzdb.readDatabase()
- print "Check timestamp: %s" % (changed, )
- print "Current timestamp: %s" % (tzdb.dtstamp, )
- results = [k for k, v in tzdb.timezones.items() if v.dtstamp > changed]
- print "Total Changed: %d" % (len(results), )
- if results:
- print "Changed:"
- for k in sorted(results):
- print " %s" % (k, )
+ _doChanged(xmlfile, changed, tzdb)
+
else:
- usage("Invalid action: %s" % (action, ))
+ usage("Invalid action: %s" % (action,))
+
+
+def _doRefresh(tzpath, xmlfile, tzdb, tzvers):
+ """
+ Refresh data from IANA.
+ """
+
+ print "Downloading latest data from IANA"
+ if tzvers:
+ path = "http://www.iana.org/time-zones/repository/releases/tzdata%s.tar.gz" % (tzvers,)
+ else:
+ path = "http://www.iana.org/time-zones/repository/tzdata-latest.tar.gz"
+ tzvers = "Latest (%s)" % (PyCalendarDateTime.getToday().getText(),)
+ data = urllib.urlretrieve(path)
+ print "Extract data at: %s" % (data[0])
+ rootdir = tempfile.mkdtemp()
+ zonedir = os.path.join(rootdir, "tzdata")
+ os.mkdir(zonedir)
+ with tarfile.open(data[0], "r:gz") as t:
+ t.extractall(zonedir)
+ print "Converting data at: %s" % (zonedir,)
+ startYear = 1800
+ endYear = 2018
+ PyCalendar.sProdID = "-//calendarserver.org//Zonal//EN"
+ zonefiles = "northamerica", "southamerica", "europe", "africa", "asia", "australasia", "antarctica", "etcetera", "backward"
+ parser = tzconvert()
+ for file in zonefiles:
+ parser.parse(os.path.join(zonedir, file))
+
+ parser.generateZoneinfoFiles(os.path.join(rootdir, "zoneinfo"), startYear, endYear, filterzones=())
+ print "Copy new zoneinfo to destination: %s" % (tzpath,)
+ z = FilePath(os.path.join(rootdir, "zoneinfo"))
+ tz = FilePath(tzpath)
+ z.copyTo(tz)
+ print "Updating XML file at: %s" % (xmlfile,)
+ tzdb.readDatabase()
+ tzdb.updateDatabase()
+ print "Current total: %d" % (len(tzdb.timezones),)
+ print "Total Changed: %d" % (tzdb.changeCount,)
+ if tzdb.changeCount:
+ print "Changed:"
+ for k in sorted(tzdb.changed):
+ print " %s" % (k,)
+
+ versfile = os.path.join(os.path.dirname(xmlfile), "version.txt")
+ print "Updating version file at: %s" % (versfile,)
+ with open(versfile, "w") as f:
+ f.write("Olson data source: %s\n" % (tzvers,))
+
+
+
+def _doCreate(xmlfile, tzdb):
+ """
+ Create new xml file.
+ """
+
+ print "Creating new XML file at: %s" % (xmlfile,)
+ tzdb.createNewDatabase()
+ print "Current total: %d" % (len(tzdb.timezones),)
+
+
+
+def _doUpdate(xmlfile, tzdb):
+ """
+ Update xml file.
+ """
+
+ print "Updating XML file at: %s" % (xmlfile,)
+ tzdb.readDatabase()
+ tzdb.updateDatabase()
+ print "Current total: %d" % (len(tzdb.timezones),)
+ print "Total Changed: %d" % (tzdb.changeCount,)
+ if tzdb.changeCount:
+ print "Changed:"
+ for k in sorted(tzdb.changed):
+ print " %s" % (k,)
+
+
+
+def _doList(xmlfile, tzdb):
+ """
+ List current timezones from xml file.
+ """
+
+ print "Listing XML file at: %s" % (xmlfile,)
+ tzdb.readDatabase()
+ print "Current timestamp: %s" % (tzdb.dtstamp,)
+ print "Timezones:"
+ for k in sorted(tzdb.timezones.keys()):
+ print " %s" % (k,)
+
+
+
+def _doChanged(xmlfile, changed, tzdb):
+ """
+ Check for local timezone changes.
+ """
+
+ print "Changes from XML file at: %s" % (xmlfile,)
+ tzdb.readDatabase()
+ print "Check timestamp: %s" % (changed,)
+ print "Current timestamp: %s" % (tzdb.dtstamp,)
+ results = [k for k, v in tzdb.timezones.items() if v.dtstamp > changed]
+ print "Total Changed: %d" % (len(results),)
+ if results:
+ print "Changed:"
+ for k in sorted(results):
+ print " %s" % (k,)
+
+
+
class StandardIOObserver (object):
"""
Log observer that writes to standard I/O.
@@ -86,25 +185,31 @@
output.write(text)
output.flush()
+
def start(self):
addObserver(self.emit)
+
def stop(self):
removeObserver(self.emit)
+
+
@inlineCallbacks
def _runInReactor(tzdb):
-
+
try:
new, changed = yield tzdb.syncWithServer()
- print "New: %d" % (new, )
- print "Changed: %d" % (changed, )
- print "Current total: %d" % (len(tzdb.timezones), )
+ print "New: %d" % (new,)
+ print "Changed: %d" % (changed,)
+ print "Current total: %d" % (len(tzdb.timezones),)
except Exception, e:
print "Could not sync with server: %s" % (str(e),)
finally:
reactor.stop()
+
+
def _doSecondaryActions(action, tzpath, xmlfile, url):
tzdb = SecondaryTimezoneDatabase(tzpath, xmlfile, url)
@@ -113,39 +218,45 @@
except:
pass
if action == "cache":
- print "Caching from secondary server: %s" % (url, )
+ print "Caching from secondary server: %s" % (url,)
observer = StandardIOObserver()
observer.start()
reactor.callLater(0, _runInReactor, tzdb)
reactor.run()
else:
- usage("Invalid action: %s" % (action, ))
+ usage("Invalid action: %s" % (action,))
+
+
def usage(error_msg=None):
if error_msg:
print error_msg
print
- print """Usage: timezonestdservice [options]
+ print """Usage: managetimezones [options]
Options:
-h Print this help and exit
-f XML file path
-z zoneinfo file path
# Primary service
+ --refresh refresh data from IANA
--create create new XML file
--update update XML file
--list list timezones in XML file
--changed changed since timestamp
-
+
+ --tzvers year/release letter of IANA data to refresh
+ default: use the latest release
+
# Secondary service
--url URL or domain of service
--cache Cache data from service
Description:
This utility will create, update or list an XML timezone database
- summary file.
+ summary file, or refresh iCalendar timezone from IANA (Olson).
"""
@@ -154,6 +265,8 @@
else:
sys.exit(0)
+
+
def main():
primary = False
secondary = False
@@ -162,18 +275,21 @@
xmlfile = None
changed = None
url = None
-
+ tzvers = None
+
# Get options
options, _ignore_args = getopt.getopt(
sys.argv[1:],
"hf:z:",
[
+ "refresh",
"create",
"update",
"list",
"changed=",
"url=",
"cache",
+ "tzvers=",
]
)
@@ -184,6 +300,9 @@
xmlfile = value
elif option == "-z":
tzpath = value
+ elif option == "--refresh":
+ action = "refresh"
+ primary = True
elif option == "--create":
action = "create"
primary = True
@@ -203,9 +322,11 @@
elif option == "--cache":
action = "cache"
secondary = True
+ elif option == "--tzvers":
+ tzvers = value
else:
usage("Unrecognized option: %s" % (option,))
-
+
if action is None:
action = "list"
primary = True
@@ -228,7 +349,7 @@
usage("Cannot use primary and secondary options together")
if primary:
- _doPrimaryActions(action, tzpath, xmlfile, changed)
+ _doPrimaryActions(action, tzpath, xmlfile, changed, tzvers)
else:
_doSecondaryActions(action, tzpath, xmlfile, url)
Modified: CalendarServer/trunk/support/build.sh
===================================================================
--- CalendarServer/trunk/support/build.sh 2012-09-23 03:36:01 UTC (rev 9842)
+++ CalendarServer/trunk/support/build.sh 2012-09-24 15:52:07 UTC (rev 9843)
@@ -743,7 +743,7 @@
"${pypi}/p/python-ldap/${ld}.tar.gz";
# XXX actually PyCalendar should be imported in-place.
- py_dependency -fe -i "src" -r 212 \
+ py_dependency -fe -i "src" -r 214 \
"pycalendar" "pycalendar" "pycalendar" \
"http://svn.mulberrymail.com/repos/PyCalendar/branches/server";
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120924/904224f0/attachment-0001.html>
More information about the calendarserver-changes
mailing list