Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-eradicate for 
openSUSE:Factory checked in at 2022-08-26 09:08:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-eradicate (Old)
 and      /work/SRC/openSUSE:Factory/.python-eradicate.new.2083 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-eradicate"

Fri Aug 26 09:08:16 2022 rev:3 rq:999344 version:2.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-eradicate/python-eradicate.changes        
2019-02-26 22:22:14.826069436 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-eradicate.new.2083/python-eradicate.changes  
    2022-08-26 09:08:17.941385049 +0200
@@ -1,0 +2,7 @@
+Thu Aug 25 09:45:28 UTC 2022 - Ben Greiner <[email protected]>
+
+- Update to 2.1.0
+  * New class-based API.
+- No further release notes
+
+-------------------------------------------------------------------

Old:
----
  eradicate-1.0.tar.gz

New:
----
  eradicate-2.1.0.tar.gz

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

Other differences:
------------------
++++++ python-eradicate.spec ++++++
--- /var/tmp/diff_new_pack.3cSWcJ/_old  2022-08-26 09:08:18.349385467 +0200
+++ /var/tmp/diff_new_pack.3cSWcJ/_new  2022-08-26 09:08:18.353385470 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-eradicate
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2022 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-eradicate
-Version:        1.0
+Version:        2.1.0
 Release:        0
 Summary:        Python utility for removing commented-out code
 License:        MIT
@@ -30,7 +30,7 @@
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 Requires(post): update-alternatives
-Requires(postun): update-alternatives
+Requires(postun):update-alternatives
 BuildArch:      noarch
 %python_subpackages
 
@@ -62,12 +62,13 @@
 %python_uninstall_alternative eradicate
 
 %check
-export PYTHONPATH=.
-%python_exec %{SOURCE1}
+%pyunittest -v
 
 %files %{python_files}
 %doc README.rst
 %python_alternative %{_bindir}/eradicate
