diff --git a/conftest.py b/conftest.py index 6fe3544..e90bed9 100644 --- a/conftest.py +++ b/conftest.py @@ -13,8 +13,8 @@ from parso.utils import parse_version_string collect_ignore = ["setup.py"] -VERSIONS_2 = '2.6', '2.7' -VERSIONS_3 = '3.3', '3.4', '3.5', '3.6', '3.7', '3.8' +VERSIONS_2 = '2.7', +VERSIONS_3 = '3.4', '3.5', '3.6', '3.7', '3.8' @pytest.fixture(scope='session') diff --git a/parso/_compatibility.py b/parso/_compatibility.py index db411ee..a7f8ca8 100644 --- a/parso/_compatibility.py +++ b/parso/_compatibility.py @@ -1,14 +1,10 @@ """ -To ensure compatibility from Python ``2.6`` - ``3.3``, a module has been +To ensure compatibility from Python ``2.7`` - ``3.3``, a module has been created. Clearly there is huge need to use conforming syntax. """ import sys import platform -# Cannot use sys.version.major and minor names, because in Python 2.6 it's not -# a namedtuple. -py_version = int(str(sys.version_info[0]) + str(sys.version_info[1])) - # unicode function try: unicode = unicode @@ -39,7 +35,7 @@ def u(string): have to cast back to a unicode (and we know that we always deal with valid unicode, because we check that in the beginning). """ - if py_version >= 30: + if sys.version_info.major >= 3: return str(string) if not isinstance(string, unicode): @@ -48,8 +44,10 @@ def u(string): try: + # Python 2.7 FileNotFoundError = FileNotFoundError except NameError: + # Python 3.3+ FileNotFoundError = IOError @@ -65,39 +63,7 @@ def utf8_repr(func): else: return result - if py_version >= 30: + if sys.version_info.major >= 3: return func else: return wrapper - - -try: - from functools import total_ordering -except ImportError: - # Python 2.6 - def total_ordering(cls): - """Class decorator that fills in missing ordering methods""" - convert = { - '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)), - ('__le__', lambda self, other: self < other or self == other), - ('__ge__', lambda self, other: not self < other)], - '__le__': [('__ge__', lambda self, other: not self <= other or self == other), - ('__lt__', lambda self, other: self <= other and not self == other), - ('__gt__', lambda self, other: not self <= other)], - '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)), - ('__ge__', lambda self, other: self > other or self == other), - ('__le__', lambda self, other: not self > other)], - '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other), - ('__gt__', lambda self, other: self >= other and not self == other), - ('__lt__', lambda self, other: not self >= other)] - } - roots = set(dir(cls)) & set(convert) - if not roots: - raise ValueError('must define at least one ordering operation: < > <= >=') - root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__ - for opname, opfunc in convert[root]: - if opname not in roots: - opfunc.__name__ = opname - opfunc.__doc__ = getattr(int, opname).__doc__ - setattr(cls, opname, opfunc) - return cls diff --git a/parso/python/issue_list.txt b/parso/python/issue_list.txt index e5e2c9d..88ca092 100644 --- a/parso/python/issue_list.txt +++ b/parso/python/issue_list.txt @@ -172,5 +172,5 @@ A list of syntax/indentation errors I've encountered in CPython. Version specific: Python 3.5: 'yield' inside async function -Python 3.3/3.4: +Python 3.4: can use starred expression only as assignment target diff --git a/parso/python/tokenize.py b/parso/python/tokenize.py index c1f78d4..70facf9 100644 --- a/parso/python/tokenize.py +++ b/parso/python/tokenize.py @@ -19,7 +19,6 @@ import itertools as _itertools from codecs import BOM_UTF8 from parso.python.token import PythonTokenTypes -from parso._compatibility import py_version from parso.utils import split_lines @@ -50,7 +49,7 @@ BOM_UTF8_STRING = BOM_UTF8.decode('utf-8') _token_collection_cache = {} -if py_version >= 30: +if sys.version_info.major >= 3: # Python 3 has str.isidentifier() to check if a char is a valid identifier is_identifier = str.isidentifier else: @@ -86,7 +85,7 @@ def _all_string_prefixes(version_info, include_fstring=False, only_fstring=False # and don't contain any permuations (include 'fr', but not # 'rf'). The various permutations will be generated. valid_string_prefixes = ['b', 'r', 'u'] - if version_info >= (3, 0): + if version_info.major >= 3: valid_string_prefixes.append('br') result = set(['']) @@ -106,7 +105,7 @@ def _all_string_prefixes(version_info, include_fstring=False, only_fstring=False # create a list with upper and lower versions of each # character result.update(different_case_versions(t)) - if version_info <= (2, 7): + if version_info.major == 2: # In Python 2 the order cannot just be random. result.update(different_case_versions('ur')) result.update(different_case_versions('br')) @@ -164,7 +163,7 @@ def _create_token_collection(version_info): else: Hexnumber = r'0[xX][0-9a-fA-F]+' Binnumber = r'0[bB][01]+' - if version_info >= (3, 0): + if version_info.major >= 3: Octnumber = r'0[oO][0-7]+' else: Octnumber = '0[oO]?[0-7]+' diff --git a/parso/tree.py b/parso/tree.py index f5871a6..c8c1539 100644 --- a/parso/tree.py +++ b/parso/tree.py @@ -1,6 +1,7 @@ +import sys from abc import abstractmethod, abstractproperty -from parso._compatibility import utf8_repr, encoding, py_version +from parso._compatibility import utf8_repr, encoding from parso.utils import split_lines @@ -321,7 +322,7 @@ class BaseNode(NodeOrLeaf): @utf8_repr def __repr__(self): code = self.get_code().replace('\n', ' ').replace('\r', ' ').strip() - if not py_version >= 30: + if not sys.version_info.major >= 3: code = code.encode(encoding, 'replace') return "<%s: %s@%s,%s>" % \ (type(self).__name__, code, self.start_pos[0], self.start_pos[1]) diff --git a/parso/utils.py b/parso/utils.py index 579c4cc..d26c88e 100644 --- a/parso/utils.py +++ b/parso/utils.py @@ -2,8 +2,9 @@ from collections import namedtuple import re import sys from ast import literal_eval +from functools import total_ordering -from parso._compatibility import unicode, total_ordering +from parso._compatibility import unicode # The following is a list in Python that are line breaks in str.splitlines, but # not in Python. In Python only \r (Carriage Return, 0xD) and \n (Line Feed, diff --git a/setup.py b/setup.py index 0d70dbc..443b2a7 100755 --- a/setup.py +++ b/setup.py @@ -27,6 +27,7 @@ setup(name='parso', packages=find_packages(exclude=['test']), package_data={'parso': ['python/grammar*.txt']}, platforms=['any'], + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Plugins', @@ -34,10 +35,8 @@ setup(name='parso', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', diff --git a/test/failing_examples.py b/test/failing_examples.py index 0fc3a67..3347cf5 100644 --- a/test/failing_examples.py +++ b/test/failing_examples.py @@ -282,10 +282,7 @@ if sys.version_info >= (3, 6): 'f"s" b""', 'b"s" f""', ] -if sys.version_info >= (2, 7): - # This is something that raises a different error in 2.6 than in the other - # versions. Just skip it for 2.6. - FAILING_EXAMPLES.append('[a, 1] += 3') +FAILING_EXAMPLES.append('[a, 1] += 3') if sys.version_info[:2] == (3, 5): # yields are not allowed in 3.5 async functions. Therefore test them diff --git a/test/test_normalizer_issues_files.py b/test/test_normalizer_issues_files.py index 7f692d1..2aea1da 100644 --- a/test/test_normalizer_issues_files.py +++ b/test/test_normalizer_issues_files.py @@ -5,9 +5,9 @@ tests of pydocstyle. import difflib import re +from functools import total_ordering import parso -from parso._compatibility import total_ordering from parso.utils import python_bytes_to_unicode diff --git a/test/test_python_errors.py b/test/test_python_errors.py index 78945db..f3a3d15 100644 --- a/test/test_python_errors.py +++ b/test/test_python_errors.py @@ -118,22 +118,12 @@ def _get_actual_exception(code): assert False, "The piece of code should raise an exception." # SyntaxError - # Python 2.6 has a bit different error messages here, so skip it. - if sys.version_info[:2] == (2, 6) and wanted == 'SyntaxError: unexpected EOF while parsing': - wanted = 'SyntaxError: invalid syntax' - if wanted == 'SyntaxError: non-keyword arg after keyword arg': # The python 3.5+ way, a bit nicer. wanted = 'SyntaxError: positional argument follows keyword argument' elif wanted == 'SyntaxError: assignment to keyword': return [wanted, "SyntaxError: can't assign to keyword", 'SyntaxError: cannot assign to __debug__'], line_nr - elif wanted == 'SyntaxError: assignment to None': - # Python 2.6 does has a slightly different error. - wanted = 'SyntaxError: cannot assign to None' - elif wanted == 'SyntaxError: can not assign to __debug__': - # Python 2.6 does has a slightly different error. - wanted = 'SyntaxError: cannot assign to __debug__' elif wanted == 'SyntaxError: can use starred expression only as assignment target': # Python 3.4/3.4 have a bit of a different warning than 3.5/3.6 in # certain places. But in others this error makes sense. diff --git a/test/test_tokenize.py b/test/test_tokenize.py index 3858145..f0fc4c2 100644 --- a/test/test_tokenize.py +++ b/test/test_tokenize.py @@ -4,8 +4,8 @@ import sys from textwrap import dedent import pytest +import sys -from parso._compatibility import py_version from parso.utils import split_lines, parse_version_string from parso.python.token import PythonTokenTypes from parso.python import tokenize @@ -137,7 +137,7 @@ def test_identifier_contains_unicode(): ''') token_list = _get_token_list(fundef) unicode_token = token_list[1] - if py_version >= 30: + if sys.version_info.major >= 3: assert unicode_token[0] == NAME else: # Unicode tokens in Python 2 seem to be identified as operators. @@ -185,19 +185,19 @@ def test_ur_literals(): assert typ == NAME check('u""') - check('ur""', is_literal=not py_version >= 30) - check('Ur""', is_literal=not py_version >= 30) - check('UR""', is_literal=not py_version >= 30) + check('ur""', is_literal=not sys.version_info.major >= 3) + check('Ur""', is_literal=not sys.version_info.major >= 3) + check('UR""', is_literal=not sys.version_info.major >= 3) check('bR""') # Starting with Python 3.3 this ordering is also possible. - if py_version >= 33: + if sys.version_info.major >= 3: check('Rb""') # Starting with Python 3.6 format strings where introduced. - check('fr""', is_literal=py_version >= 36) - check('rF""', is_literal=py_version >= 36) - check('f""', is_literal=py_version >= 36) - check('F""', is_literal=py_version >= 36) + check('fr""', is_literal=sys.version_info >= (3, 6)) + check('rF""', is_literal=sys.version_info >= (3, 6)) + check('f""', is_literal=sys.version_info >= (3, 6)) + check('F""', is_literal=sys.version_info >= (3, 6)) def test_error_literal(): diff --git a/tox.ini b/tox.ini index cebd844..c0f7675 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,9 @@ [tox] -envlist = {py26,py27,py33,py34,py35,py36,py37,py38} +envlist = {py27,py34,py35,py36,py37,py38} [testenv] extras = testing deps = - py26,py33: pytest>=3.0.7,<3.3 py27,py34: pytest<3.3 - py26,py33: setuptools<37 coverage: coverage setenv = # https://github.com/tomchristie/django-rest-framework/issues/1957