def find(paths: Iterable[str], config: Config, skipped: List[str], broken: List[str]) -> Iterator[str]: """Fines and provides an iterator for all Python source files defined in paths.""" visited_dirs: Set[Path] = set() for path in paths: if os.path.isdir(path): for dirpath, dirnames, filenames in os.walk( path, topdown=True, followlinks=config.follow_links): base_path = Path(dirpath) for dirname in list(dirnames): full_path = base_path / dirname resolved_path = full_path.resolve() if config.is_skipped(full_path): skipped.append(dirname) dirnames.remove(dirname) else: if resolved_path in visited_dirs: # pragma: no cover dirnames.remove(dirname) visited_dirs.add(resolved_path) for filename in filenames: filepath = os.path.join(dirpath, filename) if config.is_supported_filetype(filepath): if config.is_skipped(Path(os.path.abspath(filepath))): skipped.append(filename) else: yield filepath elif not os.path.exists(path): broken.append(path) else: yield path
def test_namespace_package_placement(examples_path): namespace_examples = examples_path / "namespaces" implicit = namespace_examples / "implicit" pkg_resource = namespace_examples / "pkg_resource" pkgutil = namespace_examples / "pkgutil" for namespace_test in (implicit, pkg_resource, pkgutil): print(namespace_test) config = Config(settings_path=namespace_test) no_namespaces = Config(settings_path=namespace_test, auto_identify_namespace_packages=False) namespace_override = Config(settings_path=namespace_test, known_firstparty=["root.name"]) assert place.module("root.name", config=config) == "THIRDPARTY" assert place.module("root.nested", config=config) == "FIRSTPARTY" assert place.module("root.name", config=no_namespaces) == "FIRSTPARTY" assert place.module("root.name", config=namespace_override) == "FIRSTPARTY" no_namespace = namespace_examples / "none" almost_implicit = namespace_examples / "almost-implicit" weird_encoding = namespace_examples / "weird_encoding" for lacks_namespace in (no_namespace, almost_implicit, weird_encoding): config = Config(settings_path=lacks_namespace) manual_namespace = Config(settings_path=lacks_namespace, namespace_packages=["root"]) assert place.module("root.name", config=config) == "FIRSTPARTY" assert place.module("root.nested", config=config) == "FIRSTPARTY" assert place.module("root.name", config=manual_namespace) == "THIRDPARTY" assert place.module("root.nested", config=config) == "FIRSTPARTY"
def test_init_unsupported_settings_fails_gracefully(self): with pytest.raises(exceptions.UnsupportedSettings): Config(apply=True) try: Config(apply=True) except exceptions.UnsupportedSettings as error: assert error.unsupported_settings == {"apply": {"value": True, "source": "runtime"}}
def test_known_settings(self): assert Config( known_third_party=["one"]).known_third_party == frozenset({"one"}) assert Config(known_thirdparty=["two"]).known_third_party == frozenset( {"two"}) assert Config(known_third_party=["one"], known_thirdparty=["two"]).known_third_party == frozenset( {"one"})
def test_requirements_finder(tmpdir) -> None: subdir = tmpdir.mkdir("subdir").join("lol.txt") subdir.write("flask") req_file = tmpdir.join("requirements.txt") req_file.write( "Django==1.11\n-e git+https://github.com/orsinium/deal.git#egg=deal\n") for path in (str(tmpdir), str(subdir)): finder = finders.RequirementsFinder(config=Config(), path=path) files = list(finder._get_files()) assert len(files) == 1 # file finding assert files[0].endswith("requirements.txt") # file finding assert set(finder._get_names(str(req_file))) == {"Django", "deal" } # file parsing assert finder.find("django") == sections.THIRDPARTY # package in reqs assert finder.find("flask") is None # package not in reqs assert finder.find("deal") == sections.THIRDPARTY # vcs assert len(finder.mapping) > 100 assert finder._normalize_name("deal") == "deal" assert finder._normalize_name("Django") == "django" # lowercase assert finder._normalize_name( "django_haystack") == "haystack" # mapping assert finder._normalize_name( "Flask-RESTful") == "flask_restful" # conver `-`to `_` req_file.remove()
def test_module(src_path): place_tester = partial(place.module, config=Config(src_paths=[src_path])) assert place_tester("isort") == sections.FIRSTPARTY assert place_tester("os") == sections.STDLIB assert place_tester(".deprecated") == sections.LOCALFOLDER assert place_tester("__future__") == sections.FUTURE assert place_tester("hug") == sections.THIRDPARTY
def assignment(code: str, sort_type: str, extension: str, config: Config = DEFAULT_CONFIG) -> str: """Sorts the literal present within the provided code against the provided sort type, returning the sorted representation of the source code. """ if sort_type == "assignments": return assignments(code) elif sort_type not in type_mapping: raise ValueError( "Trying to sort using an undefined sort_type. " f"Defined sort types are {', '.join(type_mapping.keys())}.") variable_name, literal = code.split(" = ") variable_name = variable_name.lstrip() try: value = ast.literal_eval(literal) except Exception as error: raise LiteralParsingFailure(code, error) expected_type, sort_function = type_mapping[sort_type] if type(value) != expected_type: raise LiteralSortTypeMismatch(type(value), expected_type) printer = ISortPrettyPrinter(config) sorted_value_code = f"{variable_name} = {sort_function(value, printer)}" if config.formatting_function: sorted_value_code = config.formatting_function(sorted_value_code, extension, config).rstrip() sorted_value_code += code[len(code.rstrip()):] return sorted_value_code
def test_no_standard_library_placement(): assert place.module_with_reason( "pathlib", config=Config(sections=["THIRDPARTY"], default_section="THIRDPARTY")) == ( "THIRDPARTY", "Default option in Config or universal default.") assert place.module("pathlib") == "STDLIB"
def test_import_statement(): assert wrap.import_statement("", [], []) == "" assert (wrap.import_statement( "from x import ", ["y"], [], config=Config(balanced_wrapping=True)) == "from x import (y)") assert ( wrap.import_statement("from long_import ", ["verylong"] * 10, []) == """from long_import (verylong, verylong, verylong, verylong, verylong, verylong, verylong, verylong, verylong, verylong)""")
def _indented_config(config: Config, indent: str): if not indent: return config return Config( config=config, line_length=max(config.line_length - len(indent), 0), wrap_length=max(config.wrap_length - len(indent), 0), lines_after_imports=1, )
def _indented_config(config: Config, indent: str): if not indent: return config return Config( config=config, line_length=max(config.line_length - len(indent), 0), wrap_length=max(config.wrap_length - len(indent), 0), lines_after_imports=1, import_headings=config.import_headings if config.indented_import_headings else {}, )
def test_src_paths_supports_glob_expansion(self, tmp_path): libs = tmp_path / "libs" libs.mkdir() requests = libs / "requests" requests.mkdir() beautifulpasta = libs / "beautifulpasta" beautifulpasta.mkdir() assert sorted( Config(directory=tmp_path, src_paths=["libs/*"]).src_paths) == sorted( (beautifulpasta, requests))
def test_sort_imports(tmpdir): tmp_file = tmpdir.join("file.py") tmp_file.write("import os, sys\n") assert main.sort_imports(str(tmp_file), DEFAULT_CONFIG, check=True).incorrectly_sorted main.sort_imports(str(tmp_file), DEFAULT_CONFIG) assert not main.sort_imports(str(tmp_file), DEFAULT_CONFIG, check=True).incorrectly_sorted skip_config = Config(skip=["file.py"]) assert main.sort_imports( str(tmp_file), config=skip_config, check=True, disregard_skip=False ).skipped assert main.sort_imports(str(tmp_file), config=skip_config, disregard_skip=False).skipped
def test_pipfile_finder(tmpdir) -> None: pipfile = tmpdir.join("Pipfile") pipfile.write(PIPFILE) finder = finders.PipfileFinder(config=Config(), path=str(tmpdir)) assert set(finder._get_names(str(tmpdir))) == {"Django", "deal"} # file parsing assert finder.find("django") == sections.THIRDPARTY # package in reqs assert finder.find("flask") is None # package not in reqs assert finder.find("deal") == sections.THIRDPARTY # vcs assert len(finder.mapping) > 100 assert finder._normalize_name("deal") == "deal" assert finder._normalize_name("Django") == "django" # lowercase assert finder._normalize_name("django_haystack") == "haystack" # mapping assert finder._normalize_name( "Flask-RESTful") == "flask_restful" # conver `-`to `_` pipfile.remove()
def test_file_contents(): ( in_lines, out_lines, import_index, _, _, _, _, _, change_count, original_line_count, _, _, ) = parse.file_contents(TEST_CONTENTS, config=Config(default_section="")) assert "\n".join(in_lines) == TEST_CONTENTS assert "import" not in "\n".join(out_lines) assert import_index == 1 assert change_count == -11 assert original_line_count == len(in_lines)
def sort_imports( content: str, module_name: str, extension: str = "py", third_party: Iterable[str] = ()) -> str: """ Sort imports with `isort`. Arguments: content -- File content. module_name -- Current module name. extension -- py or pyi third_party -- List of module names to be marked as third-party. Returns: New file content. """ known_third_party = list(third_party) or [ "aiobotocore", "boto3", "botocore", "typing_extensions", "mypy_boto3", ] if module_name in known_third_party: known_third_party.remove(module_name) result = sort_code_string( code=content, extension=extension, config=Config( profile="black", known_first_party=[module_name], known_third_party=known_third_party, line_length=LINE_LENGTH, ), ) return result or ""
def test_path_finder(monkeypatch) -> None: config = config = Config() finder = finders.PathFinder(config=config) third_party_prefix = next(path for path in finder.paths if "site-packages" in path) ext_suffixes = importlib.machinery.EXTENSION_SUFFIXES imaginary_paths = { posixpath.join(finder.stdlib_lib_prefix, "example_1.py"), posixpath.join(third_party_prefix, "example_2.py"), posixpath.join(os.getcwd(), "example_3.py"), } imaginary_paths.update({ posixpath.join(third_party_prefix, "example_" + str(i) + ext_suffix) for i, ext_suffix in enumerate(ext_suffixes, 4) }) monkeypatch.setattr("isort.deprecated.finders.exists_case_sensitive", lambda p: p in imaginary_paths) assert finder.find("example_1") == sections.STDLIB assert finder.find("example_2") == sections.THIRDPARTY assert finder.find("example_3") == settings.DEFAULT_CONFIG.default_section for i, _ in enumerate(ext_suffixes, 4): assert finder.find("example_" + str(i)) == sections.THIRDPARTY
def test_invalid_settings_path(self): with pytest.raises(exceptions.InvalidSettingsPath): Config( settings_path="this_couldnt_possibly_actually_exists/could_it")
def test_value_assignment(): assert isort.literal.assignment("x = ['b', 'a']", "list", "py") == "x = ['a', 'b']" assert (isort.literal.assignment( "x = ['b', 'a']", "list", "py", Config(formatter="example")) == 'x = ["a", "b"]')
def test_is_skipped(self): assert Config().is_skipped(Path("C:\\path\\isort.py")) assert Config(skip=["/path/isort.py"]).is_skipped( Path("C:\\path\\isort.py"))
def test_invalid_pyversion(self): with pytest.raises(ValueError): Config(py_version=10)
class TestConfig: instance = Config() def test_init(self): assert Config() def test_init_unsupported_settings_fails_gracefully(self): with pytest.raises(exceptions.UnsupportedSettings): Config(apply=True) try: Config(apply=True) except exceptions.UnsupportedSettings as error: assert error.unsupported_settings == {"apply": {"value": True, "source": "runtime"}} def test_known_settings(self): assert Config(known_third_party=["one"]).known_third_party == frozenset({"one"}) assert Config(known_thirdparty=["two"]).known_third_party == frozenset({"two"}) assert Config( known_third_party=["one"], known_thirdparty=["two"] ).known_third_party == frozenset({"one"}) def test_invalid_settings_path(self): with pytest.raises(exceptions.InvalidSettingsPath): Config(settings_path="this_couldnt_possibly_actually_exists/could_it") def test_invalid_pyversion(self): with pytest.raises(ValueError): Config(py_version=10) def test_invalid_profile(self): with pytest.raises(exceptions.ProfileDoesNotExist): Config(profile="blackandwhitestylemixedwithpep8") def test_is_skipped(self): assert Config().is_skipped(Path("C:\\path\\isort.py")) assert Config(skip=["/path/isort.py"]).is_skipped(Path("C:\\path\\isort.py")) def test_is_supported_filetype(self): assert self.instance.is_supported_filetype("file.py") assert self.instance.is_supported_filetype("file.pyi") assert self.instance.is_supported_filetype("file.pyx") assert self.instance.is_supported_filetype("file.pxd") assert not self.instance.is_supported_filetype("file.pyc") assert not self.instance.is_supported_filetype("file.txt") assert not self.instance.is_supported_filetype("file.pex") def test_is_supported_filetype_ioerror(self, tmpdir): does_not_exist = tmpdir.join("fake.txt") assert not self.instance.is_supported_filetype(str(does_not_exist)) def test_is_supported_filetype_shebang(self, tmpdir): path = tmpdir.join("myscript") path.write("#!/usr/bin/env python\n") assert self.instance.is_supported_filetype(str(path)) def test_is_supported_filetype_editor_backup(self, tmpdir): path = tmpdir.join("myscript~") path.write("#!/usr/bin/env python\n") assert not self.instance.is_supported_filetype(str(path)) def test_is_supported_filetype_defaults(self, tmpdir): assert self.instance.is_supported_filetype(str(tmpdir.join("stub.pyi"))) assert self.instance.is_supported_filetype(str(tmpdir.join("source.py"))) assert self.instance.is_supported_filetype(str(tmpdir.join("source.pyx"))) def test_is_supported_filetype_configuration(self, tmpdir): config = Config(supported_extensions=("pyx",), blocked_extensions=("py",)) assert config.is_supported_filetype(str(tmpdir.join("stub.pyx"))) assert not config.is_supported_filetype(str(tmpdir.join("stub.py"))) @pytest.mark.skipif( sys.platform == "win32", reason="cannot create fifo file on Windows platform" ) def test_is_supported_filetype_fifo(self, tmpdir): fifo_file = os.path.join(tmpdir, "fifo_file") os.mkfifo(fifo_file) assert not self.instance.is_supported_filetype(fifo_file) def test_src_paths_are_combined_and_deduplicated(self): src_paths = ["src", "tests"] src_full_paths = (Path(os.getcwd()) / f for f in src_paths) assert Config(src_paths=src_paths * 2).src_paths == tuple(src_full_paths) def test_deprecated_multi_line_output(self): assert Config(multi_line_output=6).multi_line_output == WrapModes.VERTICAL_GRID_GROUPED
def test_invalid_profile(self): with pytest.raises(exceptions.ProfileDoesNotExist): Config(profile="blackandwhitestylemixedwithpep8")
def test_is_supported_filetype_configuration(self, tmpdir): config = Config(supported_extensions=("pyx",), blocked_extensions=("py",)) assert config.is_supported_filetype(str(tmpdir.join("stub.pyx"))) assert not config.is_supported_filetype(str(tmpdir.join("stub.py")))
def test_init(self): assert Config()
def test_src_paths_are_combined_and_deduplicated(self): src_paths = ["src", "tests"] src_full_paths = (Path(os.getcwd()) / f for f in src_paths) assert Config(src_paths=src_paths * 2).src_paths == tuple(src_full_paths)
def isort_sort(source, settings_path): return code(source, config=Config(settings_path=settings_path))
def test_deprecated_multi_line_output(self): assert Config(multi_line_output=6).multi_line_output == WrapModes.VERTICAL_GRID_GROUPED
def test_sorted_imports_multiple_configs() -> None: with pytest.raises(ValueError): api.sort_code_string("import os", config=Config(line_length=80), line_length=80)
def test_extra_standard_library(src_path): place_tester = partial(place.module, config=Config(src_paths=[src_path], extra_standard_library=["hug"])) assert place_tester("os") == sections.STDLIB assert place_tester("hug") == sections.STDLIB