[CalendarServer-changes] [9945] CalDAVClientLibrary/trunk/caldavclientlibrary

source_changes at macosforge.org source_changes at macosforge.org
Tue Oct 16 13:05:47 PDT 2012


Revision: 9945
          http://trac.calendarserver.org//changeset/9945
Author:   cdaboo at apple.com
Date:     2012-10-16 13:05:47 -0700 (Tue, 16 Oct 2012)
Log Message:
-----------
Add calendar-query command to do time-range (possibly expanded) queries.

Modified Paths:
--------------
    CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py
    CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py
    CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/query.py

Added Paths:
-----------
    CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/query.py

Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py	2012-10-16 16:12:08 UTC (rev 9944)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py	2012-10-16 20:05:47 UTC (rev 9945)
@@ -33,6 +33,7 @@
     "props",
     "proxies",
     "put",
+    "query",
     "quit",
     "quota",
     "rm",

Added: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/query.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/query.py	                        (rev 0)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/query.py	2012-10-16 20:05:47 UTC (rev 9945)
@@ -0,0 +1,110 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.browser.command import Command
+from caldavclientlibrary.browser.command import WrongOptions
+from caldavclientlibrary.protocol.url import URL
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+import getopt
+import os
+import shlex
+import time
+from caldavclientlibrary.protocol.caldav.definitions import caldavxml
+
+class Cmd(Command):
+
+    def __init__(self):
+        super(Command, self).__init__()
+        self.cmds = ("query",)
+
+
+    def execute(self, name, options):
+
+        timerange = False
+        start = None
+        end = None
+        expand = False
+        data = False
+
+        opts, args = getopt.getopt(shlex.split(options), 'ts:e:xd')
+
+        for name, value in opts:
+
+            if name == "-t":
+                timerange = True
+            elif name == "-s":
+                start = value
+            elif name == "-e":
+                start = value
+            elif name == "-x":
+                expand = True
+            elif name == "-d":
+                data = True
+            else:
+                print "Unknown option: %s" % (name,)
+                print self.usage(name)
+                raise WrongOptions
+
+        if len(args) > 1:
+            print "Wrong number of arguments: %d" % (len(args),)
+            print self.usage(name)
+            raise WrongOptions
+
+        path = args[0] if len(args) else self.shell.wd
+        if not path.startswith("/"):
+            path = os.path.join(self.shell.wd, path)
+        if not path.endswith("/"):
+            path += "/"
+
+        resource = URL(url=path)
+
+        now = time.time()
+        if timerange and start is None:
+            now_tm = time.gmtime(now)
+            start = "%04d%02d%02dT000000Z" % (now_tm.tm_year, now_tm.tm_mon, now_tm.tm_mday,)
+        if timerange and end is None:
+            tomorrow_tm = time.gmtime(now + 24 * 60 * 60)
+            end = "%04d%02d%02dT000000Z" % (tomorrow_tm.tm_year, tomorrow_tm.tm_mon, tomorrow_tm.tm_mday,)
+
+        props = (davxml.getetag,)
+        if data and not expand:
+            props += (caldavxml.calendar_data,)
+        results = self.shell.account.session.queryCollection(resource, timerange, start, end, expand, props=props)
+        for href in results:
+            print href
+
+        return True
+
+
+    def complete(self, text):
+        return self.shell.wdcomplete(text)
+
+
+    def usage(self, name):
+        return """Usage: %s OPTIONS PATH
+PATH is a relative or absolute path.
+
+Options:
+-t        do time-range query
+-s        start time [DEFAULT today]
+-e        end time [DEFAULT tomorrow]
+-x        expand components
+-d        return data
+""" % (name,)
+
+
+    def helpDescription(self):
+        return "Query a calendar for data."

Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py	2012-10-16 16:12:08 UTC (rev 9944)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py	2012-10-16 20:05:47 UTC (rev 9945)
@@ -21,6 +21,7 @@
 from caldavclientlibrary.protocol.http.authentication.basic import Basic
 from caldavclientlibrary.protocol.http.authentication.digest import Digest
 from caldavclientlibrary.protocol.webdav.synccollection import SyncCollection
