From 73d58e1c256110a557a591cc95cf8df73dfef9a8 Mon Sep 17 00:00:00 2001
From: Trygve Laugstøl <trygvis@inamo.no>
Date: Wed, 28 Dec 2016 16:51:47 +0100
Subject: o Adding kicad:footprint when converting BOM to TTL.

---
 trygvis/eda/cli/kicad_bom_to_ttl.py | 64 +++++++++++++++++++++----------------
 trygvis/eda/kicad/rdf.py            |  1 +
 2 files changed, 37 insertions(+), 28 deletions(-)

(limited to 'trygvis')

diff --git a/trygvis/eda/cli/kicad_bom_to_ttl.py b/trygvis/eda/cli/kicad_bom_to_ttl.py
index 651ad32..9cd3f8c 100755
--- a/trygvis/eda/cli/kicad_bom_to_ttl.py
+++ b/trygvis/eda/cli/kicad_bom_to_ttl.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python3
-
 import functools
 import os.path
 import re
@@ -8,13 +6,14 @@ import xml.etree.ElementTree
 from urllib.parse import quote_plus
 from operator import attrgetter
 import itertools
+from typing import List
 
 import rdflib
+from rdflib import Literal, URIRef
+from rdflib.namespace import RDF, RDFS
 
 from .. import cli
 from ..kicad import rdf as kicad_rdf
-from rdflib import Literal, URIRef
-from rdflib.namespace import RDF, RDFS
 
 
 def _clean(s):
@@ -56,8 +55,8 @@ def _iso_size_to_factor(size):
 
 @functools.total_ordering
 class Value:
-    valueRe = re.compile("([0-9]+\.?[0-9]*)(.*)")
-    typeRe = re.compile("(.*)(H|Hz)$")
+    valueRe = re.compile('([0-9]+\.?[0-9]*)(.*)')
+    typeRe = re.compile('(.*)(H|Hz)$')
 
     def __init__(self, text, value, factor, type):
         self.text = text
@@ -88,7 +87,7 @@ class Value:
             return s
         if self.text is not None:
             return self.text
-        return "unknown"
+        return 'unknown'
 
     @staticmethod
     def parse(text):
@@ -117,12 +116,12 @@ class Value:
 
 
 class Component:
-    refRe = re.compile("([a-zA-Z]+)([0-9]+)")
+    refRe = re.compile('([a-zA-Z]+)([0-9]+)')
 
     def __init__(self, ref, value, footprint, fields):
-        self.ref = ref
-        self.value = Value.parse(value)
-        self.footprint = footprint
+        self.ref = ref  # type: str
+        self.value = Value.parse(value)  # type: Value
+        self.footprint = footprint  # type: str
         self.fields = fields
         m = Component.refRe.match(ref)
         if m:
@@ -187,8 +186,8 @@ class Sheet(object):
 
     @staticmethod
     def from_xml(s):
-        number = _cleaned_attr(s, "number")
-        name = _cleaned_attr(s, "name")
+        number = _cleaned_attr(s, 'number')
+        name = _cleaned_attr(s, 'name')
         node = s.find('title_block')
         title_block = TitleBlock.from_xml(node) if node is not None else TitleBlock()
         return Sheet(int(number) if number is not None else None, name, title_block)
@@ -214,8 +213,8 @@ class Design(object):
 
 class Export(object):
     def __init__(self, design, components):
-        self.design = design if design is not None else Design()
-        self.components = components
+        self.design = design if design is not None else Design()  # type: Design
+        self.components = components  # type: List[Component]
 
     @staticmethod
     def from_xml(doc):
@@ -247,7 +246,7 @@ class Export(object):
                 title = _clean(os.path.basename(self.design.source))
 
         if title is None:
-            raise cli.CliException("Could not generate a stable, identifying URL for the schematic")
+            raise cli.CliException('Could not generate a stable, identifying URL for the schematic')
 
         title = quote_plus(title)
         return kicad_rdf.KICAD_BOARD[title]
@@ -255,7 +254,7 @@ class Export(object):
 
 def run(args):
     if args.input is not None:
-        src = open(args.input, "r")
+        src = open(args.input, 'r')
     else:
         src = sys.stdin
 
@@ -263,7 +262,7 @@ def run(args):
         parent = os.path.dirname(args.output)
         if not os.path.exists(parent):
             os.mkdir(parent)
