""" Types representing entities of GNU PCB files. """ import collections class Coordinate(): """ A coordinate in a PCB file. """ MIL = 1e2 MM = 1e5 / 25.4 def __init__(self, raw: float = 0): self._raw = round(raw) def __repr__(self) -> str: return f'Coordinate({self._raw:d})' def _compare(self, other) -> int: if not isinstance(other, Coordinate): raise ValueError(f'{type(self).__name__:s} cannot be' f' compared to {type(other).__name__:s}') if self._raw < other._raw: return -1 if self._raw > other._raw: return 1 return 0 def __eq__(self, other) -> bool: return self._compare(other) == 0 def __ne__(self, other) -> bool: return self._compare(other) != 0 def __lt__(self, other) -> bool: return self._compare(other) < 0 def __le__(self, other) -> bool: return self._compare(other) <= 0 def __gt__(self, other) -> bool: return self._compare(other) > 0 def __ge__(self, other) -> bool: return self._compare(other) >= 0 def __add__(self, other): assert isinstance(other, Coordinate) return Coordinate(self._raw + other._raw) def __mul__(self, other): return Coordinate(self._raw * other) def __neg__(self): return Coordinate(-self._raw) def __sub__(self, other): assert isinstance(other, Coordinate) return Coordinate(self._raw - other._raw) def __truediv__(self, other): return Coordinate(self._raw / other) @property def mil(self) -> float: return self._raw / self.MIL @mil.setter def mil(self, mil: float): self._raw = round(mil * self.MIL) @property def mm(self) -> float: return self._raw / self.MM @mm.setter def mm(self, mm: float): self._raw = round(mm * self.MM) @property def raw(self) -> int: return self._raw @raw.setter def raw(self, raw: float): self._raw = round(raw) class Struct: """ Base class for struct-like Python objects """ _attrs = collections.OrderedDict() # attribute name: str -> default value def __init__(self, **kwargs): for name, def_val in self._attrs.items(): setattr(self, name, def_val) for name, val in kwargs.items(): if name not in self._attrs: raise ValueError( f'{type(self).__name__:s} does not have attribute {name:s}' ) setattr(self, name, val) def __repr__(self) -> str: vals = ', '.join([ f'{name:s}={repr(getattr(self, name)):s}' for name in self._attrs.keys() ]) return f'{type(self).__name__:s}({vals:s})' def _compare(self, other) -> int: if self._attrs != other._attrs: raise ValueError(f'{type(self).__name__:s} cannot be' f' compared to {type(other).__name__:s}') for name in self._attrs: s = getattr(self, name) o = getattr(other, name) if s < o: return -1 if s > o: return 1 return 0 def __eq__(self, other) -> bool: return self._compare(other) == 0 def __ne__(self, other) -> bool: return self._compare(other) != 0 def __lt__(self, other) -> bool: return self._compare(other) < 0 def __le__(self, other) -> bool: return self._compare(other) <= 0 def __gt__(self, other) -> bool: return self._compare(other) > 0 def __ge__(self, other) -> bool: return self._compare(other) >= 0 class Element(Struct): """ Element entity in a GNU PCB file. """ _attrs = collections.OrderedDict([ # attributes ('s_flags', []), ('desc', ''), ('name', ''), ('value', ''), ('m_x', Coordinate(0)), ('m_y', Coordinate(0)), ('t_x', Coordinate(0)), ('t_y', Coordinate(0)), ('t_dir', 0), ('t_scale', 0.0), ('t_s_flags', []), ('body', []) ]) def __init__(self, **kwargs): super().__init__(**kwargs) class ElementArc(Struct): """ ElementArc entity in a GNU PCB file. """ _attrs = collections.OrderedDict([ # attributes ('r_x', Coordinate(0)), ('r_y', Coordinate(0)), ('width', Coordinate(0)), ('height', Coordinate(0)), ('start_angle', 0.0), ('end_angle', 0.0), ('thickness', Coordinate(0)) ]) def __init__(self, **kwargs): super().__init__(**kwargs) class ElementLine(Struct): """ ElementLine entity in a GNU PCB file. """ _attrs = collections.OrderedDict([ # attributes ('r_x1', Coordinate(0)), ('r_y1', Coordinate(0)), ('r_x2', Coordinate(0)), ('r_y2', Coordinate(0)), ('thickness', Coordinate(0)) ]) def __init__(self, **kwargs): super().__init__(**kwargs) class Pad(Struct): """ Pad entity in a GNU PCB file. """ _attrs = collections.OrderedDict([ # attributes ('r_x1', Coordinate(0)), ('r_y1', Coordinate(0)), ('r_x2', Coordinate(0)), ('r_y2', Coordinate(0)), ('thickness', Coordinate(0)), ('clearance', Coordinate(0)), ('mask', Coordinate(0)), ('name', ''), ('number', ''), ('s_flags', []), ]) def __init__(self, **kwargs): super().__init__(**kwargs) class Pin(Struct): """ Pin entity in a GNU PCB file. """ _attrs = collections.OrderedDict([ # attributes ('r_x', Coordinate(0)), ('r_y', Coordinate(0)), ('thickness', Coordinate(0)), ('clearance', Coordinate(0)), ('mask', Coordinate(0)), ('drill', Coordinate(0)), ('name', ''), ('number', ''), ('s_flags', []), ]) def __init__(self, **kwargs): super().__init__(**kwargs)