From fe0120ef64a924268095ccdffe319c5c59579df3 Mon Sep 17 00:00:00 2001 From: Saumya Jain Date: Fri, 5 Apr 2024 18:18:40 +0200 Subject: [PATCH] Add Formulas linter and integrate with factory A new linter class, Formulas, has been added to check for issues in definition files, particularly with default parameters overrides. It has been integrated into the Linter factory to also check '.inst.cfg' and '.def.json' files for formulas-related issues. Additionally, a new 'diagnostic-incorrect-formula' check has been included in the .printer-linter configuration. CURA-10901 --- .printer-linter | 1 + printer-linter/src/printerlinter/factory.py | 5 +- .../src/printerlinter/linters/formulas.py | 81 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 printer-linter/src/printerlinter/linters/formulas.py diff --git a/.printer-linter b/.printer-linter index 3a42a5c033..4f643ebd95 100644 --- a/.printer-linter +++ b/.printer-linter @@ -3,6 +3,7 @@ checks: diagnostic-mesh-file-size: true diagnostic-definition-redundant-override: true diagnostic-resources-macos-app-directory-name: true + diagnostic-incorrect-formula: true fixes: diagnostic-definition-redundant-override: true format: diff --git a/printer-linter/src/printerlinter/factory.py b/printer-linter/src/printerlinter/factory.py index 4473fb9a4e..20ee19dee4 100644 --- a/printer-linter/src/printerlinter/factory.py +++ b/printer-linter/src/printerlinter/factory.py @@ -6,6 +6,7 @@ from .linters.defintion import Definition from .linters.linter import Linter from .linters.meshes import Meshes from .linters.directory import Directory +from .linters.formulas import Formulas def getLinter(file: Path, settings: dict) -> Optional[List[Linter]]: @@ -14,12 +15,12 @@ def getLinter(file: Path, settings: dict) -> Optional[List[Linter]]: return None if ".inst" in file.suffixes and ".cfg" in file.suffixes: - return [Directory(file, settings), Profile(file, settings)] + return [Directory(file, settings), Profile(file, settings), Formulas(file, settings)] if ".def" in file.suffixes and ".json" in file.suffixes: if file.stem in ("fdmprinter.def", "fdmextruder.def"): return None - return [Directory(file, settings), Definition(file, settings)] + return [Directory(file, settings), Definition(file, settings), Formulas(file, settings)] if file.parent.stem == "meshes": return [Meshes(file, settings)] diff --git a/printer-linter/src/printerlinter/linters/formulas.py b/printer-linter/src/printerlinter/linters/formulas.py new file mode 100644 index 0000000000..c4b0b9d69a --- /dev/null +++ b/printer-linter/src/printerlinter/linters/formulas.py @@ -0,0 +1,81 @@ +import json +import re +from pathlib import Path +from typing import Iterator + +from ..diagnostic import Diagnostic +from .linter import Linter +from configparser import ConfigParser +from ..replacement import Replacement + + +class Formulas(Linter): + """ Finds issues in definition files, such as overriding default parameters """ + def __init__(self, file: Path, settings: dict) -> None: + super().__init__(file, settings) + self._definition = {} + + + def check(self) -> Iterator[Diagnostic]: + if self._settings["checks"].get("diagnostic-incorrect-formula", False): + for check in self.checkFormulas(): + yield check + + yield + + def checkFormulas(self) -> Iterator[Diagnostic]: + + self._loadDefinitionFiles(self._file) + self._content = self._file.read_text() + definition_name = list(self._definition.keys())[0] + definition = self._definition[definition_name] + if "overrides" in definition: + for key, value_dict in definition["overrides"].items(): + for value in value_dict: + if value in ("enable", "resolve", "value", "minimum_value_warning", "maximum_value_warning", "maximum_value", "minimum_value"): + value_incorrect = self.checkValueIncorrect() + if value_incorrect: + + yield Diagnostic( + file=self._file, + diagnostic_name="diagnostic-incorrect-formula", + message=f"Given formula {value_dict} to calulate {key} of seems incorrect, please correct the formula and try again.", + level="Error", + offset=1 + ) + yield + + def _loadDefinitionFiles(self, definition_file) -> None: + """ Loads definition file contents into self._definition. Also load parent definition if it exists. """ + definition_name = Path(definition_file.stem).stem + + if not definition_file.exists() or definition_name in self._definition: + return + + if definition_file.suffix == ".json": + # Load definition file into dictionary + self._definition[definition_name] = json.loads(definition_file.read_text()) + + if definition_file.suffix == ".cfg": + self._definition[definition_name] = self.parse_cfg(definition_file) + + + def parse_cfg(self, file_path:Path) -> dict: + config = ConfigParser() + config.read([file_path]) + file_data ={} + overrides = {} + + available_sections = ["values"] + for section in available_sections: + options = config.options(section) + for option in options: + values ={} + values["value"] = config.get(section, option) + overrides[option] = values + file_data["overrides"]= overrides# Process the value here + + return file_data + + def checkValueIncorrect(self): + return True