Returned old folding algorithm, as the current implementation fails in some cases (https://github.com/collective/icalendar/issues/72)

pull/73/merge^2
Victor Varvaryuk 2012-10-25 19:16:33 +04:00
rodzic c62acc3454
commit 7f4120da4c
2 zmienionych plików z 82 dodań i 55 usunięć

Wyświetl plik

@ -16,7 +16,7 @@ from icalendar.caselessdict import CaselessDict
SequenceTypes = [TupleType, ListType]
def foldline(text, lenght=75, newline='\r\n'):
def foldline(text, length=75, newline='\r\n'):
"""Make a string folded per RFC5545 (each line must be less than 75 octets)
>>> from icalendar.parser import foldline
@ -29,20 +29,52 @@ def foldline(text, lenght=75, newline='\r\n'):
... # doctest: +NORMALIZE_WHITESPACE
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum \\r\\n
convallis imperdiet dui posuere.'
# >>> uuu = u'alfdkadäääüüaskd'
# >>> foldline(uuu, length=3)
# u'alf\ndka\nd\xe4\xe4\n\xe4\xfc\xfc\nask\nd'
"""
return newline.join(
icalendar.tools.wrap(text, lenght,
subsequent_indent=' ',
drop_whitespace=False,
break_long_words=True,
replace_whitespace=False
)
)
assert isinstance(text, str)
# text.decode('utf-8') # try to decode, to be sure it's utf-8 or ASCII
l_line = len(text)
new_lines = []
start = 0
while True:
end = start + length - 1
chunk = text[start:end]
m = NEWLINE.search(chunk)
if m is not None and m.end() != l_line:
new_lines.append(text[start:start + m.start()])
start += m.end()
continue
if end >= l_line:
end = l_line
else:
# Check that we don't fold in the middle of a UTF-8 character:
# http://lists.osafoundation.org/pipermail/ietf-calsify/2006-August/001126.html
while True:
char_value = ord(text[end])
if char_value < 128 or char_value >= 192:
# This is not in the middle of a UTF-8 character, so we
# can fold here:
break
else:
end -= 1
# Recompute the chunk, since start or end may have changed.
chunk = text[start:end]
new_lines.append(chunk)
if end == l_line:
break # Done
start = end
return (newline + ' ').join(new_lines).rstrip(' ')
# return newline.join(
# icalendar.tools.wrap(text, length,
# subsequent_indent=' ',
# drop_whitespace=False,
# break_long_words=True,
# replace_whitespace=False
# )
# )
#################################################################
# Property parameter stuff
@ -341,7 +373,7 @@ class Contentline(str):
A value can also be unicode
>>> from icalendar.prop import vText
>>> parts = ('SUMMARY', Parameters(), vText(u'INternational char æ ø å'))
>>> parts = ('SUMMARY', Parameters(), vText(u'INternational char æ ø å'))
>>> Contentline.from_parts(parts)
'SUMMARY:INternational char \\xc3\\xa6 \\xc3\\xb8 \\xc3\\xa5'

Wyświetl plik

@ -1,5 +1,7 @@
#from interlude import interact
import unittest, doctest, os
# coding: utf-8
import unittest
import doctest
import os
from icalendar import (
cal,
caselessdict,
@ -9,45 +11,34 @@ from icalendar import (
OPTIONFLAGS = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
class FuckYouTests(unittest.TestCase):
def XtestBla(self):
from icalendar import Calendar
c = Calendar()
c['description']=u'Paragraph one\n\nParagraph two'
output = c.to_ical()
cmp = ("BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\r\n \r\n "
"Paragraph two\r\nEND:VCALENDAR\r\n")
self.assertEqual(output, cmp)
def XtestTrailingNewline(self):
from icalendar.parser import Contentlines, Contentline
c = Contentlines([Contentline('BEGIN:VEVENT\\r\\n')])
output = c.to_ical()
self.assertEqual(output, 'BEGIN:VEVENT\\r\\n')
class IcalendarTestCase (unittest.TestCase):
def XtestLongLine(self):
from icalendar.parser import Contentlines, Contentline
c = Contentlines([Contentline('BEGIN:VEVENT\\r\\n')])
c.append(Contentline(''.join(['123456789 ']*10)+'\\r\\n'))
output = c.to_ical()
cmp = ("BEGIN:VEVENT\\r\\n\\r\\n123456789 123456789 123456789 "
"123456789 123456789 123456789 123456789 1234\\r\\n 56789 "
"123456789 123456789 \\r\\n")
self.assertEqual(output, cmp)
def testHmm(self):
def test_long_lines(self):
from icalendar.parser import Contentlines, Contentline
c = Contentlines([Contentline('BEGIN:VEVENT\r\n')])
c.append(Contentline(''.join(['123456789 ']*10)+'\r\n'))
output = c.to_ical()
# XXX: sure? looks weird in conjunction with generated content above.
#cmp = ('BEGIN:VEVENT\r\n\r\n123456789 123456789 123456789 123456789 '
# '123456789 123456789 123456789 1234\r\n 56789 123456789 '
# '123456789 \r\n')
cmp = ('BEGIN:VEVENT\r\n\r\n123456789 123456789 123456789 123456789 '
'123456789 123456789 123456789 \r\n 123456789 123456789 '
'123456789 \r\n\r\n')
self.assertEqual(output, cmp)
c.append(Contentline(''.join('123456789 ' * 10) + '\r\n'))
self.assertEqual(
c.to_ical(),
'BEGIN:VEVENT\r\n\r\n123456789 123456789 123456789 123456789 '
'123456789 123456789 123456789 1234\r\n 56789 123456789 '
'123456789 \r\n\r\n'
)
def test_fold_line(self):
from icalendar.parser import foldline
self.assertRaises(AssertionError, foldline, u'привет', length=3)
self.assertEqual(foldline('foobar', length=4), 'foo\r\n bar')
self.assertEqual(
foldline('Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
' Vestibulum convallis imperdiet dui posuere.'),
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
' Vestibulum conval\r\n lis imperdiet dui posuere.'
)
self.assertEqual(
foldline('DESCRIPTION:АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ'),
'DESCRIPTION:АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭ\r\n ЮЯ'
)
def load_tests(loader=None, tests=None, pattern=None):
@ -60,7 +51,11 @@ def load_tests(loader=None, tests=None, pattern=None):
for docfile in ['example.txt', 'groupscheduled.txt',
'small.txt', 'multiple.txt', 'recurrence.txt']:
filename = os.path.abspath(os.path.join(current_dir, docfile))
suite.addTest(doctest.DocFileSuite(docfile,
optionflags=OPTIONFLAGS,
globs={'__file__': filename}))
suite.addTest(
doctest.DocFileSuite(
docfile,
optionflags=OPTIONFLAGS,
globs={'__file__': filename}
)
)
return suite