nodeslicer/infra/prusaslicer_profiles/models.py

76 lines
2.6 KiB
Python

from __future__ import annotations
import tempfile
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, TYPE_CHECKING
if TYPE_CHECKING:
from .parser import ExprNode
@dataclass
class Profile:
key: str
category: str
path: Path
has_header: bool
conf_dict: dict[str, Any]
id: str = field(init=False)
vendor: str = ""
all_conf_dict: dict[str, Any] = field(default_factory=dict)
compatible_profiles: list[str] = field(default_factory=list)
compatibility_expression: ExprNode | None = None
def __post_init__(self):
self.id = self.key.split(':')[1] if len(self.key.split(':')) > 1 else self.key
def evaluate_compatibility(self, compats: dict[str, ExprNode | None]):
self.compatible_profiles = []
if self.category.startswith('printer:'):
return
for key, compat in compats.items():
if not compat:
self.compatible_profiles.append(key)
continue
if compat.eval(self.all_conf_dict):
self.compatible_profiles.append(key)
print(f'Evaled {self.id}')
def generate_inherited_confs(self, all_profiles: dict[str, Profile]):
from .utils import generate_conf
from .parser import Parser
self.all_conf_dict = generate_conf(all_profiles, self.key)
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(',')))
self.vendor = self.all_conf_dict.get('filament_vendor', '')
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}')
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():
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