1 #!/usr/bin/env python 2 3 """ 4 Parsing of vCalendar and iCalendar files. 5 6 Copyright (C) 2008 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU Lesser General Public License as published by the Free 10 Software Foundation; either version 3 of the License, or (at your option) any 11 later version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 details. 17 18 You should have received a copy of the GNU Lesser General Public License along 19 with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 -------- 22 23 References: 24 25 RFC 2445: Internet Calendaring and Scheduling Core Object Specification 26 (iCalendar) 27 http://rfc.net/rfc2445.html 28 """ 29 30 import vContent 31 32 try: 33 set 34 except NameError: 35 from sets import Set as set 36 37 class vCalendarStreamParser(vContent.StreamParser): 38 39 "A stream parser specifically for vCalendar/iCalendar." 40 41 quoted_parameters = set([ 42 "ALTREP", "DELEGATED-FROM", "DELEGATED-TO", "DIR", "MEMBER", "SENT-BY" 43 ]) 44 multivalued_parameters = set([ 45 "DELEGATED-FROM", "DELEGATED-TO", "MEMBER" 46 ]) 47 quoted_types = set(["URI"]) 48 49 def next(self): 50 51 """ 52 Return the next content item in the file as a tuple of the form 53 (name, parameters, values). 54 """ 55 56 name, parameters, values = vContent.StreamParser.next(self) 57 return name, self.decode_parameters(parameters), values 58 59 def decode_quoted_value(self, value): 60 61 "Decode the given 'value', returning a list of decoded values." 62 63 if value[0] == '"' and value[-1] == '"': 64 return value[1:-1] 65 else: 66 return value 67 68 def decode_parameters(self, parameters): 69 70 """ 71 Decode the given 'parameters' according to the vCalendar specification. 72 """ 73 74 decoded_parameters = {} 75 76 for param_name, param_value in parameters.items(): 77 if param_name in self.quoted_parameters: 78 param_value = self.decode_quoted_value(param_value) 79 separator = '","' 80 else: 81 separator = "," 82 if param_name in self.multivalued_parameters: 83 param_value = param_value.split(separator) 84 decoded_parameters[param_name] = param_value 85 86 return decoded_parameters 87 88 class vCalendarParser(vContent.Parser): 89 90 "A parser specifically for vCalendar/iCalendar." 91 92 def parse(self, f, parser_cls=None): 93 return vContent.Parser.parse(self, f, vCalendarStreamParser) 94 95 # Public functions. 96 97 def parse(f, non_standard_newline=0): 98 99 """ 100 Parse the resource data found through the use of the file object 'f', which 101 should provide Unicode data. (The codecs module can be used to open files or 102 to wrap streams in order to provide Unicode data.) 103 104 The optional 'non_standard_newline' can be set to a true value (unlike the 105 default) in order to attempt to process files with CR as the end of line 106 character. 107 108 As a result of parsing the resource, the root node of the imported resource 109 is returned. 110 """ 111 112 return vContent.parse(f, non_standard_newline, vCalendarParser) 113 114 def iterparse(f, non_standard_newline=0): 115 116 """ 117 Parse the resource data found through the use of the file object 'f', which 118 should provide Unicode data. (The codecs module can be used to open files or 119 to wrap streams in order to provide Unicode data.) 120 121 The optional 'non_standard_newline' can be set to a true value (unlike the 122 default) in order to attempt to process files with CR as the end of line 123 character. 124 125 An iterator is returned which provides event tuples describing parsing 126 events of the form (name, parameters, value). 127 """ 128 129 return vContent.iterparse(f, non_standard_newline, vCalendarStreamParser) 130 131 # vim: tabstop=4 expandtab shiftwidth=4