1.1 --- a/tests/test_calendar_stream.py Sun Nov 02 23:06:25 2008 +0100
1.2 +++ b/tests/test_calendar_stream.py Mon Nov 03 00:48:06 2008 +0100
1.3 @@ -9,7 +9,7 @@
1.4 w = vCalendar.iterwrite(out)
1.5 for name, parameters, value in doc:
1.6 print "%r, %r, %r" % (name, parameters, value)
1.7 - w.write(name, parameters, value)
1.8 + w.write_content_line(name, parameters, value)
1.9 finally:
1.10 out.close()
1.11 f.close()
2.1 --- a/tests/test_card_stream.py Sun Nov 02 23:06:25 2008 +0100
2.2 +++ b/tests/test_card_stream.py Mon Nov 03 00:48:06 2008 +0100
2.3 @@ -9,7 +9,7 @@
2.4 w = vContent.iterwrite(out)
2.5 for name, parameters, value in doc:
2.6 print "%r, %r, %r" % (name, parameters, value)
2.7 - w.write(name, parameters, value)
2.8 + w.write_content_line(name, parameters, value)
2.9 finally:
2.10 out.close()
2.11 f.close()
3.1 --- a/vCalendar.py Sun Nov 02 23:06:25 2008 +0100
3.2 +++ b/vCalendar.py Mon Nov 03 00:48:06 2008 +0100
3.3 @@ -161,12 +161,13 @@
3.4
3.5 # Public functions.
3.6
3.7 -def parse(f, non_standard_newline=0):
3.8 +def parse(stream_or_string, non_standard_newline=0):
3.9
3.10 """
3.11 - Parse the resource data found through the use of the file object 'f', which
3.12 - should provide Unicode data. (The codecs module can be used to open files or
3.13 - to wrap streams in order to provide Unicode data.)
3.14 + Parse the resource data found through the use of the 'stream_or_string',
3.15 + which is either a stream providing Unicode data (the codecs module can be
3.16 + used to open files or to wrap streams in order to provide Unicode data) or a
3.17 + filename identifying a file to be parsed.
3.18
3.19 The optional 'non_standard_newline' can be set to a true value (unlike the
3.20 default) in order to attempt to process files with CR as the end of line
3.21 @@ -176,14 +177,15 @@
3.22 is returned.
3.23 """
3.24
3.25 - return vContent.parse(f, non_standard_newline, vCalendarParser)
3.26 + return vContent.parse(stream_or_string, non_standard_newline, vCalendarParser)
3.27
3.28 -def iterparse(f, non_standard_newline=0):
3.29 +def iterparse(stream_or_string, non_standard_newline=0):
3.30
3.31 """
3.32 - Parse the resource data found through the use of the file object 'f', which
3.33 - should provide Unicode data. (The codecs module can be used to open files or
3.34 - to wrap streams in order to provide Unicode data.)
3.35 + Parse the resource data found through the use of the 'stream_or_string',
3.36 + which is either a stream providing Unicode data (the codecs module can be
3.37 + used to open files or to wrap streams in order to provide Unicode data) or a
3.38 + filename identifying a file to be parsed.
3.39
3.40 The optional 'non_standard_newline' can be set to a true value (unlike the
3.41 default) in order to attempt to process files with CR as the end of line
3.42 @@ -193,9 +195,9 @@
3.43 events of the form (name, parameters, value).
3.44 """
3.45
3.46 - return vContent.iterparse(f, non_standard_newline, vCalendarStreamParser)
3.47 + return vContent.iterparse(stream_or_string, non_standard_newline, vCalendarStreamParser)
3.48
3.49 -def iterwrite(f, line_length=None):
3.50 - return vContent.iterwrite(f, line_length, vCalendarStreamWriter)
3.51 +def iterwrite(stream_or_string, line_length=None):
3.52 + return vContent.iterwrite(stream_or_string, line_length, vCalendarStreamWriter)
3.53
3.54 # vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/vContent.py Sun Nov 02 23:06:25 2008 +0100
4.2 +++ b/vContent.py Mon Nov 03 00:48:06 2008 +0100
4.3 @@ -41,11 +41,16 @@
4.4 # Encoding-related imports.
4.5
4.6 import base64, quopri
4.7 +import codecs
4.8
4.9 # Tokenisation help.
4.10
4.11 import re
4.12
4.13 +# Configuration.
4.14 +
4.15 +default_encoding = "utf-8"
4.16 +
4.17 # Reader and parser classes.
4.18
4.19 class Reader:
4.20 @@ -65,6 +70,12 @@
4.21 self.lines = []
4.22 self.line_number = 1 # about to read line 1
4.23
4.24 + def close(self):
4.25 +
4.26 + "Close the reader."
4.27 +
4.28 + self.f.close()
4.29 +
4.30 def pushback(self, line):
4.31
4.32 """
4.33 @@ -102,13 +113,23 @@
4.34 physical lines of text.
4.35 """
4.36
4.37 + # Skip blank lines.
4.38 +
4.39 line = self.readline()
4.40 + while line:
4.41 + line_stripped = line.rstrip("\r\n")
4.42 + if not line_stripped:
4.43 + line = self.readline()
4.44 + else:
4.45 + break
4.46 + else:
4.47 + return ""
4.48
4.49 # Strip all appropriate whitespace from the right end of each line.
4.50 # For subsequent lines, remove the first whitespace character.
4.51 # See section 4.1 of the iCalendar specification.
4.52
4.53 - lines = [line.rstrip("\r\n")]
4.54 + lines = [line_stripped]
4.55
4.56 line = self.readline()
4.57 while line.startswith(" ") or line.startswith("\t"):
4.58 @@ -212,6 +233,12 @@
4.59
4.60 self.f = f
4.61
4.62 + def close(self):
4.63 +
4.64 + "Close the reader."
4.65 +
4.66 + self.f.close()
4.67 +
4.68 def __iter__(self):
4.69
4.70 "Return self as the iterator."
4.71 @@ -424,6 +451,12 @@
4.72 self.line_length = line_length or self.default_line_length
4.73 self.char_offset = 0
4.74
4.75 + def close(self):
4.76 +
4.77 + "Close the writer."
4.78 +
4.79 + self.f.close()
4.80 +
4.81 def write(self, text):
4.82
4.83 "Write the 'text' to the file."
4.84 @@ -466,7 +499,13 @@
4.85
4.86 self.f = f
4.87
4.88 - def write(self, name, parameters, value):
4.89 + def close(self):
4.90 +
4.91 + "Close the writer."
4.92 +
4.93 + self.f.close()
4.94 +
4.95 + def write_content_line(self, name, parameters, value):
4.96
4.97 """
4.98 Write a content line for the given 'name', 'parameters' and 'value'
4.99 @@ -507,14 +546,32 @@
4.100
4.101 return self.encode_content(value)
4.102
4.103 +# Utility functions.
4.104 +
4.105 +def is_input_stream(stream_or_string):
4.106 + return hasattr(stream_or_string, "read")
4.107 +
4.108 +def get_input_stream(stream_or_string):
4.109 + if is_input_stream(stream_or_string):
4.110 + return stream_or_string
4.111 + else:
4.112 + return codecs.open(stream_or_string, encoding=default_encoding)
4.113 +
4.114 +def get_output_stream(stream_or_string):
4.115 + if hasattr(stream_or_string, "write"):
4.116 + return stream_or_string
4.117 + else:
4.118 + return codecs.open(stream_or_string, "w", encoding=default_encoding)
4.119 +
4.120 # Public functions.
4.121
4.122 -def parse(f, non_standard_newline=0, parser_cls=None):
4.123 +def parse(stream_or_string, non_standard_newline=0, parser_cls=None):
4.124
4.125 """
4.126 - Parse the resource data found through the use of the file object 'f', which
4.127 - should provide Unicode data. (The codecs module can be used to open files or
4.128 - to wrap streams in order to provide Unicode data.)
4.129 + Parse the resource data found through the use of the 'stream_or_string',
4.130 + which is either a stream providing Unicode data (the codecs module can be
4.131 + used to open files or to wrap streams in order to provide Unicode data) or a
4.132 + filename identifying a file to be parsed.
4.133
4.134 The optional 'non_standard_newline' can be set to a true value (unlike the
4.135 default) in order to attempt to process files with CR as the end of line
4.136 @@ -524,16 +581,28 @@
4.137 is returned.
4.138 """
4.139
4.140 - reader = Reader(f, non_standard_newline)
4.141 - parser = (parser_cls or Parser)()
4.142 - return parser.parse(reader)
4.143 + stream = get_input_stream(stream_or_string)
4.144 + reader = Reader(stream, non_standard_newline)
4.145 +
4.146 + # Parse using the reader.
4.147
4.148 -def iterparse(f, non_standard_newline=0, parser_cls=None):
4.149 + try:
4.150 + parser = (parser_cls or Parser)()
4.151 + return parser.parse(reader)
4.152 +
4.153 + # Close any opened streams.
4.154 +
4.155 + finally:
4.156 + if not is_input_stream(stream_or_string):
4.157 + reader.close()
4.158 +
4.159 +def iterparse(stream_or_string, non_standard_newline=0, parser_cls=None):
4.160
4.161 """
4.162 - Parse the resource data found through the use of the file object 'f', which
4.163 - should provide Unicode data. (The codecs module can be used to open files or
4.164 - to wrap streams in order to provide Unicode data.)
4.165 + Parse the resource data found through the use of the 'stream_or_string',
4.166 + which is either a stream providing Unicode data (the codecs module can be
4.167 + used to open files or to wrap streams in order to provide Unicode data) or a
4.168 + filename identifying a file to be parsed.
4.169
4.170 The optional 'non_standard_newline' can be set to a true value (unlike the
4.171 default) in order to attempt to process files with CR as the end of line
4.172 @@ -543,12 +612,14 @@
4.173 events of the form (name, parameters, value).
4.174 """
4.175
4.176 - reader = Reader(f, non_standard_newline)
4.177 + stream = get_input_stream(stream_or_string)
4.178 + reader = Reader(stream, non_standard_newline)
4.179 parser = (parser_cls or StreamParser)(reader)
4.180 - return iter(parser)
4.181 + return parser
4.182
4.183 -def iterwrite(f, line_length=None, writer_cls=None):
4.184 - _writer = Writer(f, line_length)
4.185 +def iterwrite(stream_or_string, line_length=None, writer_cls=None):
4.186 + stream = get_output_stream(stream_or_string)
4.187 + _writer = Writer(stream, line_length)
4.188 writer = (writer_cls or StreamWriter)(_writer)
4.189 return writer
4.190