-%{python_sitelib}/*
+%{python_sitelib}/eradicate.py*
+%pycache_only %{python_sitelib}/__pycache__/eradicate*.pyc
+%{python_sitelib}/eradicate-%{version}*-info
 
 %changelog

++++++ eradicate-1.0.tar.gz -> eradicate-2.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/MANIFEST.in 
new/eradicate-2.1.0/MANIFEST.in
--- old/eradicate-1.0/MANIFEST.in       2015-03-14 03:22:41.000000000 +0100
+++ new/eradicate-2.1.0/MANIFEST.in     2022-04-06 11:43:12.000000000 +0200
@@ -1,4 +1,3 @@
 include MANIFEST.in
 include README.rst
 exclude Makefile
-exclude test_eradicate.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/PKG-INFO new/eradicate-2.1.0/PKG-INFO
--- old/eradicate-1.0/PKG-INFO  2018-12-23 19:30:37.000000000 +0100
+++ new/eradicate-2.1.0/PKG-INFO        2022-04-06 11:46:41.558620200 +0200
@@ -1,70 +1,10 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: eradicate
-Version: 1.0
+Version: 2.1.0
 Summary: Removes commented-out code.
 Home-page: https://github.com/myint/eradicate
 Author: Steven Myint
-Author-email: UNKNOWN
 License: Expat License
-Description: =========
-        eradicate
-        =========
-        
-        .. image:: https://travis-ci.org/myint/eradicate.svg?branch=master
-            :target: https://travis-ci.org/myint/eradicate
-            :alt: Build status
-        
-        ``eradicate`` removes commented-out code from Python files.
-        
-        
-        Introduction
-        ============
-        
-        With modern revision control available, there is no reason to save
-        commented-out code to your repository. ``eradicate`` helps cleans up
-        existing junk comments. It does this by detecting block comments that
-        contain valid Python syntax that are likely to be commented out code.
-        (It avoids false positives like the sentence ``this is not good``,
-        which is valid Python syntax, but is probably not code.)
-        
-        
-        Example
-        =======
-        
-        ::
-        
-            $ eradicate --in-place example.py
-        
-        Before running ``eradicate``.
-        
-        .. code-block:: python
-        
-            #import os
-            # from foo import junk
-            #a = 3
-            a = 4
-            #foo(1, 2, 3)
-        
-            def foo(x, y, z):
-                # print('hello')
-                print(x, y, z)
-        
-                # This is a real comment.
-                #return True
-                return False
-        
-        After running ``eradicate``.
-        
-        .. code-block:: python
-        
-            a = 4
-        
-            def foo(x, y, z):
-                print(x, y, z)
-        
-                # This is a real comment.
-                return False
-        
 Keywords: clean,format,commented-out code
 Platform: UNKNOWN
 Classifier: Environment :: Console
@@ -73,3 +13,85 @@
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Topic :: Software Development :: Quality Assurance
+
+=========
+eradicate
+=========
+
+.. image:: 
https://github.com/myint/eradicate/actions/workflows/test.yml/badge.svg
+    :target: https://github.com/myint/eradicate/actions/workflows/test.yml
+    :alt: Build status
+
+----
+
+``eradicate`` removes commented-out code from Python files.
+
+
+Introduction
+============
+
+With modern revision control available, there is no reason to save
+commented-out code to your repository. ``eradicate`` helps cleans up
+existing junk comments. It does this by detecting block comments that
+contain valid Python syntax that are likely to be commented out code.
+(It avoids false positives like the sentence ``this is not good``,
+which is valid Python syntax, but is probably not code.)
+
+
+Example
+=======
+
+.. code-block:: bash
+
+    $ eradicate --in-place example.py
+
+Before running ``eradicate``.
+
+.. code-block:: python
+
+    #import os
+    # from foo import junk
+    #a = 3
+    a = 4
+    #foo(1, 2, 3)
+
+    def foo(x, y, z):
+        # print('hello')
+        print(x, y, z)
+
+        # This is a real comment.
+        #return True
+        return False
+
+After running ``eradicate``.
+
+.. code-block:: python
+
+    a = 4
+
+    def foo(x, y, z):
+        print(x, y, z)
+
+        # This is a real comment.
+        return False
+
+
+Whitelisting
+============
+
+False positives can happen so there is a whitelist feature to fix them 
shorthand.
+You can either add entries to the default whitelist with 
``--whitelist-extend`` or overwrite the default with ``--whitelist``.
+Both arguments expect a string of ``#`` separated regex strings (whitespaces 
are preserved). E.g. ``eradicate --whitelist "foo#b a r" filename``
+Those regex strings are matched case insensitive against the start of the 
comment itself.
+
+For the default whitelist please see ``eradicate.py``.
+
+
+Related
+=======
+
+There are different tools, plugins, and integrations for ``eradicate`` users:
+
+- `flake8-eradicate <https://github.com/sobolevn/flake8-eradicate>`_ - Flake8 
plugin to find commented out or dead code.
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/README.rst 
new/eradicate-2.1.0/README.rst
--- old/eradicate-1.0/README.rst        2014-05-11 16:49:33.000000000 +0200
+++ new/eradicate-2.1.0/README.rst      2022-04-06 11:43:12.000000000 +0200
@@ -2,10 +2,12 @@
 eradicate
 =========
 
-.. image:: https://travis-ci.org/myint/eradicate.svg?branch=master
-    :target: https://travis-ci.org/myint/eradicate
+.. image:: 
https://github.com/myint/eradicate/actions/workflows/test.yml/badge.svg
+    :target: https://github.com/myint/eradicate/actions/workflows/test.yml
     :alt: Build status
 
+----
+
 ``eradicate`` removes commented-out code from Python files.
 
 
@@ -23,7 +25,7 @@
 Example
 =======
 
-::
+.. code-block:: bash
 
     $ eradicate --in-place example.py
 
@@ -56,3 +58,22 @@
 
         # This is a real comment.
         return False
+
+
+Whitelisting
+============
+
+False positives can happen so there is a whitelist feature to fix them 
shorthand.
+You can either add entries to the default whitelist with 
``--whitelist-extend`` or overwrite the default with ``--whitelist``.
+Both arguments expect a string of ``#`` separated regex strings (whitespaces 
are preserved). E.g. ``eradicate --whitelist "foo#b a r" filename``
+Those regex strings are matched case insensitive against the start of the 
comment itself.
+
+For the default whitelist please see ``eradicate.py``.
+
+
+Related
+=======
+
+There are different tools, plugins, and integrations for ``eradicate`` users:
+
+- `flake8-eradicate <https://github.com/sobolevn/flake8-eradicate>`_ - Flake8 
plugin to find commented out or dead code.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/eradicate new/eradicate-2.1.0/eradicate
--- old/eradicate-1.0/eradicate 2014-12-31 17:03:15.000000000 +0100
+++ new/eradicate-2.1.0/eradicate       2022-04-06 11:43:12.000000000 +0200
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-# Copyright (C) 2012-2015 Steven Myint
+# Copyright (C) 2012-2018 Steven Myint
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/eradicate.egg-info/PKG-INFO 
new/eradicate-2.1.0/eradicate.egg-info/PKG-INFO
--- old/eradicate-1.0/eradicate.egg-info/PKG-INFO       1970-01-01 
01:00:00.000000000 +0100
+++ new/eradicate-2.1.0/eradicate.egg-info/PKG-INFO     2022-04-06 
11:46:41.000000000 +0200
@@ -0,0 +1,97 @@
+Metadata-Version: 2.1
+Name: eradicate
+Version: 2.1.0
+Summary: Removes commented-out code.
+Home-page: https://github.com/myint/eradicate
+Author: Steven Myint
+License: Expat License
+Keywords: clean,format,commented-out code
+Platform: UNKNOWN
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Software Development :: Quality Assurance
+
+=========
+eradicate
+=========
+
+.. image:: 
https://github.com/myint/eradicate/actions/workflows/test.yml/badge.svg
+    :target: https://github.com/myint/eradicate/actions/workflows/test.yml
+    :alt: Build status
+
+----
+
+``eradicate`` removes commented-out code from Python files.
+
+
+Introduction
+============
+
+With modern revision control available, there is no reason to save
+commented-out code to your repository. ``eradicate`` helps cleans up
+existing junk comments. It does this by detecting block comments that
+contain valid Python syntax that are likely to be commented out code.
+(It avoids false positives like the sentence ``this is not good``,
+which is valid Python syntax, but is probably not code.)
+
+
+Example
+=======
+
+.. code-block:: bash
+
+    $ eradicate --in-place example.py
+
+Before running ``eradicate``.
+
+.. code-block:: python
+
+    #import os
+    # from foo import junk
+    #a = 3
+    a = 4
+    #foo(1, 2, 3)
+
+    def foo(x, y, z):
+        # print('hello')
+        print(x, y, z)
+
+        # This is a real comment.
+        #return True
+        return False
+
+After running ``eradicate``.
+
+.. code-block:: python
+
+    a = 4
+
+    def foo(x, y, z):
+        print(x, y, z)
+
+        # This is a real comment.
+        return False
+
+
+Whitelisting
+============
+
+False positives can happen so there is a whitelist feature to fix them 
shorthand.
+You can either add entries to the default whitelist with 
``--whitelist-extend`` or overwrite the default with ``--whitelist``.
+Both arguments expect a string of ``#`` separated regex strings (whitespaces 
are preserved). E.g. ``eradicate --whitelist "foo#b a r" filename``
+Those regex strings are matched case insensitive against the start of the 
comment itself.
+
+For the default whitelist please see ``eradicate.py``.
+
+
+Related
+=======
+
+There are different tools, plugins, and integrations for ``eradicate`` users:
+
+- `flake8-eradicate <https://github.com/sobolevn/flake8-eradicate>`_ - Flake8 
plugin to find commented out or dead code.
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/eradicate.egg-info/SOURCES.txt 
new/eradicate-2.1.0/eradicate.egg-info/SOURCES.txt
--- old/eradicate-1.0/eradicate.egg-info/SOURCES.txt    1970-01-01 
01:00:00.000000000 +0100
+++ new/eradicate-2.1.0/eradicate.egg-info/SOURCES.txt  2022-04-06 
11:46:41.000000000 +0200
@@ -0,0 +1,9 @@
+MANIFEST.in
+README.rst
+eradicate
+eradicate.py
+setup.py
+eradicate.egg-info/PKG-INFO
+eradicate.egg-info/SOURCES.txt
+eradicate.egg-info/dependency_links.txt
+eradicate.egg-info/top_level.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/eradicate-1.0/eradicate.egg-info/dependency_links.txt 
new/eradicate-2.1.0/eradicate.egg-info/dependency_links.txt
--- old/eradicate-1.0/eradicate.egg-info/dependency_links.txt   1970-01-01 
01:00:00.000000000 +0100
+++ new/eradicate-2.1.0/eradicate.egg-info/dependency_links.txt 2022-04-06 
11:46:41.000000000 +0200
@@ -0,0 +1 @@
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/eradicate.egg-info/top_level.txt 
new/eradicate-2.1.0/eradicate.egg-info/top_level.txt
--- old/eradicate-1.0/eradicate.egg-info/top_level.txt  1970-01-01 
01:00:00.000000000 +0100
+++ new/eradicate-2.1.0/eradicate.egg-info/top_level.txt        2022-04-06 
11:46:41.000000000 +0200
@@ -0,0 +1 @@
+eradicate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/eradicate.py 
new/eradicate-2.1.0/eradicate.py
--- old/eradicate-1.0/eradicate.py      2018-12-23 19:28:01.000000000 +0100
+++ new/eradicate-2.1.0/eradicate.py    2022-04-06 11:44:17.000000000 +0200
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2015 Steven Myint
+# Copyright (C) 2012-2018 Steven Myint
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
@@ -30,172 +30,208 @@
 import re
 import tokenize
 
-__version__ = '1.0'
+__version__ = '2.1.0'
 
 
-MULTILINE_ASSIGNMENT_REGEX = re.compile(r'^\s*\w+\s*=.*[(\[{]$')
-PARTIAL_DICTIONARY_REGEX = re.compile(r'^\s*[\'"]\w+[\'"]\s*:.+[,{]\s*$')
-
-
-def comment_contains_code(line, aggressive=True):
-    """Return True comment contains code."""
-    line = line.lstrip()
-    if not line.startswith('#'):
-        return False
-
-    line = line.lstrip(' \t\v\n#').strip()
-
-    # Ignore non-comment related hashes. For example, "# Issue #999".
-    if re.search('#[0-9]', line):
-        return False
-
-    if line.startswith('pylint:'):
-        return False
-
-    if re.match(r'.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)', line):
-        return False
+class Eradicator(object):
+    """Eradicate comments."""
+    BRACKET_REGEX = re.compile(r'^[()\[\]{}\s]+$')
+    CODING_COMMENT_REGEX = re.compile(r'.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)')
+    DEF_STATEMENT_REGEX = re.compile(r"def 
.+\)[\s]+->[\s]+[a-zA-Z_][a-zA-Z0-9_]*:$")
+    FOR_STATEMENT_REGEX = re.compile(r"for [a-zA-Z_][a-zA-Z0-9_]* in .+:$")
+    HASH_NUMBER = re.compile(r'#[0-9]')
+    MULTILINE_ASSIGNMENT_REGEX = re.compile(r'^\s*\w+\s*=.*[(\[{]$')
+    PARTIAL_DICTIONARY_REGEX = re.compile(r'^\s*[\'"]\w+[\'"]\s*:.+[,{]\s*$')
+    PRINT_RETURN_REGEX = re.compile(r'^(print|return)\b\s*')
+    WITH_STATEMENT_REGEX = re.compile(r"with .+ as [a-zA-Z_][a-zA-Z0-9_]*:$")
+
+    CODE_INDICATORS = ['(', ')', '[', ']', '{', '}', ':', '=', '%',
+                       'print', 'return', 'break', 'continue', 'import']
+    CODE_KEYWORDS = [r'elif\s+.*', 'else', 'try', 'finally', r'except\s+.*']
+    CODE_KEYWORDS_AGGR = CODE_KEYWORDS + [r'if\s+.*']
+    WHITESPACE_HASH = ' \t\v\n#'
+
+    DEFAULT_WHITELIST = (
+        r'pylint',
+        r'pyright',
+        r'noqa',
+        r'nosec',
+        r'type:\s*ignore',
+        r'fmt:\s*(on|off)',
+        
r'isort:\s*(on|off|skip|skip_file|split|dont-add-imports(:\s*\[.*?\])?)',
+        r'TODO',
+        r'FIXME',
+        r'XXX'
+    )
+    WHITELIST_REGEX = re.compile(r'|'.join(DEFAULT_WHITELIST), 
flags=re.IGNORECASE)
+
+    def comment_contains_code(self, line, aggressive=True):
+        """Return True comment contains code."""
+        line = line.lstrip()
+        if not line.startswith('#'):
+            return False
+
+        line = line.lstrip(self.WHITESPACE_HASH).strip()
+
+        # Ignore non-comment related hashes. For example, "# Issue #999".
+        if self.HASH_NUMBER.search(line):
+            return False
+
+        # Ignore whitelisted comments
+        if self.WHITELIST_REGEX.search(line):
+            return False
+
+        if self.CODING_COMMENT_REGEX.match(line):
+            return False
+
+        # Check that this is possibly code.
+        for symbol in self.CODE_INDICATORS:
+            if symbol in line:
+                break
+        else:
+            return False
 
-    # Check that this is possibly code.
-    for symbol in list('()[]{}:=%') + ['print', 'return', 'break', 'continue',
-                                       'import']:
-        if symbol in line:
-            break
-    else:
-        return False
+        if self.multiline_case(line, aggressive=aggressive):
+            return True
 
-    if multiline_case(line, aggressive=aggressive):
-        return True
+        for symbol in self.CODE_KEYWORDS_AGGR if aggressive else 
self.CODE_KEYWORDS:
+            if re.match(r'^\s*' + symbol + r'\s*:\s*$', line):
+                return True
 
-    symbol_list = [r'elif\s+.*', 'else', 'try',
-                   'finally', r'except\s+.*']
-    if aggressive:
-        symbol_list.append(r'if\s+.*')
+        line = self.PRINT_RETURN_REGEX.sub('', line)
 
-    for symbol in symbol_list:
-        if re.match(r'^\s*' + symbol + r'\s*:\s*$', line):
+        if self.PARTIAL_DICTIONARY_REGEX.match(line):
             return True
 
-    line = re.sub(r'^(print|return)\b\s*', '', line)
-
-    if re.match(PARTIAL_DICTIONARY_REGEX, line):
-        return True
+        try:
+            compile(line, '<string>', 'exec')
+        except (SyntaxError, TypeError, UnicodeDecodeError):
+            return False
+        else:
+            return True
 
-    try:
-        compile(line, '<string>', 'exec')
-        return True
-    except (SyntaxError, TypeError, UnicodeDecodeError):
-        return False
 
+    def multiline_case(self, line, aggressive=True):
+        """Return True if line is probably part of some multiline code."""
+        if aggressive:
+            for ending in ')]}':
+                if line.endswith(ending + ':'):
+                    return True
+
+                if line.strip() == ending + ',':
+                    return True
+
+            # Check whether a function/method definition with return value
+            # annotation
+            if self.DEF_STATEMENT_REGEX.search(line):
+                return True
 
-def multiline_case(line, aggressive=True):
-    """Return True if line is probably part of some multiline code."""
-    if aggressive:
-        for ending in ')]}':
-            if line.endswith(ending + ':'):
+            # Check weather a with statement
+            if self.WITH_STATEMENT_REGEX.search(line):
                 return True
 
-            if line.strip() == ending + ',':
+            # Check weather a for statement
+            if self.FOR_STATEMENT_REGEX.search(line):
                 return True
 
-        # Check whether a function/method definition with return value
-        # annotation
-        if re.search(r"def .+\)[\s]+->[\s]+[a-zA-Z_][a-zA-Z0-9_]*:$", line):
+        if line.endswith('\\'):
             return True
 
-        # Check weather a with statement
-        if re.search(r"with .+ as [a-zA-Z_][a-zA-Z0-9_]*:$", line):
+        if self.MULTILINE_ASSIGNMENT_REGEX.match(line):
             return True
 
-        # Check weather a for statement
-        if re.search(r"for [a-zA-Z_][a-zA-Z0-9_]* in .+:$", line):
+        if self.BRACKET_REGEX.match(line):
             return True
 
-    if line.endswith('\\'):
-        return True
-
-    if re.match(MULTILINE_ASSIGNMENT_REGEX, line):
-        return True
-
-    if re.match(r'^[()\[\]{}\s]+$', line):
-        return True
-
-    return False
-
-
-def commented_out_code_line_numbers(source, aggressive=True):
-    """Yield line numbers of commented-out code."""
-    sio = io.StringIO(source)
-    try:
-        for token in tokenize.generate_tokens(sio.readline):
-            token_type = token[0]
-            start_row = token[2][0]
-            line = token[4]
-
-            if (token_type == tokenize.COMMENT and
-                    line.lstrip().startswith('#') and
-                    comment_contains_code(line, aggressive)):
-                yield start_row
-    except (tokenize.TokenError, IndentationError):
-        pass
-
-
-def filter_commented_out_code(source, aggressive=True):
-    """Yield code with commented out code removed."""
-    marked_lines = list(commented_out_code_line_numbers(source,
-                                                        aggressive))
-    sio = io.StringIO(source)
-    previous_line = ''
-    for line_number, line in enumerate(sio.readlines(), start=1):
-        if (line_number not in marked_lines or
-                previous_line.rstrip().endswith('\\')):
-            yield line
-        previous_line = line
+        return False
 
 
-def fix_file(filename, args, standard_out):
-    """Run filter_commented_out_code() on file."""
-    encoding = detect_encoding(filename)
-    with open_with_encoding(filename, encoding=encoding) as input_file:
-        source = input_file.read()
+    def commented_out_code_line_numbers(self, source, aggressive=True):
+        """Yield line numbers of commented-out code."""
+        sio = io.StringIO(source)
+        try:
+            for token in tokenize.generate_tokens(sio.readline):
+                token_type = token[0]
+                start_row = token[2][0]
+                line = token[4]
+
+                if (token_type == tokenize.COMMENT and
+                        line.lstrip().startswith('#') and
+                        self.comment_contains_code(line, aggressive)):
+                    yield start_row
+        except (tokenize.TokenError, IndentationError):
+            pass
+
+
+    def filter_commented_out_code(self, source, aggressive=True):
+        """Yield code with commented out code removed."""
+        marked_lines = list(self.commented_out_code_line_numbers(source,
+                                                            aggressive))
+        sio = io.StringIO(source)
+        previous_line = ''
+        for line_number, line in enumerate(sio.readlines(), start=1):
+            if (line_number not in marked_lines or
+                    previous_line.rstrip().endswith('\\')):
+                yield line
+            previous_line = line
+
+
+    def fix_file(self, filename, args, standard_out):
+        """Run filter_commented_out_code() on file."""
+        encoding = self.detect_encoding(filename)
+        with self.open_with_encoding(filename, encoding=encoding) as 
input_file:
+            source = input_file.read()
+
+        filtered_source = ''.join(self.filter_commented_out_code(source,
+                                                            args.aggressive))
+
+        if source != filtered_source:
+            if args.in_place:
+                with self.open_with_encoding(filename, mode='w',
+                                        encoding=encoding) as output_file:
+                    output_file.write(filtered_source)
+            else:
+                diff = difflib.unified_diff(
+                    source.splitlines(),
+                    filtered_source.splitlines(),
+                    'before/' + filename,
+                    'after/' + filename,
+                    lineterm='')
+                standard_out.write('\n'.join(list(diff) + ['']))
+            return True
 
-    filtered_source = ''.join(filter_commented_out_code(source,
-                                                        args.aggressive))
 
-    if source != filtered_source:
-        if args.in_place:
-            with open_with_encoding(filename, mode='w',
-                                    encoding=encoding) as output_file:
-                output_file.write(filtered_source)
+    def open_with_encoding(self, filename, encoding, mode='r'):
+        """Return opened file with a specific encoding."""
+        return io.open(filename, mode=mode, encoding=encoding,
+                       newline='')  # Preserve line endings
+
+
+    def detect_encoding(self, filename):
+        """Return file encoding."""
+        try:
+            with open(filename, 'rb') as input_file:
+                from lib2to3.pgen2 import tokenize as lib2to3_tokenize
+                encoding = 
lib2to3_tokenize.detect_encoding(input_file.readline)[0]
+
+                # Check for correctness of encoding.
+                with self.open_with_encoding(filename, encoding) as input_file:
+                    input_file.read()
+
+            return encoding
+        except (SyntaxError, LookupError, UnicodeDecodeError):
+            return 'latin-1'
+
+    def update_whitelist(self, new_whitelist, extend_default=True):
+        """Updates the whitelist."""
+        if extend_default:
+            self.WHITELIST_REGEX = re.compile(
+                r'|'.join(list(self.DEFAULT_WHITELIST) + new_whitelist),
+                flags=re.IGNORECASE)
         else:
-            diff = difflib.unified_diff(
-                source.splitlines(),
-                filtered_source.splitlines(),
-                'before/' + filename,
-                'after/' + filename,
-                lineterm='')
-            standard_out.write('\n'.join(list(diff) + ['']))
-
-
-def open_with_encoding(filename, encoding, mode='r'):
-    """Return opened file with a specific encoding."""
-    return io.open(filename, mode=mode, encoding=encoding,
-                   newline='')  # Preserve line endings
-
-
-def detect_encoding(filename):
-    """Return file encoding."""
-    try:
-        with open(filename, 'rb') as input_file:
-            from lib2to3.pgen2 import tokenize as lib2to3_tokenize
-            encoding = lib2to3_tokenize.detect_encoding(input_file.readline)[0]
-
-            # Check for correctness of encoding.
-            with open_with_encoding(filename, encoding) as input_file:
-                input_file.read()
-
-        return encoding
-    except (SyntaxError, LookupError, UnicodeDecodeError):
-        return 'latin-1'
+            self.WHITELIST_REGEX = re.compile(
+                r'|'.join(new_whitelist),
+                flags=re.IGNORECASE)
 
 
 def main(argv, standard_out, standard_error):
@@ -209,13 +245,36 @@
     parser.add_argument('-a', '--aggressive', action='store_true',
                         help='make more aggressive changes; '
                              'this may result in false positives')
+    parser.add_argument('-e', '--error', action="store_true",
+                        help="Exit code based on result of check")
     parser.add_argument('--version', action='version',
                         version='%(prog)s ' + __version__)
+    parser.add_argument('--whitelist', action="store",
+                        help=(
+                            'String of "#" separated comment beginnings to 
whitelist. '
+                            'Single parts are interpreted as regex. '
+                            'OVERWRITING the default whitelist: {}'
+                        ).format(Eradicator.DEFAULT_WHITELIST))
+    parser.add_argument('--whitelist-extend', action="store",
+                        help=(
+                            'String of "#" separated comment beginnings to 
whitelist '
+                            'Single parts are interpreted as regex. '
+                            'Overwrites --whitelist. '
+                            'EXTENDING the default whitelist: {} '
+                        ).format(Eradicator.DEFAULT_WHITELIST))
     parser.add_argument('files', nargs='+', help='files to format')
 
     args = parser.parse_args(argv[1:])
 
+    eradicator = Eradicator()
+
+    if args.whitelist_extend:
+        eradicator.update_whitelist(args.whitelist_extend.split('#'), True)
+    elif args.whitelist:
+        eradicator.update_whitelist(args.whitelist.split('#'), False)
+
     filenames = list(set(args.files))
+    change_or_error = False
     while filenames:
         name = filenames.pop(0)
         if args.recursive and os.path.isdir(name):
@@ -227,6 +286,9 @@
                                   if not d.startswith('.')]
         else:
             try:
-                fix_file(name, args=args, standard_out=standard_out)
+                change_or_error = eradicator.fix_file(name, args=args, 
standard_out=standard_out) or change_or_error
             except IOError as exception:
                 print('{}'.format(exception), file=standard_error)
+                change_or_error = True
+    if change_or_error and args.error:
+        return 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/setup.cfg new/eradicate-2.1.0/setup.cfg
--- old/eradicate-1.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100
+++ new/eradicate-2.1.0/setup.cfg       2022-04-06 11:46:41.559085400 +0200
@@ -0,0 +1,4 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/eradicate-1.0/setup.py new/eradicate-2.1.0/setup.py
--- old/eradicate-1.0/setup.py  2017-04-17 01:23:44.000000000 +0200
+++ new/eradicate-2.1.0/setup.py        2022-04-06 11:43:12.000000000 +0200
@@ -5,7 +5,7 @@
 from __future__ import unicode_literals
 
 import ast
-from distutils import core
+from setuptools import setup
 
 
 def version():
@@ -17,7 +17,7 @@
 
 
 with open('README.rst') as readme:
-    core.setup(
+    setup(
         name='eradicate',
         version=version(),
         description='Removes commented-out code.',

++++++ test_eradicate.py ++++++
--- /var/tmp/diff_new_pack.3cSWcJ/_old  2022-08-26 09:08:18.449385569 +0200
+++ /var/tmp/diff_new_pack.3cSWcJ/_new  2022-08-26 09:08:18.453385572 +0200
@@ -10,6 +10,11 @@
 import sys
 import tempfile
 import unittest
+try:  # pragma: no cover
+    import mock
+except ModuleNotFoundError:  # pragma: no cover
+    import unittest.mock as mock
+import re
 
 import eradicate
 
@@ -17,141 +22,254 @@
 class UnitTests(unittest.TestCase):
 
     def test_comment_contains_code(self):
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# This is a (real) comment.'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# 123'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# 123.1'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# 1, 2, 3'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             'x = 1  # x = 1'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# pylint: disable=redefined-outer-name'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# Issue #999: This is not code'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '# x = 1'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#from foo import eradicate'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#import eradicate'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#"key": value,'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#"key": "value",'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#"key": 1 + 1,'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             "#'key': 1 + 1,"))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#"key": {'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#}'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#} )]'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#},'))
 
     def test_comment_contains_code_with_print(self):
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#print'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#print(1)'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#print 1'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#to print'))
 
     def test_comment_contains_code_with_return(self):
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#return x'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#to return'))
 
     def test_comment_contains_code_with_multi_line(self):
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#def foo():'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#else:'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#  else  :  '))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '# "foo %d" % \\'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#elif True:'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#x = foo('))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '#except Exception:'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# this is = to that :('))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#else'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#or else:'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#else True:'))
 
     def test_comment_contains_code_with_sentences(self):
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#code is good'))
 
     def test_comment_contains_code_with_encoding(self):
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# coding=utf-8'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '#coding= utf-8'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# coding: utf-8'))
 
-        self.assertFalse(eradicate.comment_contains_code(
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
             '# encoding: utf8'))
 
-        self.assertTrue(eradicate.comment_contains_code(
+        self.assertTrue(eradicate.Eradicator().comment_contains_code(
             '# codings=utf-8'))
 
+    def test_comment_contains_code_with_default_whitelist(self):
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# pylint: disable=A0123'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# pylint:disable=A0123'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# pylint: disable = A0123'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# pylint:disable = A0123'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# pyright: reportErrorName=true'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# noqa'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# NOQA'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# noqa: A123'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# noqa:A123'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# nosec'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# fmt: on'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# fmt: off'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# fmt:on'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# fmt:off'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: on'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:on'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: off'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:off'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: skip'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:skip'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: skip_file'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:skip_file'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: split'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:split'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: dont-add-imports'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:dont-add-imports'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: dont-add-imports: ["import os"]'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:dont-add-imports: ["import os"]'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort: dont-add-imports:["import os"]'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# isort:dont-add-imports:["import os"]'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# type: ignore'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# type:ignore'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# type: ignore[import]'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# type:ignore[import]'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# TODO: Do that'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# FIXME: Fix that'))
+
+        self.assertFalse(eradicate.Eradicator().comment_contains_code(
+            '# XXX: What ever'))
+
+
     def test_commented_out_code_line_numbers(self):
         self.assertEqual(
             [1, 3],
-            list(eradicate.commented_out_code_line_numbers(
+            list(eradicate.Eradicator().commented_out_code_line_numbers(
                 """\
 # print(5)
 # This is a comment.
@@ -166,7 +284,7 @@
     def test_commented_out_code_line_numbers_with_errors(self):
         self.assertEqual(
             [1, 3],
-            list(eradicate.commented_out_code_line_numbers(
+            list(eradicate.Eradicator().commented_out_code_line_numbers(
                 """\
 # print(5)
 # This is a comment.
@@ -184,7 +302,7 @@
     def test_commented_out_code_line_numbers_with_with_statement(self):
         self.assertEqual(
             [1, 2],
-            list(eradicate.commented_out_code_line_numbers("""\
+            list(eradicate.Eradicator().commented_out_code_line_numbers("""\
 # with open('filename', 'w') as out_file:
 #     json.dump(objects, out_file)
 #
@@ -193,7 +311,7 @@
     def test_commented_out_code_line_numbers_with_for_statement(self):
         self.assertEqual(
             [1, 2],
-            list(eradicate.commented_out_code_line_numbers("""\
+            list(eradicate.Eradicator().commented_out_code_line_numbers("""\
 # for x in y:
 #     oops = x.ham
 """)))
@@ -208,7 +326,7 @@
 # The below is another comment.
 # 3 / 2 + 21
 """,
-            ''.join(eradicate.filter_commented_out_code(
+            ''.join(eradicate.Eradicator().filter_commented_out_code(
                 """\
 # print(5)
 # This is a comment.
@@ -233,7 +351,7 @@
 """
         self.assertEqual(
             line,
-            ''.join(eradicate.filter_commented_out_code(line)))
+            ''.join(eradicate.Eradicator().filter_commented_out_code(line)))
 
     def test_filter_commented_out_code_with_larger_example(self):
         self.assertEqual(
@@ -245,7 +363,7 @@
 # The below is another comment.
 # 3 / 2 + 21
 """,
-            ''.join(eradicate.filter_commented_out_code(
+            ''.join(eradicate.Eradicator().filter_commented_out_code(
                 """\
 # print(5)
 # This is a comment.
@@ -266,13 +384,13 @@
 """
         self.assertEqual(
             code,
-            ''.join(eradicate.filter_commented_out_code(code,
+            ''.join(eradicate.Eradicator().filter_commented_out_code(code,
                                                         aggressive=False)))
 
     def test_filter_commented_out_code_with_annotation(self):
         self.assertEqual(
             '\n\n\n',
-            ''.join(eradicate.filter_commented_out_code("""\
+            ''.join(eradicate.Eradicator().filter_commented_out_code("""\
 # class CommentedClass(object):
 #     def __init__(self, prop: int) -> None:
 #         self.property = prop
@@ -290,7 +408,21 @@
     def test_detect_encoding_with_bad_encoding(self):
         with temporary_file('# -*- coding: blah -*-\n') as filename:
             self.assertEqual('latin-1',
-                             eradicate.detect_encoding(filename))
+                             eradicate.Eradicator().detect_encoding(filename))
+
+    def test_extend_whitelist(self):
+        eradicator = eradicate.Eradicator()
+        eradicator.update_whitelist(["foo"], True)
+        self.assertTrue(
+            eradicator.WHITELIST_REGEX == re.compile(
+                r'|'.join(list(eradicator.DEFAULT_WHITELIST) + ["foo"]), 
flags=re.IGNORECASE
+            )
+        )
+
+    def test_update_whitelist(self):
+        eradicator = eradicate.Eradicator()
+        eradicator.update_whitelist(["foo"], False)
+        self.assertTrue(eradicator.WHITELIST_REGEX == re.compile("foo", 
flags=re.IGNORECASE))
 
 
 class SystemTests(unittest.TestCase):
@@ -372,6 +504,28 @@
                        standard_error=ignore)
         self.assertFalse(output_file.getvalue())
 
+    def test_returns_error_code_if_requested(self):
+        with temporary_file("""\
+    # x * 3 == False
+    # x is a variable
+    """) as filename:
+            output_file = io.StringIO()
+            result = eradicate.main(argv=['my_fake_program', filename, "-e"],
+                               standard_out=output_file,
+                               standard_error=None)
+            self.assertTrue(result)
+
+    def test_returns_None_if_no_error_request(self):
+        with temporary_file("""\
+    # x * 3 == False
+    # x is a variable
+    """) as filename:
+            output_file = io.StringIO()
+            result = eradicate.main(argv=['my_fake_program', filename],
+                               standard_out=output_file,
+                               standard_error=None)
+            self.assertTrue(result is None)
+
     def test_end_to_end(self):
         with temporary_file("""\
 # x * 3 == False
@@ -386,6 +540,26 @@
  # x is a variable
 """, '\n'.join(process.communicate()[0].decode().split('\n')[2:]))
 
+    def test_whitelist(self):
+        mock_update = mock.Mock()
+        with mock.patch.object(eradicate.Eradicator, 'update_whitelist', 
mock_update):
+            with temporary_file("# empty") as filename:
+                result = eradicate.main(argv=['my_fake_program', 
'--whitelist', 'foo# bar', filename],
+                                   standard_out=None,
+                                   standard_error=None)
+            self.assertTrue(result is None)
+            mock_update.assert_called_once_with(["foo", " bar"], False)
+
+    def test_whitelist_extend(self):
+        mock_update = mock.Mock()
+        with mock.patch.object(eradicate.Eradicator, 'update_whitelist', 
mock_update):
+            with temporary_file("# empty") as filename:
+                result = eradicate.main(argv=['my_fake_program', 
'--whitelist-extend', 'foo #bar', filename],
+                                   standard_out=None,
+                                   standard_error=None)
+            self.assertTrue(result is None)
+            mock_update.assert_called_once_with(["foo ", "bar"], True)
+
 
 @contextlib.contextmanager
 def temporary_file(contents, directory='.', prefix=''):

Reply via email to