def _doTest():
                        result = None
                        if test[0] == '@':
                            if '=' in test:
                                attr, value = test[1:].split('=')
                                value = value[1:-1]
                            else:
                                attr = test[1:]
                                value = None
                            if attr not in node.keys():
                                result = "        Missing attribute returned in XML for %s\n" % (path,)
                            if value is not None and node.get(attr) != value:
                                result = "        Incorrect attribute value returned in XML for %s\n" % (path,)
                        elif test[0] == '=':
                            if node.text != test[1:]:
                                result = "        Incorrect value returned in XML for %s\n" % (path,)
                        elif test[0] == '!':
                            if node.text == test[1:]:
                                result = "        Incorrect value returned in XML for %s\n" % (path,)
                        elif test[0] == '*':
                            if node.text is None or node.text.find(test[1:]) == -1:
                                result = "        Incorrect value returned in XML for %s\n" % (path,)
                        elif test[0] == '$':
                            if node.text is None or node.text.find(test[1:]) != -1:
                                result = "        Incorrect value returned in XML for %s\n" % (path,)
                        elif test[0] == '+':
                            if node.text is None or not node.text.startswith(test[1:]):
                                result = "        Incorrect value returned in XML for %s\n" % (path,)
                        elif test[0] == '^':
                            if "=" in test:
                                element, value = test[1:].split("=", 1)
                            else:
                                element = test[1:]
                                value = None
                            for child in node.getchildren():
                                if child.tag == element and (value is None or child.text == value):
                                    break
                            else:
                                result = "        Missing child returned in XML for %s\n" % (path,)

                        # Try to parse as iCalendar
                        elif test == 'icalendar':
                            try:
                                Calendar.parseText(node.text)
                            except:
                                result = "        Incorrect value returned in iCalendar for %s\n" % (path,)

                        # Try to parse as JSON
                        elif test == 'json':
                            try:
                                json.loads(node.text)
                            except:
                                result = "        Incorrect value returned in XML for %s\n" % (path,)
                        return result
    def _getTimezoneFromServer(self, tzinfo):
        # List all from the server
        url = "%s?action=get&tzid=%s" % (self.uri, tzinfo.tzid)
        log.debug("Getting timezone from secondary server: %s" % (url,))
        response = (yield getURL(url))
        if response is None or response.code / 100 != 2:
            returnValue(None)

        ct = response.headers.getRawHeaders("content-type", ("bogus/type",))[0]
        ct = ct.split(";", 1)
        ct = ct[0]
        if ct not in ("text/calendar",):
            log.error("Invalid content-type '%s' for tzid : %s" % (ct, tzinfo.tzid))
            returnValue(None)

        ical = response.data
        try:
            calendar = Calendar.parseText(ical)
        except InvalidData:
            log.error("Invalid calendar data for tzid: %s" % (tzinfo.tzid,))
            returnValue(None)
        ical = calendar.getText()

        tzinfo.md5 = hashlib.md5(ical).hexdigest()

        try:
            tzpath = os.path.join(self.basepath, tzinfo.tzid) + ".ics"
            if not os.path.exists(os.path.dirname(tzpath)):
                os.makedirs(os.path.dirname(tzpath))
            f = open(tzpath, "w")
            f.write(ical)
            f.close()
        except IOError, e:
            log.error("Unable to write calendar file for %s: %s" % (tzinfo.tzid, str(e)))
Exemplo n.º 3
0
    def _getTimezoneFromServer(self, tzinfo):
        # List all from the server
        url = "%s?action=get&tzid=%s" % (self.uri, tzinfo.tzid,)
        log.debug("Getting timezone from secondary server: %s" % (url,))
        response = (yield getURL(url))
        if response is None or response.code / 100 != 2:
            returnValue(None)

        ct = response.headers.getRawHeaders("content-type", ("bogus/type",))[0]
        ct = ct.split(";", 1)
        ct = ct[0]
        if ct not in ("text/calendar",):
            log.error("Invalid content-type '%s' for tzid : %s" % (ct, tzinfo.tzid,))
            returnValue(None)

        ical = response.data
        try:
            calendar = Calendar.parseText(ical)
        except InvalidData:
            log.error("Invalid calendar data for tzid: %s" % (tzinfo.tzid,))
            returnValue(None)
        ical = calendar.getText()

        tzinfo.md5 = hashlib.md5(ical).hexdigest()

        try:
            tzpath = os.path.join(self.basepath, tzinfo.tzid) + ".ics"
            if not os.path.exists(os.path.dirname(tzpath)):
                os.makedirs(os.path.dirname(tzpath))
            f = open(tzpath, "w")
            f.write(ical)
            f.close()
        except IOError, e:
            log.error("Unable to write calendar file for %s: %s" % (tzinfo.tzid, str(e),))
Exemplo n.º 4
0
        def _doRoundtrip(caldata, jcaldata):
            cal1 = Calendar.parseText(caldata)
            test1 = cal1.getText()

            cal2 = Calendar.parseJSONData(jcaldata)
            test2 = cal2.getText()

            self.assertEqual(
                test1, test2, "\n".join(
                    difflib.unified_diff(
                        str(test1).splitlines(), test2.splitlines())))
Exemplo n.º 5
0
        def _doRoundtrip(caldata, resultdata):
            test1 = json.dumps(json.loads(resultdata), indent=2, separators=(',', ':'), sort_keys=True)

            cal = Calendar.parseText(caldata)

            test2 = cal.getTextJSON(sort_keys=True)
            self.assertEqual(
                test1,
                test2,
                "\n".join(difflib.unified_diff(str(test1).splitlines(), test2.splitlines()))
            )
Exemplo n.º 6
0
        def _doRoundtrip(caldata, jcaldata):
            cal1 = Calendar.parseText(caldata)
            test1 = cal1.getText()

            cal2 = Calendar.parseJSONData(jcaldata)
            test2 = cal2.getText()

            self.assertEqual(
                test1,
                test2,
                "\n".join(difflib.unified_diff(str(test1).splitlines(), test2.splitlines()))
            )
Exemplo n.º 7
0
        def _doRoundtrip(caldata, resultdata):
            test1 = json.dumps(json.loads(resultdata),
                               indent=2,
                               separators=(',', ':'),
                               sort_keys=True)

            cal = Calendar.parseText(caldata)

            test2 = cal.getTextJSON(sort_keys=True)
            self.assertEqual(
                test1, test2, "\n".join(
                    difflib.unified_diff(
                        str(test1).splitlines(), test2.splitlines())))
Exemplo n.º 8
0
def validate(fname):
    """
    Check whether the contents of the specified file is valid iCalendar or vCard data.
    """

    with open(fname) as f:
        data = f.read()

    ParserContext.allRaise()

    if data.find("BEGIN:VCALENDAR") != -1:
        try:
            cal = Calendar.parseText(data)
        except ErrorBase as e:
            print("Failed to parse iCalendar: {}: {}".format(
                e.mReason,
                e.mData,
            ))
            sys.exit(1)
    elif data.find("BEGIN:VCARD") != -1:
        try:
            cal = Card.parseText(data)
        except ErrorBase as e:
            print("Failed to parse vCard: {}: {}".format(
                e.mReason,
                e.mData,
            ))
            sys.exit(1)
    else:
        print("Failed to find valid iCalendar or vCard data")
        sys.exit(1)

    _ignore_fixed, unfixed = cal.validate(doFix=False, doRaise=False)
    if unfixed:
        print("List of problems: {}".format(unfixed, ))
    else:
        print("No problems")

    # Control character check - only HTAB, CR, LF allowed for characters in the range 0x00-0x1F
    s = str(data)
    if len(
            s.translate(
                None,
                "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
            )) != len(s):
        for ctr, i in enumerate(data):
            if i in "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F":
                print("Control character {} at position {}".format(
                    ord(i),
                    ctr,
                ))
Exemplo n.º 9
0
def validate(fname):
    """
    Check whether the contents of the specified file is valid iCalendar or vCard data.
    """

    data = open(fname).read()

    ParserContext.allRaise()

    if data.find("BEGIN:VCALENDAR") != -1:
        try:
            cal = Calendar.parseText(data)
        except ErrorBase, e:
            print "Failed to parse iCalendar: %r" % (e, )
            sys.exit(1)
