def parse(self, ins): result = False self.setProperties({}) LOOK_FOR_CONTAINER = 0 GET_PROPERTY_OR_COMPONENT = 1 state = LOOK_FOR_CONTAINER # Get lines looking for start of calendar lines = [None, None] comp = self compend = None componentstack = [] while readFoldedLine(ins, lines): line = lines[0] if state == LOOK_FOR_CONTAINER: # Look for start if line == self.getBeginDelimiter(): # Next state state = GET_PROPERTY_OR_COMPONENT # Indicate success at this point result = True # Handle blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("%s data has blank lines" % (self.sContainerDescriptor,)) # Unrecognized data else: raise InvalidData("%s data not recognized" % (self.sContainerDescriptor,), line) elif state == GET_PROPERTY_OR_COMPONENT: # Parse property or look for start of component if line.startswith("BEGIN:") and self.sComponentType is not None: # Push previous details to stack componentstack.append((comp, compend,)) # Start a new component comp = self.sComponentType.makeComponent(line[6:], comp) compend = comp.getEndDelimiter() # Look for end of object elif line == self.getEndDelimiter(): # Finalise the current calendar self.finalise() # Change state state = LOOK_FOR_CONTAINER # Look for end of current component elif line == compend: # Finalise the component (this caches data from the properties) comp.finalise() # Embed component in parent and reset to use parent componentstack[-1][0].addComponent(comp) comp, compend = componentstack.pop() # Blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("%s data has blank lines" % (self.sContainerDescriptor,)) # Must be a property else: # Parse parameter/value for top-level calendar item prop = self.sPropertyType.parseText(line) # Check for valid property if comp is self: if not comp.validProperty(prop): raise InvalidData("Invalid property", str(prop)) else: comp.addProperty(prop) else: comp.addProperty(prop) # Check for truncated data if state != LOOK_FOR_CONTAINER: raise InvalidData("%s data not complete" % (self.sContainerDescriptor,)) # Validate some things if result and not self.hasProperty("VERSION"): raise InvalidData("%s missing VERSION" % (self.sContainerDescriptor,)) return result
def parseMultipleTextData(cls, ins): if isinstance(ins, str): ins = StringIO(ins) results = [] card = cls(add_defaults=False) LOOK_FOR_VCARD = 0 GET_PROPERTY = 1 state = LOOK_FOR_VCARD # Get lines looking for start of calendar lines = [None, None] while readFoldedLine(ins, lines): line = lines[0] if state == LOOK_FOR_VCARD: # Look for start if line == card.getBeginDelimiter(): # Next state state = GET_PROPERTY # Handle blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("vCard data has blank lines") # Unrecognized data else: raise InvalidData("vCard data not recognized", line) elif state == GET_PROPERTY: # Look for end of object if line == card.getEndDelimiter(): # Finalise the current calendar card.finalise() # Validate some things if not card.hasProperty("VERSION"): raise InvalidData("vCard missing VERSION", "") results.append(card) # Change state card = Card(add_defaults=False) state = LOOK_FOR_VCARD # Blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("vCard data has blank lines") # Must be a property else: # Parse parameter/value for top-level calendar item prop = Property.parseText(line) # Check for valid property if not card.validProperty(prop): raise InvalidData("Invalid property", str(prop)) else: card.addProperty(prop) # Check for truncated data if state != LOOK_FOR_VCARD: raise InvalidData("vCard data not complete") return results
def parseComponent(self, ins): result = None LOOK_FOR_VCALENDAR = 0 GET_PROPERTY_OR_COMPONENT = 1 GOT_VCALENDAR = 4 state = LOOK_FOR_VCALENDAR # Get lines looking for start of calendar lines = [None, None] comp = self compend = None componentstack = [] got_timezone = False while readFoldedLine(ins, lines): line = lines[0] if state == LOOK_FOR_VCALENDAR: # Look for start if line == self.getBeginDelimiter(): # Next state state = GET_PROPERTY_OR_COMPONENT # Handle blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("iCalendar data has blank lines") # Unrecognized data else: raise InvalidData("iCalendar data not recognized", line) elif state == GET_PROPERTY_OR_COMPONENT: # Parse property or look for start of component if line.startswith("BEGIN:"): # Push previous details to stack componentstack.append((comp, compend,)) # Start a new component comp = self.sComponentType.makeComponent(line[6:], comp) compend = comp.getEndDelimiter() # Cache as result - but only the first one, we ignore the rest if result is None: result = comp # Look for timezone component to trigger timezone merge only if one is present if comp.getType() == definitions.cICalComponent_VTIMEZONE: got_timezone = True elif line == self.getEndDelimiter(): # Change state state = GOT_VCALENDAR # Look for end of current component elif line == compend: # Finalise the component (this caches data from the properties) comp.finalise() # Embed component in parent and reset to use parent componentstack[-1][0].addComponent(comp) comp, compend = componentstack.pop() # Blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("iCalendar data has blank lines") # Ignore top-level items elif comp is self: pass # Must be a property else: # Parse parameter/value for top-level calendar item prop = self.sPropertyType.parseText(line) # Check for valid property if comp is not self: comp.addProperty(prop) # Exit if we have one - ignore all the rest if state == GOT_VCALENDAR: break # We need to store all timezones in the static object so they can be accessed by any date object # Only do this if we read in a timezone if got_timezone: from pycalendar.timezonedb import TimezoneDatabase TimezoneDatabase.mergeTimezones(self, self.getComponents(definitions.cICalComponent_VTIMEZONE)) return result
def parse(self, ins): result = False self.setProperties({}) LOOK_FOR_CONTAINER = 0 GET_PROPERTY_OR_COMPONENT = 1 state = LOOK_FOR_CONTAINER # Get lines looking for start of calendar lines = [None, None] comp = self compend = None componentstack = [] while readFoldedLine(ins, lines): line = lines[0] if state == LOOK_FOR_CONTAINER: # Look for start if line == self.getBeginDelimiter(): # Next state state = GET_PROPERTY_OR_COMPONENT # Indicate success at this point result = True # Handle blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("%s data has blank lines" % (self.sContainerDescriptor, )) # Unrecognized data else: raise InvalidData( "%s data not recognized" % (self.sContainerDescriptor, ), line) elif state == GET_PROPERTY_OR_COMPONENT: # Parse property or look for start of component if line.startswith( "BEGIN:") and self.sComponentType is not None: # Push previous details to stack componentstack.append(( comp, compend, )) # Start a new component comp = self.sComponentType.makeComponent(line[6:], comp) compend = comp.getEndDelimiter() # Look for end of object elif line == self.getEndDelimiter(): # Finalise the current calendar self.finalise() # Change state state = LOOK_FOR_CONTAINER # Look for end of current component elif line == compend: # Finalise the component (this caches data from the properties) comp.finalise() # Embed component in parent and reset to use parent componentstack[-1][0].addComponent(comp) comp, compend = componentstack.pop() # Blank line elif len(line) == 0: # Raise if requested, otherwise just ignore if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE: raise InvalidData("%s data has blank lines" % (self.sContainerDescriptor, )) # Must be a property else: # Parse parameter/value for top-level calendar item prop = self.sPropertyType.parseText(line) # Check for valid property if comp is self: if not comp.validProperty(prop): raise InvalidData("Invalid property", str(prop)) else: comp.addProperty(prop) else: comp.addProperty(prop) # Check for truncated data if state != LOOK_FOR_CONTAINER: raise InvalidData("%s data not complete" % (self.sContainerDescriptor, )) # Validate some things if result and not self.hasProperty("VERSION"): raise InvalidData("%s missing VERSION" % (self.sContainerDescriptor, )) return result