def _as_config(kw) -> isort.Config: kw["atomic"] = False if "wrap_length" in kw and "line_length" in kw: kw["wrap_length"], kw["line_length"] = sorted([kw["wrap_length"], kw["line_length"]]) try: return isort.Config(**kw) except ValueError: kw["wrap_length"] = 0 return isort.Config(**kw)
def isort_hook( source: str, formate_filename: PathLike, formate_global_config: Optional[Mapping] = None, **kwargs, ) -> str: r""" Call `isort <https://pypi.org/project/isort/>`_, using the given keyword arguments as its configuration. :param source: The source to reformat. :param formate_filename: The path to the file being reformatted. :param formate_global_config: The global configuration dictionary. Optional. :param \*\*kwargs: :returns: The reformatted source. """ if "isort_config_file" in kwargs: isort_config = isort.Config(settings_file=str(kwargs["isort_config_file"])) else: if "line_length" not in kwargs and formate_global_config: if "line_length" in (formate_global_config or {}): kwargs["line_length"] = formate_global_config["line_length"] parsed_kwargs = {} import_headings = {} for option, value in kwargs.items(): if option.startswith("import_heading"): import_headings[option[len("import_heading") + 1:]] = value elif option in isort_string_or_sequence: if isinstance(value, str): value = (value, ) elif not isinstance(value, Sequence): value = (value, ) parsed_kwargs[option] = value elif option == "force_to_top": continue # TODO isort expects a frozenset but I thought it was boolean? elif option == "remove_redundant_aliases": continue else: parsed_kwargs[option] = value isort_config = isort.Config(import_headings=import_headings, **parsed_kwargs) if PathPlus(formate_filename).suffix == ".pyi": object.__setattr__(isort_config, "remove_redundant_aliases", False) try: return isort.code(source, config=isort_config) except FileSkipComment: return source
def __init__(self, python_version: PythonVersion, settings_path: Optional[Path] = None): if not settings_path: settings_path = Path().resolve() root = black.find_project_root((settings_path, )) path = root / "pyproject.toml" if path.is_file(): value = str(path) pyproject_toml = toml.load(value) config = pyproject_toml.get("tool", {}).get("black", {}) else: config = {} self.back_mode = black.FileMode( target_versions={BLACK_PYTHON_VERSION[python_version]}, line_length=config.get("line-length", black.DEFAULT_LINE_LENGTH), string_normalization=not config.get("skip-string-normalization", True), ) self.settings_path: str = str(settings_path) if isort.__version__.startswith('4.'): self.isort_config = None else: self.isort_config = isort.Config(settings_path=self.settings_path)
def start(argv=None): global current_file global isort_config global black_config argv = sys.argv if argv is None else argv if len(sys.argv) > 2: sys.exit("Usage: qpython [filename]") elif len(sys.argv) == 2: current_file = Path(sys.argv[1]).resolve() isort_config = isort.Config(settings_path=current_file.parent) black_config_file = black.find_pyproject_toml((str(current_file), )) if black_config_file: black_config = black.parse_pyproject_toml(black_config_file) else: black_config = {} open_file_frame.title = current_file.name if current_file.exists(): with current_file.open(encoding="utf8") as open_file: code.buffer.text = open_file.read() else: message_dialog( title="Welcome to", text=ABOUT_MESSAGE, style=style, ).run() app.layout.focus(code.buffer) app.run()
async def coroutine(): global current_file global isort_config global black_config open_dialog = TextInputDialog( title="Open file", label_text="Enter the path of a file:", completer=PathCompleter(), ) filename = await show_dialog_as_float(open_dialog) if filename is not None: current_file = Path(filename).resolve() isort_config = isort.Config(settings_path=current_file.parent) black_config_file = black.find_pyproject_toml( (str(current_file), )) if black_config_file: black_config = black.parse_pyproject_toml(black_config_file) else: black_config = {} try: with open(current_file, "r", encoding="utf8") as new_file_conent: code.buffer.text = new_file_conent.read() open_file_frame.title = current_file.name feedback(f"Successfully opened {current_file}") except IOError as error: feedback(f"Error: {error}")
async def coroutine(): global current_file global isort_config global black_config save_dialog = TextInputDialog( title="Save file", label_text="Enter the path of a file:", completer=PathCompleter(), ) filename = await show_dialog_as_float(save_dialog) if filename is not None: current_file = Path(filename).resolve() isort_config = isort.Config(settings_path=current_file.parent) black_config_file = black.find_pyproject_toml( (str(current_file), )) if black_config_file: black_config = black.parse_pyproject_toml(black_config_file) else: black_config = {} if not current_file.suffixes and not current_file.exists(): current_file = current_file.with_suffix(".py") open_file_frame.title = current_file.name save_file()
def apply_isort(code: str, settings_path: Path) -> str: if isort.__version__.startswith('4.'): return isort.SortImports(file_contents=code, settings_path=str(settings_path)).output else: return isort.code( code, config=isort.Config(settings_path=str(settings_path)))
def generate_code(service_name: str, doc: bool = False) -> str: model = load_service(service_name) output = io.StringIO() generate_service_types(output, model, doc=doc) generate_service_api(output, model, doc=doc) code = output.getvalue() try: import autoflake import isort from black import FileMode, format_str # try to format with black code = format_str(code, mode=FileMode(line_length=100)) # try to remove unused imports code = autoflake.fix_code(code, remove_all_unused_imports=True) # try to sort imports code = isort.code(code, config=isort.Config(profile="black", line_length=100)) except Exception: pass return code
def __init__( self, python_version: PythonVersion, settings_path: Optional[Path] = None, wrap_string_literal: Optional[bool] = None, ): if not settings_path: settings_path = Path().resolve() root = black_find_project_root((settings_path, )) path = root / "pyproject.toml" if path.is_file(): value = str(path) pyproject_toml = toml.load(value) config = pyproject_toml.get("tool", {}).get("black", {}) else: config = {} black_kwargs: Dict[str, Any] = {} if wrap_string_literal is not None: experimental_string_processing = wrap_string_literal else: experimental_string_processing = config.get( 'experimental-string-processing') if experimental_string_processing is not None: # pragma: no cover if black.__version__.startswith('19.'): # type: ignore warn( f'black doesn\'t support `experimental-string-processing` option' # type: ignore f' for wrapping string literal in {black.__version__}') else: black_kwargs[ 'experimental_string_processing'] = experimental_string_processing if TYPE_CHECKING: self.back_mode: black.FileMode else: self.back_mode = black.FileMode( target_versions={BLACK_PYTHON_VERSION[python_version]}, line_length=config.get("line-length", black.DEFAULT_LINE_LENGTH), string_normalization=not config.get( "skip-string-normalization", True), **black_kwargs, ) self.settings_path: str = str(settings_path) if isort.__version__.startswith('4.'): self.isort_config = None else: self.isort_config = isort.Config(settings_path=self.settings_path)
def generate_class(class_name: str, cmd: str, level=0) -> str: docker_lines = get_help_message(cmd) nl = level + 4 sections, arguments = parse_help(docker_lines) cmd_fns = "" add_imports: Set[str] = set() if "commands" in sections: logger.info("Found commands in section {}", cmd) for cmd_fn, add_import in get_def_commands(sections): cmd_fns += cmd_fn add_imports = add_imports.union(add_import) args: List[str] = _flatten(list(type_arg(arg)) for arg in arguments) # List of argument that are options only options = ", ".join([f'"{arg.arg}"' for arg in arguments if arg.is_option]) if options: options = options + "," new_line = "\n" res = indent( f''' # DO NOT EDIT: Autogenerated by {__file__} # for {_version("docker-compose")} import attr from typing import Optional, List from docker_composer.base import DockerBaseRunner {new_line.join(add_imports)} @attr.s(auto_attribs=True) class {class_name}(DockerBaseRunner): """ {indent(get_docstring(sections), level=nl)} """ {indent(args, level=nl)} _cmd: str = "{cmd or ""}" _options: List[str] = [{options}] {indent(cmd_fns, level=nl)} ''', level=level, ) try: res = isort.code(res, config=isort.Config(settings_path=project_root())) except ISortError as exc: logger.exception(exc) try: return black.format_str(res, mode=black.Mode()) except Exception as exc: logger.exception(exc) return res
def set_version_to_file(fl: Path, new_version: str, **kwargs) -> str: visitor = VersionTransformer(version_transform=lambda x: new_version, **kwargs) orig_code = fl.read_text() visitor.visit(ast.parse(orig_code)) orig_code_lines = orig_code.split('\n') new_code = '\n'.join([ *orig_code_lines[0:visitor.version_lineno - 1], f"{visitor.version_tag} = '{visitor.version_new}'", *orig_code_lines[visitor.version_lineno:] ]) try: import autopep8 except ImportError: pass else: new_code = autopep8.fix_code(new_code, options={ 'aggressive': 5, 'max_line_length': 120, 'experimental': True }, apply_config=True) try: import isort except ImportError: pass else: new_code = isort.code(new_code, config=isort.Config(line_length=120, reverse_relative=True)) fl.write_text(new_code) return visitor.version_new
def prettify_python(path_to_repo): """Format files in babelized project with ``black``. Args: path_to_repo (str): Path-like object to babelized project. """ path_to_repo = pathlib.Path(path_to_repo) with open(path_to_repo / "babel.toml") as fp: meta = toml.parse(fp.read()) module_name = meta["package"]["name"] files_to_fix = [ path_to_repo / "setup.py", path_to_repo / module_name / "bmi.py", path_to_repo / module_name / "__init__.py", path_to_repo / "docs" / "conf.py", ] config = isort.Config(quiet=True) for file_to_fix in files_to_fix: isort.api.sort_file(file_to_fix, config=config) blacken_file(file_to_fix)
def reformat_file(filename: PathLike, yapf_style: str, isort_config_file: str) -> int: """ Reformat the given file. :param filename: :param yapf_style: The name of the yapf style, or the path to the yapf style file. :param isort_config_file: The filename of the isort configuration file. """ old_isort_settings = isort.settings.CONFIG_SECTIONS.copy() try: isort.settings.CONFIG_SECTIONS["isort.cfg"] = ("settings", "isort") isort_config = isort.Config(settings_file=str(isort_config_file)) r = yapf_isort.Reformatter(filename, yapf_style, isort_config) ret = r.run() r.to_file() return ret finally: isort.settings.CONFIG_SECTIONS = old_isort_settings
st.sampled_from(sorted(isort.settings.KNOWN_SECTION_MAPPING)), "force_grid_wrap": st.integers(0, 20), "profile": st.sampled_from(sorted(isort.settings.profiles)), "py_version": st.sampled_from(("auto", ) + isort.settings.VALID_PY_TARGETS), } kwargs = {**inferred_kwargs, **specific, **force_strategies} return st.fixed_dictionaries({}, optional=kwargs).map(_as_config) st.register_type_strategy(isort.Config, configs()) @hypothesis.example("import A\nimportA\r\n\n", isort.Config(), False) @hypothesis.given( source_code=st.lists( from_grammar(auto_target=False) | from_node(auto_target=False) | from_node(libcst.Import, auto_target=False) | from_node(libcst.ImportFrom, auto_target=False), min_size=1, max_size=10, ).map("\n".join), config=st.builds(isort.Config), disregard_skip=st.booleans(), ) @hypothesis.seed(235738473415671197623909623354096762459) @hypothesis.settings(suppress_health_check=[ hypothesis.HealthCheck.too_slow, hypothesis.HealthCheck.filter_too_much
ABOUT_MESSAGE = f"""QuickPython version {__version__} Copyright (c) 2020 Timothy Crosley. Few rights reserved. MIT Licensed. Simultanously distributed to the US and Canada. And you know, the rest of the world. A productive parody. Made in Seattle. """ kb = KeyBindings() eb = KeyBindings() current_file: Optional[Path] = None default_isort_config = isort.Config(settings_path=os.getcwd()) if default_isort_config == isort.settings.DEFAULT_CONFIG: default_isort_config = isort.Config(profile="black", float_to_top=True) default_black_config_file = black.find_pyproject_toml((os.getcwd(), )) if default_black_config_file: default_black_config = black.parse_pyproject_toml( default_black_config_file) else: default_black_config = {} default_black_config = {} isort_config: isort.Config = default_isort_config black_config: dict = default_black_config
''').lstrip(), "multi_line": dedent(r''' """ Multi-line docstring """ # Comment for A. import a # Comment for B - not A! import b ''').lstrip(), } for force_sort_within_sections in [False, True]: for text_key, text_in in text_in_map.items(): config = isort.Config( force_sort_within_sections=force_sort_within_sections) text_out = isort.code(text_in, config=config) print(f"force_sort_within_sections = {force_sort_within_sections}") print(f"text_in_map[{text_key}]") diff = unified_diff( text_in.splitlines(keepends=True), text_out.splitlines(keepends=True), ) diff_text = "".join(diff) if not diff_text: diff_text = "<no diff>" print(indent(diff_text, " ")) print() r''' Output:
def check_file(text, filename, use_black=False, isort_settings_file=None): if filename.endswith(".ipynb"): messages = [] doc = json.loads(text) assert doc["metadata"]["kernelspec"]["language"] == "python" for i, cell in enumerate(doc["cells"]): cell_name = f"{filename}/In[{i + 1}]" if cell["cell_type"] == "code": cell_text = "".join(cell["source"]) try: cell_messages, new_cell_text = check_file( cell_text, cell_name, use_black=use_black, isort_settings_file=isort_settings_file, ) except black.InvalidInput: cell_messages = [] new_cell_text = cell_text messages.append(f"{cell_name}: Could not parse!") cell["source"] = new_cell_text.rstrip().splitlines(keepends=True) messages += cell_messages if len(cell["outputs"]) > 0: messages.append(f"{cell_name}: There should be no outputs!") cell["outputs"] = [] new_text = json.dumps(doc, indent=1) + "\n" return messages, new_text messages, new_text = check_maybe_preload_pydrake_for_torch( text, filename) new_text_orig = new_text formatters_used = [] if use_black: formatters_used += ["black"] black_file_mode = black.FileMode( target_versions={black.TargetVersion.PY36}, line_length=79, ) # WARNING: This may create line-length problems: # https://github.com/psf/black/issues/208 # https://github.com/psf/black/issues/1017 try: new_text = black.format_file_contents( src_contents=new_text, fast=True, mode=black_file_mode, ) except black.NothingChanged: pass if isort_settings_file is not None: # N.B. If isort_settings_file == "", then it will load a default file. if isort_settings_file != "": assert isfile(isort_settings_file), isort_settings_file formatters_used += ["isort"] isort_config = isort.Config(settings_file=isort_settings_file) new_text = isort.code(new_text, config=isort_config) # N.B. Check after applying both, as they may conflict between each other # and we don't care about intermediate results. if new_text != new_text_orig: messages.append( f"{filename}: Needs reformatting for {formatters_used}") return messages, new_text
def format_str(src): src = black.format_str(src, mode=black.FileMode(line_length=88)) src = isort.code(src, config=isort.Config(profile="black")) return src