Exemplo n.º 10
0
def validate(fname):
    """
    Check whether the contents of the specified file is valid iCalendar or vCard data.
    """

    with open(fname) as f:
        data = f.read()

    ParserContext.allRaise()

    if data.find("BEGIN:VCALENDAR") != -1:
        try:
            cal = Calendar.parseText(data)
        except ErrorBase, e:
            print "Failed to parse iCalendar: %r" % (e,)
            sys.exit(1)
Exemplo n.º 11
0
    def testjCalExample1(self):

        jcaldata = """["vcalendar",
  [
    ["calscale", {}, "text", "GREGORIAN"],
    ["prodid", {}, "text", "-//Example Inc.//Example Calendar//EN"],
    ["version", {}, "text", "2.0"]
  ],
  [
    ["vevent",
      [
        ["dtstamp", {}, "date-time", "2008-02-05T19:12:24Z"],
        ["dtstart", {}, "date", "2008-10-06"],
        ["summary", {}, "text", "Planning meeting"],
        ["uid", {}, "text", "4088E990AD89CB3DBB484909"]
      ],
      []
    ]
  ]
]
"""

        icaldata = """BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//Example Inc.//Example Calendar//EN
VERSION:2.0
BEGIN:VEVENT
DTSTAMP:20080205T191224Z
DTSTART;VALUE=DATE:20081006
SUMMARY:Planning meeting
UID:4088E990AD89CB3DBB484909
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n")

        cal1 = Calendar.parseText(icaldata)
        test1 = cal1.getText()

        cal2 = Calendar.parseJSONData(jcaldata)
        test2 = cal2.getText()

        self.assertEqual(
            test1,
            test2,
            "\n".join(difflib.unified_diff(str(test1).splitlines(), test2.splitlines()))
        )
Exemplo n.º 12
0
    def testjCalExample1(self):

        jcaldata = """["vcalendar",
  [
    ["calscale", {}, "text", "GREGORIAN"],
    ["prodid", {}, "text", "-//Example Inc.//Example Calendar//EN"],
    ["version", {}, "text", "2.0"]
  ],
  [
    ["vevent",
      [
        ["dtstamp", {}, "date-time", "2008-02-05T19:12:24Z"],
        ["dtstart", {}, "date", "2008-10-06"],
        ["summary", {}, "text", "Planning meeting"],
        ["uid", {}, "text", "4088E990AD89CB3DBB484909"]
      ],
      []
    ]
  ]
]
"""

        icaldata = """BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//Example Inc.//Example Calendar//EN
VERSION:2.0
BEGIN:VEVENT
DTSTAMP:20080205T191224Z
DTSTART;VALUE=DATE:20081006
SUMMARY:Planning meeting
UID:4088E990AD89CB3DBB484909
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n")

        cal1 = Calendar.parseText(icaldata)
        test1 = cal1.getText()

        cal2 = Calendar.parseJSONData(jcaldata)
        test2 = cal2.getText()

        self.assertEqual(
            test1, test2, "\n".join(
                difflib.unified_diff(
                    str(test1).splitlines(), test2.splitlines())))
Exemplo n.º 13
0
    def _calProperty(self, propertyname, respdata):

        try:
            cal = Calendar.parseText(respdata)
        except Exception:
            return None

        # propname is a path consisting of component names and the last one a property name
        # e.g. VEVENT/ATTACH
        bits = propertyname.split("/")
        components = bits[:-1]
        prop = bits[-1]
        bits = prop.split("$")
        pname = bits[0]
        pvalue = bits[1] if len(bits) > 1 else None

        while components:
            for c in cal.getComponents():
                if c.getType() == components[0]:
                    cal = c
                    components = components[1:]
                    break
            else:
                break

        if components:
            return None

        props = cal.getProperties(pname)
        if pvalue:
            for prop in props:
                if prop.getValue().getValue() == pvalue:
                    return prop
            else:
                return None
        else:
            return props[0] if props else None
Exemplo n.º 14
0
    def _calProperty(self, propertyname, respdata):

        try:
            cal = Calendar.parseText(respdata)
        except Exception:
            return None

        # propname is a path consisting of component names and the last one a property name
        # e.g. VEVENT/ATTACH
        bits = propertyname.split("/")
        components = bits[:-1]
        prop = bits[-1]
        bits = prop.split("$")
        pname = bits[0]
        pvalue = bits[1] if len(bits) > 1 else None

        while components:
            for c in cal.getComponents():
                if c.getType() == components[0]:
                    cal = c
                    components = components[1:]
                    break
            else:
                break

        if components:
            return None

        props = cal.getProperties(pname)
        if pvalue:
            for prop in props:
                if prop.getValue().getValue() == pvalue:
                    return prop
            else:
                return None
        else:
            return props[0] if props else None
