Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,50 @@ def test_unicode_multiline():
# json tries to encode as utf-8 and it would break if some chars could not be encoded
json.dumps(cal.serialize())

def test_missing_object_terminator(self):
"""
Test parsing of vObject without line terminator on final line.
"""
# Proper CRLF.
raw = "BEGIN:VCARD\r\n" \
+ "END:VCARD"
card = base.readOne(raw)
self.assertIsNotNone(card)

# Check with folded line too.
raw = "BEGIN:VCARD\r\n" \
+ "END:\r\n" \
+ " VCARD"
card = base.readOne(raw)
self.assertIsNotNone(card)

# LF-only (Unix-style).
raw = "BEGIN:VCARD\n" \
+ "END:VCARD"
card = base.readOne(raw)
self.assertIsNotNone(card)

# CR-only (old MacOS-style).
raw = "BEGIN:VCARD\r" \
+ "END:VCARD"
card = base.readOne(raw)
self.assertIsNotNone(card)

def test_parsing_error_line_number(self):
"""
Check that the line number reported for a parsing error is correct.
"""
# Mismatched item names, with folded line.
raw = "BEGIN:\r\n" \
+ " AAA\r\n" \
+ "END:BBB"
with self.assertRaises(base.ParseError) as context:
card = base.readOne(raw)

# Check line number of parsing error.
e = context.exception
self.assertEqual(e.args[1], 3)

@staticmethod
def test_ical_to_hcal():
"""
Expand Down
12 changes: 9 additions & 3 deletions vobject/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,12 +831,12 @@ def parseLine(line, lineNumber=None):

# logical line regular expressions

patterns['lineend'] = r'(?:\r\n|\r|\n|$)'
patterns['lineend'] = r'(?:\r\n|\r|\n)'
patterns['wrap'] = r'{lineend!s} [\t ]'.format(**patterns)
patterns['logicallines'] = r"""
(
(?: [^\r\n] | {wrap!s} )*
{lineend!s}
(?: {lineend!s} | $ )
)
""".format(**patterns)

Expand Down Expand Up @@ -883,7 +883,13 @@ def getLogicalLines(fp, allowQP=True):

lineNumber = 1
for match in logical_lines_re.finditer(val):
line, n = wrap_re.subn('', match.group())
log_line = match.group()
# It's possible that the final line of the vobject doesn't
# have a line ending. For ease of parsing, just add it.
# This should really be in an 'if not strict' branch.
if log_line[-1:] not in "\r\n":
log_line += "\r\n"
line, n = wrap_re.subn('', log_line)
if line != '':
yield line, lineNumber
lineNumber += n
Expand Down
Loading