Source code for medikit.feature.format

"""
Code formating, using third party tools.

Superseeds "yapf" feature that was only using one tool for one language.

.. code-block:: shell-session

    $ make format

"""
import functools
import os

import medikit
from medikit import settings
from medikit.events import subscribe
from medikit.feature import ABSOLUTE_PRIORITY, SUPPORT_PRIORITY, Feature
from medikit.feature.make import which
from medikit.globals import LINE_LENGTH
from medikit.structs import Script


[docs]class FormatConfig(Feature.Config): python_tools = {"yapf", "black", "isort"} javascript_tools = {"prettier"} default_tools = {"black", "isort"} all_tools = functools.reduce(set.union, [javascript_tools, python_tools], set()) _active_tools = set()
[docs] def using(self, *tools): """ Choose which tool to use when formatting the codebase. Example:: require("format").using("yapf", "isort") Note that the above is also the default, so using `require("format")` is enough to have the same effect. """ for tool in tools: if tool not in self.all_tools: raise ValueError('Unknown formating tool "{}".'.format(tool)) self._active_tools.add(tool)
@property def active_tools(self): return self._active_tools or self.default_tools
[docs]class FormatFeature(Feature): Config = FormatConfig conflicts = {"yapf"}
[docs] @subscribe("medikit.feature.python.on_generate") def on_python_generate(self, event): config = self.get_config(event) # type: FormatConfig python = self.get_config(event, "python") for tool in FormatConfig.python_tools: if tool == "black": # Black is only available starting with python 3.6, it will be up to the user to install it. continue if tool in config.active_tools: python.add_requirements(dev=[tool])
[docs] @subscribe("medikit.feature.make.on_generate", priority=SUPPORT_PRIORITY) def on_make_generate(self, event): config = self.get_config(event) # type: FormatConfig makefile = event.makefile if "yapf" in config.active_tools and "black" in config.active_tools: raise RuntimeError('Using both "black" and "yapf" does not make sense, choose one.') format_script = [] if "black" in config.active_tools: makefile["BLACK"] = which("black") makefile["BLACK_OPTIONS"] = "--line-length " + str(LINE_LENGTH) # TODO line length global option format_script += ["$(BLACK) $(BLACK_OPTIONS) . Projectfile"] if "yapf" in config.active_tools: makefile["YAPF"] = "$(PYTHON) -m yapf" makefile["YAPF_OPTIONS"] = "-rip" format_script += ["$(YAPF) $(YAPF_OPTIONS) . Projectfile"] if "isort" in config.active_tools: makefile["ISORT"] = "$(PYTHON) -m isort" makefile["ISORT_OPTIONS"] = "" format_script += ["$(ISORT) $(ISORT_OPTIONS) . Projectfile"] if "prettier" in config.active_tools: makefile["PRETTIER"] = which("prettier") makefile["PRETTIER_OPTIONS"] = "--write" makefile["PRETTIER_PATTERNS"] = "**/*.\{j,t\}s **/*.\{j,t\}sx \!docs/**" format_script += ["$(PRETTIER) $(PRETTIER_OPTIONS) $(PRETTIER_PATTERNS)"] makefile.add_target( "format", Script("\n".join(format_script)), deps=("install-dev",), phony=True, doc="Reformats the codebase (with " + ", ".join(sorted(config.active_tools)) + ").", )
[docs] @subscribe(medikit.on_start, priority=SUPPORT_PRIORITY) def on_start(self, event): config = self.get_config(event) # type: FormatConfig if "isort" in config.active_tools: with event.config.get_resource("setup.cfg") as setup_cfg: setup_cfg.set_managed_values({"isort": {"line_length": str(LINE_LENGTH)}}) if "yapf" in config.active_tools: self.render_file(".style.yapf", "yapf/style.yapf.j2")
[docs] @subscribe(medikit.on_start, priority=ABSOLUTE_PRIORITY - 1) def on_before_start(self, event): config = self.get_config(event) # type: FormatConfig if "yapf" in config.active_tools: style_config = os.path.join(os.getcwd(), ".style.yapf") if os.path.exists(style_config): self.dispatcher.info("YAPF_STYLE_CONFIG = " + style_config) settings.YAPF_STYLE_CONFIG = style_config