Skip to content

Commit b96b922

Browse files
authored
remove python 2.7 support (#211) => 3.0.0
* remove python 2.7 support * remove six * updage django versions * remove python2 hacks * bump major version 3.0.0
1 parent 62bd1ae commit b96b922

File tree

12 files changed

+48
-144
lines changed

12 files changed

+48
-144
lines changed

.travis.yml

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@ cache: pip
44

55
matrix:
66
include:
7-
- python: 2.7
8-
env: TOXENV=py27
9-
- python: 2.7
10-
env: TOXENV=py27-djangolts
11-
- python: 2.7
12-
env: TOXENV=py27-djangocurr
13-
- python: 2.7
14-
env: TOXENV=quality
157
- python: 3.5
168
env: TOXENV=py35
179
- python: 3.6
@@ -20,14 +12,14 @@ matrix:
2012
env: TOXENV=py37
2113
- python: 3.8
2214
env: TOXENV=py38
15+
- python: 3.8
16+
env: TOXENV=py38-djangolts
17+
- python: 3.8
18+
env: TOXENV=py38-djangocurr
19+
- python: 3.8
20+
env: TOXENV=quality
2321
- python: 3.8-dev
2422
env: TOXENV=pytest
25-
- os: linux
26-
dist: xenial
27-
python: pypy2.7-6.0
28-
env: TOXENV=pypy
29-
services:
30-
- docker
3123
- os: linux
3224
dist: xenial
3325
python: pypy3.5-6.0

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ in the reports for sub-tests.
3939

4040
## Requirements
4141

42-
* Python 2.7 or 3.3+
42+
* Python 3.5+
43+
* Please note Python 2.7 end-of-life was in Jan 2020, last version supporting 2.7 was 2.5.2
44+
* Please note Python 3.4 end-of-life was in Mar 2019, last version supporting 3.4 was 2.5.2
4345
* Please note Python 2.6 end-of-life was in Oct 2013, last version supporting 2.6 was 1.14.0
4446

4547
## Installation

setup.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@
1515
with codecs.open(readme_path, 'rb', 'utf8') as readme_file:
1616
long_description = readme_file.read()
1717

18-
install_requires = ['six>=1.4.0']
19-
2018
# this is for sdist to work.
2119
import sys
22-
if sys.version_info < (2, 7):
23-
# python 2.6 no longer supported, use last 1.x release instead.
24-
raise RuntimeError('This version requires Python 2.7+') # pragma: no cover
20+
if sys.version_info < (3, 5):
21+
raise RuntimeError('This version requires Python 3.5+') # pragma: no cover
2522

2623
setup(
2724
name = 'unittest-xml-reporting',
@@ -57,6 +54,5 @@
5754
packages = ['xmlrunner', 'xmlrunner.extra'],
5855
zip_safe = False,
5956
include_package_data = True,
60-
install_requires = install_requires,
6157
test_suite = 'tests'
6258
)

tests/builder_test.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from xml.dom.minidom import Document
77

88
from xmlrunner import builder
9-
import six
109

1110

1211
class TestXMLContextTest(unittest.TestCase):
@@ -27,9 +26,9 @@ def test_current_context_name(self):
2726
self.assertEqual(name, 'context-name')
2827

2928
def test_current_context_invalid_unicode_name(self):
30-
self.root.begin('tag', six.u('context-name\x01\x0B'))
29+
self.root.begin('tag', u'context-name\x01\x0B')
3130
name = self.root.element.getAttribute('name')
32-
self.assertEqual(name, six.u('context-name\uFFFD\uFFFD'))
31+
self.assertEqual(name, u'context-name\uFFFD\uFFFD')
3332

3433
def test_increment_valid_testsuites_counters(self):
3534
self.root.begin('testsuites', 'name')
@@ -99,10 +98,10 @@ def setUp(self):
9998
self.doc = self.builder._xml_doc
10099
self.builder.begin_context('testsuites', 'name')
101100

102-
self.valid_chars = six.u('выбор')
101+
self.valid_chars = u'выбор'
103102

104103
self.invalid_chars = '\x01'
105-
self.invalid_chars_replace = six.u('\ufffd')
104+
self.invalid_chars_replace = u'\ufffd'
106105

107106
def test_root_has_no_parent(self):
108107
self.assertIsNone(self.builder.current_context().parent)

tests/django_test.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
import os
55
from os import path
66
import glob
7-
try:
8-
from unittest import mock
9-
except ImportError:
10-
import mock
7+
from unittest import mock
118
import tempfile
129
import shutil
1310

@@ -19,6 +16,7 @@
1916
from django.test.utils import get_runner
2017
from django.conf import settings, UserSettingsHolder
2118
from django.apps import apps
19+
settings.configure(DEBUG=True)
2220

2321

2422
TESTS_DIR = path.dirname(__file__)
@@ -37,6 +35,7 @@ def setUp(self):
3735
self.old_settings = settings._wrapped
3836
os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings'
3937
settings.INSTALLED_APPS # load settings on first access
38+
settings.DATABASES['default'] = {}
4039
settings.DATABASES['default']['NAME'] = path.join(
4140
self.tmpdir, 'db.sqlilte3')
4241
# this goes around the "settings already loaded" issue.

tests/testsuite.py

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from xmlrunner.result import _XMLTestResult
1616
import doctest
1717
import tests.doctest_example
18-
from six import StringIO, BytesIO, exec_
18+
from io import StringIO, BytesIO
1919
from tempfile import mkdtemp
2020
from tempfile import mkstemp
2121
from shutil import rmtree
@@ -24,11 +24,7 @@
2424
from lxml import etree
2525
import os
2626
import os.path
27-
28-
try:
29-
from unittest import mock
30-
except ImportError:
31-
import mock
27+
from unittest import mock
3228

3329

3430
def _load_schema():
@@ -114,7 +110,7 @@ def wrapper(*args, **kwargs):
114110
return func(*args, **kwargs)
115111
"""
116112
evaldict = dict(func=f)
117-
exec_(code, evaldict)
113+
exec(code, evaldict)
118114
return evaldict['wrapper']
119115

120116

@@ -402,21 +398,13 @@ def _xmlrunner_non_ascii_failures(self, buffer=False):
402398

403399
# allow output non-ascii letters to stdout
404400
orig_stdout = sys.stdout
405-
if getattr(sys.stdout, 'buffer', None):
406-
# Python3
407-
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
408-
else:
409-
# Python2
410-
import codecs
411-
sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
401+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
412402

413403
try:
414404
runner.run(suite)
415405
finally:
416-
if getattr(sys.stdout, 'buffer', None):
417-
# Python3
418-
# Not to be closed when TextIOWrapper is disposed.
419-
sys.stdout.detach()
406+
# Not to be closed when TextIOWrapper is disposed.
407+
sys.stdout.detach()
420408
sys.stdout = orig_stdout
421409
outdir.seek(0)
422410
output = outdir.read()
@@ -835,10 +823,7 @@ def test_test_program_fail_wo_buffer(self):
835823
self.assertNotIn('should be printed', r[1].getvalue())
836824

837825
def test_partialmethod(self):
838-
try:
839-
from functools import partialmethod
840-
except ImportError:
841-
raise unittest.SkipTest('functools.partialmethod is not available.')
826+
from functools import partialmethod
842827
def test_partialmethod(test):
843828
pass
844829
class TestWithPartialmethod(unittest.TestCase):

tox.ini

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,23 @@ testpaths = tests
44
norecursedirs = tests/django_example
55

66
[tox]
7-
envlist = begin,py{27,py,py3,35,36,37},pytest,py27-django{lts,curr},end,quality
7+
envlist = begin,py{py,py3,35,36,37,38},pytest,py38-django{lts,curr},end,quality
88

99
[tox:travis]
10-
2.7 = begin,py27,py27-django{lts,curr},end,quality
1110
3.5 = py35
1211
3.6 = py36
1312
3.7 = py37,pytest
14-
3.8 = py38
13+
3.8 = begin,py38,py38-django{lts,curr},end,quality
1514

1615
[testenv]
1716
deps =
1817
coverage
1918
codecov>=1.4.0
2019
coveralls
21-
djangolts,pytest: django>=1.8.8,<1.9.0
22-
djangocurr: django>=1.9.1
20+
djangolts,pytest: django>=1.11.0,<1.12.0
21+
djangocurr: django>=2.2.0
2322
pytest: pytest
2423
lxml>=3.6.0
25-
mock
2624
commands =
2725
coverage run --append setup.py test
2826
coverage report --omit='.tox/*'

xmlrunner/builder.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import sys
33
import datetime
44
import time
5-
import six
65

76
from xml.dom.minidom import Document
87

@@ -20,18 +19,18 @@
2019
_char_tail = ''
2120

2221
if sys.maxunicode > 0x10000:
23-
_char_tail = six.u('%s-%s') % (
24-
six.unichr(0x10000),
25-
six.unichr(min(sys.maxunicode, 0x10FFFF))
22+
_char_tail = (u'%s-%s') % (
23+
chr(0x10000),
24+
chr(min(sys.maxunicode, 0x10FFFF))
2625
)
2726

2827
_nontext_sub = re.compile(
29-
six.u(r'[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD%s]') % _char_tail,
28+
r'[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD%s]' % _char_tail,
3029
re.U
3130
).sub
3231

3332

34-
def replace_nontext(text, replacement=six.u('\uFFFD')):
33+
def replace_nontext(text, replacement=u'\uFFFD'):
3534
return _nontext_sub(replacement, text)
3635

3736

@@ -104,7 +103,7 @@ def _set_result_counters(self):
104103
)
105104

106105
if valid_counter_for_element:
107-
value = six.text_type(
106+
value = str(
108107
self.counters.get(counter_name, 0)
109108
)
110109
self.element.setAttribute(counter_name, value)
@@ -192,7 +191,7 @@ def append(self, tag, content, **kwargs):
192191
element = self._xml_doc.createElement(tag)
193192

194193
for key, value in kwargs.items():
195-
filtered_value = replace_nontext(six.text_type(value))
194+
filtered_value = replace_nontext(str(value))
196195
element.setAttribute(key, filtered_value)
197196

198197
if content:

0 commit comments

Comments
 (0)