[CalendarServer-changes] [14027] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Sep 30 04:58:08 PDT 2014


Revision: 14027
          http://trac.calendarserver.org//changeset/14027
Author:   cdaboo at apple.com
Date:     2014-09-30 04:58:08 -0700 (Tue, 30 Sep 2014)
Log Message:
-----------
Update to latest tzdist draft.

Modified Paths:
--------------
    CalendarServer/trunk/requirements-stable.txt
    CalendarServer/trunk/twistedcaldav/ical.py
    CalendarServer/trunk/twistedcaldav/timezonestdservice.py

Modified: CalendarServer/trunk/requirements-stable.txt
===================================================================
--- CalendarServer/trunk/requirements-stable.txt	2014-09-30 11:58:01 UTC (rev 14026)
+++ CalendarServer/trunk/requirements-stable.txt	2014-09-30 11:58:08 UTC (rev 14027)
@@ -7,7 +7,7 @@
 -e .
 -e svn+http://svn.calendarserver.org/repository/calendarserver/twext/trunk@14020#egg=twextpy
 -e svn+http://svn.calendarserver.org/repository/calendarserver/PyKerberos/trunk@13420#egg=kerberos
--e svn+http://svn.calendarserver.org/repository/calendarserver/PyCalendar/trunk@13802#egg=pycalendar
+-e svn+http://svn.calendarserver.org/repository/calendarserver/PyCalendar/trunk@14025#egg=pycalendar
 
 # Specify specific versions of our dependencies so that we're all testing the same config.
 

Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py	2014-09-30 11:58:01 UTC (rev 14026)
+++ CalendarServer/trunk/twistedcaldav/ical.py	2014-09-30 11:58:08 UTC (rev 14027)
@@ -3733,7 +3733,7 @@
 
 
 
-def tzexpandlocal(tzdata, start, end):
+def tzexpandlocal(tzdata, start, end, utc_onset=False):
     """
     Expand a timezone to get onset(local)/utc-offset-from/utc-offset-to/name observance tuples within the specified
     time range.
@@ -3744,6 +3744,8 @@
     @type start: C{date}
     @param end: date for the end of the expansion.
     @type end: C{date}
+    @param utc_onset: whether or not onset values are in UTC.
+    @type utc_onset: C{bool}
 
     @return: a C{list} of tuples
     """
@@ -3778,9 +3780,9 @@
             tzcomp._pycalendar.getTimezoneOffsetSeconds(start),
             tzcomp._pycalendar.getTimezoneDescriptor(start),
         ))
-    for tzstart, _ignore_utctzstart, tzoffsetfrom, tzoffsetto, name in tzexpanded:
+    for tzstart, utctzstart, tzoffsetfrom, tzoffsetto, name in tzexpanded:
         results.append((
-            tzstart,
+            utctzstart if utc_onset else tzstart,
             tzoffsetfrom,
             tzoffsetto,
             name,

Modified: CalendarServer/trunk/twistedcaldav/timezonestdservice.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/timezonestdservice.py	2014-09-30 11:58:01 UTC (rev 14026)
+++ CalendarServer/trunk/twistedcaldav/timezonestdservice.py	2014-09-30 11:58:08 UTC (rev 14027)
@@ -17,7 +17,7 @@
 """
 Timezone service resource and operations.
 
-This is based on http://tools.ietf.org/html/draft-douglass-timezone-service which is the CalConnect
+This is based on http://tools.ietf.org/html/draft-ietf-tzdist-service which is the IETF
 proposal for a standard timezone service.
 """
 
@@ -29,7 +29,7 @@
 from txweb2 import responsecode
 from txweb2.dav.method.propfind import http_PROPFIND
 from txweb2.dav.noneprops import NonePropertyStore
-from txweb2.http import HTTPError, JSONResponse
+from txweb2.http import HTTPError, JSONResponse, StatusResponse
 from txweb2.http import Response
 from txweb2.http_headers import MimeType
 from txweb2.stream import MemoryStream
@@ -196,18 +196,13 @@
 
     http_PROPFIND = http_PROPFIND
 
-    def http_GET(self, request):
-        """
-        The timezone service POST method.
-        """
+    def http_POST(self, request):
+        raise HTTPError(StatusResponse(responsecode.NOT_ALLOWED, "Method not allowed"))
 
-        # GET and POST do the same thing
-        return self.http_POST(request)
 
-
-    def http_POST(self, request):
+    def http_GET(self, request):
         """
-        The timezone service POST method.
+        The timezone service GET method.
         """
 
         # Check authentication and access controls
@@ -234,6 +229,7 @@
                 "list"          : self.doList,
                 "get"           : self.doGet,
                 "expand"        : self.doExpand,
+                "find"          : self.doFind,
             }.get(action, None)
 
             if action is None:
@@ -290,6 +286,12 @@
                         {"name": "end", "required": False, "multi": False, },
                     ],
                 },