Exemplo n.º 15
0
    def testOffsets(self):

        data = (
            (
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
BEGIN:VTIMEZONE
TZID:America/New_York
X-LIC-LOCATION:America/New_York
BEGIN:STANDARD
DTSTART:18831118T120358
RDATE:18831118T120358
TZNAME:EST
TZOFFSETFROM:-045602
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19200101T000000
RDATE:19200101T000000
RDATE:19420101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:EST
TZOFFSETFROM:-0500
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19200328T020000
RDATE:19200328T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19201031T020000
RDATE:19201031T020000
RDATE:19450930T020000
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T190000
RDATE:19450814T190000
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
""",
                (
                    (DateTime(1942, 2, 8), False, -5),
                    (DateTime(1942, 2, 10), False, -4),
                    (DateTime(2011, 1, 1), False, -5),
                    (DateTime(2011, 4, 1), False, -4),
                    (DateTime(2011, 10, 24), False, -4),
                    (DateTime(2011, 11, 8), False, -5),
                    (DateTime(2006, 1, 1), False, -5),
                    (DateTime(2006, 4, 1), False, -5),
                    (DateTime(2006, 5, 1), False, -4),
                    (DateTime(2006, 10, 1), False, -4),
                    (DateTime(2006, 10, 24), False, -4),
                    (DateTime(2006, 11, 8), False, -5),
                    (DateTime(2014, 3, 8, 23, 0, 0), False, -5),
                    (DateTime(2014, 3, 9, 0, 0, 0), False, -5),
                    (DateTime(2014, 3, 9, 3, 0, 0), False, -4),
                    (DateTime(2014, 3, 9, 8, 0, 0), False, -4),
                    (DateTime(2014, 3, 8, 23, 0, 0), True, -5),
                    (DateTime(2014, 3, 9, 0, 0, 0), True, -5),
                    (DateTime(2014, 3, 9, 3, 0, 0), True, -5),
                    (DateTime(2014, 3, 9, 8, 0, 0), True, -4),
                    (DateTime(2014, 11, 1, 23, 0, 0), False, -4),
                    (DateTime(2014, 11, 2, 0, 0, 0), False, -4),
                    (DateTime(2014, 11, 2, 3, 0, 0), False, -5),
                    (DateTime(2014, 11, 2, 8, 0, 0), False, -5),
                    (DateTime(2014, 11, 1, 23, 0, 0), True, -4),
                    (DateTime(2014, 11, 2, 0, 0, 0), True, -4),
                    (DateTime(2014, 11, 2, 3, 0, 0), True, -4),
                    (DateTime(2014, 11, 2, 8, 0, 0), True, -5),
                )
            ),
            (
                """BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Etc/GMT+8
X-LIC-LOCATION:Etc/GMT+8
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+8
TZOFFSETFROM:-0800
TZOFFSETTO:-0800
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
""",
                (
                    (DateTime(1942, 2, 8), False, -8),
                    (DateTime(1942, 2, 10), False, -8),
                    (DateTime(2011, 1, 1), False, -8),
                    (DateTime(2011, 4, 1), False, -8),
                )
            ),
        )

        for tzdata, offsets in data:

            cal = Calendar.parseText(tzdata.replace("\n", "\r\n"))
            tz = cal.getComponents()[0]

            for dt, relative_to_utc, offset in offsets:
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(tzoffset, offset * 60 * 60, "Failed to match offset for %s at %s with caching" % (tz.getID(), dt,))
            for dt, relative_to_utc, offset in reversed(offsets):
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(tzoffset, offset * 60 * 60, "Failed to match offset for %s at %s with caching, reversed" % (tz.getID(), dt,))

            for dt, relative_to_utc, offset in offsets:
                tz.mCachedExpandAllMax = None
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(tzoffset, offset * 60 * 60, "Failed to match offset for %s at %s without caching" % (tz.getID(), dt,))
            for dt, relative_to_utc, offset in reversed(offsets):
                tz.mCachedExpandAllMax = None
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(tzoffset, offset * 60 * 60, "Failed to match offset for %s at %s without caching, reversed" % (tz.getID(), dt,))
Exemplo n.º 16
0
    def verify(self, manager, uri, response, respdata, args): #@UnusedVariable

        # Must have status 200
        if response.status != 200:
            return False, "        HTTP Status Code Wrong: %d" % (response.status,)

        # Get expected FREEBUSY info
        busy = args.get("busy", [])
        tentative = args.get("tentative", [])
        unavailable = args.get("unavailable", [])
        duration = args.get("duration") is not None

        # Parse data as calendar object
        try:
            calendar = Calendar.parseText(respdata)

            # Check for calendar
            if calendar is None:
                raise ValueError("Not a calendar: %s" % (respdata,))

            # Only one component
            comps = calendar.getComponents("VFREEBUSY")
            if len(comps) != 1:
                raise ValueError("Wrong number or unexpected components in calendar")

            # Must be VFREEBUSY
            fb = comps[0]

            # Extract periods
            busyp = []
            tentativep = []
            unavailablep = []
            for fp in fb.getProperties("FREEBUSY"):
                periods = fp.getValue().getValues()
                # Convert start/duration to start/end
                for i in range(len(periods)):
                    periods[i].getValue().setUseDuration(duration)
                # Check param
                fbtype = "BUSY"
                if fp.hasParameter("FBTYPE"):
                    fbtype = fp.getParameterValue("FBTYPE")
                if fbtype == "BUSY":
                    busyp.extend(periods)
                elif fbtype == "BUSY-TENTATIVE":
                    tentativep.extend(periods)
                elif fbtype == "BUSY-UNAVAILABLE":
                    unavailablep.extend(periods)
                else:
                    raise ValueError("Unknown FBTYPE: %s" % (fbtype,))

            # Set sizes must match
            if (
                (len(busy) != len(busyp)) or
                (len(unavailable) != len(unavailablep)) or
                (len(tentative) != len(tentativep))
            ):
                raise ValueError("Period list sizes do not match.")

            # Convert to string sets
            busy = set(busy)
            busyp = [x.getValue().getText() for x in busyp]
            busyp = set(busyp)
            tentative = set(tentative)
            tentativep = [x.getValue().getText() for x in tentativep]
            tentativep = set(tentativep)
            unavailable = set(unavailable)
            unavailablep = [x.getValue().getText() for x in unavailablep]
            unavailablep = set(unavailablep)

            # Compare all periods
            if len(busyp.symmetric_difference(busy)):
                raise ValueError("Busy periods do not match: {}".format(busyp.symmetric_difference(busy)))
            elif len(tentativep.symmetric_difference(tentative)):
                raise ValueError("Busy-tentative periods do not match")
            elif len(unavailablep.symmetric_difference(unavailable)):
                raise ValueError("Busy-unavailable periods do not match")

        except InvalidData:
            return False, "        HTTP response data is not a calendar"
        except ValueError, txt:
            return False, "        HTTP response data is invalid: %s" % (txt,)
    def verify(self, manager, uri, response, respdata, args): #@UnusedVariable
        # Get arguments
        files = args.get("filepath", [])
        caldata = args.get("data", [])
        filters = args.get("filter", [])
        statusCode = args.get("status", ["200", "201", "207"])
        doTimezones = args.get("doTimezones", None)

        if "EMAIL parameter" not in manager.server_info.features:
            filters.append("ATTENDEE:EMAIL")
            filters.append("ORGANIZER:EMAIL")
        filters.append("ATTENDEE:X-CALENDARSERVER-DTSTAMP")
        filters.append("CALSCALE")
        filters.append("PRODID")
        filters.append("DTSTAMP")
        filters.append("CREATED")
        filters.append("LAST-MODIFIED")
        filters.append("X-WR-CALNAME")

        for afilter in tuple(filters):
            if afilter[0] == "!" and afilter[1:] in filters:
                filters.remove(afilter[1:])
        filters = filter(lambda x: x[0] != "!", filters)

        if doTimezones is None:
            doTimezones = "timezones-by-reference" not in manager.server_info.features
        else:
            doTimezones = doTimezones == "true"

        # status code must be 200, 201, 207 or explicitly specified code
        if str(response.status) not in statusCode:
            return False, "        HTTP Status Code Wrong: %d" % (response.status,)

        # look for response data
        if not respdata:
            return False, "        No response body"

        # look for one file
        if len(files) != 1 and len(caldata) != 1:
            return False, "        No file to compare response to"

        # read in all data from specified file or use provided data
        if len(files):
            fd = open(files[0], "r")
            try:
                try:
                    data = fd.read()
                finally:
                    fd.close()
            except:
                data = None
        else:
            data = caldata[0] if len(caldata) else None

        if data is None:
            return False, "        Could not read data file"

        data = manager.server_info.extrasubs(manager.server_info.subs(data))

        def removePropertiesParameters(component):

            if not doTimezones:
                for subcomponent in tuple(component.getComponents()):
                    if subcomponent.getType() == "VTIMEZONE":
                        component.removeComponent(subcomponent)

            for subcomponent in component.getComponents():
                removePropertiesParameters(subcomponent)

            allProps = []
            for properties in component.getProperties().itervalues():
                allProps.extend(properties)
            for property in allProps:
                # Always reset DTSTAMP on these properties
                if property.getName() in ("ATTENDEE", "X-CALENDARSERVER-ATTENDEE-COMMENT"):
                    if property.hasParameter("X-CALENDARSERVER-DTSTAMP"):
                        property.replaceParameter(Parameter("X-CALENDARSERVER-DTSTAMP", "20080101T000000Z"))

                for filter in filters:
                    if ":" in filter:
                        propname, parameter = filter.split(":")
                        if property.getName() == propname:
                            if property.hasParameter(parameter):
                                property.removeParameters(parameter)
                    else:
                        if property.getName() == filter:
                            component.removeProperty(property)

        try:
            resp_calendar = Calendar.parseText(respdata)
            removePropertiesParameters(resp_calendar)
            respdata = resp_calendar.getText()

            data_calendar = Calendar.parseText(data)
            removePropertiesParameters(data_calendar)
            data = data_calendar.getText()

            result = respdata == data

            if result:
                return True, ""
            else:
                error_diff = "\n".join([line for line in unified_diff(data.split("\n"), respdata.split("\n"))])
                return False, "        Response data does not exactly match file data%s" % (error_diff,)
        except Exception, e:
            return False, "        Response data is not calendar data: %s" % (e,)
Exemplo n.º 18
0
    def testMasterComponent(self):

        data = (
            (
                "1.1 Non-recurring no VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "1.2 Non-recurring with VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VTIMEZONE
TZID:Etc/GMT+1
X-LIC-LOCATION:Etc/GMT+1
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+1
TZOFFSETFROM:-0100
TZOFFSETTO:-0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "2.1 Recurring no VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110602
DTSTART;VALUE=DATE:20110602
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "2.2 Recurring with VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VTIMEZONE
TZID:Etc/GMT+1
X-LIC-LOCATION:Etc/GMT+1
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+1
TZOFFSETFROM:-0100
TZOFFSETTO:-0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
RRULE:FREQ=DAILY
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;TZID=Etc/GMT+1:20110602T000000
DTSTART;TZID=Etc/GMT+1:20110602T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "3.1 Recurring no master, no VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110602
DTSTART;VALUE=DATE:20110602
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                "",
            ),
            (
                "3.2 Recurring no master, with VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VTIMEZONE
TZID:Etc/GMT+1
X-LIC-LOCATION:Etc/GMT+1
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+1
TZOFFSETFROM:-0100
TZOFFSETTO:-0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;TZID=Etc/GMT+1:20110602T000000
DTSTART;TZID=Etc/GMT+1:20110602T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                "",
            ),
        )

        for title, caldata, result in data:
            calendar = Calendar.parseText(caldata)
            master = calendar.masterComponent()
            if master is None:
                master = ""
            self.assertEqual(
                str(master), result,
                "Failed in %s: got %s, expected %s" % (title, master, result))
Exemplo n.º 19
0
    def testGetVEvents(self):

        data = (
            (
                "Non-recurring match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (DateTime(2011, 6, 1), ),
            ),
            (
                "Non-recurring no-match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110501
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (),
            ),
            (
                "Recurring match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (
                    DateTime(2011, 6, 1),
                    DateTime(2011, 6, 2),
                ),
            ),
            (
                "Recurring no match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110501
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (),
            ),
            (
                "Recurring with override match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART:20110601T120000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110602T120000
DTSTART;VALUE=DATE:20110602T130000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (
                    DateTime(2011, 6, 1, 12, 0, 0),
                    DateTime(2011, 6, 2, 13, 0, 0),
                ),
            ),
            (
                "Recurring with override no match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART:20110501T120000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110502T120000
DTSTART;VALUE=DATE:20110502T130000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (),
            ),
            (
                "Recurring partial match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110531
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (DateTime(2011, 6, 1), ),
            ),
            (
                "Recurring with override partial match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART:20110531T120000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110601T120000
DTSTART;VALUE=DATE:20110601T130000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (DateTime(2011, 6, 1, 13, 0, 0), ),
            ),
        )

        for title, caldata, result in data:
            calendar = Calendar.parseText(caldata)
            instances = []
            calendar.getVEvents(
                Period(
                    start=DateTime(2011, 6, 1),
                    end=DateTime(2011, 7, 1),
                ), instances)
            instances = tuple(
                [instance.getInstanceStart() for instance in instances])
            self.assertEqual(
                instances, result, "Failed in %s: got %s, expected %s" %
                (title, instances, result))
Exemplo n.º 20
0
    def testParseBlank(self):

        data = (
            """
BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
            """

BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR


""".replace("\n", "\r\n"),
            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT

UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT


UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
        )

        save = ParserContext.BLANK_LINES_IN_DATA
        for item in data:
            ParserContext.BLANK_LINES_IN_DATA = ParserContext.PARSER_RAISE
            self.assertRaises(InvalidData, Calendar.parseText, item)

            ParserContext.BLANK_LINES_IN_DATA = ParserContext.PARSER_IGNORE
            lines = item.split("\r\n")
            result = "\r\n".join([line for line in lines if line]) + "\r\n"
            self.assertEqual(str(Calendar.parseText(item)), result)

        ParserContext.BLANK_LINES_IN_DATA = save
Exemplo n.º 21
0
    def verify(self, manager, uri, response, respdata,
               args):  # @UnusedVariable

        # Must have status 200
        if response.status != 200:
            return False, "        HTTP Status Code Wrong: %d" % (
                response.status, )

        # Get expected FREEBUSY info
        busy = args.get("busy", [])
        tentative = args.get("tentative", [])
        unavailable = args.get("unavailable", [])
        duration = args.get("duration") is not None

        # Parse data as calendar object
        try:
            calendar = Calendar.parseText(respdata)

            # Check for calendar
            if calendar is None:
                raise ValueError("Not a calendar: %s" % (respdata, ))

            # Only one component
            comps = calendar.getComponents("VFREEBUSY")
            if len(comps) != 1:
                raise ValueError(
                    "Wrong number or unexpected components in calendar")

            # Must be VFREEBUSY
            fb = comps[0]

            # Extract periods
            busyp = []
            tentativep = []
            unavailablep = []
            for fp in fb.getProperties("FREEBUSY"):
                periods = fp.getValue().getValues()
                # Convert start/duration to start/end
                for i in range(len(periods)):
                    periods[i].getValue().setUseDuration(duration)
                # Check param
                fbtype = "BUSY"
                if fp.hasParameter("FBTYPE"):
                    fbtype = fp.getParameterValue("FBTYPE")
                if fbtype == "BUSY":
                    busyp.extend(periods)
                elif fbtype == "BUSY-TENTATIVE":
                    tentativep.extend(periods)
                elif fbtype == "BUSY-UNAVAILABLE":
                    unavailablep.extend(periods)
                else:
                    raise ValueError("Unknown FBTYPE: %s" % (fbtype, ))

            # Set sizes must match
            if ((len(busy) != len(busyp))
                    or (len(unavailable) != len(unavailablep))
                    or (len(tentative) != len(tentativep))):
                raise ValueError("Period list sizes do not match.")

            # Convert to string sets
            busy = set(busy)
            busyp = [x.getValue().getText() for x in busyp]
            busyp = set(busyp)
            tentative = set(tentative)
            tentativep = [x.getValue().getText() for x in tentativep]
            tentativep = set(tentativep)
            unavailable = set(unavailable)
            unavailablep = [x.getValue().getText() for x in unavailablep]
            unavailablep = set(unavailablep)

            # Compare all periods
            if len(busyp.symmetric_difference(busy)):
                raise ValueError("Busy periods do not match: {}".format(
                    busyp.symmetric_difference(busy)))
            elif len(tentativep.symmetric_difference(tentative)):
                raise ValueError("Busy-tentative periods do not match")
            elif len(unavailablep.symmetric_difference(unavailable)):
                raise ValueError("Busy-unavailable periods do not match")

        except InvalidData:
            return False, "        HTTP response data is not a calendar"
        except ValueError, txt:
            return False, "        HTTP response data is invalid: %s" % (txt, )
Exemplo n.º 22
0
    def testParseBlank(self):

        data = (
            """
BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),

            """

BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),

            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR


""".replace("\n", "\r\n"),

            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT

UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),

            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT


UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
        )

        save = ParserContext.BLANK_LINES_IN_DATA
        for item in data:
            ParserContext.BLANK_LINES_IN_DATA = ParserContext.PARSER_RAISE
            self.assertRaises(InvalidData, Calendar.parseText, item)

            ParserContext.BLANK_LINES_IN_DATA = ParserContext.PARSER_IGNORE
            lines = item.split("\r\n")
            result = "\r\n".join([line for line in lines if line]) + "\r\n"
            self.assertEqual(str(Calendar.parseText(item)), result)

        ParserContext.BLANK_LINES_IN_DATA = save
Exemplo n.º 23
0
    def testNode(cls, node, node_path, test):
        result = None
        if test[0] == '@':
            if '=' in test:
                attr, value = test[1:].split('=')
                value = value[1:-1]
            else:
                attr = test[1:]
                value = None
            if attr not in node.keys():
                result = "        Missing attribute returned in XML for %s\n" % (
                    node_path, )
            if value is not None and node.get(attr) != value:
                result = "        Incorrect attribute value returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '=':
            if node.text != test[1:]:
                result = "        Incorrect value returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '!':
            if node.text == test[1:]:
                result = "        Incorrect value returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '*':
            if node.text is None or node.text.find(test[1:]) == -1:
                result = "        Incorrect value returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '$':
            if node.text is None or node.text.find(test[1:]) != -1:
                result = "        Incorrect value returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '+':
            if node.text is None or not node.text.startswith(test[1:]):
                result = "        Incorrect value returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '^':
            if "=" in test:
                element, value = test[1:].split("=", 1)
            else:
                element = test[1:]
                value = None
            for child in node.getchildren():
                if child.tag == element and (value is None
                                             or child.text == value):
                    break
            else:
                result = "        Missing child returned in XML for %s\n" % (
                    node_path, )
        elif test[0] == '|':
            if len(test) == 2 and test[1] == "|":
                if node.text is None and len(node.getchildren()) == 0:
                    result = "        Empty element returned in XML for %s\n" % (
                        node_path, )
            else:
                if node.text is not None or len(node.getchildren()) != 0:
                    result = "        Non-empty element returned in XML for %s\n" % (
                        node_path, )

        # Try to parse as iCalendar
        elif test == 'icalendar':
            try:
                Calendar.parseText(node.text)
            except:
                result = "        Incorrect value returned in iCalendar for %s\n" % (
                    node_path, )

        # Try to parse as JSON
        elif test == 'json':
            try:
                json.loads(node.text)
            except:
                result = "        Incorrect value returned in XML for %s\n" % (
                    node_path, )
        return result
Exemplo n.º 24
0
    def testConversions(self):

        tzdata = """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
BEGIN:VTIMEZONE
TZID:America/New_York
X-LIC-LOCATION:America/New_York
BEGIN:STANDARD
DTSTART:18831118T120358
RDATE:18831118T120358
TZNAME:EST
TZOFFSETFROM:-045602
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19200101T000000
RDATE:19200101T000000
RDATE:19420101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:EST
TZOFFSETFROM:-0500
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19200328T020000
RDATE:19200328T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19201031T020000
RDATE:19201031T020000
RDATE:19450930T020000
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T190000
RDATE:19450814T190000
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VTIMEZONE
TZID:America/Los_Angeles
X-LIC-LOCATION:America/Los_Angeles
BEGIN:STANDARD
DTSTART:18831118T120702
RDATE:18831118T120702
TZNAME:PST
TZOFFSETFROM:-075258
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T100000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T090000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:PWT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T160000
RDATE:19450814T160000
TZNAME:PPT
TZOFFSETFROM:-0700
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19450930T020000
RDATE:19450930T020000
RDATE:19490101T020000
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:STANDARD
DTSTART:19460101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:PST
TZOFFSETFROM:-0800
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19480314T020000
RDATE:19480314T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19500430T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T100000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19500924T020000
RRULE:FREQ=YEARLY;UNTIL=19610924T090000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:STANDARD
DTSTART:19621028T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T090000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T100000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T100000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYDAY=1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
"""
        data = (
            (
                DateTime(2014, 3, 8, 23, 0, 0,
                         Timezone(tzid="America/New_York")),
                DateTime(2014, 3, 8, 20, 0, 0,
                         Timezone(tzid="America/Los_Angeles")),
            ),
            (
                DateTime(2014, 3, 9, 3, 0, 0, Timezone(utc=True)),
                DateTime(2014, 3, 8, 19, 0, 0,
                         Timezone(tzid="America/Los_Angeles")),
            ),
            (
                DateTime(2014, 3, 9, 13, 0, 0, Timezone(utc=True)),
                DateTime(2014, 3, 9, 6, 0, 0,
                         Timezone(tzid="America/Los_Angeles")),
            ),
        )

        Calendar.parseText(tzdata.replace("\n", "\r\n"))

        for dtfrom, dtto in data:

            self.assertEqual(dtfrom, dtto)

            newdtfrom = dtfrom.duplicate()
            newdtfrom.adjustTimezone(dtto.getTimezone())
            self.assertEqual(newdtfrom, dtto)
            self.assertEqual(newdtfrom.getHours(), dtto.getHours())
Exemplo n.º 25
0
    def verify(self, manager, uri, response, respdata, args): #@UnusedVariable

        # Must have status 200
        if response.status != 200:
            return False, "        HTTP Status Code Wrong: %d" % (response.status,)

        # Get expected FREEBUSY info
        users = args.get("attendee", [])
        busy = args.get("busy", [])
        tentative = args.get("tentative", [])
        unavailable = args.get("unavailable", [])

        # Extract each calendar-data object
        try:
            tree = ElementTree(file=StringIO.StringIO(respdata))
        except ExpatError:
            return False, "           Could not parse proper XML response\n"

        for calendar in tree.findall("./{urn:ietf:params:xml:ns:caldav}response/{urn:ietf:params:xml:ns:caldav}calendar-data"):
            # Parse data as calendar object
            try:
                calendar = Calendar.parseText(calendar.text)

                # Check for calendar
                if calendar is None:
                    raise ValueError("Not a calendar: %s" % (calendar,))

                # Only one component
                comps = calendar.getComponents("VFREEBUSY")
                if len(comps) != 1:
                    raise ValueError("Wrong number or unexpected components in calendar")

                # Must be VFREEBUSY
                fb = comps[0]

                    # Check for attendee value
                for attendee in fb.getProperties("ATTENDEE"):
                    if attendee.getValue().getValue() in users:
                        users.remove(attendee.getValue().getValue())
                        break
                else:
                    continue

                # Extract periods
                busyp = []
                tentativep = []
                unavailablep = []
                for fp in fb.getProperties("FREEBUSY"):
                    periods = fp.getValue().getValues()
                    # Convert start/duration to start/end
                    for i in range(len(periods)):
                        periods[i].getValue().setUseDuration(False)
                    # Check param
                    fbtype = "BUSY"
                    if fp.hasParameter("FBTYPE"):
                        fbtype = fp.getParameterValue("FBTYPE")
                    if fbtype == "BUSY":
                        busyp.extend(periods)
                    elif fbtype == "BUSY-TENTATIVE":
                        tentativep.extend(periods)
                    elif fbtype == "BUSY-UNAVAILABLE":
                        unavailablep.extend(periods)
                    else:
                        raise ValueError("Unknown FBTYPE: %s" % (fbtype,))

                # Set sizes must match
                if ((len(busy) != len(busyp)) or
                    (len(unavailable) != len(unavailablep)) or
                    (len(tentative) != len(tentativep))):
                    raise ValueError("Period list sizes do not match.")

                # Convert to string sets
                busy = set(busy)
                busyp = [x.getValue().getText() for x in busyp]
                busyp = set(busyp)
                tentative = set(tentative)
                tentativep = [x.getValue().getText() for x in tentativep]
                tentativep = set(tentativep)
                unavailable = set(unavailable)
                unavailablep = [x.getValue().getText() for x in unavailablep]
                unavailablep = set(unavailablep)

                # Compare all periods
                if len(busyp.symmetric_difference(busy)):
                    raise ValueError("Busy periods do not match")
                elif len(tentativep.symmetric_difference(tentative)):
                    raise ValueError("Busy-tentative periods do not match")
                elif len(unavailablep.symmetric_difference(unavailable)):
                    raise ValueError("Busy-unavailable periods do not match")

                break

            except InvalidData:
                return False, "        HTTP response data is not a calendar"
            except ValueError, txt:
                return False, "        HTTP response data is invalid: %s" % (txt,)
Exemplo n.º 26
0
    def testGetVEvents(self):

        data = (
            (
                "Non-recurring match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (DateTime(2011, 6, 1),),
            ),
            (
                "Non-recurring no-match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110501
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (),
            ),
            (
                "Recurring match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (
                    DateTime(2011, 6, 1),
                    DateTime(2011, 6, 2),
                ),
            ),
            (
                "Recurring no match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110501
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (),
            ),
            (
                "Recurring with override match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART:20110601T120000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110602T120000
DTSTART;VALUE=DATE:20110602T130000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (
                    DateTime(2011, 6, 1, 12, 0, 0),
                    DateTime(2011, 6, 2, 13, 0, 0),
                ),
            ),
            (
                "Recurring with override no match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART:20110501T120000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110502T120000
DTSTART;VALUE=DATE:20110502T130000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (),
            ),
            (
                "Recurring partial match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110531
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (
                    DateTime(2011, 6, 1),
                ),
            ),
            (
                "Recurring with override partial match",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART:20110531T120000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY;COUNT=2
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110601T120000
DTSTART;VALUE=DATE:20110601T130000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                (
                    DateTime(2011, 6, 1, 13, 0, 0),
                ),
            ),
        )

        for title, caldata, result in data:
            calendar = Calendar.parseText(caldata)
            instances = []
            calendar.getVEvents(
                Period(
                    start=DateTime(2011, 6, 1),
                    end=DateTime(2011, 7, 1),
                ),
                instances
            )
            instances = tuple([instance.getInstanceStart() for instance in instances])
            self.assertEqual(instances, result, "Failed in %s: got %s, expected %s" % (title, instances, result))
Exemplo n.º 27
0
    def testjCalExample2(self):

        jcaldata = """["vcalendar",
  [
    ["prodid", {}, "text", "-//Example Corp.//Example Client//EN"],
    ["version", {}, "text", "2.0"]
  ],
  [
    ["vtimezone",
      [
        ["last-modified", {}, "date-time", "2004-01-10T03:28:45Z"],
        ["tzid", {}, "text", "US/Eastern"]
      ],
      [
        ["daylight",
          [
            ["dtstart", {}, "date-time", "2000-04-04T02:00:00"],
            ["rrule",
              {},
              "recur",
              {
                "freq": "YEARLY",
                "byday": "1SU",
                "bymonth": 4
              }
            ],
            ["tzname", {}, "text", "EDT"],
            ["tzoffsetfrom", {}, "utc-offset", "-05:00"],
            ["tzoffsetto", {}, "utc-offset", "-04:00"]
          ],
          []
        ],
        ["standard",
          [
            ["dtstart", {}, "date-time", "2000-10-26T02:00:00"],
            ["rrule",
              {},
              "recur",
              {
                "freq": "YEARLY",
                "byday": "-1SU",
                "bymonth": 10
              }
            ],
            ["tzname", {}, "text", "EST"],
            ["tzoffsetfrom", {}, "utc-offset", "-04:00:00"],
            ["tzoffsetto", {}, "utc-offset", "-05:00:00"]
          ],
          []
        ]
      ]
    ],
    ["vevent",
      [
        ["dtstamp", {}, "date-time", "2006-02-06T00:11:21Z"],
        ["dtstart",
          { "tzid": "US/Eastern" },
          "date-time",
          "2006-01-02T12:00:00"
        ],
        ["duration", {}, "duration", "PT1H"],
        ["rrule", {}, "recur", { "freq": "DAILY", "count": 5 } ],
        ["rdate",
          { "tzid": "US/Eastern" },
          "period",
          ["2006-01-02T15:00:00", "PT2H"]
        ],
        ["summary", {}, "text", "Event #2"],
        ["description",
         {},
         "text",
         "We are having a meeting all this week at 12 pm for one hour, with an additional meeting on the first day 2 hours long.\\nPlease bring your own lunch for the 12 pm meetings."
        ],
        ["uid", {}, "text", "*****@*****.**"]
      ],
      []
    ],
    ["vevent",
      [
        ["dtstamp", {}, "date-time", "2006-02-06T00:11:21Z"],
        ["dtstart",
          { "tzid": "US/Eastern" },
          "date-time",
          "2006-01-04T14:00:00"
        ],
        ["duration", {}, "duration", "PT1H"],
        ["recurrence-id",
          { "tzid": "US/Eastern" },
          "date-time",
          "2006-01-04T12:00:00"
        ],
        ["summary", {}, "text", "Event #2 bis"],
        ["uid", {}, "text", "*****@*****.**"]
      ],
      []
    ]
  ]
]
"""

        icaldata = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//Example Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060102T120000
DURATION:PT1H
RRULE:FREQ=DAILY;COUNT=5
RDATE;TZID=US/Eastern;VALUE=PERIOD:20060102T150000/PT2H
SUMMARY:Event #2
DESCRIPTION:We are having a meeting all this week at 12 pm fo
 r one hour\\, with an additional meeting on the first day 2 h
 ours long.\\nPlease bring your own lunch for the 12 pm meetin
 gs.
UID:[email protected]
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060104T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060104T120000
SUMMARY:Event #2 bis
UID:[email protected]
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n")

        cal1 = Calendar.parseText(icaldata)
        test1 = cal1.getText()

        cal2 = Calendar.parseJSONData(jcaldata)
        test2 = cal2.getText()

        self.assertEqual(
            test1, test2, "\n".join(
                difflib.unified_diff(
                    str(test1).splitlines(), test2.splitlines())))
Exemplo n.º 28
0
    def testConversions(self):

        tzdata = """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
BEGIN:VTIMEZONE
TZID:America/New_York
X-LIC-LOCATION:America/New_York
BEGIN:STANDARD
DTSTART:18831118T120358
RDATE:18831118T120358
TZNAME:EST
TZOFFSETFROM:-045602
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19200101T000000
RDATE:19200101T000000
RDATE:19420101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:EST
TZOFFSETFROM:-0500
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19200328T020000
RDATE:19200328T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19201031T020000
RDATE:19201031T020000
RDATE:19450930T020000
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T190000
RDATE:19450814T190000
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VTIMEZONE
TZID:America/Los_Angeles
X-LIC-LOCATION:America/Los_Angeles
BEGIN:STANDARD
DTSTART:18831118T120702
RDATE:18831118T120702
TZNAME:PST
TZOFFSETFROM:-075258
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T100000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T090000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:PWT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T160000
RDATE:19450814T160000
TZNAME:PPT
TZOFFSETFROM:-0700
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19450930T020000
RDATE:19450930T020000
RDATE:19490101T020000
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:STANDARD
DTSTART:19460101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:PST
TZOFFSETFROM:-0800
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19480314T020000
RDATE:19480314T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19500430T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T100000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19500924T020000
RRULE:FREQ=YEARLY;UNTIL=19610924T090000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:STANDARD
DTSTART:19621028T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T090000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T100000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T090000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T100000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T100000Z;BYDAY=1SU;BYMONTH=4
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:PDT
TZOFFSETFROM:-0800
TZOFFSETTO:-0700
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:PST
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
"""
        data = (
            (
                DateTime(2014, 3, 8, 23, 0, 0, Timezone(tzid="America/New_York")),
                DateTime(2014, 3, 8, 20, 0, 0, Timezone(tzid="America/Los_Angeles")),
            ),
            (
                DateTime(2014, 3, 9, 3, 0, 0, Timezone(utc=True)),
                DateTime(2014, 3, 8, 19, 0, 0, Timezone(tzid="America/Los_Angeles")),
            ),
            (
                DateTime(2014, 3, 9, 13, 0, 0, Timezone(utc=True)),
                DateTime(2014, 3, 9, 6, 0, 0, Timezone(tzid="America/Los_Angeles")),
            ),
        )

        Calendar.parseText(tzdata.replace("\n", "\r\n"))

        for dtfrom, dtto in data:

            self.assertEqual(dtfrom, dtto)

            newdtfrom = dtfrom.duplicate()
            newdtfrom.adjustTimezone(dtto.getTimezone())
            self.assertEqual(newdtfrom, dtto)
            self.assertEqual(newdtfrom.getHours(), dtto.getHours())
Exemplo n.º 29
0
    def testCachePreserveOnAdjustment(self):

        # UTC first
        dt = DateTime(2012, 6, 7, 12, 0, 0, Timezone(tzid="utc"))
        dt.getPosixTime()

        # check existing cache is complete
        self.assertTrue(dt.mPosixTimeCached)
        self.assertNotEqual(dt.mPosixTime, 0)
        self.assertEqual(dt.mTZOffset, None)

        # duplicate preserves cache details
        dt2 = dt.duplicate()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, dt.mTZOffset)

        # adjust preserves cache details
        dt2.adjustToUTC()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, dt.mTZOffset)

        # Now timezone
        tzdata = """BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:America/Pittsburgh
BEGIN:STANDARD
DTSTART:18831118T120358
RDATE:18831118T120358
TZNAME:EST
TZOFFSETFROM:-045602
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19200101T000000
RDATE:19200101T000000
RDATE:19420101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:EST
TZOFFSETFROM:-0500
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19200328T020000
RDATE:19200328T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19201031T020000
RDATE:19201031T020000
RDATE:19450930T020000
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T190000
RDATE:19450814T190000
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
""".replace("\n", "\r\n")

        Calendar.parseText(tzdata)

        dt = DateTime(2012, 6, 7, 12, 0, 0,
                      Timezone(tzid="America/Pittsburgh"))
        dt.getPosixTime()

        # check existing cache is complete
        self.assertTrue(dt.mPosixTimeCached)
        self.assertNotEqual(dt.mPosixTime, 0)
        self.assertEqual(dt.mTZOffset, -14400)

        # duplicate preserves cache details
        dt2 = dt.duplicate()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, dt.mTZOffset)

        # adjust preserves cache details
        dt2.adjustToUTC()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, 0)
Exemplo n.º 30
0
    def testMasterComponent(self):

        data = (
            (
                "1.1 Non-recurring no VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "1.2 Non-recurring with VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VTIMEZONE
TZID:Etc/GMT+1
X-LIC-LOCATION:Etc/GMT+1
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+1
TZOFFSETFROM:-0100
TZOFFSETTO:-0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "2.1 Recurring no VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY
SUMMARY:New Year's Day
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110602
DTSTART;VALUE=DATE:20110602
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20110601
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "2.2 Recurring with VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VTIMEZONE
TZID:Etc/GMT+1
X-LIC-LOCATION:Etc/GMT+1
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+1
TZOFFSETFROM:-0100
TZOFFSETTO:-0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
RRULE:FREQ=DAILY
END:VEVENT
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;TZID=Etc/GMT+1:20110602T000000
DTSTART;TZID=Etc/GMT+1:20110602T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                """BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;TZID=Etc/GMT+1:20110601T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
RRULE:FREQ=DAILY
SUMMARY:New Year's Day
END:VEVENT
""".replace("\n", "\r\n"),
            ),
            (
                "3.1 Recurring no master, no VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;VALUE=DATE:20110602
DTSTART;VALUE=DATE:20110602
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                "",
            ),
            (
                "3.2 Recurring no master, with VTIMEZONE",
                """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VTIMEZONE
TZID:Etc/GMT+1
X-LIC-LOCATION:Etc/GMT+1
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+1
TZOFFSETFROM:-0100
TZOFFSETTO:-0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
RECURRENCE-ID;TZID=Etc/GMT+1:20110602T000000
DTSTART;TZID=Etc/GMT+1:20110602T000000
DURATION:P1D
DTSTAMP:20020101T000000Z
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
                "",
            ),
        )

        for title, caldata, result in data:
            calendar = Calendar.parseText(caldata)
            master = calendar.masterComponent()
            if master is None:
                master = ""
            self.assertEqual(str(master), result, "Failed in %s: got %s, expected %s" % (title, master, result))
