def check_copy_consistency(self, comment, class_name, class_code, overwrite_result=None): code = comment + f"\nclass {class_name}(nn.Module):\n" + class_code if overwrite_result is not None: expected = comment + f"\nclass {class_name}(nn.Module):\n" + overwrite_result code = black.format_str(code, mode=black.FileMode([black.TargetVersion.PY35], line_length=119)) fname = os.path.join(self.transformer_dir, "new_code.py") with open(fname, "w") as f: f.write(code) if overwrite_result is None: self.assertTrue(len(check_copies.is_copy_consistent(fname)) == 0) else: check_copies.is_copy_consistent(f.name, overwrite=True) with open(fname, "r") as f: self.assertTrue(f.read(), expected)
def black_format_code(contents: str) -> str: """Formats the given import section using black.""" try: immediate.buffer.text = "" return black.format_file_contents( contents, fast=True, mode=black.FileMode(), ) except black.NothingChanged: return contents except Exception as error: immediate.buffer.text = str(error) return contents
def format_with_black(source: str) -> FormattingChanges: mode = black.FileMode( target_versions=set(), is_pyi=False, line_length=black.DEFAULT_LINE_LENGTH, string_normalization=True, ) try: formatted = black.format_file_contents(source, fast=False, mode=mode) except black.NothingChanged: return source return FormattingChanges(formatted)
def format_python_file(filename): try: import black black.format_file_in_place( pathlib.Path(filename).absolute(), fast=True, mode=black.FileMode( line_length=88, target_versions={black.TargetVersion.PY33} ), write_back=black.WriteBack.YES, ) except: pass
def _blacken_code(code): major, minor, _ = platform.python_version_tuple() pyversion = 'py{major}{minor}'.format(major=major, minor=minor) target_versions = [black.TargetVersion[pyversion.upper()]] line_length = black.DEFAULT_LINE_LENGTH string_normalization = True mode = black.FileMode( target_versions=target_versions, line_length=line_length, string_normalization=string_normalization, ) return black.format_file_contents(code, fast=False, mode=mode)
def black_format(code: str, is_pyi: bool = False, line_length: int = 88) -> str: """Formats the provided code snippet using black""" try: return black.format_file_contents( code, fast=True, mode=black.FileMode( is_pyi=is_pyi, line_length=line_length, ), ) except black.NothingChanged: return code
def format_signature(signature_start: str, signature_end: str): """pretty formatting to avoid long signatures on one single line""" # first, we make it look like a real function declaration. fake_signature_start = 'x' * len(signature_start) fake_signature = fake_signature_start + signature_end fake_python_code = f'def {fake_signature}:\n pass\n' # we format with black mode = black.FileMode(line_length=110) formatted_fake_python_code = black.format_str(fake_python_code, mode=mode) # we make the final, multiline signature new_signature_end = extract_signature_end(formatted_fake_python_code) return signature_start + new_signature_end
def new_piccolo_conf(engine_name: str, force: bool = False, root: str = "."): print("Creating new piccolo_conf file ...") file_path = os.path.join(root, "piccolo_conf.py") if os.path.exists(file_path) and not force: sys.exit("The file already exists - exiting.") with open(file_path, "w") as f: template = JINJA_ENV.get_template("piccolo_conf.py.jinja") file_contents = template.render(engine_name=engine_name) file_contents = black.format_str(file_contents, mode=black.FileMode(line_length=82)) f.write(file_contents)
def _write_file(self, base_name: str, lines: List): """ Write all the lines""" output_file = self.outputdir / f"{base_name.lower()}.py" # Reformat the file with black. This way there is no need for difficult # list mangling file_contents = black.format_str("\n".join(lines), mode=black.FileMode()) # Reformat the file with isort file_contents = isort.code(file_contents) with open(output_file, "w") as f: # Add newlines, since writelines does not add those f.writelines(line for line in file_contents)
def _make_test(imports: Set[str], body: str) -> str: # Discarding "builtins." and "__main__" probably isn't particularly useful # for user code, but important for making a good impression in demos. body = body.replace("builtins.", "").replace("__main__.", "") imports.discard("builtins") imports.discard("__main__") header = IMPORT_SECTION.format( imports="".join(f"import {imp}\n" for imp in sorted(imports)), reject="reject, " if " reject()\n" in body else "", ) nothings = body.count("st.nothing()") if nothings == 1: header += "# TODO: replace st.nothing() with an appropriate strategy\n\n" elif nothings >= 1: header += "# TODO: replace st.nothing() with appropriate strategies\n\n" return black.format_str(header + body, mode=black.FileMode())
def blacken_file(filepath): """Format a Python file with ``black``. Args: filepath (str): Path-like object to a Python file. """ with open(filepath, "r") as fp: try: new_contents = blk.format_file_contents(fp.read(), fast=True, mode=blk.FileMode()) except blk.NothingChanged: new_contents = None if new_contents: with open(filepath, "w") as fp: fp.write(new_contents)
def outputfile_compiler(output_file: OutputTemplate) -> str: templates_folder = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "templates")) env = jinja2.Environment( trim_blocks=True, lstrip_blocks=True, loader=jinja2.FileSystemLoader(templates_folder), ) template = env.get_template("template.py.j2") return black.format_str( template.render(output_file=output_file), mode=black.FileMode(target_versions={black.TargetVersion.PY37}), )
def process(self, content: str) -> str: try: import black except ImportError: return content try: return black.format_file_contents( content, fast=False, mode=black.FileMode(), ) except black.InvalidInput as e: logger.error(e) return content
def _step_external( step: Dict, last_step: Dict, start: Union[str, int], stop: Union[str, int], gas: Tuple[int, int], subcall: Dict, expand: bool, ) -> str: key = _step_internal(step, last_step, start, stop, gas, subcall) if not expand: return key mode = black.FileMode(line_length=60) result: OrderedDict = OrderedDict({key: {}}) result[key][f"address: {step['address']}"] = None if "value" in subcall: result[key][f"value: {subcall['value']}"] = None if "inputs" not in subcall: result[key][f"calldata: {subcall['calldata']}"] = None if subcall["inputs"]: result[key]["input arguments:"] = [ f"{k}: {black.format_str(str(v), mode=mode)}" for k, v in subcall["inputs"].items() ] else: result[key]["input arguments: None"] = None if "return_value" in subcall: value = subcall["return_value"] if isinstance(value, tuple) and len(value) > 1: result[key]["return values:"] = [ black.format_str(str(i), mode=mode) for i in value ] else: if isinstance(value, tuple): value = value[0] value_str = black.format_str(str(value), mode=mode) result[key][f"return value: {value_str}"] = None if "revert_msg" in subcall: result[key][ f"revert reason: {color('bright red')}{subcall['revert_msg']}{color}"] = None return build_tree(result, multiline_pad=0).rstrip()
def read_black_config(self, path: PathLike) -> black.FileMode: if not Path(path).is_file(): raise FileNotFoundError(f"{path} is not a file.") try: pyproject_toml = toml.load(path) config = pyproject_toml.get("tool", {}).get("black", {}) except toml.TomlDecodeError as error: raise MalformattedToml(error) if "line_length" not in config: config["line_length"] = self.line_length try: return black.FileMode(**config) except TypeError as error: raise InvalidBlackConfiguration(error)
async def _create_new_migration(app_config: AppConfig, auto=False) -> None: """ Creates a new migration file on disk. """ _id = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S") # Originally we just used the _id as the filename, but colons aren't # supported in Windows, so we need to sanitize it. We don't want to # change the _id format though, as it would break existing migrations. # The filename doesn't have any special significance - only the id matters. filename = _id.replace(":", "-") path = os.path.join(app_config.migrations_folder_path, f"{filename}.py") if auto: alter_statements = await AutoMigrationManager().get_alter_statements( app_config=app_config) _alter_statements = list( chain(*[i.statements for i in alter_statements])) extra_imports = sorted( list(set(chain(*[i.extra_imports for i in alter_statements])))) extra_definitions = sorted( list(set(chain(*[i.extra_definitions for i in alter_statements])))) if sum([len(i.statements) for i in alter_statements]) == 0: print("No changes detected - exiting.") sys.exit(0) file_contents = render_template( migration_id=_id, auto=True, alter_statements=_alter_statements, extra_imports=extra_imports, extra_definitions=extra_definitions, app_name=app_config.app_name, ) else: file_contents = render_template(migration_id=_id, auto=False) # Beautify the file contents a bit. file_contents = black.format_str(file_contents, mode=black.FileMode(line_length=82)) with open(path, "w") as f: f.write(file_contents)
def black_format_import_section(contents: str, extension: str, config: isort.settings.Config) -> str: """Formats the given import section using black.""" if extension.lower() not in ("pyi", "py"): return contents try: return black.format_file_contents( contents, fast=True, mode=black.FileMode( is_pyi=extension.lower() == "pyi", line_length=config.line_length, ), ) except black.NothingChanged: return contents
def to_python(self, *, indent=0, strict=True, pretty=False, black_mode=None): global have_black self.get_tables() # for table consistency check/raise if pretty: strict = True python_str = self.to_python_implementation(indent=indent, strict=strict) if pretty and have_black: if black_mode is None: black_mode = black.FileMode() python_str = black.format_str(python_str, mode=black_mode) return python_str
def tangle(self, line, cell): import black enabled = Tangle.instance().enabled Tangle.instance().enabled = True cell = self.shell.input_transformer_manager.transform_cell(cell) IPython.display.display(IPython.display.Code(cell, language="python")) IPython.display.display( IPython.display.Code( black.format_str( ast.dump( self.shell.transform_ast( self.shell.compile.ast_parse(cell))), mode=black.FileMode(), ))) Tangle.instance().enabled = enabled
def _format_path(path: Path, *, check: bool) -> Tuple[str, bool, list]: content = path.read_text("utf-8") lines = content.splitlines() errors = [] offset = 0 changed = False for source, lineno in exdown.extract(path, syntax_filter="python"): sourcelines = source.splitlines() try: outputlines = black.format_str( source, mode=black.FileMode( target_versions={black.TargetVersion.PY37}), ).splitlines() except black.InvalidInput as exc: if source.startswith(">>> "): # Probably a Python shell snippet. Skip it since Black can't read those. continue errors.append(_danger(f"ERROR: at {path}:{lineno}: {exc}")) continue if sourcelines == outputlines: continue changed = True if check: continue lines_before = lines[:lineno + offset] lines_after = lines[lineno + offset + len(sourcelines):] lines = lines_before + outputlines + lines_after offset += len(outputlines) - len(sourcelines) if check and changed: errors.append(_warn(f"Needs formatting: {path}")) lines.append("") # Final newline. if not content.endswith("\n"): changed = True output = "\n".join(lines) return output, changed, errors
def blacken(lines, mode=None): for original_line_range, code_format, line_unit in lines: if code_format == "none": yield line_unit continue indentation_depth, parameters, code = extract_code( line_unit, code_format) current_mode = black.FileMode() if mode is None else copy.copy(mode) current_mode.line_length -= indentation_depth + parameters.pop( "prompt_length", 0) original_line_number, _ = original_line_range original_line_number += parameters.pop("n_header_lines", 0) try: blackened = black.format_str(code, mode=current_mode).rstrip() except TokenError as e: message, (apparent_line_number, column) = e.args lineno = original_line_number + (apparent_line_number - 1) faulty_line = code.split("\n")[(apparent_line_number - 1) - 1] raise black.InvalidInput( f"Cannot parse: {lineno}:{column}: {message}: {faulty_line}") except black.InvalidInput as e: message, apparent_line_number, column, faulty_line = parse_message( str(e)) lineno = original_line_number + (apparent_line_number - 1) raise black.InvalidInput( f"{message}: {lineno}:{column}: {faulty_line}") except IndentationError as e: lineno = original_line_number + (e.lineno - 1) line = e.text.rstrip() # TODO: try to find the actual line, this exception is # only raised when the indentation causes the code to # become ambiguous raise black.InvalidInput(f"Invalid indentation: {lineno}: {line}") reformatted = reformat_code(blackened, code_format, indentation_depth, **parameters) yield reformatted
def apply(*, source: str) -> str: """ Apply automatic code formatting to source code. Args: source: The source code. Returns: The formatted source code. """ try: return black.format_file_contents(src_contents=source, fast=False, mode=black.FileMode()) except black.NothingChanged: return source
def blackify(python_string): if isinstance(python_string, list): python_string = "".join(python_string) error = None blackified = "" python_string = python_string.strip() if not python_string: error = ValueError(f"Nothing to format.") else: try: blackified = black.format_str(python_string, mode=black.FileMode()) except Exception as e: error = e print(error) return blackified
def __init__( self, snakefile: TokenIterator, line_length: int = DEFAULT_LINE_LENGTH, black_config: Optional[PathLike] = None, ): self._line_length: int = line_length self.result: str = "" self.lagging_comments: str = "" self.no_formatting_yet: bool = True if black_config is None: self.black_mode = black.FileMode(line_length=self.line_length) else: self.black_mode = self.read_black_config(black_config) super().__init__(snakefile) # Call to parse snakefile
def stringify_translated_workflow(wf): try: import black try: return black.format_str(wf, mode=black.FileMode(line_length=82)) except black.InvalidInput: Logger.warn( "Check the generated Janis code carefully, as there might be a syntax error. You should report this error along with the workflow you're trying to generate from" ) except ImportError: Logger.debug( "Janis can automatically format generated Janis code if you install black: https://github.com/psf/black" ) return wf
def ast_pretty_dump(node: ast.AST, annotate_fields: bool = True, include_attributes: bool = False) -> str: """ Use black formatting library to prettify the dumped AST """ dumped = ast.dump(node, annotate_fields, include_attributes) try: import black return black.format_str(dumped, mode=black.FileMode()) except ImportError: raise RuntimeError("Black is required to use ast_pretty_dump(). " "Try `python -m pip install -U black` to install.") except AttributeError: # FIXME remove version incompatible check after black publishes the first # stable version. raise RuntimeError("black version incompatible")
def main(): import argparse from sys import stderr, stdin, stdout try: import black black_available = True except ImportError: black_available = False parser = argparse.ArgumentParser(description=__doc__, epilog=__author__) parser.add_argument( "src", nargs="*", type=argparse.FileType("r"), default=[stdin], help="xml file(s) to process (default stdin)", ) parser.add_argument( "--out", type=argparse.FileType("w"), default=stdout, help="filename to write to in single-file mode (default stdout)", ) parser.add_argument("--dir", help="directory to write to in multi-file mode") args = parser.parse_args() if args.dir and not (path.exists(args.dir) and path.isdir(args.dir)): print("%s: no such directory" % args.dir, file=stderr) return 1 results = {} for f in args.src: results = {**results, **render_template(f)} if black_available: fm = black.FileMode() results = {k: black.format_str(v, mode=fm) for k, v in results.items()} if args.dir: write_to_dir(results, args.dir) else: filecontents = "\n\n".join(results.values()) args.out.write(filecontents)
def pretty_print(self, params=FormatParams(), import_column=None, from_spaces=1): """ Pretty-print into a single string. :type params: `FormatParams` :param modulename_ljust: Number of characters to left-justify the 'from' name. :rtype: ``str`` """ s0 = '' s = '' assert from_spaces >= 1 if self.fromname is not None: s += "from%s%s " % (' ' * from_spaces, self.fromname) if import_column is not None: if len(s) > import_column: # The caller wants the 'import' statement lined up left of # where the current end of the line is. So wrap it # specially like this:: # from foo import ... # from foo.bar.baz \ # import ... s0 = s + '\\\n' s = ' ' * import_column else: s = s.ljust(import_column) s += "import " tokens = [] for importname, asname in self.aliases: if asname is not None: t = "%s as %s" % (importname, asname) else: t = "%s" % (importname, ) tokens.append(t) res = s0 + pyfill(s, tokens, params=params) if params.use_black: import black mode = black.FileMode() return black.format_str(res, mode=mode) return res
def format_code(self, code: str, **options) -> str: import black has_semicolon = code.strip().endswith(";") code = re.sub("^%", "#%#", code, flags=re.M) if black.__version__ >= '19.3b0': code = black.format_str(code, mode=black.FileMode(**options))[:-1] else: code = black.format_str(code, **options)[:-1] code = re.sub("^#%#", "%", code, flags=re.M) if has_semicolon: code += ";" return code
def __init__(self, order_callback=None, pre_block_hooks=None, formatters=None): if pre_block_hooks is None: pre_block_hooks = [] if formatters is None: # these are defaults; use formatter=[] to get no formatting formatters = [ BlackFormatter(black.FileMode()), ISortFormatter(), ] self.order_callback = order_callback self.pre_block_hooks = pre_block_hooks self.formatters = formatters self.instances = []