Skip to content

Commit 998da0e

Browse files
committed
Remove Python 2 compatibility code
- Remove from __future__ imports from all files - Simplify emails/compat: remove Python 2 branch, keep only Python 3 code - Delete unused ordereddict.py and orderedset.py - Remove is_py2/is_py3/is_py26/is_py34_plus version checks - Remove Travis CI pypy workaround from test_loaders - All 74 tests pass on Python 3.14
1 parent f7c3582 commit 998da0e

37 files changed

Lines changed: 53 additions & 566 deletions

emails/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
3636
"""
3737

38-
from __future__ import unicode_literals
3938

4039
__title__ = 'emails'
4140
__version__ = '0.6'

emails/backend/inmemory/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# encoding: utf-8
2-
from __future__ import unicode_literals
32

43
__all__ = ['InMemoryBackend', ]
54

emails/backend/smtp/backend.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# encoding: utf-8
2-
from __future__ import unicode_literals
32
import smtplib
43
import logging
54
from functools import wraps

emails/backend/smtp/exceptions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# encoding: utf-8
2-
from __future__ import unicode_literals
32
import socket
43

54

emails/compat/__init__.py

Lines changed: 43 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,185 +1,59 @@
11
# -*- coding: utf-8 -*-
2-
from __future__ import unicode_literals
3-
"""
4-
pythoncompat
5-
"""
6-
7-
from .orderedset import OrderedSet
8-
9-
#from . import _urlparse as urlparse
10-
11-
122
import sys
3+
import urllib.parse as urlparse
4+
from collections import OrderedDict
5+
from collections.abc import Callable
6+
from io import StringIO, BytesIO
137

14-
# -------
15-
# Pythons
16-
# -------
17-
18-
# Syntax sugar.
19-
_ver = sys.version_info
20-
21-
#: Python 2.x?
22-
is_py2 = (_ver[0] == 2)
23-
24-
#: Python 3.x?
25-
is_py3 = (_ver[0] == 3)
26-
27-
#: Python 3.0.x
28-
is_py30 = (is_py3 and _ver[1] == 0)
29-
30-
#: Python 3.1.x
31-
is_py31 = (is_py3 and _ver[1] == 1)
32-
33-
#: Python 3.2.x
34-
is_py32 = (is_py3 and _ver[1] == 2)
35-
36-
#: Python 3.3.x
37-
is_py33 = (is_py3 and _ver[1] == 3)
38-
39-
#: Python 3.4.x
40-
is_py34 = (is_py3 and _ver[1] == 4)
41-
is_py34_plus = (is_py3 and _ver[1] >= 4)
42-
43-
#: Python 2.7.x
44-
is_py27 = (is_py2 and _ver[1] == 7)
45-
46-
#: Python 2.6.x
47-
is_py26 = (is_py2 and _ver[1] == 6)
48-
49-
#: Python 2.5.x
50-
is_py25 = (is_py2 and _ver[1] == 5)
51-
52-
#: Python 2.4.x
53-
is_py24 = (is_py2 and _ver[1] == 4)
54-
55-
56-
# ---------
57-
# Platforms
58-
# ---------
59-
60-
61-
# Syntax sugar.
62-
_ver = sys.version.lower()
63-
64-
is_pypy = ('pypy' in _ver)
65-
is_jython = ('jython' in _ver)
66-
is_ironpython = ('iron' in _ver)
67-
68-
# Assume CPython, if nothing else.
69-
is_cpython = not any((is_pypy, is_jython, is_ironpython))
70-
71-
# Windows-based system.
72-
is_windows = 'win32' in str(sys.platform).lower()
73-
74-
# Standard Linux 2+ system.
75-
is_linux = ('linux' in str(sys.platform).lower())
76-
is_osx = ('darwin' in str(sys.platform).lower())
77-
is_hpux = ('hpux' in str(sys.platform).lower()) # Complete guess.
78-
is_solaris = ('solar==' in str(sys.platform).lower()) # Complete guess.
79-
80-
# ---------
81-
# Specifics
82-
# ---------
8+
from email.utils import escapesre, specialsre
839

84-
if is_py2:
10+
NativeStringIO = StringIO
8511

86-
unichr = unichr
87-
text_type = unicode
88-
string_types = (str, unicode)
89-
integer_types = (int, long)
90-
int_to_byte = chr
12+
string_types = (str, )
13+
text_type = str
9114

92-
import urlparse
93-
from .ordereddict import OrderedDict
9415

95-
from StringIO import StringIO
96-
from cStringIO import StringIO as BytesIO
97-
NativeStringIO = BytesIO
98-
99-
def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
100-
if x is None or isinstance(x, str):
101-
return x
102-
return x.encode(charset, errors)
103-
104-
def is_callable(x):
105-
return callable(x)
106-
107-
def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
108-
if x is None:
109-
return None
110-
if isinstance(x, (bytes, bytearray, buffer)):
111-
return bytes(x)
112-
if isinstance(x, unicode):
113-
return x.encode(charset, errors)
114-
raise TypeError('Expected bytes')
115-
116-
from email.utils import formataddr
117-
118-
119-
elif is_py3:
120-
import urllib.parse as urlparse
121-
122-
try:
123-
from collections.abc import Callable
124-
except ImportError:
125-
from collections import Callable
126-
127-
from collections import OrderedDict
128-
129-
from io import StringIO, BytesIO
130-
NativeStringIO = StringIO
131-
132-
unichr = chr
133-
text_type = str
134-
string_types = (str, )
135-
integer_types = (int, )
136-
137-
def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
138-
if x is None or isinstance(x, str):
139-
return x
140-
return x.decode(charset, errors)
141-
142-
def is_callable(x):
143-
return isinstance(x, Callable)
144-
145-
def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
146-
if x is None:
147-
return None
148-
if isinstance(x, (bytes, bytearray, memoryview)):
149-
return bytes(x)
150-
if isinstance(x, str):
151-
return x.encode(charset, errors)
152-
raise TypeError('Expected bytes')
153-
154-
from email.utils import escapesre, specialsre
155-
156-
def formataddr(pair):
157-
"""
158-
This code is copy of python2 email.utils.formataddr.
159-
Takes a 2-tuple of the form (realname, email_address) and returns RFC2822-like string.
160-
Does not encode non-ascii realname.
161-
162-
Python3 email.utils.formataddr do encode realname.
163-
164-
TODO: switch to email.headerregistry.AddressHeader ?
165-
"""
166-
167-
name, address = pair
168-
if name:
169-
quotes = ''
170-
if specialsre.search(name):
171-
quotes = '"'
172-
name = escapesre.sub(r'\\\g<0>', name)
173-
return '%s%s%s <%s>' % (quotes, name, quotes, address)
174-
return address
16+
def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
17+
if x is None or isinstance(x, str):
18+
return x
19+
return x.decode(charset, errors)
17520

17621

17722
def to_unicode(x, charset=sys.getdefaultencoding(), errors='strict',
17823
allow_none_charset=False):
17924
if x is None:
18025
return None
18126
if not isinstance(x, bytes):
182-
return text_type(x)
27+
return str(x)
18328
if charset is None and allow_none_charset:
18429
return x
185-
return x.decode(charset, errors)
30+
return x.decode(charset, errors)
31+
32+
33+
def to_bytes(x, charset=sys.getdefaultencoding(), errors='strict'):
34+
if x is None:
35+
return None
36+
if isinstance(x, (bytes, bytearray, memoryview)):
37+
return bytes(x)
38+
if isinstance(x, str):
39+
return x.encode(charset, errors)
40+
raise TypeError('Expected bytes')
41+
42+
43+
def is_callable(x):
44+
return isinstance(x, Callable)
45+
46+
47+
def formataddr(pair):
48+
"""
49+
Takes a 2-tuple of the form (realname, email_address) and returns RFC2822-like string.
50+
Does not encode non-ascii realname (unlike stdlib email.utils.formataddr).
51+
"""
52+
name, address = pair
53+
if name:
54+
quotes = ''
55+
if specialsre.search(name):
56+
quotes = '"'
57+
name = escapesre.sub(r'\\\g<0>', name)
58+
return '%s%s%s <%s>' % (quotes, name, quotes, address)
59+
return address

0 commit comments

Comments
 (0)