blob: 919a81a7c902c549d7b4a209e015bc0382ae3d46 [file] [log] [blame]
#!/usr/bin/env python
# coding: utf-8
"""Test suite for autoflake."""
from __future__ import unicode_literals
import contextlib
import io
import os
import re
import shutil
import subprocess
import sys
import tempfile
import unittest
import autoflake
ROOT_DIRECTORY = os.path.abspath(os.path.dirname(__file__))
if (
'AUTOFLAKE_COVERAGE' in os.environ and
int(os.environ['AUTOFLAKE_COVERAGE'])
):
AUTOFLAKE_COMMAND = ['coverage', 'run', '--branch', '--parallel',
'--omit=*/distutils/*,*/site-packages/*',
os.path.join(ROOT_DIRECTORY, 'autoflake.py')]
else:
# We need to specify the executable to make sure the correct Python
# interpreter gets used.
AUTOFLAKE_COMMAND = [sys.executable,
os.path.join(
ROOT_DIRECTORY,
'autoflake.py')] # pragma: no cover
class UnitTests(unittest.TestCase):
"""Unit tests."""
def test_imports(self):
self.assertGreater(len(autoflake.SAFE_IMPORTS), 0)
def test_unused_import_line_numbers(self):
self.assertEqual(
[1],
list(autoflake.unused_import_line_numbers(
autoflake.check('import os\n'))))
def test_unused_import_line_numbers_with_from(self):
self.assertEqual(
[1],
list(autoflake.unused_import_line_numbers(
autoflake.check('from os import path\n'))))
def test_unused_import_line_numbers_with_dot(self):
self.assertEqual(
[1],
list(autoflake.unused_import_line_numbers(
autoflake.check('import os.path\n'))))
def test_extract_package_name(self):
self.assertEqual('os', autoflake.extract_package_name('import os'))
self.assertEqual(
'os', autoflake.extract_package_name('from os import path'))
self.assertEqual(
'os', autoflake.extract_package_name('import os.path'))
def test_extract_package_name_should_ignore_doctest_for_now(self):
self.assertFalse(autoflake.extract_package_name('>>> import os'))
def test_standard_package_names(self):
self.assertIn('os', list(autoflake.standard_package_names()))
self.assertIn('subprocess', list(autoflake.standard_package_names()))
self.assertIn('urllib', list(autoflake.standard_package_names()))
self.assertNotIn('autoflake', list(autoflake.standard_package_names()))
self.assertNotIn('pep8', list(autoflake.standard_package_names()))
def test_get_line_ending(self):
self.assertEqual('\n', autoflake.get_line_ending('\n'))
self.assertEqual('\n', autoflake.get_line_ending('abc\n'))
self.assertEqual('\t \t\n', autoflake.get_line_ending('abc\t \t\n'))
self.assertEqual('', autoflake.get_line_ending('abc'))
self.assertEqual('', autoflake.get_line_ending(''))
def test_get_indentation(self):
self.assertEqual('', autoflake.get_indentation(''))
self.assertEqual(' ', autoflake.get_indentation(' abc'))
self.assertEqual(' ', autoflake.get_indentation(' abc \n\t'))
self.assertEqual('\t', autoflake.get_indentation('\tabc \n\t'))
self.assertEqual(' \t ', autoflake.get_indentation(' \t abc \n\t'))
self.assertEqual('', autoflake.get_indentation(' '))
def test_filter_star_import(self):
self.assertEqual(
'from math import cos',
autoflake.filter_star_import('from math import *',
['cos']))
self.assertEqual(
'from math import cos, sin',
autoflake.filter_star_import('from math import *',
['sin', 'cos']))
def test_filter_unused_variable(self):
self.assertEqual('foo()',
autoflake.filter_unused_variable('x = foo()'))
self.assertEqual(' foo()',
autoflake.filter_unused_variable(' x = foo()'))
def test_filter_unused_variable_with_literal_or_name(self):
self.assertEqual('pass',
autoflake.filter_unused_variable('x = 1'))
self.assertEqual('pass',
autoflake.filter_unused_variable('x = y'))
self.assertEqual('pass',
autoflake.filter_unused_variable('x = {}'))
def test_filter_unused_variable_with_basic_data_structures(self):
self.assertEqual('pass',
autoflake.filter_unused_variable('x = dict()'))
self.assertEqual('pass',
autoflake.filter_unused_variable('x = list()'))
self.assertEqual('pass',
autoflake.filter_unused_variable('x = set()'))
def test_filter_unused_variable_should_ignore_multiline(self):
self.assertEqual('x = foo()\\',
autoflake.filter_unused_variable('x = foo()\\'))
def test_filter_unused_variable_should_multiple_assignments(self):
self.assertEqual('x = y = foo()',
autoflake.filter_unused_variable('x = y = foo()'))
def test_filter_unused_variable_with_exception(self):
self.assertEqual(
'except Exception:',
autoflake.filter_unused_variable('except Exception as exception:'))
self.assertEqual(
'except (ImportError, ValueError):',
autoflake.filter_unused_variable(
'except (ImportError, ValueError) as foo:'))
def test_filter_code(self):
self.assertEqual(
"""\
import os
pass
os.foo()
""",
''.join(autoflake.filter_code("""\
import os
import re
os.foo()
""")))
def test_filter_code_with_indented_import(self):
self.assertEqual(
"""\
import os
if True:
pass
os.foo()
""",
''.join(autoflake.filter_code("""\
import os
if True:
import re
os.foo()
""")))
def test_filter_code_with_from(self):
self.assertEqual(
"""\
pass
x = 1
""",
''.join(autoflake.filter_code("""\
from os import path
x = 1
""")))
def test_filter_code_with_not_from(self):
self.assertEqual(
"""\
pass
x = 1
""",
''.join(autoflake.filter_code("""\
import frommer
x = 1
""",
remove_all_unused_imports=True)))
def test_filter_code_with_used_from(self):
self.assertEqual(
"""\
import frommer
print(frommer)
""",
''.join(autoflake.filter_code("""\
import frommer
print(frommer)
""",
remove_all_unused_imports=True)))
def test_filter_code_with_ambiguous_from(self):
self.assertEqual(
"""\
pass
""",
''.join(autoflake.filter_code("""\
from frommer import abc, frommer, xyz
""",
remove_all_unused_imports=True)))
def test_filter_code_should_avoid_inline_except(self):
line = """\
try: from zap import foo
except: from zap import bar
"""
self.assertEqual(
line,
''.join(autoflake.filter_code(line,
remove_all_unused_imports=True)))
def test_filter_code_should_avoid_escaped_newlines(self):
line = """\
try:\\
from zap import foo
except:\\
from zap import bar
"""
self.assertEqual(
line,
''.join(autoflake.filter_code(line,
remove_all_unused_imports=True)))
def test_filter_code_with_remove_all_unused_imports(self):
self.assertEqual(
"""\
pass
pass
x = 1
""",
''.join(autoflake.filter_code("""\
import foo
import zap
x = 1
""", remove_all_unused_imports=True)))
def test_filter_code_with_additional_imports(self):
self.assertEqual(
"""\
pass
import zap
x = 1
""",
''.join(autoflake.filter_code("""\
import foo
import zap
x = 1
""", additional_imports=['foo', 'bar'])))
def test_filter_code_should_ignore_imports_with_inline_comment(self):
self.assertEqual(
"""\
from os import path # foo
pass
from fake_foo import z # foo, foo, zap
x = 1
""",
''.join(autoflake.filter_code("""\
from os import path # foo
from os import path
from fake_foo import z # foo, foo, zap
x = 1
""")))
def test_filter_code_should_respect_noqa(self):
self.assertEqual(
"""\
pass
import re # noqa
from subprocess import Popen # NOQA
x = 1
""",
''.join(autoflake.filter_code("""\
from os import path
import re # noqa
from subprocess import Popen # NOQA
x = 1
""")))
def test_filter_code_expand_star_imports(self):
self.assertEqual(
"""\
from math import sin
sin(1)
""",
''.join(autoflake.filter_code("""\
from math import *
sin(1)
""", expand_star_imports=True)))
self.assertEqual(
"""\
from math import cos, sin
sin(1)
cos(1)
""",
''.join(autoflake.filter_code("""\
from math import *
sin(1)
cos(1)
""", expand_star_imports=True)))
def test_filter_code_ignore_multiple_star_import(self):
self.assertEqual(
"""\
from math import *
from re import *
sin(1)
cos(1)
""",
''.join(autoflake.filter_code("""\
from math import *
from re import *
sin(1)
cos(1)
""", expand_star_imports=True)))
def test_filter_code_with_special_re_symbols_in_key(self):
self.assertEqual(
"""\
a = {
'????': 2,
}
print(a)
""",
''.join(autoflake.filter_code("""\
a = {
'????': 3,
'????': 2,
}
print(a)
""", remove_duplicate_keys=True)))
def test_multiline_import(self):
self.assertTrue(autoflake.multiline_import(r"""\
import os, \
math, subprocess
"""))
self.assertFalse(autoflake.multiline_import("""\
import os, math, subprocess
"""))
self.assertTrue(autoflake.multiline_import("""\
import os, math, subprocess
""", previous_line='if: \\\n'))
self.assertTrue(
autoflake.multiline_import('from os import (path, sep)'))
def test_multiline_statement(self):
self.assertFalse(autoflake.multiline_statement('x = foo()'))
self.assertTrue(autoflake.multiline_statement('x = 1;'))
self.assertTrue(autoflake.multiline_statement('import os, \\'))
self.assertTrue(autoflake.multiline_statement('foo('))
self.assertTrue(autoflake.multiline_statement('1',
previous_line='x = \\'))
def test_break_up_import(self):
self.assertEqual(
'import abc\nimport math\nimport subprocess\n',
autoflake.break_up_import('import abc, subprocess, math\n'))
def test_break_up_import_with_indentation(self):
self.assertEqual(
' import abc\n import math\n import subprocess\n',
autoflake.break_up_import(' import abc, subprocess, math\n'))
def test_break_up_import_should_do_nothing_on_no_line_ending(self):
self.assertEqual(
'import abc, subprocess, math',
autoflake.break_up_import('import abc, subprocess, math'))
def test_filter_from_import_no_remove(self):
self.assertEqual(
"""\
from foo import abc, math, subprocess\n""",
autoflake.filter_from_import(
' from foo import abc, subprocess, math\n',
unused_module=[]))
def test_filter_from_import_remove_module(self):
self.assertEqual(
"""\
from foo import math, subprocess\n""",
autoflake.filter_from_import(
' from foo import abc, subprocess, math\n',
unused_module=['foo.abc']))
def test_filter_from_import_remove_all(self):
self.assertEqual(
' pass\n',
autoflake.filter_from_import(
' from foo import abc, subprocess, math\n',
unused_module=['foo.abc', 'foo.subprocess',
'foo.math']))
def test_filter_code_should_ignore_multiline_imports(self):
self.assertEqual(
r"""\
import os
pass
import os, \
math, subprocess
os.foo()
""",
''.join(autoflake.filter_code(r"""\
import os
import re
import os, \
math, subprocess
os.foo()
""")))
def test_filter_code_should_ignore_semicolons(self):
self.assertEqual(
r"""\
import os
pass
import os; import math, subprocess
os.foo()
""",
''.join(autoflake.filter_code(r"""\
import os
import re
import os; import math, subprocess
os.foo()
""")))
def test_filter_code_should_ignore_non_standard_library(self):
self.assertEqual(
"""\
import os
import my_own_module
pass
from my_package import another_module
from my_package import subprocess
from my_blah.my_blah_blah import blah
os.foo()
""",
''.join(autoflake.filter_code("""\
import os
import my_own_module
import re
from my_package import another_module
from my_package import subprocess
from my_blah.my_blah_blah import blah
os.foo()
""")))
def test_filter_code_should_ignore_unsafe_imports(self):
self.assertEqual(
"""\
import rlcompleter
pass
pass
pass
print(1)
""",
''.join(autoflake.filter_code("""\
import rlcompleter
import sys
import io
import os
print(1)
""")))
def test_filter_code_should_ignore_docstring(self):
line = """
def foo():
'''
>>> import math
'''
"""
self.assertEqual(line, ''.join(autoflake.filter_code(line)))
def test_fix_code(self):
self.assertEqual(
"""\
import os
import math
from sys import version
os.foo()
math.pi
x = version
""",
autoflake.fix_code("""\
import os
import re
import abc, math, subprocess
from sys import exit, version
os.foo()
math.pi
x = version
"""))
def test_fix_code_with_from_and_as(self):
self.assertEqual(
"""\
from collections import namedtuple as xyz
xyz
""",
autoflake.fix_code("""\
from collections import defaultdict, namedtuple as xyz
xyz
"""))
self.assertEqual(
"""\
from collections import namedtuple as xyz
xyz
""",
autoflake.fix_code("""\
from collections import defaultdict as abc, namedtuple as xyz
xyz
"""))
self.assertEqual(
"""\
from collections import namedtuple
namedtuple
""",
autoflake.fix_code("""\
from collections import defaultdict as abc, namedtuple
namedtuple
"""))
self.assertEqual(
"""\
""",
autoflake.fix_code("""\
from collections import defaultdict as abc, namedtuple as xyz
"""))
def test_fix_code_with_from_with_and_without_remove_all(self):
code = """\
from x import a as b, c as d
"""
self.assertEqual(
"""\
""",
autoflake.fix_code(code, remove_all_unused_imports=True))
self.assertEqual(
code,
autoflake.fix_code(code, remove_all_unused_imports=False))
def test_fix_code_with_from_and_depth_module(self):
self.assertEqual(
"""\
from distutils.version import StrictVersion
StrictVersion('1.0.0')
""",
autoflake.fix_code("""\
from distutils.version import LooseVersion, StrictVersion
StrictVersion('1.0.0')
"""))
self.assertEqual(
"""\
from distutils.version import StrictVersion as version
version('1.0.0')
""",
autoflake.fix_code("""\
from distutils.version import LooseVersion, StrictVersion as version
version('1.0.0')
"""))
def test_fix_code_with_indented_from(self):
self.assertEqual(
"""\
def z():
from ctypes import POINTER, byref
POINTER, byref
""",
autoflake.fix_code("""\
def z():
from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
POINTER, byref
"""))
self.assertEqual(
"""\
def z():
pass
""",
autoflake.fix_code("""\
def z():
from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
"""))
def test_fix_code_with_empty_string(self):
self.assertEqual(
'',
autoflake.fix_code(''))
def test_fix_code_with_from_and_as_and_escaped_newline(self):
"""Make sure stuff after escaped newline is not lost."""
result = autoflake.fix_code("""\
from collections import defaultdict, namedtuple \\
as xyz
xyz
""")
# We currently leave lines with escaped newlines as is. But in the
# future this we may parse them and remove unused import accordingly.
# For now, we'll work around it here.
result = re.sub(r' *\\\n *as ', ' as ', result)
self.assertEqual(
"""\
from collections import namedtuple as xyz
xyz
""",
autoflake.fix_code(result))
def test_fix_code_with_unused_variables(self):
self.assertEqual(
"""\
def main():
y = 11
print(y)
""",
autoflake.fix_code("""\
def main():
x = 10
y = 11
print(y)
""",
remove_unused_variables=True))
def test_fix_code_with_unused_variables_should_skip_nonlocal(self):
"""pyflakes does not handle nonlocal correctly."""
code = """\
def bar():
x = 1
def foo():
nonlocal x
x = 2
"""
self.assertEqual(
code,
autoflake.fix_code(code,
remove_unused_variables=True))
def test_detect_encoding_with_bad_encoding(self):
with temporary_file('# -*- coding: blah -*-\n') as filename:
self.assertEqual('latin-1',
autoflake.detect_encoding(filename))
def test_fix_code_with_comma_on_right(self):
"""pyflakes does not handle nonlocal correctly."""
self.assertEqual(
"""\
def main():
pass
""",
autoflake.fix_code("""\
def main():
x = (1, 2, 3)
""",
remove_unused_variables=True))
def test_fix_code_with_unused_variables_should_skip_multiple(self):
code = """\
def main():
(x, y, z) = (1, 2, 3)
print(z)
"""
self.assertEqual(
code,
autoflake.fix_code(code,
remove_unused_variables=True))
def test_fix_code_should_handle_pyflakes_recursion_error_gracefully(self):
code = 'x = [{}]'.format('+'.join(['abc' for _ in range(2000)]))
self.assertEqual(
code,
autoflake.fix_code(code))
def test_fix_code_with_duplicate_key(self):
self.assertEqual(
"""\
a = {
(0,1): 3,
}
print(a)
""",
''.join(autoflake.fix_code("""\
a = {
(0,1): 1,
(0, 1): 'two',
(0,1): 3,
}
print(a)
""", remove_duplicate_keys=True)))
def test_fix_code_with_duplicate_key_longer(self):
self.assertEqual(
"""\
{
'a': 0,
'c': 2,
'd': 3,
'e': 4,
'f': 5,
'b': 6,
}
""",
''.join(autoflake.fix_code("""\
{
'a': 0,
'b': 1,
'c': 2,
'd': 3,
'e': 4,
'f': 5,
'b': 6,
}
""", remove_duplicate_keys=True)))
def test_fix_code_with_duplicate_key_with_many_braces(self):
self.assertEqual(
"""\
a = None
{None: {None: None},
}
{
None: a.b,
}
""",
''.join(autoflake.fix_code("""\
a = None
{None: {None: None},
}
{
None: a.a,
None: a.b,
}
""", remove_duplicate_keys=True)))
def test_fix_code_should_ignore_complex_case_of_duplicate_key(self):
"""We only handle simple cases."""
code = """\
a = {(0,1): 1, (0, 1): 'two',
(0,1): 3,
}
print(a)
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_fix_code_should_ignore_complex_case_of_duplicate_key_comma(self):
"""We only handle simple cases."""
code = """\
{
1: {0,
},
1: {2,
},
}
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_fix_code_should_ignore_complex_case_of_duplicate_key_partially(
self):
"""We only handle simple cases."""
code = """\
a = {(0,1): 1, (0, 1): 'two',
(0,1): 3,
(2,3): 4,
(2,3): 4,
(2,3): 5,
}
print(a)
"""
self.assertEqual(
"""\
a = {(0,1): 1, (0, 1): 'two',
(0,1): 3,
(2,3): 5,
}
print(a)
""",
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_fix_code_should_ignore_more_cases_of_duplicate_key(self):
"""We only handle simple cases."""
code = """\
a = {
(0,1):
1,
(0, 1): 'two',
(0,1): 3,
}
print(a)
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_fix_code_should_ignore_duplicate_key_with_comments(self):
"""We only handle simple cases."""
code = """\
a = {
(0,1) # : f
:
1,
(0, 1): 'two',
(0,1): 3,
}
print(a)
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
code = """\
{
1: {0,
},
1: #{2,
#},
0
}
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_fix_code_should_ignore_duplicate_key_with_multiline_key(self):
"""We only handle simple cases."""
code = """\
a = {
(0,1
): 1,
(0, 1): 'two',
(0,1): 3,
}
print(a)
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_fix_code_should_ignore_duplicate_key_with_no_comma(self):
"""We don't want to delete the line and leave a lone comma."""
code = """\
a = {
(0,1) : 1
,
(0, 1): 'two',
(0,1): 3,
}
print(a)
"""
self.assertEqual(
code,
''.join(autoflake.fix_code(code,
remove_duplicate_keys=True)))
def test_useless_pass_line_numbers(self):
self.assertEqual(
[1],
list(autoflake.useless_pass_line_numbers(
'pass\n')))
self.assertEqual(
[],
list(autoflake.useless_pass_line_numbers(
'if True:\n pass\n')))
def test_useless_pass_line_numbers_with_escaped_newline(self):
self.assertEqual(
[],
list(autoflake.useless_pass_line_numbers(
'if True:\\\n pass\n')))
def test_useless_pass_line_numbers_with_more_complex(self):
self.assertEqual(
[6],
list(autoflake.useless_pass_line_numbers(
"""\
if True:
pass
else:
True
x = 1
pass
""")))
def test_filter_useless_pass(self):
self.assertEqual(
"""\
if True:
pass
else:
True
x = 1
""",
''.join(autoflake.filter_useless_pass(
"""\
if True:
pass
else:
True
x = 1
pass
""")))
def test_filter_useless_pass_with_syntax_error(self):
source = """\
if True:
if True:
if True:
if True:
if True:
pass
else:
True
pass
pass
x = 1
"""
self.assertEqual(
source,
''.join(autoflake.filter_useless_pass(source)))
def test_filter_useless_pass_more_complex(self):
self.assertEqual(
"""\
if True:
pass
else:
def foo():
pass
# abc
def bar():
# abc
pass
def blah():
123
pass # Nope.
True
x = 1
""",
''.join(autoflake.filter_useless_pass(
"""\
if True:
pass
else:
def foo():
pass
# abc
def bar():
# abc
pass
def blah():
123
pass
pass # Nope.
pass
True
x = 1
pass
""")))
def test_filter_useless_pass_with_try(self):
self.assertEqual(
"""\
import os
os.foo()
try:
pass
except ImportError:
pass
""",
''.join(autoflake.filter_useless_pass(
"""\
import os
os.foo()
try:
pass
pass
except ImportError:
pass
""")))
def test_filter_useless_pass_leading_pass(self):
self.assertEqual(
"""\
if True:
pass
else:
True
x = 1
""",
''.join(autoflake.filter_useless_pass(
"""\
if True:
pass
pass
pass
pass
else:
pass
True
x = 1
pass
""")))
def test_filter_useless_pass_leading_pass_with_number(self):
self.assertEqual(
"""\
def func11():
0, 11 / 2
return 1
""",
''.join(autoflake.filter_useless_pass(
"""\
def func11():
pass
0, 11 / 2
return 1
""")))
def test_filter_useless_pass_leading_pass_with_string(self):
self.assertEqual(
"""\
def func11():
'hello'
return 1
""",
''.join(autoflake.filter_useless_pass(
"""\
def func11():
pass
'hello'
return 1
""")))
def test_check(self):
self.assertTrue(autoflake.check('import os'))
def test_check_with_bad_syntax(self):
self.assertFalse(autoflake.check('foo('))
def test_check_with_unicode(self):
self.assertFalse(autoflake.check('print("∑")'))
self.assertTrue(autoflake.check('import os # ∑'))
def test_get_diff_text(self):
# We ignore the first two lines since it differs on Python 2.6.
self.assertEqual(
"""\
-foo
+bar
""",
'\n'.join(autoflake.get_diff_text(['foo\n'],
['bar\n'],
'').split('\n')[3:]))
def test_get_diff_text_without_newline(self):
# We ignore the first two lines since it differs on Python 2.6.
self.assertEqual(
"""\
-foo
\\ No newline at end of file
+foo
""",
'\n'.join(autoflake.get_diff_text(['foo'],
['foo\n'],
'').split('\n')[3:]))
def test_is_literal_or_name(self):
self.assertTrue(autoflake.is_literal_or_name('123'))
self.assertTrue(autoflake.is_literal_or_name('[1, 2, 3]'))
self.assertTrue(autoflake.is_literal_or_name('xyz'))
self.assertFalse(autoflake.is_literal_or_name('xyz.prop'))
self.assertFalse(autoflake.is_literal_or_name(' '))
self.assertFalse(autoflake.is_literal_or_name(' 1'))
def test_is_python_file(self):
self.assertTrue(autoflake.is_python_file(
os.path.join(ROOT_DIRECTORY, 'autoflake.py')))
with temporary_file('#!/usr/bin/env python', suffix='') as filename:
self.assertTrue(autoflake.is_python_file(filename))
with temporary_file('#!/usr/bin/python', suffix='') as filename:
self.assertTrue(autoflake.is_python_file(filename))
with temporary_file('#!/usr/bin/python3', suffix='') as filename:
self.assertTrue(autoflake.is_python_file(filename))
with temporary_file('#!/usr/bin/pythonic', suffix='') as filename:
self.assertFalse(autoflake.is_python_file(filename))
with temporary_file('###!/usr/bin/python', suffix='') as filename:
self.assertFalse(autoflake.is_python_file(filename))
self.assertFalse(autoflake.is_python_file(os.devnull))
self.assertFalse(autoflake.is_python_file('/bin/bash'))
def test_match_file(self):
with temporary_file('', suffix='.py', prefix='.') as filename:
self.assertFalse(autoflake.match_file(filename, exclude=[]),
msg=filename)
self.assertFalse(autoflake.match_file(os.devnull, exclude=[]))
with temporary_file('', suffix='.py', prefix='') as filename:
self.assertTrue(autoflake.match_file(filename, exclude=[]),
msg=filename)
def test_find_files(self):
temp_directory = tempfile.mkdtemp()
try:
target = os.path.join(temp_directory, 'dir')
os.mkdir(target)
with open(os.path.join(target, 'a.py'), 'w'):
pass
exclude = os.path.join(target, 'ex')
os.mkdir(exclude)
with open(os.path.join(exclude, 'b.py'), 'w'):
pass
sub = os.path.join(exclude, 'sub')
os.mkdir(sub)
with open(os.path.join(sub, 'c.py'), 'w'):
pass
# FIXME: Avoid changing directory. This may interfere with parallel
# test runs.
cwd = os.getcwd()
os.chdir(temp_directory)
try:
files = list(autoflake.find_files(
['dir'], True, [os.path.join('dir', 'ex')]))
finally:
os.chdir(cwd)
file_names = [os.path.basename(f) for f in files]
self.assertIn('a.py', file_names)
self.assertNotIn('b.py', file_names)
self.assertNotIn('c.py', file_names)
finally:
shutil.rmtree(temp_directory)
def test_exclude(self):
temp_directory = tempfile.mkdtemp(dir='.')
try:
with open(os.path.join(temp_directory, 'a.py'), 'w') as output:
output.write('import re\n')
os.mkdir(os.path.join(temp_directory, 'd'))
with open(os.path.join(temp_directory, 'd', 'b.py'),
'w') as output:
output.write('import os\n')
p = subprocess.Popen(
list(AUTOFLAKE_COMMAND) +
[temp_directory, '--recursive', '--exclude=a*'],
stdout=subprocess.PIPE)
result = p.communicate()[0].decode('utf-8')
self.assertNotIn('import re', result)
self.assertIn('import os', result)
finally:
shutil.rmtree(temp_directory)
class SystemTests(unittest.TestCase):
"""System tests."""
def test_diff(self):
with temporary_file("""\
import re
import os
import my_own_module
x = 1
""") as filename:
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program', filename],
standard_out=output_file,
standard_error=None)
self.assertEqual("""\
-import re
-import os
import my_own_module
x = 1
""", '\n'.join(output_file.getvalue().split('\n')[3:]))
def test_diff_with_nonexistent_file(self):
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program', 'nonexistent_file'],
standard_out=output_file,
standard_error=output_file)
self.assertIn('no such file', output_file.getvalue().lower())
def test_diff_with_encoding_declaration(self):
with temporary_file("""\
# coding: iso-8859-1
import re
import os
import my_own_module
x = 1
""") as filename:
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program', filename],
standard_out=output_file,
standard_error=None)
self.assertEqual("""\
# coding: iso-8859-1
-import re
-import os
import my_own_module
x = 1
""", '\n'.join(output_file.getvalue().split('\n')[3:]))
def test_in_place(self):
with temporary_file("""\
import foo
x = foo
import subprocess
x()
try:
import os
except ImportError:
import os
""") as filename:
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program', '--in-place', filename],
standard_out=output_file,
standard_error=None)
with open(filename) as f:
self.assertEqual("""\
import foo
x = foo
x()
try:
pass
except ImportError:
pass
""", f.read())
def test_in_place_with_empty_file(self):
line = ''
with temporary_file(line) as filename:
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program', '--in-place', filename],
standard_out=output_file,
standard_error=None)
with open(filename) as f:
self.assertEqual(line, f.read())
def test_in_place_with_with_useless_pass(self):
with temporary_file("""\
import foo
x = foo
import subprocess
x()
try:
pass
import os
except ImportError:
pass
import os
import sys
""") as filename:
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program', '--in-place', filename],
standard_out=output_file,
standard_error=None)
with open(filename) as f:
self.assertEqual("""\
import foo
x = foo
x()
try:
pass
except ImportError:
pass
""", f.read())
def test_with_missing_file(self):
output_file = io.StringIO()
ignore = StubFile()
autoflake._main(argv=['my_fake_program', '--in-place', '.fake'],
standard_out=output_file,
standard_error=ignore)
self.assertFalse(output_file.getvalue())
def test_ignore_hidden_directories(self):
with temporary_directory() as directory:
with temporary_directory(prefix='.',
directory=directory) as inner_directory:
with temporary_file("""\
import re
import os
""", directory=inner_directory):
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program',
'--recursive',
directory],
standard_out=output_file,
standard_error=None)
self.assertEqual(
'',
output_file.getvalue().strip())
def test_redundant_options(self):
output_file = io.StringIO()
autoflake._main(argv=['my_fake_program',
'--remove-all', '--imports=blah', __file__],
standard_out=output_file,
standard_error=output_file)
self.assertIn('redundant', output_file.getvalue())
def test_end_to_end(self):
with temporary_file("""\
import fake_fake, fake_foo, fake_bar, fake_zoo
import re, os
x = os.sep
print(x)
""") as filename:
process = subprocess.Popen(AUTOFLAKE_COMMAND +
['--imports=fake_foo,fake_bar',
filename],
stdout=subprocess.PIPE)
self.assertEqual("""\
-import fake_fake, fake_foo, fake_bar, fake_zoo
-import re, os
+import fake_fake
+import fake_zoo
+import os
x = os.sep
print(x)
""", '\n'.join(process.communicate()[0].decode().split('\n')[3:]))
def test_end_to_end_with_remove_all_unused_imports(self):
with temporary_file("""\
import fake_fake, fake_foo, fake_bar, fake_zoo
import re, os
x = os.sep
print(x)
""") as filename:
process = subprocess.Popen(AUTOFLAKE_COMMAND +
['--remove-all',
filename],
stdout=subprocess.PIPE)
self.assertEqual("""\
-import fake_fake, fake_foo, fake_bar, fake_zoo
-import re, os
+import os
x = os.sep
print(x)
""", '\n'.join(process.communicate()[0].decode().split('\n')[3:]))
def test_end_to_end_with_remove_duplicate_keys_multiple_lines(self):
with temporary_file("""\
a = {
'b': 456,
'a': 123,
'b': 7834,
'a': 'wow',
'b': 456,
'c': 'hello',
'c': 'hello2',
'b': 'hiya',
}
print(a)
""") as filename:
process = subprocess.Popen(AUTOFLAKE_COMMAND +
['--remove-duplicate-keys',
filename],
stdout=subprocess.PIPE)
self.assertEqual("""\
a = {
- 'b': 456,
- 'a': 123,
- 'b': 7834,
'a': 'wow',
- 'b': 456,
- 'c': 'hello',
'c': 'hello2',
'b': 'hiya',
}
""", '\n'.join(process.communicate()[0].decode().split('\n')[3:]))
def test_end_to_end_with_remove_duplicate_keys_and_other_errors(self):
with temporary_file("""\
from math import *
print(sin(4))
a = { # Hello
'b': 456,
'a': 123,
'b': 7834,
'a': 'wow',
'b': 456,
'c': 'hello',
'c': 'hello2',
'b': 'hiya',
}
print(a)
""") as filename:
process = subprocess.Popen(AUTOFLAKE_COMMAND +
['--remove-duplicate-keys',
filename],
stdout=subprocess.PIPE)
self.assertEqual("""\
from math import *
print(sin(4))
a = { # Hello
- 'b': 456,
- 'a': 123,
- 'b': 7834,
'a': 'wow',
- 'b': 456,
- 'c': 'hello',
'c': 'hello2',
'b': 'hiya',
}
""", '\n'.join(process.communicate()[0].decode().split('\n')[3:]))
def test_end_to_end_with_remove_duplicate_keys_tuple(self):
with temporary_file("""\
a = {
(0,1): 1,
(0, 1): 'two',
(0,1): 3,
}
print(a)
""") as filename:
process = subprocess.Popen(AUTOFLAKE_COMMAND +
['--remove-duplicate-keys',
filename],
stdout=subprocess.PIPE)
self.assertEqual("""\
a = {
- (0,1): 1,
- (0, 1): 'two',
(0,1): 3,
}
print(a)
""", '\n'.join(process.communicate()[0].decode().split('\n')[3:]))
def test_end_to_end_with_error(self):
with temporary_file("""\
import fake_fake, fake_foo, fake_bar, fake_zoo
import re, os
x = os.sep
print(x)
""") as filename:
process = subprocess.Popen(AUTOFLAKE_COMMAND +
['--imports=fake_foo,fake_bar',
'--remove-all',
filename],
stderr=subprocess.PIPE)
self.assertIn(
'redundant',
process.communicate()[1].decode())
@contextlib.contextmanager
def temporary_file(contents, directory='.', suffix='.py', prefix=''):
"""Write contents to temporary file and yield it."""
f = tempfile.NamedTemporaryFile(suffix=suffix, prefix=prefix,
delete=False, dir=directory)
try:
f.write(contents.encode())
f.close()
yield f.name
finally:
os.remove(f.name)
@contextlib.contextmanager
def temporary_directory(directory='.', prefix='tmp.'):
"""Create temporary directory and yield its path."""
temp_directory = tempfile.mkdtemp(prefix=prefix, dir=directory)
try:
yield temp_directory
finally:
shutil.rmtree(temp_directory)
class StubFile(object):
"""Fake file that ignores everything."""
def write(*_):
"""Ignore."""
if __name__ == '__main__':
unittest.main()