Hello community, here is the log from the commit of package python-pyflakes for openSUSE:Factory checked in at 2018-08-27 12:54:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pyflakes (Old) and /work/SRC/openSUSE:Factory/.python-pyflakes.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyflakes" Mon Aug 27 12:54:07 2018 rev:22 rq:629206 version:2.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pyflakes/python-pyflakes.changes 2018-01-19 11:48:50.176017628 +0100 +++ /work/SRC/openSUSE:Factory/.python-pyflakes.new/python-pyflakes.changes 2018-08-27 12:54:15.392481745 +0200 @@ -1,0 +2,11 @@ +Mon Jul 30 15:07:24 UTC 2018 - t.gru...@katodev.de + +- update to version 2.0.0: + * Drop support for EOL Python <2.7 and 3.2-3.3 + * Check for unused exception binding in `except:` block + * Handle string literal type annotations + * Ignore redefinitions of `_`, unless originally defined by import + * Support `__class__` without `self` in Python 3 + * Issue an error for `raise NotImplemented(...)` + +------------------------------------------------------------------- Old: ---- pyflakes-1.6.0.tar.gz New: ---- pyflakes-2.0.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pyflakes.spec ++++++ --- /var/tmp/diff_new_pack.wnJMS7/_old 2018-08-27 12:54:16.636483111 +0200 +++ /var/tmp/diff_new_pack.wnJMS7/_new 2018-08-27 12:54:16.640483115 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without test Name: python-pyflakes -Version: 1.6.0 +Version: 2.0.0 Release: 0 Url: https://github.com/PyCQA/pyflakes Summary: Passive checker of Python programs ++++++ pyflakes-1.6.0.tar.gz -> pyflakes-2.0.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/NEWS.txt new/pyflakes-2.0.0/NEWS.txt --- old/pyflakes-1.6.0/NEWS.txt 2017-08-03 16:36:44.000000000 +0200 +++ new/pyflakes-2.0.0/NEWS.txt 2018-05-20 19:06:28.000000000 +0200 @@ -1,3 +1,11 @@ +2.0.0 (2018-05-20) + - Drop support for EOL Python <2.7 and 3.2-3.3 + - Check for unused exception binding in `except:` block + - Handle string literal type annotations + - Ignore redefinitions of `_`, unless originally defined by import + - Support `__class__` without `self` in Python 3 + - Issue an error for `raise NotImplemented(...)` + 1.6.0 (2017-08-03) - Process function scope variable annotations for used names - Find Python files without extensions by their shebang diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/PKG-INFO new/pyflakes-2.0.0/PKG-INFO --- old/pyflakes-1.6.0/PKG-INFO 2017-08-03 16:54:11.000000000 +0200 +++ new/pyflakes-2.0.0/PKG-INFO 2018-05-20 19:13:28.000000000 +0200 @@ -1,11 +1,12 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: pyflakes -Version: 1.6.0 +Version: 2.0.0 Summary: passive checker of Python programs Home-page: https://github.com/PyCQA/pyflakes Author: A lot of people Author-email: code-qual...@python.org License: MIT +Description-Content-Type: UNKNOWN Description: ======== Pyflakes ======== @@ -17,7 +18,7 @@ modules with side effects. It's also much faster. It is `available on PyPI <https://pypi.python.org/pypi/pyflakes>`_ - and it supports all active versions of Python from 2.5 to 3.6. + and it supports all active versions of Python: 2.7 and 3.4 to 3.7. @@ -40,7 +41,7 @@ * If you require more options and more flexibility, you could give a look to Flake8_ too. - + Design Principles ----------------- @@ -91,6 +92,11 @@ .. _`rebase your changes`: https://git-scm.com/book/en/v2/Git-Branching-Rebasing .. _`GitHub pull request`: https://github.com/PyCQA/pyflakes/pulls + Changelog + --------- + + Please see `NEWS.txt <NEWS.txt>`_. + Platform: UNKNOWN Classifier: Development Status :: 6 - Mature Classifier: Environment :: Console @@ -98,6 +104,14 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development Classifier: Topic :: Utilities +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/README.rst new/pyflakes-2.0.0/README.rst --- old/pyflakes-1.6.0/README.rst 2017-08-03 16:28:59.000000000 +0200 +++ new/pyflakes-2.0.0/README.rst 2018-05-20 18:58:57.000000000 +0200 @@ -9,7 +9,7 @@ modules with side effects. It's also much faster. It is `available on PyPI <https://pypi.python.org/pypi/pyflakes>`_ -and it supports all active versions of Python from 2.5 to 3.6. +and it supports all active versions of Python: 2.7 and 3.4 to 3.7. @@ -32,7 +32,7 @@ * If you require more options and more flexibility, you could give a look to Flake8_ too. - + Design Principles ----------------- @@ -82,3 +82,8 @@ .. _Pychecker: http://pychecker.sourceforge.net/ .. _`rebase your changes`: https://git-scm.com/book/en/v2/Git-Branching-Rebasing .. _`GitHub pull request`: https://github.com/PyCQA/pyflakes/pulls + +Changelog +--------- + +Please see `NEWS.txt <NEWS.txt>`_. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/__init__.py new/pyflakes-2.0.0/pyflakes/__init__.py --- old/pyflakes-1.6.0/pyflakes/__init__.py 2017-08-03 16:35:03.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/__init__.py 2018-05-20 19:06:40.000000000 +0200 @@ -1 +1 @@ -__version__ = '1.6.0' +__version__ = '2.0.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/__main__.py new/pyflakes-2.0.0/pyflakes/__main__.py --- old/pyflakes-1.6.0/pyflakes/__main__.py 2014-09-23 16:08:41.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/__main__.py 2018-05-20 18:58:57.000000000 +0200 @@ -1,5 +1,5 @@ from pyflakes.api import main -# python -m pyflakes (with Python >= 2.7) +# python -m pyflakes if __name__ == '__main__': main(prog='pyflakes') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/api.py new/pyflakes-2.0.0/pyflakes/api.py --- old/pyflakes-1.6.0/pyflakes/api.py 2017-06-21 16:37:06.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/api.py 2018-05-20 18:58:57.000000000 +0200 @@ -89,19 +89,8 @@ if reporter is None: reporter = modReporter._makeDefaultReporter() try: - # in Python 2.6, compile() will choke on \r\n line endings. In later - # versions of python it's smarter, and we want binary mode to give - # compile() the best opportunity to do the right thing WRT text - # encodings. - if sys.version_info < (2, 7): - mode = 'rU' - else: - mode = 'rb' - - with open(filename, mode) as f: + with open(filename, 'rb') as f: codestr = f.read() - if sys.version_info < (2, 7): - codestr += '\n' # Work around for Python <= 2.6 except UnicodeError: reporter.unexpectedError(filename, 'problem decoding source') return 1 @@ -117,6 +106,10 @@ if filename.endswith('.py'): return True + # Avoid obvious Emacs backup files + if filename.endswith("~"): + return False + max_bytes = 128 try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/checker.py new/pyflakes-2.0.0/pyflakes/checker.py --- old/pyflakes-1.6.0/pyflakes/checker.py 2017-06-21 16:37:06.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/checker.py 2018-05-20 18:58:57.000000000 +0200 @@ -5,14 +5,13 @@ Also, it models the Bindings and Scopes. """ import __future__ +import ast import doctest import os import sys PY2 = sys.version_info < (3, 0) -PY32 = sys.version_info < (3, 3) # Python 2.5 to 3.2 -PY33 = sys.version_info < (3, 4) # Python 2.5 to 3.3 -PY34 = sys.version_info < (3, 5) # Python 2.5 to 3.4 +PY34 = sys.version_info < (3, 5) # Python 2.7 to 3.4 try: sys.pypy_version_info PYPY = True @@ -21,16 +20,6 @@ builtin_vars = dir(__import__('__builtin__' if PY2 else 'builtins')) -try: - import ast -except ImportError: # Python 2.5 - import _ast as ast - - if 'decorator_list' not in ast.ClassDef._fields: - # Patch the missing attribute 'decorator_list' - ast.ClassDef.decorator_list = () - ast.FunctionDef.decorator_list = property(lambda s: s.decorators) - from pyflakes import messages @@ -38,12 +27,22 @@ def getNodeType(node_class): # workaround str.upper() which is locale-dependent return str(unicode(node_class.__name__).upper()) + + def get_raise_argument(node): + return node.type + else: def getNodeType(node_class): return node_class.__name__.upper() + def get_raise_argument(node): + return node.exc + + # Silence `pyflakes` from reporting `undefined name 'unicode'` in Python 3. + unicode = str + # Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally) -if PY32: +if PY2: def getAlternatives(n): if isinstance(n, (ast.If, ast.TryFinally)): return [n.body] @@ -128,13 +127,17 @@ result.name, result, ) - elif (not PY33) and isinstance(item, ast.NameConstant): + elif (not PY2) and isinstance(item, ast.NameConstant): # None, True, False are nameconstants in python3, but names in 2 return item.value else: return UnhandledKeyType() +def is_notimplemented_name_node(node): + return isinstance(node, ast.Name) and getNodeName(node) == 'NotImplemented' + + class Binding(object): """ Represents the binding of a value to a name. @@ -407,8 +410,8 @@ @ivar globals: Names declared 'global' in this function. """ usesLocals = False - alwaysUsed = set(['__tracebackhide__', - '__traceback_info__', '__traceback_supplement__']) + alwaysUsed = {'__tracebackhide__', '__traceback_info__', + '__traceback_supplement__'} def __init__(self): super(FunctionScope, self).__init__() @@ -676,8 +679,9 @@ self.report(messages.RedefinedInListComp, node, value.name, existing.source) elif not existing.used and value.redefines(existing): - self.report(messages.RedefinedWhileUnused, - node, value.name, existing.source) + if value.name != '_' or isinstance(existing, Importation): + self.report(messages.RedefinedWhileUnused, + node, value.name, existing.source) elif isinstance(existing, Importation) and value.redefines(existing): existing.redefined.append(node) @@ -706,10 +710,14 @@ # try enclosing function scopes and global scope for scope in self.scopeStack[-1::-1]: - # only generators used in a class scope can access the names - # of the class. this is skipped during the first iteration - if in_generators is False and isinstance(scope, ClassScope): - continue + if isinstance(scope, ClassScope): + if not PY2 and name == '__class__': + return + elif in_generators is False: + # only generators used in a class scope can access the + # names of the class. this is skipped during the first + # iteration + continue try: scope[name].used = (self.scope, node) @@ -919,12 +927,45 @@ self.popScope() self.scopeStack = saved_stack + def handleAnnotation(self, annotation, node): + if isinstance(annotation, ast.Str): + # Defer handling forward annotation. + def handleForwardAnnotation(): + try: + tree = ast.parse(annotation.s) + except SyntaxError: + self.report( + messages.ForwardAnnotationSyntaxError, + node, + annotation.s, + ) + return + + body = tree.body + if len(body) != 1 or not isinstance(body[0], ast.Expr): + self.report( + messages.ForwardAnnotationSyntaxError, + node, + annotation.s, + ) + return + + parsed_annotation = tree.body[0].value + for descendant in ast.walk(parsed_annotation): + ast.copy_location(descendant, annotation) + + self.handleNode(parsed_annotation, node) + + self.deferFunction(handleForwardAnnotation) + else: + self.handleNode(annotation, node) + def ignore(self, node): pass # "stmt" type nodes DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \ - ASYNCWITH = ASYNCWITHITEM = RAISE = TRYFINALLY = EXEC = \ + ASYNCWITH = ASYNCWITHITEM = TRYFINALLY = EXEC = \ EXPR = ASSIGN = handleChildren PASS = ignore @@ -948,6 +989,19 @@ EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = \ MATMULT = ignore + def RAISE(self, node): + self.handleChildren(node) + + arg = get_raise_argument(node) + + if isinstance(arg, ast.Call): + if is_notimplemented_name_node(arg.func): + # Handle "raise NotImplemented(...)" + self.report(messages.RaiseNotImplemented, node) + elif is_notimplemented_name_node(arg): + # Handle "raise NotImplemented" + self.report(messages.RaiseNotImplemented, node) + # additional node types COMPREHENSION = KEYWORD = FORMATTEDVALUE = JOINEDSTR = handleChildren @@ -1141,9 +1195,9 @@ wildcard = getattr(node.args, arg_name) if not wildcard: continue - args.append(wildcard if PY33 else wildcard.arg) + args.append(wildcard if PY2 else wildcard.arg) if is_py3_func: - if PY33: # Python 2.5 to 3.3 + if PY2: # Python 2.7 argannotation = arg_name + 'annotation' annotations.append(getattr(node.args, argannotation)) else: # Python >= 3.4 @@ -1157,9 +1211,11 @@ if arg in args[:idx]: self.report(messages.DuplicateArgument, node, arg) - for child in annotations + defaults: - if child: - self.handleNode(child, node) + for annotation in annotations: + self.handleAnnotation(annotation, node) + + for default in defaults: + self.handleNode(default, node) def runFunction(): @@ -1182,7 +1238,7 @@ self.report(messages.UnusedVariable, binding.source, name) self.deferAssignment(checkUnusedAssignments) - if PY32: + if PY2: def checkReturnWithArgumentInsideGenerator(): """ Check to see if there is any return statement with @@ -1319,34 +1375,52 @@ self.handleChildren(node) return - # 3.x: the name of the exception, which is not a Name node, but - # a simple string, creates a local that is only bound within the scope - # of the except: block. + # If the name already exists in the scope, modify state of existing + # binding. + if node.name in self.scope: + self.handleNodeStore(node) + + # 3.x: the name of the exception, which is not a Name node, but a + # simple string, creates a local that is only bound within the scope of + # the except: block. As such, temporarily remove the existing binding + # to more accurately determine if the name is used in the except: + # block. for scope in self.scopeStack[::-1]: - if node.name in scope: - is_name_previously_defined = True + try: + binding = scope.pop(node.name) + except KeyError: + pass + else: + prev_definition = scope, binding break else: - is_name_previously_defined = False + prev_definition = None self.handleNodeStore(node) self.handleChildren(node) - if not is_name_previously_defined: - # See discussion on https://github.com/PyCQA/pyflakes/pull/59 - # We're removing the local name since it's being unbound - # after leaving the except: block and it's always unbound - # if the except: block is never entered. This will cause an - # "undefined name" error raised if the checked code tries to - # use the name afterwards. - # - # Unless it's been removed already. Then do nothing. + # See discussion on https://github.com/PyCQA/pyflakes/pull/59 - try: - del self.scope[node.name] - except KeyError: - pass + # We're removing the local name since it's being unbound after leaving + # the except: block and it's always unbound if the except: block is + # never entered. This will cause an "undefined name" error raised if + # the checked code tries to use the name afterwards. + # + # Unless it's been removed already. Then do nothing. + + try: + binding = self.scope.pop(node.name) + except KeyError: + pass + else: + if not binding.used: + self.report(messages.UnusedVariable, node, node.name) + + # Restore. + if prev_definition: + scope, binding = prev_definition + scope[node.name] = binding def ANNASSIGN(self, node): if node.value: @@ -1354,7 +1428,7 @@ # Otherwise it's not really ast.Store and shouldn't silence # UndefinedLocal warnings. self.handleNode(node.target, node) - self.handleNode(node.annotation, node) + self.handleAnnotation(node.annotation, node) if node.value: # If the assignment has value, handle the *value* now. self.handleNode(node.value, node) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/messages.py new/pyflakes-2.0.0/pyflakes/messages.py --- old/pyflakes-1.6.0/pyflakes/messages.py 2016-12-30 16:09:43.000000000 +0100 +++ new/pyflakes-2.0.0/pyflakes/messages.py 2018-05-20 18:58:57.000000000 +0200 @@ -231,3 +231,15 @@ Assertion test is a tuple, which are always True. """ message = 'assertion is always true, perhaps remove parentheses?' + + +class ForwardAnnotationSyntaxError(Message): + message = 'syntax error in forward annotation %r' + + def __init__(self, filename, loc, annotation): + Message.__init__(self, filename, loc) + self.message_args = (annotation,) + + +class RaiseNotImplemented(Message): + message = "'raise NotImplemented' should be 'raise NotImplementedError'" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/test/harness.py new/pyflakes-2.0.0/pyflakes/test/harness.py --- old/pyflakes-1.6.0/pyflakes/test/harness.py 2015-11-17 14:16:01.000000000 +0100 +++ new/pyflakes-2.0.0/pyflakes/test/harness.py 2018-05-20 18:58:57.000000000 +0200 @@ -1,5 +1,4 @@ -import sys import textwrap import unittest @@ -7,12 +6,8 @@ __all__ = ['TestCase', 'skip', 'skipIf'] -if sys.version_info < (2, 7): - skip = lambda why: (lambda func: 'skip') # not callable - skipIf = lambda cond, why: (skip(why) if cond else lambda func: func) -else: - skip = unittest.skip - skipIf = unittest.skipIf +skip = unittest.skip +skipIf = unittest.skipIf PyCF_ONLY_AST = 1024 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/test/test_api.py new/pyflakes-2.0.0/pyflakes/test/test_api.py --- old/pyflakes-1.6.0/pyflakes/test/test_api.py 2017-06-21 16:37:06.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/test/test_api.py 2018-05-20 18:58:57.000000000 +0200 @@ -180,6 +180,7 @@ """ os.mkdir(os.path.join(self.tempdir, 'foo')) apath = self.makeEmptyFile('foo', 'a.py') + self.makeEmptyFile('foo', 'a.py~') os.mkdir(os.path.join(self.tempdir, 'bar')) bpath = self.makeEmptyFile('bar', 'b.py') cpath = self.makeEmptyFile('c.py') @@ -514,6 +515,7 @@ foo(bar=baz, bax) %s""" % (sourcePath, column, message, last_line)]) + @skipIf(PYPY, 'Output in PyPy varies highly, depending on version') def test_invalidEscape(self): """ The invalid escape syntax raises ValueError in Python 2 @@ -523,13 +525,6 @@ sourcePath = self.makeTempFile(r"foo = '\xyz'") if ver < (3,): decoding_error = "%s: problem decoding source\n" % (sourcePath,) - elif PYPY: - # pypy3 only - decoding_error = """\ -%s:1:6: %s: ('unicodeescape', b'\\\\xyz', 0, 2, 'truncated \\\\xXX escape') -foo = '\\xyz' - ^ -""" % (sourcePath, 'UnicodeDecodeError') else: last_line = ' ^\n' if ERROR_HAS_LAST_LINE else '' # Column has been "fixed" since 3.2.4 and 3.3.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/test/test_dict.py new/pyflakes-2.0.0/pyflakes/test/test_dict.py --- old/pyflakes-1.6.0/pyflakes/test/test_dict.py 2016-09-01 21:49:06.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/test/test_dict.py 2018-05-20 18:58:57.000000000 +0200 @@ -19,15 +19,11 @@ @skipIf(version_info < (3,), "bytes and strings with same 'value' are not equal in python3") - @skipIf(version_info[0:2] == (3, 2), - "python3.2 does not allow u"" literal string definition") def test_duplicate_keys_bytes_vs_unicode_py3(self): self.flakes("{b'a': 1, u'a': 2}") @skipIf(version_info < (3,), "bytes and strings with same 'value' are not equal in python3") - @skipIf(version_info[0:2] == (3, 2), - "python3.2 does not allow u"" literal string definition") def test_duplicate_values_bytes_vs_unicode_py3(self): self.flakes( "{1: b'a', 1: u'a'}", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/test/test_imports.py new/pyflakes-2.0.0/pyflakes/test/test_imports.py --- old/pyflakes-1.6.0/pyflakes/test/test_imports.py 2016-09-01 21:49:06.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/test/test_imports.py 2018-05-20 18:58:57.000000000 +0200 @@ -1,4 +1,3 @@ - from sys import version_info from pyflakes import messages as m @@ -570,12 +569,15 @@ ''') def test_redefinedByExcept(self): - as_exc = ', ' if version_info < (2, 6) else ' as ' + expected = [m.RedefinedWhileUnused] + if version_info >= (3,): + # The exc variable is unused inside the exception handler. + expected.append(m.UnusedVariable) self.flakes(''' import fu try: pass - except Exception%sfu: pass - ''' % as_exc, m.RedefinedWhileUnused) + except Exception as fu: pass + ''', *expected) def test_usedInRaise(self): self.flakes(''' @@ -1146,13 +1148,6 @@ return "hello" ''', m.UndefinedName) - -class Python26Tests(TestCase): - """ - Tests for checking of syntax which is valid in Python 2.6 and newer. - """ - - @skipIf(version_info < (2, 6), "Python >= 2.6 only") def test_usedAsClassDecorator(self): """ Using an imported name as a class decorator results in no warnings, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/test/test_other.py new/pyflakes-2.0.0/pyflakes/test/test_other.py --- old/pyflakes-1.6.0/pyflakes/test/test_other.py 2017-06-21 16:37:02.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/test/test_other.py 2018-05-20 18:58:57.000000000 +0200 @@ -81,7 +81,6 @@ (1 for a, b in [(1, 2)]) ''') - @skipIf(version_info < (2, 7), "Python >= 2.7 only") def test_redefinedInSetComprehension(self): """ Test that reusing a variable in a set comprehension does not raise @@ -111,7 +110,6 @@ {1 for a, b in [(1, 2)]} ''') - @skipIf(version_info < (2, 7), "Python >= 2.7 only") def test_redefinedInDictComprehension(self): """ Test that reusing a variable in a dict comprehension does not raise @@ -151,6 +149,25 @@ def a(): pass ''', m.RedefinedWhileUnused) + def test_redefinedUnderscoreFunction(self): + """ + Test that shadowing a function definition named with underscore doesn't + raise anything. + """ + self.flakes(''' + def _(): pass + def _(): pass + ''') + + def test_redefinedUnderscoreImportation(self): + """ + Test that shadowing an underscore importation raises a warning. + """ + self.flakes(''' + from .i18n import _ + def _(): pass + ''', m.RedefinedWhileUnused) + def test_redefinedClassFunction(self): """ Test that shadowing a function definition in a class suite with another @@ -260,7 +277,6 @@ a = classmethod(a) ''') - @skipIf(version_info < (2, 6), "Python >= 2.6 only") def test_modernProperty(self): self.flakes(""" class A: @@ -1565,7 +1581,6 @@ pass ''', m.UndefinedName) - @skipIf(version_info < (2, 7), "Python >= 2.7 only") def test_dictComprehension(self): """ Dict comprehensions are properly handled. @@ -1574,7 +1589,6 @@ a = {1: x for x in range(10)} ''') - @skipIf(version_info < (2, 7), "Python >= 2.7 only") def test_setComprehensionAndLiteral(self): """ Set comprehensions are properly handled. @@ -1585,17 +1599,31 @@ ''') def test_exceptionUsedInExcept(self): - as_exc = ', ' if version_info < (2, 6) else ' as ' self.flakes(''' try: pass - except Exception%se: e - ''' % as_exc) + except Exception as e: e + ''') + + self.flakes(''' + def download_review(): + try: pass + except Exception as e: e + ''') + + @skipIf(version_info < (3,), + "In Python 2 exception names stay bound after the exception handler") + def test_exceptionUnusedInExcept(self): + self.flakes(''' + try: pass + except Exception as e: pass + ''', m.UnusedVariable) + def test_exceptionUnusedInExceptInFunction(self): self.flakes(''' def download_review(): try: pass - except Exception%se: e - ''' % as_exc) + except Exception as e: pass + ''', m.UnusedVariable) def test_exceptWithoutNameInFunction(self): """ @@ -1874,3 +1902,94 @@ class C: foo: not_a_real_type = None ''', m.UndefinedName) + self.flakes(''' + from foo import Bar + bar: Bar + ''') + self.flakes(''' + from foo import Bar + bar: 'Bar' + ''') + self.flakes(''' + import foo + bar: foo.Bar + ''') + self.flakes(''' + import foo + bar: 'foo.Bar' + ''') + self.flakes(''' + from foo import Bar + def f(bar: Bar): pass + ''') + self.flakes(''' + from foo import Bar + def f(bar: 'Bar'): pass + ''') + self.flakes(''' + from foo import Bar + def f(bar) -> Bar: return bar + ''') + self.flakes(''' + from foo import Bar + def f(bar) -> 'Bar': return bar + ''') + self.flakes(''' + bar: 'Bar' + ''', m.UndefinedName) + self.flakes(''' + bar: 'foo.Bar' + ''', m.UndefinedName) + self.flakes(''' + from foo import Bar + bar: str + ''', m.UnusedImport) + self.flakes(''' + from foo import Bar + def f(bar: str): pass + ''', m.UnusedImport) + self.flakes(''' + def f(a: A) -> A: pass + class A: pass + ''', m.UndefinedName, m.UndefinedName) + self.flakes(''' + def f(a: 'A') -> 'A': return a + class A: pass + ''') + self.flakes(''' + a: A + class A: pass + ''', m.UndefinedName) + self.flakes(''' + a: 'A' + class A: pass + ''') + self.flakes(''' + a: 'A B' + ''', m.ForwardAnnotationSyntaxError) + self.flakes(''' + a: 'A; B' + ''', m.ForwardAnnotationSyntaxError) + self.flakes(''' + a: '1 + 2' + ''') + self.flakes(''' + a: 'a: "A"' + ''', m.ForwardAnnotationSyntaxError) + + def test_raise_notimplemented(self): + self.flakes(''' + raise NotImplementedError("This is fine") + ''') + + self.flakes(''' + raise NotImplementedError + ''') + + self.flakes(''' + raise NotImplemented("This isn't gonna work") + ''', m.RaiseNotImplemented) + + self.flakes(''' + raise NotImplemented + ''', m.RaiseNotImplemented) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes/test/test_undefined_names.py new/pyflakes-2.0.0/pyflakes/test/test_undefined_names.py --- old/pyflakes-1.6.0/pyflakes/test/test_undefined_names.py 2016-05-06 18:40:47.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes/test/test_undefined_names.py 2018-05-20 18:58:57.000000000 +0200 @@ -25,15 +25,16 @@ @skipIf(version_info < (3,), 'in Python 2 exception names stay bound after the except: block') def test_undefinedExceptionName(self): - """Exception names can't be used after the except: block.""" + """Exception names can't be used after the except: block. + + The exc variable is unused inside the exception handler.""" self.flakes(''' try: raise ValueError('ve') except ValueError as exc: pass exc - ''', - m.UndefinedName) + ''', m.UndefinedName, m.UnusedVariable) def test_namesDeclaredInExceptBlocks(self): """Locals declared in except: blocks can be used after the block. @@ -71,7 +72,8 @@ """Exception names are unbound after the `except:` block. Last line will raise UnboundLocalError on Python 3 but would print out - 've' on Python 2.""" + 've' on Python 2. The exc variable is unused inside the exception + handler.""" self.flakes(''' try: raise ValueError('ve') @@ -79,14 +81,15 @@ pass print(exc) exc = 'Original value' - ''', - m.UndefinedName) + ''', m.UndefinedName, m.UnusedVariable) def test_undefinedExceptionNameObscuringLocalVariableFalsePositive1(self): """Exception names obscure locals, can't be used after. Unless. Last line will never raise UnboundLocalError because it's only entered if no exception was raised.""" + # The exc variable is unused inside the exception handler. + expected = [] if version_info < (3,) else [m.UnusedVariable] self.flakes(''' exc = 'Original value' try: @@ -95,7 +98,7 @@ print('exception logged') raise exc - ''') + ''', *expected) def test_delExceptionInExcept(self): """The exception name can be deleted in the except: block.""" @@ -111,6 +114,8 @@ Last line will never raise UnboundLocalError because `error` is only falsy if the `except:` block has not been entered.""" + # The exc variable is unused inside the exception handler. + expected = [] if version_info < (3,) else [m.UnusedVariable] self.flakes(''' exc = 'Original value' error = None @@ -122,7 +127,7 @@ print(error) else: exc - ''') + ''', *expected) @skip('error reporting disabled due to false positives below') def test_undefinedExceptionNameObscuringGlobalVariable(self): @@ -168,6 +173,8 @@ Last line will never raise NameError because it's only entered if no exception was raised.""" + # The exc variable is unused inside the exception handler. + expected = [] if version_info < (3,) else [m.UnusedVariable] self.flakes(''' exc = 'Original value' def func(): @@ -178,13 +185,15 @@ print('exception logged') raise exc - ''') + ''', *expected) def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive2(self): """Exception names obscure globals, can't be used after. Unless. Last line will never raise NameError because `error` is only falsy if the `except:` block has not been entered.""" + # The exc variable is unused inside the exception handler. + expected = [] if version_info < (3,) else [m.UnusedVariable] self.flakes(''' exc = 'Original value' def func(): @@ -198,7 +207,7 @@ print(error) else: exc - ''') + ''', *expected) def test_functionsNeedGlobalScope(self): self.flakes(''' @@ -719,14 +728,13 @@ B = dict((i, str(i)) for i in T) ''') - if version_info >= (2, 7): - self.flakes(''' - class A: - T = range(10) - - X = {x for x in T} - Y = {x:x for x in T} - ''') + self.flakes(''' + class A: + T = range(10) + + X = {x for x in T} + Y = {x:x for x in T} + ''') def test_definedInClassNested(self): """Defined name for nested generator expressions in a class.""" @@ -752,7 +760,6 @@ (42 for i in range(i)) ''', m.UndefinedName) - @skipIf(version_info < (2, 7), 'Dictionary comprehensions do not exist') def test_definedFromLambdaInDictionaryComprehension(self): """ Defined name referenced from a lambda function within a dict/set @@ -771,7 +778,6 @@ any(lambda: id(x) for x in range(10)) ''') - @skipIf(version_info < (2, 7), 'Dictionary comprehensions do not exist') def test_undefinedFromLambdaInDictionaryComprehension(self): """ Undefined name referenced from a lambda function within a dict/set @@ -790,6 +796,24 @@ any(lambda: id(y) for x in range(10)) ''', m.UndefinedName) + def test_dunderClass(self): + """ + `__class__` is defined in class scope under Python 3, but is not + in Python 2. + """ + code = ''' + class Test(object): + def __init__(self): + print(__class__.__name__) + self.x = 1 + + t = Test() + ''' + if version_info < (3,): + self.flakes(code, m.UndefinedName) + else: + self.flakes(code) + class NameTests(TestCase): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/pyflakes.egg-info/PKG-INFO new/pyflakes-2.0.0/pyflakes.egg-info/PKG-INFO --- old/pyflakes-1.6.0/pyflakes.egg-info/PKG-INFO 2017-08-03 16:54:11.000000000 +0200 +++ new/pyflakes-2.0.0/pyflakes.egg-info/PKG-INFO 2018-05-20 19:13:28.000000000 +0200 @@ -1,11 +1,12 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: pyflakes -Version: 1.6.0 +Version: 2.0.0 Summary: passive checker of Python programs Home-page: https://github.com/PyCQA/pyflakes Author: A lot of people Author-email: code-qual...@python.org License: MIT +Description-Content-Type: UNKNOWN Description: ======== Pyflakes ======== @@ -17,7 +18,7 @@ modules with side effects. It's also much faster. It is `available on PyPI <https://pypi.python.org/pypi/pyflakes>`_ - and it supports all active versions of Python from 2.5 to 3.6. + and it supports all active versions of Python: 2.7 and 3.4 to 3.7. @@ -40,7 +41,7 @@ * If you require more options and more flexibility, you could give a look to Flake8_ too. - + Design Principles ----------------- @@ -91,6 +92,11 @@ .. _`rebase your changes`: https://git-scm.com/book/en/v2/Git-Branching-Rebasing .. _`GitHub pull request`: https://github.com/PyCQA/pyflakes/pulls + Changelog + --------- + + Please see `NEWS.txt <NEWS.txt>`_. + Platform: UNKNOWN Classifier: Development Status :: 6 - Mature Classifier: Environment :: Console @@ -98,6 +104,14 @@ Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development Classifier: Topic :: Utilities +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/setup.cfg new/pyflakes-2.0.0/setup.cfg --- old/pyflakes-1.6.0/setup.cfg 2017-08-03 16:54:11.000000000 +0200 +++ new/pyflakes-2.0.0/setup.cfg 2018-05-20 19:13:28.000000000 +0200 @@ -1,6 +1,9 @@ [bdist_wheel] universal = 1 +[metadata] +license_file = LICENSE + [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyflakes-1.6.0/setup.py new/pyflakes-2.0.0/setup.py --- old/pyflakes-1.6.0/setup.py 2016-12-30 16:09:43.000000000 +0100 +++ new/pyflakes-2.0.0/setup.py 2018-05-20 18:58:57.000000000 +0200 @@ -44,6 +44,7 @@ author_email="code-qual...@python.org", url="https://github.com/PyCQA/pyflakes", packages=["pyflakes", "pyflakes.scripts", "pyflakes.test"], + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', classifiers=[ "Development Status :: 6 - Mature", "Environment :: Console", @@ -51,7 +52,14 @@ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development", "Topic :: Utilities", ],