Exemplo n.º 31
0
    def testjCalExample2(self):

        jcaldata = """["vcalendar",
  [
    ["prodid", {}, "text", "-//Example Corp.//Example Client//EN"],
    ["version", {}, "text", "2.0"]
  ],
  [
    ["vtimezone",
      [
        ["last-modified", {}, "date-time", "2004-01-10T03:28:45Z"],
        ["tzid", {}, "text", "US/Eastern"]
      ],
      [
        ["daylight",
          [
            ["dtstart", {}, "date-time", "2000-04-04T02:00:00"],
            ["rrule",
              {},
              "recur",
              {
                "freq": "YEARLY",
                "byday": "1SU",
                "bymonth": 4
              }
            ],
            ["tzname", {}, "text", "EDT"],
            ["tzoffsetfrom", {}, "utc-offset", "-05:00"],
            ["tzoffsetto", {}, "utc-offset", "-04:00"]
          ],
          []
        ],
        ["standard",
          [
            ["dtstart", {}, "date-time", "2000-10-26T02:00:00"],
            ["rrule",
              {},
              "recur",
              {
                "freq": "YEARLY",
                "byday": "-1SU",
                "bymonth": 10
              }
            ],
            ["tzname", {}, "text", "EST"],
            ["tzoffsetfrom", {}, "utc-offset", "-04:00:00"],
            ["tzoffsetto", {}, "utc-offset", "-05:00:00"]
          ],
          []
        ]
      ]
    ],
    ["vevent",
      [
        ["dtstamp", {}, "date-time", "2006-02-06T00:11:21Z"],
        ["dtstart",
          { "tzid": "US/Eastern" },
          "date-time",
          "2006-01-02T12:00:00"
        ],
        ["duration", {}, "duration", "PT1H"],
        ["rrule", {}, "recur", { "freq": "DAILY", "count": 5 } ],
        ["rdate",
          { "tzid": "US/Eastern" },
          "period",
          ["2006-01-02T15:00:00", "PT2H"]
        ],
        ["summary", {}, "text", "Event #2"],
        ["description",
         {},
         "text",
         "We are having a meeting all this week at 12 pm for one hour, with an additional meeting on the first day 2 hours long.\\nPlease bring your own lunch for the 12 pm meetings."
        ],
        ["uid", {}, "text", "*****@*****.**"]
      ],
      []
    ],
    ["vevent",
      [
        ["dtstamp", {}, "date-time", "2006-02-06T00:11:21Z"],
        ["dtstart",
          { "tzid": "US/Eastern" },
          "date-time",
          "2006-01-04T14:00:00"
        ],
        ["duration", {}, "duration", "PT1H"],
        ["recurrence-id",
          { "tzid": "US/Eastern" },
          "date-time",
          "2006-01-04T12:00:00"
        ],
        ["summary", {}, "text", "Event #2 bis"],
        ["uid", {}, "text", "*****@*****.**"]
      ],
      []
    ]
  ]
]
"""

        icaldata = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//Example Client//EN
