Skip to content

Commit

Permalink
Merge pull request #246 from jdufresne/drop-py26
Browse files Browse the repository at this point in the history
Drop support for Python 2.6
  • Loading branch information
thet authored Nov 8, 2017
2 parents 5feee9b + 80f2c30 commit 2003b29
Show file tree
Hide file tree
Showing 24 changed files with 208 additions and 209 deletions.
17 changes: 6 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
4 changes: 3 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`_

----
Expand Down
2 changes: 1 addition & 1 deletion bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
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
Expand Down
27 changes: 9 additions & 18 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import codecs
import setuptools
import sys
import re
import ast

Expand All @@ -25,12 +24,6 @@
'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',
Expand All @@ -40,19 +33,17 @@
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',
Expand Down
3 changes: 1 addition & 2 deletions src/icalendar/cal.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,7 @@ def _extract_offsets(component, tzname):
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)
Expand Down
7 changes: 2 additions & 5 deletions src/icalendar/caselessdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 16 additions & 14 deletions src/icalendar/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
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
Expand All @@ -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')\
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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)


#################################################################
Expand All @@ -115,7 +117,7 @@ def param_value(value):
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')


Expand Down Expand Up @@ -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
Expand All @@ -313,8 +315,8 @@ def from_parts(cls, name, params, values, sorted=True):
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.
Expand Down Expand Up @@ -348,7 +350,7 @@ def parts(self):
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)
)

Expand Down
6 changes: 0 additions & 6 deletions src/icalendar/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 2 deletions src/icalendar/tests/hypothesis/test_fuzzing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import hypothesis.strategies as st

from icalendar.parser import Contentline, Contentlines, Parameters
from icalendar.tests import unittest
import unittest


def printable_characters(**kw):
Expand All @@ -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):
Expand Down
36 changes: 19 additions & 17 deletions src/icalendar/tests/test_encoding.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
from icalendar.tests import unittest
from __future__ import unicode_literals

import unittest

import datetime
import icalendar
Expand All @@ -16,28 +18,28 @@ def test_create_from_ical(self):
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(
Expand All @@ -52,13 +54,13 @@ def test_create_to_ical(self):
'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()
Expand All @@ -71,7 +73,7 @@ def test_create_event_simple(self):
"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())
Expand All @@ -80,7 +82,7 @@ def test_unicode_parameter_name(self):
# 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(
Expand Down
Loading

0 comments on commit 2003b29

Please sign in to comment.