diff --git a/k2t.py b/k2t.py index cb8abad..11311cb 100644 --- a/k2t.py +++ b/k2t.py @@ -1,9 +1,84 @@ +""" +Functions from converting between KLayout layer properties files and a custom TOML format +""" from typing import Self, Type, Any import tomllib from dataclasses import dataclass, fields from xml.etree import ElementTree +def k2t(kfile: str, tfile: str) -> None: + """ + Convert from KLayout layer properties xml (.lyp) to TOML + + Args: + kfile: Path to klayout lyp file (input) + tfile: Path for TOML file (output) + """ + tree = ElementTree.parse(kfile) + root = tree.getroot() + + assert root.tag == 'layer-properties' + name = None + entries = [] + patterns = [] + linestyles = [] + for child in root: + if child.tag == 'custom-dither-pattern': + patterns.append(Pattern.from_xml(child)) + elif child.tag == 'custom-line-style': + linestyles.append(LineStyle.from_xml(child)) + elif child.tag == 'properties': + entries.append(Entry.from_xml(child)) + elif child.tag == 'name': + name = child.text + else: + raise Exception(f'Unexpected tag: {child.tag}') + + if name is not None: + print(f'Discarding tab name: {name}') + + with open(tfile, 'wt') as ff: + for entry in entries: + ff.write(entry.to_toml()) + for pattern in patterns: + ff.write(pattern.to_toml()) + for linestyle in linestyles: + ff.write(linestyle.to_toml()) + + +def t2k(tfile: str, kfile: str) -> None: + """ + Convert from TOML to KLayout layer properties xml (.lyp) + + Args: + tfile: Path to TOML file (input) + kfile: Path for klayout lyp file (output) + """ + root = ElementTree.Element('layer-properties') + + with open(tfile, 'rb') as ff: + ttree = tomllib.load(ff) + + entries = [Entry.from_toml(entry) + for entry in ttree['layers']] + patterns = [Pattern.from_toml(pat) + for pat in ttree['patterns']] + linestyles = [LineStyle.from_toml(ls) + for ls in ttree['linestyles']] + + for entry in entries: + root.append(entry.to_xml()) + for pattern in patterns: + root.append(pattern.to_xml()) + for linestyle in linestyles: + root.append(linestyle.to_xml()) + + ktree = ElementTree.ElementTree(root) + ElementTree.indent(ktree) + ktree.write(kfile) + + @dataclass(slots=True) class Entry: name: str @@ -272,63 +347,5 @@ class LineStyle: return cls(**tree) -def k2t(kfile: str, tfile: str) -> None: - tree = ElementTree.parse(kfile) - root = tree.getroot() - - assert root.tag == 'layer-properties' - name = None - entries = [] - patterns = [] - linestyles = [] - for child in root: - if child.tag == 'custom-dither-pattern': - patterns.append(Pattern.from_xml(child)) - elif child.tag == 'custom-line-style': - linestyles.append(LineStyle.from_xml(child)) - elif child.tag == 'properties': - entries.append(Entry.from_xml(child)) - elif child.tag == 'name': - name = child.text - else: - raise Exception(f'Unexpected tag: {child.tag}') - - if name is not None: - print(f'Discarding tab name: {name}') - - with open(tfile, 'wt') as ff: - for entry in entries: - ff.write(entry.to_toml()) - for pattern in patterns: - ff.write(pattern.to_toml()) - for linestyle in linestyles: - ff.write(linestyle.to_toml()) - - -def t2k(tfile: str, kfile: str) -> None: - root = ElementTree.Element('layer-properties') - - with open(tfile, 'rb') as ff: - ttree = tomllib.load(ff) - - entries = [Entry.from_toml(entry) - for entry in ttree['layers']] - patterns = [Pattern.from_toml(pat) - for pat in ttree['patterns']] - linestyles = [LineStyle.from_toml(ls) - for ls in ttree['linestyles']] - - for entry in entries: - root.append(entry.to_xml()) - for pattern in patterns: - root.append(pattern.to_xml()) - for linestyle in linestyles: - root.append(linestyle.to_xml()) - - ktree = ElementTree.ElementTree(root) - ElementTree.indent(ktree) - ktree.write(kfile) - - def toml_escape(string: str) -> str: return string.replace('\\', '\\\\').replace('"', '\\"')