diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..2036733
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,53 @@
+name: Test
+
+on: [push, pull_request, workflow_dispatch]
+
+env:
+ FORCE_COLOR: 1
+
+jobs:
+ test:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ["3.6", "3.7", "3.8", "3.9", "3.10-dev"]
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ exclude:
+ # TODO Fix these versions on Windows
+ - {os: windows-latest, python-version: "3.7"}
+ - {os: windows-latest, python-version: "3.8"}
+ - {os: windows-latest, python-version: "3.9"}
+ - {os: windows-latest, python-version: "3.10-dev"}
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Get pip cache dir
+ id: pip-cache
+ run: |
+ echo "::set-output name=dir::$(pip cache dir)"
+
+ - name: Cache
+ uses: actions/cache@v2
+ with:
+ path: ${{ steps.pip-cache.outputs.dir }}
+ key:
+ ${{ matrix.os }}-${{ matrix.python-version }}-v1-${{ hashFiles('**/tox.ini') }}
+ restore-keys: |
+ ${{ matrix.os }}-${{ matrix.python-version }}-v1-
+
+ - name: Install dependencies
+ run: |
+ python -m pip install -U pip
+ python -m pip install -e .
+ pip install -r tests/requirements.txt
+
+ - name: Test
+ run: |
+ pytest -vv
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index e69ccf5..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-dist: xenial
-language: python
-# Use new container-based Travis infrastructure.
-sudo: false
-cache: pip
-
-python:
- - 2.7
- - 3.5
- - 3.6
- - 3.7
- - "nightly"
-
-allow_failures:
- # Just tests how PyInstaller performs with upcoming Python 3.8
- - python: "nightly"
-
-# Install dependencies.
-install:
- # Install unittest2pytest
- - pip install -e .
-
- # Install dependencies for tests.
-
- # The download-progress bars break Travis's log view. Disable them
- # by piping output through another program (if output is not a tty,
- # no progress bars)
- - pip install -r tests/requirements.txt | cat
-
-script:
- - py.test -vv
diff --git a/DEVELOPER.rst b/DEVELOPER.rst
index 2819ac6..587605b 100644
--- a/DEVELOPER.rst
+++ b/DEVELOPER.rst
@@ -3,12 +3,12 @@ Testing
===========
Continuous integration tests are available at
-https://travis-ci.org/pytest-dev/unittest2pytest/.
+https://github.com/pytest-dev/unittest2pytest/actions.
-Prior to pushing a pull-request to github, please test locally::
+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 py37,py38,py39
Version Scheme
@@ -54,10 +54,10 @@ Full Release Process
4. Be sure that the current code passes tests locally::
- tox -e py27,py33,py34
+ tox -e py37,py38,py39
5. Be sure `CI tests
- `_ pass.
+ `_ pass.
Now we start with the main release process.
@@ -154,7 +154,7 @@ Now we start with the main release process.
git push --follow-tags origin master
-15. Create release on github:
+15. Create release on GitHub:
a. Go to the `unittest2pytest release page
`_
diff --git a/README.rst b/README.rst
index 65a2496..0b31528 100644
--- a/README.rst
+++ b/README.rst
@@ -13,9 +13,9 @@ Helps converting unittest test-cases to pytest
:Homepage: https://github.com/pytest-dev/unittest2pytest
-.. image:: https://secure.travis-ci.org/pytest-dev/unittest2pytest.png?branch=develop
- :target: https://travis-ci.org/pytest-dev/unittest2pytest/
-
+.. image:: https://github.com/pytest-dev/unittest2pytest/actions/workflows/test.yml/badge.svg
+ :target: https://github.com/pytest-dev/unittest2pytest/actions
+ :alt: See Build Status on GitHub Actions
`unittest2pytest` is a tool that helps rewriting Python `unittest`
test-cases into pytest_ test-cases.
diff --git a/setup.cfg b/setup.cfg
index 8313024..ebd6f52 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,3 @@
-[bdist_wheel]
-universal = 1
-
[zest.releaser]
python-file-with-version = unittest2pytest/__init__.py
push-changes = no
diff --git a/setup.py b/setup.py
index ce2848f..8c305d4 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
# Copyright 2015-2019 by Hartmut Goebel
#
@@ -20,9 +19,7 @@
#
from setuptools import setup
-import codecs
import re
-import sys
def get_version(filename):
@@ -37,14 +34,11 @@ def get_version(filename):
def read(filename):
- try:
- return unicode(codecs.open(filename, encoding='utf-8').read())
- except NameError:
- return open(filename, 'r', encoding='utf-8').read()
+ return open(filename, 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 +63,16 @@ 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 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
"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/test_all_fixes.py b/tests/test_all_fixes.py
index c435554..2463e70 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,7 +21,6 @@
# along with this program. If not, see .
#
-from __future__ import unicode_literals
__author__ = "Hartmut Goebel "
__copyright__ = "Copyright 2015-2019 by Hartmut Goebel"
@@ -108,7 +106,7 @@ def test_check_fixture(in_file, fixer, tmpdir):
try:
compile(''.join(expected_contents), expected_file, 'exec')
except Exception as e:
- pytest.fail("FATAL: %s does not compile: %s" % (expected_file, e),
+ pytest.fail(f"FATAL: {expected_file} does not compile: {e}",
False)
if result_file_contents != expected_contents:
diff --git a/tox.ini b/tox.ini
index 154599b..fea8ff2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,10 @@
-# Tox (http://tox.testrun.org/) is a tool for running tests
+# Tox (https://tox.readthedocs.io) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.
[tox]
-envlist = py27, py35, py36, py37
+envlist = py36, py37, py38, py39, py310
[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..2b0cad5 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.
@@ -136,9 +135,8 @@ def RaisesOp(context, exceptionClass, indent, kws, arglist, node):
exceptionClass.prefix = ""
args = [exceptionClass]
# Add match keyword arg to with statement if an expected regex was provided.
- # In py27 the keyword is `expected_regexp`, in py3 is `expected_regex`
- if 'expected_regex' in kws or 'expected_regexp' in kws:
- expected_regex = kws.get('expected_regex', kws.get('expected_regexp')).clone()
+ if 'expected_regex' in kws:
+ expected_regex = kws.get('expected_regex').clone()
expected_regex.prefix = ''
args.append(String(', '))
args.append(
diff --git a/unittest2pytest/utils.py b/unittest2pytest/utils.py
index 9f96200..c223830 100644
--- a/unittest2pytest/utils.py
+++ b/unittest2pytest/utils.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Some utility functions for unittest2pytest.
"""
@@ -27,80 +26,25 @@
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