Skip to content

Instantly share code, notes, and snippets.

@jbweber
Created March 6, 2025 11:25
Show Gist options
  • Save jbweber/b162a782ab70b9fbb6e3c37bafc0bdba to your computer and use it in GitHub Desktop.
Save jbweber/b162a782ab70b9fbb6e3c37bafc0bdba to your computer and use it in GitHub Desktop.
import argparse
import glob
import json
import os
import platform
from pathlib import Path
def parse_json_file(path):
with open(path, "r", encoding="utf-8") as json_file:
return json.load(json_file)
def get_orca_slicer_config_path():
if platform.system() == "Windows":
return Path.home() / "AppData" / "Roaming" / "OrcaSlicer"
if platform.system() == "Linux":
return Path.home() / ".conf" / "OrcaSlicer"
if platform.system() == "Darwin":
return Path.home() / "Library" / "Application Support" / "OrcaSlicer"
return None
def load_system_data():
orca_slicer_config_path = get_orca_slicer_config_path()
system_files = glob.glob(str(orca_slicer_config_path / "system" / "*.json"))
system_data = {}
for system_file in system_files:
system_file_data = parse_json_file(system_file)
key = os.path.basename(system_file).split('.')[0]
system_data[key] = system_file_data
return (orca_slicer_config_path, system_data)
def merge_filament(orca_system_path, orca_system_data, filament_path):
filament_profile = parse_json_file(filament_path)
profiles = [filament_profile]
next_base = None
while True:
previous_profile = profiles[-1]
next_profile = get_parent_filament(orca_system_path, orca_system_data, previous_profile, next_base)
if next_profile is None:
break
profiles.append(next_profile[1])
next_base = next_profile[0]
# ignore some keys, this may not be right
merged_profile = {}
ignore = ["inherits", "from", "filament_id", "setting_id", "instantiation", "is_custom_defined"]
while len(profiles) > 0:
to_merge = profiles.pop()
filtered = to_merge
filtered = {k: v for k, v in to_merge.items() if k not in ignore}
merged_profile = {**merged_profile, **filtered}
return merged_profile
def find_filament(data, input, limit):
results = []
for key in data.keys():
if limit and key != limit:
continue
for i in data[key]['filament_list']:
if i['name'] == input:
results.append((key, i))
return results
def get_parent_filament(orca_system_path, library, current, base):
parent = current.get("inherits", None)
if not parent:
return None
filaments = find_filament(library, parent, base)
if len(filaments) != 1:
raise Exception("more than one option found, fix logic")
filament_base = filaments[0][0]
filaments_path = filaments[0][1]['sub_path']
with open(str(orca_system_path / filament_base / filaments_path)) as f:
return (filament_base, json.load(f))
def merge_process(orca_system_path, orca_system_data, process_path):
process_profile = parse_json_file(process_path)
profiles = [process_profile]
next_base = None
while True:
previous_profile = profiles[-1]
next_profile = get_parent_process(orca_system_path, orca_system_data, previous_profile, next_base)
if next_profile is None:
break
profiles.append(next_profile[1])
next_base = next_profile[0]
# ignore some keys, this may not be right
merged_profile = {}
ignore = ["inherits", "from", "print_settings_id", "setting_id", "instantiation", "is_custom_defined"]
while len(profiles) > 0:
to_merge = profiles.pop()
filtered = to_merge
filtered = {k: v for k, v in to_merge.items() if k not in ignore}
merged_profile = {**merged_profile, **filtered}
return merged_profile
def find_process(data, input, limit):
results = []
for key in data.keys():
if limit and key != limit:
continue
process_list = data[key].get('process_list')
if not process_list:
continue
for i in process_list:
if i['name'] == input:
results.append((key, i))
return results
def get_parent_process(orca_system_path, library, current, base):
parent = current.get("inherits", None)
if not parent:
return None
processes = find_process(library, parent, base)
if len(processes) != 1:
raise Exception("more than one option found, fix logic")
process_base = processes[0][0]
process_path = processes[0][1]['sub_path']
with open(str(orca_system_path / process_base / process_path)) as f:
return (process_base, json.load(f))
def main():
parser = argparse.ArgumentParser(description="explore orca configurations")
parser.add_argument("path", type=Path, help="path to configuration")
# probably a better way to figure this out, but who knows right now
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-f", "--filament", action="store_true", help="lookup filament")
group.add_argument("-p", "--process", action="store_true", help="lookup process")
args = parser.parse_args()
if not args.path.exists():
print(f"Error: configuration file '{args.path}' does not exist.")
return
if not args.path.is_file():
print(f"Error: '{args.path}' is not a file")
(orca_slicer_config_path, orca_slicer_system_data) = load_system_data()
if args.filament:
data = merge_filament(orca_slicer_config_path / "system", orca_slicer_system_data, args.path)
print(json.dumps(dict(sorted(data.items())), indent=2))
if args.process:
data = merge_process(orca_slicer_config_path / "system", orca_slicer_system_data, args.path)
print(json.dumps(dict(sorted(data.items())), indent=2))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment