diff --git a/.coveragerc b/.coveragerc index 48670b41d..61ff66749 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,6 +1,4 @@ [run] -omit = +omit = # standlonetemplate is read dynamically and tested by test_genscript *standalonetemplate.py - # oldinterpret could be removed, as it is no longer used in py26+ - *oldinterpret.py diff --git a/README.rst b/README.rst index 15ad6ea18..3630dd4c6 100644 --- a/README.rst +++ b/README.rst @@ -76,7 +76,7 @@ Features - Can run `unittest `_ (or trial), `nose `_ test suites out of the box; -- Python2.6+, Python3.3+, PyPy-2.3, Jython-2.5 (untested); +- Python 2.7, Python 3.4+, PyPy 2.3, Jython 2.5 (untested); - Rich plugin architecture, with over 315+ `external plugins `_ and thriving community; diff --git a/_pytest/_argcomplete.py b/_pytest/_argcomplete.py index 965ec7951..0625a75f9 100644 --- a/_pytest/_argcomplete.py +++ b/_pytest/_argcomplete.py @@ -4,9 +4,6 @@ needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail to find the magic string, so _ARGCOMPLETE env. var is never set, and this does not need special code. -argcomplete does not support python 2.5 (although the changes for that -are minor). - Function try_argcomplete(parser) should be called directly before the call to ArgumentParser.parse_args(). diff --git a/_pytest/_code/source.py b/_pytest/_code/source.py index 2959d635a..8b0bc3b44 100644 --- a/_pytest/_code/source.py +++ b/_pytest/_code/source.py @@ -342,8 +342,6 @@ def get_statement_startend2(lineno, node): def getstatementrange_ast(lineno, source, assertion=False, astnode=None): if astnode is None: content = str(source) - if sys.version_info < (2, 7): - content += "\n" try: astnode = compile(content, "source", "exec", 1024) # 1024 for AST except ValueError: diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py index e9e39dae0..a48e98c85 100644 --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -67,10 +67,8 @@ class AssertionState: def install_importhook(config): """Try to install the rewrite hook, raise SystemError if it fails.""" - # Both Jython and CPython 2.6.0 have AST bugs that make the - # assertion rewriting hook malfunction. - if (sys.platform.startswith('java') or - sys.version_info[:3] == (2, 6, 0)): + # Jython has an AST bug that make the assertion rewriting hook malfunction. + if (sys.platform.startswith('java')): raise SystemError('rewrite not supported') config._assertstate = AssertionState(config, 'rewrite') diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py index 956ff487f..6800f82e6 100644 --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -34,7 +34,6 @@ else: PYC_EXT = ".py" + (__debug__ and "c" or "o") PYC_TAIL = "." + PYTEST_TAG + PYC_EXT -REWRITE_NEWLINES = sys.version_info[:2] != (2, 7) and sys.version_info < (3, 2) ASCII_IS_DEFAULT_ENCODING = sys.version_info[0] < 3 if sys.version_info >= (3, 5): @@ -321,10 +320,6 @@ def _rewrite_test(config, fn): return None, None finally: del state._indecode - # On Python versions which are not 2.7 and less than or equal to 3.1, the - # parser expects *nix newlines. - if REWRITE_NEWLINES: - source = source.replace(RN, N) + N try: tree = ast.parse(source) except SyntaxError: diff --git a/_pytest/fixtures.py b/_pytest/fixtures.py index f57031e1a..af993f3f9 100644 --- a/_pytest/fixtures.py +++ b/_pytest/fixtures.py @@ -19,10 +19,7 @@ from _pytest.compat import ( from _pytest.outcomes import fail, TEST_OUTCOME from _pytest.compat import FuncargnamesCompatAttr -if sys.version_info[:2] == (2, 6): - from ordereddict import OrderedDict -else: - from collections import OrderedDict +from collections import OrderedDict def pytest_sessionstart(session): diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 2d35bf80a..345a1acd0 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -112,12 +112,9 @@ class LsofFdLeakChecker(object): # XXX copied from execnet's conftest.py - needs to be merged winpymap = { 'python2.7': r'C:\Python27\python.exe', - 'python2.6': r'C:\Python26\python.exe', - 'python3.1': r'C:\Python31\python.exe', - 'python3.2': r'C:\Python32\python.exe', - 'python3.3': r'C:\Python33\python.exe', 'python3.4': r'C:\Python34\python.exe', 'python3.5': r'C:\Python35\python.exe', + 'python3.6': r'C:\Python36\python.exe', } @@ -143,8 +140,7 @@ def getexecutable(name, cache={}): return executable -@pytest.fixture(params=['python2.6', 'python2.7', 'python3.3', "python3.4", - 'pypy', 'pypy3']) +@pytest.fixture(params=['python2.7', 'python3.4', 'pypy', 'pypy3']) def anypython(request): name = request.param executable = getexecutable(name) diff --git a/_pytest/python_api.py b/_pytest/python_api.py index b73e0457c..b52f68810 100644 --- a/_pytest/python_api.py +++ b/_pytest/python_api.py @@ -453,8 +453,7 @@ def raises(expected_exception, *args, **kwargs): This helper produces a ``ExceptionInfo()`` object (see below). - If using Python 2.5 or above, you may use this function as a - context manager:: + You may use this function as a context manager:: >>> with raises(ZeroDivisionError): ... 1/0 @@ -609,13 +608,6 @@ class RaisesContext(object): __tracebackhide__ = True if tp[0] is None: fail(self.message) - if sys.version_info < (2, 7): - # py26: on __exit__() exc_value often does not contain the - # exception value. - # http://bugs.python.org/issue7853 - if not isinstance(tp[1], BaseException): - exc_type, value, traceback = tp - tp = exc_type, exc_type(value), traceback self.excinfo.__init__(tp) suppress_exception = issubclass(self.excinfo.type, self.expected_exception) if sys.version_info[0] == 2 and suppress_exception: diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 586f44184..66079be7e 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -6,7 +6,7 @@ import py import pytest import _pytest._code -pythonlist = ['python2.6', 'python2.7', 'python3.4', 'python3.5'] +pythonlist = ['python2.7', 'python3.4', 'python3.5'] @pytest.fixture(params=pythonlist) def python1(request, tmpdir): picklefile = tmpdir.join("data.pickle") diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 1571e4f6b..d2eb77d3e 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -1,7 +1,7 @@ Installation and Getting Started =================================== -**Pythons**: Python 2.6,2.7,3.3,3.4,3.5, Jython, PyPy-2.3 +**Pythons**: Python 2.7, 3.4, 3.5, 3.6, Jython, PyPy-2.3 **Platforms**: Unix/Posix and Windows @@ -9,8 +9,6 @@ Installation and Getting Started **dependencies**: `py `_, `colorama (Windows) `_, -`argparse (py26) `_, -`ordereddict (py26) `_. **documentation as PDF**: `download latest `_ @@ -50,17 +48,17 @@ That's it. You can execute the test function now:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_sample.py F - + ======= FAILURES ======== _______ test_answer ________ - + def test_answer(): > assert func(3) == 5 E assert 4 == 5 E + where 4 = func(3) - + test_sample.py:5: AssertionError ======= 1 failed in 0.12 seconds ======== @@ -129,15 +127,15 @@ run the module by passing its filename:: .F ======= FAILURES ======== _______ TestClass.test_two ________ - + self = - + def test_two(self): x = "hello" > assert hasattr(x, 'check') E AssertionError: assert False E + where False = hasattr('hello', 'check') - + test_class.py:8: AssertionError 1 failed, 1 passed in 0.12 seconds @@ -166,14 +164,14 @@ before performing the test function call. Let's just run it:: F ======= FAILURES ======== _______ test_needsfiles ________ - + tmpdir = local('PYTEST_TMPDIR/test_needsfiles0') - + def test_needsfiles(tmpdir): print (tmpdir) > assert 0 E assert 0 - + test_tmpdir.py:3: AssertionError --------------------------- Captured stdout call --------------------------- PYTEST_TMPDIR/test_needsfiles0 diff --git a/doc/en/index.rst b/doc/en/index.rst index 1d2ca57ef..d9414a076 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -28,17 +28,17 @@ To execute it:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_sample.py F - + ======= FAILURES ======== _______ test_answer ________ - + def test_answer(): > assert inc(3) == 5 E assert 4 == 5 E + where 4 = inc(3) - + test_sample.py:5: AssertionError ======= 1 failed in 0.12 seconds ======== @@ -57,7 +57,7 @@ Features - Can run :ref:`unittest ` (including trial) and :ref:`nose ` test suites out of the box; -- Python2.6+, Python3.3+, PyPy-2.3, Jython-2.5 (untested); +- Python 2.7, Python 3.4+, PyPy 2.3, Jython 2.5 (untested); - Rich plugin architecture, with over 315+ `external plugins `_ and thriving community; diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index 1504c251c..b87cb1ae5 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -64,11 +64,11 @@ during import time. If you wish to skip something conditionally then you can use ``skipif`` instead. Here is an example of marking a test function to be skipped -when run on a Python3.3 interpreter:: +when run on a Python3.6 interpreter:: import sys - @pytest.mark.skipif(sys.version_info < (3,3), - reason="requires python3.3") + @pytest.mark.skipif(sys.version_info < (3,6), + reason="requires python3.6") def test_function(): ... @@ -250,8 +250,8 @@ You can change the default value of the ``strict`` parameter using the As with skipif_ you can also mark your expectation of a failure on a particular platform:: - @pytest.mark.xfail(sys.version_info >= (3,3), - reason="python3.3 api changes") + @pytest.mark.xfail(sys.version_info >= (3,6), + reason="python3.6 api changes") def test_function(): ... @@ -311,12 +311,12 @@ Running it with the report-on-xfail option gives this output:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/example, inifile: collected 7 items - + xfail_demo.py xxxxxxx ======= short test summary info ======== XFAIL xfail_demo.py::test_hello XFAIL xfail_demo.py::test_hello2 - reason: [NOTRUN] + reason: [NOTRUN] XFAIL xfail_demo.py::test_hello3 condition: hasattr(os, 'sep') XFAIL xfail_demo.py::test_hello4 @@ -326,7 +326,7 @@ Running it with the report-on-xfail option gives this output:: XFAIL xfail_demo.py::test_hello6 reason: reason XFAIL xfail_demo.py::test_hello7 - + ======= 7 xfailed in 0.12 seconds ======== .. _`skip/xfail with parametrize`: diff --git a/setup.py b/setup.py index b58a4014c..61e880c2a 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ classifiers = [ 'Topic :: Utilities', ] + [ ('Programming Language :: Python :: %s' % x) - for x in '2.7 3 3.4 3.5 3.6'.split() + for x in '2 2.7 3 3.4 3.5 3.6'.split() ] with open('README.rst') as fd: diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 712776906..903e5d499 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -344,7 +344,7 @@ class TestGeneralUsage(object): Importing a module that didn't exist, even if the ImportError was gracefully handled, would make our test crash. - Use recwarn here to silence this warning in Python 2.6 and 2.7: + Use recwarn here to silence this warning in Python 2.7: ImportWarning: Not importing directory '...\not_a_package': missing __init__.py """ testdir.mkdir('not_a_package') diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index f8f8a0365..f7f6123a2 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -345,10 +345,7 @@ def test_excinfo_no_sourcecode(): except ValueError: excinfo = _pytest._code.ExceptionInfo() s = str(excinfo.traceback[-1]) - if py.std.sys.version_info < (2, 5): - assert s == " File '':1 in ?\n ???\n" - else: - assert s == " File '':1 in \n ???\n" + assert s == " File '':1 in \n ???\n" def test_excinfo_no_python_sourcecode(tmpdir): @@ -1244,9 +1241,6 @@ def test_no_recursion_index_on_recursion_error(): except: from _pytest._code.code import ExceptionInfo exc_info = ExceptionInfo() - if sys.version_info[:2] == (2, 6): - assert "'RecursionDepthError' object has no attribute '___" in str(exc_info.getrepr()) - else: - assert 'maximum recursion' in str(exc_info.getrepr()) + assert 'maximum recursion' in str(exc_info.getrepr()) else: assert 0 diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 1d315aa9b..ed45f0896 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -273,7 +273,6 @@ class TestSourceParsingAndCompiling(object): assert getstatement(2, source).lines == source.lines[2:3] assert getstatement(3, source).lines == source.lines[3:4] - @pytest.mark.skipif("sys.version_info < (2,6)") def test_getstatementrange_out_of_bounds_py3(self): source = Source("if xxx:\n from .collections import something") r = source.getstatementrange(1) @@ -283,7 +282,6 @@ class TestSourceParsingAndCompiling(object): source = Source(":") pytest.raises(SyntaxError, lambda: source.getstatementrange(0)) - @pytest.mark.skipif("sys.version_info < (2,6)") def test_compile_to_ast(self): import ast source = Source("x = 4") diff --git a/testing/python/approx.py b/testing/python/approx.py index d591b8ba5..300e1ce86 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -24,11 +24,8 @@ class MyDocTestRunner(doctest.DocTestRunner): class TestApprox(object): def test_repr_string(self): - # for some reason in Python 2.6 it is not displaying the tolerance representation correctly plus_minus = u'\u00b1' if sys.version_info[0] > 2 else u'+-' tol1, tol2, infr = '1.0e-06', '2.0e-06', 'inf' - if sys.version_info[:2] == (2, 6): - tol1, tol2, infr = '???', '???', '???' assert repr(approx(1.0)) == '1.0 {pm} {tol1}'.format(pm=plus_minus, tol1=tol1) assert repr(approx([1.0, 2.0])) == 'approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])'.format( pm=plus_minus, tol1=tol1, tol2=tol2) @@ -375,9 +372,6 @@ class TestApprox(object): assert [3] == [pytest.approx(4)] """) expected = '4.0e-06' - # for some reason in Python 2.6 it is not displaying the tolerance representation correctly - if sys.version_info[:2] == (2, 6): - expected = '???' result = testdir.runpytest() result.stdout.fnmatch_lines([ '*At index 0 diff: 3 != 4 * {0}'.format(expected), diff --git a/testing/python/collect.py b/testing/python/collect.py index ccd5c11e7..c3a204568 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -164,17 +164,10 @@ class TestClass(object): assert fix == 1 """) result = testdir.runpytest() - if sys.version_info < (2, 7): - # in 2.6, the code to handle static methods doesn't work - result.stdout.fnmatch_lines([ - "*collected 0 items*", - "*cannot collect static method*", - ]) - else: - result.stdout.fnmatch_lines([ - "*collected 2 items*", - "*2 passed in*", - ]) + result.stdout.fnmatch_lines([ + "*collected 2 items*", + "*2 passed in*", + ]) def test_setup_teardown_class_as_classmethod(self, testdir): testdir.makepyfile(test_mod1=""" diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 2d61b7440..07912f0b7 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -640,7 +640,7 @@ def test_rewritten(): testdir.tmpdir.join("test_newlines.py").write(b, "wb") assert testdir.runpytest().ret == 0 - @pytest.mark.skipif(sys.version_info < (3, 3), + @pytest.mark.skipif(sys.version_info < (3, 4), reason='packages without __init__.py not supported on python 2') def test_package_without__init__py(self, testdir): pkg = testdir.mkdir('a_package_without_init_py') diff --git a/testing/test_config.py b/testing/test_config.py index 3cad6d587..d049725cd 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -139,7 +139,7 @@ class TestConfigAPI(object): assert config.getoption(x) == "this" pytest.raises(ValueError, "config.getoption('qweqwe')") - @pytest.mark.skipif('sys.version_info[:2] not in [(2, 6), (2, 7)]') + @pytest.mark.skipif('sys.version_info[0] < 3') def test_config_getoption_unicode(self, testdir): testdir.makeconftest(""" from __future__ import unicode_literals diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 02fdf0ada..921592570 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -300,13 +300,7 @@ def test_argcomplete(testdir, monkeypatch): elif not result.stdout.str(): pytest.skip("bash provided no output, argcomplete not available?") else: - if py.std.sys.version_info < (2, 7): - result.stdout.lines = result.stdout.lines[0].split('\x0b') - result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"]) - else: - result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"]) - if py.std.sys.version_info < (2, 7): - return + result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"]) os.mkdir('test_argcomplete.d') arg = 'test_argc' monkeypatch.setenv('COMP_LINE', "pytest " + arg) diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 8051deda4..2bc1630cd 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -168,7 +168,6 @@ def test_teardown_issue1649(testdir): assert type(obj).__name__ != 'TestCaseObjectsShouldBeCleanedUp' -@pytest.mark.skipif("sys.version_info < (2,7)") def test_unittest_skip_issue148(testdir): testpath = testdir.makepyfile(""" import unittest @@ -629,7 +628,6 @@ def test_unittest_typerror_traceback(testdir): assert result.ret == 1 -@pytest.mark.skipif("sys.version_info < (2,7)") @pytest.mark.parametrize('runner', ['pytest', 'unittest']) def test_unittest_expected_failure_for_failing_test_is_xfail(testdir, runner): script = testdir.makepyfile(""" @@ -656,7 +654,6 @@ def test_unittest_expected_failure_for_failing_test_is_xfail(testdir, runner): assert result.ret == 0 -@pytest.mark.skipif("sys.version_info < (2,7)") @pytest.mark.parametrize('runner', ['pytest', 'unittest']) def test_unittest_expected_failure_for_passing_test_is_fail(testdir, runner): script = testdir.makepyfile(""" @@ -787,7 +784,6 @@ def test_issue333_result_clearing(testdir): reprec.assertoutcome(failed=1) -@pytest.mark.skipif("sys.version_info < (2,7)") def test_unittest_raise_skip_issue748(testdir): testdir.makepyfile(test_foo=""" import unittest @@ -803,7 +799,6 @@ def test_unittest_raise_skip_issue748(testdir): """) -@pytest.mark.skipif("sys.version_info < (2,7)") def test_unittest_skip_issue1169(testdir): testdir.makepyfile(test_foo=""" import unittest