aboutsummaryrefslogtreecommitdiff
path: root/src/ee/kicad
diff options
context:
space:
mode:
Diffstat (limited to 'src/ee/kicad')
-rw-r--r--src/ee/kicad/functions.py105
-rw-r--r--src/ee/kicad/make_bom.py164
-rw-r--r--src/ee/kicad/model.py24
-rw-r--r--src/ee/kicad/sch_fact_types.py18
4 files changed, 151 insertions, 160 deletions
diff --git a/src/ee/kicad/functions.py b/src/ee/kicad/functions.py
new file mode 100644
index 0000000..39614b6
--- /dev/null
+++ b/src/ee/kicad/functions.py
@@ -0,0 +1,105 @@
+import re
+
+import ee.kicad.model
+import ee.kicad.sch_fact_types as kicad_ft
+from ee.kicad import sch_fact_types
+from ee.part import Part
+from ee.part import common_fact_types
+from ee.xml import uris
+
+
+def part_type_from_footprint(lib):
+ if lib == "Capacitor_SMD":
+ return uris.CAPACITOR
+ elif lib == "Resistor_SMD":
+ return uris.RESISTOR
+ elif lib == "Diode_SMD":
+ return uris.DIODE
+ elif lib == "Inductor_SMD":
+ return uris.INDUCTOR
+ elif lib == "Crystal":
+ return uris.CRYSTAL
+
+
+def part_type_from_ref_type(ref_type):
+ if ref_type == "C":
+ return uris.CAPACITOR
+ elif ref_type == "R":
+ return uris.RESISTOR
+ elif ref_type == "D":
+ return uris.DIODE
+ elif ref_type == "L":
+ return uris.INDUCTOR
+ elif ref_type == "X":
+ return uris.CRYSTAL
+ elif ref_type == "Q":
+ return uris.TRANSISTOR
+
+
+def part_type_strategy(part: Part) -> Part:
+ pt = None
+
+ fp_lib = part.facts.get_value(kicad_ft.footprint_library)
+ if fp_lib is not None:
+ pt = part_type_from_footprint(fp_lib)
+
+ ref = part.get_only_schematic_reference()
+ if ref:
+ ref_type, ref_num = ee.kicad.model.split_ref(ref.referenceProp)
+
+ if ref_type:
+ pt = part_type_from_ref_type(ref_type)
+
+ if pt is not None:
+ part.facts.add(common_fact_types.ee_component_type, pt)
+
+ return part
+
+
+def fix_value_strategy(part: Part) -> Part:
+ ref = part.get_only_schematic_reference()
+
+ if not ref:
+ return part
+
+ ref_type, ref_num = ee.kicad.model.split_ref(ref.referenceProp)
+
+ if not ref_num:
+ return part
+
+ v = part.facts.get_value(sch_fact_types.value)
+ if not v:
+ return part
+
+ symbol_name = part.facts.get_value(sch_fact_types.symbol_name)
+
+ if ref_type in ("D", "R", "L", "C") and v == symbol_name:
+ part.remove_fact(uris.make_fact_key("value"))
+
+ if ref_type == "Q" and v == symbol_name and re.match("^Q_[NP]MOS_[DSG]{3}$", symbol_name):
+ part.remove_fact(uris.make_fact_key("value"))
+
+ return part
+
+
+def mpn_strategy(part: Part) -> Part:
+ for field in part.facts.all(sch_fact_types.field):
+
+ k, v = re.split(":", field.value, 1)
+ if k == "mpn":
+ part.add_mpn(v)
+
+ return part
+
+
+def default(part: Part) -> Part:
+ functions = [
+ fix_value_strategy,
+ mpn_strategy,
+ part_type_strategy,
+ ]
+
+ for f in functions:
+ part = f(part)
+
+ return part
diff --git a/src/ee/kicad/make_bom.py b/src/ee/kicad/make_bom.py
index dcdf96b..13b2157 100644
--- a/src/ee/kicad/make_bom.py
+++ b/src/ee/kicad/make_bom.py
@@ -1,145 +1,19 @@
-import pydoc
-import re
from pathlib import Path
-from typing import Optional, List, Callable, Mapping
from xml.dom import minidom
from xml.etree import ElementTree
-from ee import EeException
-from ee.kicad.model import Component
+from ee.kicad import sch_fact_types
from ee.kicad.read_schematic import read_schematics
from ee.kicad.to_bom import to_bom, to_bom_xml
from ee.part import PartDb, save_db, Part
-from ee.xml import types, uris
+from ee.xml import types
__all__ = [
- "StrategyCallable",
- "MakeBomStrategy",
- "apply_strategies",
- "mpn_strategy",
- "part_type_strategy",
- "dpn_strategy_factory",
"make_bom",
]
-StrategyCallable = Callable[[Component, Part], Optional[Part]]
-
-def apply_strategies(c: Component, part: Part, strategies: List[StrategyCallable]):
- for strategy in strategies:
- part = strategy(c, part)
-
- if part is None:
- return
-
- if not isinstance(part, Part):
- raise EeException("Values returned from strategy must be a Part, got {}".format(type(part)))
-
- return part
-
-
-def part_type_from_footprint(fp):
- lib, part_name = fp.split(":")
-
- if lib == "Capacitor_SMD":
- return uris.CAPACITOR
- elif lib == "Resistor_SMD":
- return uris.RESISTOR
- elif lib == "Diode_SMD":
- return uris.DIODE
- elif lib == "Inductor_SMD":
- return uris.INDUCTOR
- elif lib == "Crystal":
- return uris.CRYSTAL
-
-
-def part_type_from_ref_type(ref_type):
- if ref_type == "C":
- return uris.CAPACITOR
- elif ref_type == "R":
- return uris.RESISTOR
- elif ref_type == "D":
- return uris.DIODE
- elif ref_type == "L":
- return uris.INDUCTOR
- elif ref_type == "X":
- return uris.CRYSTAL
- elif ref_type == "Q":
- return uris.TRANSISTOR
-
-
-def part_type_strategy(component: Component, part: Part) -> Part:
- pt = None
-
- fp = component.footprint
- if fp is not None:
- pt = part_type_from_footprint(fp)
-
- if pt is None and component.has_ref_num:
- pt = part_type_from_ref_type(component.ref_type)
-
- if pt is not None:
- part.get_facts().append(types.Fact(uris.make_fact_key("type"), value=pt))
-
- return part
-
-
-def fix_value_strategy(component: Component, part: Part) -> Part:
- if not component.has_ref_num:
- return part
-
- rt = component.ref_type
- v = component.value
-
- if rt in ("D", "R", "L", "C") and v == component.symbol.name:
- part.remove_fact(uris.make_fact_key("value"))
-
- if rt == "Q" and v == component.symbol.name and re.match("^Q_[NP]MOS_[DSG]{3}$", component.symbol.name):
- part.remove_fact(uris.make_fact_key("value"))
-
- return part
-
-
-def mpn_strategy(component: Component, part: Part) -> Part:
- mpn = component.get_field("mpn")
- if mpn is not None:
- part.add_mpn(mpn.value)
-
- return part
-
-
-def dpn_strategy_factory(dpn_mappings: Mapping[str, str]) -> StrategyCallable:
- def dpn_strategy(component: Component, part: Part) -> Part:
- for field_name, distributor in dpn_mappings:
- s = component.get_field(field_name)
- if s is None:
- continue
-
- part.add_spn(s.value)
-
- return part
-
- return dpn_strategy
-
-
-class MakeBomStrategy():
- def __init__(self):
- self.dpn_mappings = {}
- self.default_strategies = [
- fix_value_strategy,
- mpn_strategy,
- part_type_strategy,
- dpn_strategy_factory(self.dpn_mappings),
- ]
-
- def process_part(self, component: Component, part: Part):
- return self.default_process_part(component, part)
-
- def default_process_part(self, component: Component, part: Part):
- return apply_strategies(component, part, self.default_strategies)
-
-
-def work(sch, out: Path, strategy: MakeBomStrategy, new_mode, pretty):
+def work(sch, out: Path, new_mode, pretty):
def strip(s):
s = (s or "").strip()
@@ -165,39 +39,31 @@ def work(sch, out: Path, strategy: MakeBomStrategy, new_mode, pretty):
value = strip(c.value)
if value:
- part.facts.add(uris.make_fact_key("value"), value)
+ part.facts.add(sch_fact_types.value, value)
+
+ if c.symbol.library:
+ part.facts.add(sch_fact_types.symbol_library, c.symbol.library)
+ part.facts.add(sch_fact_types.symbol_name, c.symbol.name)
footprint = strip(c.footprint)
if footprint:
- part.facts.add(uris.make_fact_key("footprint"), footprint)
+ part.facts.add(sch_fact_types.footprint, footprint)
i = footprint.find(":")
if i >= 0:
lib, footprint = footprint.split(":")
- part.facts.add(uris.make_fact_key("kicad-schematic-library"), lib)
- part.facts.add(uris.make_fact_key("kicad-schematic-footprint"), footprint)
+ part.facts.add(sch_fact_types.footprint_library, lib)
+ part.facts.add(sch_fact_types.footprint_name, footprint)
- part = strategy.process_part(c, part)
-
- if part is None:
- continue
+ for f in c.named_fields:
+ part.facts.add(sch_fact_types.field, "{}:{}".format(f.name, f.value))
parts.add_entry(part, True)
save_db(out, parts)
-def make_bom(sch_file: Path, out_dir: Path, strategy_name: str, new_mode: bool, pretty: bool):
+def make_bom(sch_file: Path, out_dir: Path, new_mode: bool, pretty: bool):
sch = read_schematics(str(sch_file))
- make_bom_strategy_factory = pydoc.locate(strategy_name)
-
- if not callable(make_bom_strategy_factory):
- raise EeException("Not a callable: {}, is a {}".format(strategy_name, type(make_bom_strategy_factory)))
-
- make_bom_strategy = make_bom_strategy_factory() # type: MakeBomStrategy
-
- if not isinstance(make_bom_strategy, MakeBomStrategy):
- raise EeException("Not a MakeBomStrategy: {}, is a {}".format(strategy_name, type(make_bom_strategy)))
-
- work(sch, out_dir, make_bom_strategy, new_mode, pretty)
+ work(sch, out_dir, new_mode, pretty)
diff --git a/src/ee/kicad/model.py b/src/ee/kicad/model.py
index 295a40a..1f6cf96 100644
--- a/src/ee/kicad/model.py
+++ b/src/ee/kicad/model.py
@@ -1,6 +1,6 @@
import re
from functools import total_ordering
-from typing import List, Set
+from typing import List, Set, Tuple, Optional
from ee import EeException
@@ -62,7 +62,16 @@ class Symbol(object):
self.name = symbol
else:
self.library = symbol[0:i]
- self.name = symbol[i+1:]
+ self.name = symbol[i + 1:]
+
+
+def split_ref(ref: str) -> Tuple[Optional[str], Optional[int]]:
+ r = re.compile("([^0-9]+)(.+)")
+ try:
+ parts = r.split(ref)
+ return parts[1], int(parts[2])
+ except ValueError:
+ return None, None
@total_ordering
@@ -76,14 +85,7 @@ class Component(object):
self._ref = ref
self._fields = fields # type List[ComponentField]
- r = re.compile("([^0-9]+)(.+)")
- try:
- parts = r.split(self._ref)
- self._ref_type = parts[1]
- self._ref_num = int(parts[2])
- except ValueError:
- self._ref_type = None
- self._ref_num = None
+ self._ref_type, self._ref_num = split_ref(self._ref)
def __eq__(self, o: object) -> bool:
other = o # type: Component
@@ -157,7 +159,7 @@ class Component(object):
return list(self._fields)
@property
- def named_fields(self):
+ def named_fields(self) -> List[ComponentField]:
return [f for f in self._fields if f.name]
def get_field(self, name) -> ComponentField:
diff --git a/src/ee/kicad/sch_fact_types.py b/src/ee/kicad/sch_fact_types.py
new file mode 100644
index 0000000..c9ea918
--- /dev/null
+++ b/src/ee/kicad/sch_fact_types.py
@@ -0,0 +1,18 @@
+from ee.part import FactType
+
+
+def make_fact_key(key: str):
+ return "http://purl.org/ee/kicad-sch-fact-type#{}".format(key)
+
+
+value = FactType(make_fact_key("value"), "Value")
+component = FactType(make_fact_key("component"), "Value")
+
+symbol_library = FactType(make_fact_key("symbol-library"), "Value")
+symbol_name = FactType(make_fact_key("symbol-name"), "Value")
+
+footprint = FactType(make_fact_key("footprint"), "Value")
+footprint_library = FactType(make_fact_key("footprint-library"), "Value")
+footprint_name = FactType(make_fact_key("footprint-name"), "Value")
+
+field = FactType(make_fact_key("field"), "Value")