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