Skip to content

Commit

Permalink
Merge pull request #41 from eeintech/units_symbol_id
Browse files Browse the repository at this point in the history
Added support for updating children units symbol ID
  • Loading branch information
mvnmgrx committed Feb 14, 2023
2 parents ec6546f + 0fab0de commit b854781
Show file tree
Hide file tree
Showing 5 changed files with 10,331 additions and 3 deletions.
56 changes: 54 additions & 2 deletions src/kiutils/symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from dataclasses import dataclass, field
from typing import Optional, List
from os import path
import re

from kiutils.items.common import Effects, Position, Property, Font
from kiutils.items.syitems import *
Expand Down Expand Up @@ -189,10 +190,55 @@ class Symbol():
https://dev-docs.kicad.org/en/file-formats/sexpr-intro/index.html#_symbols
"""

id: str = ""
"""Each symbol must have a unique "LIBRARY_ID" for each top level symbol in the library or a unique
"UNIT_ID" for each unit embedded in a parent symbol. Library identifiers are only valid it top
level symbols and unit identifiers are on valid as unit symbols inside a parent symbol."""
@property
def id(self):
unit_style_ids = f"_{self.unitId}_{self.styleId}" if (self.unitId is not None and self.styleId is not None) else ""
if self.libraryNickname:
return f'{self.libraryNickname}:{self.entryName}{unit_style_ids}'
else:
return f'{self.entryName}{unit_style_ids}'

@id.setter
def id(self, symbol_id):
# Split library id into nickname, entry name, unit id and style id (if any)
parse_symbol_id = re.match(r"^(.+?):(.+?)_(\d+?)_(\d+?)$", symbol_id)
if parse_symbol_id:
self.libraryNickname = parse_symbol_id.group(1)
self.entryName = parse_symbol_id.group(2)
self.unitId = int(parse_symbol_id.group(3))
self.styleId = int(parse_symbol_id.group(4))
else:
parse_symbol_id = re.match(r"^(.+?):(.+?)$", symbol_id)
if parse_symbol_id:
self.libraryNickname = parse_symbol_id.group(1)
entryName_t = parse_symbol_id.group(2)
else:
entryName_t = symbol_id

parse_symbol_id = re.match(r"^(.+?)_(\d+?)_(\d+?)$", entryName_t)
if parse_symbol_id:
self.entryName = parse_symbol_id.group(1)
self.unitId = int(parse_symbol_id.group(2))
self.styleId = int(parse_symbol_id.group(3))
else:
if self.libraryNickname:
self.entryName = entryName_t
else:
self.entryName = symbol_id

# Update units id to match parent id
for unit in self.units:
unit.entryName = self.entryName

libraryNickname: Optional[str] = None
entryName: str = None
""" The schematic symbol library and printed circuit board footprint library file formats use library identifiers.
Library identifiers are defined as a quoted string using the "LIBRARY_NICKNAME:ENTRY_NAME" format where
"LIBRARY_NICKNAME" is the nickname of the library in the symbol or footprint library table and
"ENTRY_NAME" is the name of the symbol or footprint in the library separated by a colon. """

extends: Optional[str] = None
"""The optional `extends` token attribute defines the "LIBRARY_ID" of another symbol inside the
Expand Down Expand Up @@ -243,9 +289,15 @@ class Symbol():
units: List = field(default_factory=list)
"""The `units` can be one or more child symbol tokens embedded in a parent symbol"""

unitId: Optional[int] = None
"""Unit identifier: an integer that identifies which unit the symbol represents"""

styleId: Optional[int] = None
"""Style identifier: indicates which body style the unit represents"""

@classmethod
def from_sexpr(cls, exp: list):
"""Convert the given S-Expresstion into a Symbol object
"""Convert the given S-Expression into a Symbol object
Args:
exp (list): Part of parsed S-Expression `(symbol ...)`
Expand Down
20 changes: 19 additions & 1 deletion tests/test_symbol.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def test_createNewSymbolInEmptyLibrary(self):
self.testData.compareToTestFile = True
self.testData.pathToTestFile = path.join(SYMBOL_BASE, 'test_createNewSymbolInEmptyLibrary')

# Create an empty symbol libraray
# Create an empty symbol library
symbolLib = SymbolLib(
version = KIUTILS_CREATE_NEW_VERSION_STR,
generator = 'kiutils'
Expand All @@ -88,3 +88,21 @@ def test_createNewSymbolInEmptyLibrary(self):

self.assertTrue(to_file_and_compare(symbolLib, self.testData))

def test_renameSymbol(self):
"""Rename symbol inside library and verify all units are also renamed"""
self.testData.compareToTestFile = True
self.testData.pathToTestFile = path.join(SYMBOL_BASE, 'test_renameSymbol')
symbolLib = SymbolLib().from_file(path.join(SYMBOL_BASE, 'test_symbolDemorganSyItems'))
symbol = symbolLib.symbols[0]
symbol.id = 'AD1853JRS'
self.assertTrue(to_file_and_compare(symbolLib, self.testData))

def test_mergeLibraries(self):
"""Merge two symbol libraries together"""
self.testData.compareToTestFile = True
self.testData.pathToTestFile = path.join(SYMBOL_BASE, 'test_mergedLibraries')
symbolLib1 = SymbolLib().from_file(path.join(SYMBOL_BASE, 'test_analogDACs'))
symbolLib2 = SymbolLib().from_file(path.join(SYMBOL_BASE, 'test_symbolDemorganSyItems'))
for symbol in symbolLib2.symbols:
symbolLib1.symbols.insert(0, symbol)
self.assertTrue(to_file_and_compare(symbolLib1, self.testData))

0 comments on commit b854781

Please sign in to comment.