aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2019-05-11 14:48:15 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2019-05-11 14:48:15 +0200
commit0149fcfa2bd9ac8c9f6b05851f7264f005aa2305 (patch)
tree3757a7148377bf18e32234d375444ffccbc5a8f0
parenteffb3470dd1be3a0dd1eaa83991cef45b5e08dab (diff)
downloadee-python-0149fcfa2bd9ac8c9f6b05851f7264f005aa2305.tar.gz
ee-python-0149fcfa2bd9ac8c9f6b05851f7264f005aa2305.tar.bz2
ee-python-0149fcfa2bd9ac8c9f6b05851f7264f005aa2305.tar.xz
ee-python-0149fcfa2bd9ac8c9f6b05851f7264f005aa2305.zip
drawio-to-parts: new tool.
ee.xsd: new type: Assembly and AssemblyPart. Should probably be its own file type. ee.part: Better DSL instead of using the raw xml types.
-rw-r--r--src/ee/digikey/search_parts.py2
-rw-r--r--src/ee/drawio.py153
-rw-r--r--src/ee/part/__init__.py202
-rw-r--r--src/ee/part/excel.py9
-rw-r--r--src/ee/supplier/seeed.py2
-rw-r--r--src/ee/tools/drawio_decompress.py2
-rw-r--r--src/ee/tools/drawio_to_parts.py (renamed from src/ee/tools/drawio-to-parts.py)9
-rw-r--r--src/ee/tools/templates/build.ninja.j29
-rw-r--r--src/ee/xml/types.py357
-rw-r--r--xsd/ee.xsd27
10 files changed, 695 insertions, 77 deletions
diff --git a/src/ee/digikey/search_parts.py b/src/ee/digikey/search_parts.py
index c7f981e..c248831 100644
--- a/src/ee/digikey/search_parts.py
+++ b/src/ee/digikey/search_parts.py
@@ -17,7 +17,7 @@ def resolved(supplier, p: DigikeyProduct) -> Part:
distributor_info=types.DistributorInfo(state="resolved"),
links=types.LinkList(),
facts=types.FactList(),
- references=types.ReferencesList())
+ references=types.ReferenceList())
part = Part(xml)
if p.url:
diff --git a/src/ee/drawio.py b/src/ee/drawio.py
index de98986..b079979 100644
--- a/src/ee/drawio.py
+++ b/src/ee/drawio.py
@@ -2,10 +2,14 @@ import base64
import urllib.parse
import zlib
from pathlib import Path
-from typing import Mapping, MutableMapping
+from typing import Mapping, MutableMapping, List, Optional
from xml.dom import minidom
+
from lxml import etree
+from ee.db import ObjDb
+from ee.part import PartDb, save_db, load_db, Part, AssemblyPart
+
def decompress(input_stream, output_stream):
doc = minidom.parse(input_stream)
@@ -48,8 +52,8 @@ class GraphEdge(object):
self.target_id = target_id
self.value = value
- self.source: GraphObject = None
- self.target: GraphObject = None
+ self.source: Optional[GraphObject] = None
+ self.target: Optional[GraphObject] = None
def add_attr(self, key, value):
self.attrs[key] = value
@@ -60,6 +64,10 @@ class GraphModel(object):
self.objects = objects
self.edges = edges
+ @property
+ def roots(self):
+ return [o for o in self.objects.values() if len(o.incoming) == 0]
+
@staticmethod
def create(objects: Mapping[str, GraphObject], edges: Mapping[str, GraphEdge]) -> "GraphModel":
for id_, edge in edges.items():
@@ -130,10 +138,72 @@ def load_graph(doc) -> GraphModel:
return GraphModel.create(objects, edges)
-def to_parts(in_path: Path, out_path: Path):
+def to_parts(in_path: Path, out_path: Path, part_dbs: List[Path]):
+ parts: ObjDb[Part] = ObjDb[Part]()
+ description_idx = parts.add_index("description", lambda p: p.underlying.descriptionProp)
+
+ def find_part(o: GraphObject):
+ if "part" in o.attrs:
+ d = o.attrs["part"]
+ else:
+ d = o.value
+
+ hits = description_idx.get(d)
+ if len(hits) == 0:
+ # print("No part with description found in database: '{}'".format(d))
+ return
+ elif len(hits) == 1:
+ found = hits[0]
+ return found
+ else:
+ # print("Found multiple parts with description '{}'".format(d))
+ return
+
+ def add_part(o: GraphObject):
+ print("obj: {}".format(o.value))
+
+ p = find_part(o)
+
+ uri = p.uri if p else None
+ ap = AssemblyPart(uri)
+
+ if uri:
+ ap.references.add_part_reference(uri)
+
+ ap.references.add_description_reference(o.value)
+
+ for out in o.outgoing.values():
+ sub_part = add_part(out.target)
+ ap.add_sub_part(sub_part)
+
+ # description = out.target.value
+ # print(" out: {}".format(description))
+ #
+ # p = find_part(out.target)
+ #
+ # if p is None:
+ # continue
+ #
+ # ap.add_sub_part(p.uri)
+
+ return ap
+
+ for part_db in part_dbs:
+ for xml in load_db(part_db).iterparts():
+ parts.add(Part(xml))
+
doc = etree.parse(str(in_path))
+ print(doc)
graph = load_graph(doc)
+ db = PartDb()
+ a = db.assembly
+
+ for root in graph.roots:
+ a.parts.append(add_part(root))
+
+ save_db(out_path, db)
+
def to_dot(in_path: Path, out_path: Path):
def to_id(s: str):
@@ -145,43 +215,44 @@ def to_dot(in_path: Path, out_path: Path):
doc = etree.parse(str(in_path))
graph = load_graph(doc)
- print("digraph parts {")
- for id_, obj in graph.objects.items():
- if len(obj.attrs):
- attr_str = "\\n".join(["{}={}".format(k, quote(v)) for k, v in obj.attrs.items()])
- print(" {}_attrs [shape=plaintext, label=\"{}\"]".format(to_id(obj.id), quote(attr_str)))
- print(" {}_attrs -> {} [arrowhead=none,style=dotted]".format(to_id(obj.id), to_id(obj.id)))
-
- attrs = {}
- if obj.value:
- attrs["label"] = obj.value
-
- attr_str = ",".join(["{}=\"{}\"".format(k, quote(v)) for k, v in attrs.items()])
- print(" {} [{}];".format(to_id(obj.id), attr_str))
-
- for id_, edge in graph.edges.items():
- source_id = edge.source.id
- target_id = edge.target.id
-
- if len(edge.attrs):
- print(" // source={}, target={}".format(source_id, target_id))
- attr_str = "\\n".join(["{}={}".format(k, quote(v)) for k, v in edge.attrs.items()])
-
- print(" {}_fake [shape=plaintext, label=\"{}\"]".format(to_id(edge.target.id), attr_str))
- print(" {}_fake -> {}".format(to_id(edge.target.id), to_id(edge.target.id)))
- # source_id = "{}_fake".format(to_id(edge.id))
- target_id = "{}_fake".format(to_id(edge.target.id))
- arrowhead="none"
- else:
- arrowhead="normal"
+ with open(str(out_path), "w") as f:
+ print("digraph parts {", file=f)
+ for id_, obj in graph.objects.items():
+ if len(obj.attrs):
+ attr_str = "\\n".join(["{}={}".format(k, quote(v)) for k, v in obj.attrs.items()])
+ print(" {}_attrs [shape=plaintext, label=\"{}\"]".format(to_id(obj.id), quote(attr_str)), file=f)
+ print(" {}_attrs -> {} [arrowhead=none,style=dotted]".format(to_id(obj.id), to_id(obj.id)), file=f)
+
+ attrs = {}
+ if obj.value:
+ attrs["label"] = obj.value
+
+ attr_str = ",".join(["{}=\"{}\"".format(k, quote(v)) for k, v in attrs.items()])
+ print(" {} [{}];".format(to_id(obj.id), attr_str), file=f)
+
+ for id_, edge in graph.edges.items():
+ source_id = edge.source.id
+ target_id = edge.target.id
+
+ if len(edge.attrs):
+ print(" // source={}, target={}".format(source_id, target_id), file=f)
+ attr_str = "\\n".join(["{}={}".format(k, quote(v)) for k, v in edge.attrs.items()])
- attrs = {}
- # if edge.value:
- # attrs["label"] = edge.value
+ print(" {}_fake [shape=plaintext, label=\"{}\"]".format(to_id(edge.target.id), attr_str), file=f)
+ print(" {}_fake -> {}".format(to_id(edge.target.id), to_id(edge.target.id)), file=f)
+ # source_id = "{}_fake".format(to_id(edge.id))
+ target_id = "{}_fake".format(to_id(edge.target.id))
+ arrowhead = "none"
+ else:
+ arrowhead = "normal"
+
+ attrs = {}
+ # if edge.value:
+ # attrs["label"] = edge.value
- # attr_str = ",".join(["{}=\"{}\"".format(k, quote(v)) for k, v in attrs.items()])
+ # attr_str = ",".join(["{}=\"{}\"".format(k, quote(v)) for k, v in attrs.items()])
- print(" {} -> {} [arrowhead={}];".format(to_id(source_id), to_id(target_id), arrowhead))
- for k, v in edge.attrs.items():
- print(" // {}={}".format(k, v))
- print("}")
+ print(" {} -> {} [arrowhead={}];".format(to_id(source_id), to_id(target_id), arrowhead), file=f)
+ for k, v in edge.attrs.items():
+ print(" // {}={}".format(k, v))
+ print("}")
diff --git a/src/ee/part/__init__.py b/src/ee/part/__init__.py
index 4354771..996eeff 100644
--- a/src/ee/part/__init__.py
+++ b/src/ee/part/__init__.py
@@ -13,11 +13,152 @@ __all__ = [
]
+class Reference(object):
+ pass
+
+ def to_xml(self):
+ return None
+
+
+class PartReference(Reference):
+ def __init__(self, uri: str):
+ self.uri = uri
+
+ def to_xml(self):
+ return types.PartReference(part_uri=self.uri)
+
+
+class SchematicReference(Reference):
+ def __init__(self, reference: str):
+ self.reference = reference
+
+ def to_xml(self):
+ return types.SchematicReference(reference=self.reference)
+
+
+class PartNumber(Reference):
+ def __init__(self, value: str):
+ self.value = value
+
+ def to_xml(self):
+ return types.PartNumber(value=self.value)
+
+
+class SupplierPartNumber(Reference):
+ def __init__(self, value: str):
+ self.value = value
+
+ def to_xml(self):
+ return types.SupplierPartNumber(value=self.value)
+
+
+class ReferenceList(object):
+ def __init__(self, part_uri):
+ self.part_uri_ = part_uri
+ self.part_references: List[PartReference] = []
+ self.schematic_references: List[SchematicReference] = []
+ self.mpns: List[PartNumber] = []
+ self.spns: List[SupplierPartNumber] = []
+ self.description_references: List[str] = []
+
+ def to_xml(self):
+ part_references = [r.to_xml() for r in self.part_references if isinstance(r, PartReference)]
+ schematic_references = [r.to_xml() for r in self.schematic_references if isinstance(r, SchematicReference)]
+ mpns = [r.to_xml() for r in self.mpns if isinstance(r, PartNumber)]
+ spns = [r.to_xml() for r in self.spns if isinstance(r, SupplierPartNumber)]
+ description_references = self.description_references
+
+ if len(part_references) or len(schematic_references) or len(mpns) or len(spns) or \
+ len(description_references):
+ return types.ReferenceList(part_reference=part_references,
+ schematic_reference=schematic_references,
+ part_number=mpns,
+ supplier_part_number=spns,
+ description=description_references)
+
+ # Part Reference
+
+ def add_part_reference(self, uri):
+ self.part_references.append(PartReference(uri))
+
+ def get_exactly_one_part_reference(self) -> PartReference:
+ refs = self.part_references
+ if len(refs) == 0:
+ raise EeException("This part does not contain any part references{}".
+ format(", uri=" + self.part_uri_ if self.part_uri_ else ""))
+ if len(refs) != 1:
+ raise EeException("This part does not contain exactly one part reference: {}".
+ format(", ".join([ref.uri for ref in refs])))
+
+ return refs[0]
+
+ # Schematic references
+
+ def add_schematic_reference(self, ref):
+ self.schematic_references.append(SchematicReference(reference=ref))
+
+ def get_only_schematic_reference(self) -> Optional[SchematicReference]:
+ return next(iter(self.schematic_references), None)
+
+ def get_exactly_one_schematic_reference(self) -> SchematicReference:
+ refs = self.schematic_references
+ if len(refs) == 0:
+ raise EeException("This part does not contain any schematic references{}".
+ format(", uri=" + self.part_uri_ if self.part_uri_ else ""))
+ if len(refs) != 1:
+ raise EeException("This part does not contain exactly one schematic reference: {}".
+ format(", ".join([ref.reference for ref in refs])))
+
+ return refs[0]
+
+ # MPNs
+
+ def add_mpn(self, mpn: str):
+ self.mpns.append(PartNumber(value=mpn))
+
+ def get_only_mpn(self) -> Optional[PartNumber]:
+ return next(iter(self.mpns), None)
+
+ def get_exactly_one_mpn(self) -> PartNumber:
+ mpns = self.mpns
+ if len(mpns) == 0:
+ raise EeException("This part does not contain any manufacturer part numbers{}".
+ format(", uri=" + self.part_uri_ if self.part_uri_ else ""))
+ if len(mpns) != 1:
+ raise EeException("This part does not contain exactly one mpn: {}".
+ format(", ".join([mpn.value for mpn in mpns])))
+
+ return mpns[0]
+
+ # SPNs
+
+ def add_spn(self, mpn: str):
+ self.spns.append(SupplierPartNumber(value=mpn))
+
+ def get_only_spn(self) -> Optional[SupplierPartNumber]:
+ return next(iter(self.spns), None)
+
+ def get_exactly_one_spn(self) -> SupplierPartNumber:
+ spns = self.spns
+ if len(spns) == 0:
+ raise EeException("This part does not contain any supplier part numbers{}".
+ format(", uri=" + self.part_uri_ if self.part_uri_ else ""))
+ if len(spns) != 1:
+ raise EeException("This part does not contain exactly one spn: {}".
+ format(", ".join([spn.value for spn in spns])))
+
+ return spns[0]
+
+ def add_description_reference(self, description: str):
+ self.description_references.append(description)
+
+
+# TODO: Replace self.xml.referencesProp with ReferenceList
class Part(object):
def __init__(self, xml: types.Part):
assert type(xml) == types.Part
self.xml = xml
- xml.referencesProp = xml.referencesProp if xml.referencesProp is not None else types.ReferencesList()
+ xml.referencesProp = xml.referencesProp if xml.referencesProp is not None else types.ReferenceList()
xml.price_breaksProp = xml.price_breaksProp if xml.price_breaksProp is not None else types.PriceBreakList()
xml.linksProp = xml.linksProp if xml.linksProp is not None else types.LinkList()
xml.factsProp = xml.factsProp if xml.factsProp is not None else types.FactList()
@@ -172,11 +313,27 @@ class Entry(object):
self.pn = next((p.valueProp for p in Part(part).get_mpns()), None)
+class AssemblyPart(object):
+ def __init__(self, uri: Optional[str]):
+ self.count = 0
+ self.sub_parts: List[AssemblyPart] = []
+ self.references = ReferenceList(uri)
+
+ def add_sub_part(self, ap: "AssemblyPart"):
+ self.sub_parts.append(ap)
+
+
+class Assembly(object):
+ def __init__(self):
+ self.parts: List[AssemblyPart] = []
+
+
class PartDb(object):
def __init__(self):
self.parts: List[Entry] = []
self.pn_index: MutableMapping[str, Entry] = {}
self.new_entries = 0
+ self._assembly: Optional[Assembly] = None
def add_entry(self, part: Union[Part, types.Part], new: bool):
if isinstance(part, Part):
@@ -202,6 +359,16 @@ class PartDb(object):
entry = self.pn_index.get(pn, None)
return entry.part if entry else None
+ @property
+ def has_assembly(self):
+ return self._assembly is not None
+
+ @property
+ def assembly(self):
+ if self._assembly is None:
+ self._assembly = Assembly()
+ return self._assembly
+
def load_db(path: Path) -> PartDb:
db = PartDb()
@@ -223,12 +390,35 @@ def find_root_tag(root):
def save_db(path: Path, db: PartDb, sort=False):
part_db = types.PartDb()
- parts = part_db.parts = types.PartList()
- for part in db.iterparts(sort=sort):
- p = Part(part)
- p.clean_xml()
- parts.partProp.append(p.underlying)
+ if db.size() > 0:
+ part_db.parts = types.PartList()
+
+ for part in db.iterparts(sort=sort):
+ p = Part(part)
+ p.clean_xml()
+ part_db.parts.partProp.append(p.underlying)
+
+ if db.has_assembly:
+
+ def to_xml(ap: AssemblyPart):
+ xml = types.AssemblyPart()
+ if ap.count != 0:
+ xml.countProp = ap.count
+ if ap.sub_parts:
+ xml.sub_partsProp = types.AssemblyPartList([to_xml(ap_) for ap_ in ap.sub_parts])
+
+ xml.set_references(ap.references.to_xml())
+
+ return xml
+
+ assembly = db.assembly
+ part_list = types.AssemblyPartList()
+
+ for ap in assembly.parts:
+ part_list.add_assembly_part(to_xml(ap))
+
+ part_db.assemblyProp = types.Assembly(assembly_parts=part_list)
with path.open("w") as f:
part_db.export(outfile=f, level=0, name_=find_root_tag(part_db))
diff --git a/src/ee/part/excel.py b/src/ee/part/excel.py
index 12b583d..b0c4a2b 100644
--- a/src/ee/part/excel.py
+++ b/src/ee/part/excel.py
@@ -1,3 +1,4 @@
+import uuid
from pathlib import Path
from typing import Optional, Mapping
@@ -38,12 +39,12 @@ def from_excel(path: Path, sheet_name: Optional[str]) -> PartDb:
print("Bad part, line #{}. MPN or description is required".format(idx))
continue
- part = Part(types.Part())
+ uri = "urn:uuid:{}".format(uuid.uuid5(uuid.NAMESPACE_URL, url))
+ part = Part(types.Part(uri=uri))
- if not mpn:
- mpn = desc.replace(" ", "-").lower()
+ if mpn:
+ part.add_mpn(mpn)
- part.add_mpn(mpn)
part.xml.descriptionProp = desc
if price:
diff --git a/src/ee/supplier/seeed.py b/src/ee/supplier/seeed.py
index b4b17e9..1982f68 100644
--- a/src/ee/supplier/seeed.py
+++ b/src/ee/supplier/seeed.py
@@ -110,7 +110,7 @@ def download_opl(out_path: Path, cache_dir: Path, opl_type: str):
ladder_price = p["ladder_price"]
- xml = types.Part(references=types.ReferencesList(), price_breaks=types.PriceBreakList())
+ xml = types.Part(references=types.ReferenceList(), price_breaks=types.PriceBreakList())
xml.supplierProp = supplier_uri
xml.descriptionProp = desc
diff --git a/src/ee/tools/drawio_decompress.py b/src/ee/tools/drawio_decompress.py
index 8949eec..8fafd54 100644
--- a/src/ee/tools/drawio_decompress.py
+++ b/src/ee/tools/drawio_decompress.py
@@ -18,7 +18,7 @@ in_stream = out_stream = None
try:
in_stream = open(args.in_path, "rb") if args.in_path else sys.stdin
- out_stream = open(args.out, "wr") if args.out else sys.stdout
+ out_stream = open(args.out, "w") if args.out else sys.stdout
decompress(in_stream, out_stream)
except IOError:
diff --git a/src/ee/tools/drawio-to-parts.py b/src/ee/tools/drawio_to_parts.py
index 562e341..671aaea 100644
--- a/src/ee/tools/drawio-to-parts.py
+++ b/src/ee/tools/drawio_to_parts.py
@@ -14,7 +14,12 @@ parser.add_argument("--out",
required=True,
metavar="PART DB")
+parser.add_argument("--parts",
+ nargs="*",
+ metavar="PART DB")
+
args = parser.parse_args()
-# ee.drawio.to_parts(Path(args.in_path), Path(args.out))
-ee.drawio.to_dot(Path(args.in_path), Path(args.out))
+parts = args.parts or []
+ee.drawio.to_parts(Path(args.in_path), Path(args.out), [Path(path) for path in parts])
+# ee.drawio.to_dot(Path(args.in_path), Path(args.out))
diff --git a/src/ee/tools/templates/build.ninja.j2 b/src/ee/tools/templates/build.ninja.j2
index d62f350..b9a65df 100644
--- a/src/ee/tools/templates/build.ninja.j2
+++ b/src/ee/tools/templates/build.ninja.j2
@@ -53,6 +53,15 @@ rule import-parts-yaml
description = import-parts-yaml $in
command = $ee import-parts-yaml --in $in --out $out
+rule drawio-decompress
+ command = $ee drawio-decompress --in $in --out $out
+
+rule drawio-to-parts
+ command = $ee drawio-to-parts --in $in --out $out $args
+
+rule part-from-excel
+ command = $ee part-from-excel --in $in --out $out --sheet "$sheet"
+
{% if gerber_zip is defined %}
build gerbers: phony {{ gerber_zip }}
build {{ gerber_zip }}: kicad-gerber $pcb
diff --git a/src/ee/xml/types.py b/src/ee/xml/types.py
index 8e5e39f..a6ef46b 100644
--- a/src/ee/xml/types.py
+++ b/src/ee/xml/types.py
@@ -3,7 +3,7 @@
#
# Generated by generateDS.py.
-# Python 3.7.2+ (default, Feb 2 2019, 14:31:48) [GCC 8.2.0]
+# Python 3.7.3rc1 (default, Mar 13 2019, 11:01:15) [GCC 8.3.0]
#
# Command line options:
# ('-f', '')
@@ -729,10 +729,11 @@ def _cast(typ, value):
class PartDb(GeneratedsSuper):
subclass = None
superclass = None
- def __init__(self, parts=None, **kwargs_):
+ def __init__(self, parts=None, assembly=None, **kwargs_):
self.original_tagname_ = None
self.parent_object_ = kwargs_.get('parent_object_')
self.parts = parts
+ self.assembly = assembly
def factory(*args_, **kwargs_):
if CurrentSubclassModule_ is not None:
subclass = getSubclassFromModule_(
@@ -749,9 +750,15 @@ class PartDb(GeneratedsSuper):
def set_parts(self, parts):
self.parts = parts
partsProp = property(get_parts, set_parts)
+ def get_assembly(self):
+ return self.assembly
+ def set_assembly(self, assembly):
+ self.assembly = assembly
+ assemblyProp = property(get_assembly, set_assembly)
def hasContent_(self):
if (
- self.parts is not None
+ self.parts is not None or
+ self.assembly is not None
):
return True
else:
@@ -786,6 +793,8 @@ class PartDb(GeneratedsSuper):
eol_ = ''
if self.parts is not None:
self.parts.export(outfile, level, namespaceprefix_, namespacedef_='', name_='parts', pretty_print=pretty_print)
+ if self.assembly is not None:
+ self.assembly.export(outfile, level, namespaceprefix_, namespacedef_='', name_='assembly', pretty_print=pretty_print)
def build(self, node):
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
@@ -801,6 +810,11 @@ class PartDb(GeneratedsSuper):
obj_.build(child_)
self.parts = obj_
obj_.original_tagname_ = 'parts'
+ elif nodeName_ == 'assembly':
+ obj_ = Assembly.factory(parent_object_=self)
+ obj_.build(child_)
+ self.assembly = obj_
+ obj_.original_tagname_ = 'assembly'
# end class PartDb
@@ -969,7 +983,7 @@ class Part(GeneratedsSuper):
self.links = obj_
obj_.original_tagname_ = 'links'
elif nodeName_ == 'references':
- obj_ = ReferencesList.factory(parent_object_=self)
+ obj_ = ReferenceList.factory(parent_object_=self)
obj_.build(child_)
self.references = obj_
obj_.original_tagname_ = 'references'
@@ -1392,10 +1406,10 @@ class SchematicReference(GeneratedsSuper):
# end class SchematicReference
-class ReferencesList(GeneratedsSuper):
+class ReferenceList(GeneratedsSuper):
subclass = None
superclass = None
- def __init__(self, part_reference=None, schematic_reference=None, part_number=None, supplier_part_number=None, **kwargs_):
+ def __init__(self, part_reference=None, schematic_reference=None, part_number=None, supplier_part_number=None, description=None, **kwargs_):
self.original_tagname_ = None
self.parent_object_ = kwargs_.get('parent_object_')
if part_reference is None:
@@ -1414,16 +1428,20 @@ class ReferencesList(GeneratedsSuper):
self.supplier_part_number = []
else:
self.supplier_part_number = supplier_part_number
+ if description is None:
+ self.description = []
+ else:
+ self.description = description
def factory(*args_, **kwargs_):
if CurrentSubclassModule_ is not None:
subclass = getSubclassFromModule_(
- CurrentSubclassModule_, ReferencesList)
+ CurrentSubclassModule_, ReferenceList)
if subclass is not None:
return subclass(*args_, **kwargs_)
- if ReferencesList.subclass:
- return ReferencesList.subclass(*args_, **kwargs_)
+ if ReferenceList.subclass:
+ return ReferenceList.subclass(*args_, **kwargs_)
else:
- return ReferencesList(*args_, **kwargs_)
+ return ReferenceList(*args_, **kwargs_)
factory = staticmethod(factory)
def get_part_reference(self):
return self.part_reference
@@ -1477,18 +1495,32 @@ class ReferencesList(GeneratedsSuper):
def replace_supplier_part_number_at(self, index, value):
self.supplier_part_number[index] = value
supplier_part_numberProp = property(get_supplier_part_number, set_supplier_part_number)
+ def get_description(self):
+ return self.description
+ def set_description(self, description):
+ self.description = description
+ def add_description(self, value):
+ self.description.append(value)
+ def add_description(self, value):
+ self.description.append(value)
+ def insert_description_at(self, index, value):
+ self.description.insert(index, value)
+ def replace_description_at(self, index, value):
+ self.description[index] = value
+ descriptionProp = property(get_description, set_description)
def hasContent_(self):
if (
self.part_reference or
self.schematic_reference or
self.part_number or
- self.supplier_part_number
+ self.supplier_part_number or
+ self.description
):
return True
else:
return False
- def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='ReferencesList', pretty_print=True):
- imported_ns_def_ = GenerateDSNamespaceDefs_.get('ReferencesList')
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='ReferenceList', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('ReferenceList')
if imported_ns_def_ is not None:
namespacedef_ = imported_ns_def_
if pretty_print:
@@ -1500,17 +1532,17 @@ class ReferencesList(GeneratedsSuper):
showIndent(outfile, level, pretty_print)
outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
already_processed = set()
- self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='ReferencesList')
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='ReferenceList')
if self.hasContent_():
outfile.write('>%s' % (eol_, ))
- self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='ReferencesList', pretty_print=pretty_print)
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='ReferenceList', pretty_print=pretty_print)
showIndent(outfile, level, pretty_print)
outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
else:
outfile.write('/>%s' % (eol_, ))
- def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='ReferencesList'):
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='ReferenceList'):
pass
- def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='ReferencesList', fromsubclass_=False, pretty_print=True):
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='ReferenceList', fromsubclass_=False, pretty_print=True):
if pretty_print:
eol_ = '\n'
else:
@@ -1523,6 +1555,9 @@ class ReferencesList(GeneratedsSuper):
part_number_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='part-number', pretty_print=pretty_print)
for supplier_part_number_ in self.supplier_part_number:
supplier_part_number_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='supplier-part-number', pretty_print=pretty_print)
+ for description_ in self.description:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%sdescription>%s</%sdescription>%s' % (namespaceprefix_ , self.gds_encode(self.gds_format_string(quote_xml(description_), input_name='description')), namespaceprefix_ , eol_))
def build(self, node):
already_processed = set()
self.buildAttributes(node, node.attrib, already_processed)
@@ -1553,7 +1588,11 @@ class ReferencesList(GeneratedsSuper):
obj_.build(child_)
self.supplier_part_number.append(obj_)
obj_.original_tagname_ = 'supplier-part-number'
-# end class ReferencesList
+ elif nodeName_ == 'description':
+ description_ = child_.text
+ description_ = self.gds_validate_string(description_, node, 'description')
+ self.description.append(description_)
+# end class ReferenceList
class Fact(GeneratedsSuper):
@@ -2297,6 +2336,283 @@ class LinkList(GeneratedsSuper):
# end class LinkList
+class AssemblyPart(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, references=None, count=None, sub_parts=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.references = references
+ self.count = count
+ self.sub_parts = sub_parts
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, AssemblyPart)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if AssemblyPart.subclass:
+ return AssemblyPart.subclass(*args_, **kwargs_)
+ else:
+ return AssemblyPart(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_references(self):
+ return self.references
+ def set_references(self, references):
+ self.references = references
+ referencesProp = property(get_references, set_references)
+ def get_count(self):
+ return self.count
+ def set_count(self, count):
+ self.count = count
+ countProp = property(get_count, set_count)
+ def get_sub_parts(self):
+ return self.sub_parts
+ def set_sub_parts(self, sub_parts):
+ self.sub_parts = sub_parts
+ sub_partsProp = property(get_sub_parts, set_sub_parts)
+ def hasContent_(self):
+ if (
+ self.references is not None or
+ self.count is not None or
+ self.sub_parts is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='AssemblyPart', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('AssemblyPart')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.original_tagname_ is not None:
+ name_ = self.original_tagname_
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='AssemblyPart')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='AssemblyPart', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='AssemblyPart'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='AssemblyPart', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.references is not None:
+ self.references.export(outfile, level, namespaceprefix_, namespacedef_='', name_='references', pretty_print=pretty_print)
+ if self.count is not None:
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%scount>%s</%scount>%s' % (namespaceprefix_ , self.gds_format_double(self.count, input_name='count'), namespaceprefix_ , eol_))
+ if self.sub_parts is not None:
+ self.sub_parts.export(outfile, level, namespaceprefix_, namespacedef_='', name_='sub-parts', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'references':
+ obj_ = ReferenceList.factory(parent_object_=self)
+ obj_.build(child_)
+ self.references = obj_
+ obj_.original_tagname_ = 'references'
+ elif nodeName_ == 'count' and child_.text:
+ sval_ = child_.text
+ try:
+ fval_ = float(sval_)
+ except (TypeError, ValueError) as exp:
+ raise_parse_error(child_, 'requires float or double: %s' % exp)
+ fval_ = self.gds_validate_float(fval_, node, 'count')
+ self.count = fval_
+ elif nodeName_ == 'sub-parts':
+ obj_ = AssemblyPartList.factory(parent_object_=self)
+ obj_.build(child_)
+ self.sub_parts = obj_
+ obj_.original_tagname_ = 'sub-parts'
+# end class AssemblyPart
+
+
+class AssemblyPartList(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, assembly_part=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ if assembly_part is None:
+ self.assembly_part = []
+ else:
+ self.assembly_part = assembly_part
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, AssemblyPartList)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if AssemblyPartList.subclass:
+ return AssemblyPartList.subclass(*args_, **kwargs_)
+ else:
+ return AssemblyPartList(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_assembly_part(self):
+ return self.assembly_part
+ def set_assembly_part(self, assembly_part):
+ self.assembly_part = assembly_part
+ def add_assembly_part(self, value):
+ self.assembly_part.append(value)
+ def add_assembly_part(self, value):
+ self.assembly_part.append(value)
+ def insert_assembly_part_at(self, index, value):
+ self.assembly_part.insert(index, value)
+ def replace_assembly_part_at(self, index, value):
+ self.assembly_part[index] = value
+ assembly_partProp = property(get_assembly_part, set_assembly_part)
+ def hasContent_(self):
+ if (
+ self.assembly_part
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='AssemblyPartList', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('AssemblyPartList')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.original_tagname_ is not None:
+ name_ = self.original_tagname_
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='AssemblyPartList')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='AssemblyPartList', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='AssemblyPartList'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='AssemblyPartList', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ for assembly_part_ in self.assembly_part:
+ assembly_part_.export(outfile, level, namespaceprefix_, namespacedef_='', name_='assembly-part', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'assembly-part':
+ obj_ = AssemblyPart.factory(parent_object_=self)
+ obj_.build(child_)
+ self.assembly_part.append(obj_)
+ obj_.original_tagname_ = 'assembly-part'
+# end class AssemblyPartList
+
+
+class Assembly(GeneratedsSuper):
+ subclass = None
+ superclass = None
+ def __init__(self, assembly_parts=None, **kwargs_):
+ self.original_tagname_ = None
+ self.parent_object_ = kwargs_.get('parent_object_')
+ self.assembly_parts = assembly_parts
+ def factory(*args_, **kwargs_):
+ if CurrentSubclassModule_ is not None:
+ subclass = getSubclassFromModule_(
+ CurrentSubclassModule_, Assembly)
+ if subclass is not None:
+ return subclass(*args_, **kwargs_)
+ if Assembly.subclass:
+ return Assembly.subclass(*args_, **kwargs_)
+ else:
+ return Assembly(*args_, **kwargs_)
+ factory = staticmethod(factory)
+ def get_assembly_parts(self):
+ return self.assembly_parts
+ def set_assembly_parts(self, assembly_parts):
+ self.assembly_parts = assembly_parts
+ assembly_partsProp = property(get_assembly_parts, set_assembly_parts)
+ def hasContent_(self):
+ if (
+ self.assembly_parts is not None
+ ):
+ return True
+ else:
+ return False
+ def export(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='Assembly', pretty_print=True):
+ imported_ns_def_ = GenerateDSNamespaceDefs_.get('Assembly')
+ if imported_ns_def_ is not None:
+ namespacedef_ = imported_ns_def_
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.original_tagname_ is not None:
+ name_ = self.original_tagname_
+ showIndent(outfile, level, pretty_print)
+ outfile.write('<%s%s%s' % (namespaceprefix_, name_, namespacedef_ and ' ' + namespacedef_ or '', ))
+ already_processed = set()
+ self.exportAttributes(outfile, level, already_processed, namespaceprefix_, name_='Assembly')
+ if self.hasContent_():
+ outfile.write('>%s' % (eol_, ))
+ self.exportChildren(outfile, level + 1, namespaceprefix_, namespacedef_, name_='Assembly', pretty_print=pretty_print)
+ showIndent(outfile, level, pretty_print)
+ outfile.write('</%s%s>%s' % (namespaceprefix_, name_, eol_))
+ else:
+ outfile.write('/>%s' % (eol_, ))
+ def exportAttributes(self, outfile, level, already_processed, namespaceprefix_='', name_='Assembly'):
+ pass
+ def exportChildren(self, outfile, level, namespaceprefix_='', namespacedef_='', name_='Assembly', fromsubclass_=False, pretty_print=True):
+ if pretty_print:
+ eol_ = '\n'
+ else:
+ eol_ = ''
+ if self.assembly_parts is not None:
+ self.assembly_parts.export(outfile, level, namespaceprefix_, namespacedef_='', name_='assembly-parts', pretty_print=pretty_print)
+ def build(self, node):
+ already_processed = set()
+ self.buildAttributes(node, node.attrib, already_processed)
+ for child in node:
+ nodeName_ = Tag_pattern_.match(child.tag).groups()[-1]
+ self.buildChildren(child, node, nodeName_)
+ return self
+ def buildAttributes(self, node, attrs, already_processed):
+ pass
+ def buildChildren(self, child_, node, nodeName_, fromsubclass_=False):
+ if nodeName_ == 'assembly-parts':
+ obj_ = AssemblyPartList.factory(parent_object_=self)
+ obj_.build(child_)
+ self.assembly_parts = obj_
+ obj_.original_tagname_ = 'assembly-parts'
+# end class Assembly
+
+
GDSClassesMapping = {
'part': Part,
'part-db': PartDb,
@@ -2428,6 +2744,9 @@ if __name__ == '__main__':
__all__ = [
"Amount",
+ "Assembly",
+ "AssemblyPart",
+ "AssemblyPartList",
"DistributorInfo",
"Fact",
"FactList",
@@ -2440,7 +2759,7 @@ __all__ = [
"PartReference",
"PriceBreak",
"PriceBreakList",
- "ReferencesList",
+ "ReferenceList",
"SchematicReference",
"SupplierPartNumber"
]
diff --git a/xsd/ee.xsd b/xsd/ee.xsd
index 446bab7..32c97b3 100644
--- a/xsd/ee.xsd
+++ b/xsd/ee.xsd
@@ -39,6 +39,7 @@ TODO: rename 'id' to 'url'.
<xs:complexType name="PartDb">
<xs:sequence>
<xs:element name="parts" type="PartList" minOccurs="0"/>
+ <xs:element name="assembly" type="Assembly" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
@@ -49,7 +50,7 @@ TODO: rename 'id' to 'url'.
<xs:element name="part-type" type="xs:anyURI"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="links" type="LinkList"/>
- <xs:element name="references" type="ReferencesList"/>
+ <xs:element name="references" type="ReferenceList"/>
<xs:element name="distributor-info" type="DistributorInfo"/>
<xs:element name="facts" type="FactList"/>
<xs:element name="price-breaks" type="PriceBreakList"/>
@@ -87,13 +88,14 @@ TODO: rename 'id' to 'url'.
</xs:sequence>
</xs:complexType>
- <xs:complexType name="ReferencesList">
+ <xs:complexType name="ReferenceList">
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element name="part-reference" type="PartReference"/>
<xs:element name="schematic-reference" type="SchematicReference"/>
<xs:element name="part-number" type="PartNumber"/>
<xs:element name="supplier-part-number" type="SupplierPartNumber"/>
+ <xs:element name="description" type="xs:string"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
@@ -149,4 +151,25 @@ TODO: rename 'id' to 'url'.
</xs:sequence>
</xs:complexType>
+ <!-- Assembly should probably be its own format -->
+ <xs:complexType name="AssemblyPart">
+ <xs:sequence>
+ <xs:element name="references" type="ReferenceList"/>
+ <xs:element name="count" type="xs:double" minOccurs="0"/>
+ <xs:element name="sub-parts" type="AssemblyPartList" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="AssemblyPartList">
+ <xs:sequence>
+ <xs:element name="assembly-part" type="AssemblyPart" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Assembly">
+ <xs:sequence>
+ <xs:element name="assembly-parts" type="AssemblyPartList"/>
+ </xs:sequence>
+ </xs:complexType>
+
</xs:schema>