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 instead
pull/246/head
Jon Dufresne 2017-10-22 14:07:19 -07:00
rodzic 5feee9bac5
commit 80f2c308c6
24 zmienionych plików z 208 dodań i 209 usunięć

Wyświetl plik

@ -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:

Wyświetl plik

@ -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)

Wyświetl plik

@ -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`_
----

Wyświetl plik

@ -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

Wyświetl plik

@ -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',

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)
)

Wyświetl plik

@ -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

Wyświetl plik

@ -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):

Wyświetl plik

@ -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(

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):
"""

Wyświetl plik

@ -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

Wyświetl plik

@ -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))
)

Wyświetl plik

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from icalendar.caselessdict import CaselessDict
from icalendar.tests import unittest
import unittest
import datetime
import icalendar

Wyświetl plik

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from icalendar.tests import unittest
import unittest
import datetime
import icalendar

Wyświetl plik

@ -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())

Wyświetl plik

@ -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)
)
)

Wyświetl plik

@ -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(

Wyświetl plik

@ -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]}

Wyświetl plik

@ -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'
)

Wyświetl plik

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from icalendar.tests import unittest
import unittest
from icalendar.tools import UIDGenerator

Wyświetl plik

@ -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