BEGIN:VTIMEZONE
LAST-MODIFIED:20040110T032845Z
TZID:US/Eastern
BEGIN:DAYLIGHT
DTSTART:20000404T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20001026T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060102T120000
DURATION:PT1H
RRULE:FREQ=DAILY;COUNT=5
RDATE;TZID=US/Eastern;VALUE=PERIOD:20060102T150000/PT2H
SUMMARY:Event #2
DESCRIPTION:We are having a meeting all this week at 12 pm fo
 r one hour\\, with an additional meeting on the first day 2 h
 ours long.\\nPlease bring your own lunch for the 12 pm meetin
 gs.
UID:[email protected]
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20060206T001121Z
DTSTART;TZID=US/Eastern:20060104T140000
DURATION:PT1H
RECURRENCE-ID;TZID=US/Eastern:20060104T120000
SUMMARY:Event #2 bis
UID:[email protected]
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n")

        cal1 = Calendar.parseText(icaldata)
        test1 = cal1.getText()

        cal2 = Calendar.parseJSONData(jcaldata)
        test2 = cal2.getText()

        self.assertEqual(
            test1,
            test2,
            "\n".join(difflib.unified_diff(str(test1).splitlines(), test2.splitlines()))
        )
Exemplo n.º 32
0
def anonymizeData(directoryMap, data):
    try:
        pyobj = Calendar.parseText(data)
    except Exception, e:
        print("Failed to parse (%s): %s" % (e, data))
        return None
