| #!/usr/bin/env python |
| """Test suite for autoflake.""" |
| import contextlib |
| import functools |
| 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__)) |
| |
| |
| AUTOFLAKE_COMMAND = [ |
| sys.executable, |
| os.path.join( |
| ROOT_DIRECTORY, |
| "autoflake.py", |
| ), |
| ] |
| |
| |
| 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_unused_variable_drop_rhs(self): |
| self.assertEqual( |
| "", |
| autoflake.filter_unused_variable( |
| "x = foo()", |
| drop_rhs=True, |
| ), |
| ) |
| |
| self.assertEqual( |
| "", |
| autoflake.filter_unused_variable( |
| " x = foo()", |
| drop_rhs=True, |
| ), |
| ) |
| |
| def test_filter_unused_variable_with_literal_or_name_drop_rhs(self): |
| self.assertEqual( |
| "pass", |
| autoflake.filter_unused_variable("x = 1", drop_rhs=True), |
| ) |
| |
| self.assertEqual( |
| "pass", |
| autoflake.filter_unused_variable("x = y", drop_rhs=True), |
| ) |
| |
| self.assertEqual( |
| "pass", |
| autoflake.filter_unused_variable("x = {}", drop_rhs=True), |
| ) |
| |
| def test_filter_unused_variable_with_basic_data_structures_drop_rhs(self): |
| self.assertEqual( |
| "pass", |
| autoflake.filter_unused_variable("x = dict()", drop_rhs=True), |
| ) |
| |
| self.assertEqual( |
| "pass", |
| autoflake.filter_unused_variable("x = list()", drop_rhs=True), |
| ) |
| |
| self.assertEqual( |
| "pass", |
| autoflake.filter_unused_variable("x = set()", drop_rhs=True), |
| ) |
| |
| def test_filter_unused_variable_should_ignore_multiline_drop_rhs(self): |
| self.assertEqual( |
| "x = foo()\\", |
| autoflake.filter_unused_variable("x = foo()\\", drop_rhs=True), |
| ) |
| |
| def test_filter_unused_variable_should_multiple_assignments_drop_rhs(self): |
| self.assertEqual( |
| "x = y = foo()", |
| autoflake.filter_unused_variable("x = y = foo()", drop_rhs=True), |
| ) |
| |
| def test_filter_unused_variable_with_exception_drop_rhs(self): |
| self.assertEqual( |
| "except Exception:", |
| autoflake.filter_unused_variable( |
| "except Exception as exception:", |
| drop_rhs=True, |
| ), |
| ) |
| |
| self.assertEqual( |
| "except (ImportError, ValueError):", |
| autoflake.filter_unused_variable( |
| "except (ImportError, ValueError) as foo:", |
| drop_rhs=True, |
| ), |
| ) |
| |
| 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 subprocess\nimport math\n", |
| autoflake.break_up_import("import abc, subprocess, math\n"), |
| ) |
| |
| def test_break_up_import_with_indentation(self): |
| self.assertEqual( |
| " import abc\n import subprocess\n import math\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, subprocess, math\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 subprocess, math\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_multiline_imports(self): |
| self.assertEqual( |
| r"""\ |
| import os |
| pass |
| import os |
| os.foo() |
| """, |
| "".join( |
| autoflake.filter_code( |
| r"""\ |
| import os |
| import re |
| import os, \ |
| math, subprocess |
| os.foo() |
| """, |
| ), |
| ), |
| ) |
| |
| def test_filter_code_multiline_from_imports(self): |
| self.assertEqual( |
| r"""\ |
| import os |
| pass |
| from os.path import ( |
| join, |
| ) |
| join('a', 'b') |
| pass |
| os.foo() |
| from os.path import \ |
| isdir |
| isdir('42') |
| """, |
| "".join( |
| autoflake.filter_code( |
| r"""\ |
| import os |
| import re |
| from os.path import ( |
| exists, |
| join, |
| ) |
| join('a', 'b') |
| from os.path import \ |
| abspath, basename, \ |
| commonpath |
| os.foo() |
| from os.path import \ |
| isfile \ |
| , isdir |
| isdir('42') |
| """, |
| ), |
| ), |
| ) |
| |
| 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_with_ignore_init_module_imports_flag(self): |
| # Need a temp directory in order to specify file name as __init__.py |
| temp_directory = tempfile.mkdtemp(dir=".") |
| temp_file = os.path.join(temp_directory, "__init__.py") |
| try: |
| with open(temp_file, "w") as output: |
| output.write("import re\n") |
| |
| p = subprocess.Popen( |
| list(AUTOFLAKE_COMMAND) + ["--ignore-init-module-imports", temp_file], |
| stdout=subprocess.PIPE, |
| ) |
| result = p.communicate()[0].decode("utf-8") |
| |
| self.assertNotIn("import re", result) |
| finally: |
| shutil.rmtree(temp_directory) |
| |
| def test_without_ignore_init_module_imports_flag(self): |
| # Need a temp directory in order to specify file name as __init__.py |
| temp_directory = tempfile.mkdtemp(dir=".") |
| temp_file = os.path.join(temp_directory, "__init__.py") |
| try: |
| with open(temp_file, "w") as output: |
| output.write("import re\n") |
| |
| p = subprocess.Popen( |
| list(AUTOFLAKE_COMMAND) + [temp_file], |
| stdout=subprocess.PIPE, |
| ) |
| result = p.communicate()[0].decode("utf-8") |
| |
| self.assertIn("import re", result) |
| finally: |
| shutil.rmtree(temp_directory) |
| |
| 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_drop_rhs(self): |
| self.assertEqual( |
| """\ |
| def main(): |
| y = 11 |
| print(y) |
| """, |
| autoflake.fix_code( |
| """\ |
| def main(): |
| x = 10 |
| y = 11 |
| print(y) |
| """, |
| remove_unused_variables=True, |
| remove_rhs_for_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_fix_code_with_unused_variables_should_skip_nonlocal_drop_rhs( |
| 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, |
| remove_rhs_for_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_comma_on_right_drop_rhs(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, |
| remove_rhs_for_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_with_unused_variables_should_skip_multiple_drop_rhs( |
| self, |
| ): |
| code = """\ |
| def main(): |
| (x, y, z) = (1, 2, 3) |
| print(z) |
| """ |
| self.assertEqual( |
| code, |
| autoflake.fix_code( |
| code, |
| remove_unused_variables=True, |
| remove_rhs_for_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_fix_code_keeps_pass_statements(self): |
| code = """\ |
| if True: |
| pass |
| else: |
| def foo(): |
| \"\"\" A docstring. \"\"\" |
| pass |
| def foo2(): |
| \"\"\" A docstring. \"\"\" |
| |
| pass |
| def foo3(): |
| \"\"\" A docstring. \"\"\" |
| |
| |
| pass |
| def bar(): |
| # abc |
| pass |
| def blah(): |
| 123 |
| pass |
| pass # Nope. |
| pass |
| """ |
| |
| self.assertEqual( |
| code, |
| "".join( |
| autoflake.fix_code( |
| code, |
| ignore_pass_statements=True, |
| ), |
| ), |
| ) |
| |
| def test_fix_code_keeps_passes_after_docstrings(self): |
| actual = autoflake.fix_code( |
| """\ |
| if True: |
| pass |
| else: |
| def foo(): |
| \"\"\" A docstring. \"\"\" |
| pass |
| def foo2(): |
| \"\"\" A docstring. \"\"\" |
| |
| pass |
| def foo3(): |
| \"\"\" A docstring. \"\"\" |
| |
| |
| pass |
| def bar(): |
| # abc |
| pass |
| def blah(): |
| 123 |
| pass |
| pass # Nope. |
| pass |
| """, |
| ignore_pass_after_docstring=True, |
| ) |
| |
| expected = """\ |
| if True: |
| pass |
| else: |
| def foo(): |
| \"\"\" A docstring. \"\"\" |
| pass |
| def foo2(): |
| \"\"\" A docstring. \"\"\" |
| |
| pass |
| def foo3(): |
| \"\"\" A docstring. \"\"\" |
| |
| |
| pass |
| def bar(): |
| # abc |
| pass |
| def blah(): |
| 123 |
| pass # Nope. |
| """ |
| |
| self.assertEqual(actual, expected) |
| |
| 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_useless_pass_line_numbers_after_docstring(self): |
| actual_pass_line_numbers = list( |
| autoflake.useless_pass_line_numbers( |
| """\ |
| @abc.abstractmethod |
| def some_abstract_method(): |
| \"\"\"Some docstring.\"\"\" |
| pass |
| """, |
| ), |
| ) |
| |
| expected_pass_line_numbers = [4] |
| self.assertEqual(expected_pass_line_numbers, actual_pass_line_numbers) |
| |
| def test_useless_pass_line_numbers_keep_pass_after_docstring(self): |
| actual_pass_line_numbers = list( |
| autoflake.useless_pass_line_numbers( |
| """\ |
| @abc.abstractmethod |
| def some_abstract_method(): |
| \"\"\"Some docstring.\"\"\" |
| pass |
| """, |
| ignore_pass_after_docstring=True, |
| ), |
| ) |
| |
| expected_pass_line_numbers = [] |
| self.assertEqual(expected_pass_line_numbers, actual_pass_line_numbers) |
| |
| 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_keep_pass_after_docstring(self): |
| source = """\ |
| def foo(): |
| \"\"\" This is not a useless 'pass'. \"\"\" |
| pass |
| |
| @abc.abstractmethod |
| def bar(): |
| \"\"\" |
| Also this is not a useless 'pass'. |
| \"\"\" |
| pass |
| """ |
| self.assertEqual( |
| source, |
| "".join( |
| autoflake.filter_useless_pass( |
| source, |
| ignore_pass_after_docstring=True, |
| ), |
| ), |
| ) |
| |
| def test_filter_useless_pass_keeps_pass_statements(self): |
| source = """\ |
| if True: |
| pass |
| pass |
| pass |
| pass |
| else: |
| pass |
| True |
| x = 1 |
| pass |
| """ |
| |
| self.assertEqual( |
| source, |
| "".join( |
| autoflake.filter_useless_pass( |
| source, |
| ignore_pass_statements=True, |
| ), |
| ), |
| ) |
| |
| def test_filter_useless_paspasss_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(" ")) |
| |
| 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_is_exclude_file(self): |
| self.assertTrue( |
| autoflake.is_exclude_file( |
| "1.py", |
| ["test*", "1*"], |
| ), |
| ) |
| |
| self.assertFalse( |
| autoflake.is_exclude_file( |
| "2.py", |
| ["test*", "1*"], |
| ), |
| ) |
| |
| # folder glob |
| self.assertTrue( |
| autoflake.is_exclude_file( |
| "test/test.py", |
| ["test/**.py"], |
| ), |
| ) |
| |
| self.assertTrue( |
| autoflake.is_exclude_file( |
| "test/auto_test.py", |
| ["test/*_test.py"], |
| ), |
| ) |
| |
| self.assertFalse( |
| autoflake.is_exclude_file( |
| "test/auto_auto.py", |
| ["test/*_test.py"], |
| ), |
| ) |
| |
| 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_check_with_empty_file(self): |
| line = "" |
| |
| with temporary_file(line) as filename: |
| output_file = io.StringIO() |
| autoflake._main( |
| argv=["my_fake_program", "--check", filename], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual( |
| f"{filename}: No issues detected!{os.linesep}", |
| output_file.getvalue(), |
| ) |
| |
| def test_check_correct_file(self): |
| with temporary_file( |
| """\ |
| import foo |
| x = foo.bar |
| print(x) |
| """, |
| ) as filename: |
| output_file = io.StringIO() |
| autoflake._main( |
| argv=["my_fake_program", "--check", filename], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual( |
| f"{filename}: No issues detected!{os.linesep}", |
| output_file.getvalue(), |
| ) |
| |
| def test_check_correct_file_with_quiet(self): |
| with temporary_file( |
| """\ |
| import foo |
| x = foo.bar |
| print(x) |
| """, |
| ) as filename: |
| output_file = io.StringIO() |
| autoflake._main( |
| argv=[ |
| "my_fake_program", |
| "--check", |
| "--quiet", |
| filename, |
| ], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual("", output_file.getvalue()) |
| |
| def test_check_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() |
| exit_status = autoflake._main( |
| argv=["my_fake_program", "--check", filename], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual(exit_status, 1) |
| self.assertEqual( |
| f"{filename}: Unused imports/variables detected{os.linesep}", |
| output_file.getvalue(), |
| ) |
| |
| def test_check_with_multiple_files(self): |
| with temporary_file("import sys") as file1: |
| with temporary_file("import sys") as file2: |
| output_file = io.StringIO() |
| exit_status = autoflake._main( |
| argv=["my_fake_program", "--check", file1, file2], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual(exit_status, 1) |
| self.assertEqual( |
| { |
| f"{file1}: Unused imports/variables detected", |
| f"{file2}: Unused imports/variables detected", |
| }, |
| set(output_file.getvalue().strip().split(os.linesep)), |
| ) |
| |
| def test_check_diff_with_empty_file(self): |
| line = "" |
| |
| with temporary_file(line) as filename: |
| output_file = io.StringIO() |
| autoflake._main( |
| argv=["my_fake_program", "--check-diff", filename], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual( |
| f"{filename}: No issues detected!{os.linesep}", |
| output_file.getvalue(), |
| ) |
| |
| def test_check_diff_correct_file(self): |
| with temporary_file( |
| """\ |
| import foo |
| x = foo.bar |
| print(x) |
| """, |
| ) as filename: |
| output_file = io.StringIO() |
| autoflake._main( |
| argv=["my_fake_program", "--check-diff", filename], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual( |
| f"{filename}: No issues detected!{os.linesep}", |
| output_file.getvalue(), |
| ) |
| |
| def test_check_diff_correct_file_with_quiet(self): |
| with temporary_file( |
| """\ |
| import foo |
| x = foo.bar |
| print(x) |
| """, |
| ) as filename: |
| output_file = io.StringIO() |
| autoflake._main( |
| argv=[ |
| "my_fake_program", |
| "--check-diff", |
| "--quiet", |
| filename, |
| ], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual("", output_file.getvalue()) |
| |
| def test_check_diff_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() |
| exit_status = autoflake._main( |
| argv=["my_fake_program", "--check-diff", filename], |
| standard_out=output_file, |
| standard_error=None, |
| ) |
| self.assertEqual(exit_status, 1) |
| self.assertEqual( |
| """\ |
| import foo |
| x = foo |
| -import subprocess |
| x() |
| try: |
| pass |
| - import os |
| except ImportError: |
| pass |
| - import os |
| - import sys |
| """, |
| "\n".join(output_file.getvalue().split("\n")[3:]), |
| ) |
| |
| 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_in_place_and_stdout(self): |
| output_file = io.StringIO() |
| self.assertRaises( |
| SystemExit, |
| autoflake._main, |
| argv=["my_fake_program", "--in-place", "--stdout", __file__], |
| standard_out=output_file, |
| standard_error=output_file, |
| ) |
| |
| 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(os.linesep)[3:]), |
| ) |
| |
| def test_end_to_end_multiple_files(self): |
| with temporary_file( |
| """\ |
| import fake_fake, fake_foo, fake_bar, fake_zoo |
| import re, os |
| x = os.sep |
| print(x) |
| """, |
| ) as filename1: |
| with temporary_file( |
| """\ |
| import os |
| x = os.sep |
| print(x) |
| """, |
| ) as filename2: |
| process = subprocess.Popen( |
| AUTOFLAKE_COMMAND |
| + [ |
| "--imports=fake_foo,fake_bar", |
| "--check", |
| "--jobs=2", |
| filename1, |
| filename2, |
| ], |
| stdout=subprocess.PIPE, |
| ) |
| |
| status_code = process.wait() |
| self.assertEqual(1, status_code) |
| |
| 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(os.linesep)[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(os.linesep)[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(os.linesep)[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(os.linesep)[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( |
| "not allowed with argument", |
| process.communicate()[1].decode(), |
| ) |
| |
| def test_end_to_end_from_stdin(self): |
| stdin_data = b"""\ |
| import fake_fake, fake_foo, fake_bar, fake_zoo |
| import re, os |
| x = os.sep |
| print(x) |
| """ |
| process = subprocess.Popen( |
| AUTOFLAKE_COMMAND + ["--remove-all", "-"], |
| stdout=subprocess.PIPE, |
| stdin=subprocess.PIPE, |
| ) |
| stdout, _ = process.communicate(stdin_data) |
| self.assertEqual( |
| """\ |
| import os |
| x = os.sep |
| print(x) |
| """, |
| "\n".join(stdout.decode().split(os.linesep)), |
| ) |
| |
| def test_end_to_end_from_stdin_with_in_place(self): |
| stdin_data = b"""\ |
| import fake_fake, fake_foo, fake_bar, fake_zoo |
| import re, os, sys |
| x = os.sep |
| print(x) |
| """ |
| process = subprocess.Popen( |
| AUTOFLAKE_COMMAND + ["--remove-all", "--in-place", "-"], |
| stdout=subprocess.PIPE, |
| stdin=subprocess.PIPE, |
| ) |
| stdout, _ = process.communicate(stdin_data) |
| self.assertEqual( |
| """\ |
| import os |
| x = os.sep |
| print(x) |
| """, |
| "\n".join(stdout.decode().split(os.linesep)), |
| ) |
| |
| def test_end_to_end_dont_remove_unused_imports_when_not_using_flag(self): |
| with temporary_file( |
| """\ |
| from . import fake_bar |
| from . import fake_foo |
| fake_foo.fake_function() |
| """, |
| ) as filename: |
| process = subprocess.Popen( |
| AUTOFLAKE_COMMAND |
| + [ |
| filename, |
| ], |
| stdout=subprocess.PIPE, |
| ) |
| self.assertEqual( |
| "", |
| "\n".join(process.communicate()[0].decode().split(os.linesep)[3:]), |
| ) |
| |
| |
| class MultilineFromImportTests(unittest.TestCase): |
| def test_is_over(self): |
| filt = autoflake.FilterMultilineImport("from . import (\n") |
| self.assertTrue(filt.is_over("module)\n")) |
| self.assertTrue(filt.is_over(" )\n")) |
| self.assertTrue(filt.is_over(" ) # comment\n")) |
| self.assertTrue(filt.is_over("from module import (a, b)\n")) |
| self.assertFalse(filt.is_over("# )")) |
| self.assertFalse(filt.is_over("module\n")) |
| self.assertFalse(filt.is_over("module, \\\n")) |
| self.assertFalse(filt.is_over("\n")) |
| |
| filt = autoflake.FilterMultilineImport("from . import module, \\\n") |
| self.assertTrue(filt.is_over("module\n")) |
| self.assertTrue(filt.is_over("\n")) |
| self.assertTrue(filt.is_over("m1, m2 # comment with \\\n")) |
| self.assertFalse(filt.is_over("m1, m2 \\\n")) |
| self.assertFalse(filt.is_over("m1, m2 \\ #\n")) |
| self.assertFalse(filt.is_over("m1, m2 \\ # comment with \\\n")) |
| self.assertFalse(filt.is_over("\\\n")) |
| |
| # "Multiline" imports that are not really multiline |
| filt = autoflake.FilterMultilineImport( |
| "import os; " "import math, subprocess", |
| ) |
| self.assertTrue(filt.is_over()) |
| |
| unused = () |
| |
| def assert_fix(self, lines, result, remove_all=True): |
| fixer = autoflake.FilterMultilineImport( |
| lines[0], |
| remove_all_unused_imports=remove_all, |
| unused_module=self.unused, |
| ) |
| fixed = functools.reduce(lambda acc, x: acc(x), lines[1:], fixer()) |
| self.assertEqual(fixed, result) |
| |
| def test_fix(self): |
| self.unused = ["third_party.lib" + str(x) for x in (1, 3, 4)] |
| |
| # Example m0 (isort) |
| self.assert_fix( |
| [ |
| "from third_party import (lib1, lib2, lib3,\n", |
| " lib4, lib5, lib6)\n", |
| ], |
| "from third_party import (lib2, lib5, lib6)\n", |
| ) |
| |
| # Example m1(isort) |
| self.assert_fix( |
| [ |
| "from third_party import (lib1,\n", |
| " lib2,\n", |
| " lib3,\n", |
| " lib4,\n", |
| " lib5,\n", |
| " lib6)\n", |
| ], |
| "from third_party import (lib2,\n" |
| " lib5,\n" |
| " lib6)\n", |
| ) |
| |
| # Variation m1(isort) |
| self.assert_fix( |
| [ |
| "from third_party import (lib1\n", |
| " ,lib2\n", |
| " ,lib3\n", |
| " ,lib4\n", |
| " ,lib5\n", |
| " ,lib6)\n", |
| ], |
| "from third_party import (lib2\n" |
| " ,lib5\n" |
| " ,lib6)\n", |
| ) |
| |
| # Example m2 (isort) |
| self.assert_fix( |
| [ |
| "from third_party import \\\n", |
| " lib1, lib2, lib3, \\\n", |
| " lib4, lib5, lib6\n", |
| ], |
| "from third_party import \\\n" " lib2, lib5, lib6\n", |
| ) |
| |
| # Example m3 (isort) |
| self.assert_fix( |
| [ |
| "from third_party import (\n", |
| " lib1,\n", |
| " lib2,\n", |
| " lib3,\n", |
| " lib4,\n", |
| " lib5\n", |
| ")\n", |
| ], |
| "from third_party import (\n" " lib2,\n" " lib5\n" ")\n", |
| ) |
| |
| # Example m4 (isort) |
| self.assert_fix( |
| [ |
| "from third_party import (\n", |
| " lib1, lib2, lib3, lib4,\n", |
| " lib5, lib6)\n", |
| ], |
| "from third_party import (\n" " lib2, lib5, lib6)\n", |
| ) |
| |
| # Example m5 (isort) |
| self.assert_fix( |
| [ |
| "from third_party import (\n", |
| " lib1, lib2, lib3, lib4,\n", |
| " lib5, lib6\n", |
| ")\n", |
| ], |
| "from third_party import (\n" " lib2, lib5, lib6\n" ")\n", |
| ) |
| |
| # Some Deviations |
| self.assert_fix( |
| [ |
| "from third_party import (\n", |
| " lib1\\\n", # only unused + line continuation |
| " ,lib2, \n", |
| " libA\n", # used import with no commas |
| " ,lib3, \n", # leading and trailing commas + unused import |
| " libB, \n", |
| " \\\n", # empty line with continuation |
| " lib4,\n", # unused import with comment |
| ")\n", |
| ], |
| "from third_party import (\n" |
| " lib2\\\n" |
| " ,libA, \n" |
| " libB,\n" |
| ")\n", |
| ) |
| |
| self.assert_fix( |
| [ |
| "from third_party import (\n", |
| " lib1\n", |
| ",\n", |
| " lib2\n", |
| ",\n", |
| " lib3\n", |
| ",\n", |
| " lib4\n", |
| ",\n", |
| " lib5\n", |
| ")\n", |
| ], |
| "from third_party import (\n" " lib2\n" ",\n" " lib5\n" ")\n", |
| ) |
| |
| self.assert_fix( |
| [ |
| "from third_party import (\n", |
| " lib1 \\\n", |
| ", \\\n", |
| " lib2 \\\n", |
| ",\\\n", |
| " lib3\n", |
| ",\n", |
| " lib4\n", |
| ",\n", |
| " lib5 \\\n", |
| ")\n", |
| ], |
| "from third_party import (\n" |
| " lib2 \\\n" |
| ", \\\n" |
| " lib5 \\\n" |
| ")\n", |
| ) |
| |
| def test_indentation(self): |
| # Some weird indentation examples |
| self.unused = ["third_party.lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| " from third_party import (\n", |
| " lib1, lib2, lib3, lib4,\n", |
| " lib5, lib6\n", |
| ")\n", |
| ], |
| " from third_party import (\n" " lib2, lib5, lib6\n" ")\n", |
| ) |
| self.assert_fix( |
| [ |
| "\tfrom third_party import \\\n", |
| "\t\tlib1, lib2, lib3, \\\n", |
| "\t\tlib4, lib5, lib6\n", |
| ], |
| "\tfrom third_party import \\\n" "\t\tlib2, lib5, lib6\n", |
| ) |
| |
| def test_fix_relative(self): |
| # Example m0 (isort) |
| self.unused = [".lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "from . import (lib1, lib2, lib3,\n", |
| " lib4, lib5, lib6)\n", |
| ], |
| "from . import (lib2, lib5, lib6)\n", |
| ) |
| |
| # Example m1(isort) |
| self.unused = ["..lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "from .. import (lib1,\n", |
| " lib2,\n", |
| " lib3,\n", |
| " lib4,\n", |
| " lib5,\n", |
| " lib6)\n", |
| ], |
| "from .. import (lib2,\n" |
| " lib5,\n" |
| " lib6)\n", |
| ) |
| |
| # Example m2 (isort) |
| self.unused = ["...lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "from ... import \\\n", |
| " lib1, lib2, lib3, \\\n", |
| " lib4, lib5, lib6\n", |
| ], |
| "from ... import \\\n" " lib2, lib5, lib6\n", |
| ) |
| |
| # Example m3 (isort) |
| self.unused = [".parent.lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "from .parent import (\n", |
| " lib1,\n", |
| " lib2,\n", |
| " lib3,\n", |
| " lib4,\n", |
| " lib5\n", |
| ")\n", |
| ], |
| "from .parent import (\n" " lib2,\n" " lib5\n" ")\n", |
| ) |
| |
| def test_fix_without_from(self): |
| self.unused = ["lib" + str(x) for x in (1, 3, 4)] |
| |
| # Multiline but not "from" |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1, lib2, lib3 \\\n", |
| " ,lib4, lib5, lib6\n", |
| ], |
| "import \\\n" " lib2, lib5, lib6\n", |
| ) |
| self.assert_fix( |
| [ |
| "import lib1, lib2, lib3, \\\n", |
| " lib4, lib5, lib6\n", |
| ], |
| "import lib2, lib5, lib6\n", |
| ) |
| |
| # Problematic example without "from" |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1,\\\n", |
| " lib2, \\\n", |
| " libA\\\n", # used import with no commas |
| " ,lib3, \\\n", # leading and trailing commas with unused |
| " libB, \\\n", |
| " \\ \n", # empty line with continuation |
| " lib4\\\n", # unused import with comment |
| "\n", |
| ], |
| "import \\\n" " lib2,\\\n" " libA, \\\n" " libB\\\n" "\n", |
| ) |
| |
| self.unused = [f"lib{x}.x.y.z" for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1.x.y.z \\", |
| " , \\\n", |
| " lib2.x.y.z \\\n", |
| " , \\\n", |
| " lib3.x.y.z \\\n", |
| " , \\\n", |
| " lib4.x.y.z \\\n", |
| " , \\\n", |
| " lib5.x.y.z\n", |
| ], |
| "import \\\n" " lib2.x.y.z \\" " , \\\n" " lib5.x.y.z\n", |
| ) |
| |
| def test_give_up(self): |
| # Semicolon |
| self.unused = ["lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1, lib2, lib3, \\\n", |
| " lib4, lib5; import lib6\n", |
| ], |
| "import \\\n" " lib1, lib2, lib3, \\\n" " lib4, lib5; import lib6\n", |
| ) |
| # Comments |
| self.unused = [".lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "from . import ( # comment\n", |
| " lib1,\\\n", # only unused + line continuation |
| " lib2, \n", |
| " libA\n", # used import with no commas |
| " ,lib3, \n", # leading and trailing commas + unused import |
| " libB, \n", |
| " \\ \n", # empty line with continuation |
| " lib4, # noqa \n", # unused import with comment |
| ") ; import sys\n", |
| ], |
| "from . import ( # comment\n" |
| " lib1,\\\n" |
| " lib2, \n" |
| " libA\n" |
| " ,lib3, \n" |
| " libB, \n" |
| " \\ \n" |
| " lib4, # noqa \n" |
| ") ; import sys\n", |
| ) |
| |
| def test_just_one_import_used(self): |
| self.unused = ["lib2"] |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1\n", |
| ], |
| "import \\\n" " lib1\n", |
| ) |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib2\n", |
| ], |
| "pass\n", |
| ) |
| # Example from issue #8 |
| self.unused = ["re.subn"] |
| self.assert_fix( |
| [ |
| "\tfrom re import (subn)\n", |
| ], |
| "\tpass\n", |
| ) |
| |
| def test_just_one_import_left(self): |
| # Examples from issue #8 |
| self.unused = ["math.sqrt"] |
| self.assert_fix( |
| [ |
| "from math import (\n", |
| " sqrt,\n", |
| " log\n", |
| " )\n", |
| ], |
| "from math import (\n" " log\n" " )\n", |
| ) |
| self.unused = ["module.b"] |
| self.assert_fix( |
| [ |
| "from module import (a, b)\n", |
| ], |
| "from module import a\n", |
| ) |
| self.assert_fix( |
| [ |
| "from module import (a,\n", |
| " b)\n", |
| ], |
| "from module import a\n", |
| ) |
| self.unused = [] |
| self.assert_fix( |
| [ |
| "from re import (subn)\n", |
| ], |
| "from re import (subn)\n", |
| ) |
| |
| def test_no_empty_imports(self): |
| self.unused = ["lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1, lib3, \\\n", |
| " lib4 \n", |
| ], |
| "pass \n", |
| ) |
| |
| # Indented parenthesized block |
| self.unused = [".parent.lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "\t\tfrom .parent import (\n", |
| " lib1,\n", |
| " lib3,\n", |
| " lib4,\n", |
| ")\n", |
| ], |
| "\t\tpass\n", |
| ) |
| |
| def test_without_remove_all(self): |
| self.unused = ["lib" + str(x) for x in (1, 3, 4)] |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " lib1,\\\n", |
| " lib3,\\\n", |
| " lib4\n", |
| ], |
| "import \\\n" " lib1,\\\n" " lib3,\\\n" " lib4\n", |
| remove_all=False, |
| ) |
| |
| self.unused += ["os.path." + x for x in ("dirname", "isdir", "join")] |
| self.assert_fix( |
| [ |
| "from os.path import (\n", |
| " dirname,\n", |
| " isdir,\n", |
| " join,\n", |
| ")\n", |
| ], |
| "pass\n", |
| remove_all=False, |
| ) |
| self.assert_fix( |
| [ |
| "import \\\n", |
| " os.path.dirname, \\\n", |
| " lib1, \\\n", |
| " lib3\n", |
| ], |
| "import \\\n" " lib1, \\\n" " lib3\n", |
| remove_all=False, |
| ) |
| |
| |
| class ConfigFileTest(unittest.TestCase): |
| def setUp(self): |
| self.tmpdir = tempfile.mkdtemp(prefix="autoflake.") |
| |
| def tearDown(self): |
| if self.tmpdir is not None: |
| shutil.rmtree(self.tmpdir) |
| self.tmpdir = None |
| |
| def effective_path(self, path, is_file=True): |
| path = os.path.normpath(path) |
| if os.path.isabs(path): |
| raise ValueError("Should not create an absolute test path") |
| effective_path = os.path.sep.join([self.tmpdir, path]) |
| if not effective_path.startswith( |
| f"{self.tmpdir}{os.path.sep}", |
| ) and (effective_path != self.tmpdir or is_file): |
| raise ValueError("Should create a path within the tmp dir only") |
| return effective_path |
| |
| def create_dir(self, path): |
| effective_path = self.effective_path(path, False) |
| if sys.version_info >= (3, 2, 0): |
| os.makedirs(effective_path, exist_ok=True) |
| else: |
| if os.path.exists(effective_path): |
| return |
| try: |
| os.mkdir(effective_path) |
| except OSError: |
| parent = os.path.split(path)[0] |
| if not parent: |
| raise |
| self.create_dir(parent) |
| os.mkdir(effective_path) |
| |
| def create_file(self, path, contents=""): |
| effective_path = self.effective_path(path) |
| self.create_dir(os.path.split(path)[0]) |
| with open(effective_path, "w") as f: |
| f.write(contents) |
| |
| def with_defaults(self, **kwargs): |
| return { |
| "check": False, |
| "check_diff": False, |
| "expand_star_imports": False, |
| "ignore_init_module_imports": False, |
| "ignore_pass_after_docstring": False, |
| "ignore_pass_statements": False, |
| "in_place": False, |
| "quiet": False, |
| "recursive": False, |
| "remove_all_unused_imports": False, |
| "remove_duplicate_keys": False, |
| "remove_rhs_for_unused_variables": False, |
| "remove_unused_variables": False, |
| "write_to_stdout": False, |
| **kwargs, |
| } |
| |
| def test_no_config_file(self): |
| self.create_file("test_me.py") |
| original_args = { |
| "files": [self.effective_path("test_me.py")], |
| } |
| args, success = autoflake.merge_configuration_file(original_args) |
| assert success is True |
| assert args == self.with_defaults(**original_args) |
| |
| def test_non_nested_pyproject_toml_empty(self): |
| self.create_file("test_me.py") |
| self.create_file("pyproject.toml", '[tool.other]\nprop="value"\n') |
| files = [self.effective_path("test_me.py")] |
| original_args = {"files": files} |
| args, success = autoflake.merge_configuration_file(original_args) |
| assert success is True |
| assert args == self.with_defaults(**original_args) |
| |
| def test_non_nested_pyproject_toml_non_empty(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports=true\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| expand_star_imports=True, |
| ) |
| |
| def test_non_nested_setup_cfg_non_empty(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "setup.cfg", |
| "[other]\nexpand-star-imports = yes\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults(files=files) |
| |
| def test_non_nested_setup_cfg_empty(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "setup.cfg", |
| "[autoflake]\nexpand-star-imports = yes\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| expand_star_imports=True, |
| ) |
| |
| def test_nested_file(self): |
| self.create_file("nested/file/test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports=true\n", |
| ) |
| files = [self.effective_path("nested/file/test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| expand_star_imports=True, |
| ) |
| |
| def test_common_path_nested_file_do_not_load(self): |
| self.create_file("nested/file/test_me.py") |
| self.create_file("nested/other/test_me.py") |
| self.create_file( |
| "nested/file/pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports=true\n", |
| ) |
| files = [ |
| self.effective_path("nested/file/test_me.py"), |
| self.effective_path("nested/other/test_me.py"), |
| ] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults(files=files) |
| |
| def test_common_path_nested_file_do_load(self): |
| self.create_file("nested/file/test_me.py") |
| self.create_file("nested/other/test_me.py") |
| self.create_file( |
| "nested/pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports=true\n", |
| ) |
| files = [ |
| self.effective_path("nested/file/test_me.py"), |
| self.effective_path("nested/other/test_me.py"), |
| ] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| expand_star_imports=True, |
| ) |
| |
| def test_common_path_instead_of_common_prefix(self): |
| """Using common prefix would result in a failure.""" |
| self.create_file("nested/file-foo/test_me.py") |
| self.create_file("nested/file-bar/test_me.py") |
| self.create_file( |
| "nested/file/pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports=true\n", |
| ) |
| files = [ |
| self.effective_path("nested/file-foo/test_me.py"), |
| self.effective_path("nested/file-bar/test_me.py"), |
| ] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults(files=files) |
| |
| def test_continue_search_if_no_config_found(self): |
| self.create_file("nested/test_me.py") |
| self.create_file( |
| "nested/pyproject.toml", |
| '[tool.other]\nprop = "value"\n', |
| ) |
| self.create_file( |
| "pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports = true\n", |
| ) |
| files = [self.effective_path("nested/test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| expand_star_imports=True, |
| ) |
| |
| def test_stop_search_if_config_found(self): |
| self.create_file("nested/test_me.py") |
| self.create_file( |
| "nested/pyproject.toml", |
| "[tool.autoflake]\n", |
| ) |
| self.create_file( |
| "pyproject.toml", |
| "[tool.autoflake]\nexpand-star-imports = true\n", |
| ) |
| files = [self.effective_path("nested/test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults(files=files) |
| |
| def test_config_option(self): |
| with temporary_file( |
| suffix=".ini", |
| contents=("[autoflake]\n" "check = True\n"), |
| ) as temp_config: |
| self.create_file("test_me.py") |
| files = [self.effective_path("test_me.py")] |
| |
| args, success = autoflake.merge_configuration_file( |
| { |
| "files": files, |
| "config_file": temp_config, |
| }, |
| ) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| config_file=temp_config, |
| check=True, |
| ) |
| |
| def test_load_false(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "setup.cfg", |
| "[autoflake]\nexpand-star-imports = no\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| expand_star_imports=False, |
| ) |
| |
| def test_list_value_pyproject_toml(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| '[tool.autoflake]\nimports=["my_lib", "other_lib"]\n', |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| imports="my_lib,other_lib", |
| ) |
| |
| def test_list_value_comma_sep_string_pyproject_toml(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| '[tool.autoflake]\nimports="my_lib,other_lib"\n', |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| imports="my_lib,other_lib", |
| ) |
| |
| def test_list_value_setup_cfg(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "setup.cfg", |
| "[autoflake]\nimports=my_lib,other_lib\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| imports="my_lib,other_lib", |
| ) |
| |
| def test_non_bool_value_for_bool_property(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| '[tool.autoflake]\nexpand-star-imports="invalid"\n', |
| ) |
| files = [self.effective_path("test_me.py")] |
| _, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is False |
| |
| def test_non_bool_value_for_bool_property_in_setup_cfg(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "setup.cfg", |
| "[autoflake]\nexpand-star-imports=ok\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| _, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is False |
| |
| def test_non_list_value_for_list_property(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| "[tool.autoflake]\nexclude=true\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| _, success = autoflake.merge_configuration_file({"files": files}) |
| assert success is False |
| |
| def test_merge_with_cli_set_list_property(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| '[tool.autoflake]\nimports=["my_lib"]\n', |
| ) |
| files = [self.effective_path("test_me.py")] |
| args, success = autoflake.merge_configuration_file( |
| {"files": files, "imports": "other_lib"}, |
| ) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| imports="my_lib,other_lib", |
| ) |
| |
| def test_merge_prioritizes_flags(self): |
| self.create_file("test_me.py") |
| self.create_file( |
| "pyproject.toml", |
| "[tool.autoflake]\ncheck = false\n", |
| ) |
| files = [self.effective_path("test_me.py")] |
| flag_args = { |
| "files": files, |
| "imports": "other_lib", |
| "check": True, |
| } |
| args, success = autoflake.merge_configuration_file(flag_args) |
| assert success is True |
| assert args == self.with_defaults( |
| files=files, |
| imports="other_lib", |
| check=True, |
|