Hello community,

here is the log from the commit of package python-vulture for openSUSE:Factory 
checked in at 2020-02-07 15:55:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-vulture (Old)
 and      /work/SRC/openSUSE:Factory/.python-vulture.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-vulture"

Fri Feb  7 15:55:16 2020 rev:6 rq:770681 version:1.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-vulture/python-vulture.changes    
2019-02-20 14:10:39.790952816 +0100
+++ /work/SRC/openSUSE:Factory/.python-vulture.new.26092/python-vulture.changes 
2020-02-07 15:56:39.783581845 +0100
@@ -1,0 +2,15 @@
+Thu Feb  6 17:35:31 UTC 2020 - Marketa Calabkova <[email protected]>
+
+- update to 1.3
+  * Detect redundant ‘if’ conditions without ‘else’ blocks.
+  * Add whitelist for string.Formatter
+  * Fix tests for Python 3.8
+  * Use new Constant AST node under Python 3.8+
+  * Add test for f-strings
+  * Add whitelist for logging module.
+  * Add sys.excepthook to sys whitelist.
+  * Add whitelist for ctypes module.
+  * Check that type annotations are parsed and type comments are ignored
+  * Support checking files with BOM under Python 2.7
+
+-------------------------------------------------------------------

Old:
----
  vulture-1.0.tar.gz

New:
----
  vulture-1.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-vulture.spec ++++++
--- /var/tmp/diff_new_pack.oCjARr/_old  2020-02-07 15:56:41.291582614 +0100
+++ /var/tmp/diff_new_pack.oCjARr/_new  2020-02-07 15:56:41.295582616 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-vulture
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-vulture
-Version:        1.0
+Version:        1.3
 Release:        0
 Summary:        Python module for finding dead code
 License:        MIT

++++++ vulture-1.0.tar.gz -> vulture-1.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/NEWS.rst new/vulture-1.3/NEWS.rst
--- old/vulture-1.0/NEWS.rst    2018-10-23 18:27:25.000000000 +0200
+++ new/vulture-1.3/NEWS.rst    2020-02-03 12:00:25.000000000 +0100
@@ -1,6 +1,28 @@
 News
 ====
 
