diff --git a/.travis.yml b/.travis.yml
index e69ccf5..91154e6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,14 +5,14 @@ sudo: false
cache: pip
python:
- - 2.7
- - 3.5
- 3.6
- 3.7
+ - 3.8
+ - 3.9
- "nightly"
allow_failures:
- # Just tests how PyInstaller performs with upcoming Python 3.8
+ # Just tests how PyInstaller performs with upcoming Python 3.10
- python: "nightly"
# Install dependencies.
@@ -28,4 +28,4 @@ install:
- pip install -r tests/requirements.txt | cat
script:
- - py.test -vv
+ - pytest -vv
diff --git a/CHANGES.rst b/CHANGES.rst
index 4eb2fef..ca746ac 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,10 @@ Changelog
0.5 (unreleased)
----------------
-- Nothing changed yet.
+* Drop support for Python 2 and 3.5
+
+* Fix ``assertDictContainsSubset``. On Python 3, the replacement would raise
+ a TypeError if the dictionary contained non-string keys.
0.4 (2019-06-30)
diff --git a/DEVELOPER.rst b/DEVELOPER.rst
index 2819ac6..8fc32d2 100644
--- a/DEVELOPER.rst
+++ b/DEVELOPER.rst
@@ -8,7 +8,7 @@ https://travis-ci.org/pytest-dev/unittest2pytest/.
Prior to pushing a pull-request to github, please test locally::
pip install tox pytest
- tox # or tox -e py27,py33,py34
+ tox # or tox -e py36,py37,py38,py39
Version Scheme
@@ -54,7 +54,7 @@ Full Release Process
4. Be sure that the current code passes tests locally::
- tox -e py27,py33,py34
+ tox -e py36,py37,py38,py39
5. Be sure `CI tests
`_ pass.
diff --git a/setup.py b/setup.py
index ce2848f..154908e 100644
--- a/setup.py
+++ b/setup.py
@@ -43,8 +43,6 @@ def read(filename):
return open(filename, 'r', encoding='utf-8').read()
long_description = '\n\n'.join([read('README.rst'),
read('CHANGES.rst')])
-if sys.version_info < (3,):
- long_description = long_description.encode('utf-8')
setup(
@@ -69,15 +67,14 @@ def read(filename):
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python",
- "Programming Language :: Python :: 2",
- "Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
"Topic :: Software Development",
"Topic :: Utilities",
],
- python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*",
+ python_requires=">=3.6",
zip_safe=False
)
diff --git a/tests/fixtures/self_assert/assertDictContainsSubset_out.py b/tests/fixtures/self_assert/assertDictContainsSubset_out.py
index a9415f5..07e7f51 100644
--- a/tests/fixtures/self_assert/assertDictContainsSubset_out.py
+++ b/tests/fixtures/self_assert/assertDictContainsSubset_out.py
@@ -2,19 +2,19 @@
class TestDictEqual(TestCase):
def test_simple(self):
- assert dict(superset, **{'a: 1'}) == superset
+ assert {**superset, **{'a: 1'}} == superset
def test_simple_msg(self):
- assert dict({'a: 1'}, **subset) == {'a: 1'}, "This is wrong!"
+ assert {**{'a: 1'}, **subset} == {'a: 1'}, "This is wrong!"
def test_simple_msg2(self):
- assert dict({'a: 1'}, **subset) == {'a: 1'}, "This is wrong!"
+ assert {**{'a: 1'}, **subset} == {'a: 1'}, "This is wrong!"
def test_line_wrapping(self):
- assert dict({
+ assert {**{
'a': 1,
'b': 2,
- }, **{'b': 2}) == {
+ }, **{'b': 2}} == {
'a': 1,
'b': 2,
}, \
diff --git a/tests/test_all_fixes.py b/tests/test_all_fixes.py
index c435554..e10d7b2 100644
--- a/tests/test_all_fixes.py
+++ b/tests/test_all_fixes.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
"""
This file is part of test-suite for unittest2pytest.
"""
@@ -22,8 +21,6 @@
# along with this program. If not, see .
#
-from __future__ import unicode_literals
-
__author__ = "Hartmut Goebel "
__copyright__ = "Copyright 2015-2019 by Hartmut Goebel"
__licence__ = "GNU General Public License version 3 or later (GPLv3+)"
diff --git a/tox.ini b/tox.ini
index 154599b..26d02c1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
-envlist = py27, py35, py36, py37
+envlist = py36, py37, py38, py39
[testenv]
deps =
diff --git a/unittest2pytest/__init__.py b/unittest2pytest/__init__.py
index e63c1a5..4d087ef 100644
--- a/unittest2pytest/__init__.py
+++ b/unittest2pytest/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Copyright 2015-2019 by Hartmut Goebel
#
diff --git a/unittest2pytest/__main__.py b/unittest2pytest/__main__.py
index dfcf051..384f85c 100755
--- a/unittest2pytest/__main__.py
+++ b/unittest2pytest/__main__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Copyright 2015-2019 by Hartmut Goebel
#
diff --git a/unittest2pytest/fixes/fix_remove_class.py b/unittest2pytest/fixes/fix_remove_class.py
index 0fb3b3d..9f0109d 100644
--- a/unittest2pytest/fixes/fix_remove_class.py
+++ b/unittest2pytest/fixes/fix_remove_class.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
fix_remove_class - lib2to3 fix for removing "class Testxxx(TestCase):"
headers and dedenting the contained code.
diff --git a/unittest2pytest/fixes/fix_self_assert.py b/unittest2pytest/fixes/fix_self_assert.py
index 8000c08..5f0f24f 100644
--- a/unittest2pytest/fixes/fix_self_assert.py
+++ b/unittest2pytest/fixes/fix_self_assert.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
fix_self_assert - lib2to3 fix for replacing assertXXX() method calls
by their pytest equivalent.
@@ -277,7 +276,7 @@ def get_import_nodes(node):
'assertTupleEqual': partial(CompOp, '=='),
'assertSequenceEqual': SequenceEqual,
- 'assertDictContainsSubset': partial(DualOp, 'dict(\2, **\1) == \2'),
+ 'assertDictContainsSubset': partial(DualOp, '{**\2, **\1} == \2'),
'assertItemsEqual': partial(DualOp, 'sorted(\1) == sorted(\2)'),
'assertAlmostEqual': partial(AlmostOp, "==", "<"),
diff --git a/unittest2pytest/utils.py b/unittest2pytest/utils.py
index 9f96200..fa152bb 100644
--- a/unittest2pytest/utils.py
+++ b/unittest2pytest/utils.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Some utility functions for unittest2pytest.
"""
@@ -27,80 +26,24 @@
import inspect
-try:
- from inspect import Parameter
-except ImportError:
- # Python 2
- pass
-from collections import OrderedDict
+from inspect import Parameter
class SelfMarker: pass
-def __apply_defaults(boundargs):
- # Backport of Python 3.5 inspect.BoundArgs.apply_defaults()
- arguments = boundargs.arguments
- if not arguments:
- return
- new_arguments = []
- for name, param in boundargs.signature.parameters.items():
- try:
- new_arguments.append((name, arguments[name]))
- except KeyError:
- if param.default is not Parameter.empty:
- val = param.default
- elif param.kind is Parameter.VAR_POSITIONAL:
- val = ()
- elif param.kind is Parameter.VAR_KEYWORD:
- val = {}
- else:
- # This BoundArguments was likely produced by
- # Signature.bind_partial().
- continue
- new_arguments.append((name, val))
- boundargs.arguments = OrderedDict(new_arguments)
-
-
def resolve_func_args(test_func, posargs, kwargs):
- try:
- inspect.signature
- except AttributeError:
- # Python 2.7
- posargs.insert(0, SelfMarker)
- args = inspect.getcallargs(test_func, *posargs, **kwargs)
-
- assert args['self'] == SelfMarker
- argspec = inspect.getargspec(test_func)
- #if not 'Raises' in method:
- # assert argspec.varargs is None # unhandled case
- # assert argspec.keywords is None # unhandled case
-
- # get the required arguments
- if argspec.defaults:
- required_args = argspec.args[1:-len(argspec.defaults)]
- else:
- required_args = argspec.args[1:]
- required_args = [args[argname] for argname in required_args]
-
- else:
- sig = inspect.signature(test_func)
- assert (list(iter(sig.parameters))[0] == 'self')
- posargs.insert(0, SelfMarker)
- ba = sig.bind(*posargs, **kwargs)
- try:
- ba.apply_defaults
- except AttributeError:
- # Python < 3.5
- __apply_defaults(ba)
- else:
- ba.apply_defaults()
- args = ba.arguments
- required_args = [n for n,v in sig.parameters.items()
- if (v.default is Parameter.empty and
- v.kind not in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD))]
- assert args['self'] == SelfMarker
- assert required_args[0] == 'self'
- del required_args[0], args['self']
- required_args = [args[n] for n in required_args]
+ sig = inspect.signature(test_func)
+ assert (list(iter(sig.parameters))[0] == 'self')
+ posargs.insert(0, SelfMarker)
+ ba = sig.bind(*posargs, **kwargs)
+ ba.apply_defaults()
+ args = ba.arguments
+ required_args = [n for n,v in sig.parameters.items()
+ if (v.default is Parameter.empty and
+ v.kind not in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD))]
+ assert args['self'] == SelfMarker
+ assert required_args[0] == 'self'
+ del required_args[0], args['self']
+ required_args = [args[n] for n in required_args]
return required_args, args