-        dst = open(args.output, "wb")
+        dst = open(args.output, 'wb')
     else:
         dst = sys.stdout.buffer
 
@@ -279,14 +278,14 @@ def process(src, dst, schematic_url):
 
     export = Export.from_xml(root)
 
-    # print("components:")
+    # print('components:')
     # for c in export.components:
     #  print(c)
 
     # for name in export.component_fields():
     #     cli.info(name)
 
-    # cli.info("components:")
+    # cli.info('components:')
     # fmt = '%2s%3s'
     # cli.info(fmt % ('Ref', ''))
 
@@ -304,8 +303,8 @@ def process(src, dst, schematic_url):
             component_count += 1
 
             value = str(c.value)
-            part = c.find_field("part")
-            digikey = c.find_field("digikey")
+            part = c.find_field('part')
+            digikey = c.find_field('digikey')
             footprint = c.footprint
 
             if c.ref_class is not None:
@@ -313,7 +312,7 @@ def process(src, dst, schematic_url):
                 ref_instance = c.ref_instance
             else:
                 ref_class = c.ref
-                ref_instance = ""
+                ref_instance = ''
 
             # cli.info(fmt % (ref_class, ref_instance))
             # cli.info('    Value: %s' % c.value.text)
@@ -331,7 +330,7 @@ def process(src, dst, schematic_url):
                     part = None
             else:
                 part_count += 1
-                part = "MISSING"
+                part = 'MISSING'
 
                 # if part is not None:
                 #     cli.info('    Part: %s' % part)
@@ -355,9 +354,10 @@ def process(src, dst, schematic_url):
 
     # The components and fields could/should have been a BNodes. Their generated names are not very nice.
     # TODO: try using a hash of the current value and put that under a special generated namespace.
-    # "http://example.org/my-board" + ref="C10" => "http://example.org/my-boardC10"
-    # hash("http://example.org/my-boardC10") => 123456
-    # add_prefix(hash) => "https://trygvis.io/purl/kicad/generated#123456"
+    # 'http://example.org/my-board' + ref='C10' => 'http://example.org/my-boardC10'
+    # hash('http://example.org/my-boardC10') => 123456
+    # add_prefix(hash) => 'https://trygvis.io/purl/kicad/generated#123456'
+    footprints = set()
     for c in export.components:
         ns = rdflib.Namespace(schematic_url)
         node = ns[c.ref]
@@ -367,8 +367,16 @@ def process(src, dst, schematic_url):
         g.add((node, RDFS.label, Literal(c.ref)))
         g.add((node, kicad_rdf.KICAD.value, Literal(c.value.text)))
 
+        footprint_uri = URIRef(kicad_rdf.KICAD_FOOTPRINT[quote_plus(c.footprint)])
+        if not footprint_uri in footprints:
+            g.add((footprint_uri, RDF.type, kicad_rdf.KICAD_TYPE.footprint))
+            g.add((footprint_uri, RDFS.label, Literal(c.footprint)))
+            footprints.add(footprint_uri)
+
+        g.add((node, kicad_rdf.KICAD.footprint, footprint_uri))
+
         for name, value in c.fields.items():
-            f = ns["%s-%s" % (c.ref, name)]
+            f = ns['%s-%s' % (c.ref, name)]
             g.add((node, kicad_rdf.KICAD.field, f))
             g.add((f, RDF.type, kicad_rdf.KICAD_TYPE.field))
             g.add((f, kicad_rdf.KICAD.field_name, Literal(name)))
diff --git a/trygvis/eda/kicad/rdf.py b/trygvis/eda/kicad/rdf.py
index 24cba00..34b73e1 100644
--- a/trygvis/eda/kicad/rdf.py
+++ b/trygvis/eda/kicad/rdf.py
@@ -2,6 +2,7 @@ import rdflib
 
 KICAD = rdflib.Namespace("https://trygvis/purl/kicad#")
 KICAD_TYPE = rdflib.Namespace("https://trygvis/purl/kicad-type#")
+KICAD_FOOTPRINT = rdflib.Namespace("https://trygvis/purl/kicad-footprints#")
 
 # Namespace for all unknown kicad boards
 KICAD_BOARD = rdflib.Namespace("https://trygvis/purl/kicad-board#")
-- 
cgit v1.2.3