+1.3 (2020-02-03)
+----------------
+* Detect redundant 'if' conditions without 'else' blocks.
+* Add whitelist for ``string.Formatter`` (Joseph Bylund, #183).
+
+
+1.2 (2019-11-22)
+----------------
+* Fix tests for Python 3.8 (#166).
+* Use new ``Constant`` AST node under Python 3.8+ (#175).
+* Add test for f-strings (#177).
+* Add whitelist for ``logging`` module.
+
+
+1.1 (2019-09-23)
+----------------
+* Add ``sys.excepthook`` to ``sys`` whitelist.
+* Add whitelist for ``ctypes`` module.
+* Check that type annotations are parsed and type comments are ignored (thanks 
@kx-chen).
+* Support checking files with BOM under Python 2.7 (#170).
+
+
 1.0 (2018-10-23)
 ----------------
 * Add ``--ignore-decorators`` flag (thanks @RJ722).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/PKG-INFO new/vulture-1.3/PKG-INFO
--- old/vulture-1.0/PKG-INFO    2018-10-23 18:29:40.000000000 +0200
+++ new/vulture-1.3/PKG-INFO    2020-02-03 12:50:15.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: vulture
-Version: 1.0
+Version: 1.3
 Summary: Find dead code
 Home-page: https://github.com/jendrikseipp/vulture
 Author: Jendrik Seipp
@@ -37,7 +37,7 @@
         * tested: tests itself and has complete test coverage
         * complements pyflakes and has the same output syntax
         * sorts unused classes and functions by size with ``--sort-by-size``
-        * supports Python 2.7 and Python >= 3.4
+        * supports Python 2.7 and Python >= 3.5
         
         
         Installation
@@ -62,6 +62,10 @@
         The provided arguments may be Python files or directories. For each
         directory Vulture analyzes all contained `*.py` files.
         
+        Vulture assigns each chunk of dead code a confidence value. A 
confidence
+        value of 100% means that the code will never be executed. Values below
+        100% are only estimates for how likely it is that the code is unused.
+        
         After you have found and deleted dead code, run Vulture again, because
         it may discover more dead code.
         
@@ -209,9 +213,15 @@
         Similar programs
         ----------------
         
-        * Vulture can be used together with *pyflakes*
-        * The *coverage* module can find unused code more reliably, but 
requires
-          all branches of the code to actually be run.
+        * `pyflakes <https://pypi.org/project/pyflakes/>`_ finds unused 
imports and
+          unused local variables (in addition to many other programmatic 
errors).
+        * `coverage <https://pypi.org/project/coverage/>`_ finds unused
+          code more reliably than Vulture, but requires all branches of the 
code to
+          actually be run.
+        * `uncalled <https://pypi.org/project/uncalled/>`_ finds dead code by 
using
+          the abstract syntax tree (like Vulture), regular expressions, or 
both.
+        * `dead <https://pypi.org/project/dead/>`_ finds dead code by using
+          the abstract syntax tree (like Vulture).
         
         
         Participate
@@ -228,6 +238,28 @@
         News
         ====
         
+        1.3 (2020-02-03)
+        ----------------
+        * Detect redundant 'if' conditions without 'else' blocks.
+        * Add whitelist for ``string.Formatter`` (Joseph Bylund, #183).
+        
+        
+        1.2 (2019-11-22)
+        ----------------
+        * Fix tests for Python 3.8 (#166).
+        * Use new ``Constant`` AST node under Python 3.8+ (#175).
+        * Add test for f-strings (#177).
+        * Add whitelist for ``logging`` module.
+        
+        
+        1.1 (2019-09-23)
+        ----------------
+        * Add ``sys.excepthook`` to ``sys`` whitelist.
+        * Add whitelist for ``ctypes`` module.
+        * Check that type annotations are parsed and type comments are ignored 
(thanks @kx-chen).
+        * Support checking files with BOM under Python 2.7 (#170).
+        
+        
         1.0 (2018-10-23)
         ----------------
         * Add ``--ignore-decorators`` flag (thanks @RJ722).
@@ -462,9 +494,10 @@
 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 :: Quality Assurance
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/README.rst new/vulture-1.3/README.rst
--- old/vulture-1.0/README.rst  2018-07-31 14:52:23.000000000 +0200
+++ new/vulture-1.3/README.rst  2019-10-29 12:57:15.000000000 +0100
@@ -29,7 +29,7 @@
 * tested: tests itself and has complete test coverage
 * complements pyflakes and has the same output syntax
 * sorts unused classes and functions by size with ``--sort-by-size``
-* supports Python 2.7 and Python >= 3.4
+* supports Python 2.7 and Python >= 3.5
 
 
 Installation
@@ -54,6 +54,10 @@
 The provided arguments may be Python files or directories. For each
 directory Vulture analyzes all contained `*.py` files.
 
+Vulture assigns each chunk of dead code a confidence value. A confidence
+value of 100% means that the code will never be executed. Values below
+100% are only estimates for how likely it is that the code is unused.
+
 After you have found and deleted dead code, run Vulture again, because
 it may discover more dead code.
 
@@ -201,9 +205,15 @@
 Similar programs
 ----------------
 
-* Vulture can be used together with *pyflakes*
-* The *coverage* module can find unused code more reliably, but requires
-  all branches of the code to actually be run.
+* `pyflakes <https://pypi.org/project/pyflakes/>`_ finds unused imports and
+  unused local variables (in addition to many other programmatic errors).
+* `coverage <https://pypi.org/project/coverage/>`_ finds unused
+  code more reliably than Vulture, but requires all branches of the code to
+  actually be run.
+* `uncalled <https://pypi.org/project/uncalled/>`_ finds dead code by using
+  the abstract syntax tree (like Vulture), regular expressions, or both.
+* `dead <https://pypi.org/project/dead/>`_ finds dead code by using
+  the abstract syntax tree (like Vulture).
 
 
 Participate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/TODO.rst new/vulture-1.3/TODO.rst
--- old/vulture-1.0/TODO.rst    2018-10-16 23:46:53.000000000 +0200
+++ new/vulture-1.3/TODO.rst    2020-02-03 12:04:37.000000000 +0100
@@ -1,6 +1,10 @@
 TODOs
 =====
 
+* Convert README.rst and NEWS.rst files to Markdown.
+* Detect unused variables in assignment expressions under Python 3.8+.
+* Use end_lineno and end_col_offset attributes when running Python 3.8+.
+
 
 Non-TODOs
 =========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/builtins.txt new/vulture-1.3/builtins.txt
--- old/vulture-1.0/builtins.txt        2017-08-12 10:04:30.000000000 +0200
+++ new/vulture-1.3/builtins.txt        1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-python2 = ['ArithmeticError', 'AssertionError', 'AttributeError', 
'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 
'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 
'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 
'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 
'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 
'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 
'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 
'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 
'ValueError', 'Warning', 'ZeroDivisionError', '__debug__', '__doc__', 
'__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 
'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 
'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 
'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 
'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 
'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 
'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 
'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 
'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 
'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 
'zip']
-
-python3 = ['ArithmeticError', 'AssertionError', 'AttributeError', 
'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 
'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 
'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 
'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 
'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 
'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 
'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 
'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 
'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 
'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 
'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 
'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 
'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', 
'__build_class__', '__debug__', '__doc__', '__import__', '__loader__', 
'__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 
'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 
'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 
'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 
'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 
'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 
'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 
'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 
'type', 'vars', 'zip']
-
-print(sorted(set(python2) | set(python3)))
-
-try:
-    # Python 3
-    import builtins
-except ImportError:
-    # Python 2
-    import __builtin__ as builtins
-
-print(vars(builtins))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/multi.txt new/vulture-1.3/multi.txt
--- old/vulture-1.0/multi.txt   2017-07-26 11:21:49.000000000 +0200
+++ new/vulture-1.3/multi.txt   1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-def test():
-    pass
-
-def test():
-    pass
-
-a = 1
-a = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/setup.py new/vulture-1.3/setup.py
--- old/vulture-1.0/setup.py    2018-06-30 12:41:55.000000000 +0200
+++ new/vulture-1.3/setup.py    2019-09-30 08:33:42.000000000 +0200
@@ -58,9 +58,9 @@
         '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 :: Quality Assurance'
@@ -68,6 +68,7 @@
     entry_points={
         'console_scripts': ['vulture = vulture.core:main'],
     },
+    python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
     tests_require=['pytest', 'pytest-cov'],
     cmdclass={'test': PyTest},
     packages=setuptools.find_packages(exclude=['tests']),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/__init__.py 
new/vulture-1.3/tests/__init__.py
--- old/vulture-1.0/tests/__init__.py   2018-07-03 10:55:48.000000000 +0200
+++ new/vulture-1.3/tests/__init__.py   2019-09-02 16:16:07.000000000 +0200
@@ -5,6 +5,7 @@
 import sys
 
 import pytest
+
 from vulture import core
 
 DIR = os.path.dirname(os.path.abspath(__file__))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_conditions.py 
new/vulture-1.3/tests/test_conditions.py
--- old/vulture-1.0/tests/test_conditions.py    2018-06-03 22:10:54.000000000 
+0200
+++ new/vulture-1.3/tests/test_conditions.py    2019-11-22 21:10:15.000000000 
+0100
@@ -35,6 +35,7 @@
 def test_true():
     check_condition("True", True)
     check_condition("2", True)
+    check_condition("'s'", True)
     check_condition("['foo', 'bar']", True)
     check_condition("{'a': 1, 'b': 2}", True)
 
@@ -181,3 +182,12 @@
     pass
 """)
     check_unreachable(v, 9, 4, 'else')
+
+
+def test_redundant_if(v):
+    v.scan("""\
+if [5]:
+    pass
+""")
+    print(v.unreachable_code[0].size)
+    check_unreachable(v, 1, 2, 'if')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_confidence.py 
new/vulture-1.3/tests/test_confidence.py
--- old/vulture-1.0/tests/test_confidence.py    2017-08-25 23:16:11.000000000 
+0200
+++ new/vulture-1.3/tests/test_confidence.py    2019-09-02 16:53:32.000000000 
+0200
@@ -9,9 +9,9 @@
 def check_min_confidence(code, min_confidence, expected):
     v = core.Vulture(verbose=True)
     v.scan(code)
-    detected = dict(
-        (item.name, item.confidence)
-        for item in v.get_unused_code(min_confidence=min_confidence))
+    detected = {
+        item.name: item.confidence
+        for item in v.get_unused_code(min_confidence=min_confidence)}
     assert detected == expected
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_encoding.py 
new/vulture-1.3/tests/test_encoding.py
--- old/vulture-1.0/tests/test_encoding.py      1970-01-01 01:00:00.000000000 
+0100
+++ new/vulture-1.3/tests/test_encoding.py      2019-09-02 12:06:41.000000000 
+0200
@@ -0,0 +1,43 @@
+import codecs
+import io
+
+from . import v
+assert v  # Silence pyflakes.
+
+
+def test_encoding1(v):
+    v.scan(u"""\
+# -*- coding: utf-8 -*-
+pass
+""")
+    assert not v.found_dead_code_or_error
+
+
+def test_encoding2(v):
+    v.scan(u"""\
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+pass
+""")
+    assert not v.found_dead_code_or_error
+
+
+def test_non_utf8_encoding(v, tmpdir):
+    code = ""
+    name = "non_utf8"
+    non_utf_8_file = str(tmpdir.mkdir(name).join(name + ".py"))
+    with open(non_utf_8_file, mode='wb') as f:
+        f.write(codecs.BOM_UTF16_LE)
+        f.write(code.encode('utf_16_le'))
+    v.scavenge([f.name])
+    assert v.found_dead_code_or_error
+
+
+def test_utf8_with_bom(v, tmpdir):
+    name = "utf8_bom"
+    filename = str(tmpdir.mkdir(name).join(name + ".py"))
+    # utf8_sig prepends the BOM to the file.
+    with io.open(filename, mode='w', encoding="utf-8-sig") as f:
+        f.write(u"")
+    v.scavenge([f.name])
+    assert not v.found_dead_code_or_error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_errors.py 
new/vulture-1.3/tests/test_errors.py
--- old/vulture-1.0/tests/test_errors.py        2018-06-30 12:41:55.000000000 
+0200
+++ new/vulture-1.3/tests/test_errors.py        2019-09-02 11:18:11.000000000 
+0200
@@ -1,5 +1,3 @@
-import codecs
-
 import pytest
 
 from . import v
@@ -23,18 +21,3 @@
 """)
     with pytest.raises(ValueError):
         v.get_unused_code(min_confidence=150)
-
-
-def test_non_utf8_encoding(v, tmpdir):
-    code = """\
-def foo():
-    pass
-
-foo()
-"""
-    non_utf_8_file = str(tmpdir.mkdir("non_utf8").join("non_utf8.py"))
-    with open(non_utf_8_file, 'wb') as f:
-        f.write(codecs.BOM_UTF16_LE)
-        f.write(code.encode('utf_16_le'))
-    v.scavenge([f.name])
-    assert v.found_dead_code_or_error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_format_strings.py 
new/vulture-1.3/tests/test_format_strings.py
--- old/vulture-1.0/tests/test_format_strings.py        2017-07-30 
19:13:54.000000000 +0200
+++ new/vulture-1.3/tests/test_format_strings.py        2019-11-11 
21:34:43.000000000 +0100
@@ -1,3 +1,7 @@
+import sys
+
+import pytest
+
 from . import check, v
 assert v  # Silence pyflakes.
 
@@ -12,6 +16,18 @@
     check(v.used_names, ['a', 'b', 'c', 'd', 'locals'])
 
 
[email protected](
+    sys.version_info < (3, 6),
+    reason="needs f-string support (added in Python 3.6)")
+def test_f_string(v):
+    v.scan('''\
+f'{a}, {b:0d} {c:<30} {d:.2%} {e()} {f:{width}.{precision}}'
+f'{ {x:y for (x, y) in ((1, 2), (3, 4))} }'
+''')
+    check(v.used_names,
+          ['a', 'b', 'c', 'd', 'e', 'f', 'precision', 'width', 'x', 'y'])
+
+
 def test_new_format_string_access(v):
     v.scan("'{a.b}, {c.d.e} {f[g]} {h[i][j]}'.format(**locals())")
     check(v.used_names, ['a', 'c', 'f', 'h', 'locals'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_report.py 
new/vulture-1.3/tests/test_report.py
--- old/vulture-1.0/tests/test_report.py        2018-08-17 01:04:57.000000000 
+0200
+++ new/vulture-1.3/tests/test_report.py        2019-09-23 22:08:48.000000000 
+0200
@@ -1,3 +1,5 @@
+import sys
+
 import pytest
 
 from . import v
@@ -43,6 +45,8 @@
 {filename}:11: unreachable code after 'return' (100% confidence)
 {filename}:13: unused property 'myprop' (60% confidence)
 """
+    if sys.version_info >= (3, 8):
+        expected = expected.replace("{filename}:13:", "{filename}:14:")
     check_report(mock_code, expected)
 
 
@@ -56,4 +60,6 @@
 # unreachable code after 'return' ({filename}:11)
 _.myprop  # unused property ({filename}:13)
 """
+    if sys.version_info >= (3, 8):
+        expected = expected.replace("{filename}:13)", "{filename}:14)")
     check_report(mock_code, expected, make_whitelist=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_scavenging.py 
new/vulture-1.3/tests/test_scavenging.py
--- old/vulture-1.0/tests/test_scavenging.py    2018-06-06 13:31:23.000000000 
+0200
+++ new/vulture-1.3/tests/test_scavenging.py    2019-10-29 20:41:06.000000000 
+0100
@@ -1,3 +1,7 @@
+import sys
+
+import pytest
+
 from . import check, skip_if_not_has_async, v
 assert v  # Silence pyflakes.
 
@@ -516,23 +520,6 @@
     check(v.unused_vars, ['bar'])
 
 
-def test_encoding1(v):
-    v.scan(u"""\
-# -*- coding: utf-8 -*-
-pass
-""")
-    assert True
-
-
-def test_encoding2(v):
-    v.scan(u"""\
-#! /usr/bin/env python
-# -*- coding: utf-8 -*-
-pass
-""")
-    assert True
-
-
 def test_multiple_definition(v):
     v.scan("""\
 a = 1
@@ -541,3 +528,48 @@
     check(v.defined_vars, ['a', 'a'])
     check(v.used_names, [])
     check(v.unused_vars, ['a', 'a'])
+
+
[email protected](sys.version_info < (3, 5),
+                    reason="requires Python 3.5+")
+def test_arg_type_annotation(v):
+    v.scan("""\
+from typing import Iterable
+
+def f(n: int) -> Iterable[int]:
+    yield n
+""")
+
+    check(v.unused_vars, [])
+    check(v.unused_funcs, ['f'])
+    check(v.unused_imports, [])
+
+
[email protected](sys.version_info < (3, 6),
+                    reason="requires Python 3.6+")
+def test_var_type_annotation(v):
+    v.scan("""\
+from typing import List
+
+x: List[int] = [1]
+""")
+
+    check(v.unused_vars, ['x'])
+    check(v.unused_funcs, [])
+    check(v.unused_imports, [])
+
+
+def test_type_hint_comments(v):
+    v.scan("""\
+import typing
+
+if typing.TYPE_CHECKING:
+    from typing import List, Text
+
+def foo(foo_li):
+    # type: (List[Text]) -> None
+    for bar in foo_li:
+        bar.xyz()
+""")
+
+    check(v.unused_imports, ['List', 'Text'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_size.py 
new/vulture-1.3/tests/test_size.py
--- old/vulture-1.0/tests/test_size.py  2017-08-15 16:29:38.000000000 +0200
+++ new/vulture-1.3/tests/test_size.py  2019-09-23 22:11:26.000000000 +0200
@@ -36,7 +36,7 @@
             assert count_lines(node) == size
             break
     else:
-        assert False, 'Failed to find top-level class "Foo" in code'
+        raise AssertionError('Failed to find top-level class "Foo" in code')
 
 
 def test_size_basic():
@@ -78,7 +78,10 @@
         else:
             pass
 """
-    check_size(example, 11)
+    size = 11
+    if sys.version_info >= (3, 8):
+        size = 10
+    check_size(example, size)
 
 
 def test_size_while():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tests/test_utils.py 
new/vulture-1.3/tests/test_utils.py
--- old/vulture-1.0/tests/test_utils.py 2018-07-31 14:52:23.000000000 +0200
+++ new/vulture-1.3/tests/test_utils.py 2019-09-02 16:22:34.000000000 +0200
@@ -1,8 +1,9 @@
 import ast
 
-from . import skip_if_not_has_async
 from vulture import utils
 
+from . import skip_if_not_has_async
+
 
 def check_decorator_names(code, expected_names):
     decorator_names = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/tox.ini new/vulture-1.3/tox.ini
--- old/vulture-1.0/tox.ini     2018-08-17 01:04:57.000000000 +0200
+++ new/vulture-1.3/tox.ini     2020-01-22 19:55:09.000000000 +0100
@@ -1,26 +1,34 @@
 [tox]
-envlist = cleanup, docs, py27, py34, py35, py36, py37, style
+envlist = cleanup, docs, py{27,35,36,37,38}, style
 skip_missing_interpreters = true
 
 # Erase old coverage results, then accumulate them during this tox run.
 [testenv:cleanup]
-deps = coverage
-commands = coverage erase
+deps =
+  coverage
+commands =
+  coverage erase
 
 [testenv]
 deps =
-  coverage
-  pytest
+  coverage<5.0.0
+  pytest>=3.3
   pytest-cov
 commands =
   py.test
 
 [testenv:docs]
 deps =
-    collective.checkdocs
-    pygments
-commands = python setup.py checkdocs
+  collective.checkdocs
+  pygments
+commands =
+  python setup.py checkdocs
 
 [testenv:style]
-deps = flake8
-commands = flake8 setup.py tests/ vulture/
+deps =
+  flake8
+  py36,py37: flake8-2020
+  py36,py37: flake8-bugbear
+  py36,py37: flake8-comprehensions
+commands =
+  flake8 setup.py tests/ vulture/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/core.py 
new/vulture-1.3/vulture/core.py
--- old/vulture-1.0/vulture/core.py     2018-10-23 18:29:40.000000000 +0200
+++ new/vulture-1.3/vulture/core.py     2020-02-03 12:50:14.000000000 +0100
@@ -1,9 +1,8 @@
-#! /usr/bin/env python
 # -*- coding: utf-8 -*-
 #
 # vulture - Find dead code.
 #
-# Copyright (c) 2012-2018 Jendrik Seipp ([email protected])
+# Copyright (c) 2012-2019 Jendrik Seipp ([email protected])
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the
@@ -38,18 +37,14 @@
 from vulture import lines
 from vulture import utils
 
-__version__ = '1.0'
+__version__ = '1.3'
 
 DEFAULT_CONFIDENCE = 60
 
-# The ast module in Python 2 trips over "coding" cookies, so strip them.
-ENCODING_REGEX = re.compile(
-    r"^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+).*?$", flags=re.M)
-
-IGNORED_VARIABLE_NAMES = set(['object', 'self'])
+IGNORED_VARIABLE_NAMES = {'object', 'self'}
 # True and False are NameConstants since Python 3.4.
 if sys.version_info < (3, 4):
-    IGNORED_VARIABLE_NAMES |= set(['True', 'False'])
+    IGNORED_VARIABLE_NAMES |= {'True', 'False'}
 
 
 def _get_unused_items(defined_items, used_names):
@@ -103,6 +98,8 @@
     """
     Hold the name, type and location of defined code.
     """
+    __slots__ = ('name', 'typ', 'filename', 'first_lineno',
+                 'last_lineno', 'message', 'confidence')
 
     def __init__(self, name, typ, filename, first_lineno, last_lineno,
                  message='',
@@ -123,10 +120,10 @@
     def get_report(self, add_size=False):
         if add_size:
             line_format = 'line' if self.size == 1 else 'lines'
-            size_report = ', {0:d} {1}'.format(self.size, line_format)
+            size_report = ', {:d} {}'.format(self.size, line_format)
         else:
             size_report = ''
-        return "{0}:{1:d}: {2} ({3}% confidence{4})".format(
+        return "{}:{:d}: {} ({}% confidence{})".format(
             utils.format_path(self.filename), self.first_lineno,
             self.message, self.confidence, size_report)
 
@@ -185,21 +182,21 @@
         self.found_dead_code_or_error = False
 
     def scan(self, code, filename=''):
-        code = ENCODING_REGEX.sub("", code, count=1)
+        code = utils.sanitize_code(code)
         self.code = code.splitlines()
         self.filename = filename
         try:
             node = ast.parse(code, filename=self.filename)
         except SyntaxError as err:
-            text = ' at "{0}"'.format(err.text.strip()) if err.text else ''
-            print('{0}:{1:d}: {2}{3}'.format(
+            text = ' at "{}"'.format(err.text.strip()) if err.text else ''
+            print('{}:{:d}: {}{}'.format(
                 utils.format_path(filename), err.lineno, err.msg, text),
                 file=sys.stderr)
             self.found_dead_code_or_error = True
         except (TypeError, ValueError) as err:
             # Python < 3.5 raises TypeError and Python >= 3.5 raises
             # ValueError if source contains null bytes.
-            print('{0}: invalid source code "{1}"'.format(
+            print('{}: invalid source code "{}"'.format(
                 utils.format_path(filename), err), file=sys.stderr)
             self.found_dead_code_or_error = True
         else:
@@ -224,7 +221,7 @@
             self._log('Scanning:', module)
             try:
                 module_string = utils.read_file(module)
-            except utils.VultureInputException as err:
+            except utils.VultureInputException as err:  # noqa: F841
                 print(
                     'Error: Could not read file {module} - {err}\n'
                     'Try to change the encoding to UTF-8.'.format(**locals()),
@@ -233,7 +230,7 @@
             else:
                 self.scan(module_string, filename=module)
 
-        unique_imports = set(item.name for item in self.defined_imports)
+        unique_imports = {item.name for item in self.defined_imports}
         for import_name in unique_imports:
             path = os.path.join('whitelists', import_name) + '_whitelist.py'
             if exclude_file(path):
@@ -344,14 +341,53 @@
                 last_node=node.body[-1],
                 message="unsatisfiable '{name}' condition".format(**locals()),
                 confidence=100)
-        else:
-            else_body = getattr(node, 'orelse')
-            if utils.condition_is_always_true(node.test) and else_body:
+        elif utils.condition_is_always_true(node.test):
+            else_body = node.orelse
+            if else_body:
                 self._define(
                     self.unreachable_code, 'else', else_body[0],
                     last_node=else_body[-1],
                     message="unreachable 'else' block",
                     confidence=100)
+            elif name == 'if':
+                # Redundant if-condition without else block.
+                self._define(
+                    self.unreachable_code, name, node,
+                    message="redundant if-condition".format(**locals()),
+                    confidence=100)
+
+    def _handle_string(self, s):
+        """
+        Parse variable names in format strings:
+
+        '%(my_var)s' % locals()
+        '{my_var}'.format(**locals())
+
+        """
+        # Old format strings.
+        self.used_names |= set(re.findall(r'\%\((\w+)\)', s))
+
+        def is_identifier(name):
+            return bool(re.match(r'[a-zA-Z_][a-zA-Z0-9_]*', name))
+
+        # New format strings.
+        parser = string.Formatter()
+        try:
+            names = [name for _, name, _, _ in parser.parse(s) if name]
+        except ValueError:
+            # Invalid format string.
+            names = []
+
+        for field_name in names:
+            # Remove brackets and contents: "a[0][b].c[d].e" -> "a.c.e".
+            # "a.b.c" -> name = "a", attributes = ["b", "c"]
+            name_and_attrs = re.sub(r'\[\w*\]', '', field_name).split('.')
+            name = name_and_attrs[0]
+            if is_identifier(name):
+                self.used_names.add(name)
+            for attr in name_and_attrs[1:]:
+                if is_identifier(attr):
+                    self.used_attrs.add(attr)
 
     def _define(self, collection, name, first_node, last_node=None,
                 message='', confidence=DEFAULT_CONFIDENCE, ignore=None):
@@ -439,38 +475,13 @@
         elif isinstance(node.ctx, (ast.Param, ast.Store)):
             self._define_variable(node.id, node)
 
-    def visit_Str(self, node):
-        """
-        Parse variable names in format strings:
-
-        '%(my_var)s' % locals()
-        '{my_var}'.format(**locals())
-
-        """
-        # Old format strings.
-        self.used_names |= set(re.findall(r'\%\((\w+)\)', node.s))
-
-        def is_identifier(s):
-            return bool(re.match(r'[a-zA-Z_][a-zA-Z0-9_]*', s))
-
-        # New format strings.
-        parser = string.Formatter()
-        try:
-            names = [name for _, name, _, _ in parser.parse(node.s) if name]
-        except ValueError:
-            # Invalid format string.
-            names = []
-
-        for field_name in names:
-            # Remove brackets and contents: "a[0][b].c[d].e" -> "a.c.e".
-            # "a.b.c" -> name = "a", attributes = ["b", "c"]
-            name_and_attrs = re.sub(r'\[\w*\]', '', field_name).split('.')
-            name = name_and_attrs[0]
-            if is_identifier(name):
-                self.used_names.add(name)
-            for attr in name_and_attrs[1:]:
-                if is_identifier(attr):
-                    self.used_attrs.add(attr)
+    if sys.version_info < (3, 8):
+        def visit_Str(self, node):
+            self._handle_string(node.s)
+    else:
+        def visit_Constant(self, node):
+            if isinstance(node.value, str):
+                self._handle_string(node.value)
 
     def visit_While(self, node):
         self._handle_conditional_node(node, 'while')
@@ -525,7 +536,7 @@
         return exclude.split(',')
 
     usage = "%(prog)s [options] PATH [PATH ...]"
-    version = "vulture {0}".format(__version__)
+    version = "vulture {}".format(__version__)
     glob_help = 'Patterns may contain glob wildcards (*, ?, [abc], [!abc]).'
     parser = argparse.ArgumentParser(prog='vulture', usage=usage)
     parser.add_argument(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/lines.py 
new/vulture-1.3/vulture/lines.py
--- old/vulture-1.0/vulture/lines.py    2017-08-15 16:17:27.000000000 +0200
+++ new/vulture-1.3/vulture/lines.py    2019-09-02 16:54:24.000000000 +0200
@@ -15,7 +15,7 @@
     list of nodes, we return the last one.
 
     """
-    ignored_fields = set(['ctx', 'decorator_list', 'names', 'returns'])
+    ignored_fields = {'ctx', 'decorator_list', 'names', 'returns'}
     fields = node._fields
     # The fields of ast.Call are in the wrong order.
     if isinstance(node, ast.Call):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/utils.py 
new/vulture-1.3/vulture/utils.py
--- old/vulture-1.0/vulture/utils.py    2018-07-31 14:52:23.000000000 +0200
+++ new/vulture-1.3/vulture/utils.py    2019-11-30 18:13:35.000000000 +0100
@@ -1,11 +1,17 @@
 import ast
 import codecs
 import os
+import re
 import sys
 import tokenize
 
-# Encoding to use when converting input files to unicode.
-ENCODING = 'utf-8'
+# Encoding to use when converting input files to unicode. Python 2 trips
+# over the BOM, so we use "utf-8-sig" which drops the BOM.
+ENCODING = 'utf-8-sig'
+
+# The ast module in Python 2 trips over "coding" cookies, so strip them.
+ENCODING_REGEX = re.compile(
+    r"^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+).*?$", flags=re.M)
 
 
 class VultureInputException(Exception):
@@ -73,7 +79,7 @@
     for path in paths:
         path = os.path.abspath(path)
         if toplevel and path.endswith('.pyc'):
-            sys.exit('.pyc files are not supported: {0}'.format(path))
+            sys.exit('.pyc files are not supported: {}'.format(path))
         if os.path.isfile(path) and (path.endswith('.py') or toplevel):
             modules.append(path)
         elif os.path.isdir(path):
@@ -82,7 +88,7 @@
                 for filename in sorted(os.listdir(path))]
             modules.extend(get_modules(subpaths, toplevel=False))
         elif toplevel:
-            sys.exit('Error: {0} could not be found.'.format(path))
+            sys.exit('Error: {} could not be found.'.format(path))
     return modules
 
 
@@ -106,6 +112,10 @@
         raise VultureInputException(err)
 
 
+def sanitize_code(code):
+    return ENCODING_REGEX.sub("", code, count=1)
+
+
 class LoggingList(list):
     def __init__(self, typ, verbose):
         self.typ = typ
@@ -114,7 +124,7 @@
 
     def append(self, item):
         if self._verbose:
-            print('define {0} "{1}"'.format(self.typ, item.name))
+            print('define {} "{}"'.format(self.typ, item.name))
         list.append(self, item)
 
 
@@ -126,5 +136,5 @@
 
     def add(self, name):
         if self._verbose:
-            print('use {0} "{1}"'.format(self.typ, name))
+            print('use {} "{}"'.format(self.typ, name))
         set.add(self, name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/whitelists/argparse_whitelist.py 
new/vulture-1.3/vulture/whitelists/argparse_whitelist.py
--- old/vulture-1.0/vulture/whitelists/argparse_whitelist.py    2018-07-03 
10:46:37.000000000 +0200
+++ new/vulture-1.3/vulture/whitelists/argparse_whitelist.py    2019-11-11 
19:49:34.000000000 +0100
@@ -1,7 +1,6 @@
 import argparse
 
-_ = argparse.ArgumentParser()
-_.epilog
+argparse.ArgumentParser().epilog
 
-argparse.ArgumentDefaultsHelpFormatter._fill_text
-argparse.ArgumentDefaultsHelpFormatter._get_help_string
+argparse.ArgumentDefaultsHelpFormatter('prog')._fill_text
+argparse.ArgumentDefaultsHelpFormatter('prog')._get_help_string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/whitelists/ast_whitelist.py 
new/vulture-1.3/vulture/whitelists/ast_whitelist.py
--- old/vulture-1.0/vulture/whitelists/ast_whitelist.py 2018-07-03 
10:46:37.000000000 +0200
+++ new/vulture-1.3/vulture/whitelists/ast_whitelist.py 2019-11-01 
20:22:38.000000000 +0100
@@ -17,6 +17,7 @@
 whitelist_node_visitor.visit_Call
 whitelist_node_visitor.visit_ClassDef
 whitelist_node_visitor.visit_Compare
+whitelist_node_visitor.visit_Constant
 whitelist_node_visitor.visit_Delete
 whitelist_node_visitor.visit_Dict
 whitelist_node_visitor.visit_DictComp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/vulture-1.0/vulture/whitelists/collections_whitelist.py 
new/vulture-1.3/vulture/whitelists/collections_whitelist.py
--- old/vulture-1.0/vulture/whitelists/collections_whitelist.py 2018-07-03 
10:46:37.000000000 +0200
+++ new/vulture-1.3/vulture/whitelists/collections_whitelist.py 2019-11-11 
19:49:34.000000000 +0100
@@ -1,4 +1,4 @@
 import collections
 
 # To free memory, the "default_factory" attribute can be set to None.
-collections.defaultdict.default_factory
+collections.defaultdict().default_factory
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/whitelists/ctypes_whitelist.py 
new/vulture-1.3/vulture/whitelists/ctypes_whitelist.py
--- old/vulture-1.0/vulture/whitelists/ctypes_whitelist.py      1970-01-01 
01:00:00.000000000 +0100
+++ new/vulture-1.3/vulture/whitelists/ctypes_whitelist.py      2019-11-02 
22:51:32.000000000 +0100
@@ -0,0 +1,8 @@
+from ctypes import _CFuncPtr
+from ctypes import _Pointer
+
+_CFuncPtr.argtypes
+_CFuncPtr.errcheck
+_CFuncPtr.restype
+
+_Pointer.contents
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/whitelists/logging_whitelist.py 
new/vulture-1.3/vulture/whitelists/logging_whitelist.py
--- old/vulture-1.0/vulture/whitelists/logging_whitelist.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/vulture-1.3/vulture/whitelists/logging_whitelist.py     2019-11-22 
20:19:06.000000000 +0100
@@ -0,0 +1,4 @@
+import logging
+
+logging.Filter.filter
+logging.StreamHandler.emit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/whitelists/string_whitelist.py 
new/vulture-1.3/vulture/whitelists/string_whitelist.py
--- old/vulture-1.0/vulture/whitelists/string_whitelist.py      1970-01-01 
01:00:00.000000000 +0100
+++ new/vulture-1.3/vulture/whitelists/string_whitelist.py      2020-01-22 
20:06:18.000000000 +0100
@@ -0,0 +1,10 @@
+import string
+
+string.Formatter.check_unused_args
+string.Formatter.convert_field
+string.Formatter.format
+string.Formatter.format_field
+string.Formatter.get_field
+string.Formatter.get_value
+string.Formatter.parse
+string.Formatter.vformat
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture/whitelists/sys_whitelist.py 
new/vulture-1.3/vulture/whitelists/sys_whitelist.py
--- old/vulture-1.0/vulture/whitelists/sys_whitelist.py 2018-07-03 
10:46:37.000000000 +0200
+++ new/vulture-1.3/vulture/whitelists/sys_whitelist.py 2018-10-29 
13:25:40.000000000 +0100
@@ -1,5 +1,7 @@
 import sys
 
+sys.excepthook
+
 # Never report redirected streams as unused.
 sys.stderr
 sys.stdin
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture.egg-info/PKG-INFO 
new/vulture-1.3/vulture.egg-info/PKG-INFO
--- old/vulture-1.0/vulture.egg-info/PKG-INFO   2018-10-23 18:29:40.000000000 
+0200
+++ new/vulture-1.3/vulture.egg-info/PKG-INFO   2020-02-03 12:50:15.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: vulture
-Version: 1.0
+Version: 1.3
 Summary: Find dead code
 Home-page: https://github.com/jendrikseipp/vulture
 Author: Jendrik Seipp
@@ -37,7 +37,7 @@
         * tested: tests itself and has complete test coverage
         * complements pyflakes and has the same output syntax
         * sorts unused classes and functions by size with ``--sort-by-size``
-        * supports Python 2.7 and Python >= 3.4
+        * supports Python 2.7 and Python >= 3.5
         
         
         Installation
@@ -62,6 +62,10 @@
         The provided arguments may be Python files or directories. For each
         directory Vulture analyzes all contained `*.py` files.
         
+        Vulture assigns each chunk of dead code a confidence value. A 
confidence
+        value of 100% means that the code will never be executed. Values below
+        100% are only estimates for how likely it is that the code is unused.
+        
         After you have found and deleted dead code, run Vulture again, because
         it may discover more dead code.
         
@@ -209,9 +213,15 @@
         Similar programs
         ----------------
         
-        * Vulture can be used together with *pyflakes*
-        * The *coverage* module can find unused code more reliably, but 
requires
-          all branches of the code to actually be run.
+        * `pyflakes <https://pypi.org/project/pyflakes/>`_ finds unused 
imports and
+          unused local variables (in addition to many other programmatic 
errors).
+        * `coverage <https://pypi.org/project/coverage/>`_ finds unused
+          code more reliably than Vulture, but requires all branches of the 
code to
+          actually be run.
+        * `uncalled <https://pypi.org/project/uncalled/>`_ finds dead code by 
using
+          the abstract syntax tree (like Vulture), regular expressions, or 
both.
+        * `dead <https://pypi.org/project/dead/>`_ finds dead code by using
+          the abstract syntax tree (like Vulture).
         
         
         Participate
@@ -228,6 +238,28 @@
         News
         ====
         
+        1.3 (2020-02-03)
+        ----------------
+        * Detect redundant 'if' conditions without 'else' blocks.
+        * Add whitelist for ``string.Formatter`` (Joseph Bylund, #183).
+        
+        
+        1.2 (2019-11-22)
+        ----------------
+        * Fix tests for Python 3.8 (#166).
+        * Use new ``Constant`` AST node under Python 3.8+ (#175).
+        * Add test for f-strings (#177).
+        * Add whitelist for ``logging`` module.
+        
+        
+        1.1 (2019-09-23)
+        ----------------
+        * Add ``sys.excepthook`` to ``sys`` whitelist.
+        * Add whitelist for ``ctypes`` module.
+        * Check that type annotations are parsed and type comments are ignored 
(thanks @kx-chen).
+        * Support checking files with BOM under Python 2.7 (#170).
+        
+        
         1.0 (2018-10-23)
         ----------------
         * Add ``--ignore-decorators`` flag (thanks @RJ722).
@@ -462,9 +494,10 @@
 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 :: Quality Assurance
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/vulture-1.0/vulture.egg-info/SOURCES.txt 
new/vulture-1.3/vulture.egg-info/SOURCES.txt
--- old/vulture-1.0/vulture.egg-info/SOURCES.txt        2018-10-23 
18:29:40.000000000 +0200
+++ new/vulture-1.3/vulture.egg-info/SOURCES.txt        2020-02-03 
12:50:15.000000000 +0100
@@ -4,14 +4,13 @@
 NEWS.rst
 README.rst
 TODO.rst
-builtins.txt
-multi.txt
 setup.cfg
 setup.py
 tox.ini
 tests/__init__.py
 tests/test_conditions.py
 tests/test_confidence.py
+tests/test_encoding.py
 tests/test_errors.py
 tests/test_format_strings.py
 tests/test_ignore.py
@@ -38,6 +37,9 @@
 vulture/whitelists/argparse_whitelist.py
 vulture/whitelists/ast_whitelist.py
 vulture/whitelists/collections_whitelist.py
+vulture/whitelists/ctypes_whitelist.py
+vulture/whitelists/logging_whitelist.py
+vulture/whitelists/string_whitelist.py
 vulture/whitelists/sys_whitelist.py
 vulture/whitelists/threading_whitelist.py
 vulture/whitelists/unittest_whitelist.py


Reply via email to