Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow non-string keys when rewriting assertDictContainsSubset #55

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -28,4 +28,4 @@ install:
- pip install -r tests/requirements.txt | cat

script:
- py.test -vv
- pytest -vv
5 changes: 4 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions DEVELOPER.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
<https://travis-ci.org/pytest-dev/unittest2pytest/>`_ pass.
Expand Down
9 changes: 3 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
)
10 changes: 5 additions & 5 deletions tests/fixtures/self_assert/assertDictContainsSubset_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}, \
Expand Down
3 changes: 0 additions & 3 deletions tests/test_all_fixes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This file is part of test-suite for unittest2pytest.
"""
Expand All @@ -22,8 +21,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

from __future__ import unicode_literals

__author__ = "Hartmut Goebel <[email protected]>"
__copyright__ = "Copyright 2015-2019 by Hartmut Goebel"
__licence__ = "GNU General Public License version 3 or later (GPLv3+)"
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# and then run "tox" from this directory.

[tox]
envlist = py27, py35, py36, py37
envlist = py36, py37, py38, py39

[testenv]
deps =
Expand Down
1 change: 0 additions & 1 deletion unittest2pytest/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# Copyright 2015-2019 by Hartmut Goebel <[email protected]>
#
Expand Down
1 change: 0 additions & 1 deletion unittest2pytest/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
#
# Copyright 2015-2019 by Hartmut Goebel <[email protected]>
#
Expand Down
1 change: 0 additions & 1 deletion unittest2pytest/fixes/fix_remove_class.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
fix_remove_class - lib2to3 fix for removing "class Testxxx(TestCase):"
headers and dedenting the contained code.
Expand Down
3 changes: 1 addition & 2 deletions unittest2pytest/fixes/fix_self_assert.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
fix_self_assert - lib2to3 fix for replacing assertXXX() method calls
by their pytest equivalent.
Expand Down Expand Up @@ -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, "==", "<"),
Expand Down
85 changes: 14 additions & 71 deletions unittest2pytest/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Some utility functions for unittest2pytest.
"""
Expand Down Expand Up @@ -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