+                {
+                    "name": "find",
+                    "parameters": [
+                        {"name": "pattern", "required": True, "multi": False, },
+                    ],
+                },
             ]
         }
         return JSONResponse(responsecode.OK, result, pretty=config.TimezoneService.PrettyPrintJSON)
@@ -416,11 +418,14 @@
             if len(start) > 1:
                 raise ValueError()
             elif len(start) == 1:
-                start = DateTime.parseText("{}0101".format(int(start[0])))
+                if len(start[0]) != 20:
+                    raise ValueError()
+                start = DateTime.parseText(start[0], fullISO=True)
             else:
-                start = DateTime.getToday()
+                start = DateTime.getNowUTC()
                 start.setDay(1)
                 start.setMonth(1)
+                start.setHHMMSS(0, 0, 0)
         except ValueError:
             raise HTTPError(JSONResponse(
                 responsecode.BAD_REQUEST,
@@ -436,11 +441,14 @@
             if len(end) > 1:
                 raise ValueError()
             elif len(end) == 1:
-                end = DateTime.parseText("{}0101".format(int(end[0])))
+                if len(end[0]) != 20:
+                    raise ValueError()
+                end = DateTime.parseText(end[0], fullISO=True)
             else:
-                end = DateTime.getToday()
+                end = DateTime.getNowUTC()
                 end.setDay(1)
                 end.setMonth(1)
+                start.setHHMMSS(0, 0, 0)
                 end.offsetYear(10)
             if end <= start:
                 raise ValueError()
@@ -469,12 +477,13 @@
         # Now do the expansion (but use a cache to avoid re-calculating TZs)
         observances = self.expandcache.get((tzid, start, end), None)
         if observances is None:
-            observances = tzexpandlocal(tzdata, start, end)
+            observances = tzexpandlocal(tzdata, start, end, utc_onset=True)
             self.expandcache[(tzid, start, end)] = observances
 
         # Turn into JSON
         result = {
             "dtstamp": self.timezones.dtstamp,
+            "tzid": tzid,
             "observances": [
                 {
                     "name": name,
@@ -487,7 +496,81 @@
         return JSONResponse(responsecode.OK, result, pretty=config.TimezoneService.PrettyPrintJSON)
 
 
+    def doFind(self, request):
+        """
+        Return a list of all timezones matching a pattern.
+        """
 
+        pattern = request.args.get("pattern", ())
+        if len(pattern) != 1:
+            raise HTTPError(JSONResponse(
+                responsecode.BAD_REQUEST,
+                {
+                    "error": "invalid-pattern",
+                    "description": "Invalid pattern query parameter",
+                },
+                pretty=config.TimezoneService.PrettyPrintJSON,
+            ))
+        pattern = pattern[0]
+
+        def _comp_is(pattern, s):
+            return pattern == s
+        def _comp_startswith(pattern, s):
+            return s.startswith(pattern)
+        def _comp_endswith(pattern, s):
+            return s.endswith(pattern)
+        def _comp_contains(pattern, s):
+            return pattern in s
+
+        def _normalize(s):
+            return s.replace("_", " ").lower()
+
+        if pattern.startswith("*") and pattern.endswith("*"):
+            pattern = pattern[1:-1]
+            comparator = _comp_contains
+        elif pattern.endswith("*"):
+            pattern = pattern[:-1]
+            comparator = _comp_startswith
+        elif pattern.startswith("*"):
+            pattern = pattern[1:]
+            comparator = _comp_endswith
+        else:
+            comparator = _comp_is
+        pattern = _normalize(pattern)
+
+        if not pattern:
+            raise HTTPError(JSONResponse(
+                responsecode.BAD_REQUEST,
+                {
+                    "error": "invalid-pattern",
+                    "description": "Invalid pattern query parameter",
+                },
+                pretty=config.TimezoneService.PrettyPrintJSON,
+            ))
+
+        timezones = []
+        for tz in self.timezones.listTimezones(None):
+            matched = comparator(pattern, _normalize(tz.tzid))
+            if not matched:
+                for alias in tz.aliases:
+                    if comparator(pattern, _normalize(alias)):
+                        matched = True
+                        break
+            if matched:
+                timezones.append({
+                    "tzid": tz.tzid,
+                    "last-modified": tz.dtstamp,
+                    "aliases": tz.aliases,
+                })
+
+        result = {
+            "dtstamp": self.timezones.dtstamp,
+            "timezones": timezones,
+        }
+        return JSONResponse(responsecode.OK, result, pretty=config.TimezoneService.PrettyPrintJSON)
+
+
+
 class TimezoneInfo(object):
     """
     Maintains information from an on-disk store of timezone files.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140930/be79eb6d/attachment-0001.html>


More information about the calendarserver-changes mailing list