from __future__ import annotations import tempfile from pathlib import Path from typing import Any, TYPE_CHECKING if TYPE_CHECKING: from .parser import ExprNode class Profile: def __init__( self, key: str, category: str, path: Path, has_header: bool, conf_dict: dict[str, Any] ): self.key = key self.category = category self.path = path self.has_header = has_header self.conf_dict = conf_dict self.id = self.key.split(':')[1] if len(self.key.split(':')) > 1 else self.key self.vendor = "" self.all_conf_dict: dict[str, Any] = {} self.compatibility_expression: ExprNode | None = None self.compatible_profiles: list[Profile] = [] @property def compatible_print_profiles(self) -> list[Profile]: return [k for k in self.compatible_profiles if k.category == 'print'] @property def compatible_filament_profiles(self) -> list[Profile]: return [k for k in self.compatible_profiles if k.category == 'filament'] def generate_inherited_conf(self, all_profiles: dict[str, Profile]): """Calculates the full configuration dictionary by resolving inheritance.""" from .utils import generate_conf from .parser import Parser self.all_conf_dict = generate_conf(all_profiles, self.key) self.vendor = self.all_conf_dict.get('filament_vendor', '') if self.category == 'printer': nozzle_diameters = self.all_conf_dict.get('nozzle_diameter', '0.4') self.all_conf_dict['num_extruders'] = str(len(nozzle_diameters.split(','))) if exp := self.all_conf_dict.get('compatible_printers_condition'): try: self.compatibility_expression = Parser(exp).parse() except Exception as e: print(f'Expression parsing failed for {self.id}: {exp} - {e}') def evaluate_compatibility(self, profiles: dict[str, Profile]): """Checks which of the provided profiles are compatible with this one.""" self.compatible_profiles = [] for key, p in profiles.items(): compat = p.compatibility_expression if not compat or compat.eval(self.all_conf_dict): self.compatible_profiles += [p] class ConfigWriter: def __init__(self, conf: dict[str, str | list[str]]) -> None: self.config_dict: dict[str, str | list[str]] = conf self.temp_dir = tempfile.gettempdir() def write_ini_3mf(self, config_local_path: Path): with open(config_local_path, 'w') as file: for key, val in dict(sorted(self.config_dict.items())).items(): if key == "wipe_tower_position": continue file.write(f"; {key} = {val}\n") def get(self, key: str, default: str = "") -> str | list[str]: return self.config_dict.get(key, default) @property def checksum(self) -> int: import json, zlib data = json.dumps(self.config_dict, sort_keys=True).encode("utf-8") return zlib.crc32(data) & 0xFFFFFFFF