def read_configuration(self) -> Configuration: """Search for a configuration file and validate it against a Marshmallow schema.""" config_file: Path | None = None for possible_file in CONFIG_FILES: path: Path = self.root / possible_file if not path.exists(): continue if not config_file: logger.info(f"Config file: reading from {path}") config_file = path else: logger.warning(f"Config file: ignoring existing {path}") if not config_file: logger.warning("Config file: none found") return Configuration(None, [], "") toml_doc = TomlDoc(path=config_file) config_dict = search_json(toml_doc.as_object, TOOL_NITPICK_JMEX, {}) validation_errors = ToolNitpickSectionSchema().validate(config_dict) if not validation_errors: return Configuration(config_file, config_dict.get("style", []), config_dict.get("cache", "")) # pylint: disable=import-outside-toplevel from nitpick.plugins.info import FileInfo raise QuitComplainingError( Reporter(FileInfo(self, PYPROJECT_TOML)).make_fuss( StyleViolations.INVALID_DATA_TOOL_NITPICK, flatten_marshmallow_errors(validation_errors), section=TOOL_NITPICK_KEY, ))
def merge_styles(self, offline: bool) -> Iterator[Fuss]: """Merge one or multiple style files.""" config = self.read_configuration() # pylint: disable=import-outside-toplevel from nitpick.style import StyleManager style = StyleManager(self, offline, config.cache) base = config.file.expanduser().resolve().as_uri( ) if config.file else None style_errors = list( style.find_initial_styles(peekable(always_iterable(config.styles)), base)) if style_errors: raise QuitComplainingError(style_errors) self.style_dict = style.merge_toml_dict() from nitpick.flake8 import NitpickFlake8Extension minimum_version = search_json(self.style_dict, NITPICK_MINIMUM_VERSION_JMEX, None) logger.debug(f"Minimum version: {minimum_version}") if minimum_version and version_to_tuple( NitpickFlake8Extension.version) < version_to_tuple( minimum_version): yield Reporter().make_fuss( ProjectViolations.MINIMUM_VERSION, project=PROJECT_NAME, expected=minimum_version, actual=NitpickFlake8Extension.version, ) self.nitpick_section = self.style_dict.get("nitpick", {}) self.nitpick_files_section = self.nitpick_section.get("files", {})
def _include_style(self, style_url: furl) -> Iterator[Fuss]: if style_url.url in self._already_included: return self._already_included.add(style_url.url) file_contents = self._style_fetcher_manager.fetch(style_url) if file_contents is None: return # generate a 'human readable' version of the URL; a relative path for local files # and the URL otherwise. display_name = style_url.url if style_url.scheme == "file": path = furl_path_to_python_path(style_url.path) with suppress(ValueError): path = path.relative_to(self.project.root) display_name = str(path) read_toml_dict = self._read_toml(file_contents, display_name) # normalize sub-style URIs, before merging sub_styles = [ self._style_fetcher_manager.normalize_url(ref, style_url) for ref in always_iterable( search_json(read_toml_dict, NITPICK_STYLES_INCLUDE_JMEX, [])) ] if sub_styles: read_toml_dict.setdefault("nitpick", {}).setdefault( "styles", {})["include"] = [str(url) for url in sub_styles] toml_dict, validation_errors = self._config_validator.validate( read_toml_dict) if validation_errors: yield Reporter(FileInfo(self.project, display_name)).make_fuss( StyleViolations.INVALID_CONFIG, flatten_marshmallow_errors(validation_errors)) dpath.util.merge(self._merged_styles, flatten(toml_dict, custom_reducer(SEPARATOR_FLATTEN))) yield from self.include_multiple_styles(sub_styles)
def find(expression): """Find with JMESpath.""" print(f"\nExpression: {expression}") rv = search_json(workflow.as_object, jmespath.compile(expression), {}) print(f"Type: {type(rv)}") pprint(rv)
def nitpick_file_dict(self) -> JsonDict: """Nitpick configuration for this file as a TOML dict, taken from the style file.""" return search_json(self.info.project.nitpick_section, f'files."{self.filename}"', {})