Exemplo n.º 33
0
    def testCachePreserveOnAdjustment(self):

        # UTC first
        dt = DateTime(2012, 6, 7, 12, 0, 0, Timezone(tzid="utc"))
        dt.getPosixTime()

        # check existing cache is complete
        self.assertTrue(dt.mPosixTimeCached)
        self.assertNotEqual(dt.mPosixTime, 0)
        self.assertEqual(dt.mTZOffset, None)

        # duplicate preserves cache details
        dt2 = dt.duplicate()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, dt.mTZOffset)

        # adjust preserves cache details
        dt2.adjustToUTC()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, dt.mTZOffset)

        # Now timezone
        tzdata = """BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:America/Pittsburgh
BEGIN:STANDARD
DTSTART:18831118T120358
RDATE:18831118T120358
TZNAME:EST
TZOFFSETFROM:-045602
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19200101T000000
RDATE:19200101T000000
RDATE:19420101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:EST
TZOFFSETFROM:-0500
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19200328T020000
RDATE:19200328T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19201031T020000
RDATE:19201031T020000
RDATE:19450930T020000
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T190000
RDATE:19450814T190000
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
""".replace("\n", "\r\n")

        Calendar.parseText(tzdata)

        dt = DateTime(2012, 6, 7, 12, 0, 0, Timezone(tzid="America/Pittsburgh"))
        dt.getPosixTime()

        # check existing cache is complete
        self.assertTrue(dt.mPosixTimeCached)
        self.assertNotEqual(dt.mPosixTime, 0)
        self.assertEqual(dt.mTZOffset, -14400)

        # duplicate preserves cache details
        dt2 = dt.duplicate()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, dt.mTZOffset)

        # adjust preserves cache details
        dt2.adjustToUTC()
        self.assertTrue(dt2.mPosixTimeCached)
        self.assertEqual(dt2.mPosixTime, dt.mPosixTime)
        self.assertEqual(dt2.mTZOffset, 0)