+from caldavclientlibrary.protocol.caldav.query import QueryVEVENTTimeRange
 try:
     from caldavclientlibrary.protocol.http.authentication.gssapi import Kerberos
 except ImportError:
@@ -560,6 +561,42 @@
         return (newsynctoken, changed, removed, other,)
 
 
+    def queryCollection(self, rurl, timerange, start, end, expand, props=()):
+
+        assert(isinstance(rurl, URL))
+
+        hrefs = set()
+
+        # Create CalDAV query REPORT
+        if timerange:
+            request = QueryVEVENTTimeRange(self, rurl.relativeURL(), start, end, expand, props=props)
+        else:
+            raise NotImplementedError
+        result = ResponseDataString()
+        request.setOutput(result)
+
+        # Process it
+        self.runSession(request)
+
+        # If its a 207 we want to parse the XML
+        if request.getStatusCode() == statuscodes.MultiStatus:
+
+            parser = PropFindParser()
+            parser.parseData(result.getData())
+
+            # Look at each propfind result
+            for item in parser.getResults().itervalues():
+
+                # Get child element name (decode URL)
+                name = URL(url=item.getResource(), decode=True)
+                hrefs.add(name)
+
+        else:
+            self.handleHTTPError(request)
+
+        return hrefs
+
+
     def deleteResource(self, rurl):
 
         assert(isinstance(rurl, URL))

Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/query.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/query.py	2012-10-16 16:12:08 UTC (rev 9944)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/query.py	2012-10-16 20:05:47 UTC (rev 9945)
@@ -52,6 +52,21 @@
         # <CalDAV:calendar-query> element
         query = Element(caldavxml.calendar_query)
 
+        self.addProps(query)
+
+        # Now add each href
+        self.addFilterElement(query)
+
+        # Now we have the complete document, so write it out (no indentation)
+        xmldoc = BetterElementTree(query)
+        xmldoc.writeUTF8(os)
+
+
+    def addProps(self, query):
+        """
+        Add properties to the query XML.
+        """
+
         if self.props:
             # <DAV:prop> element
             prop = SubElement(query, davxml.prop)
@@ -61,14 +76,7 @@
                 # Add property element taking namespace into account
                 SubElement(prop, propname)
 
-        # Now add each href
-        self.addFilterElement(query)
 
-        # Now we have the complete document, so write it out (no indentation)
-        xmldoc = BetterElementTree(query)
-        xmldoc.writeUTF8(os)
-
-
     def addFilterElement(self, query):
         """
         Add a CALDAV:filter element to the specified CALDAV:calendar-query element.
@@ -80,13 +88,35 @@
 
 class QueryVEVENTTimeRange(Query):
 
-    def __init__(self, session, url, trstart, trend, props=()):
+    def __init__(self, session, url, trstart, trend, expand, props=()):
 
         self.trstart = trstart
         self.trend = trend
+        self.expand = expand
+
         super(QueryVEVENTTimeRange, self).__init__(session, url, props)
 
 
+    def addProps(self, query):
+        """
+        Add properties to the query XML.
+        """
+
+        if self.props or self.expand:
+            # <DAV:prop> element
+            prop = SubElement(query, davxml.prop)
+
+            # Now add each property
+            for propname in self.props:
+                # Add property element taking namespace into account
+                SubElement(prop, propname)
+
+            # Now do expand
+            if self.expand:
+                cdata = SubElement(prop, caldavxml.calendar_data)
+                SubElement(cdata, caldavxml.expand, {"start": self.trstart, "end": self.trend})
+
+
     def addFilterElement(self, query):
         """
         Add a CALDAV:filter element to the specified CALDAV:calendar-query element.
@@ -102,7 +132,7 @@
         #       </CALDAV:time-range>
         #     </CALDAV:component-filter>
         #   </CALDAV:component-filter>
-        # </CalDAV:calendar-query>
+        # </CalDAV:filter>
 
         filter = SubElement(query, caldavxml.filter)
         calcompfilter = SubElement(filter, caldavxml.comp_filter, {"name": "VCALENDAR"})
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20121016/93c17993/attachment-0001.html>


More information about the calendarserver-changes mailing list