Skip to content

Commit

Permalink
Drop Python 2 support (#64)
Browse files Browse the repository at this point in the history
Python 2 is long obsolete, and cannot be CI tested in any reasonable way. Make official the current defacto situation.
  • Loading branch information
cjwatson authored Jul 22, 2024
1 parent eacbc80 commit 374b265
Show file tree
Hide file tree
Showing 18 changed files with 97 additions and 124 deletions.
4 changes: 1 addition & 3 deletions INSTALL.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ Installing Test Repository
Run time dependencies
~~~~~~~~~~~~~~~~~~~~~

* Either:
+ Python 2: version 2.7 or newer
+ Python 3: version 3.4 or newer
* Python 3: version 3.4 or newer

* subunit (0.0.18 or newer).

Expand Down
8 changes: 8 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
testrepository release notes
############################

0.0.22
++++++

CHANGES
-------

* Drop Python 2 support. (Colin Watson)

0.0.21
++++++

Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ classifiers = [
"License :: OSI Approved :: Apache Software License",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
"Programming Language :: Python",
"Topic :: Software Development :: Quality Assurance",
Expand Down
4 changes: 1 addition & 3 deletions testrepository/arguments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@

import sys

from testtools.compat import reraise


class AbstractArgument(object):
"""A argument that a command may need.
Expand Down Expand Up @@ -101,7 +99,7 @@ def parse(self, argv):
break
if count < self.minimum_count:
if error is not None:
reraise(error[0], error[1], error[2])
raise error[1].with_traceback(error[2])
raise ValueError('not enough arguments present/matched in %s' % argv)
del argv[:count]
return result
Expand Down
5 changes: 2 additions & 3 deletions testrepository/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import sys

import subunit
from testtools.compat import _u

from testrepository.repository import file

Expand Down Expand Up @@ -204,8 +203,8 @@ def get_command_parser(cmd):
parser = OptionParser()
for option in cmd.options:
parser.add_option(option)
usage = _u('%%prog %(cmd)s [options] %(args)s\n\n%(help)s') % {
'args': _u(' ').join(map(lambda x:x.summary(), cmd.args)),
usage = '%%prog %(cmd)s [options] %(args)s\n\n%(help)s' % {
'args': ' '.join(map(lambda x:x.summary(), cmd.args)),
'cmd': getattr(cmd, 'name', cmd),
'help': getdoc(cmd),
}
Expand Down
1 change: 0 additions & 1 deletion testrepository/commands/list_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from io import BytesIO

from testtools import TestResult
from testtools.compat import _b

from testrepository.arguments.doubledash import DoubledashArgument
from testrepository.arguments.string import StringArgument
Expand Down
7 changes: 3 additions & 4 deletions testrepository/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from testtools import (
TestByTestResult,
)
from testtools.compat import _b

from testrepository.arguments.doubledash import DoubledashArgument
from testrepository.arguments.string import StringArgument
Expand All @@ -36,7 +35,7 @@
from testrepository.testlist import parse_list


LINEFEED = _b('\n')[0]
LINEFEED = b'\n'[0]


class ReturnCodeToSubunit(object):
Expand Down Expand Up @@ -74,7 +73,7 @@ def _append_return_code_as_test(self):
# line. V2 needs to start on any fresh utf8 character border
# - which is not guaranteed in an arbitrary stream endpoint, so
# injecting a \n gives us such a guarantee.
self.source.write(_b('\n'))
self.source.write(b'\n')
stream = subunit.StreamResultToBytes(self.source)
stream.status(test_id='process-returncode', test_status='fail',
file_name='traceback', mime_type='text/plain;charset=utf8',
Expand All @@ -84,7 +83,7 @@ def _append_return_code_as_test(self):

def read(self, count=-1):
if count == 0:
return _b('')
return b''
result = self.source.read(count)
if result:
self.lastoutput = result[-1]
Expand Down
3 changes: 1 addition & 2 deletions testrepository/repository/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import subunit.v2
from subunit import TestProtocolClient
import testtools
from testtools.compat import _b

from testrepository.repository import (
AbstractRepository,
Expand Down Expand Up @@ -123,7 +122,7 @@ def get_failing(self):
except IOError:
err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
run_subunit_content = _b('')
run_subunit_content = b''
else:
raise
return _DiskRun(None, run_subunit_content)
Expand Down
7 changes: 2 additions & 5 deletions testrepository/testlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,19 @@
from subunit import ByteStreamToStreamResult
from testtools.testresult.doubles import StreamResult

from testtools.compat import _b, _u


def write_list(stream, test_ids):
"""Write test_ids out to stream.
:param stream: A file-like object.
:param test_ids: An iterable of test ids.
"""
# May need utf8 explicitly?
stream.write(_b('\n'.join(list(test_ids) + [''])))
stream.write(('\n'.join(list(test_ids) + [''])).encode('utf8'))


def parse_list(list_bytes):
"""Parse list_bytes into a list of test ids."""
return [id.strip() for id in list_bytes.decode('utf8').split(_u('\n'))
return [id.strip() for id in list_bytes.decode('utf8').split('\n')
if id.strip()]


Expand Down
3 changes: 1 addition & 2 deletions testrepository/tests/commands/test_failing.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

from subunit.v2 import ByteStreamToStreamResult
import testtools
from testtools.compat import _b
from testtools.matchers import (
DocTestMatches,
Equals,
Expand Down Expand Up @@ -110,7 +109,7 @@ def test_with_subunit_no_failures_exit_0(self):
self.assertEqual(0, cmd.execute())
self.assertEqual(1, len(ui.outputs))
self.assertEqual('stream', ui.outputs[0][0])
self.assertThat(ui.outputs[0][1], Equals(_b('')))
self.assertThat(ui.outputs[0][1], Equals(b''))

def test_with_list_shows_list_of_tests(self):
ui, cmd = self.get_test_ui_and_cmd(options=[('list', True)])
Expand Down
5 changes: 2 additions & 3 deletions testrepository/tests/commands/test_list_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from subprocess import PIPE

import subunit
from testtools.compat import _b
from testtools.matchers import MatchesException

from testrepository.commands import list_tests
Expand Down Expand Up @@ -91,7 +90,7 @@ def test_calls_list_tests(self):
('popen', (expected_cmd,),
{'shell': True, 'stdout': PIPE, 'stdin': PIPE}),
('communicate',),
('stream', _b('returned\nvalues\n')),
('stream', b'returned\nvalues\n'),
], ui.outputs)

def test_filters_use_filtered_list(self):
Expand All @@ -116,6 +115,6 @@ def test_filters_use_filtered_list(self):
('popen', (expected_cmd,),
{'shell': True, 'stdout': PIPE, 'stdin': PIPE}),
('communicate',),
('stream', _b('returned\n')),
('stream', b'returned\n'),
], ui.outputs)
self.assertEqual(0, retcode)
17 changes: 8 additions & 9 deletions testrepository/tests/commands/test_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import iso8601

import testtools
from testtools.compat import _b
from testtools.content import text_content
from testtools.matchers import MatchesException
from testtools.tests.helpers import LoggingResult
Expand All @@ -42,7 +41,7 @@
class TestCommandLoad(ResourcedTestCase):

def test_load_loads_subunit_stream_to_default_repository(self):
ui = UI([('subunit', _b(''))])
ui = UI([('subunit', b'')])
cmd = load.load(ui)
ui.set_command(cmd)
calls = []
Expand All @@ -61,7 +60,7 @@ def test_load_loads_subunit_stream_to_default_repository(self):
def test_load_loads_named_file_if_given(self):
datafile = NamedTemporaryFile()
self.addCleanup(datafile.close)
ui = UI([('subunit', _b(''))], args=[datafile.name])
ui = UI([('subunit', b'')], args=[datafile.name])
cmd = load.load(ui)
ui.set_command(cmd)
calls = []
Expand All @@ -80,7 +79,7 @@ def test_load_loads_named_file_if_given(self):
self.assertEqual(1, repo.count())

def test_load_initialises_repo_if_doesnt_exist_and_init_forced(self):
ui = UI([('subunit', _b(''))], options=[('force_init', True)])
ui = UI([('subunit', b'')], options=[('force_init', True)])
cmd = load.load(ui)
ui.set_command(cmd)
calls = []
Expand All @@ -91,7 +90,7 @@ def test_load_initialises_repo_if_doesnt_exist_and_init_forced(self):
self.assertEqual([('open', ui.here), ('initialise', ui.here)], calls)

def test_load_errors_if_repo_doesnt_exist(self):
ui = UI([('subunit', _b(''))])
ui = UI([('subunit', b'')])
cmd = load.load(ui)
ui.set_command(cmd)
calls = []
Expand All @@ -105,7 +104,7 @@ def test_load_errors_if_repo_doesnt_exist(self):
ui.outputs[0][1], MatchesException(RepositoryNotFound('memory:')))

def test_load_returns_0_normally(self):
ui = UI([('subunit', _b(''))])
ui = UI([('subunit', b'')])
cmd = load.load(ui)
ui.set_command(cmd)
cmd.repository_factory = memory.RepositoryFactory()
Expand Down Expand Up @@ -190,7 +189,7 @@ def test_load_new_shows_test_skips(self):
ui.outputs)

def test_load_new_shows_test_summary_no_tests(self):
ui = UI([('subunit', _b(''))])
ui = UI([('subunit', b'')])
cmd = load.load(ui)
ui.set_command(cmd)
cmd.repository_factory = memory.RepositoryFactory()
Expand All @@ -202,7 +201,7 @@ def test_load_new_shows_test_summary_no_tests(self):
ui.outputs)

def test_load_quiet_shows_nothing(self):
ui = UI([('subunit', _b(''))], [('quiet', True)])
ui = UI([('subunit', b'')], [('quiet', True)])
cmd = load.load(ui)
ui.set_command(cmd)
cmd.repository_factory = memory.RepositoryFactory()
Expand All @@ -225,7 +224,7 @@ def test_load_abort_over_interactive_stream(self):
self.assertEqual(1, ret)

def test_partial_passed_to_repo(self):
ui = UI([('subunit', _b(''))], [('quiet', True), ('partial', True)])
ui = UI([('subunit', b'')], [('quiet', True), ('partial', True)])
cmd = load.load(ui)
ui.set_command(cmd)
cmd.repository_factory = memory.RepositoryFactory()
Expand Down
9 changes: 4 additions & 5 deletions testrepository/tests/commands/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import subunit
from subunit import RemotedTestCase
from testscenarios.scenarios import multiply_scenarios
from testtools.compat import _b
from testtools.matchers import (
Equals,
HasLength,
Expand Down Expand Up @@ -501,7 +500,7 @@ def readline(stream):


def readlines(stream):
return _b('').join(stream.readlines())
return b''.join(stream.readlines())


def accumulate(stream, reader):
Expand All @@ -510,7 +509,7 @@ def accumulate(stream, reader):
while content:
accumulator.append(content)
content = reader(stream)
return _b('').join(accumulator)
return b''.join(accumulator)


class TestReturnCodeToSubunit(ResourcedTestCase):
Expand All @@ -521,8 +520,8 @@ class TestReturnCodeToSubunit(ResourcedTestCase):
('readline', dict(reader=readline)),
('readlines', dict(reader=readlines)),
],
[('noeol', dict(stdout=_b('foo\nbar'))),
('trailingeol', dict(stdout=_b('foo\nbar\n')))])
[('noeol', dict(stdout=b'foo\nbar')),
('trailingeol', dict(stdout=b'foo\nbar\n'))])

def test_returncode_0_no_change(self):
proc = ProcessModel(None)
Expand Down
1 change: 0 additions & 1 deletion testrepository/tests/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
PlaceHolder,
)
import testtools
from testtools.compat import _b
from testtools.testresult.doubles import (
ExtendedTestResult,
StreamResult,
Expand Down
Loading

0 comments on commit 374b265

Please sign in to comment.