Exemplo n.º 34
0
    def verify(self, manager, uri, response, respdata, args):  # @UnusedVariable

        # Must have status 200
        if response.status != 200:
            return False, "        HTTP Status Code Wrong: %d" % (response.status,)

        # Get expected FREEBUSY info
        users = args.get("attendee", [])
        busy = args.get("busy", [])
        tentative = args.get("tentative", [])
        unavailable = args.get("unavailable", [])

        # Extract each calendar-data object
        try:
            tree = ElementTree(file=StringIO.StringIO(respdata))
        except ExpatError:
            return False, "           Could not parse proper XML response\n"

        for calendar in tree.findall("./{urn:ietf:params:xml:ns:caldav}response/{urn:ietf:params:xml:ns:caldav}calendar-data"):
            # Parse data as calendar object
            try:
                calendar = Calendar.parseText(calendar.text)

                # Check for calendar
                if calendar is None:
                    raise ValueError("Not a calendar: %s" % (calendar,))

                # Only one component
                comps = calendar.getComponents("VFREEBUSY")
                if len(comps) != 1:
                    raise ValueError("Wrong number or unexpected components in calendar")

                # Must be VFREEBUSY
                fb = comps[0]

                # Check for attendee value
                for attendee in fb.getProperties("ATTENDEE"):
                    if attendee.getValue().getValue() in users:
                        users.remove(attendee.getValue().getValue())
                        break
                else:
                    continue

                # Extract periods
                busyp = []
                tentativep = []
                unavailablep = []
                for fp in fb.getProperties("FREEBUSY"):
                    periods = fp.getValue().getValues()
                    # Convert start/duration to start/end
                    for i in range(len(periods)):
                        periods[i].getValue().setUseDuration(False)
                    # Check param
                    fbtype = "BUSY"
                    if fp.hasParameter("FBTYPE"):
                        fbtype = fp.getParameterValue("FBTYPE")
                    if fbtype == "BUSY":
                        busyp.extend(periods)
                    elif fbtype == "BUSY-TENTATIVE":
                        tentativep.extend(periods)
                    elif fbtype == "BUSY-UNAVAILABLE":
                        unavailablep.extend(periods)
                    else:
                        raise ValueError("Unknown FBTYPE: %s" % (fbtype,))

                # Set sizes must match
                if (
                    (len(busy) != len(busyp)) or
                    (len(unavailable) != len(unavailablep)) or
                    (len(tentative) != len(tentativep))
                ):
                    raise ValueError("Period list sizes do not match.")

                # Convert to string sets
                busy = set(busy)
                busyp = [x.getValue().getText() for x in busyp]
                busyp = set(busyp)
                tentative = set(tentative)
                tentativep = [x.getValue().getText() for x in tentativep]
                tentativep = set(tentativep)
                unavailable = set(unavailable)
                unavailablep = [x.getValue().getText() for x in unavailablep]
                unavailablep = set(unavailablep)

                # Compare all periods
                if len(busyp.symmetric_difference(busy)):
                    raise ValueError("Busy periods do not match")
                elif len(tentativep.symmetric_difference(tentative)):
                    raise ValueError("Busy-tentative periods do not match")
                elif len(unavailablep.symmetric_difference(unavailable)):
                    raise ValueError("Busy-unavailable periods do not match")

                break

            except InvalidData:
                return False, "        HTTP response data is not a calendar"
            except ValueError, txt:
                return False, "        HTTP response data is invalid: %s" % (txt,)
            except Exception, e:
                return False, "        Response data is not calendar data: %s" % (e,)
