kopia lustrzana https://github.com/collective/icalendar
Drop support for Python 2.6 and 3.3
I would humbly like to suggest icalendar drop support for Python 2.6. The last release of Python 2.6 was 2013-10-29. It is no longer receiving security or bug fixes. https://www.python.org/dev/peps/pep-0361/ The pip project itself has decided to drop support for 2.6. At the beginning of the year, their numbers estimated that Python 2.6 accounts for ~2% of their downloads. https://github.com/pypa/pip/pull/4343 For projects that still use Python 2.6, they can continue to pip install an older version. I've tried my best to remove as much 2.6 specific code as I can, including the 'Programming Language :: Python :: 2.6' trove classifier from setup.py. I've also removed Travis CI testing, which should result in slightly faster testing and fewer wasted resources. Changed: * Update documented Python support and trove classifiers * Update Travis test matrix and tox test matrix * Use set literals (and more literals in general) * Use dict comprehension * Remove dependencies on ordereddict and unittest2 * Remove u string prefix, use more modern unicode literals insteadpull/246/head
rodzic
5feee9bac5
commit
80f2c308c6
17
.travis.yml
17
.travis.yml
|
@ -1,16 +1,11 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "pypy"
|
||||
- "pypy3"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: "pypy3"
|
||||
- 2.7
|
||||
- 3.4
|
||||
- 3.5
|
||||
- 3.6
|
||||
- pypy
|
||||
- pypy3
|
||||
install:
|
||||
- pip install tox
|
||||
script:
|
||||
|
|
|
@ -4,7 +4,9 @@ Changelog
|
|||
3.12.1 (unreleased)
|
||||
-------------------
|
||||
|
||||
- Nothing changed yet.
|
||||
Breaking changes:
|
||||
|
||||
- Drop support for Python 2.6 and 3.3.
|
||||
|
||||
|
||||
3.12 (2017-11-07)
|
||||
|
|
|
@ -11,7 +11,7 @@ with Python.
|
|||
:Code: https://github.com/collective/icalendar
|
||||
:Mailing list: https://github.com/collective/icalendar/issues
|
||||
:Dependencies: `python-dateutil`_ and `pytz`_.
|
||||
:Compatible with: Python 2.6, 2.7 and 3.3+
|
||||
:Compatible with: Python 2.7 and 3.4+
|
||||
:License: `BSD`_
|
||||
|
||||
----
|
||||
|
|
|
@ -88,7 +88,7 @@ if not options.allow_site_packages:
|
|||
for sitepackage_path in site.getsitepackages():
|
||||
sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
|
||||
|
||||
setup_args = dict(to_dir=tmpeggs, download_delay=0)
|
||||
setup_args = {'to_dir': tmpeggs, 'download_delay': 0}
|
||||
ez['use_setuptools'](**setup_args)
|
||||
import setuptools
|
||||
import pkg_resources
|
||||
|
|
27
setup.py
27
setup.py
|
@ -1,7 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import codecs
|
||||
import setuptools
|
||||
import sys
|
||||
import re
|
||||
import ast
|
||||
|
||||
|
@ -25,12 +24,6 @@ install_requires = [
|
|||
'pytz',
|
||||
]
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
# Python unittest2 only needed for Python 2.6
|
||||
tests_require.append('unittest2')
|
||||
# OrderedDict was added in 2.7
|
||||
install_requires.append('ordereddict')
|
||||
|
||||
|
||||
setuptools.setup(
|
||||
name='icalendar',
|
||||
|
@ -40,19 +33,17 @@ setuptools.setup(
|
|||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
],
|
||||
keywords='calendar calendaring ical icalendar event todo journal '
|
||||
'recurring',
|
||||
|
|
|
@ -538,8 +538,7 @@ class Timezone(Component):
|
|||
if 'RRULE' in component:
|
||||
rrulestr = component['RRULE'].to_ical().decode('utf-8')
|
||||
rrule = dateutil.rrule.rrulestr(rrulestr, dtstart=dtstart)
|
||||
if not set(['UNTIL', 'COUNT']).intersection(
|
||||
component['RRULE'].keys()):
|
||||
if not {'UNTIL', 'COUNT'}.intersection(component['RRULE'].keys()):
|
||||
# pytz.timezones don't know any transition dates after 2038
|
||||
# either
|
||||
rrule._until = datetime(2038, 12, 31)
|
||||
|
|
|
@ -2,17 +2,14 @@
|
|||
from icalendar.compat import iteritems
|
||||
from icalendar.parser_tools import to_unicode
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from ordereddict import OrderedDict
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
def canonsort_keys(keys, canonical_order=None):
|
||||
"""Sorts leading keys according to canonical_order. Keys not specified in
|
||||
canonical_order will appear alphabetically at the end.
|
||||
"""
|
||||
canonical_map = dict((k, i) for i, k in enumerate(canonical_order or []))
|
||||
canonical_map = {k: i for i, k in enumerate(canonical_order or [])}
|
||||
head = [k for k in keys if k in canonical_map]
|
||||
tail = [k for k in keys if k not in canonical_map]
|
||||
return sorted(head, key=lambda k: canonical_map[k]) + sorted(tail)
|
||||
|
|
|
@ -6,6 +6,8 @@ Eg. RFC 2426 (vCard)
|
|||
It is stupid in the sense that it treats the content purely as strings. No type
|
||||
conversion is attempted.
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from icalendar import compat
|
||||
from icalendar.caselessdict import CaselessDict
|
||||
from icalendar.parser_tools import DEFAULT_ENCODING
|
||||
|
@ -32,12 +34,12 @@ def unescape_char(text):
|
|||
assert isinstance(text, (compat.unicode_type, compat.bytes_type))
|
||||
# NOTE: ORDER MATTERS!
|
||||
if isinstance(text, compat.unicode_type):
|
||||
return text.replace(u'\\N', u'\\n')\
|
||||
.replace(u'\r\n', u'\n')\
|
||||
.replace(u'\\n', u'\n')\
|
||||
.replace(u'\\,', u',')\
|
||||
.replace(u'\\;', u';')\
|
||||
.replace(u'\\\\', u'\\')
|
||||
return text.replace('\\N', '\\n')\
|
||||
.replace('\r\n', '\n')\
|
||||
.replace('\\n', '\n')\
|
||||
.replace('\\,', ',')\
|
||||
.replace('\\;', ';')\
|
||||
.replace('\\\\', '\\')
|
||||
elif isinstance(text, compat.bytes_type):
|
||||
return text.replace(b'\\N', b'\\n')\
|
||||
.replace(b'\r\n', b'\n')\
|
||||
|
@ -60,7 +62,7 @@ def tzid_from_dt(dt):
|
|||
return tzid
|
||||
|
||||
|
||||
def foldline(line, limit=75, fold_sep=u'\r\n '):
|
||||
def foldline(line, limit=75, fold_sep='\r\n '):
|
||||
"""Make a string folded as defined in RFC5545
|
||||
Lines of text SHOULD NOT be longer than 75 octets, excluding the line
|
||||
break. Long content lines SHOULD be split into a multiple line
|
||||
|
@ -70,7 +72,7 @@ def foldline(line, limit=75, fold_sep=u'\r\n '):
|
|||
SPACE or HTAB).
|
||||
"""
|
||||
assert isinstance(line, compat.unicode_type)
|
||||
assert u'\n' not in line
|
||||
assert '\n' not in line
|
||||
|
||||
# Use a fast and simple variant for the common case that line is all ASCII.
|
||||
try:
|
||||
|
@ -92,7 +94,7 @@ def foldline(line, limit=75, fold_sep=u'\r\n '):
|
|||
byte_count = char_byte_len
|
||||
ret_chars.append(char)
|
||||
|
||||
return u''.join(ret_chars)
|
||||
return ''.join(ret_chars)
|
||||
|
||||
|
||||
#################################################################
|
||||
|
@ -115,7 +117,7 @@ NAME = re.compile(r'[\w.-]+')
|
|||
UNSAFE_CHAR = re.compile('[\x00-\x08\x0a-\x1f\x7F",:;]')
|
||||
QUNSAFE_CHAR = re.compile('[\x00-\x08\x0a-\x1f\x7F"]')
|
||||
FOLD = re.compile(b'(\r?\n)+[ \t]')
|
||||
uFOLD = re.compile(u'(\r?\n)+[ \t]')
|
||||
uFOLD = re.compile('(\r?\n)+[ \t]')
|
||||
NEWLINE = re.compile(r'\r?\n')
|
||||
|
||||
|
||||
|
@ -289,7 +291,7 @@ class Contentline(compat.unicode_type):
|
|||
"""
|
||||
def __new__(cls, value, strict=False, encoding=DEFAULT_ENCODING):
|
||||
value = to_unicode(value, encoding=encoding)
|
||||
assert u'\n' not in value, ('Content line can not contain unescaped '
|
||||
assert '\n' not in value, ('Content line can not contain unescaped '
|
||||
'new line characters.')
|
||||
self = super(Contentline, cls).__new__(cls, value)
|
||||
self.strict = strict
|
||||
|
@ -313,8 +315,8 @@ class Contentline(compat.unicode_type):
|
|||
values = to_unicode(values)
|
||||
if params:
|
||||
params = to_unicode(params.to_ical(sorted=sorted))
|
||||
return cls(u'%s;%s:%s' % (name, params, values))
|
||||
return cls(u'%s:%s' % (name, values))
|
||||
return cls('%s;%s:%s' % (name, params, values))
|
||||
return cls('%s:%s' % (name, values))
|
||||
|
||||
def parts(self):
|
||||
"""Split the content line up into (name, parameters, values) parts.
|
||||
|
@ -348,7 +350,7 @@ class Contentline(compat.unicode_type):
|
|||
return (name, params, values)
|
||||
except ValueError as exc:
|
||||
raise ValueError(
|
||||
u"Content line could not be parsed into parts: '%s': %s"
|
||||
"Content line could not be parsed into parts: '%s': %s"
|
||||
% (self, exc)
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# unittest/unittest2 importer
|
||||
import unittest
|
||||
if not hasattr(unittest.TestCase, 'assertIsNotNone'):
|
||||
import unittest2 as unittest
|
||||
unittest # pep 8
|
|
@ -4,7 +4,7 @@ from hypothesis import given, settings
|
|||
import hypothesis.strategies as st
|
||||
|
||||
from icalendar.parser import Contentline, Contentlines, Parameters
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
|
||||
def printable_characters(**kw):
|
||||
|
@ -15,7 +15,7 @@ def printable_characters(**kw):
|
|||
)
|
||||
|
||||
key = st.text(string.ascii_letters + string.digits, min_size=1)
|
||||
value = printable_characters(blacklist_characters=u'\\;:\"')
|
||||
value = printable_characters(blacklist_characters='\\;:\"')
|
||||
|
||||
|
||||
class TestFuzzing(unittest.TestCase):
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar.tests import unittest
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
import icalendar
|
||||
|
@ -16,28 +18,28 @@ class TestEncoding(unittest.TestCase):
|
|||
cal = icalendar.Calendar.from_ical(data)
|
||||
|
||||
self.assertEqual(cal['prodid'].to_ical().decode('utf-8'),
|
||||
u"-//Plönë.org//NONSGML plone.app.event//EN")
|
||||
"-//Plönë.org//NONSGML plone.app.event//EN")
|
||||
self.assertEqual(cal['X-WR-CALDESC'].to_ical().decode('utf-8'),
|
||||
u"test non ascii: äöü ÄÖÜ €")
|
||||
"test non ascii: äöü ÄÖÜ €")
|
||||
|
||||
event = cal.walk('VEVENT')[0]
|
||||
self.assertEqual(event['SUMMARY'].to_ical().decode('utf-8'),
|
||||
u'Non-ASCII Test: ÄÖÜ äöü €')
|
||||
'Non-ASCII Test: ÄÖÜ äöü €')
|
||||
self.assertEqual(
|
||||
event['DESCRIPTION'].to_ical().decode('utf-8'),
|
||||
u'icalendar should be able to handle non-ascii: €äüöÄÜÖ.'
|
||||
'icalendar should be able to handle non-ascii: €äüöÄÜÖ.'
|
||||
)
|
||||
self.assertEqual(event['LOCATION'].to_ical().decode('utf-8'),
|
||||
u'Tribstrül')
|
||||
'Tribstrül')
|
||||
|
||||
def test_create_to_ical(self):
|
||||
cal = icalendar.Calendar()
|
||||
|
||||
cal.add('prodid', u"-//Plönë.org//NONSGML plone.app.event//EN")
|
||||
cal.add('version', u"2.0")
|
||||
cal.add('x-wr-calname', u"äöü ÄÖÜ €")
|
||||
cal.add('x-wr-caldesc', u"test non ascii: äöü ÄÖÜ €")
|
||||
cal.add('x-wr-relcalid', u"12345")
|
||||
cal.add('prodid', "-//Plönë.org//NONSGML plone.app.event//EN")
|
||||
cal.add('version', "2.0")
|
||||
cal.add('x-wr-calname', "äöü ÄÖÜ €")
|
||||
cal.add('x-wr-caldesc', "test non ascii: äöü ÄÖÜ €")
|
||||
cal.add('x-wr-relcalid', "12345")
|
||||
|
||||
event = icalendar.Event()
|
||||
event.add(
|
||||
|
@ -52,13 +54,13 @@ class TestEncoding(unittest.TestCase):
|
|||
'created',
|
||||
pytz.utc.localize(datetime.datetime(2010, 10, 10, 0, 0, 0))
|
||||
)
|
||||
event.add('uid', u'123456')
|
||||
event.add('summary', u'Non-ASCII Test: ÄÖÜ äöü €')
|
||||
event.add('uid', '123456')
|
||||
event.add('summary', 'Non-ASCII Test: ÄÖÜ äöü €')
|
||||
event.add(
|
||||
'description',
|
||||
u'icalendar should be able to de/serialize non-ascii.'
|
||||
'icalendar should be able to de/serialize non-ascii.'
|
||||
)
|
||||
event.add('location', u'Tribstrül')
|
||||
event.add('location', 'Tribstrül')
|
||||
cal.add_component(event)
|
||||
|
||||
ical_lines = cal.to_ical().splitlines()
|
||||
|
@ -71,7 +73,7 @@ class TestEncoding(unittest.TestCase):
|
|||
"dtstart",
|
||||
pytz.utc.localize(datetime.datetime(2010, 10, 10, 0, 0, 0))
|
||||
)
|
||||
event.add("summary", u"åäö")
|
||||
event.add("summary", "åäö")
|
||||
out = event.to_ical()
|
||||
summary = b'SUMMARY:\xc3\xa5\xc3\xa4\xc3\xb6'
|
||||
self.assertTrue(summary in out.splitlines())
|
||||
|
@ -80,7 +82,7 @@ class TestEncoding(unittest.TestCase):
|
|||
# Test for issue #80
|
||||
cal = icalendar.Calendar()
|
||||
event = icalendar.Event()
|
||||
event.add(u'DESCRIPTION', u'äöüßÄÖÜ')
|
||||
event.add('DESCRIPTION', 'äöüßÄÖÜ')
|
||||
cal.add_component(event)
|
||||
c = cal.to_ical()
|
||||
self.assertEqual(
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from icalendar.parser_tools import to_unicode
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
import icalendar
|
||||
|
@ -82,7 +84,7 @@ END:VTIMEZONE"""
|
|||
# Non-unicode characters
|
||||
event = icalendar.Event()
|
||||
event.add("dtstart", datetime.datetime(2012, 9, 3, 0, 0, 0))
|
||||
event.add("summary", u"abcdef")
|
||||
event.add("summary", "abcdef")
|
||||
self.assertEqual(
|
||||
event.to_ical(),
|
||||
b"BEGIN:VEVENT\r\nSUMMARY:abcdef\r\nDTSTART;VALUE=DATE-TIME:"
|
||||
|
@ -92,7 +94,7 @@ END:VTIMEZONE"""
|
|||
# Unicode characters
|
||||
event = icalendar.Event()
|
||||
event.add("dtstart", datetime.datetime(2012, 9, 3, 0, 0, 0))
|
||||
event.add("summary", u"åäö")
|
||||
event.add("summary", "åäö")
|
||||
self.assertEqual(
|
||||
event.to_ical(),
|
||||
b"BEGIN:VEVENT\r\nSUMMARY:\xc3\xa5\xc3\xa4\xc3\xb6\r\n"
|
||||
|
@ -178,7 +180,7 @@ END:VCALENDAR"""
|
|||
|
||||
cal = icalendar.Calendar.from_ical(ical_str)
|
||||
org_cn = cal.walk('VEVENT')[0]['ORGANIZER'].params['CN']
|
||||
self.assertEqual(org_cn, u'acme, ädmin')
|
||||
self.assertEqual(org_cn, 'acme, ädmin')
|
||||
|
||||
def test_issue_104__ignore_exceptions(self):
|
||||
"""
|
||||
|
@ -295,7 +297,7 @@ END:VCALENDAR"""
|
|||
|
||||
self.assertEqual(
|
||||
ctl.parts(),
|
||||
(u'TEL', Parameters({'TYPE': ['HOME', 'VOICE']}), u'000000000'),
|
||||
('TEL', Parameters({'TYPE': ['HOME', 'VOICE']}), '000000000'),
|
||||
)
|
||||
|
||||
def test_issue_143(self):
|
||||
|
@ -308,17 +310,17 @@ END:VCALENDAR"""
|
|||
ctl = Contentline.from_ical("ITEMADRNULLTHISISTHEADRESS08158SOMECITY12345.ADR:;;This is the Adress 08; Some City;;12345;Germany") # nopep8
|
||||
self.assertEqual(
|
||||
ctl.parts(),
|
||||
(u'ITEMADRNULLTHISISTHEADRESS08158SOMECITY12345.ADR',
|
||||
('ITEMADRNULLTHISISTHEADRESS08158SOMECITY12345.ADR',
|
||||
Parameters(),
|
||||
u';;This is the Adress 08; Some City;;12345;Germany'),
|
||||
';;This is the Adress 08; Some City;;12345;Germany'),
|
||||
)
|
||||
|
||||
ctl2 = Contentline.from_ical("ITEMADRNULLTHISISTHEADRESS08158SOMECITY12345.X-ABLABEL:") # nopep8
|
||||
self.assertEqual(
|
||||
ctl2.parts(),
|
||||
(u'ITEMADRNULLTHISISTHEADRESS08158SOMECITY12345.X-ABLABEL',
|
||||
('ITEMADRNULLTHISISTHEADRESS08158SOMECITY12345.X-ABLABEL',
|
||||
Parameters(),
|
||||
u''),
|
||||
''),
|
||||
)
|
||||
|
||||
def test_issue_157(self):
|
||||
|
@ -436,32 +438,32 @@ END:VCALENDAR"""
|
|||
def test_issue_237(self):
|
||||
"""Issue #237 - Fail to parse timezone with non-ascii TZID"""
|
||||
|
||||
ical_str = [u'BEGIN:VCALENDAR',
|
||||
u'BEGIN:VTIMEZONE',
|
||||
u'TZID:(UTC-03:00) Brasília',
|
||||
u'BEGIN:STANDARD',
|
||||
u'TZNAME:Brasília standard',
|
||||
u'DTSTART:16010101T235959',
|
||||
u'TZOFFSETFROM:-0200',
|
||||
u'TZOFFSETTO:-0300',
|
||||
u'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=3SA;BYMONTH=2',
|
||||
u'END:STANDARD',
|
||||
u'BEGIN:DAYLIGHT',
|
||||
u'TZNAME:Brasília daylight',
|
||||
u'DTSTART:16010101T235959',
|
||||
u'TZOFFSETFROM:-0300',
|
||||
u'TZOFFSETTO:-0200',
|
||||
u'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SA;BYMONTH=10',
|
||||
u'END:DAYLIGHT',
|
||||
u'END:VTIMEZONE',
|
||||
u'BEGIN:VEVENT',
|
||||
u'DTSTART;TZID=\"(UTC-03:00) Brasília\":20170511T133000',
|
||||
u'DTEND;TZID=\"(UTC-03:00) Brasília\":20170511T140000',
|
||||
u'END:VEVENT',
|
||||
u'END:VCALENDAR',
|
||||
ical_str = ['BEGIN:VCALENDAR',
|
||||
'BEGIN:VTIMEZONE',
|
||||
'TZID:(UTC-03:00) Brasília',
|
||||
'BEGIN:STANDARD',
|
||||
'TZNAME:Brasília standard',
|
||||
'DTSTART:16010101T235959',
|
||||
'TZOFFSETFROM:-0200',
|
||||
'TZOFFSETTO:-0300',
|
||||
'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=3SA;BYMONTH=2',
|
||||
'END:STANDARD',
|
||||
'BEGIN:DAYLIGHT',
|
||||
'TZNAME:Brasília daylight',
|
||||
'DTSTART:16010101T235959',
|
||||
'TZOFFSETFROM:-0300',
|
||||
'TZOFFSETTO:-0200',
|
||||
'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SA;BYMONTH=10',
|
||||
'END:DAYLIGHT',
|
||||
'END:VTIMEZONE',
|
||||
'BEGIN:VEVENT',
|
||||
'DTSTART;TZID=\"(UTC-03:00) Brasília\":20170511T133000',
|
||||
'DTEND;TZID=\"(UTC-03:00) Brasília\":20170511T140000',
|
||||
'END:VEVENT',
|
||||
'END:VCALENDAR',
|
||||
]
|
||||
|
||||
cal = icalendar.Calendar.from_ical(u'\r\n'.join(ical_str))
|
||||
cal = icalendar.Calendar.from_ical('\r\n'.join(ical_str))
|
||||
self.assertEqual(cal.errors, [])
|
||||
|
||||
dtstart = cal.walk(name='VEVENT')[0].decoded("DTSTART")
|
||||
|
@ -469,10 +471,10 @@ END:VCALENDAR"""
|
|||
self.assertEqual(dtstart, expected)
|
||||
|
||||
try:
|
||||
expected_zone = str(u'(UTC-03:00) Brasília')
|
||||
expected_tzname = str(u'Brasília standard')
|
||||
expected_zone = str('(UTC-03:00) Brasília')
|
||||
expected_tzname = str('Brasília standard')
|
||||
except UnicodeEncodeError:
|
||||
expected_zone = u'(UTC-03:00) Brasília'.encode('ascii', 'replace')
|
||||
expected_tzname = u'Brasília standard'.encode('ascii', 'replace')
|
||||
expected_zone = '(UTC-03:00) Brasília'.encode('ascii', 'replace')
|
||||
expected_tzname = 'Brasília standard'.encode('ascii', 'replace')
|
||||
self.assertEqual(dtstart.tzinfo.zone, expected_zone)
|
||||
self.assertEqual(dtstart.tzname(), expected_tzname)
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import icalendar
|
||||
import os
|
||||
import textwrap
|
||||
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
|
||||
class IcalendarTestCase (unittest.TestCase):
|
||||
|
@ -143,14 +145,14 @@ class IcalendarTestCase (unittest.TestCase):
|
|||
parts = ('SUMMARY', Parameters(), vText('INternational char æ ø å'))
|
||||
self.assertEqual(
|
||||
Contentline.from_parts(*parts),
|
||||
u'SUMMARY:INternational char æ ø å'
|
||||
'SUMMARY:INternational char æ ø å'
|
||||
)
|
||||
|
||||
# A value can also be unicode
|
||||
parts = ('SUMMARY', Parameters(), vText(u'INternational char æ ø å'))
|
||||
parts = ('SUMMARY', Parameters(), vText('INternational char æ ø å'))
|
||||
self.assertEqual(
|
||||
Contentline.from_parts(*parts),
|
||||
u'SUMMARY:INternational char æ ø å'
|
||||
'SUMMARY:INternational char æ ø å'
|
||||
)
|
||||
|
||||
# Traversing could look like this.
|
||||
|
@ -226,7 +228,7 @@ class IcalendarTestCase (unittest.TestCase):
|
|||
'X-APPLE-RADIUS': '328.7978217977285',
|
||||
'X-ADDRESS': 'Kaiserliche Hofburg, 1010 Wien',
|
||||
'X-APPLE-REFERENCEFRAME': '1',
|
||||
'X-TITLE': u'HELDENPLATZ',
|
||||
'X-TITLE': 'HELDENPLATZ',
|
||||
'X-APPLE-MAPKIT-HANDLE':
|
||||
'CAESXQEZGR3QZXJYZWLJAA==',
|
||||
'VALUE': 'URI',
|
||||
|
@ -238,30 +240,30 @@ class IcalendarTestCase (unittest.TestCase):
|
|||
def test_fold_line(self):
|
||||
from ..parser import foldline
|
||||
|
||||
self.assertEqual(foldline(u'foo'), u'foo')
|
||||
self.assertEqual(foldline('foo'), 'foo')
|
||||
self.assertEqual(
|
||||
foldline(u"Lorem ipsum dolor sit amet, consectetur adipiscing "
|
||||
u"elit. Vestibulum convallis imperdiet dui posuere."),
|
||||
(u'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
|
||||
u'Vestibulum conval\r\n lis imperdiet dui posuere.')
|
||||
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.')
|
||||
)
|
||||
|
||||
# I don't really get this test
|
||||
# at least just but bytes in there
|
||||
# porting it to "run" under python 2 & 3 makes it not much better
|
||||
with self.assertRaises(AssertionError):
|
||||
foldline(u'привет'.encode('utf-8'), limit=3)
|
||||
foldline('привет'.encode('utf-8'), limit=3)
|
||||
|
||||
self.assertEqual(foldline(u'foobar', limit=4), u'foo\r\n bar')
|
||||
self.assertEqual(foldline('foobar', limit=4), 'foo\r\n bar')
|
||||
self.assertEqual(
|
||||
foldline(u'Lorem ipsum dolor sit amet, consectetur adipiscing elit'
|
||||
u'. Vestibulum convallis imperdiet dui posuere.'),
|
||||
(u'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
u' Vestibulum conval\r\n lis imperdiet dui posuere.')
|
||||
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(u'DESCRIPTION:АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ'),
|
||||
u'DESCRIPTION:АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭ\r\n ЮЯ'
|
||||
foldline('DESCRIPTION:АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ'),
|
||||
'DESCRIPTION:АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭ\r\n ЮЯ'
|
||||
)
|
||||
|
||||
def test_value_double_quoting(self):
|
||||
|
@ -307,7 +309,7 @@ class TestEncoding(unittest.TestCase):
|
|||
for event in cal.walk('vevent'):
|
||||
self.assertEqual(len(event.errors), 1, 'Not the right amount of errors.')
|
||||
error = event.errors[0][1]
|
||||
self.assertTrue(error.startswith(u'Content line could not be parsed into parts'))
|
||||
self.assertTrue(error.startswith('Content line could not be parsed into parts'))
|
||||
|
||||
def test_apple_xlocation(self):
|
||||
"""
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar import Calendar
|
||||
from icalendar.prop import vText
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import os
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from icalendar import Calendar
|
||||
from icalendar import Event
|
||||
from icalendar import Parameters
|
||||
from icalendar import vCalAddress
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import icalendar
|
||||
import re
|
||||
|
@ -38,9 +40,9 @@ class TestPropertyParams(unittest.TestCase):
|
|||
vevent['ORGANIZER'] = cal_address
|
||||
self.assertEqual(
|
||||
vevent.to_ical().decode('utf-8'),
|
||||
u'BEGIN:VEVENT\r\n'
|
||||
u'ORGANIZER;CN="Джон Доу":mailto:john.doe@example.org\r\n'
|
||||
u'END:VEVENT\r\n'
|
||||
'BEGIN:VEVENT\r\n'
|
||||
'ORGANIZER;CN="Джон Доу":mailto:john.doe@example.org\r\n'
|
||||
'END:VEVENT\r\n'
|
||||
)
|
||||
|
||||
self.assertEqual(vevent['ORGANIZER'].params['CN'],
|
||||
|
@ -48,14 +50,14 @@ class TestPropertyParams(unittest.TestCase):
|
|||
|
||||
def test_quoting(self):
|
||||
# not double-quoted
|
||||
self._test_quoting(u"Aramis", u'Aramis')
|
||||
self._test_quoting("Aramis", 'Aramis')
|
||||
# if a space is present - enclose in double quotes
|
||||
self._test_quoting(u"Aramis Alameda", u'"Aramis Alameda"')
|
||||
self._test_quoting("Aramis Alameda", '"Aramis Alameda"')
|
||||
# a single quote in parameter value - double quote the value
|
||||
self._test_quoting(u"Aramis d'Alameda", u'"Aramis d\'Alameda"')
|
||||
self._test_quoting("Aramis d'Alameda", '"Aramis d\'Alameda"')
|
||||
# double quote is replaced with single quote
|
||||
self._test_quoting(u"Aramis d\"Alameda", u'"Aramis d\'Alameda"')
|
||||
self._test_quoting(u"Арамис д'Аламеда", u'"Арамис д\'Аламеда"')
|
||||
self._test_quoting("Aramis d\"Alameda", '"Aramis d\'Alameda"')
|
||||
self._test_quoting("Арамис д'Аламеда", '"Арамис д\'Аламеда"')
|
||||
|
||||
def _test_quoting(self, cn_param, cn_quoted):
|
||||
"""
|
||||
|
@ -74,14 +76,14 @@ class TestPropertyParams(unittest.TestCase):
|
|||
|
||||
def test_escaping(self):
|
||||
# verify that escaped non safe chars are decoded correctly
|
||||
NON_SAFE_CHARS = u',\\;:'
|
||||
NON_SAFE_CHARS = ',\\;:'
|
||||
for char in NON_SAFE_CHARS:
|
||||
cn_escaped = u"Society\\%s 2014" % char
|
||||
cn_decoded = u"Society%s 2014" % char
|
||||
cn_escaped = "Society\\%s 2014" % char
|
||||
cn_decoded = "Society%s 2014" % char
|
||||
vevent = Event.from_ical(
|
||||
u'BEGIN:VEVENT\r\n'
|
||||
u'ORGANIZER;CN=%s:that\r\n'
|
||||
u'END:VEVENT\r\n' % cn_escaped
|
||||
'BEGIN:VEVENT\r\n'
|
||||
'ORGANIZER;CN=%s:that\r\n'
|
||||
'END:VEVENT\r\n' % cn_escaped
|
||||
)
|
||||
self.assertEqual(vevent['ORGANIZER'].params['CN'], cn_decoded)
|
||||
|
||||
|
@ -97,7 +99,7 @@ class TestPropertyParams(unittest.TestCase):
|
|||
)
|
||||
self.assertEqual(
|
||||
vevent['ORGANIZER'].to_ical().decode('utf-8'),
|
||||
u'это, то; that\\ %th%%at%:'
|
||||
'это, то; that\\ %th%%at%:'
|
||||
)
|
||||
|
||||
def test_parameters_class(self):
|
||||
|
@ -205,12 +207,12 @@ END:VCALENDAR"""
|
|||
b'MAILTO:rembrand@xs4all.nl')
|
||||
self.assertEqual(event['attendee'][0].params.to_ical(),
|
||||
b'CN=RembrandXS;PARTSTAT=NEEDS-ACTION;RSVP=TRUE')
|
||||
self.assertEqual(event['attendee'][0].params['cn'], u'RembrandXS')
|
||||
self.assertEqual(event['attendee'][0].params['cn'], 'RembrandXS')
|
||||
|
||||
def test_repr(self):
|
||||
"""Test correct class representation.
|
||||
"""
|
||||
it = Parameters(parameter1='Value1')
|
||||
self.assertTrue(
|
||||
re.match(r"Parameters\({u?'PARAMETER1': 'Value1'}\)", str(it))
|
||||
re.match(r"Parameters\({u?'PARAMETER1': u?'Value1'}\)", str(it))
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar.caselessdict import CaselessDict
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
import icalendar
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
import icalendar
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar.tests import unittest
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
import datetime
|
||||
import dateutil.parser
|
||||
|
@ -50,12 +52,12 @@ class TestTimezoned(unittest.TestCase):
|
|||
def test_create_to_ical(self):
|
||||
cal = icalendar.Calendar()
|
||||
|
||||
cal.add('prodid', u"-//Plone.org//NONSGML plone.app.event//EN")
|
||||
cal.add('version', u"2.0")
|
||||
cal.add('x-wr-calname', u"test create calendar")
|
||||
cal.add('x-wr-caldesc', u"icalendar tests")
|
||||
cal.add('x-wr-relcalid', u"12345")
|
||||
cal.add('x-wr-timezone', u"Europe/Vienna")
|
||||
cal.add('prodid', "-//Plone.org//NONSGML plone.app.event//EN")
|
||||
cal.add('version', "2.0")
|
||||
cal.add('x-wr-calname', "test create calendar")
|
||||
cal.add('x-wr-caldesc', "icalendar tests")
|
||||
cal.add('x-wr-relcalid', "12345")
|
||||
cal.add('x-wr-timezone', "Europe/Vienna")
|
||||
|
||||
tzc = icalendar.Timezone()
|
||||
tzc.add('tzid', 'Europe/Vienna')
|
||||
|
@ -93,21 +95,21 @@ class TestTimezoned(unittest.TestCase):
|
|||
event.add(
|
||||
'created',
|
||||
tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10)))
|
||||
event.add('uid', u'123456')
|
||||
event.add('uid', '123456')
|
||||
event.add(
|
||||
'last-modified',
|
||||
tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10)))
|
||||
event.add('summary', u'artsprint 2012')
|
||||
# event.add('rrule', u'FREQ=YEARLY;INTERVAL=1;COUNT=10')
|
||||
event.add('description', u'sprinting at the artsprint')
|
||||
event.add('location', u'aka bild, wien')
|
||||
event.add('categories', u'first subject')
|
||||
event.add('categories', u'second subject')
|
||||
event.add('attendee', u'häns')
|
||||
event.add('attendee', u'franz')
|
||||
event.add('attendee', u'sepp')
|
||||
event.add('contact', u'Max Mustermann, 1010 Wien')
|
||||
event.add('url', u'http://plone.org')
|
||||
event.add('summary', 'artsprint 2012')
|
||||
# event.add('rrule', 'FREQ=YEARLY;INTERVAL=1;COUNT=10')
|
||||
event.add('description', 'sprinting at the artsprint')
|
||||
event.add('location', 'aka bild, wien')
|
||||
event.add('categories', 'first subject')
|
||||
event.add('categories', 'second subject')
|
||||
event.add('attendee', 'häns')
|
||||
event.add('attendee', 'franz')
|
||||
event.add('attendee', 'sepp')
|
||||
event.add('contact', 'Max Mustermann, 1010 Wien')
|
||||
event.add('url', 'http://plone.org')
|
||||
cal.add_component(event)
|
||||
|
||||
test_out = b'|'.join(cal.to_ical().splitlines())
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import icalendar
|
||||
import pytz
|
||||
|
@ -74,7 +76,7 @@ class TestCalComponent(unittest.TestCase):
|
|||
|
||||
# You can get the values back directly ...
|
||||
c.add('prodid', '-//my product//')
|
||||
self.assertEqual(c['prodid'], prop.vText(u'-//my product//'))
|
||||
self.assertEqual(c['prodid'], prop.vText('-//my product//'))
|
||||
|
||||
# ... or decoded to a python type
|
||||
self.assertEqual(c.decoded('prodid'), b'-//my product//')
|
||||
|
@ -156,7 +158,7 @@ class TestCalComponent(unittest.TestCase):
|
|||
# Text fields which span multiple mulitple lines require proper
|
||||
# indenting
|
||||
c = Calendar()
|
||||
c['description'] = u'Paragraph one\n\nParagraph two'
|
||||
c['description'] = 'Paragraph one\n\nParagraph two'
|
||||
self.assertEqual(
|
||||
c.to_ical(),
|
||||
b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two'
|
||||
|
@ -182,7 +184,7 @@ class TestCalComponent(unittest.TestCase):
|
|||
# set_inline() methods.
|
||||
self.assertEqual(
|
||||
c.get_inline('resources', decode=0),
|
||||
[u'Chair', u'Table', u'Room: 42']
|
||||
['Chair', 'Table', 'Room: 42']
|
||||
)
|
||||
|
||||
# These can also be decoded
|
||||
|
@ -247,7 +249,7 @@ class TestCalComponent(unittest.TestCase):
|
|||
binary = prop.vBinary('us')
|
||||
comp.add('ATTACH', binary)
|
||||
|
||||
self.assertEqual(comp['ATTACH'], [u'me', 'you', binary])
|
||||
self.assertEqual(comp['ATTACH'], ['me', 'you', binary])
|
||||
|
||||
def test_cal_Component_add_property_parameter(self):
|
||||
# Test the for timezone correctness: dtstart should preserve it's
|
||||
|
@ -322,21 +324,21 @@ class TestCalComponent(unittest.TestCase):
|
|||
component['key1'] = 'value1'
|
||||
|
||||
self.assertTrue(
|
||||
re.match(r"Component\({u?'KEY1': 'value1'}\)", str(component))
|
||||
re.match(r"Component\({u?'KEY1': u?'value1'}\)", str(component))
|
||||
)
|
||||
|
||||
calendar = Calendar()
|
||||
calendar['key1'] = 'value1'
|
||||
|
||||
self.assertTrue(
|
||||
re.match(r"VCALENDAR\({u?'KEY1': 'value1'}\)", str(calendar))
|
||||
re.match(r"VCALENDAR\({u?'KEY1': u?'value1'}\)", str(calendar))
|
||||
)
|
||||
|
||||
event = Event()
|
||||
event['key1'] = 'value1'
|
||||
|
||||
self.assertTrue(
|
||||
re.match(r"VEVENT\({u?'KEY1': 'value1'}\)", str(event))
|
||||
re.match(r"VEVENT\({u?'KEY1': u?'value1'}\)", str(event))
|
||||
)
|
||||
|
||||
# Representation of nested Components
|
||||
|
@ -347,7 +349,10 @@ class TestCalComponent(unittest.TestCase):
|
|||
|
||||
self.assertTrue(
|
||||
re.match(
|
||||
r"Component\({u?'KEY1': 'VALUE1'}, Component\({u?'KEY1': 'value1'}\), VCALENDAR\({u?'KEY1': 'value1'}, VEVENT\({u?'KEY1': 'value1'}\)\)\)", # nopep8
|
||||
r"Component\({u?'KEY1': u?'VALUE1'}, "
|
||||
r"Component\({u?'KEY1': u?'value1'}\), "
|
||||
r"VCALENDAR\({u?'KEY1': u?'value1'}, "
|
||||
r"VEVENT\({u?'KEY1': u?'value1'}\)\)\)",
|
||||
str(nested)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
import icalendar
|
||||
|
||||
|
@ -41,9 +41,9 @@ class TestCaselessdict(unittest.TestCase):
|
|||
def test_caselessdict_canonsort_items(self):
|
||||
canonsort_items = icalendar.caselessdict.canonsort_items
|
||||
|
||||
d = dict(
|
||||
i=7, c='at', a=3.5, l=(2, 3), e=[4, 5], n=13, d={'x': 'y'}, r=1.0
|
||||
)
|
||||
d = {
|
||||
'i': 7, 'c': 'at', 'a': 3.5, 'l': (2, 3), 'e': [4, 5], 'n': 13, 'd': {'x': 'y'}, 'r': 1.0,
|
||||
}
|
||||
|
||||
out = canonsort_items(d)
|
||||
self.assertEqual(
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from icalendar.parser_tools import data_encode
|
||||
from icalendar.parser_tools import to_unicode
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
|
||||
|
||||
class TestParserTools(unittest.TestCase):
|
||||
|
||||
def test_parser_tools_to_unicode(self):
|
||||
|
||||
self.assertEqual(to_unicode('spam'), u'spam')
|
||||
self.assertEqual(to_unicode(u'spam'), u'spam')
|
||||
self.assertEqual(to_unicode(u'spam'.encode('utf-8')), u'spam')
|
||||
self.assertEqual(to_unicode(b'\xc6\xb5'), u'\u01b5')
|
||||
self.assertEqual(to_unicode(u'\xc6\xb5'.encode('iso-8859-1')),
|
||||
u'\u01b5')
|
||||
self.assertEqual(to_unicode(b'\xc6\xb5', encoding='ascii'), u'\u01b5')
|
||||
self.assertEqual(to_unicode(b'spam'), 'spam')
|
||||
self.assertEqual(to_unicode('spam'), 'spam')
|
||||
self.assertEqual(to_unicode('spam'.encode('utf-8')), 'spam')
|
||||
self.assertEqual(to_unicode(b'\xc6\xb5'), '\u01b5')
|
||||
self.assertEqual(to_unicode('\xc6\xb5'.encode('iso-8859-1')),
|
||||
'\u01b5')
|
||||
self.assertEqual(to_unicode(b'\xc6\xb5', encoding='ascii'), '\u01b5')
|
||||
self.assertEqual(to_unicode(1), 1)
|
||||
self.assertEqual(to_unicode(None), None)
|
||||
|
||||
def test_parser_tools_data_encode(self):
|
||||
|
||||
data1 = {
|
||||
u'k1': u'v1', 'k2': 'v2', u'k3': u'v3',
|
||||
'li1': ['it1', u'it2', {'k4': u'v4', u'k5': 'v5'}, 123]
|
||||
'k1': 'v1', 'k2': 'v2', 'k3': 'v3',
|
||||
'li1': ['it1', 'it2', {'k4': 'v4', 'k5': 'v5'}, 123]
|
||||
}
|
||||
res = {b'k3': b'v3', b'k2': b'v2', b'k1': b'v1',
|
||||
b'li1': [b'it1', b'it2', {b'k5': b'v5', b'k4': b'v4'}, 123]}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import date
|
||||
from datetime import datetime
|
||||
from datetime import time
|
||||
from datetime import timedelta
|
||||
from icalendar.parser import Parameters
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
from icalendar.prop import vDatetime
|
||||
from icalendar.windows_to_olson import WINDOWS_TO_OLSON
|
||||
|
||||
|
@ -333,7 +335,7 @@ class TestProp(unittest.TestCase):
|
|||
def test_prop_vText(self):
|
||||
from ..prop import vText
|
||||
|
||||
self.assertEqual(vText(u'Simple text').to_ical(), b'Simple text')
|
||||
self.assertEqual(vText('Simple text').to_ical(), b'Simple text')
|
||||
|
||||
# Escaped text
|
||||
t = vText('Text ; with escaped, chars')
|
||||
|
@ -345,13 +347,13 @@ class TestProp(unittest.TestCase):
|
|||
|
||||
# If you pass a unicode object, it will be utf-8 encoded. As this is
|
||||
# the (only) standard that RFC 2445 support.
|
||||
t = vText(u'international chars \xe4\xf6\xfc')
|
||||
t = vText('international chars \xe4\xf6\xfc')
|
||||
self.assertEqual(t.to_ical(),
|
||||
b'international chars \xc3\xa4\xc3\xb6\xc3\xbc')
|
||||
|
||||
# and parsing?
|
||||
self.assertEqual(vText.from_ical('Text \\; with escaped\\, chars'),
|
||||
u'Text ; with escaped, chars')
|
||||
'Text ; with escaped, chars')
|
||||
|
||||
t = vText.from_ical('A string with\\; some\\\\ characters in\\it')
|
||||
self.assertEqual(t, "A string with; some\\ characters in\\it")
|
||||
|
@ -359,7 +361,7 @@ class TestProp(unittest.TestCase):
|
|||
# We are forgiving to utf-8 encoding errors:
|
||||
# We intentionally use a string with unexpected encoding
|
||||
#
|
||||
self.assertEqual(vText.from_ical(b'Ol\xe9'), u'Ol\ufffd')
|
||||
self.assertEqual(vText.from_ical(b'Ol\xe9'), 'Ol\ufffd')
|
||||
|
||||
# Notice how accented E character, encoded with latin-1, got replaced
|
||||
# with the official U+FFFD REPLACEMENT CHARACTER.
|
||||
|
@ -466,15 +468,15 @@ class TestProp(unittest.TestCase):
|
|||
|
||||
# It can also be used to directly encode property and parameter values
|
||||
self.assertEqual(
|
||||
factory.to_ical('comment', u'by Rasmussen, Max M\xfcller'),
|
||||
factory.to_ical('comment', 'by Rasmussen, Max M\xfcller'),
|
||||
b'by Rasmussen\\, Max M\xc3\xbcller'
|
||||
)
|
||||
self.assertEqual(factory.to_ical('priority', 1), b'1')
|
||||
self.assertEqual(factory.to_ical('cn', u'Rasmussen, Max M\xfcller'),
|
||||
self.assertEqual(factory.to_ical('cn', 'Rasmussen, Max M\xfcller'),
|
||||
b'Rasmussen\\, Max M\xc3\xbcller')
|
||||
self.assertEqual(
|
||||
factory.from_ical('cn', b'Rasmussen\\, Max M\xc3\xb8ller'),
|
||||
u'Rasmussen, Max M\xf8ller'
|
||||
'Rasmussen, Max M\xf8ller'
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from icalendar.tests import unittest
|
||||
import unittest
|
||||
from icalendar.tools import UIDGenerator
|
||||
|
||||
|
||||
|
|
6
tox.ini
6
tox.ini
|
@ -1,15 +1,15 @@
|
|||
# to run for a specific environment, use ``tox -e ENVNAME``
|
||||
[tox]
|
||||
envlist = py26,py27,py33,py34,py35,py36
|
||||
envlist = py27,py34,py35,py36,pypy,pypy3
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
pytest
|
||||
coverage
|
||||
py{27,33,34,35,36}: hypothesis>=3.0
|
||||
py{27,34,35,36}: hypothesis>=3.0
|
||||
.[test]
|
||||
commands =
|
||||
coverage run --source=src/icalendar --omit=*/tests/* --module pytest []
|
||||
py{27,33,34,35,36}: coverage run --append --source=src/icalendar --omit=*/tests/* --module pytest [] src/icalendar/tests/hypothesis/
|
||||
py{27,34,35,36}: coverage run --append --source=src/icalendar --omit=*/tests/* --module pytest [] src/icalendar/tests/hypothesis/
|
||||
coverage report
|
||||
coverage html
|
||||
|
|
Ładowanie…
Reference in New Issue