From 722ce4fc83e694f6a3404d8874bac730a3d2a1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Alvergnat?= Date: Fri, 12 Oct 2018 22:05:07 +0200 Subject: [PATCH] Add python 3.7 support and fix deprecation warnings Close #11 Close #17 --- .travis.yml | 4 ++-- README.rst | 4 ++-- pylintrc | 3 ++- rebulk/loose.py | 46 ++++++++++++++++++++++++++++++++++++++++---- rebulk/match.py | 10 +++++++--- rebulk/processors.py | 2 +- rebulk/rules.py | 18 ++++++++--------- rebulk/utils.py | 5 ++++- setup.py | 8 +++++--- tox.ini | 7 +------ 10 files changed, 74 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index a705b29..43d764b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,11 @@ python: - 3.4 - 3.5 - 3.6 + # - 3.7 # https://github.com/travis-ci/travis-ci/issues/9815 - pypy install: - - pip install pip --upgrade + - if [ $TRAVIS_PYTHON_VERSION != 2.6 ] && [ $TRAVIS_PYTHON_VERSION != 3.3 ]; then pip install pip --upgrade; fi - pip install -e .[dev,test] - - pip install pytest --upgrade - pip install coveralls script: - if [ $TRAVIS_PYTHON_VERSION != 2.6 ]; then pylint rebulk; fi diff --git a/README.rst b/README.rst index 6e1e589..e04ec62 100644 --- a/README.rst +++ b/README.rst @@ -96,7 +96,7 @@ You can define several patterns with a single ``regex`` method call. .. code-block:: python - >>> Rebulk().regex(r'Wint\wr', 'com\w{3}').matches("Winter is coming...") + >>> Rebulk().regex(r'Wint\wr', r'com\w{3}').matches("Winter is coming...") [, ] All keyword arguments from `re.compile`_ are supported. @@ -136,7 +136,7 @@ If `regex module`_ is available, it automatically supports repeated captures. Defined as a list of 2-tuple, each tuple is an abbreviation. It simply replace ``tuple[0]`` with ``tuple[1]`` in the expression. - >>> Rebulk().regex(r'Custom-separators', abbreviations=[("-", "[\W_]+")])\ + >>> Rebulk().regex(r'Custom-separators', abbreviations=[("-", r"[\W_]+")])\ ... .matches("Custom_separators using-abbreviations") [] diff --git a/pylintrc b/pylintrc index a1389c3..fe47548 100644 --- a/pylintrc +++ b/pylintrc @@ -68,7 +68,8 @@ disable=basestring-builtin,range-builtin-not-iterating,unichr-builtin,buffer-bui map-builtin-not-iterating,old-ne-operator,long-builtin,intern-builtin,zip-builtin-not-iterating,reduce-builtin, unicode-builtin,old-division,xrange-builtin,old-octal-literal,coerce-method, too-few-public-methods,too-many-arguments,too-many-instance-attributes,bad-builtin,too-many-ancestors, - too-few-format-args,fixme,duplicate-code,deprecated-lambda,cyclic-import, + too-few-format-args,fixme,duplicate-code,deprecated-lambda,cyclic-import,useless-object-inheritance, + inconsistent-return-statements, I [REPORTS] diff --git a/rebulk/loose.py b/rebulk/loose.py index 72543b1..427b69a 100644 --- a/rebulk/loose.py +++ b/rebulk/loose.py @@ -3,8 +3,18 @@ """ Various utilities functions """ -import inspect + + import sys +import inspect + +try: + from inspect import getfullargspec as getargspec + _fullargspec_supported = True +except ImportError: + _fullargspec_supported = False + from inspect import getargspec + from .utils import is_iterable if sys.version_info < (3, 4, 0): # pragma: no cover @@ -63,7 +73,7 @@ def function_args(callable_, *args, **kwargs): :return: (args, kwargs) matching the function signature :rtype: tuple """ - argspec = inspect.getargspec(callable_) # pylint:disable=deprecated-method + argspec = getargspec(callable_) # pylint:disable=deprecated-method return argspec_args(argspec, False, *args, **kwargs) @@ -80,7 +90,7 @@ def constructor_args(class_, *args, **kwargs): :return: (args, kwargs) matching the function signature :rtype: tuple """ - argspec = inspect.getargspec(_constructor(class_)) # pylint:disable=deprecated-method + argspec = getargspec(_constructor(class_)) # pylint:disable=deprecated-method return argspec_args(argspec, True, *args, **kwargs) @@ -99,7 +109,7 @@ def argspec_args(argspec, constructor, *args, **kwargs): :return: (args, kwargs) matching the function signature :rtype: tuple """ - if argspec.keywords: + if argspec.varkw: call_kwarg = kwargs else: call_kwarg = dict((k, kwargs[k]) for k in kwargs if k in argspec.args) # Python 2.6 dict comprehension @@ -110,6 +120,34 @@ def argspec_args(argspec, constructor, *args, **kwargs): return call_args, call_kwarg +if not _fullargspec_supported: + def argspec_args_legacy(argspec, constructor, *args, **kwargs): + """ + Return (args, kwargs) matching the argspec object + + :param argspec: argspec to use + :type argspec: argspec + :param constructor: is it a constructor ? + :type constructor: bool + :param args: + :type args: + :param kwargs: + :type kwargs: + :return: (args, kwargs) matching the function signature + :rtype: tuple + """ + if argspec.keywords: + call_kwarg = kwargs + else: + call_kwarg = dict((k, kwargs[k]) for k in kwargs if k in argspec.args) # Python 2.6 dict comprehension + if argspec.varargs: + call_args = args + else: + call_args = args[:len(argspec.args) - (1 if constructor else 0)] + return call_args, call_kwarg + argspec_args = argspec_args_legacy + + def ensure_list(param): """ Retrieves a list from given parameter. diff --git a/rebulk/match.py b/rebulk/match.py index a786df4..8bf4124 100644 --- a/rebulk/match.py +++ b/rebulk/match.py @@ -5,7 +5,11 @@ """ import copy import itertools -from collections import defaultdict, MutableSequence +from collections import defaultdict +try: + from collections.abc import MutableSequence +except ImportError: + from collections import MutableSequence try: from collections import OrderedDict # pylint:disable=ungrouped-imports @@ -778,9 +782,9 @@ def crop(self, crops, predicate=None, index=None): right.start = end if right: ret.append(right) - elif end <= current.end and end > current.start: + elif current.end >= end > current.start: current.start = end - elif start >= current.start and start < current.end: + elif current.start <= start < current.end: current.end = start return filter_index(ret, predicate, index) diff --git a/rebulk/processors.py b/rebulk/processors.py index b9fa52b..6a4f0ba 100644 --- a/rebulk/processors.py +++ b/rebulk/processors.py @@ -30,7 +30,7 @@ def _default_conflict_solver(match, conflicting_match): """ if len(conflicting_match.initiator) < len(match.initiator): return conflicting_match - elif len(match.initiator) < len(conflicting_match.initiator): + if len(match.initiator) < len(conflicting_match.initiator): return match return None diff --git a/rebulk/rules.py b/rebulk/rules.py index 19b563a..2514904 100644 --- a/rebulk/rules.py +++ b/rebulk/rules.py @@ -140,10 +140,9 @@ def then(self, matches, when_response, context): matches.remove(match) ret.append(match) return ret - else: - if when_response in matches: - matches.remove(when_response) - return when_response + if when_response in matches: + matches.remove(when_response) + return when_response class AppendMatch(Consequence): # pylint: disable=abstract-method @@ -164,12 +163,11 @@ def then(self, matches, when_response, context): matches.append(match) ret.append(match) return ret - else: - if self.match_name: - when_response.name = self.match_name - if when_response not in matches: - matches.append(when_response) - return when_response + if self.match_name: + when_response.name = self.match_name + if when_response not in matches: + matches.append(when_response) + return when_response class RenameMatch(Consequence): # pylint: disable=abstract-method diff --git a/rebulk/utils.py b/rebulk/utils.py index 9aaf56d..85ddd41 100644 --- a/rebulk/utils.py +++ b/rebulk/utils.py @@ -3,7 +3,10 @@ """ Various utilities functions """ -from collections import MutableSet +try: + from collections.abc import MutableSet +except ImportError: + from collections import MutableSet from types import GeneratorType diff --git a/setup.py b/setup.py index 9fda917..b3b9e0e 100644 --- a/setup.py +++ b/setup.py @@ -15,11 +15,11 @@ native_requires = ['regex'] -setup_requires = ['pytest-runner'] +setup_requires = ['pytest-runner' + ('<3' if sys.version_info < (2, 7) else '')] -dev_require = ['pytest>=2.7.3', 'pytest-capturelog', 'zest.releaser[recommended]', 'pylint', 'tox'] +dev_require = ['pytest' + ('<3' if sys.version_info < (2, 7) else ''), 'zest.releaser[recommended]', 'pylint', 'tox'] -tests_require = ['pytest'] +tests_require = ['pytest' + ('<3' if sys.version_info < (2, 7) else '')] with io.open('rebulk/__version__.py', 'r') as f: version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]$', f.read(), re.MULTILINE).group(1) @@ -40,6 +40,8 @@ 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Topic :: Software Development :: Libraries :: Python Modules' ], keywords='re regexp regular expression search pattern string match', diff --git a/tox.ini b/tox.ini index ac1ef2d..5dc2c79 100644 --- a/tox.ini +++ b/tox.ini @@ -1,16 +1,11 @@ [tox] -envlist = py26,py27,py33,py34,py35,pypy +envlist = py26,py27,py33,py34,py35,py36,py37,pypy [testenv:py26] commands = {envbindir}/pip install -e .[dev] {envpython} setup.py test -[testenv:py35] -commands = - {envbindir}/pip install -e .[dev] - {envpython} setup.py test - [testenv] commands = {envbindir}/pip install -e .[dev]