Exemplo n.º 35
0
def anonymizeData(directoryMap, data):
    try:
        pyobj = Calendar.parseText(data)
    except Exception, e:
        print("Failed to parse (%s): %s" % (e, data))
        return None
Exemplo n.º 36
0
    def testOffsets(self):

        data = (
            ("""BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
BEGIN:VTIMEZONE
TZID:America/New_York
X-LIC-LOCATION:America/New_York
BEGIN:STANDARD
DTSTART:18831118T120358
RDATE:18831118T120358
TZNAME:EST
TZOFFSETFROM:-045602
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19180331T020000
RRULE:FREQ=YEARLY;UNTIL=19190330T070000Z;BYDAY=-1SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19181027T020000
RRULE:FREQ=YEARLY;UNTIL=19191026T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19200101T000000
RDATE:19200101T000000
RDATE:19420101T000000
RDATE:19460101T000000
RDATE:19670101T000000
TZNAME:EST
TZOFFSETFROM:-0500
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19200328T020000
RDATE:19200328T020000
RDATE:19740106T020000
RDATE:19750223T020000
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19201031T020000
RDATE:19201031T020000
RDATE:19450930T020000
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19210424T020000
RRULE:FREQ=YEARLY;UNTIL=19410427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19210925T020000
RRULE:FREQ=YEARLY;UNTIL=19410928T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19420209T020000
RDATE:19420209T020000
TZNAME:EWT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19450814T190000
RDATE:19450814T190000
TZNAME:EPT
TZOFFSETFROM:-0400
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19460428T020000
RRULE:FREQ=YEARLY;UNTIL=19660424T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19460929T020000
RRULE:FREQ=YEARLY;UNTIL=19540926T060000Z;BYDAY=-1SU;BYMONTH=9
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:STANDARD
DTSTART:19551030T020000
RRULE:FREQ=YEARLY;UNTIL=19661030T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19670430T020000
RRULE:FREQ=YEARLY;UNTIL=19730429T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19671029T020000
RRULE:FREQ=YEARLY;UNTIL=20061029T060000Z;BYDAY=-1SU;BYMONTH=10
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19760425T020000
RRULE:FREQ=YEARLY;UNTIL=19860427T070000Z;BYDAY=-1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:19870405T020000
RRULE:FREQ=YEARLY;UNTIL=20060402T070000Z;BYDAY=1SU;BYMONTH=4
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:DAYLIGHT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZNAME:EDT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZNAME:EST
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
""", (
                (DateTime(1942, 2, 8), False, -5),
                (DateTime(1942, 2, 10), False, -4),
                (DateTime(2011, 1, 1), False, -5),
                (DateTime(2011, 4, 1), False, -4),
                (DateTime(2011, 10, 24), False, -4),
                (DateTime(2011, 11, 8), False, -5),
                (DateTime(2006, 1, 1), False, -5),
                (DateTime(2006, 4, 1), False, -5),
                (DateTime(2006, 5, 1), False, -4),
                (DateTime(2006, 10, 1), False, -4),
                (DateTime(2006, 10, 24), False, -4),
                (DateTime(2006, 11, 8), False, -5),
                (DateTime(2014, 3, 8, 23, 0, 0), False, -5),
                (DateTime(2014, 3, 9, 0, 0, 0), False, -5),
                (DateTime(2014, 3, 9, 3, 0, 0), False, -4),
                (DateTime(2014, 3, 9, 8, 0, 0), False, -4),
                (DateTime(2014, 3, 8, 23, 0, 0), True, -5),
                (DateTime(2014, 3, 9, 0, 0, 0), True, -5),
                (DateTime(2014, 3, 9, 3, 0, 0), True, -5),
                (DateTime(2014, 3, 9, 8, 0, 0), True, -4),
                (DateTime(2014, 11, 1, 23, 0, 0), False, -4),
                (DateTime(2014, 11, 2, 0, 0, 0), False, -4),
                (DateTime(2014, 11, 2, 3, 0, 0), False, -5),
                (DateTime(2014, 11, 2, 8, 0, 0), False, -5),
                (DateTime(2014, 11, 1, 23, 0, 0), True, -4),
                (DateTime(2014, 11, 2, 0, 0, 0), True, -4),
                (DateTime(2014, 11, 2, 3, 0, 0), True, -4),
                (DateTime(2014, 11, 2, 8, 0, 0), True, -5),
            )),
            ("""BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//calendarserver.org//Zonal//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Etc/GMT+8
X-LIC-LOCATION:Etc/GMT+8
BEGIN:STANDARD
DTSTART:18000101T000000
RDATE:18000101T000000
TZNAME:GMT+8
TZOFFSETFROM:-0800
TZOFFSETTO:-0800
END:STANDARD
END:VTIMEZONE
END:VCALENDAR
""", (
                (DateTime(1942, 2, 8), False, -8),
                (DateTime(1942, 2, 10), False, -8),
                (DateTime(2011, 1, 1), False, -8),
                (DateTime(2011, 4, 1), False, -8),
            )),
        )

        for tzdata, offsets in data:

            cal = Calendar.parseText(tzdata.replace("\n", "\r\n"))
            tz = cal.getComponents()[0]

            for dt, relative_to_utc, offset in offsets:
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(
                    tzoffset, offset * 60 * 60,
                    "Failed to match offset for %s at %s with caching" % (
                        tz.getID(),
                        dt,
                    ))
            for dt, relative_to_utc, offset in reversed(offsets):
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(
                    tzoffset, offset * 60 * 60,
                    "Failed to match offset for %s at %s with caching, reversed"
                    % (
                        tz.getID(),
                        dt,
                    ))

            for dt, relative_to_utc, offset in offsets:
                tz.mCachedExpandAllMax = None
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(
                    tzoffset, offset * 60 * 60,
                    "Failed to match offset for %s at %s without caching" % (
                        tz.getID(),
                        dt,
                    ))
            for dt, relative_to_utc, offset in reversed(offsets):
                tz.mCachedExpandAllMax = None
                tzoffset = tz.getTimezoneOffsetSeconds(dt, relative_to_utc)
                self.assertEqual(
                    tzoffset, offset * 60 * 60,
                    "Failed to match offset for %s at %s without caching, reversed"
                    % (
                        tz.getID(),
                        dt,
                    ))