#-*- Python -*-
""".. module:: Swoop
.. moduleauthor:: Steven Swanson (swanson@cs.ucsd.edu)
Swoop is a library of Python objects for representing and manipulating
Cadsoft Eagle board, schematic, and library files used in designing printed
circuit boards (PCBs). It parses an input Eagle file, creates a internal
representation data structure that represents the file's contents,
provides accessors and mutators to query, read, and modify those contents, and
generates valid Eagle files as output.
Swoop uses several different objects to represent and manipulate Eagle files.
1. **EagleFilePart** Swoop use a tree of :class:`EagleFilePart` objects to represent an Eagle file. There many subclasses of :class:`EagleFilePart` that correspond to different parts of the file.
2. **Utility classes** Most notably :class:`From` which provides a fluent interface for Eagle files and :class:`EagleFilePartVisitor` which implements a visitor framework for Swoop data structures.
3. **Exception classes** For reporting errors.
In addition, Swoop provides a :doc:`several mechanisms </ExtendingSwoop>` for extending its functionality.
Because the Swoop data structures map (almost) directly to Eagle file
structures, some understanding of the Eagle file format is necessary in order
to use Swoop. However, it is possible to use Swoop without understanding all
the details the format. The eagle.dtd that ships with Eagle (in the 'doc'
directory) is a good place to start learning about the file format. If you are
familiar with Eagle, the file format is relatively easy to understand.
The code for most of Swoop is autogenerated by a Python script called
:code:`GenerateSwoop.py` using the Jinja templating system.
Swoop was created by the `NVSL <http://nvsl.ucsd.edu/>`_ at `UCSD <http://www.ucsd.edu/>`_ as part of the `Gadgetron project <http://nvsl.ucsd.edu/index.php?path=projects/gadget>`_.
"""
from lxml import etree as ET
import eagleDTD
import StringIO
import logging as log
import copy
import os
import re
supportedVersions = ["6.5.0", "6.6.0", "7.0.0", "7.1.0", "7.2.0"]
def NotImplemented(s):
raise NotImplementedError(s)
[docs]class SwoopError (Exception):
"""
An internal error occurred.
"""
def __init__(self, text):
self.text = text
def __str__(self):
return self.text
[docs]class EagleFilePart(object):
"""
Base class for all eagle tag objects. It provides fallback implementations
of core features, facilities for navagating the part tree, and provides the
:code:`parent` attribute.
"""
def __init__(self):
self.parent = None
[docs] def get_file(self):
"""
Get the :class:`EagleFile` containing this object.
:rtype: :class:`EagleFile`
"""
r = self.get_root()
if isinstance(r, EagleFile):
return r
else:
return None
def get_class_for_tag(self, tag):
if self.get_file() is None:
raise NotImplementedError("Creation of children from file-less EFPs is not supported")
# print "---"
# print type(self.get_file()).__name__
# print type(self.get_file()).class_map["library"]
# print "+++"
return type(self.get_file()).class_map[tag]
[docs] def get_parent(self):
"""
Get this object's parent.
:returns: The object's parent.
:rtype: :class:`EagleFilePart`
"""
return self.parent
[docs] def detach(self):
"""
Remove this :class:'EagleFilePart` from its parent.
:returns: :code:`self`
:rtype: :class:`EagleFilePart`
"""
self.parent.remove_child(self)
return self
@classmethod
def _from_et (cls, et):
"""
Parse the part from an Element Tree
"""
raise NotImplementedError()
[docs] def get_et ():
"""
Generate an element tree that represents the :code:`EagleFilePart`.
:rtype: :class:`etree.ElementTree`
"""
raise NotImplementedError()
[docs] def get_root(self):
"""
Find the root of this :class:`EagleFilePart` tree.
:rtype: :class:`EagleFilePart`
"""
if self.get_parent() is not None:
return self.get_parent().get_root()
else:
return self
[docs] def clone(self):
"""
Clone the :class:`EagleFilePart`. It should be identical to the orginial, except that the parent should be :code:`None`.
:rtype: :class:`EagleFilePart`
"""
raise NotImplementedError()
[docs] def get_children(self):
"""
Return a list of all the :code:`EagleFilePart` children of this :code:`EagleFilePart`
:rtype: List of :class:`EagleFilePart` objects
"""
raise NotImplementedError()
[docs] def check_sanity(self):
"""
Perform a (recursive) sanity check on this :code:`EagleFilePart`
:rtype: :code:`None`
"""
for i in self.get_children():
if i.parent != self:
raise SwoopError("Parent pointer mismatch. Child = " + str(i) + "; child.parent = " + str(i.parent) + "; Parent = " + str(self) )
i.check_sanity()
[docs] def with_type(self,t):
"""
Filter this :code:`EagleFilePart` object based on its type. For use in combination with :class:`From` objects.
Return :code:`self` if self is an instance of type :code:`t` and :code:`None` otherwise. This is useful in combination with :class:`From` object.
:param t: The type to check for.
:returns: :code:`self` if self is an instance of type :code:`t` and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
return self if isinstance(self, t) else None
[docs] def make_from(self):
"""
Create a a :class:`From` object containing this object.
:returns: :class:`From` object containing this object.
:rtype: :class:`From`
"""
return From(self)
def parseByType(efp, attrType, s):
if attrType == "None_is_empty_string":
if s is None:
r = ""
else:
r = s
elif s is not None:
if attrType == "str":
r = s
elif attrType == "int":
r = int(s)
elif attrType == "float":
r = float(s)
elif attrType == "bool":
if s.upper() in ["YES"]:
r = True
elif s.upper() in ["NO"]:
r = False
else:
raise SwoopError("Invalid eagle bool value '" + s +"' in child of " + str(efp))
elif attrType == "constant_bool":
r = (s != "no")
elif attrType == "layer_string":
r = efp.get_file().layer_number_to_name(int(s))
else:
raise SwoopError("Unknown attr type '" + attrType + "'")
assert r is not None
else:
r = None
return r
def unparseByType(efp, attrType, v):
if attrType == "None_is_empty_string":
if v == "":
r = None
else:
r = v
elif v is not None:
if attrType == "str": # Doing nothing to strings lets us handle weird
# unicode characters.
r = v
elif attrType in ["int", "float"]:
r = str(v)
elif attrType == "bool":
if v:
return "yes"
else:
return "no"
elif attrType == "constant_bool":
if not v:
r = "no"
else:
r = None
elif attrType == "layer_string":
r = str(efp.get_file().layer_name_to_number(v))
else:
raise SwoopError("Unknown attr type '" + attrType + "'")
if attrType != "constant_bool":
assert r is not None
else:
r = None
return r
[docs]class EagleFile(EagleFilePart):
"""
Base class for Eagle files. It handle opening, parsing, validation, associated errors, writing output, and the mapping between layer numbers and layer names.
This class also serves a factory class for :class:`EagleFilePart` objects.
Calling the :meth:`new_*()` methods on an :class:`EagleFile`, yields new
objects that include any Swoop extensions that have been applied.
"""
# A validator for element tree representations of eagle files.
DTD = None if eagleDTD.DTD is None else ET.DTD(StringIO.StringIO(eagleDTD.DTD))
class_map = {}
boardFileType = None
schematicFileType = None
libraryFileType = None
def new_Layer(self):
return type(self).class_map["layer"]()
def new_Via(self):
return type(self).class_map["via"]()
def new_Pin(self):
return type(self).class_map["pin"]()
def new_Text(self):
return type(self).class_map["text"]()
def new_Frame(self):
return type(self).class_map["frame"]()
def new_Portref(self):
return type(self).class_map["portref"]()
def new_Module(self):
return type(self).class_map["module"]()
def new_Connect(self):
return type(self).class_map["connect"]()
def new_Pass(self):
return type(self).class_map["pass"]()
def new_Technology(self):
return type(self).class_map["technology"]()
def new_Port(self):
return type(self).class_map["port"]()
def new_Approved(self):
return type(self).class_map["approved"]()
def new_Wire(self):
return type(self).class_map["wire"]()
def new_Sheet(self):
return type(self).class_map["sheet"]()
def new_Polygon(self):
return type(self).class_map["polygon"]()
def new_Deviceset(self):
return type(self).class_map["deviceset"]()
def new_Param(self):
return type(self).class_map["param"]()
def new_Label(self):
return type(self).class_map["label"]()
def new_Note(self):
return type(self).class_map["note"]()
def new_Instance(self):
return type(self).class_map["instance"]()
def new_Moduleinst(self):
return type(self).class_map["moduleinst"]()
def new_Setting(self):
return type(self).class_map["setting"]()
def new_Pad(self):
return type(self).class_map["pad"]()
def new_Schematic(self):
return type(self).class_map["schematic"]()
def new_Attribute(self):
return type(self).class_map["attribute"]()
def new_Gate(self):
return type(self).class_map["gate"]()
def new_Circle(self):
return type(self).class_map["circle"]()
def new_Smd(self):
return type(self).class_map["smd"]()
def new_Rectangle(self):
return type(self).class_map["rectangle"]()
def new_Junction(self):
return type(self).class_map["junction"]()
def new_Description(self):
return type(self).class_map["description"]()
def new_BoardFile(self):
return type(self).class_map["eagle"]()
def new_Bus(self):
return type(self).class_map["bus"]()
def new_Symbol(self):
return type(self).class_map["symbol"]()
def new_Variant(self):
return type(self).class_map["variant"]()
def new_Compatibility(self):
return type(self).class_map["compatibility"]()
def new_Class(self):
return type(self).class_map["class"]()
def new_Variantdef(self):
return type(self).class_map["variantdef"]()
def new_Part(self):
return type(self).class_map["part"]()
def new_Grid(self):
return type(self).class_map["grid"]()
def new_Library(self):
return type(self).class_map["library"]()
def new_Pinref(self):
return type(self).class_map["pinref"]()
def new_Device(self):
return type(self).class_map["device"]()
def new_Hole(self):
return type(self).class_map["hole"]()
def new_Segment(self):
return type(self).class_map["segment"]()
def new_Net(self):
return type(self).class_map["net"]()
def new_Contactref(self):
return type(self).class_map["contactref"]()
def new_Package(self):
return type(self).class_map["package"]()
def new_Designrules(self):
return type(self).class_map["designrules"]()
def new_Signal(self):
return type(self).class_map["signal"]()
def new_Vertex(self):
return type(self).class_map["vertex"]()
def new_SchematicFile(self):
return type(self).class_map["eagle"]()
def new_Element(self):
return type(self).class_map["element"]()
def new_LibraryFile(self):
return type(self).class_map["eagle"]()
def new_Clearance(self):
return type(self).class_map["clearance"]()
def new_Dimension(self):
return type(self).class_map["dimension"]()
def __init__ (self):
"""
Construct an empty :class:`EagleFile`.
"""
EagleFilePart.__init__(self)
self.filename= None
self.root = None
self.tree = None
self.layers = {}
self.layersByName = {}
@classmethod
def get_schematic_file_type(cls):
if cls.schematicFileType is None:
return SchematicFile
else:
return cls.schematicFileType
@classmethod
def get_board_file_type(cls):
if cls.boardFileType is None:
return BoardFile
else:
return cls.boardFileType
@classmethod
def get_library_file_type(cls):
if cls.libraryFileType is None:
return LibraryFile
else:
return cls.libraryFileType
[docs] def validate(self):
"""
Check that this file conforms to the eagle DTD. Return True, if it does, False otherwise.
:rtype: Bool
"""
et = self.get_et()
if EagleFile.DTD is not None:
v = EagleFile.DTD.validate(et)
else:
log.warning("Can't validate Swoop tree. DTD is missing.")
v = True;
if not v:
log.warning("Eagle file opened as '" + str(self.filename) +"' is invalid: " + str(EagleFile.DTD.error_log.filter_from_errors()[0]))
else:
log.info("Eagle file opened as '" + str(self.filename) +"' parsed to valid Eagle data.")
for t in et.findall(".//*"):
for a in t.attrib.values():
if a == str(None):
log.warning("Eagle file opened as '" + str(self.filename) +"' has 'None' attribute value")
return False
return v
@classmethod
[docs] def open(cls,filename, bestEffort = True):
"""
Loads a Eagle file from a .sch, .lbr, or .brd file. A synonym for :meth:`EagleFile.from_file`
:param filename: Filename to load.
:param bestEffort: If :code:`True`, load the file even if it doesn't conform to the DTD.
:returns: A new :class:`BoardFile`, :class:`LibraryFile`, or :class:`SchematicFile` object
"""
return cls.from_file(filename, bestEffort)
@classmethod
[docs] def from_file (cls, filename, bestEffort = True):
"""
Loads a Eagle file from a .sch, .lbr, or .brd file. A synonym for :meth:`EagleFile.open`
:param filename: Filename to load.
:param bestEffort: If :code:`True`, load the file even if it doesn't conform to the DTD.
:returns: A new :class:`BoardFile`, :class:`LibraryFile`, or :class:`SchematicFile` object
"""
try:
tree = ET.parse(filename)
except ET.XMLSyntaxError as e:
raise EagleFormatError("Eagle file '" + str(filename) +"' doesn't look like XML eagle file. Try resaving with a newer version of eagle.")
root = tree.getroot()
if EagleFile.DTD is not None:
v = EagleFile.DTD.validate(root)
else:
log.warning("Can't validate input file. DTD is missing.")
v = True;
if not v:
if bestEffort:
log.warning("Eagle file opened as '" + str(filename) +"' is invalid on disk: " + str(EagleFile.DTD.error_log.filter_from_errors()[0]))
else:
raise EagleFormatError("Eagle file opened as '" + str(filename) +"' is invalid on disk: " + str(EagleFile.DTD.error_log.filter_from_errors()[0]))
if filename[-4:] == ".sch":
ef = cls.get_schematic_file_type()._from_et(root, None)
elif filename[-4:] == ".brd":
ef = cls.get_board_file_type()._from_et(root, None)
elif filename[-4:] == ".lbr":
ef = cls.get_library_file_type()._from_et(root, None, filename)
else:
raise SwoopError("Unknown file suffix: '" + filename[-4:] + "'")
ef.filename = filename
ef.root = root
ef.tree = tree
if ef.get_version() not in supportedVersions:
if bestEffort:
log.warning("Eagle file opened as '" + str(filename) +"' is not one of " + str(supportedVersions) + ". Doing our best.")
else:
raise EagleFormatError("Eagle file opened as '" + str(filename) +"' is not one of " + str(supportedVersions) + ". Chickening out.")
ef.check_sanity()
return ef
@staticmethod
def from_file_by_type(filename, ftype):
n = EagleFile.from_file(filename)
if not isinstance(n, ftype):
raise SwoopError("File is '" + filename + "' is not " + ftype.__name__)
return n
[docs] def write (self, file, check_sanity=True, dtd_validate=True):
"""
Exports the Schematic to an EAGLE schematic file.
:param file: Filename or file-like object for output.
:param check_sanity: Perform semantic sanity checks before output.
:param dtd_validate: Check for DTD compliance before output.
"""
header="""<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE eagle SYSTEM "eagle.dtd">
"""
if type(file) is str:
f = open(file, "w")
filename = file
else:
f = file
filename = None
if check_sanity:
self.check_sanity()
if dtd_validate and not self.validate():
if filename is not None:
f = open(filename + ".broken.xml", "w")
f.write(header + ET.tostring(ET.ElementTree(self.get_et()),pretty_print=True))
raise SwoopError("Swoop structure does not validate" + str(EagleFile.DTD.error_log.filter_from_errors()[0]))
else:
f.write(header+ET.tostring(ET.ElementTree(self.get_et()),pretty_print=True))
[docs] def add_layer (self, layer):
"""
Add a layer to this file.
:param layer: The :class:`Layer` to add.
:rtype: :code:`None`
"""
assert isinstance(layer, Layer)
self.layers[int(layer.number)] = layer
self.layersByName[layer.name] = layer
layer.parent = self
[docs] def get_layers(self):
"""
Get a map of names to Layer objects
:rtype: Map of :code:`EagleFilePart` objects keyed by layer name.
"""
return self.layersByName
[docs] def get_layersByNumber(self):
"""
Get a map of numbers to Layer objects.
:rtype: Map of :code:`EagleFilePart` objects keyed by layer number.
"""
return self.layers
# def get_flippedLayer(self, l):
# if (isinstance(l, str)):
# origName = l
# if l[0] == "t":
# l = "b" + l[1:]
# elif l[0] == "b":
# l = "t" + l[1:]
# elif l == "Top":
# l = "Bottom"
# elif l == "Bottom":
# l = "Top"
# if l not in self.layersByName:
# raise SwoopError("Tried to flip layer '" + origName + "', but '" + l + "' doesn't exist")
# return name
# elif (isinstance(l,int)):
# if l in self.layers:
# return self.get_flippedLayer(self, self.layers[l]).number
# else:
# raise SwoopError("Can't find layer number " + number)
# elif (isinstance(l,Layer)):
# if l.name in self.layersByName:
# return self.layersByName[get_flippedLayer(l.name)]
# else:
# raise SwoopError("Can't find layer '" + l.name +"' in this file")
def parse_layer_number(self, num):
if num is None:
return None
return self.layer_number_to_name(num)
def unparse_layer_name(self, name):
if name is None:
return None
return self.layer_name_to_number(name)
[docs] def layer_number_to_name(self, num):
"""
Given a layer number, return the name.
:rtype: :class:`Layer`
"""
n = int(num)
if n not in self.layers:
raise SwoopError("No layer number " + str(n) +" in " + str(self.filename))
return self.layers[n].name
[docs] def layer_name_to_number(self, name):
"""
Given a layer name, return the number.
:rtype: :class:`Layer`
"""
assert type(name) is str
if name not in self.layersByName:
raise SwoopError("No layer named '" + name + "' in " + str(self.filename))
return self.layersByName[name].number
[docs] def remove_layer(self, layer):
"""
Remove a layer.
:param layer: :class:`Layer` object, layer name, or layer number that should be deleted.
:rtype: :code:`None`
"""
if type(layer) is str:
l = self.layersByName[layer]
self.remove_layer(l)
elif type(layer) is int:
l = self.layers[layer]
self.remove_layer(l)
elif isinstance(layer, Layer):
self.layersByName[layer.name].parent = None
del self.layersByName[layer.name]
del self.layers[int(layer.number)]
else:
raise SwoopError("Invalid layer spec: " + str(layer))
# def get_manifest(self):
# raise NotImplementedError("Manifest for " + str(type(self)))
[docs] def find_library_by_name(self, l):
"""
Lookup a library by name and return it.
:param l: Library name.
:rtype: :class:`Library` or :code:`None` if the library is not present.
"""
return self.libraries.get(l)
[docs]def Mixin(mixin, prefix, base=EagleFile):
"""Extend Swoop by adding a mixin to every class.
This function creates a new subclasses of every class Swoop uses to
represent an Eagle file (including the file types). The names of the new
classes are prefixed with :code:`prefix` and they all inherit from the
original class and :code:`mixin`.
:param mixin: Mixin class. Its constructor should take no arguments.
:param prefix: Prefix for the class name. It'll be prepended to the names of all the Swoop classes.
:param base: Starting point for the extension. This should either be :class:`Swoop.EagleFile` or a class returned by a previous call to this function.
:returns: A new subclass of :code:`base` that can be used just like :class:`EagleFile`
:rtype: A class.
"""
def Extend(C, m, name):
class T(C,m):
class_map={}
def __init__(self):
C.__init__(self)
m.__init__(self)
T.__name__ = name
return T
n = Extend(base,mixin, prefix + base.__name__)
#print n.class_map.get("library")
for i in base.class_map:
n.class_map[i] = Extend(base.class_map[i], mixin, prefix + base.class_map[i].__name__)
n.boardFileType = Extend(base.get_board_file_type(), mixin, prefix + base.get_board_file_type().__name__)
n.schematicFileType = Extend(base.get_schematic_file_type(), mixin, prefix + base.get_schematic_file_type().__name__)
n.libraryFileType = Extend(base.get_library_file_type(), mixin, prefix + base.get_library_file_type().__name__)
n.boardFileType.class_map = copy.copy(n.class_map)
n.schematicFileType.class_map = copy.copy(n.class_map)
n.libraryFileType.class_map = copy.copy(n.class_map)
# print "there " + str(n)
# print "there " + str(n.boardFileType)
# print "there " + str(n.schematicFileType)
# print "there " + str(n.libraryFileType)
# print "there " + str(n.libraryFileType.class_map)
#print "here" + str(n.class_map.get("library"))
return n
def smartAddSubTags(root, path):
"""
Add tags as need to create a container for the contents of an xpath.
:rtype: :code:`None`
"""
pathSegments = path.split("|")[0].replace("./","").split("/")
target = root
for p in pathSegments[0:-1]:
new_target = target.find(p)
if new_target is None:
target = ET.SubElement(target,p)
else:
target = new_target
return target
def filter_list(l, match_type, attrs):
r = []
if attrs is None:
attrs = {}
for efp in l:
match = True
for k in attrs:
if type(attrs[k]) in [str,int,float]:
match = match and getattr(efp,k) == attrs[k]
elif callable(attrs[k]):
match = match and attrs[k](efp)
else:
assert False
if match_type is not None:
match = match and isinstance(efp, match_type)
if match:
r.append(efp)
return r
def matching(e):
"""Helper function for filtering :class:`From` objects. The filter allows
items to pass based on whether they match the regex :code:`e`. For
example, this will print the number of packages with names starting with
"FOO" in a library.
.. code-block:: python
print(From(library).
get_packages().
with_name(matching("^FOO.*")).count()
"""
return lambda x: re.match(e, x) is not None
def not_matching(e):
"""Helper function for filtering :class:`From` objects. The filter allows
items to pass based on whether they *don't* match the regex :code:`e`.
For example, this will print the number of packages with names not starting
with "FOO" in a library.
.. code-block:: python
print(From(library).
get_packages().
with_name(not_matching("^FOO.*")).count()
"""
return lambda x: re.match(e, x) is None
[docs]class From(object):
"""An ordered collection of (usually) :class:`EagleFilePart` objects. Invoke
a method on a :class:`From` object, invokes the same method with the same
arguments on all the objects it holds. The results are placed in a new
:class:`From` object that is returned.
:class:`From` objects also provide several utility functions for
accessing, filtering, mapping, and reducing their contents.
You can combine the contents of the two :class:`From` objects with the
:code`+` operator.
:class:`From` objects are iterable.
"""
def __init__(self, *args):
r = []
for i in args:
if type(i) is list:
r += i
elif type(i) == From:
r += i.efps
else:
r += [i]
self.efps = r
def __str__(self):
return "From: " + str(self.efps)
def __repr__(self):
return self.__str__()
def __len__(self):
return len(self.efps)
def __getitem__(self,n):
return self.efps[n]
def __add__(self, rhs):
return self.append(rhs)
def __getattr__(self, name):
def wrapper(*args, **kargs):
r = []
for i in self.efps:
t = getattr(i,name)(*args,**kargs)
if type(t) is dict:
r += t.values()
elif type(t) is list:
r += t
elif t is None:
pass
else:
r.append(t)
return From(r)
return wrapper
[docs] def append(self, l):
"""
Merge the contents of :code:`l` into this :class`From` object.
:param l: Python list of :class:`EagleFilePart` objects, a :class:`From` object, or an :class:`EagleFilePart` object.
:returns: This :class:`From` object with the new items added.
:rtype: :class:`From`
"""
if type(l) is list:
self.efps += i
elif type(l) == From:
self.efps += l.efps
else:
self.efps += [l]
return self
[docs] def unpack(self):
"""
Return the contents of the :class:`From` object as a list.
:returns: A list containing the contents of the :class:`From`
:rtype: List
"""
return self.efps
[docs] def first(self):
"""
Return the first item in the :class:`From` object. If the :class:`From` is empty, raise an :class:`IndexError` exception.
:returns: The first item in the :class:`From`
:rtype: Varies
:throws: :class:`IndexError`
"""
return self.efps[0]
[docs] def filtered_by(self, func):
"""
Filter the :class:`From`. Similar to the builtin :code:`filter` method.
:returns: A :class:`From` object contain the elements, :code:`x` for which :code:`func(x)` return :code:`True`
"""
return From([x for x in self.efps if func(x)])
[docs] def unique(self):
"""
Remove duplicate elements from the :class:`From`
:returns: A :class:`From` object contain the unique elements in this :class:`From`.
"""
return From(list(set(self.efps)))
[docs] def count(self):
"""
Count the elements in the :class:`From`
:returns: The number of elements.
:rtype: int
"""
return len(self.efps)
[docs] def sort(self, cmp=None, key=None, reverse=False):
"""
Sort the :class:`From` object. Similar to the builtin :code:`sorted` method (and takes the same arguments).
:param cmp: Comparison function.
:param key: A key accessor function.
:param reverse: If :code:`True` sort in reverse order.
:returns: A sorted :class:`From`
"""
return From(sorted(self.efps, cmp, key, reverse))
[docs] def map(self, func):
"""
Apply a function to the elments of this :class:`From` and return a :class:`From` containing the results. Similar to the builtin :code:`map` function.
:param func: The function to apply.
:returns: A :class:`From` containing the results.
"""
return From(map(func, self.efps))
[docs] def apply(self, func):
"""Apply a function to the elments of this :class:`From` and return a
:class:`From` containing the results. Similar to the builtin
:code:`map` function. A synonym for :meth:`From.map`.
:param func: The function to apply.
:returns: A :class:`From` containing the results.
"""
return From(map(func, self.efps))
[docs] def reduce(self, func, init=None):
"""
Reduce the elments of this :class:`From` and return the result. Similar to the builtin :code:`reduce` function.
:param func: The function to apply.
:param init: The starting value for the reduction.
:returns: The reduce result
:rtype: Varies
"""
if init is None:
return reduce(func, self.efps)
else:
return reduce(func, self.efps, init)
def from_file(filename):
return From(EagleFile.from_file(filename))
class EagleFilePartVisitor(object):
"""A visitor utility class for :class:`EagleFile` objects.
The class traverses a subtree of :class:`EagleFilePart` objects in
depth-first order. Subclasses can define *vistor* methods of the form
:code:`*X*_pre()` and :code:`*X*_post()` that will be called in pre-order
and post-order during the traversal. If a subclass doesn't define a
particular an :class:`EagleFilePart` subclass, :meth:`default_pre` and
:meth:`default_pre` will be used instead.
Subclasses can also override :meth:`visitFilter` and
:meth:`decendFilter` to control which :class:`EagleFilePart` the visitor
invokes the visitor methods on and which :class:`EagleFilePart` the visitor
decends into. By default, both visitor methods are called on all
:class:`EagleFilePart` objects and in the visitor always decends.
The :meth:`go` method start execution. It also returns :code:`self` so
you can easily apply accessor functions after execution. You can also call
:meth:`visit` on an :class:`EagleFilePart` object to visit the subtree
underneath it
For example, here's a simple visitor that counts the total number of
:class:`EagleFileParts` in a file and, separately, the number of
:class:`Element` objects:
.. code-block:: python
class Counter(SwoopTools.EagleFilePartVisitor):
def __init__(self, root=None):
SwoopTools.EagleFilePartVisitor.__init__(self,root)
self.count = 0;
self.elementCount = 0
self.layerCount = 0
def default_pre(self, efp):
self.count += 1
def Element_pre(self, e):
self.count += 1
self.elementCount += 1
And you can use it like so:
.. code-block:: python
from Swoop import *
from SwoopTools import *
ef = EagleFile.from_file(my_file)
c = Counter(ef)
print "The file has this many parts: " + str(c.go().count)
print "There are this many Elements: " + str(c.elementCount)
"""
def __init__(self, root=None):
self.root = root
def go(self):
"""
Start the visiting process.
:rtype: :code:`self`
"""
self.visit(self.root)
return self
def visitFilter(self, e):
"""Predicate that determines whether to call the visit functions on this
:class:`EagleFilePart`. The default implementation returns ``True``.
:param e: The :class:`EagleFilePart` to be visited.
:rtype: ``Bool``
"""
return True
def decendFilter(self, e):
"""Predicate that determines whether to decend into the subtree rooted at ``e``. The default implementation returns ``True``.
:param e: The root :class:`EagleFilePart`.
:rtype: ``Bool``
"""
return True
def default_pre(self,e):
"""Default pre-order visitor function.
This method can return a value that will be passed to the corresponding
post-order visitor function, making it easy to pass state between the
two.
The default implementation does nothing and returns ``None``
:param e: The :class:`EagleFilePart` being visited.
:rtype: Any
"""
return None
def default_post(self,e, context):
"""Default post-order visitor function. The default implementation does nothing.
:param e: The :class:`EagleFilePart` being visited.
:param context: The value returned by corresponding pre-order visitor.
:rype: ``None``
"""
pass
def visit(self, efp):
""" Run this visitor on the subtree rooted at ``efp``.
:param efp: The :class:`EagleFilePart` at the root of the tree.
:rtype: ``self``
"""
if self.visitFilter(efp):
context = efp.accept_preorder_visitor(self)
if self.decendFilter(efp):
for e in efp.get_children():
self.visit(e)
if self.visitFilter(efp):
context = efp.accept_postorder_visitor(self, context)
return self
class Layer(EagleFilePart):
"""
Class representing the contents of a <layer> tag in Eagle files.
Attributes:
* :code:`number`
* :code:`name`
* :code:`color`
* :code:`fill`
* :code:`visible`
* :code:`active`
"""
def __init__(self):
"""
Construct an empty :class:`Layer` object.
"""
EagleFilePart.__init__(self)
self.number=None
self.name=None
self.color=None
self.fill=None
self.visible=None
self.active=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Layer` from a :code:`layer` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Layer`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Layer` from a :code:`layer` element. This is useful if you have a subclass of :class:`Layer` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Layer`
"""
if root.tag != "layer":
raise EagleFormatError("Tried to create layer from " + root.tag)
self.number=parseByType(parent, "int", root.get("number"))
self.name=parseByType(parent, "str", root.get("name"))
self.color=parseByType(parent, "int", root.get("color"))
self.fill=parseByType(parent, "int", root.get("fill"))
self.visible=parseByType(parent, "bool", root.get("visible"))
self.active=parseByType(parent, "bool", root.get("active"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
return self.number;
def get_et(self):
"""
Generate a <layer> element tree for a :class:`Layer`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("layer")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "int", self.number)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("number", v)
else:
r.set("number", "")
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "int", self.color)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("color", v)
else:
r.set("color", "")
## Unparse the values.
v = unparseByType(self, "int", self.fill)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("fill", v)
else:
r.set("fill", "")
## Unparse the values.
v = unparseByType(self, "bool", self.visible)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("visible", v)
## Unparse the values.
v = unparseByType(self, "bool", self.active)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("active", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
def clone(self):
"""
Recursively clone this :code:`Layer`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Layer`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Layer_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Layer_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
def get_number(self):
""" Return the value of :code:`number` for this :class:`Layer`. This corresponds to the :code:`number` attribute of a :code:`<layer>` in an Eagle file.
:rtype: :code:`int`
"""
return self.number
def set_number(self,v):
""" Set the value of :code:`number` for this :class:`Layer`. This corresponds to the :code:`number` attribute of a :code:`<layer>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.number = v
return self
def with_number(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`number`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`number` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_number()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.number == v else None
elif callable(v):
return self if v(self.number) else None
def get_name(self):
""" Return the value of :code:`name` for this :class:`Layer`. This corresponds to the :code:`name` attribute of a :code:`<layer>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Layer`. This corresponds to the :code:`name` attribute of a :code:`<layer>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
def get_color(self):
""" Return the value of :code:`color` for this :class:`Layer`. This corresponds to the :code:`color` attribute of a :code:`<layer>` in an Eagle file.
:rtype: :code:`int`
"""
return self.color
def set_color(self,v):
""" Set the value of :code:`color` for this :class:`Layer`. This corresponds to the :code:`color` attribute of a :code:`<layer>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.color = v
return self
def with_color(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`color`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`color` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_color()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.color == v else None
elif callable(v):
return self if v(self.color) else None
def get_fill(self):
""" Return the value of :code:`fill` for this :class:`Layer`. This corresponds to the :code:`fill` attribute of a :code:`<layer>` in an Eagle file.
:rtype: :code:`int`
"""
return self.fill
def set_fill(self,v):
""" Set the value of :code:`fill` for this :class:`Layer`. This corresponds to the :code:`fill` attribute of a :code:`<layer>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.fill = v
return self
def with_fill(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`fill`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`fill` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_fill()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.fill == v else None
elif callable(v):
return self if v(self.fill) else None
def get_visible(self):
""" Return the value of :code:`visible` for this :class:`Layer`. This corresponds to the :code:`visible` attribute of a :code:`<layer>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.visible
def set_visible(self,v):
""" Set the value of :code:`visible` for this :class:`Layer`. This corresponds to the :code:`visible` attribute of a :code:`<layer>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.visible = v
return self
def with_visible(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`visible`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`visible` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_visible()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.visible == v else None
elif callable(v):
return self if v(self.visible) else None
def get_active(self):
""" Return the value of :code:`active` for this :class:`Layer`. This corresponds to the :code:`active` attribute of a :code:`<layer>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.active
def set_active(self,v):
""" Set the value of :code:`active` for this :class:`Layer`. This corresponds to the :code:`active` attribute of a :code:`<layer>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.active = v
return self
def with_active(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`active`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`active` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_active()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.active == v else None
elif callable(v):
return self if v(self.active) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["layer"] = Layer
[docs]class Via(EagleFilePart):
"""
Class representing the contents of a <via> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
* :code:`extent`
* :code:`drill`
* :code:`diameter`
* :code:`shape`
* :code:`alwaysstop`
"""
def __init__(self):
"""
Construct an empty :class:`Via` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
self.extent=None
self.drill=None
self.diameter=None
self.shape=None
self.alwaysstop=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Via` from a :code:`via` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Via`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Via` from a :code:`via` element. This is useful if you have a subclass of :class:`Via` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Via`
"""
if root.tag != "via":
raise EagleFormatError("Tried to create via from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.extent=parseByType(parent, "str", root.get("extent"))
self.drill=parseByType(parent, "float", root.get("drill"))
self.diameter=parseByType(parent, "float", root.get("diameter"))
self.shape=parseByType(parent, "str", root.get("shape"))
self.alwaysstop=parseByType(parent, "bool", root.get("alwaysstop"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.extent)
r = r + str(self.drill)
r = r + str(self.diameter)
r = r + str(self.shape)
r = r + str(self.alwaysstop)
return r
[docs] def get_et(self):
"""
Generate a <via> element tree for a :class:`Via`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("via")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "str", self.extent)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("extent", v)
else:
r.set("extent", "")
## Unparse the values.
v = unparseByType(self, "float", self.drill)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("drill", v)
else:
r.set("drill", "")
## Unparse the values.
v = unparseByType(self, "float", self.diameter)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("diameter", v)
## Unparse the values.
v = unparseByType(self, "str", self.shape)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("shape", v)
## Unparse the values.
v = unparseByType(self, "bool", self.alwaysstop)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("alwaysstop", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Via`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Via`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Via_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Via_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Via`. This corresponds to the :code:`x` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Via`. This corresponds to the :code:`x` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Via`. This corresponds to the :code:`y` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Via`. This corresponds to the :code:`y` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_extent(self):
""" Return the value of :code:`extent` for this :class:`Via`. This corresponds to the :code:`extent` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`str`
"""
return self.extent
[docs] def set_extent(self,v):
""" Set the value of :code:`extent` for this :class:`Via`. This corresponds to the :code:`extent` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.extent = v
return self
[docs] def with_extent(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`extent`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`extent` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_extent()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.extent == v else None
elif callable(v):
return self if v(self.extent) else None
[docs] def get_drill(self):
""" Return the value of :code:`drill` for this :class:`Via`. This corresponds to the :code:`drill` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`float`
"""
return self.drill
[docs] def set_drill(self,v):
""" Set the value of :code:`drill` for this :class:`Via`. This corresponds to the :code:`drill` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.drill = v
return self
[docs] def with_drill(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`drill`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`drill` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_drill()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.drill == v else None
elif callable(v):
return self if v(self.drill) else None
[docs] def get_diameter(self):
""" Return the value of :code:`diameter` for this :class:`Via`. This corresponds to the :code:`diameter` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`float`
"""
return self.diameter
[docs] def set_diameter(self,v):
""" Set the value of :code:`diameter` for this :class:`Via`. This corresponds to the :code:`diameter` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.diameter = v
return self
[docs] def with_diameter(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`diameter`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`diameter` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_diameter()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.diameter == v else None
elif callable(v):
return self if v(self.diameter) else None
[docs] def get_shape(self):
""" Return the value of :code:`shape` for this :class:`Via`. This corresponds to the :code:`shape` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`str`
"""
return self.shape
[docs] def set_shape(self,v):
""" Set the value of :code:`shape` for this :class:`Via`. This corresponds to the :code:`shape` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.shape = v
return self
[docs] def with_shape(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`shape`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`shape` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_shape()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.shape == v else None
elif callable(v):
return self if v(self.shape) else None
[docs] def get_alwaysstop(self):
""" Return the value of :code:`alwaysstop` for this :class:`Via`. This corresponds to the :code:`alwaysstop` attribute of a :code:`<via>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.alwaysstop
[docs] def set_alwaysstop(self,v):
""" Set the value of :code:`alwaysstop` for this :class:`Via`. This corresponds to the :code:`alwaysstop` attribute of a :code:`<via>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.alwaysstop = v
return self
[docs] def with_alwaysstop(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`alwaysstop`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`alwaysstop` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_alwaysstop()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.alwaysstop == v else None
elif callable(v):
return self if v(self.alwaysstop) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["via"] = Via
[docs]class Pin(EagleFilePart):
"""
Class representing the contents of a <pin> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`x`
* :code:`y`
* :code:`visible`
* :code:`length`
* :code:`direction`
* :code:`function`
* :code:`swaplevel`
* :code:`rot`
"""
def __init__(self):
"""
Construct an empty :class:`Pin` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.x=None
self.y=None
self.visible=None
self.length=None
self.direction=None
self.function=None
self.swaplevel=None
self.rot=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Pin` from a :code:`pin` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Pin`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Pin` from a :code:`pin` element. This is useful if you have a subclass of :class:`Pin` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Pin`
"""
if root.tag != "pin":
raise EagleFormatError("Tried to create pin from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.visible=parseByType(parent, "str", root.get("visible"))
self.length=parseByType(parent, "str", root.get("length"))
self.direction=parseByType(parent, "str", root.get("direction"))
self.function=parseByType(parent, "str", root.get("function"))
self.swaplevel=parseByType(parent, "int", root.get("swaplevel"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.visible)
r = r + str(self.length)
r = r + str(self.direction)
r = r + str(self.function)
r = r + str(self.swaplevel)
r = r + str(self.rot)
return r
[docs] def get_et(self):
"""
Generate a <pin> element tree for a :class:`Pin`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("pin")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "str", self.visible)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("visible", v)
## Unparse the values.
v = unparseByType(self, "str", self.length)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("length", v)
## Unparse the values.
v = unparseByType(self, "str", self.direction)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("direction", v)
## Unparse the values.
v = unparseByType(self, "str", self.function)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("function", v)
## Unparse the values.
v = unparseByType(self, "int", self.swaplevel)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("swaplevel", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Pin`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Pin`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Pin_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Pin_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Pin`. This corresponds to the :code:`name` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Pin`. This corresponds to the :code:`name` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Pin`. This corresponds to the :code:`x` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Pin`. This corresponds to the :code:`x` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Pin`. This corresponds to the :code:`y` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Pin`. This corresponds to the :code:`y` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_visible(self):
""" Return the value of :code:`visible` for this :class:`Pin`. This corresponds to the :code:`visible` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`str`
"""
return self.visible
[docs] def set_visible(self,v):
""" Set the value of :code:`visible` for this :class:`Pin`. This corresponds to the :code:`visible` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.visible = v
return self
[docs] def with_visible(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`visible`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`visible` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_visible()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.visible == v else None
elif callable(v):
return self if v(self.visible) else None
[docs] def get_length(self):
""" Return the value of :code:`length` for this :class:`Pin`. This corresponds to the :code:`length` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`str`
"""
return self.length
[docs] def set_length(self,v):
""" Set the value of :code:`length` for this :class:`Pin`. This corresponds to the :code:`length` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.length = v
return self
[docs] def with_length(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`length`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`length` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_length()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.length == v else None
elif callable(v):
return self if v(self.length) else None
[docs] def get_direction(self):
""" Return the value of :code:`direction` for this :class:`Pin`. This corresponds to the :code:`direction` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`str`
"""
return self.direction
[docs] def set_direction(self,v):
""" Set the value of :code:`direction` for this :class:`Pin`. This corresponds to the :code:`direction` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.direction = v
return self
[docs] def with_direction(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`direction`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`direction` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_direction()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.direction == v else None
elif callable(v):
return self if v(self.direction) else None
[docs] def get_function(self):
""" Return the value of :code:`function` for this :class:`Pin`. This corresponds to the :code:`function` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`str`
"""
return self.function
[docs] def set_function(self,v):
""" Set the value of :code:`function` for this :class:`Pin`. This corresponds to the :code:`function` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.function = v
return self
[docs] def with_function(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`function`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`function` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_function()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.function == v else None
elif callable(v):
return self if v(self.function) else None
[docs] def get_swaplevel(self):
""" Return the value of :code:`swaplevel` for this :class:`Pin`. This corresponds to the :code:`swaplevel` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`int`
"""
return self.swaplevel
[docs] def set_swaplevel(self,v):
""" Set the value of :code:`swaplevel` for this :class:`Pin`. This corresponds to the :code:`swaplevel` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.swaplevel = v
return self
[docs] def with_swaplevel(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`swaplevel`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`swaplevel` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_swaplevel()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.swaplevel == v else None
elif callable(v):
return self if v(self.swaplevel) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Pin`. This corresponds to the :code:`rot` attribute of a :code:`<pin>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Pin`. This corresponds to the :code:`rot` attribute of a :code:`<pin>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["pin"] = Pin
[docs]class Text(EagleFilePart):
"""
Class representing the contents of a <text> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
* :code:`size`
* :code:`layer`
* :code:`font`
* :code:`ratio`
* :code:`rot`
* :code:`align`
* :code:`distance`
"""
def __init__(self):
"""
Construct an empty :class:`Text` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
self.size=None
self.layer=None
self.font=None
self.ratio=None
self.rot=None
self.align=None
self.distance=None
self.text = ""
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Text` from a :code:`text` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Text`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Text` from a :code:`text` element. This is useful if you have a subclass of :class:`Text` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Text`
"""
if root.tag != "text":
raise EagleFormatError("Tried to create text from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.size=parseByType(parent, "float", root.get("size"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.font=parseByType(parent, "str", root.get("font"))
self.ratio=parseByType(parent, "int", root.get("ratio"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.align=parseByType(parent, "str", root.get("align"))
self.distance=parseByType(parent, "int", root.get("distance"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
self.text = root.text
def sortkey(self):
r = ""
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.size)
r = r + str(self.layer)
r = r + str(self.font)
r = r + str(self.ratio)
r = r + str(self.rot)
r = r + str(self.align)
r = r + str(self.distance)
return r
[docs] def get_et(self):
"""
Generate a <text> element tree for a :class:`Text`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("text")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.size)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("size", v)
else:
r.set("size", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "str", self.font)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("font", v)
## Unparse the values.
v = unparseByType(self, "int", self.ratio)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("ratio", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
## Unparse the values.
v = unparseByType(self, "str", self.align)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("align", v)
## Unparse the values.
v = unparseByType(self, "int", self.distance)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("distance", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
r.text = self.text
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Text`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Text`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Text_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Text_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Text`. This corresponds to the :code:`x` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Text`. This corresponds to the :code:`x` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Text`. This corresponds to the :code:`y` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Text`. This corresponds to the :code:`y` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_size(self):
""" Return the value of :code:`size` for this :class:`Text`. This corresponds to the :code:`size` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`float`
"""
return self.size
[docs] def set_size(self,v):
""" Set the value of :code:`size` for this :class:`Text`. This corresponds to the :code:`size` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.size = v
return self
[docs] def with_size(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`size`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`size` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_size()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.size == v else None
elif callable(v):
return self if v(self.size) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Text`. This corresponds to the :code:`layer` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Text`. This corresponds to the :code:`layer` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_font(self):
""" Return the value of :code:`font` for this :class:`Text`. This corresponds to the :code:`font` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`str`
"""
return self.font
[docs] def set_font(self,v):
""" Set the value of :code:`font` for this :class:`Text`. This corresponds to the :code:`font` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.font = v
return self
[docs] def with_font(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`font`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`font` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_font()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.font == v else None
elif callable(v):
return self if v(self.font) else None
[docs] def get_ratio(self):
""" Return the value of :code:`ratio` for this :class:`Text`. This corresponds to the :code:`ratio` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`int`
"""
return self.ratio
[docs] def set_ratio(self,v):
""" Set the value of :code:`ratio` for this :class:`Text`. This corresponds to the :code:`ratio` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.ratio = v
return self
[docs] def with_ratio(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`ratio`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`ratio` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_ratio()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.ratio == v else None
elif callable(v):
return self if v(self.ratio) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Text`. This corresponds to the :code:`rot` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Text`. This corresponds to the :code:`rot` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
[docs] def get_align(self):
""" Return the value of :code:`align` for this :class:`Text`. This corresponds to the :code:`align` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`str`
"""
return self.align
[docs] def set_align(self,v):
""" Set the value of :code:`align` for this :class:`Text`. This corresponds to the :code:`align` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.align = v
return self
[docs] def with_align(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`align`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`align` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_align()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.align == v else None
elif callable(v):
return self if v(self.align) else None
[docs] def get_distance(self):
""" Return the value of :code:`distance` for this :class:`Text`. This corresponds to the :code:`distance` attribute of a :code:`<text>` in an Eagle file.
:rtype: :code:`int`
"""
return self.distance
[docs] def set_distance(self,v):
""" Set the value of :code:`distance` for this :class:`Text`. This corresponds to the :code:`distance` attribute of a :code:`<text>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.distance = v
return self
[docs] def with_distance(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`distance`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`distance` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_distance()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.distance == v else None
elif callable(v):
return self if v(self.distance) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def with_text(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`text`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`text` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_text()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.text == v else None
elif callable(v):
return self if v(self.text) else None
else:
raise SwoopError("Illegal type passed to with_text")
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["text"] = Text
[docs]class Frame(EagleFilePart):
"""
Class representing the contents of a <frame> tag in Eagle files.
Attributes:
* :code:`x1`
* :code:`y1`
* :code:`x2`
* :code:`y2`
* :code:`columns`
* :code:`rows`
* :code:`layer`
* :code:`border_left`
* :code:`border_right`
* :code:`border_top`
* :code:`border_bottom`
"""
def __init__(self):
"""
Construct an empty :class:`Frame` object.
"""
EagleFilePart.__init__(self)
self.x1=None
self.y1=None
self.x2=None
self.y2=None
self.columns=None
self.rows=None
self.layer=None
self.border_left=None
self.border_right=None
self.border_top=None
self.border_bottom=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Frame` from a :code:`frame` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Frame`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Frame` from a :code:`frame` element. This is useful if you have a subclass of :class:`Frame` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Frame`
"""
if root.tag != "frame":
raise EagleFormatError("Tried to create frame from " + root.tag)
self.x1=parseByType(parent, "float", root.get("x1"))
self.y1=parseByType(parent, "float", root.get("y1"))
self.x2=parseByType(parent, "float", root.get("x2"))
self.y2=parseByType(parent, "float", root.get("y2"))
self.columns=parseByType(parent, "int", root.get("columns"))
self.rows=parseByType(parent, "int", root.get("rows"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.border_left=parseByType(parent, "bool", root.get("border-left"))
self.border_right=parseByType(parent, "bool", root.get("border-right"))
self.border_top=parseByType(parent, "bool", root.get("border-top"))
self.border_bottom=parseByType(parent, "bool", root.get("border-bottom"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x1)
r = r + str(self.y1)
r = r + str(self.x2)
r = r + str(self.y2)
r = r + str(self.columns)
r = r + str(self.rows)
r = r + str(self.layer)
r = r + str(self.border_left)
r = r + str(self.border_right)
r = r + str(self.border_top)
r = r + str(self.border_bottom)
return r
[docs] def get_et(self):
"""
Generate a <frame> element tree for a :class:`Frame`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("frame")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x1", v)
else:
r.set("x1", "")
## Unparse the values.
v = unparseByType(self, "float", self.y1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y1", v)
else:
r.set("y1", "")
## Unparse the values.
v = unparseByType(self, "float", self.x2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x2", v)
else:
r.set("x2", "")
## Unparse the values.
v = unparseByType(self, "float", self.y2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y2", v)
else:
r.set("y2", "")
## Unparse the values.
v = unparseByType(self, "int", self.columns)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("columns", v)
else:
r.set("columns", "")
## Unparse the values.
v = unparseByType(self, "int", self.rows)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rows", v)
else:
r.set("rows", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "bool", self.border_left)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("border-left", v)
## Unparse the values.
v = unparseByType(self, "bool", self.border_right)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("border-right", v)
## Unparse the values.
v = unparseByType(self, "bool", self.border_top)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("border-top", v)
## Unparse the values.
v = unparseByType(self, "bool", self.border_bottom)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("border-bottom", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Frame`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Frame`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Frame_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Frame_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x1(self):
""" Return the value of :code:`x1` for this :class:`Frame`. This corresponds to the :code:`x1` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x1
[docs] def set_x1(self,v):
""" Set the value of :code:`x1` for this :class:`Frame`. This corresponds to the :code:`x1` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x1 = v
return self
[docs] def with_x1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x1 == v else None
elif callable(v):
return self if v(self.x1) else None
[docs] def get_y1(self):
""" Return the value of :code:`y1` for this :class:`Frame`. This corresponds to the :code:`y1` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y1
[docs] def set_y1(self,v):
""" Set the value of :code:`y1` for this :class:`Frame`. This corresponds to the :code:`y1` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y1 = v
return self
[docs] def with_y1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y1 == v else None
elif callable(v):
return self if v(self.y1) else None
[docs] def get_x2(self):
""" Return the value of :code:`x2` for this :class:`Frame`. This corresponds to the :code:`x2` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x2
[docs] def set_x2(self,v):
""" Set the value of :code:`x2` for this :class:`Frame`. This corresponds to the :code:`x2` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x2 = v
return self
[docs] def with_x2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x2 == v else None
elif callable(v):
return self if v(self.x2) else None
[docs] def get_y2(self):
""" Return the value of :code:`y2` for this :class:`Frame`. This corresponds to the :code:`y2` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y2
[docs] def set_y2(self,v):
""" Set the value of :code:`y2` for this :class:`Frame`. This corresponds to the :code:`y2` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y2 = v
return self
[docs] def with_y2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y2 == v else None
elif callable(v):
return self if v(self.y2) else None
[docs] def get_columns(self):
""" Return the value of :code:`columns` for this :class:`Frame`. This corresponds to the :code:`columns` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`int`
"""
return self.columns
[docs] def set_columns(self,v):
""" Set the value of :code:`columns` for this :class:`Frame`. This corresponds to the :code:`columns` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.columns = v
return self
[docs] def with_columns(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`columns`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`columns` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_columns()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.columns == v else None
elif callable(v):
return self if v(self.columns) else None
[docs] def get_rows(self):
""" Return the value of :code:`rows` for this :class:`Frame`. This corresponds to the :code:`rows` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`int`
"""
return self.rows
[docs] def set_rows(self,v):
""" Set the value of :code:`rows` for this :class:`Frame`. This corresponds to the :code:`rows` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rows = v
return self
[docs] def with_rows(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rows`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rows` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rows()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rows == v else None
elif callable(v):
return self if v(self.rows) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Frame`. This corresponds to the :code:`layer` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Frame`. This corresponds to the :code:`layer` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_border_left(self):
""" Return the value of :code:`border_left` for this :class:`Frame`. This corresponds to the :code:`border_left` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.border_left
[docs] def set_border_left(self,v):
""" Set the value of :code:`border_left` for this :class:`Frame`. This corresponds to the :code:`border_left` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.border_left = v
return self
[docs] def with_border_left(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`border_left`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`border_left` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_border_left()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.border_left == v else None
elif callable(v):
return self if v(self.border_left) else None
[docs] def get_border_right(self):
""" Return the value of :code:`border_right` for this :class:`Frame`. This corresponds to the :code:`border_right` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.border_right
[docs] def set_border_right(self,v):
""" Set the value of :code:`border_right` for this :class:`Frame`. This corresponds to the :code:`border_right` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.border_right = v
return self
[docs] def with_border_right(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`border_right`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`border_right` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_border_right()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.border_right == v else None
elif callable(v):
return self if v(self.border_right) else None
[docs] def get_border_top(self):
""" Return the value of :code:`border_top` for this :class:`Frame`. This corresponds to the :code:`border_top` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.border_top
[docs] def set_border_top(self,v):
""" Set the value of :code:`border_top` for this :class:`Frame`. This corresponds to the :code:`border_top` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.border_top = v
return self
[docs] def with_border_top(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`border_top`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`border_top` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_border_top()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.border_top == v else None
elif callable(v):
return self if v(self.border_top) else None
[docs] def get_border_bottom(self):
""" Return the value of :code:`border_bottom` for this :class:`Frame`. This corresponds to the :code:`border_bottom` attribute of a :code:`<frame>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.border_bottom
[docs] def set_border_bottom(self,v):
""" Set the value of :code:`border_bottom` for this :class:`Frame`. This corresponds to the :code:`border_bottom` attribute of a :code:`<frame>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.border_bottom = v
return self
[docs] def with_border_bottom(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`border_bottom`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`border_bottom` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_border_bottom()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.border_bottom == v else None
elif callable(v):
return self if v(self.border_bottom) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["frame"] = Frame
[docs]class Portref(EagleFilePart):
"""
Class representing the contents of a <portref> tag in Eagle files.
Attributes:
* :code:`moduleinst`
* :code:`port`
"""
def __init__(self):
"""
Construct an empty :class:`Portref` object.
"""
EagleFilePart.__init__(self)
self.moduleinst=None
self.port=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Portref` from a :code:`portref` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Portref`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Portref` from a :code:`portref` element. This is useful if you have a subclass of :class:`Portref` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Portref`
"""
if root.tag != "portref":
raise EagleFormatError("Tried to create portref from " + root.tag)
self.moduleinst=parseByType(parent, "str", root.get("moduleinst"))
self.port=parseByType(parent, "str", root.get("port"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.moduleinst)
r = r + str(self.port)
return r
[docs] def get_et(self):
"""
Generate a <portref> element tree for a :class:`Portref`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("portref")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.moduleinst)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("moduleinst", v)
else:
r.set("moduleinst", "")
## Unparse the values.
v = unparseByType(self, "str", self.port)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("port", v)
else:
r.set("port", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Portref`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Portref`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Portref_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Portref_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_moduleinst(self):
""" Return the value of :code:`moduleinst` for this :class:`Portref`. This corresponds to the :code:`moduleinst` attribute of a :code:`<portref>` in an Eagle file.
:rtype: :code:`str`
"""
return self.moduleinst
[docs] def set_moduleinst(self,v):
""" Set the value of :code:`moduleinst` for this :class:`Portref`. This corresponds to the :code:`moduleinst` attribute of a :code:`<portref>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.moduleinst = v
return self
[docs] def with_moduleinst(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`moduleinst`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`moduleinst` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_moduleinst()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.moduleinst == v else None
elif callable(v):
return self if v(self.moduleinst) else None
[docs] def get_port(self):
""" Return the value of :code:`port` for this :class:`Portref`. This corresponds to the :code:`port` attribute of a :code:`<portref>` in an Eagle file.
:rtype: :code:`str`
"""
return self.port
[docs] def set_port(self,v):
""" Set the value of :code:`port` for this :class:`Portref`. This corresponds to the :code:`port` attribute of a :code:`<portref>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.port = v
return self
[docs] def with_port(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`port`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`port` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_port()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.port == v else None
elif callable(v):
return self if v(self.port) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_moduleinst(self):
"""Find the :class:`Moduleinst` object refered to by the :code:`moduleinst` attribute of this object. This is like
:meth:`get_moduleinst`, except it returns the :class:`Moduleinst` object instead of its name.
:returns: The object
:rtype: :class:`Moduleinst`
"""
f = lambda efp, key: NotImplemented('Lookup of moduleinst from portref not implemented.')
return f(self, self.moduleinst)
[docs] def find_port(self):
"""Find the :class:`Port` object refered to by the :code:`port` attribute of this object. This is like
:meth:`get_port`, except it returns the :class:`Port` object instead of its name.
:returns: The object
:rtype: :class:`Port`
"""
f = lambda efp, key: NotImplemented('Lookup of port from portref not implemented.')
return f(self, self.port)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["portref"] = Portref
[docs]class Module(EagleFilePart):
"""
Class representing the contents of a <module> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`prefix`
* :code:`dx`
* :code:`dy`
Collections:
* :code:`description`: Singleton :class:`Description` object.
* :code:`sheet`: List of :class:`Sheet` objects.
* :code:`port`: Map of :class:`Port` objects indexed by their :code:`name`.
* :code:`variantdef`: Map of :class:`Variantdef` objects indexed by their :code:`name`.
* :code:`part`: Map of :class:`Part` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Module` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.prefix=None
self.dx=None
self.dy=None
self.sheets=[]
self.ports={}
self.variantdefs={}
self.parts={}
self.description=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Module` from a :code:`module` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Module`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Module` from a :code:`module` element. This is useful if you have a subclass of :class:`Module` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Module`
"""
if root.tag != "module":
raise EagleFormatError("Tried to create module from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.prefix=parseByType(parent, "str", root.get("prefix"))
self.dx=parseByType(parent, "float", root.get("dx"))
self.dy=parseByType(parent, "float", root.get("dy"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./ports/port"):
self.add_port(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./variantdefs/variantdef"):
self.add_variantdef(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./parts/part"):
self.add_part(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./sheets/sheet"):
self.add_sheet(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.prefix)
r = r + str(self.dx)
r = r + str(self.dy)
return r
[docs] def get_et(self):
"""
Generate a <module> element tree for a :class:`Module`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("module")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.prefix)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("prefix", v)
## Unparse the values.
v = unparseByType(self, "float", self.dx)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("dx", v)
else:
r.set("dx", "")
## Unparse the values.
v = unparseByType(self, "float", self.dy)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("dy", v)
else:
r.set("dy", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.ports) is not 0:
target = smartAddSubTags(r, "./ports/port")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.ports.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./variantdefs/variantdef")
## add a map.
if len(self.variantdefs) is not 0:
target = smartAddSubTags(r, "./variantdefs/variantdef")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.variantdefs.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./parts/part")
## add a map.
if len(self.parts) is not 0:
target = smartAddSubTags(r, "./parts/part")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.parts.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.sheets) is not 0:
target = smartAddSubTags(r, "./sheets/sheet")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.sheets,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Module`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Module`
"""
n = copy.copy(self)
n.ports = {}
for x in self.ports.values():
n.add_port(x.clone())
n.variantdefs = {}
for x in self.variantdefs.values():
n.add_variantdef(x.clone())
n.parts = {}
for x in self.parts.values():
n.add_part(x.clone())
n.sheets = []
for x in self.sheets:
n.add_sheet(x.clone())
if n.description is not None:
n.description = self.description.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Module_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Module_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Module`. This corresponds to the :code:`name` attribute of a :code:`<module>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Module`. This corresponds to the :code:`name` attribute of a :code:`<module>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_prefix(self):
""" Return the value of :code:`prefix` for this :class:`Module`. This corresponds to the :code:`prefix` attribute of a :code:`<module>` in an Eagle file.
:rtype: :code:`str`
"""
return self.prefix
[docs] def set_prefix(self,v):
""" Set the value of :code:`prefix` for this :class:`Module`. This corresponds to the :code:`prefix` attribute of a :code:`<module>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.prefix = v
return self
[docs] def with_prefix(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`prefix`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`prefix` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_prefix()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.prefix == v else None
elif callable(v):
return self if v(self.prefix) else None
[docs] def get_dx(self):
""" Return the value of :code:`dx` for this :class:`Module`. This corresponds to the :code:`dx` attribute of a :code:`<module>` in an Eagle file.
:rtype: :code:`float`
"""
return self.dx
[docs] def set_dx(self,v):
""" Set the value of :code:`dx` for this :class:`Module`. This corresponds to the :code:`dx` attribute of a :code:`<module>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.dx = v
return self
[docs] def with_dx(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`dx`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`dx` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_dx()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.dx == v else None
elif callable(v):
return self if v(self.dx) else None
[docs] def get_dy(self):
""" Return the value of :code:`dy` for this :class:`Module`. This corresponds to the :code:`dy` attribute of a :code:`<module>` in an Eagle file.
:rtype: :code:`float`
"""
return self.dy
[docs] def set_dy(self,v):
""" Set the value of :code:`dy` for this :class:`Module`. This corresponds to the :code:`dy` attribute of a :code:`<module>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.dy = v
return self
[docs] def with_dy(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`dy`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`dy` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_dy()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.dy == v else None
elif callable(v):
return self if v(self.dy) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_sheet(self, s):
""" Add a :class:`Sheet` to the :code:`sheets` of this :class:`Module`.
:param s: The :class:`Sheet` to add.
:rtype: :code:`self`
"""
self.sheets.append(s)
s.parent = self
return self
[docs] def get_nth_sheet(self, n):
""" get then nth :class:`Sheet` object from the :code:`sheets` of this :class:`Module`.
:param n: Index of the item to return.
:rtype: :class:`Sheet` object
"""
return self.sheets[n]
[docs] def get_sheets(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`sheets` list of :class:`Sheet` objects for this :class:`Module`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Sheet` objects
:rtype: List of :class:`Sheet` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.sheets
[docs] def clear_sheets(self):
"""
Remove all the :class:`Sheet` objects from the :code:`sheets` of this :class:`Module`.
:rtype: :code:`self`
"""
for efp in self.sheets:
efp.parent = None
self.sheets = []
return self
[docs] def remove_sheet(self, efp):
"""
Remove a :class:`Sheet` from the :code:`sheets` of this :class:`Module`.
:param efp: The :class:`Sheet` object to remove.
:rtype: :code:`self`
"""
self.sheets = [x for x in self.sheets if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_port(self, s):
""" Add a :class:`Port` to the :code:`ports` of this :class:`Module`.
:param s: The :class:`Port` to add.
:rtype: :code:`self`
"""
self.ports[s.name] = s
s.parent = self
return self
[docs] def get_nth_port(self, n):
""" get then nth :class:`Port` object from the :code:`ports` of this :class:`Module`.
:param n: Index of the item to return.
:rtype: :class:`Port` object
"""
return self.ports.values()[n]
[docs] def get_port(self, key):
""" Lookup and return a :class:`Port` from the :code:`ports` of this :class:`Module`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Port` objects.
:rtype: A :class:`Port` object or :code:`None`, if there is no such item.
"""
return self.ports.get(key)
[docs] def get_ports(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`ports` map of :class:`Port` objects for this :class:`Module`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Port` objects
:rtype: List of :class:`Port` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.ports.values()
[docs] def clear_ports(self):
"""
Remove all the :class:`Port` objects from the :code:`ports` of this :class:`Module`.
:rtype: :code:`self`
"""
for efp in self.ports.values():
efp.parent = None
self.ports = {}
return self
[docs] def remove_port(self, efp):
"""
Remove a :class:`Port` from the :code:`ports` of this :class:`Module`.
:param efp: The :class:`Port` object to remove.
:rtype: :code:`self`
"""
del self.ports[efp.name]
efp.parent = None
return self
[docs] def add_variantdef(self, s):
""" Add a :class:`Variantdef` to the :code:`variantdefs` of this :class:`Module`.
:param s: The :class:`Variantdef` to add.
:rtype: :code:`self`
"""
self.variantdefs[s.name] = s
s.parent = self
return self
[docs] def get_nth_variantdef(self, n):
""" get then nth :class:`Variantdef` object from the :code:`variantdefs` of this :class:`Module`.
:param n: Index of the item to return.
:rtype: :class:`Variantdef` object
"""
return self.variantdefs.values()[n]
[docs] def get_variantdef(self, key):
""" Lookup and return a :class:`Variantdef` from the :code:`variantdefs` of this :class:`Module`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Variantdef` objects.
:rtype: A :class:`Variantdef` object or :code:`None`, if there is no such item.
"""
return self.variantdefs.get(key)
[docs] def get_variantdefs(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`variantdefs` map of :class:`Variantdef` objects for this :class:`Module`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Variantdef` objects
:rtype: List of :class:`Variantdef` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.variantdefs.values()
[docs] def clear_variantdefs(self):
"""
Remove all the :class:`Variantdef` objects from the :code:`variantdefs` of this :class:`Module`.
:rtype: :code:`self`
"""
for efp in self.variantdefs.values():
efp.parent = None
self.variantdefs = {}
return self
[docs] def remove_variantdef(self, efp):
"""
Remove a :class:`Variantdef` from the :code:`variantdefs` of this :class:`Module`.
:param efp: The :class:`Variantdef` object to remove.
:rtype: :code:`self`
"""
del self.variantdefs[efp.name]
efp.parent = None
return self
[docs] def add_part(self, s):
""" Add a :class:`Part` to the :code:`parts` of this :class:`Module`.
:param s: The :class:`Part` to add.
:rtype: :code:`self`
"""
self.parts[s.name] = s
s.parent = self
return self
[docs] def get_nth_part(self, n):
""" get then nth :class:`Part` object from the :code:`parts` of this :class:`Module`.
:param n: Index of the item to return.
:rtype: :class:`Part` object
"""
return self.parts.values()[n]
[docs] def get_part(self, key):
""" Lookup and return a :class:`Part` from the :code:`parts` of this :class:`Module`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Part` objects.
:rtype: A :class:`Part` object or :code:`None`, if there is no such item.
"""
return self.parts.get(key)
[docs] def get_parts(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`parts` map of :class:`Part` objects for this :class:`Module`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Part` objects
:rtype: List of :class:`Part` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.parts.values()
[docs] def clear_parts(self):
"""
Remove all the :class:`Part` objects from the :code:`parts` of this :class:`Module`.
:rtype: :code:`self`
"""
for efp in self.parts.values():
efp.parent = None
self.parts = {}
return self
[docs] def remove_part(self, efp):
"""
Remove a :class:`Part` from the :code:`parts` of this :class:`Module`.
:param efp: The :class:`Part` object to remove.
:rtype: :code:`self`
"""
del self.parts[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`Module`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`Module`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.sheets
r = r + self.ports.values()
r = r + self.variantdefs.values()
r = r + self.parts.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_port(efp)
except:
pass
try:
self.remove_variantdef(efp)
except:
pass
try:
self.remove_part(efp)
except:
pass
try:
self.remove_sheet(efp)
except:
pass
if self.get_description == efp:
self.set_description(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["module"] = Module
[docs]class Connect(EagleFilePart):
"""
Class representing the contents of a <connect> tag in Eagle files.
Attributes:
* :code:`gate`
* :code:`pin`
* :code:`pad`
* :code:`route`
"""
def __init__(self):
"""
Construct an empty :class:`Connect` object.
"""
EagleFilePart.__init__(self)
self.gate=None
self.pin=None
self.pad=None
self.route=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Connect` from a :code:`connect` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Connect`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Connect` from a :code:`connect` element. This is useful if you have a subclass of :class:`Connect` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Connect`
"""
if root.tag != "connect":
raise EagleFormatError("Tried to create connect from " + root.tag)
self.gate=parseByType(parent, "str", root.get("gate"))
self.pin=parseByType(parent, "str", root.get("pin"))
self.pad=parseByType(parent, "str", root.get("pad"))
self.route=parseByType(parent, "str", root.get("route"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.gate)
r = r + str(self.pin)
r = r + str(self.pad)
r = r + str(self.route)
return r
[docs] def get_et(self):
"""
Generate a <connect> element tree for a :class:`Connect`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("connect")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.gate)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("gate", v)
else:
r.set("gate", "")
## Unparse the values.
v = unparseByType(self, "str", self.pin)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("pin", v)
else:
r.set("pin", "")
## Unparse the values.
v = unparseByType(self, "str", self.pad)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("pad", v)
else:
r.set("pad", "")
## Unparse the values.
v = unparseByType(self, "str", self.route)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("route", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Connect`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Connect`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Connect_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Connect_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_gate(self):
""" Return the value of :code:`gate` for this :class:`Connect`. This corresponds to the :code:`gate` attribute of a :code:`<connect>` in an Eagle file.
:rtype: :code:`str`
"""
return self.gate
[docs] def set_gate(self,v):
""" Set the value of :code:`gate` for this :class:`Connect`. This corresponds to the :code:`gate` attribute of a :code:`<connect>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.gate = v
return self
[docs] def with_gate(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`gate`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`gate` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_gate()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.gate == v else None
elif callable(v):
return self if v(self.gate) else None
[docs] def get_pin(self):
""" Return the value of :code:`pin` for this :class:`Connect`. This corresponds to the :code:`pin` attribute of a :code:`<connect>` in an Eagle file.
:rtype: :code:`str`
"""
return self.pin
[docs] def set_pin(self,v):
""" Set the value of :code:`pin` for this :class:`Connect`. This corresponds to the :code:`pin` attribute of a :code:`<connect>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.pin = v
return self
[docs] def with_pin(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`pin`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`pin` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_pin()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.pin == v else None
elif callable(v):
return self if v(self.pin) else None
[docs] def get_pad(self):
""" Return the value of :code:`pad` for this :class:`Connect`. This corresponds to the :code:`pad` attribute of a :code:`<connect>` in an Eagle file.
:rtype: :code:`str`
"""
return self.pad
[docs] def set_pad(self,v):
""" Set the value of :code:`pad` for this :class:`Connect`. This corresponds to the :code:`pad` attribute of a :code:`<connect>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.pad = v
return self
[docs] def with_pad(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`pad`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`pad` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_pad()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.pad == v else None
elif callable(v):
return self if v(self.pad) else None
[docs] def get_route(self):
""" Return the value of :code:`route` for this :class:`Connect`. This corresponds to the :code:`route` attribute of a :code:`<connect>` in an Eagle file.
:rtype: :code:`str`
"""
return self.route
[docs] def set_route(self,v):
""" Set the value of :code:`route` for this :class:`Connect`. This corresponds to the :code:`route` attribute of a :code:`<connect>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.route = v
return self
[docs] def with_route(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`route`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`route` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_route()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.route == v else None
elif callable(v):
return self if v(self.route) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_gate(self):
"""Find the :class:`Gate` object refered to by the :code:`gate` attribute of this object. This is like
:meth:`get_gate`, except it returns the :class:`Gate` object instead of its name.
:returns: The object
:rtype: :class:`Gate`
"""
f = lambda efp, key: NotImplemented('Lookup of gate from connect not implemented.')
return f(self, self.gate)
[docs] def find_pin(self):
"""Find the :class:`Pin` object refered to by the :code:`pin` attribute of this object. This is like
:meth:`get_pin`, except it returns the :class:`Pin` object instead of its name.
:returns: The object
:rtype: :class:`Pin`
"""
f = lambda efp, key: NotImplemented('Lookup of pin from connect not implemented.')
return f(self, self.pin)
[docs] def find_pad(self):
"""Find the :class:`Pad` object refered to by the :code:`pad` attribute of this object. This is like
:meth:`get_pad`, except it returns the :class:`Pad` object instead of its name.
:returns: The object
:rtype: :class:`Pad`
"""
f = lambda efp, key: NotImplemented('Lookup of pad from connect not implemented.')
return f(self, self.pad)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["connect"] = Connect
[docs]class Pass(EagleFilePart):
"""
Class representing the contents of a <pass> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`refer`
* :code:`active`
Collections:
* :code:`param`: Map of :class:`Param` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Pass` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.refer=None
self.active=None
self.params={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Pass` from a :code:`pass` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Pass`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Pass` from a :code:`pass` element. This is useful if you have a subclass of :class:`Pass` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Pass`
"""
if root.tag != "pass":
raise EagleFormatError("Tried to create pass from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.refer=parseByType(parent, "str", root.get("refer"))
self.active=parseByType(parent, "str", root.get("active"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./param"):
self.add_param(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.refer)
r = r + str(self.active)
return r
[docs] def get_et(self):
"""
Generate a <pass> element tree for a :class:`Pass`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("pass")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.refer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("refer", v)
## Unparse the values.
v = unparseByType(self, "str", self.active)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("active", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.params) is not 0:
target = smartAddSubTags(r, "./param")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.params.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Pass`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Pass`
"""
n = copy.copy(self)
n.params = {}
for x in self.params.values():
n.add_param(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Pass_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Pass_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Pass`. This corresponds to the :code:`name` attribute of a :code:`<pass>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Pass`. This corresponds to the :code:`name` attribute of a :code:`<pass>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_refer(self):
""" Return the value of :code:`refer` for this :class:`Pass`. This corresponds to the :code:`refer` attribute of a :code:`<pass>` in an Eagle file.
:rtype: :code:`str`
"""
return self.refer
[docs] def set_refer(self,v):
""" Set the value of :code:`refer` for this :class:`Pass`. This corresponds to the :code:`refer` attribute of a :code:`<pass>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.refer = v
return self
[docs] def with_refer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`refer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`refer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_refer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.refer == v else None
elif callable(v):
return self if v(self.refer) else None
[docs] def get_active(self):
""" Return the value of :code:`active` for this :class:`Pass`. This corresponds to the :code:`active` attribute of a :code:`<pass>` in an Eagle file.
:rtype: :code:`str`
"""
return self.active
[docs] def set_active(self,v):
""" Set the value of :code:`active` for this :class:`Pass`. This corresponds to the :code:`active` attribute of a :code:`<pass>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.active = v
return self
[docs] def with_active(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`active`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`active` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_active()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.active == v else None
elif callable(v):
return self if v(self.active) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_param(self, s):
""" Add a :class:`Param` to the :code:`params` of this :class:`Pass`.
:param s: The :class:`Param` to add.
:rtype: :code:`self`
"""
self.params[s.name] = s
s.parent = self
return self
[docs] def get_nth_param(self, n):
""" get then nth :class:`Param` object from the :code:`params` of this :class:`Pass`.
:param n: Index of the item to return.
:rtype: :class:`Param` object
"""
return self.params.values()[n]
[docs] def get_param(self, key):
""" Lookup and return a :class:`Param` from the :code:`params` of this :class:`Pass`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Param` objects.
:rtype: A :class:`Param` object or :code:`None`, if there is no such item.
"""
return self.params.get(key)
[docs] def get_params(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`params` map of :class:`Param` objects for this :class:`Pass`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Param` objects
:rtype: List of :class:`Param` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.params.values()
[docs] def clear_params(self):
"""
Remove all the :class:`Param` objects from the :code:`params` of this :class:`Pass`.
:rtype: :code:`self`
"""
for efp in self.params.values():
efp.parent = None
self.params = {}
return self
[docs] def remove_param(self, efp):
"""
Remove a :class:`Param` from the :code:`params` of this :class:`Pass`.
:param efp: The :class:`Param` object to remove.
:rtype: :code:`self`
"""
del self.params[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.params.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_param(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["pass"] = Pass
[docs]class Technology(EagleFilePart):
"""
Class representing the contents of a <technology> tag in Eagle files.
Attributes:
* :code:`name`
Collections:
* :code:`attribute`: Map of :class:`Attribute` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Technology` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.attributes={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Technology` from a :code:`technology` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Technology`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Technology` from a :code:`technology` element. This is useful if you have a subclass of :class:`Technology` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Technology`
"""
if root.tag != "technology":
raise EagleFormatError("Tried to create technology from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./attribute"):
self.add_attribute(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
return r
[docs] def get_et(self):
"""
Generate a <technology> element tree for a :class:`Technology`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("technology")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./attribute")
## add a map.
if len(self.attributes) is not 0:
target = smartAddSubTags(r, "./attribute")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.attributes.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Technology`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Technology`
"""
n = copy.copy(self)
n.attributes = {}
for x in self.attributes.values():
n.add_attribute(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Technology_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Technology_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Technology`. This corresponds to the :code:`name` attribute of a :code:`<technology>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Technology`. This corresponds to the :code:`name` attribute of a :code:`<technology>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_attribute(self, s):
""" Add a :class:`Attribute` to the :code:`attributes` of this :class:`Technology`.
:param s: The :class:`Attribute` to add.
:rtype: :code:`self`
"""
self.attributes[s.name] = s
s.parent = self
return self
[docs] def get_nth_attribute(self, n):
""" get then nth :class:`Attribute` object from the :code:`attributes` of this :class:`Technology`.
:param n: Index of the item to return.
:rtype: :class:`Attribute` object
"""
return self.attributes.values()[n]
[docs] def get_attribute(self, key):
""" Lookup and return a :class:`Attribute` from the :code:`attributes` of this :class:`Technology`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Attribute` objects.
:rtype: A :class:`Attribute` object or :code:`None`, if there is no such item.
"""
return self.attributes.get(key)
[docs] def get_attributes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`attributes` map of :class:`Attribute` objects for this :class:`Technology`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Attribute` objects
:rtype: List of :class:`Attribute` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.attributes.values()
[docs] def clear_attributes(self):
"""
Remove all the :class:`Attribute` objects from the :code:`attributes` of this :class:`Technology`.
:rtype: :code:`self`
"""
for efp in self.attributes.values():
efp.parent = None
self.attributes = {}
return self
[docs] def remove_attribute(self, efp):
"""
Remove a :class:`Attribute` from the :code:`attributes` of this :class:`Technology`.
:param efp: The :class:`Attribute` object to remove.
:rtype: :code:`self`
"""
del self.attributes[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.attributes.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_attribute(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["technology"] = Technology
[docs]class Port(EagleFilePart):
"""
Class representing the contents of a <port> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`side`
* :code:`dimension`
* :code:`direction`
"""
def __init__(self):
"""
Construct an empty :class:`Port` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.side=None
self.dimension=None
self.direction=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Port` from a :code:`port` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Port`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Port` from a :code:`port` element. This is useful if you have a subclass of :class:`Port` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Port`
"""
if root.tag != "port":
raise EagleFormatError("Tried to create port from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.side=parseByType(parent, "int", root.get("side"))
self.dimension=parseByType(parent, "str", root.get("dimension"))
self.direction=parseByType(parent, "str", root.get("direction"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.side)
r = r + str(self.dimension)
r = r + str(self.direction)
return r
[docs] def get_et(self):
"""
Generate a <port> element tree for a :class:`Port`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("port")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "int", self.side)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("side", v)
else:
r.set("side", "")
## Unparse the values.
v = unparseByType(self, "str", self.dimension)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("dimension", v)
else:
r.set("dimension", "")
## Unparse the values.
v = unparseByType(self, "str", self.direction)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("direction", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Port`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Port`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Port_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Port_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Port`. This corresponds to the :code:`name` attribute of a :code:`<port>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Port`. This corresponds to the :code:`name` attribute of a :code:`<port>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_side(self):
""" Return the value of :code:`side` for this :class:`Port`. This corresponds to the :code:`side` attribute of a :code:`<port>` in an Eagle file.
:rtype: :code:`int`
"""
return self.side
[docs] def set_side(self,v):
""" Set the value of :code:`side` for this :class:`Port`. This corresponds to the :code:`side` attribute of a :code:`<port>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.side = v
return self
[docs] def with_side(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`side`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`side` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_side()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.side == v else None
elif callable(v):
return self if v(self.side) else None
[docs] def get_dimension(self):
""" Return the value of :code:`dimension` for this :class:`Port`. This corresponds to the :code:`dimension` attribute of a :code:`<port>` in an Eagle file.
:rtype: :code:`str`
"""
return self.dimension
[docs] def set_dimension(self,v):
""" Set the value of :code:`dimension` for this :class:`Port`. This corresponds to the :code:`dimension` attribute of a :code:`<port>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.dimension = v
return self
[docs] def with_dimension(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`dimension`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`dimension` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_dimension()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.dimension == v else None
elif callable(v):
return self if v(self.dimension) else None
[docs] def get_direction(self):
""" Return the value of :code:`direction` for this :class:`Port`. This corresponds to the :code:`direction` attribute of a :code:`<port>` in an Eagle file.
:rtype: :code:`str`
"""
return self.direction
[docs] def set_direction(self,v):
""" Set the value of :code:`direction` for this :class:`Port`. This corresponds to the :code:`direction` attribute of a :code:`<port>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.direction = v
return self
[docs] def with_direction(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`direction`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`direction` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_direction()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.direction == v else None
elif callable(v):
return self if v(self.direction) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["port"] = Port
[docs]class Approved(EagleFilePart):
"""
Class representing the contents of a <approved> tag in Eagle files.
Attributes:
* :code:`hash`
"""
def __init__(self):
"""
Construct an empty :class:`Approved` object.
"""
EagleFilePart.__init__(self)
self.hash=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Approved` from a :code:`approved` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Approved`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Approved` from a :code:`approved` element. This is useful if you have a subclass of :class:`Approved` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Approved`
"""
if root.tag != "approved":
raise EagleFormatError("Tried to create approved from " + root.tag)
self.hash=parseByType(parent, "str", root.get("hash"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.hash)
return r
[docs] def get_et(self):
"""
Generate a <approved> element tree for a :class:`Approved`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("approved")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.hash)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("hash", v)
else:
r.set("hash", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Approved`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Approved`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Approved_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Approved_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_hash(self):
""" Return the value of :code:`hash` for this :class:`Approved`. This corresponds to the :code:`hash` attribute of a :code:`<approved>` in an Eagle file.
:rtype: :code:`str`
"""
return self.hash
[docs] def set_hash(self,v):
""" Set the value of :code:`hash` for this :class:`Approved`. This corresponds to the :code:`hash` attribute of a :code:`<approved>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.hash = v
return self
[docs] def with_hash(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`hash`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`hash` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_hash()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.hash == v else None
elif callable(v):
return self if v(self.hash) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["approved"] = Approved
[docs]class Wire(EagleFilePart):
"""
Class representing the contents of a <wire> tag in Eagle files.
Attributes:
* :code:`x1`
* :code:`y1`
* :code:`x2`
* :code:`y2`
* :code:`width`
* :code:`layer`
* :code:`extent`
* :code:`style`
* :code:`curve`
* :code:`cap`
"""
def __init__(self):
"""
Construct an empty :class:`Wire` object.
"""
EagleFilePart.__init__(self)
self.x1=None
self.y1=None
self.x2=None
self.y2=None
self.width=None
self.layer=None
self.extent=None
self.style=None
self.curve=None
self.cap=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Wire` from a :code:`wire` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Wire`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Wire` from a :code:`wire` element. This is useful if you have a subclass of :class:`Wire` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Wire`
"""
if root.tag != "wire":
raise EagleFormatError("Tried to create wire from " + root.tag)
self.x1=parseByType(parent, "float", root.get("x1"))
self.y1=parseByType(parent, "float", root.get("y1"))
self.x2=parseByType(parent, "float", root.get("x2"))
self.y2=parseByType(parent, "float", root.get("y2"))
self.width=parseByType(parent, "float", root.get("width"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.extent=parseByType(parent, "str", root.get("extent"))
self.style=parseByType(parent, "str", root.get("style"))
self.curve=parseByType(parent, "float", root.get("curve"))
self.cap=parseByType(parent, "str", root.get("cap"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x1)
r = r + str(self.y1)
r = r + str(self.x2)
r = r + str(self.y2)
r = r + str(self.width)
r = r + str(self.layer)
r = r + str(self.extent)
r = r + str(self.style)
r = r + str(self.curve)
r = r + str(self.cap)
return r
[docs] def get_et(self):
"""
Generate a <wire> element tree for a :class:`Wire`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("wire")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x1", v)
else:
r.set("x1", "")
## Unparse the values.
v = unparseByType(self, "float", self.y1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y1", v)
else:
r.set("y1", "")
## Unparse the values.
v = unparseByType(self, "float", self.x2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x2", v)
else:
r.set("x2", "")
## Unparse the values.
v = unparseByType(self, "float", self.y2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y2", v)
else:
r.set("y2", "")
## Unparse the values.
v = unparseByType(self, "float", self.width)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("width", v)
else:
r.set("width", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "str", self.extent)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("extent", v)
## Unparse the values.
v = unparseByType(self, "str", self.style)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("style", v)
## Unparse the values.
v = unparseByType(self, "float", self.curve)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("curve", v)
## Unparse the values.
v = unparseByType(self, "str", self.cap)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("cap", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Wire`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Wire`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Wire_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Wire_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x1(self):
""" Return the value of :code:`x1` for this :class:`Wire`. This corresponds to the :code:`x1` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x1
[docs] def set_x1(self,v):
""" Set the value of :code:`x1` for this :class:`Wire`. This corresponds to the :code:`x1` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x1 = v
return self
[docs] def with_x1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x1 == v else None
elif callable(v):
return self if v(self.x1) else None
[docs] def get_y1(self):
""" Return the value of :code:`y1` for this :class:`Wire`. This corresponds to the :code:`y1` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y1
[docs] def set_y1(self,v):
""" Set the value of :code:`y1` for this :class:`Wire`. This corresponds to the :code:`y1` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y1 = v
return self
[docs] def with_y1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y1 == v else None
elif callable(v):
return self if v(self.y1) else None
[docs] def get_x2(self):
""" Return the value of :code:`x2` for this :class:`Wire`. This corresponds to the :code:`x2` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x2
[docs] def set_x2(self,v):
""" Set the value of :code:`x2` for this :class:`Wire`. This corresponds to the :code:`x2` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x2 = v
return self
[docs] def with_x2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x2 == v else None
elif callable(v):
return self if v(self.x2) else None
[docs] def get_y2(self):
""" Return the value of :code:`y2` for this :class:`Wire`. This corresponds to the :code:`y2` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y2
[docs] def set_y2(self,v):
""" Set the value of :code:`y2` for this :class:`Wire`. This corresponds to the :code:`y2` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y2 = v
return self
[docs] def with_y2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y2 == v else None
elif callable(v):
return self if v(self.y2) else None
[docs] def get_width(self):
""" Return the value of :code:`width` for this :class:`Wire`. This corresponds to the :code:`width` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`float`
"""
return self.width
[docs] def set_width(self,v):
""" Set the value of :code:`width` for this :class:`Wire`. This corresponds to the :code:`width` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.width = v
return self
[docs] def with_width(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`width`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`width` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_width()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.width == v else None
elif callable(v):
return self if v(self.width) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Wire`. This corresponds to the :code:`layer` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Wire`. This corresponds to the :code:`layer` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_extent(self):
""" Return the value of :code:`extent` for this :class:`Wire`. This corresponds to the :code:`extent` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`str`
"""
return self.extent
[docs] def set_extent(self,v):
""" Set the value of :code:`extent` for this :class:`Wire`. This corresponds to the :code:`extent` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.extent = v
return self
[docs] def with_extent(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`extent`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`extent` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_extent()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.extent == v else None
elif callable(v):
return self if v(self.extent) else None
[docs] def get_style(self):
""" Return the value of :code:`style` for this :class:`Wire`. This corresponds to the :code:`style` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`str`
"""
return self.style
[docs] def set_style(self,v):
""" Set the value of :code:`style` for this :class:`Wire`. This corresponds to the :code:`style` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.style = v
return self
[docs] def with_style(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`style`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`style` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_style()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.style == v else None
elif callable(v):
return self if v(self.style) else None
[docs] def get_curve(self):
""" Return the value of :code:`curve` for this :class:`Wire`. This corresponds to the :code:`curve` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`float`
"""
return self.curve
[docs] def set_curve(self,v):
""" Set the value of :code:`curve` for this :class:`Wire`. This corresponds to the :code:`curve` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.curve = v
return self
[docs] def with_curve(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`curve`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`curve` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_curve()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.curve == v else None
elif callable(v):
return self if v(self.curve) else None
[docs] def get_cap(self):
""" Return the value of :code:`cap` for this :class:`Wire`. This corresponds to the :code:`cap` attribute of a :code:`<wire>` in an Eagle file.
:rtype: :code:`str`
"""
return self.cap
[docs] def set_cap(self,v):
""" Set the value of :code:`cap` for this :class:`Wire`. This corresponds to the :code:`cap` attribute of a :code:`<wire>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.cap = v
return self
[docs] def with_cap(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`cap`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`cap` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_cap()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.cap == v else None
elif callable(v):
return self if v(self.cap) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["wire"] = Wire
[docs]class Sheet(EagleFilePart):
"""
Class representing the contents of a <sheet> tag in Eagle files.
Attributes:
Collections:
* :code:`description`: Singleton :class:`Description` object.
* :code:`plain_element`: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects.
* :code:`instance`: List of :class:`Instance` objects.
* :code:`moduleinst`: Map of :class:`Moduleinst` objects indexed by their :code:`name`.
* :code:`bus`: Map of :class:`Bus` objects indexed by their :code:`name`.
* :code:`net`: Map of :class:`Net` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Sheet` object.
"""
EagleFilePart.__init__(self)
self.plain_elements=[]
self.instances=[]
self.moduleinsts={}
self.busses={}
self.nets={}
self.description=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Sheet` from a :code:`sheet` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Sheet`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Sheet` from a :code:`sheet` element. This is useful if you have a subclass of :class:`Sheet` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Sheet`
"""
if root.tag != "sheet":
raise EagleFormatError("Tried to create sheet from " + root.tag)
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./moduleinsts/moduleinst"):
self.add_moduleinst(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./busses/bus"):
self.add_bus(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./nets/net"):
self.add_net(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./plain/polygon|./plain/wire|./plain/text|./plain/dimension|./plain/circle|./plain/rectangle|./plain/frame|./plain/hole"):
self.add_plain_element(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./instances/instance"):
self.add_instance(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
return r
[docs] def get_et(self):
"""
Generate a <sheet> element tree for a :class:`Sheet`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("sheet")
### Set the tag attributes
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./plain/polygon|./plain/wire|./plain/text|./plain/dimension|./plain/circle|./plain/rectangle|./plain/frame|./plain/hole")
## add a list.
if len(self.plain_elements) is not 0:
target = smartAddSubTags(r, "./plain/polygon|./plain/wire|./plain/text|./plain/dimension|./plain/circle|./plain/rectangle|./plain/frame|./plain/hole")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.plain_elements,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.moduleinsts) is not 0:
target = smartAddSubTags(r, "./moduleinsts/moduleinst")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.moduleinsts.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./instances/instance")
## add a list.
if len(self.instances) is not 0:
target = smartAddSubTags(r, "./instances/instance")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.instances,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./busses/bus")
## add a map.
if len(self.busses) is not 0:
target = smartAddSubTags(r, "./busses/bus")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.busses.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./nets/net")
## add a map.
if len(self.nets) is not 0:
target = smartAddSubTags(r, "./nets/net")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.nets.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Sheet`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Sheet`
"""
n = copy.copy(self)
n.moduleinsts = {}
for x in self.moduleinsts.values():
n.add_moduleinst(x.clone())
n.busses = {}
for x in self.busses.values():
n.add_bus(x.clone())
n.nets = {}
for x in self.nets.values():
n.add_net(x.clone())
n.plain_elements = []
for x in self.plain_elements:
n.add_plain_element(x.clone())
n.instances = []
for x in self.instances:
n.add_instance(x.clone())
if n.description is not None:
n.description = self.description.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Sheet_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Sheet_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_plain_element(self, s):
""" Add a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` to the :code:`plain_elements` of this :class:`Sheet`.
:param s: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` to add.
:rtype: :code:`self`
"""
self.plain_elements.append(s)
s.parent = self
return self
[docs] def get_nth_plain_element(self, n):
""" get then nth :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` object from the :code:`plain_elements` of this :class:`Sheet`.
:param n: Index of the item to return.
:rtype: :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` object
"""
return self.plain_elements[n]
[docs] def get_plain_elements(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`plain_elements` list of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` objects for this :class:`Sheet`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects
:rtype: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.plain_elements
[docs] def clear_plain_elements(self):
"""
Remove all the :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects from the :code:`plain_elements` of this :class:`Sheet`.
:rtype: :code:`self`
"""
for efp in self.plain_elements:
efp.parent = None
self.plain_elements = []
return self
[docs] def remove_plain_element(self, efp):
"""
Remove a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` from the :code:`plain_elements` of this :class:`Sheet`.
:param efp: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` object to remove.
:rtype: :code:`self`
"""
self.plain_elements = [x for x in self.plain_elements if x != efp]
efp.parent = None
return self
[docs] def add_instance(self, s):
""" Add a :class:`Instance` to the :code:`instances` of this :class:`Sheet`.
:param s: The :class:`Instance` to add.
:rtype: :code:`self`
"""
self.instances.append(s)
s.parent = self
return self
[docs] def get_nth_instance(self, n):
""" get then nth :class:`Instance` object from the :code:`instances` of this :class:`Sheet`.
:param n: Index of the item to return.
:rtype: :class:`Instance` object
"""
return self.instances[n]
[docs] def get_instances(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`instances` list of :class:`Instance` objects for this :class:`Sheet`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Instance` objects
:rtype: List of :class:`Instance` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.instances
[docs] def clear_instances(self):
"""
Remove all the :class:`Instance` objects from the :code:`instances` of this :class:`Sheet`.
:rtype: :code:`self`
"""
for efp in self.instances:
efp.parent = None
self.instances = []
return self
[docs] def remove_instance(self, efp):
"""
Remove a :class:`Instance` from the :code:`instances` of this :class:`Sheet`.
:param efp: The :class:`Instance` object to remove.
:rtype: :code:`self`
"""
self.instances = [x for x in self.instances if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_moduleinst(self, s):
""" Add a :class:`Moduleinst` to the :code:`moduleinsts` of this :class:`Sheet`.
:param s: The :class:`Moduleinst` to add.
:rtype: :code:`self`
"""
self.moduleinsts[s.name] = s
s.parent = self
return self
[docs] def get_nth_moduleinst(self, n):
""" get then nth :class:`Moduleinst` object from the :code:`moduleinsts` of this :class:`Sheet`.
:param n: Index of the item to return.
:rtype: :class:`Moduleinst` object
"""
return self.moduleinsts.values()[n]
[docs] def get_moduleinst(self, key):
""" Lookup and return a :class:`Moduleinst` from the :code:`moduleinsts` of this :class:`Sheet`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Moduleinst` objects.
:rtype: A :class:`Moduleinst` object or :code:`None`, if there is no such item.
"""
return self.moduleinsts.get(key)
[docs] def get_moduleinsts(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`moduleinsts` map of :class:`Moduleinst` objects for this :class:`Sheet`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Moduleinst` objects
:rtype: List of :class:`Moduleinst` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.moduleinsts.values()
[docs] def clear_moduleinsts(self):
"""
Remove all the :class:`Moduleinst` objects from the :code:`moduleinsts` of this :class:`Sheet`.
:rtype: :code:`self`
"""
for efp in self.moduleinsts.values():
efp.parent = None
self.moduleinsts = {}
return self
[docs] def remove_moduleinst(self, efp):
"""
Remove a :class:`Moduleinst` from the :code:`moduleinsts` of this :class:`Sheet`.
:param efp: The :class:`Moduleinst` object to remove.
:rtype: :code:`self`
"""
del self.moduleinsts[efp.name]
efp.parent = None
return self
[docs] def add_bus(self, s):
""" Add a :class:`Bus` to the :code:`busses` of this :class:`Sheet`.
:param s: The :class:`Bus` to add.
:rtype: :code:`self`
"""
self.busses[s.name] = s
s.parent = self
return self
[docs] def get_nth_bus(self, n):
""" get then nth :class:`Bus` object from the :code:`busses` of this :class:`Sheet`.
:param n: Index of the item to return.
:rtype: :class:`Bus` object
"""
return self.busses.values()[n]
[docs] def get_bus(self, key):
""" Lookup and return a :class:`Bus` from the :code:`busses` of this :class:`Sheet`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Bus` objects.
:rtype: A :class:`Bus` object or :code:`None`, if there is no such item.
"""
return self.busses.get(key)
[docs] def get_busses(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`busses` map of :class:`Bus` objects for this :class:`Sheet`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Bus` objects
:rtype: List of :class:`Bus` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.busses.values()
[docs] def clear_busses(self):
"""
Remove all the :class:`Bus` objects from the :code:`busses` of this :class:`Sheet`.
:rtype: :code:`self`
"""
for efp in self.busses.values():
efp.parent = None
self.busses = {}
return self
[docs] def remove_bus(self, efp):
"""
Remove a :class:`Bus` from the :code:`busses` of this :class:`Sheet`.
:param efp: The :class:`Bus` object to remove.
:rtype: :code:`self`
"""
del self.busses[efp.name]
efp.parent = None
return self
[docs] def add_net(self, s):
""" Add a :class:`Net` to the :code:`nets` of this :class:`Sheet`.
:param s: The :class:`Net` to add.
:rtype: :code:`self`
"""
self.nets[s.name] = s
s.parent = self
return self
[docs] def get_nth_net(self, n):
""" get then nth :class:`Net` object from the :code:`nets` of this :class:`Sheet`.
:param n: Index of the item to return.
:rtype: :class:`Net` object
"""
return self.nets.values()[n]
[docs] def get_net(self, key):
""" Lookup and return a :class:`Net` from the :code:`nets` of this :class:`Sheet`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Net` objects.
:rtype: A :class:`Net` object or :code:`None`, if there is no such item.
"""
return self.nets.get(key)
[docs] def get_nets(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`nets` map of :class:`Net` objects for this :class:`Sheet`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Net` objects
:rtype: List of :class:`Net` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.nets.values()
[docs] def clear_nets(self):
"""
Remove all the :class:`Net` objects from the :code:`nets` of this :class:`Sheet`.
:rtype: :code:`self`
"""
for efp in self.nets.values():
efp.parent = None
self.nets = {}
return self
[docs] def remove_net(self, efp):
"""
Remove a :class:`Net` from the :code:`nets` of this :class:`Sheet`.
:param efp: The :class:`Net` object to remove.
:rtype: :code:`self`
"""
del self.nets[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`Sheet`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`Sheet`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.plain_elements
r = r + self.instances
r = r + self.moduleinsts.values()
r = r + self.busses.values()
r = r + self.nets.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_moduleinst(efp)
except:
pass
try:
self.remove_bus(efp)
except:
pass
try:
self.remove_net(efp)
except:
pass
try:
self.remove_plain_element(efp)
except:
pass
try:
self.remove_instance(efp)
except:
pass
if self.get_description == efp:
self.set_description(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["sheet"] = Sheet
[docs]class Polygon(EagleFilePart):
"""
Class representing the contents of a <polygon> tag in Eagle files.
Attributes:
* :code:`width`
* :code:`layer`
* :code:`spacing`
* :code:`pour`
* :code:`isolate`
* :code:`orphans`
* :code:`thermals`
* :code:`rank`
Collections:
* :code:`vertex`: List of :class:`Vertex` objects.
"""
def __init__(self):
"""
Construct an empty :class:`Polygon` object.
"""
EagleFilePart.__init__(self)
self.width=None
self.layer=None
self.spacing=None
self.pour=None
self.isolate=None
self.orphans=None
self.thermals=None
self.rank=None
self.vertices=[]
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Polygon` from a :code:`polygon` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Polygon`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Polygon` from a :code:`polygon` element. This is useful if you have a subclass of :class:`Polygon` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Polygon`
"""
if root.tag != "polygon":
raise EagleFormatError("Tried to create polygon from " + root.tag)
self.width=parseByType(parent, "float", root.get("width"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.spacing=parseByType(parent, "float", root.get("spacing"))
self.pour=parseByType(parent, "str", root.get("pour"))
self.isolate=parseByType(parent, "float", root.get("isolate"))
self.orphans=parseByType(parent, "bool", root.get("orphans"))
self.thermals=parseByType(parent, "bool", root.get("thermals"))
self.rank=parseByType(parent, "int", root.get("rank"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
for c in root.xpath("./vertex"):
self.add_vertex(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.width)
r = r + str(self.layer)
r = r + str(self.spacing)
r = r + str(self.pour)
r = r + str(self.isolate)
r = r + str(self.orphans)
r = r + str(self.thermals)
r = r + str(self.rank)
return r
[docs] def get_et(self):
"""
Generate a <polygon> element tree for a :class:`Polygon`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("polygon")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.width)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("width", v)
else:
r.set("width", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "float", self.spacing)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("spacing", v)
## Unparse the values.
v = unparseByType(self, "str", self.pour)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("pour", v)
## Unparse the values.
v = unparseByType(self, "float", self.isolate)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("isolate", v)
## Unparse the values.
v = unparseByType(self, "bool", self.orphans)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("orphans", v)
## Unparse the values.
v = unparseByType(self, "bool", self.thermals)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("thermals", v)
## Unparse the values.
v = unparseByType(self, "int", self.rank)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rank", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.vertices) is not 0:
target = smartAddSubTags(r, "./vertex")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.vertices,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Polygon`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Polygon`
"""
n = copy.copy(self)
n.vertices = []
for x in self.vertices:
n.add_vertex(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Polygon_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Polygon_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_width(self):
""" Return the value of :code:`width` for this :class:`Polygon`. This corresponds to the :code:`width` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`float`
"""
return self.width
[docs] def set_width(self,v):
""" Set the value of :code:`width` for this :class:`Polygon`. This corresponds to the :code:`width` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.width = v
return self
[docs] def with_width(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`width`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`width` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_width()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.width == v else None
elif callable(v):
return self if v(self.width) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Polygon`. This corresponds to the :code:`layer` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Polygon`. This corresponds to the :code:`layer` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_spacing(self):
""" Return the value of :code:`spacing` for this :class:`Polygon`. This corresponds to the :code:`spacing` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`float`
"""
return self.spacing
[docs] def set_spacing(self,v):
""" Set the value of :code:`spacing` for this :class:`Polygon`. This corresponds to the :code:`spacing` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.spacing = v
return self
[docs] def with_spacing(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`spacing`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`spacing` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_spacing()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.spacing == v else None
elif callable(v):
return self if v(self.spacing) else None
[docs] def get_pour(self):
""" Return the value of :code:`pour` for this :class:`Polygon`. This corresponds to the :code:`pour` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`str`
"""
return self.pour
[docs] def set_pour(self,v):
""" Set the value of :code:`pour` for this :class:`Polygon`. This corresponds to the :code:`pour` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.pour = v
return self
[docs] def with_pour(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`pour`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`pour` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_pour()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.pour == v else None
elif callable(v):
return self if v(self.pour) else None
[docs] def get_isolate(self):
""" Return the value of :code:`isolate` for this :class:`Polygon`. This corresponds to the :code:`isolate` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`float`
"""
return self.isolate
[docs] def set_isolate(self,v):
""" Set the value of :code:`isolate` for this :class:`Polygon`. This corresponds to the :code:`isolate` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.isolate = v
return self
[docs] def with_isolate(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`isolate`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`isolate` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_isolate()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.isolate == v else None
elif callable(v):
return self if v(self.isolate) else None
[docs] def get_orphans(self):
""" Return the value of :code:`orphans` for this :class:`Polygon`. This corresponds to the :code:`orphans` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.orphans
[docs] def set_orphans(self,v):
""" Set the value of :code:`orphans` for this :class:`Polygon`. This corresponds to the :code:`orphans` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.orphans = v
return self
[docs] def with_orphans(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`orphans`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`orphans` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_orphans()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.orphans == v else None
elif callable(v):
return self if v(self.orphans) else None
[docs] def get_thermals(self):
""" Return the value of :code:`thermals` for this :class:`Polygon`. This corresponds to the :code:`thermals` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.thermals
[docs] def set_thermals(self,v):
""" Set the value of :code:`thermals` for this :class:`Polygon`. This corresponds to the :code:`thermals` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.thermals = v
return self
[docs] def with_thermals(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`thermals`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`thermals` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_thermals()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.thermals == v else None
elif callable(v):
return self if v(self.thermals) else None
[docs] def get_rank(self):
""" Return the value of :code:`rank` for this :class:`Polygon`. This corresponds to the :code:`rank` attribute of a :code:`<polygon>` in an Eagle file.
:rtype: :code:`int`
"""
return self.rank
[docs] def set_rank(self,v):
""" Set the value of :code:`rank` for this :class:`Polygon`. This corresponds to the :code:`rank` attribute of a :code:`<polygon>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rank = v
return self
[docs] def with_rank(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rank`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rank` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rank()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rank == v else None
elif callable(v):
return self if v(self.rank) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_vertex(self, s):
""" Add a :class:`Vertex` to the :code:`vertices` of this :class:`Polygon`.
:param s: The :class:`Vertex` to add.
:rtype: :code:`self`
"""
self.vertices.append(s)
s.parent = self
return self
[docs] def get_nth_vertex(self, n):
""" get then nth :class:`Vertex` object from the :code:`vertices` of this :class:`Polygon`.
:param n: Index of the item to return.
:rtype: :class:`Vertex` object
"""
return self.vertices[n]
[docs] def get_vertices(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`vertices` list of :class:`Vertex` objects for this :class:`Polygon`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Vertex` objects
:rtype: List of :class:`Vertex` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.vertices
[docs] def clear_vertices(self):
"""
Remove all the :class:`Vertex` objects from the :code:`vertices` of this :class:`Polygon`.
:rtype: :code:`self`
"""
for efp in self.vertices:
efp.parent = None
self.vertices = []
return self
[docs] def remove_vertex(self, efp):
"""
Remove a :class:`Vertex` from the :code:`vertices` of this :class:`Polygon`.
:param efp: The :class:`Vertex` object to remove.
:rtype: :code:`self`
"""
self.vertices = [x for x in self.vertices if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.vertices
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_vertex(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["polygon"] = Polygon
[docs]class Deviceset(EagleFilePart):
"""
Class representing the contents of a <deviceset> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`prefix`
* :code:`uservalue`
Collections:
* :code:`description`: Singleton :class:`Description` object.
* :code:`gate`: Map of :class:`Gate` objects indexed by their :code:`name`.
* :code:`device`: Map of :class:`Device` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Deviceset` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.prefix=None
self.uservalue=None
self.gates={}
self.devices={}
self.description=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Deviceset` from a :code:`deviceset` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Deviceset`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Deviceset` from a :code:`deviceset` element. This is useful if you have a subclass of :class:`Deviceset` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Deviceset`
"""
if root.tag != "deviceset":
raise EagleFormatError("Tried to create deviceset from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.prefix=parseByType(parent, "str", root.get("prefix"))
self.uservalue=parseByType(parent, "bool", root.get("uservalue"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./gates/gate"):
self.add_gate(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./devices/device"):
self.add_device(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
x = root.xpath("./description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.prefix)
r = r + str(self.uservalue)
return r
[docs] def get_et(self):
"""
Generate a <deviceset> element tree for a :class:`Deviceset`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("deviceset")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.prefix)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("prefix", v)
## Unparse the values.
v = unparseByType(self, "bool", self.uservalue)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("uservalue", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./gates/gate")
## add a map.
if len(self.gates) is not 0:
target = smartAddSubTags(r, "./gates/gate")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.gates.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./devices/device")
## add a map.
if len(self.devices) is not 0:
target = smartAddSubTags(r, "./devices/device")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.devices.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Deviceset`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Deviceset`
"""
n = copy.copy(self)
n.gates = {}
for x in self.gates.values():
n.add_gate(x.clone())
n.devices = {}
for x in self.devices.values():
n.add_device(x.clone())
if n.description is not None:
n.description = self.description.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Deviceset_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Deviceset_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Deviceset`. This corresponds to the :code:`name` attribute of a :code:`<deviceset>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Deviceset`. This corresponds to the :code:`name` attribute of a :code:`<deviceset>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_prefix(self):
""" Return the value of :code:`prefix` for this :class:`Deviceset`. This corresponds to the :code:`prefix` attribute of a :code:`<deviceset>` in an Eagle file.
:rtype: :code:`str`
"""
return self.prefix
[docs] def set_prefix(self,v):
""" Set the value of :code:`prefix` for this :class:`Deviceset`. This corresponds to the :code:`prefix` attribute of a :code:`<deviceset>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.prefix = v
return self
[docs] def with_prefix(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`prefix`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`prefix` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_prefix()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.prefix == v else None
elif callable(v):
return self if v(self.prefix) else None
[docs] def get_uservalue(self):
""" Return the value of :code:`uservalue` for this :class:`Deviceset`. This corresponds to the :code:`uservalue` attribute of a :code:`<deviceset>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.uservalue
[docs] def set_uservalue(self,v):
""" Set the value of :code:`uservalue` for this :class:`Deviceset`. This corresponds to the :code:`uservalue` attribute of a :code:`<deviceset>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.uservalue = v
return self
[docs] def with_uservalue(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`uservalue`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`uservalue` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_uservalue()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.uservalue == v else None
elif callable(v):
return self if v(self.uservalue) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_gate(self, s):
""" Add a :class:`Gate` to the :code:`gates` of this :class:`Deviceset`.
:param s: The :class:`Gate` to add.
:rtype: :code:`self`
"""
self.gates[s.name] = s
s.parent = self
return self
[docs] def get_nth_gate(self, n):
""" get then nth :class:`Gate` object from the :code:`gates` of this :class:`Deviceset`.
:param n: Index of the item to return.
:rtype: :class:`Gate` object
"""
return self.gates.values()[n]
[docs] def get_gate(self, key):
""" Lookup and return a :class:`Gate` from the :code:`gates` of this :class:`Deviceset`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Gate` objects.
:rtype: A :class:`Gate` object or :code:`None`, if there is no such item.
"""
return self.gates.get(key)
[docs] def get_gates(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`gates` map of :class:`Gate` objects for this :class:`Deviceset`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Gate` objects
:rtype: List of :class:`Gate` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.gates.values()
[docs] def clear_gates(self):
"""
Remove all the :class:`Gate` objects from the :code:`gates` of this :class:`Deviceset`.
:rtype: :code:`self`
"""
for efp in self.gates.values():
efp.parent = None
self.gates = {}
return self
[docs] def remove_gate(self, efp):
"""
Remove a :class:`Gate` from the :code:`gates` of this :class:`Deviceset`.
:param efp: The :class:`Gate` object to remove.
:rtype: :code:`self`
"""
del self.gates[efp.name]
efp.parent = None
return self
[docs] def add_device(self, s):
""" Add a :class:`Device` to the :code:`devices` of this :class:`Deviceset`.
:param s: The :class:`Device` to add.
:rtype: :code:`self`
"""
self.devices[s.name] = s
s.parent = self
return self
[docs] def get_nth_device(self, n):
""" get then nth :class:`Device` object from the :code:`devices` of this :class:`Deviceset`.
:param n: Index of the item to return.
:rtype: :class:`Device` object
"""
return self.devices.values()[n]
[docs] def get_device(self, key):
""" Lookup and return a :class:`Device` from the :code:`devices` of this :class:`Deviceset`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Device` objects.
:rtype: A :class:`Device` object or :code:`None`, if there is no such item.
"""
return self.devices.get(key)
[docs] def get_devices(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`devices` map of :class:`Device` objects for this :class:`Deviceset`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Device` objects
:rtype: List of :class:`Device` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.devices.values()
[docs] def clear_devices(self):
"""
Remove all the :class:`Device` objects from the :code:`devices` of this :class:`Deviceset`.
:rtype: :code:`self`
"""
for efp in self.devices.values():
efp.parent = None
self.devices = {}
return self
[docs] def remove_device(self, efp):
"""
Remove a :class:`Device` from the :code:`devices` of this :class:`Deviceset`.
:param efp: The :class:`Device` object to remove.
:rtype: :code:`self`
"""
del self.devices[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`Deviceset`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`Deviceset`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.gates.values()
r = r + self.devices.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_gate(efp)
except:
pass
try:
self.remove_device(efp)
except:
pass
if self.get_description == efp:
self.set_description(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["deviceset"] = Deviceset
[docs]class Param(EagleFilePart):
"""
Class representing the contents of a <param> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`value`
"""
def __init__(self):
"""
Construct an empty :class:`Param` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.value=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Param` from a :code:`param` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Param`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Param` from a :code:`param` element. This is useful if you have a subclass of :class:`Param` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Param`
"""
if root.tag != "param":
raise EagleFormatError("Tried to create param from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.value=parseByType(parent, "str", root.get("value"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.value)
return r
[docs] def get_et(self):
"""
Generate a <param> element tree for a :class:`Param`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("param")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.value)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("value", v)
else:
r.set("value", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Param`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Param`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Param_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Param_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Param`. This corresponds to the :code:`name` attribute of a :code:`<param>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Param`. This corresponds to the :code:`name` attribute of a :code:`<param>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_value(self):
""" Return the value of :code:`value` for this :class:`Param`. This corresponds to the :code:`value` attribute of a :code:`<param>` in an Eagle file.
:rtype: :code:`str`
"""
return self.value
[docs] def set_value(self,v):
""" Set the value of :code:`value` for this :class:`Param`. This corresponds to the :code:`value` attribute of a :code:`<param>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.value = v
return self
[docs] def with_value(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`value`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`value` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_value()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.value == v else None
elif callable(v):
return self if v(self.value) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["param"] = Param
[docs]class Label(EagleFilePart):
"""
Class representing the contents of a <label> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
* :code:`size`
* :code:`layer`
* :code:`font`
* :code:`ratio`
* :code:`rot`
* :code:`xref`
"""
def __init__(self):
"""
Construct an empty :class:`Label` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
self.size=None
self.layer=None
self.font=None
self.ratio=None
self.rot=None
self.xref=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Label` from a :code:`label` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Label`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Label` from a :code:`label` element. This is useful if you have a subclass of :class:`Label` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Label`
"""
if root.tag != "label":
raise EagleFormatError("Tried to create label from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.size=parseByType(parent, "float", root.get("size"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.font=parseByType(parent, "str", root.get("font"))
self.ratio=parseByType(parent, "int", root.get("ratio"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.xref=parseByType(parent, "bool", root.get("xref"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.size)
r = r + str(self.layer)
r = r + str(self.font)
r = r + str(self.ratio)
r = r + str(self.rot)
r = r + str(self.xref)
return r
[docs] def get_et(self):
"""
Generate a <label> element tree for a :class:`Label`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("label")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.size)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("size", v)
else:
r.set("size", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "str", self.font)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("font", v)
## Unparse the values.
v = unparseByType(self, "int", self.ratio)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("ratio", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
## Unparse the values.
v = unparseByType(self, "bool", self.xref)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("xref", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Label`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Label`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Label_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Label_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Label`. This corresponds to the :code:`x` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Label`. This corresponds to the :code:`x` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Label`. This corresponds to the :code:`y` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Label`. This corresponds to the :code:`y` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_size(self):
""" Return the value of :code:`size` for this :class:`Label`. This corresponds to the :code:`size` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`float`
"""
return self.size
[docs] def set_size(self,v):
""" Set the value of :code:`size` for this :class:`Label`. This corresponds to the :code:`size` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.size = v
return self
[docs] def with_size(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`size`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`size` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_size()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.size == v else None
elif callable(v):
return self if v(self.size) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Label`. This corresponds to the :code:`layer` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Label`. This corresponds to the :code:`layer` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_font(self):
""" Return the value of :code:`font` for this :class:`Label`. This corresponds to the :code:`font` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`str`
"""
return self.font
[docs] def set_font(self,v):
""" Set the value of :code:`font` for this :class:`Label`. This corresponds to the :code:`font` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.font = v
return self
[docs] def with_font(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`font`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`font` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_font()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.font == v else None
elif callable(v):
return self if v(self.font) else None
[docs] def get_ratio(self):
""" Return the value of :code:`ratio` for this :class:`Label`. This corresponds to the :code:`ratio` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`int`
"""
return self.ratio
[docs] def set_ratio(self,v):
""" Set the value of :code:`ratio` for this :class:`Label`. This corresponds to the :code:`ratio` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.ratio = v
return self
[docs] def with_ratio(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`ratio`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`ratio` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_ratio()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.ratio == v else None
elif callable(v):
return self if v(self.ratio) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Label`. This corresponds to the :code:`rot` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Label`. This corresponds to the :code:`rot` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
[docs] def get_xref(self):
""" Return the value of :code:`xref` for this :class:`Label`. This corresponds to the :code:`xref` attribute of a :code:`<label>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.xref
[docs] def set_xref(self,v):
""" Set the value of :code:`xref` for this :class:`Label`. This corresponds to the :code:`xref` attribute of a :code:`<label>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.xref = v
return self
[docs] def with_xref(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`xref`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`xref` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_xref()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.xref == v else None
elif callable(v):
return self if v(self.xref) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["label"] = Label
[docs]class Note(EagleFilePart):
"""
Class representing the contents of a <note> tag in Eagle files.
Attributes:
* :code:`minversion`
* :code:`version`
* :code:`severity`
"""
def __init__(self):
"""
Construct an empty :class:`Note` object.
"""
EagleFilePart.__init__(self)
self.minversion=None
self.version=None
self.severity=None
self.text = ""
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Note` from a :code:`note` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Note`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Note` from a :code:`note` element. This is useful if you have a subclass of :class:`Note` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Note`
"""
if root.tag != "note":
raise EagleFormatError("Tried to create note from " + root.tag)
self.minversion=parseByType(parent, "str", root.get("minversion"))
self.version=parseByType(parent, "str", root.get("version"))
self.severity=parseByType(parent, "str", root.get("severity"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
self.text = root.text
def sortkey(self):
r = ""
r = r + str(self.minversion)
r = r + str(self.version)
r = r + str(self.severity)
return r
[docs] def get_et(self):
"""
Generate a <note> element tree for a :class:`Note`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("note")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.minversion)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("minversion", v)
else:
r.set("minversion", "")
## Unparse the values.
v = unparseByType(self, "str", self.version)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("version", v)
else:
r.set("version", "")
## Unparse the values.
v = unparseByType(self, "str", self.severity)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("severity", v)
else:
r.set("severity", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
r.text = self.text
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Note`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Note`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Note_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Note_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_minversion(self):
""" Return the value of :code:`minversion` for this :class:`Note`. This corresponds to the :code:`minversion` attribute of a :code:`<note>` in an Eagle file.
:rtype: :code:`str`
"""
return self.minversion
[docs] def set_minversion(self,v):
""" Set the value of :code:`minversion` for this :class:`Note`. This corresponds to the :code:`minversion` attribute of a :code:`<note>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.minversion = v
return self
[docs] def with_minversion(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`minversion`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`minversion` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_minversion()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.minversion == v else None
elif callable(v):
return self if v(self.minversion) else None
[docs] def get_version(self):
""" Return the value of :code:`version` for this :class:`Note`. This corresponds to the :code:`version` attribute of a :code:`<note>` in an Eagle file.
:rtype: :code:`str`
"""
return self.version
[docs] def set_version(self,v):
""" Set the value of :code:`version` for this :class:`Note`. This corresponds to the :code:`version` attribute of a :code:`<note>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.version = v
return self
[docs] def with_version(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`version`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`version` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_version()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.version == v else None
elif callable(v):
return self if v(self.version) else None
[docs] def get_severity(self):
""" Return the value of :code:`severity` for this :class:`Note`. This corresponds to the :code:`severity` attribute of a :code:`<note>` in an Eagle file.
:rtype: :code:`str`
"""
return self.severity
[docs] def set_severity(self,v):
""" Set the value of :code:`severity` for this :class:`Note`. This corresponds to the :code:`severity` attribute of a :code:`<note>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.severity = v
return self
[docs] def with_severity(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`severity`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`severity` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_severity()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.severity == v else None
elif callable(v):
return self if v(self.severity) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def with_text(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`text`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`text` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_text()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.text == v else None
elif callable(v):
return self if v(self.text) else None
else:
raise SwoopError("Illegal type passed to with_text")
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["note"] = Note
[docs]class Instance(EagleFilePart):
"""
Class representing the contents of a <instance> tag in Eagle files.
Attributes:
* :code:`part`
* :code:`gate`
* :code:`x`
* :code:`y`
* :code:`smashed`
* :code:`rot`
Collections:
* :code:`attribute`: Map of :class:`Attribute` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Instance` object.
"""
EagleFilePart.__init__(self)
self.part=None
self.gate=None
self.x=None
self.y=None
self.smashed=None
self.rot=None
self.attributes={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Instance` from a :code:`instance` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Instance`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Instance` from a :code:`instance` element. This is useful if you have a subclass of :class:`Instance` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Instance`
"""
if root.tag != "instance":
raise EagleFormatError("Tried to create instance from " + root.tag)
self.part=parseByType(parent, "str", root.get("part"))
self.gate=parseByType(parent, "str", root.get("gate"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.smashed=parseByType(parent, "str", root.get("smashed"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./attribute"):
self.add_attribute(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.part)
r = r + str(self.gate)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.smashed)
r = r + str(self.rot)
return r
[docs] def get_et(self):
"""
Generate a <instance> element tree for a :class:`Instance`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("instance")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.part)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("part", v)
else:
r.set("part", "")
## Unparse the values.
v = unparseByType(self, "str", self.gate)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("gate", v)
else:
r.set("gate", "")
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "str", self.smashed)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("smashed", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./attribute")
## add a map.
if len(self.attributes) is not 0:
target = smartAddSubTags(r, "./attribute")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.attributes.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Instance`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Instance`
"""
n = copy.copy(self)
n.attributes = {}
for x in self.attributes.values():
n.add_attribute(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Instance_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Instance_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_part(self):
""" Return the value of :code:`part` for this :class:`Instance`. This corresponds to the :code:`part` attribute of a :code:`<instance>` in an Eagle file.
:rtype: :code:`str`
"""
return self.part
[docs] def set_part(self,v):
""" Set the value of :code:`part` for this :class:`Instance`. This corresponds to the :code:`part` attribute of a :code:`<instance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.part = v
return self
[docs] def with_part(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`part`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`part` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_part()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.part == v else None
elif callable(v):
return self if v(self.part) else None
[docs] def get_gate(self):
""" Return the value of :code:`gate` for this :class:`Instance`. This corresponds to the :code:`gate` attribute of a :code:`<instance>` in an Eagle file.
:rtype: :code:`str`
"""
return self.gate
[docs] def set_gate(self,v):
""" Set the value of :code:`gate` for this :class:`Instance`. This corresponds to the :code:`gate` attribute of a :code:`<instance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.gate = v
return self
[docs] def with_gate(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`gate`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`gate` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_gate()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.gate == v else None
elif callable(v):
return self if v(self.gate) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Instance`. This corresponds to the :code:`x` attribute of a :code:`<instance>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Instance`. This corresponds to the :code:`x` attribute of a :code:`<instance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Instance`. This corresponds to the :code:`y` attribute of a :code:`<instance>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Instance`. This corresponds to the :code:`y` attribute of a :code:`<instance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_smashed(self):
""" Return the value of :code:`smashed` for this :class:`Instance`. This corresponds to the :code:`smashed` attribute of a :code:`<instance>` in an Eagle file.
:rtype: :code:`str`
"""
return self.smashed
[docs] def set_smashed(self,v):
""" Set the value of :code:`smashed` for this :class:`Instance`. This corresponds to the :code:`smashed` attribute of a :code:`<instance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.smashed = v
return self
[docs] def with_smashed(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`smashed`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`smashed` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_smashed()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.smashed == v else None
elif callable(v):
return self if v(self.smashed) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Instance`. This corresponds to the :code:`rot` attribute of a :code:`<instance>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Instance`. This corresponds to the :code:`rot` attribute of a :code:`<instance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_part(self):
"""Find the :class:`Part` object refered to by the :code:`part` attribute of this object. This is like
:meth:`get_part`, except it returns the :class:`Part` object instead of its name.
:returns: The object
:rtype: :class:`Part`
"""
f = lambda efp, key: NotImplemented('Lookup of part from instance not implemented.')
return f(self, self.part)
[docs] def find_gate(self):
"""Find the :class:`Gate` object refered to by the :code:`gate` attribute of this object. This is like
:meth:`get_gate`, except it returns the :class:`Gate` object instead of its name.
:returns: The object
:rtype: :class:`Gate`
"""
f = lambda efp, key: NotImplemented('Lookup of gate from instance not implemented.')
return f(self, self.gate)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_attribute(self, s):
""" Add a :class:`Attribute` to the :code:`attributes` of this :class:`Instance`.
:param s: The :class:`Attribute` to add.
:rtype: :code:`self`
"""
self.attributes[s.name] = s
s.parent = self
return self
[docs] def get_nth_attribute(self, n):
""" get then nth :class:`Attribute` object from the :code:`attributes` of this :class:`Instance`.
:param n: Index of the item to return.
:rtype: :class:`Attribute` object
"""
return self.attributes.values()[n]
[docs] def get_attribute(self, key):
""" Lookup and return a :class:`Attribute` from the :code:`attributes` of this :class:`Instance`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Attribute` objects.
:rtype: A :class:`Attribute` object or :code:`None`, if there is no such item.
"""
return self.attributes.get(key)
[docs] def get_attributes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`attributes` map of :class:`Attribute` objects for this :class:`Instance`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Attribute` objects
:rtype: List of :class:`Attribute` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.attributes.values()
[docs] def clear_attributes(self):
"""
Remove all the :class:`Attribute` objects from the :code:`attributes` of this :class:`Instance`.
:rtype: :code:`self`
"""
for efp in self.attributes.values():
efp.parent = None
self.attributes = {}
return self
[docs] def remove_attribute(self, efp):
"""
Remove a :class:`Attribute` from the :code:`attributes` of this :class:`Instance`.
:param efp: The :class:`Attribute` object to remove.
:rtype: :code:`self`
"""
del self.attributes[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.attributes.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_attribute(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["instance"] = Instance
[docs]class Moduleinst(EagleFilePart):
"""
Class representing the contents of a <moduleinst> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`module`
* :code:`modulevariant`
* :code:`x`
* :code:`y`
* :code:`offset`
* :code:`smashed`
* :code:`rot`
"""
def __init__(self):
"""
Construct an empty :class:`Moduleinst` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.module=None
self.modulevariant=None
self.x=None
self.y=None
self.offset=None
self.smashed=None
self.rot=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Moduleinst` from a :code:`moduleinst` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Moduleinst`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Moduleinst` from a :code:`moduleinst` element. This is useful if you have a subclass of :class:`Moduleinst` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Moduleinst`
"""
if root.tag != "moduleinst":
raise EagleFormatError("Tried to create moduleinst from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.module=parseByType(parent, "str", root.get("module"))
self.modulevariant=parseByType(parent, "str", root.get("modulevariant"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.offset=parseByType(parent, "int", root.get("offset"))
self.smashed=parseByType(parent, "str", root.get("smashed"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.module)
r = r + str(self.modulevariant)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.offset)
r = r + str(self.smashed)
r = r + str(self.rot)
return r
[docs] def get_et(self):
"""
Generate a <moduleinst> element tree for a :class:`Moduleinst`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("moduleinst")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.module)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("module", v)
else:
r.set("module", "")
## Unparse the values.
v = unparseByType(self, "str", self.modulevariant)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("modulevariant", v)
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "int", self.offset)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("offset", v)
## Unparse the values.
v = unparseByType(self, "str", self.smashed)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("smashed", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Moduleinst`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Moduleinst`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Moduleinst_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Moduleinst_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Moduleinst`. This corresponds to the :code:`name` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Moduleinst`. This corresponds to the :code:`name` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_module(self):
""" Return the value of :code:`module` for this :class:`Moduleinst`. This corresponds to the :code:`module` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`str`
"""
return self.module
[docs] def set_module(self,v):
""" Set the value of :code:`module` for this :class:`Moduleinst`. This corresponds to the :code:`module` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.module = v
return self
[docs] def with_module(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`module`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`module` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_module()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.module == v else None
elif callable(v):
return self if v(self.module) else None
[docs] def get_modulevariant(self):
""" Return the value of :code:`modulevariant` for this :class:`Moduleinst`. This corresponds to the :code:`modulevariant` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`str`
"""
return self.modulevariant
[docs] def set_modulevariant(self,v):
""" Set the value of :code:`modulevariant` for this :class:`Moduleinst`. This corresponds to the :code:`modulevariant` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.modulevariant = v
return self
[docs] def with_modulevariant(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`modulevariant`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`modulevariant` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_modulevariant()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.modulevariant == v else None
elif callable(v):
return self if v(self.modulevariant) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Moduleinst`. This corresponds to the :code:`x` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Moduleinst`. This corresponds to the :code:`x` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Moduleinst`. This corresponds to the :code:`y` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Moduleinst`. This corresponds to the :code:`y` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_offset(self):
""" Return the value of :code:`offset` for this :class:`Moduleinst`. This corresponds to the :code:`offset` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`int`
"""
return self.offset
[docs] def set_offset(self,v):
""" Set the value of :code:`offset` for this :class:`Moduleinst`. This corresponds to the :code:`offset` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.offset = v
return self
[docs] def with_offset(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`offset`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`offset` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_offset()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.offset == v else None
elif callable(v):
return self if v(self.offset) else None
[docs] def get_smashed(self):
""" Return the value of :code:`smashed` for this :class:`Moduleinst`. This corresponds to the :code:`smashed` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`str`
"""
return self.smashed
[docs] def set_smashed(self,v):
""" Set the value of :code:`smashed` for this :class:`Moduleinst`. This corresponds to the :code:`smashed` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.smashed = v
return self
[docs] def with_smashed(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`smashed`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`smashed` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_smashed()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.smashed == v else None
elif callable(v):
return self if v(self.smashed) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Moduleinst`. This corresponds to the :code:`rot` attribute of a :code:`<moduleinst>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Moduleinst`. This corresponds to the :code:`rot` attribute of a :code:`<moduleinst>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_module(self):
"""Find the :class:`Module` object refered to by the :code:`module` attribute of this object. This is like
:meth:`get_module`, except it returns the :class:`Module` object instead of its name.
:returns: The object
:rtype: :class:`Module`
"""
f = lambda efp, key: NotImplemented('Module lookup not implemented')
return f(self, self.module)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["moduleinst"] = Moduleinst
[docs]class Setting(EagleFilePart):
"""
Class representing the contents of a <setting> tag in Eagle files.
Attributes:
* :code:`alwaysvectorfont`
* :code:`verticaltext`
"""
def __init__(self):
"""
Construct an empty :class:`Setting` object.
"""
EagleFilePart.__init__(self)
self.alwaysvectorfont=None
self.verticaltext=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Setting` from a :code:`setting` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Setting`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Setting` from a :code:`setting` element. This is useful if you have a subclass of :class:`Setting` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Setting`
"""
if root.tag != "setting":
raise EagleFormatError("Tried to create setting from " + root.tag)
self.alwaysvectorfont=parseByType(parent, "bool", root.get("alwaysvectorfont"))
self.verticaltext=parseByType(parent, "str", root.get("verticaltext"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.alwaysvectorfont)
r = r + str(self.verticaltext)
return r
[docs] def get_et(self):
"""
Generate a <setting> element tree for a :class:`Setting`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("setting")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "bool", self.alwaysvectorfont)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("alwaysvectorfont", v)
## Unparse the values.
v = unparseByType(self, "str", self.verticaltext)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("verticaltext", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Setting`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Setting`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Setting_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Setting_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_alwaysvectorfont(self):
""" Return the value of :code:`alwaysvectorfont` for this :class:`Setting`. This corresponds to the :code:`alwaysvectorfont` attribute of a :code:`<setting>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.alwaysvectorfont
[docs] def set_alwaysvectorfont(self,v):
""" Set the value of :code:`alwaysvectorfont` for this :class:`Setting`. This corresponds to the :code:`alwaysvectorfont` attribute of a :code:`<setting>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.alwaysvectorfont = v
return self
[docs] def with_alwaysvectorfont(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`alwaysvectorfont`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`alwaysvectorfont` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_alwaysvectorfont()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.alwaysvectorfont == v else None
elif callable(v):
return self if v(self.alwaysvectorfont) else None
[docs] def get_verticaltext(self):
""" Return the value of :code:`verticaltext` for this :class:`Setting`. This corresponds to the :code:`verticaltext` attribute of a :code:`<setting>` in an Eagle file.
:rtype: :code:`str`
"""
return self.verticaltext
[docs] def set_verticaltext(self,v):
""" Set the value of :code:`verticaltext` for this :class:`Setting`. This corresponds to the :code:`verticaltext` attribute of a :code:`<setting>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.verticaltext = v
return self
[docs] def with_verticaltext(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`verticaltext`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`verticaltext` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_verticaltext()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.verticaltext == v else None
elif callable(v):
return self if v(self.verticaltext) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["setting"] = Setting
[docs]class Pad(EagleFilePart):
"""
Class representing the contents of a <pad> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`x`
* :code:`y`
* :code:`drill`
* :code:`diameter`
* :code:`shape`
* :code:`rot`
* :code:`stop`
* :code:`thermals`
* :code:`first`
"""
def __init__(self):
"""
Construct an empty :class:`Pad` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.x=None
self.y=None
self.drill=None
self.diameter=None
self.shape=None
self.rot=None
self.stop=None
self.thermals=None
self.first=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Pad` from a :code:`pad` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Pad`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Pad` from a :code:`pad` element. This is useful if you have a subclass of :class:`Pad` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Pad`
"""
if root.tag != "pad":
raise EagleFormatError("Tried to create pad from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.drill=parseByType(parent, "float", root.get("drill"))
self.diameter=parseByType(parent, "float", root.get("diameter"))
self.shape=parseByType(parent, "str", root.get("shape"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.stop=parseByType(parent, "bool", root.get("stop"))
self.thermals=parseByType(parent, "bool", root.get("thermals"))
self.first=parseByType(parent, "bool", root.get("first"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.drill)
r = r + str(self.diameter)
r = r + str(self.shape)
r = r + str(self.rot)
r = r + str(self.stop)
r = r + str(self.thermals)
r = r + str(self.first)
return r
[docs] def get_et(self):
"""
Generate a <pad> element tree for a :class:`Pad`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("pad")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.drill)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("drill", v)
else:
r.set("drill", "")
## Unparse the values.
v = unparseByType(self, "float", self.diameter)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("diameter", v)
## Unparse the values.
v = unparseByType(self, "str", self.shape)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("shape", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
## Unparse the values.
v = unparseByType(self, "bool", self.stop)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("stop", v)
## Unparse the values.
v = unparseByType(self, "bool", self.thermals)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("thermals", v)
## Unparse the values.
v = unparseByType(self, "bool", self.first)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("first", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Pad`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Pad`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Pad_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Pad_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Pad`. This corresponds to the :code:`name` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Pad`. This corresponds to the :code:`name` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Pad`. This corresponds to the :code:`x` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Pad`. This corresponds to the :code:`x` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Pad`. This corresponds to the :code:`y` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Pad`. This corresponds to the :code:`y` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_drill(self):
""" Return the value of :code:`drill` for this :class:`Pad`. This corresponds to the :code:`drill` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`float`
"""
return self.drill
[docs] def set_drill(self,v):
""" Set the value of :code:`drill` for this :class:`Pad`. This corresponds to the :code:`drill` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.drill = v
return self
[docs] def with_drill(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`drill`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`drill` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_drill()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.drill == v else None
elif callable(v):
return self if v(self.drill) else None
[docs] def get_diameter(self):
""" Return the value of :code:`diameter` for this :class:`Pad`. This corresponds to the :code:`diameter` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`float`
"""
return self.diameter
[docs] def set_diameter(self,v):
""" Set the value of :code:`diameter` for this :class:`Pad`. This corresponds to the :code:`diameter` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.diameter = v
return self
[docs] def with_diameter(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`diameter`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`diameter` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_diameter()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.diameter == v else None
elif callable(v):
return self if v(self.diameter) else None
[docs] def get_shape(self):
""" Return the value of :code:`shape` for this :class:`Pad`. This corresponds to the :code:`shape` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`str`
"""
return self.shape
[docs] def set_shape(self,v):
""" Set the value of :code:`shape` for this :class:`Pad`. This corresponds to the :code:`shape` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.shape = v
return self
[docs] def with_shape(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`shape`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`shape` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_shape()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.shape == v else None
elif callable(v):
return self if v(self.shape) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Pad`. This corresponds to the :code:`rot` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Pad`. This corresponds to the :code:`rot` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
[docs] def get_stop(self):
""" Return the value of :code:`stop` for this :class:`Pad`. This corresponds to the :code:`stop` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.stop
[docs] def set_stop(self,v):
""" Set the value of :code:`stop` for this :class:`Pad`. This corresponds to the :code:`stop` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.stop = v
return self
[docs] def with_stop(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`stop`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`stop` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_stop()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.stop == v else None
elif callable(v):
return self if v(self.stop) else None
[docs] def get_thermals(self):
""" Return the value of :code:`thermals` for this :class:`Pad`. This corresponds to the :code:`thermals` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.thermals
[docs] def set_thermals(self,v):
""" Set the value of :code:`thermals` for this :class:`Pad`. This corresponds to the :code:`thermals` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.thermals = v
return self
[docs] def with_thermals(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`thermals`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`thermals` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_thermals()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.thermals == v else None
elif callable(v):
return self if v(self.thermals) else None
[docs] def get_first(self):
""" Return the value of :code:`first` for this :class:`Pad`. This corresponds to the :code:`first` attribute of a :code:`<pad>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.first
[docs] def set_first(self,v):
""" Set the value of :code:`first` for this :class:`Pad`. This corresponds to the :code:`first` attribute of a :code:`<pad>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.first = v
return self
[docs] def with_first(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`first`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`first` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_first()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.first == v else None
elif callable(v):
return self if v(self.first) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["pad"] = Pad
[docs]class Schematic(EagleFilePart):
"""
Class representing the contents of a <schematic> tag in Eagle files.
Attributes:
* :code:`xreflabel`
* :code:`xrefpart`
"""
def __init__(self):
"""
Construct an empty :class:`Schematic` object.
"""
EagleFilePart.__init__(self)
self.xreflabel=None
self.xrefpart=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Schematic` from a :code:`schematic` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Schematic`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Schematic` from a :code:`schematic` element. This is useful if you have a subclass of :class:`Schematic` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Schematic`
"""
if root.tag != "schematic":
raise EagleFormatError("Tried to create schematic from " + root.tag)
self.xreflabel=parseByType(parent, "str", root.get("xreflabel"))
self.xrefpart=parseByType(parent, "str", root.get("xrefpart"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.xreflabel)
r = r + str(self.xrefpart)
return r
[docs] def get_et(self):
"""
Generate a <schematic> element tree for a :class:`Schematic`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("schematic")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.xreflabel)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("xreflabel", v)
## Unparse the values.
v = unparseByType(self, "str", self.xrefpart)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("xrefpart", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Schematic`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Schematic`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Schematic_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Schematic_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_xreflabel(self):
""" Return the value of :code:`xreflabel` for this :class:`Schematic`. This corresponds to the :code:`xreflabel` attribute of a :code:`<schematic>` in an Eagle file.
:rtype: :code:`str`
"""
return self.xreflabel
[docs] def set_xreflabel(self,v):
""" Set the value of :code:`xreflabel` for this :class:`Schematic`. This corresponds to the :code:`xreflabel` attribute of a :code:`<schematic>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.xreflabel = v
return self
[docs] def with_xreflabel(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`xreflabel`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`xreflabel` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_xreflabel()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.xreflabel == v else None
elif callable(v):
return self if v(self.xreflabel) else None
[docs] def get_xrefpart(self):
""" Return the value of :code:`xrefpart` for this :class:`Schematic`. This corresponds to the :code:`xrefpart` attribute of a :code:`<schematic>` in an Eagle file.
:rtype: :code:`str`
"""
return self.xrefpart
[docs] def set_xrefpart(self,v):
""" Set the value of :code:`xrefpart` for this :class:`Schematic`. This corresponds to the :code:`xrefpart` attribute of a :code:`<schematic>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.xrefpart = v
return self
[docs] def with_xrefpart(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`xrefpart`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`xrefpart` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_xrefpart()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.xrefpart == v else None
elif callable(v):
return self if v(self.xrefpart) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["schematic"] = Schematic
class Base_Attribute(EagleFilePart):
"""
Class representing the contents of a <attribute> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`value`
* :code:`x`
* :code:`y`
* :code:`size`
* :code:`layer`
* :code:`font`
* :code:`ratio`
* :code:`rot`
* :code:`display`
* :code:`align`
* :code:`constant`
"""
def __init__(self):
"""
Construct an empty :class:`Base_Attribute` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.value=None
self.x=None
self.y=None
self.size=None
self.layer=None
self.font=None
self.ratio=None
self.rot=None
self.display=None
self.align=None
self.constant=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Attribute` from a :code:`attribute` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Attribute`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Attribute` from a :code:`attribute` element. This is useful if you have a subclass of :class:`Attribute` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Attribute`
"""
if root.tag != "attribute":
raise EagleFormatError("Tried to create attribute from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.value=parseByType(parent, "str", root.get("value"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.size=parseByType(parent, "float", root.get("size"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.font=parseByType(parent, "str", root.get("font"))
self.ratio=parseByType(parent, "int", root.get("ratio"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.display=parseByType(parent, "str", root.get("display"))
self.align=parseByType(parent, "str", root.get("align"))
self.constant=parseByType(parent, "constant_bool", root.get("constant"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.value)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.size)
r = r + str(self.layer)
r = r + str(self.font)
r = r + str(self.ratio)
r = r + str(self.rot)
r = r + str(self.display)
r = r + str(self.align)
r = r + str(self.constant)
return r
def get_et(self):
"""
Generate a <attribute> element tree for a :class:`Attribute`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("attribute")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.value)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("value", v)
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
## Unparse the values.
v = unparseByType(self, "float", self.size)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("size", v)
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
## Unparse the values.
v = unparseByType(self, "str", self.font)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("font", v)
## Unparse the values.
v = unparseByType(self, "int", self.ratio)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("ratio", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
## Unparse the values.
v = unparseByType(self, "str", self.display)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("display", v)
## Unparse the values.
v = unparseByType(self, "str", self.align)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("align", v)
## Unparse the values.
v = unparseByType(self, "constant_bool", self.constant)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("constant", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
def clone(self):
"""
Recursively clone this :code:`Attribute`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Attribute`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Attribute_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Attribute_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
def get_name(self):
""" Return the value of :code:`name` for this :class:`Attribute`. This corresponds to the :code:`name` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Attribute`. This corresponds to the :code:`name` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
def get_value(self):
""" Return the value of :code:`value` for this :class:`Attribute`. This corresponds to the :code:`value` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`str`
"""
return self.value
def set_value(self,v):
""" Set the value of :code:`value` for this :class:`Attribute`. This corresponds to the :code:`value` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.value = v
return self
def with_value(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`value`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`value` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_value()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.value == v else None
elif callable(v):
return self if v(self.value) else None
def get_x(self):
""" Return the value of :code:`x` for this :class:`Attribute`. This corresponds to the :code:`x` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Attribute`. This corresponds to the :code:`x` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
def get_y(self):
""" Return the value of :code:`y` for this :class:`Attribute`. This corresponds to the :code:`y` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Attribute`. This corresponds to the :code:`y` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
def get_size(self):
""" Return the value of :code:`size` for this :class:`Attribute`. This corresponds to the :code:`size` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`float`
"""
return self.size
def set_size(self,v):
""" Set the value of :code:`size` for this :class:`Attribute`. This corresponds to the :code:`size` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.size = v
return self
def with_size(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`size`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`size` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_size()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.size == v else None
elif callable(v):
return self if v(self.size) else None
def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Attribute`. This corresponds to the :code:`layer` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Attribute`. This corresponds to the :code:`layer` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
def get_font(self):
""" Return the value of :code:`font` for this :class:`Attribute`. This corresponds to the :code:`font` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`str`
"""
return self.font
def set_font(self,v):
""" Set the value of :code:`font` for this :class:`Attribute`. This corresponds to the :code:`font` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.font = v
return self
def with_font(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`font`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`font` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_font()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.font == v else None
elif callable(v):
return self if v(self.font) else None
def get_ratio(self):
""" Return the value of :code:`ratio` for this :class:`Attribute`. This corresponds to the :code:`ratio` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`int`
"""
return self.ratio
def set_ratio(self,v):
""" Set the value of :code:`ratio` for this :class:`Attribute`. This corresponds to the :code:`ratio` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.ratio = v
return self
def with_ratio(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`ratio`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`ratio` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_ratio()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.ratio == v else None
elif callable(v):
return self if v(self.ratio) else None
def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Attribute`. This corresponds to the :code:`rot` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Attribute`. This corresponds to the :code:`rot` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
def get_display(self):
""" Return the value of :code:`display` for this :class:`Attribute`. This corresponds to the :code:`display` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`str`
"""
return self.display
def set_display(self,v):
""" Set the value of :code:`display` for this :class:`Attribute`. This corresponds to the :code:`display` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.display = v
return self
def with_display(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`display`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`display` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_display()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.display == v else None
elif callable(v):
return self if v(self.display) else None
def get_align(self):
""" Return the value of :code:`align` for this :class:`Attribute`. This corresponds to the :code:`align` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`str`
"""
return self.align
def set_align(self,v):
""" Set the value of :code:`align` for this :class:`Attribute`. This corresponds to the :code:`align` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.align = v
return self
def with_align(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`align`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`align` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_align()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.align == v else None
elif callable(v):
return self if v(self.align) else None
def get_constant(self):
""" Return the value of :code:`constant` for this :class:`Attribute`. This corresponds to the :code:`constant` attribute of a :code:`<attribute>` in an Eagle file.
:rtype: :code:`constant_bool`
"""
return self.constant
def set_constant(self,v):
""" Set the value of :code:`constant` for this :class:`Attribute`. This corresponds to the :code:`constant` attribute of a :code:`<attribute>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.constant = v
return self
def with_constant(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`constant`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`constant` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_constant()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.constant == v else None
elif callable(v):
return self if v(self.constant) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["attribute"] = Base_Attribute
[docs]class Gate(EagleFilePart):
"""
Class representing the contents of a <gate> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`symbol`
* :code:`x`
* :code:`y`
* :code:`addlevel`
* :code:`swaplevel`
"""
def __init__(self):
"""
Construct an empty :class:`Gate` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.symbol=None
self.x=None
self.y=None
self.addlevel=None
self.swaplevel=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Gate` from a :code:`gate` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Gate`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Gate` from a :code:`gate` element. This is useful if you have a subclass of :class:`Gate` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Gate`
"""
if root.tag != "gate":
raise EagleFormatError("Tried to create gate from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.symbol=parseByType(parent, "str", root.get("symbol"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.addlevel=parseByType(parent, "str", root.get("addlevel"))
self.swaplevel=parseByType(parent, "int", root.get("swaplevel"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.symbol)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.addlevel)
r = r + str(self.swaplevel)
return r
[docs] def get_et(self):
"""
Generate a <gate> element tree for a :class:`Gate`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("gate")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.symbol)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("symbol", v)
else:
r.set("symbol", "")
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "str", self.addlevel)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("addlevel", v)
## Unparse the values.
v = unparseByType(self, "int", self.swaplevel)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("swaplevel", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Gate`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Gate`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Gate_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Gate_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Gate`. This corresponds to the :code:`name` attribute of a :code:`<gate>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Gate`. This corresponds to the :code:`name` attribute of a :code:`<gate>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_symbol(self):
""" Return the value of :code:`symbol` for this :class:`Gate`. This corresponds to the :code:`symbol` attribute of a :code:`<gate>` in an Eagle file.
:rtype: :code:`str`
"""
return self.symbol
[docs] def set_symbol(self,v):
""" Set the value of :code:`symbol` for this :class:`Gate`. This corresponds to the :code:`symbol` attribute of a :code:`<gate>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.symbol = v
return self
[docs] def with_symbol(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`symbol`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`symbol` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_symbol()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.symbol == v else None
elif callable(v):
return self if v(self.symbol) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Gate`. This corresponds to the :code:`x` attribute of a :code:`<gate>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Gate`. This corresponds to the :code:`x` attribute of a :code:`<gate>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Gate`. This corresponds to the :code:`y` attribute of a :code:`<gate>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Gate`. This corresponds to the :code:`y` attribute of a :code:`<gate>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_addlevel(self):
""" Return the value of :code:`addlevel` for this :class:`Gate`. This corresponds to the :code:`addlevel` attribute of a :code:`<gate>` in an Eagle file.
:rtype: :code:`str`
"""
return self.addlevel
[docs] def set_addlevel(self,v):
""" Set the value of :code:`addlevel` for this :class:`Gate`. This corresponds to the :code:`addlevel` attribute of a :code:`<gate>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.addlevel = v
return self
[docs] def with_addlevel(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`addlevel`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`addlevel` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_addlevel()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.addlevel == v else None
elif callable(v):
return self if v(self.addlevel) else None
[docs] def get_swaplevel(self):
""" Return the value of :code:`swaplevel` for this :class:`Gate`. This corresponds to the :code:`swaplevel` attribute of a :code:`<gate>` in an Eagle file.
:rtype: :code:`int`
"""
return self.swaplevel
[docs] def set_swaplevel(self,v):
""" Set the value of :code:`swaplevel` for this :class:`Gate`. This corresponds to the :code:`swaplevel` attribute of a :code:`<gate>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.swaplevel = v
return self
[docs] def with_swaplevel(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`swaplevel`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`swaplevel` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_swaplevel()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.swaplevel == v else None
elif callable(v):
return self if v(self.swaplevel) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_symbol(self):
"""Find the :class:`Symbol` object refered to by the :code:`symbol` attribute of this object. This is like
:meth:`get_symbol`, except it returns the :class:`Symbol` object instead of its name.
:returns: The object
:rtype: :class:`Symbol`
"""
f = lambda efp, key: efp.get_parent().get_parent().get_symbol(key)
return f(self, self.symbol)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["gate"] = Gate
[docs]class Circle(EagleFilePart):
"""
Class representing the contents of a <circle> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
* :code:`radius`
* :code:`width`
* :code:`layer`
"""
def __init__(self):
"""
Construct an empty :class:`Circle` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
self.radius=None
self.width=None
self.layer=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Circle` from a :code:`circle` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Circle`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Circle` from a :code:`circle` element. This is useful if you have a subclass of :class:`Circle` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Circle`
"""
if root.tag != "circle":
raise EagleFormatError("Tried to create circle from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.radius=parseByType(parent, "float", root.get("radius"))
self.width=parseByType(parent, "float", root.get("width"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.radius)
r = r + str(self.width)
r = r + str(self.layer)
return r
[docs] def get_et(self):
"""
Generate a <circle> element tree for a :class:`Circle`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("circle")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.radius)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("radius", v)
else:
r.set("radius", "")
## Unparse the values.
v = unparseByType(self, "float", self.width)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("width", v)
else:
r.set("width", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Circle`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Circle`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Circle_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Circle_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Circle`. This corresponds to the :code:`x` attribute of a :code:`<circle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Circle`. This corresponds to the :code:`x` attribute of a :code:`<circle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Circle`. This corresponds to the :code:`y` attribute of a :code:`<circle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Circle`. This corresponds to the :code:`y` attribute of a :code:`<circle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_radius(self):
""" Return the value of :code:`radius` for this :class:`Circle`. This corresponds to the :code:`radius` attribute of a :code:`<circle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.radius
[docs] def set_radius(self,v):
""" Set the value of :code:`radius` for this :class:`Circle`. This corresponds to the :code:`radius` attribute of a :code:`<circle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.radius = v
return self
[docs] def with_radius(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`radius`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`radius` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_radius()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.radius == v else None
elif callable(v):
return self if v(self.radius) else None
[docs] def get_width(self):
""" Return the value of :code:`width` for this :class:`Circle`. This corresponds to the :code:`width` attribute of a :code:`<circle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.width
[docs] def set_width(self,v):
""" Set the value of :code:`width` for this :class:`Circle`. This corresponds to the :code:`width` attribute of a :code:`<circle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.width = v
return self
[docs] def with_width(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`width`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`width` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_width()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.width == v else None
elif callable(v):
return self if v(self.width) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Circle`. This corresponds to the :code:`layer` attribute of a :code:`<circle>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Circle`. This corresponds to the :code:`layer` attribute of a :code:`<circle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["circle"] = Circle
[docs]class Smd(EagleFilePart):
"""
Class representing the contents of a <smd> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`x`
* :code:`y`
* :code:`dx`
* :code:`dy`
* :code:`layer`
* :code:`roundness`
* :code:`rot`
* :code:`stop`
* :code:`thermals`
* :code:`cream`
"""
def __init__(self):
"""
Construct an empty :class:`Smd` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.x=None
self.y=None
self.dx=None
self.dy=None
self.layer=None
self.roundness=None
self.rot=None
self.stop=None
self.thermals=None
self.cream=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Smd` from a :code:`smd` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Smd`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Smd` from a :code:`smd` element. This is useful if you have a subclass of :class:`Smd` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Smd`
"""
if root.tag != "smd":
raise EagleFormatError("Tried to create smd from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.dx=parseByType(parent, "float", root.get("dx"))
self.dy=parseByType(parent, "float", root.get("dy"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.roundness=parseByType(parent, "int", root.get("roundness"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.stop=parseByType(parent, "bool", root.get("stop"))
self.thermals=parseByType(parent, "bool", root.get("thermals"))
self.cream=parseByType(parent, "bool", root.get("cream"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.dx)
r = r + str(self.dy)
r = r + str(self.layer)
r = r + str(self.roundness)
r = r + str(self.rot)
r = r + str(self.stop)
r = r + str(self.thermals)
r = r + str(self.cream)
return r
[docs] def get_et(self):
"""
Generate a <smd> element tree for a :class:`Smd`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("smd")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.dx)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("dx", v)
else:
r.set("dx", "")
## Unparse the values.
v = unparseByType(self, "float", self.dy)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("dy", v)
else:
r.set("dy", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "int", self.roundness)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("roundness", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
## Unparse the values.
v = unparseByType(self, "bool", self.stop)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("stop", v)
## Unparse the values.
v = unparseByType(self, "bool", self.thermals)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("thermals", v)
## Unparse the values.
v = unparseByType(self, "bool", self.cream)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("cream", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Smd`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Smd`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Smd_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Smd_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Smd`. This corresponds to the :code:`name` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Smd`. This corresponds to the :code:`name` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Smd`. This corresponds to the :code:`x` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Smd`. This corresponds to the :code:`x` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Smd`. This corresponds to the :code:`y` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Smd`. This corresponds to the :code:`y` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_dx(self):
""" Return the value of :code:`dx` for this :class:`Smd`. This corresponds to the :code:`dx` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`float`
"""
return self.dx
[docs] def set_dx(self,v):
""" Set the value of :code:`dx` for this :class:`Smd`. This corresponds to the :code:`dx` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.dx = v
return self
[docs] def with_dx(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`dx`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`dx` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_dx()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.dx == v else None
elif callable(v):
return self if v(self.dx) else None
[docs] def get_dy(self):
""" Return the value of :code:`dy` for this :class:`Smd`. This corresponds to the :code:`dy` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`float`
"""
return self.dy
[docs] def set_dy(self,v):
""" Set the value of :code:`dy` for this :class:`Smd`. This corresponds to the :code:`dy` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.dy = v
return self
[docs] def with_dy(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`dy`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`dy` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_dy()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.dy == v else None
elif callable(v):
return self if v(self.dy) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Smd`. This corresponds to the :code:`layer` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Smd`. This corresponds to the :code:`layer` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_roundness(self):
""" Return the value of :code:`roundness` for this :class:`Smd`. This corresponds to the :code:`roundness` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`int`
"""
return self.roundness
[docs] def set_roundness(self,v):
""" Set the value of :code:`roundness` for this :class:`Smd`. This corresponds to the :code:`roundness` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.roundness = v
return self
[docs] def with_roundness(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`roundness`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`roundness` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_roundness()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.roundness == v else None
elif callable(v):
return self if v(self.roundness) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Smd`. This corresponds to the :code:`rot` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Smd`. This corresponds to the :code:`rot` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
[docs] def get_stop(self):
""" Return the value of :code:`stop` for this :class:`Smd`. This corresponds to the :code:`stop` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.stop
[docs] def set_stop(self,v):
""" Set the value of :code:`stop` for this :class:`Smd`. This corresponds to the :code:`stop` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.stop = v
return self
[docs] def with_stop(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`stop`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`stop` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_stop()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.stop == v else None
elif callable(v):
return self if v(self.stop) else None
[docs] def get_thermals(self):
""" Return the value of :code:`thermals` for this :class:`Smd`. This corresponds to the :code:`thermals` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.thermals
[docs] def set_thermals(self,v):
""" Set the value of :code:`thermals` for this :class:`Smd`. This corresponds to the :code:`thermals` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.thermals = v
return self
[docs] def with_thermals(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`thermals`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`thermals` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_thermals()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.thermals == v else None
elif callable(v):
return self if v(self.thermals) else None
[docs] def get_cream(self):
""" Return the value of :code:`cream` for this :class:`Smd`. This corresponds to the :code:`cream` attribute of a :code:`<smd>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.cream
[docs] def set_cream(self,v):
""" Set the value of :code:`cream` for this :class:`Smd`. This corresponds to the :code:`cream` attribute of a :code:`<smd>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.cream = v
return self
[docs] def with_cream(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`cream`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`cream` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_cream()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.cream == v else None
elif callable(v):
return self if v(self.cream) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["smd"] = Smd
[docs]class Rectangle(EagleFilePart):
"""
Class representing the contents of a <rectangle> tag in Eagle files.
Attributes:
* :code:`x1`
* :code:`y1`
* :code:`x2`
* :code:`y2`
* :code:`layer`
* :code:`rot`
"""
def __init__(self):
"""
Construct an empty :class:`Rectangle` object.
"""
EagleFilePart.__init__(self)
self.x1=None
self.y1=None
self.x2=None
self.y2=None
self.layer=None
self.rot=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Rectangle` from a :code:`rectangle` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Rectangle`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Rectangle` from a :code:`rectangle` element. This is useful if you have a subclass of :class:`Rectangle` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Rectangle`
"""
if root.tag != "rectangle":
raise EagleFormatError("Tried to create rectangle from " + root.tag)
self.x1=parseByType(parent, "float", root.get("x1"))
self.y1=parseByType(parent, "float", root.get("y1"))
self.x2=parseByType(parent, "float", root.get("x2"))
self.y2=parseByType(parent, "float", root.get("y2"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x1)
r = r + str(self.y1)
r = r + str(self.x2)
r = r + str(self.y2)
r = r + str(self.layer)
r = r + str(self.rot)
return r
[docs] def get_et(self):
"""
Generate a <rectangle> element tree for a :class:`Rectangle`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("rectangle")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x1", v)
else:
r.set("x1", "")
## Unparse the values.
v = unparseByType(self, "float", self.y1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y1", v)
else:
r.set("y1", "")
## Unparse the values.
v = unparseByType(self, "float", self.x2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x2", v)
else:
r.set("x2", "")
## Unparse the values.
v = unparseByType(self, "float", self.y2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y2", v)
else:
r.set("y2", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Rectangle`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Rectangle`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Rectangle_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Rectangle_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x1(self):
""" Return the value of :code:`x1` for this :class:`Rectangle`. This corresponds to the :code:`x1` attribute of a :code:`<rectangle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x1
[docs] def set_x1(self,v):
""" Set the value of :code:`x1` for this :class:`Rectangle`. This corresponds to the :code:`x1` attribute of a :code:`<rectangle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x1 = v
return self
[docs] def with_x1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x1 == v else None
elif callable(v):
return self if v(self.x1) else None
[docs] def get_y1(self):
""" Return the value of :code:`y1` for this :class:`Rectangle`. This corresponds to the :code:`y1` attribute of a :code:`<rectangle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y1
[docs] def set_y1(self,v):
""" Set the value of :code:`y1` for this :class:`Rectangle`. This corresponds to the :code:`y1` attribute of a :code:`<rectangle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y1 = v
return self
[docs] def with_y1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y1 == v else None
elif callable(v):
return self if v(self.y1) else None
[docs] def get_x2(self):
""" Return the value of :code:`x2` for this :class:`Rectangle`. This corresponds to the :code:`x2` attribute of a :code:`<rectangle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x2
[docs] def set_x2(self,v):
""" Set the value of :code:`x2` for this :class:`Rectangle`. This corresponds to the :code:`x2` attribute of a :code:`<rectangle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x2 = v
return self
[docs] def with_x2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x2 == v else None
elif callable(v):
return self if v(self.x2) else None
[docs] def get_y2(self):
""" Return the value of :code:`y2` for this :class:`Rectangle`. This corresponds to the :code:`y2` attribute of a :code:`<rectangle>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y2
[docs] def set_y2(self,v):
""" Set the value of :code:`y2` for this :class:`Rectangle`. This corresponds to the :code:`y2` attribute of a :code:`<rectangle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y2 = v
return self
[docs] def with_y2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y2 == v else None
elif callable(v):
return self if v(self.y2) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Rectangle`. This corresponds to the :code:`layer` attribute of a :code:`<rectangle>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Rectangle`. This corresponds to the :code:`layer` attribute of a :code:`<rectangle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Rectangle`. This corresponds to the :code:`rot` attribute of a :code:`<rectangle>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Rectangle`. This corresponds to the :code:`rot` attribute of a :code:`<rectangle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["rectangle"] = Rectangle
[docs]class Junction(EagleFilePart):
"""
Class representing the contents of a <junction> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
"""
def __init__(self):
"""
Construct an empty :class:`Junction` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Junction` from a :code:`junction` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Junction`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Junction` from a :code:`junction` element. This is useful if you have a subclass of :class:`Junction` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Junction`
"""
if root.tag != "junction":
raise EagleFormatError("Tried to create junction from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x)
r = r + str(self.y)
return r
[docs] def get_et(self):
"""
Generate a <junction> element tree for a :class:`Junction`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("junction")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Junction`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Junction`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Junction_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Junction_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Junction`. This corresponds to the :code:`x` attribute of a :code:`<junction>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Junction`. This corresponds to the :code:`x` attribute of a :code:`<junction>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Junction`. This corresponds to the :code:`y` attribute of a :code:`<junction>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Junction`. This corresponds to the :code:`y` attribute of a :code:`<junction>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["junction"] = Junction
[docs]class Description(EagleFilePart):
"""
Class representing the contents of a <description> tag in Eagle files.
Attributes:
* :code:`language`
"""
def __init__(self):
"""
Construct an empty :class:`Description` object.
"""
EagleFilePart.__init__(self)
self.language=None
self.text = ""
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Description` from a :code:`description` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Description`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Description` from a :code:`description` element. This is useful if you have a subclass of :class:`Description` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Description`
"""
if root.tag != "description":
raise EagleFormatError("Tried to create description from " + root.tag)
self.language=parseByType(parent, "str", root.get("language"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
self.text = root.text
def sortkey(self):
r = ""
r = r + str(self.language)
return r
[docs] def get_et(self):
"""
Generate a <description> element tree for a :class:`Description`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("description")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.language)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("language", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
r.text = self.text
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Description`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Description`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Description_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Description_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_language(self):
""" Return the value of :code:`language` for this :class:`Description`. This corresponds to the :code:`language` attribute of a :code:`<description>` in an Eagle file.
:rtype: :code:`str`
"""
return self.language
[docs] def set_language(self,v):
""" Set the value of :code:`language` for this :class:`Description`. This corresponds to the :code:`language` attribute of a :code:`<description>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.language = v
return self
[docs] def with_language(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`language`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`language` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_language()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.language == v else None
elif callable(v):
return self if v(self.language) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def with_text(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`text`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`text` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_text()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.text == v else None
elif callable(v):
return self if v(self.text) else None
else:
raise SwoopError("Illegal type passed to with_text")
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["description"] = Description
[docs]class BoardFile(EagleFile):
"""
Class representing the contents of a <eagle> tag in Eagle files.
Attributes:
* :code:`version`
Collections:
* :code:`grid`: Singleton :class:`Grid` object.
* :code:`description`: Singleton :class:`Description` object.
* :code:`designrules`: Singleton :class:`Designrules` object.
* :code:`compatibility`: Singleton :class:`Compatibility` object.
* :code:`setting`: List of :class:`Setting` objects.
* :code:`plain_element`: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects.
* :code:`approved`: List of :class:`Approved` objects.
* :code:`layer`: Map of :class:`Layer` objects indexed by their :code:`number`.
* :code:`library`: Map of :class:`Library` objects indexed by their :code:`name`.
* :code:`attribute`: Map of :class:`Attribute` objects indexed by their :code:`name`.
* :code:`variantdef`: Map of :class:`Variantdef` objects indexed by their :code:`name`.
* :code:`class`: Map of :class:`Class` objects indexed by their :code:`name`.
* :code:`pass`: Map of :class:`Pass` objects indexed by their :code:`name`.
* :code:`element`: Map of :class:`Element` objects indexed by their :code:`name`.
* :code:`signal`: Map of :class:`Signal` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`BoardFile` object.
"""
EagleFile.__init__(self)
self.version=None
self.settings=[]
self.plain_elements=[]
self.approved_errors=[]
self.layers={}
self.libraries={}
self.attributes={}
self.variantdefs={}
self.classes={}
self.autorouter_passes={}
self.elements={}
self.signals={}
self.grid=None
self.description=None
self.designrules=None
self.compatibility=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`BoardFile` from a :code:`eagle` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`BoardFile`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`BoardFile` from a :code:`eagle` element. This is useful if you have a subclass of :class:`BoardFile` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`BoardFile`
"""
if root.tag != "eagle":
raise EagleFormatError("Tried to create eagle from " + root.tag)
self.version=parseByType(parent, "str", root.get("version"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./drawing/layers/layer"):
self.add_layer(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/libraries/library"):
self.add_library(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/attributes/attribute"):
self.add_attribute(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/variantdefs/variantdef"):
self.add_variantdef(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/classes/class"):
self.add_class(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/autorouter/pass"):
self.add_pass(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/elements/element"):
self.add_element(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/board/signals/signal"):
self.add_signal(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./drawing/settings/setting"):
self.add_setting(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./drawing/board/plain/polygon|./drawing/board/plain/wire|./drawing/board/plain/text|./drawing/board/plain/dimension|./drawing/board/plain/circle|./drawing/board/plain/rectangle|./drawing/board/plain/frame|./drawing/board/plain/hole"):
self.add_plain_element(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./drawing/board/errors/approved"):
self.add_approved(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./drawing/grid")
if len(x) is not 0:
self.set_grid(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./drawing/board/description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./drawing/board/designrules")
if len(x) is not 0:
self.set_designrules(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./compatibility")
if len(x) is not 0:
self.set_compatibility(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.version)
return r
[docs] def get_et(self):
"""
Generate a <eagle> element tree for a :class:`BoardFile`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("eagle")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.version)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("version", v)
else:
r.set("version", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/settings/setting")
## add a list.
if len(self.settings) is not 0:
target = smartAddSubTags(r, "./drawing/settings/setting")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.settings,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.grid is not None:
target = smartAddSubTags(r, "./drawing/grid")
target.append(self.grid.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.layers) is not 0:
target = smartAddSubTags(r, "./drawing/layers/layer")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.layers.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./drawing/board/description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/plain/polygon|./drawing/board/plain/wire|./drawing/board/plain/text|./drawing/board/plain/dimension|./drawing/board/plain/circle|./drawing/board/plain/rectangle|./drawing/board/plain/frame|./drawing/board/plain/hole")
## add a list.
if len(self.plain_elements) is not 0:
target = smartAddSubTags(r, "./drawing/board/plain/polygon|./drawing/board/plain/wire|./drawing/board/plain/text|./drawing/board/plain/dimension|./drawing/board/plain/circle|./drawing/board/plain/rectangle|./drawing/board/plain/frame|./drawing/board/plain/hole")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.plain_elements,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/libraries/library")
## add a map.
if len(self.libraries) is not 0:
target = smartAddSubTags(r, "./drawing/board/libraries/library")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.libraries.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/attributes/attribute")
## add a map.
if len(self.attributes) is not 0:
target = smartAddSubTags(r, "./drawing/board/attributes/attribute")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.attributes.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/variantdefs/variantdef")
## add a map.
if len(self.variantdefs) is not 0:
target = smartAddSubTags(r, "./drawing/board/variantdefs/variantdef")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.variantdefs.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.classes) is not 0:
target = smartAddSubTags(r, "./drawing/board/classes/class")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.classes.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.designrules is not None:
target = smartAddSubTags(r, "./drawing/board/designrules")
target.append(self.designrules.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.autorouter_passes) is not 0:
target = smartAddSubTags(r, "./drawing/board/autorouter/pass")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.autorouter_passes.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/elements/element")
## add a map.
if len(self.elements) is not 0:
target = smartAddSubTags(r, "./drawing/board/elements/element")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.elements.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/board/signals/signal")
## add a map.
if len(self.signals) is not 0:
target = smartAddSubTags(r, "./drawing/board/signals/signal")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.signals.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.approved_errors) is not 0:
target = smartAddSubTags(r, "./drawing/board/errors/approved")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.approved_errors,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.compatibility is not None:
target = smartAddSubTags(r, "./compatibility")
target.append(self.compatibility.get_et())
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`BoardFile`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`BoardFile`
"""
n = copy.copy(self)
n.layers = {}
for x in self.layers.values():
n.add_layer(x.clone())
n.libraries = {}
for x in self.libraries.values():
n.add_library(x.clone())
n.attributes = {}
for x in self.attributes.values():
n.add_attribute(x.clone())
n.variantdefs = {}
for x in self.variantdefs.values():
n.add_variantdef(x.clone())
n.classes = {}
for x in self.classes.values():
n.add_class(x.clone())
n.autorouter_passes = {}
for x in self.autorouter_passes.values():
n.add_pass(x.clone())
n.elements = {}
for x in self.elements.values():
n.add_element(x.clone())
n.signals = {}
for x in self.signals.values():
n.add_signal(x.clone())
n.settings = []
for x in self.settings:
n.add_setting(x.clone())
n.plain_elements = []
for x in self.plain_elements:
n.add_plain_element(x.clone())
n.approved_errors = []
for x in self.approved_errors:
n.add_approved(x.clone())
if n.grid is not None:
n.grid = self.grid.clone()
if n.description is not None:
n.description = self.description.clone()
if n.designrules is not None:
n.designrules = self.designrules.clone()
if n.compatibility is not None:
n.compatibility = self.compatibility.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "BoardFile_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "BoardFile_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_version(self):
""" Return the value of :code:`version` for this :class:`BoardFile`. This corresponds to the :code:`version` attribute of a :code:`<eagle>` in an Eagle file.
:rtype: :code:`str`
"""
return self.version
[docs] def set_version(self,v):
""" Set the value of :code:`version` for this :class:`BoardFile`. This corresponds to the :code:`version` attribute of a :code:`<eagle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.version = v
return self
[docs] def with_version(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`version`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`version` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_version()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.version == v else None
elif callable(v):
return self if v(self.version) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_setting(self, s):
""" Add a :class:`Setting` to the :code:`settings` of this :class:`BoardFile`.
:param s: The :class:`Setting` to add.
:rtype: :code:`self`
"""
self.settings.append(s)
s.parent = self
return self
[docs] def get_nth_setting(self, n):
""" get then nth :class:`Setting` object from the :code:`settings` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Setting` object
"""
return self.settings[n]
[docs] def get_settings(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`settings` list of :class:`Setting` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Setting` objects
:rtype: List of :class:`Setting` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.settings
[docs] def clear_settings(self):
"""
Remove all the :class:`Setting` objects from the :code:`settings` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.settings:
efp.parent = None
self.settings = []
return self
[docs] def remove_setting(self, efp):
"""
Remove a :class:`Setting` from the :code:`settings` of this :class:`BoardFile`.
:param efp: The :class:`Setting` object to remove.
:rtype: :code:`self`
"""
self.settings = [x for x in self.settings if x != efp]
efp.parent = None
return self
[docs] def add_plain_element(self, s):
""" Add a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` to the :code:`plain_elements` of this :class:`BoardFile`.
:param s: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` to add.
:rtype: :code:`self`
"""
self.plain_elements.append(s)
s.parent = self
return self
[docs] def get_nth_plain_element(self, n):
""" get then nth :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` object from the :code:`plain_elements` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` object
"""
return self.plain_elements[n]
[docs] def get_plain_elements(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`plain_elements` list of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects
:rtype: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.plain_elements
[docs] def clear_plain_elements(self):
"""
Remove all the :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` and :class:`Hole` objects from the :code:`plain_elements` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.plain_elements:
efp.parent = None
self.plain_elements = []
return self
[docs] def remove_plain_element(self, efp):
"""
Remove a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` from the :code:`plain_elements` of this :class:`BoardFile`.
:param efp: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Frame` or :class:`Hole` object to remove.
:rtype: :code:`self`
"""
self.plain_elements = [x for x in self.plain_elements if x != efp]
efp.parent = None
return self
[docs] def add_approved(self, s):
""" Add a :class:`Approved` to the :code:`approved_errors` of this :class:`BoardFile`.
:param s: The :class:`Approved` to add.
:rtype: :code:`self`
"""
self.approved_errors.append(s)
s.parent = self
return self
[docs] def get_nth_approved(self, n):
""" get then nth :class:`Approved` object from the :code:`approved_errors` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Approved` object
"""
return self.approved_errors[n]
[docs] def get_approved_errors(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`approved_errors` list of :class:`Approved` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Approved` objects
:rtype: List of :class:`Approved` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.approved_errors
[docs] def clear_approved_errors(self):
"""
Remove all the :class:`Approved` objects from the :code:`approved_errors` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.approved_errors:
efp.parent = None
self.approved_errors = []
return self
[docs] def remove_approved(self, efp):
"""
Remove a :class:`Approved` from the :code:`approved_errors` of this :class:`BoardFile`.
:param efp: The :class:`Approved` object to remove.
:rtype: :code:`self`
"""
self.approved_errors = [x for x in self.approved_errors if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_library(self, s):
""" Add a :class:`Library` to the :code:`libraries` of this :class:`BoardFile`.
:param s: The :class:`Library` to add.
:rtype: :code:`self`
"""
self.libraries[s.name] = s
s.parent = self
return self
[docs] def get_nth_library(self, n):
""" get then nth :class:`Library` object from the :code:`libraries` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Library` object
"""
return self.libraries.values()[n]
[docs] def get_library(self, key):
""" Lookup and return a :class:`Library` from the :code:`libraries` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Library` objects.
:rtype: A :class:`Library` object or :code:`None`, if there is no such item.
"""
return self.libraries.get(key)
[docs] def get_libraries(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`libraries` map of :class:`Library` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Library` objects
:rtype: List of :class:`Library` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.libraries.values()
[docs] def clear_libraries(self):
"""
Remove all the :class:`Library` objects from the :code:`libraries` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.libraries.values():
efp.parent = None
self.libraries = {}
return self
[docs] def remove_library(self, efp):
"""
Remove a :class:`Library` from the :code:`libraries` of this :class:`BoardFile`.
:param efp: The :class:`Library` object to remove.
:rtype: :code:`self`
"""
del self.libraries[efp.name]
efp.parent = None
return self
[docs] def add_attribute(self, s):
""" Add a :class:`Attribute` to the :code:`attributes` of this :class:`BoardFile`.
:param s: The :class:`Attribute` to add.
:rtype: :code:`self`
"""
self.attributes[s.name] = s
s.parent = self
return self
[docs] def get_nth_attribute(self, n):
""" get then nth :class:`Attribute` object from the :code:`attributes` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Attribute` object
"""
return self.attributes.values()[n]
[docs] def get_attribute(self, key):
""" Lookup and return a :class:`Attribute` from the :code:`attributes` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Attribute` objects.
:rtype: A :class:`Attribute` object or :code:`None`, if there is no such item.
"""
return self.attributes.get(key)
[docs] def get_attributes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`attributes` map of :class:`Attribute` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Attribute` objects
:rtype: List of :class:`Attribute` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.attributes.values()
[docs] def clear_attributes(self):
"""
Remove all the :class:`Attribute` objects from the :code:`attributes` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.attributes.values():
efp.parent = None
self.attributes = {}
return self
[docs] def remove_attribute(self, efp):
"""
Remove a :class:`Attribute` from the :code:`attributes` of this :class:`BoardFile`.
:param efp: The :class:`Attribute` object to remove.
:rtype: :code:`self`
"""
del self.attributes[efp.name]
efp.parent = None
return self
[docs] def add_variantdef(self, s):
""" Add a :class:`Variantdef` to the :code:`variantdefs` of this :class:`BoardFile`.
:param s: The :class:`Variantdef` to add.
:rtype: :code:`self`
"""
self.variantdefs[s.name] = s
s.parent = self
return self
[docs] def get_nth_variantdef(self, n):
""" get then nth :class:`Variantdef` object from the :code:`variantdefs` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Variantdef` object
"""
return self.variantdefs.values()[n]
[docs] def get_variantdef(self, key):
""" Lookup and return a :class:`Variantdef` from the :code:`variantdefs` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Variantdef` objects.
:rtype: A :class:`Variantdef` object or :code:`None`, if there is no such item.
"""
return self.variantdefs.get(key)
[docs] def get_variantdefs(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`variantdefs` map of :class:`Variantdef` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Variantdef` objects
:rtype: List of :class:`Variantdef` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.variantdefs.values()
[docs] def clear_variantdefs(self):
"""
Remove all the :class:`Variantdef` objects from the :code:`variantdefs` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.variantdefs.values():
efp.parent = None
self.variantdefs = {}
return self
[docs] def remove_variantdef(self, efp):
"""
Remove a :class:`Variantdef` from the :code:`variantdefs` of this :class:`BoardFile`.
:param efp: The :class:`Variantdef` object to remove.
:rtype: :code:`self`
"""
del self.variantdefs[efp.name]
efp.parent = None
return self
[docs] def add_class(self, s):
""" Add a :class:`Class` to the :code:`classes` of this :class:`BoardFile`.
:param s: The :class:`Class` to add.
:rtype: :code:`self`
"""
self.classes[s.name] = s
s.parent = self
return self
[docs] def get_nth_class(self, n):
""" get then nth :class:`Class` object from the :code:`classes` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Class` object
"""
return self.classes.values()[n]
[docs] def get_class(self, key):
""" Lookup and return a :class:`Class` from the :code:`classes` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Class` objects.
:rtype: A :class:`Class` object or :code:`None`, if there is no such item.
"""
return self.classes.get(key)
[docs] def get_classes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`classes` map of :class:`Class` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Class` objects
:rtype: List of :class:`Class` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.classes.values()
[docs] def clear_classes(self):
"""
Remove all the :class:`Class` objects from the :code:`classes` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.classes.values():
efp.parent = None
self.classes = {}
return self
[docs] def remove_class(self, efp):
"""
Remove a :class:`Class` from the :code:`classes` of this :class:`BoardFile`.
:param efp: The :class:`Class` object to remove.
:rtype: :code:`self`
"""
del self.classes[efp.name]
efp.parent = None
return self
[docs] def add_pass(self, s):
""" Add a :class:`Pass` to the :code:`autorouter_passes` of this :class:`BoardFile`.
:param s: The :class:`Pass` to add.
:rtype: :code:`self`
"""
self.autorouter_passes[s.name] = s
s.parent = self
return self
[docs] def get_nth_pass(self, n):
""" get then nth :class:`Pass` object from the :code:`autorouter_passes` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Pass` object
"""
return self.autorouter_passes.values()[n]
[docs] def get_pass(self, key):
""" Lookup and return a :class:`Pass` from the :code:`autorouter_passes` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Pass` objects.
:rtype: A :class:`Pass` object or :code:`None`, if there is no such item.
"""
return self.autorouter_passes.get(key)
[docs] def get_autorouter_passes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`autorouter_passes` map of :class:`Pass` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Pass` objects
:rtype: List of :class:`Pass` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.autorouter_passes.values()
[docs] def clear_autorouter_passes(self):
"""
Remove all the :class:`Pass` objects from the :code:`autorouter_passes` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.autorouter_passes.values():
efp.parent = None
self.autorouter_passes = {}
return self
[docs] def remove_pass(self, efp):
"""
Remove a :class:`Pass` from the :code:`autorouter_passes` of this :class:`BoardFile`.
:param efp: The :class:`Pass` object to remove.
:rtype: :code:`self`
"""
del self.autorouter_passes[efp.name]
efp.parent = None
return self
[docs] def add_element(self, s):
""" Add a :class:`Element` to the :code:`elements` of this :class:`BoardFile`.
:param s: The :class:`Element` to add.
:rtype: :code:`self`
"""
self.elements[s.name] = s
s.parent = self
return self
[docs] def get_nth_element(self, n):
""" get then nth :class:`Element` object from the :code:`elements` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Element` object
"""
return self.elements.values()[n]
[docs] def get_element(self, key):
""" Lookup and return a :class:`Element` from the :code:`elements` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Element` objects.
:rtype: A :class:`Element` object or :code:`None`, if there is no such item.
"""
return self.elements.get(key)
[docs] def get_elements(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`elements` map of :class:`Element` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Element` objects
:rtype: List of :class:`Element` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.elements.values()
[docs] def clear_elements(self):
"""
Remove all the :class:`Element` objects from the :code:`elements` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.elements.values():
efp.parent = None
self.elements = {}
return self
[docs] def remove_element(self, efp):
"""
Remove a :class:`Element` from the :code:`elements` of this :class:`BoardFile`.
:param efp: The :class:`Element` object to remove.
:rtype: :code:`self`
"""
del self.elements[efp.name]
efp.parent = None
return self
[docs] def add_signal(self, s):
""" Add a :class:`Signal` to the :code:`signals` of this :class:`BoardFile`.
:param s: The :class:`Signal` to add.
:rtype: :code:`self`
"""
self.signals[s.name] = s
s.parent = self
return self
[docs] def get_nth_signal(self, n):
""" get then nth :class:`Signal` object from the :code:`signals` of this :class:`BoardFile`.
:param n: Index of the item to return.
:rtype: :class:`Signal` object
"""
return self.signals.values()[n]
[docs] def get_signal(self, key):
""" Lookup and return a :class:`Signal` from the :code:`signals` of this :class:`BoardFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Signal` objects.
:rtype: A :class:`Signal` object or :code:`None`, if there is no such item.
"""
return self.signals.get(key)
[docs] def get_signals(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`signals` map of :class:`Signal` objects for this :class:`BoardFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Signal` objects
:rtype: List of :class:`Signal` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.signals.values()
[docs] def clear_signals(self):
"""
Remove all the :class:`Signal` objects from the :code:`signals` of this :class:`BoardFile`.
:rtype: :code:`self`
"""
for efp in self.signals.values():
efp.parent = None
self.signals = {}
return self
[docs] def remove_signal(self, efp):
"""
Remove a :class:`Signal` from the :code:`signals` of this :class:`BoardFile`.
:param efp: The :class:`Signal` object to remove.
:rtype: :code:`self`
"""
del self.signals[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_grid(self, s):
""" Set the :class:`Grid` for this :class:`BoardFile`.
:param s: :class:`Grid` to set.
:rtype: :code:`self`
"""
if self.grid is not None:
self.grid.parent = None
self.grid = s
if self.grid.parent is not None:
self.grid.parent = self
return self
[docs] def get_grid(self):
""" Get the grid from this :class:`BoardFile`.
:rtype: :class:`Grid` object
"""
return self.grid
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`BoardFile`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`BoardFile`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def set_designrules(self, s):
""" Set the :class:`Designrules` for this :class:`BoardFile`.
:param s: :class:`Designrules` to set.
:rtype: :code:`self`
"""
if self.designrules is not None:
self.designrules.parent = None
self.designrules = s
if self.designrules.parent is not None:
self.designrules.parent = self
return self
[docs] def get_designrules(self):
""" Get the designrules from this :class:`BoardFile`.
:rtype: :class:`Designrules` object
"""
return self.designrules
[docs] def set_compatibility(self, s):
""" Set the :class:`Compatibility` for this :class:`BoardFile`.
:param s: :class:`Compatibility` to set.
:rtype: :code:`self`
"""
if self.compatibility is not None:
self.compatibility.parent = None
self.compatibility = s
if self.compatibility.parent is not None:
self.compatibility.parent = self
return self
[docs] def get_compatibility(self):
""" Get the compatibility from this :class:`BoardFile`.
:rtype: :class:`Compatibility` object
"""
return self.compatibility
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.settings
r = r + self.plain_elements
r = r + self.approved_errors
r = r + self.layers.values()
r = r + self.libraries.values()
r = r + self.attributes.values()
r = r + self.variantdefs.values()
r = r + self.classes.values()
r = r + self.autorouter_passes.values()
r = r + self.elements.values()
r = r + self.signals.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_layer(efp)
except:
pass
try:
self.remove_library(efp)
except:
pass
try:
self.remove_attribute(efp)
except:
pass
try:
self.remove_variantdef(efp)
except:
pass
try:
self.remove_class(efp)
except:
pass
try:
self.remove_pass(efp)
except:
pass
try:
self.remove_element(efp)
except:
pass
try:
self.remove_signal(efp)
except:
pass
try:
self.remove_setting(efp)
except:
pass
try:
self.remove_plain_element(efp)
except:
pass
try:
self.remove_approved(efp)
except:
pass
if self.get_grid == efp:
self.set_grid(None)
if self.get_description == efp:
self.set_description(None)
if self.get_designrules == efp:
self.set_designrules(None)
if self.get_compatibility == efp:
self.set_compatibility(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["eagle"] = BoardFile
[docs]class Bus(EagleFilePart):
"""
Class representing the contents of a <bus> tag in Eagle files.
Attributes:
* :code:`name`
Collections:
* :code:`segment`: List of :class:`Segment` objects.
"""
def __init__(self):
"""
Construct an empty :class:`Bus` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.segments=[]
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Bus` from a :code:`bus` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Bus`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Bus` from a :code:`bus` element. This is useful if you have a subclass of :class:`Bus` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Bus`
"""
if root.tag != "bus":
raise EagleFormatError("Tried to create bus from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
for c in root.xpath("./segment"):
self.add_segment(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
return r
[docs] def get_et(self):
"""
Generate a <bus> element tree for a :class:`Bus`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("bus")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.segments) is not 0:
target = smartAddSubTags(r, "./segment")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.segments,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Bus`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Bus`
"""
n = copy.copy(self)
n.segments = []
for x in self.segments:
n.add_segment(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Bus_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Bus_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Bus`. This corresponds to the :code:`name` attribute of a :code:`<bus>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Bus`. This corresponds to the :code:`name` attribute of a :code:`<bus>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_segment(self, s):
""" Add a :class:`Segment` to the :code:`segments` of this :class:`Bus`.
:param s: The :class:`Segment` to add.
:rtype: :code:`self`
"""
self.segments.append(s)
s.parent = self
return self
[docs] def get_nth_segment(self, n):
""" get then nth :class:`Segment` object from the :code:`segments` of this :class:`Bus`.
:param n: Index of the item to return.
:rtype: :class:`Segment` object
"""
return self.segments[n]
[docs] def get_segments(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`segments` list of :class:`Segment` objects for this :class:`Bus`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Segment` objects
:rtype: List of :class:`Segment` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.segments
[docs] def clear_segments(self):
"""
Remove all the :class:`Segment` objects from the :code:`segments` of this :class:`Bus`.
:rtype: :code:`self`
"""
for efp in self.segments:
efp.parent = None
self.segments = []
return self
[docs] def remove_segment(self, efp):
"""
Remove a :class:`Segment` from the :code:`segments` of this :class:`Bus`.
:param efp: The :class:`Segment` object to remove.
:rtype: :code:`self`
"""
self.segments = [x for x in self.segments if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.segments
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_segment(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["bus"] = Bus
[docs]class Symbol(EagleFilePart):
"""
Class representing the contents of a <symbol> tag in Eagle files.
Attributes:
* :code:`name`
Collections:
* :code:`description`: Singleton :class:`Description` object.
* :code:`drawing_element`: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` and :class:`Hole` objects.
* :code:`pin`: Map of :class:`Pin` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Symbol` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.drawing_elements=[]
self.pins={}
self.description=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Symbol` from a :code:`symbol` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Symbol`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Symbol` from a :code:`symbol` element. This is useful if you have a subclass of :class:`Symbol` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Symbol`
"""
if root.tag != "symbol":
raise EagleFormatError("Tried to create symbol from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./pin"):
self.add_pin(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./polygon|./wire|./text|./dimension|./circle|./rectangle|./frame|./hole"):
self.add_drawing_element(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
return r
[docs] def get_et(self):
"""
Generate a <symbol> element tree for a :class:`Symbol`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("symbol")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.drawing_elements) is not 0:
target = smartAddSubTags(r, "./polygon|./wire|./text|./dimension|./circle|./rectangle|./frame|./hole")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.drawing_elements,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.pins) is not 0:
target = smartAddSubTags(r, "./pin")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.pins.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Symbol`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Symbol`
"""
n = copy.copy(self)
n.pins = {}
for x in self.pins.values():
n.add_pin(x.clone())
n.drawing_elements = []
for x in self.drawing_elements:
n.add_drawing_element(x.clone())
if n.description is not None:
n.description = self.description.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Symbol_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Symbol_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Symbol`. This corresponds to the :code:`name` attribute of a :code:`<symbol>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Symbol`. This corresponds to the :code:`name` attribute of a :code:`<symbol>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_drawing_element(self, s):
""" Add a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` to the :code:`drawing_elements` of this :class:`Symbol`.
:param s: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` to add.
:rtype: :code:`self`
"""
self.drawing_elements.append(s)
s.parent = self
return self
[docs] def get_nth_drawing_element(self, n):
""" get then nth :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` object from the :code:`drawing_elements` of this :class:`Symbol`.
:param n: Index of the item to return.
:rtype: :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` object
"""
return self.drawing_elements[n]
[docs] def get_drawing_elements(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`drawing_elements` list of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` objects for this :class:`Symbol`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` and :class:`Hole` objects
:rtype: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` and :class:`Hole` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.drawing_elements
[docs] def clear_drawing_elements(self):
"""
Remove all the :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` and :class:`Hole` objects from the :code:`drawing_elements` of this :class:`Symbol`.
:rtype: :code:`self`
"""
for efp in self.drawing_elements:
efp.parent = None
self.drawing_elements = []
return self
[docs] def remove_drawing_element(self, efp):
"""
Remove a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` from the :code:`drawing_elements` of this :class:`Symbol`.
:param efp: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle` or :class:`Hole` object to remove.
:rtype: :code:`self`
"""
self.drawing_elements = [x for x in self.drawing_elements if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_pin(self, s):
""" Add a :class:`Pin` to the :code:`pins` of this :class:`Symbol`.
:param s: The :class:`Pin` to add.
:rtype: :code:`self`
"""
self.pins[s.name] = s
s.parent = self
return self
[docs] def get_nth_pin(self, n):
""" get then nth :class:`Pin` object from the :code:`pins` of this :class:`Symbol`.
:param n: Index of the item to return.
:rtype: :class:`Pin` object
"""
return self.pins.values()[n]
[docs] def get_pin(self, key):
""" Lookup and return a :class:`Pin` from the :code:`pins` of this :class:`Symbol`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Pin` objects.
:rtype: A :class:`Pin` object or :code:`None`, if there is no such item.
"""
return self.pins.get(key)
[docs] def get_pins(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`pins` map of :class:`Pin` objects for this :class:`Symbol`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Pin` objects
:rtype: List of :class:`Pin` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.pins.values()
[docs] def clear_pins(self):
"""
Remove all the :class:`Pin` objects from the :code:`pins` of this :class:`Symbol`.
:rtype: :code:`self`
"""
for efp in self.pins.values():
efp.parent = None
self.pins = {}
return self
[docs] def remove_pin(self, efp):
"""
Remove a :class:`Pin` from the :code:`pins` of this :class:`Symbol`.
:param efp: The :class:`Pin` object to remove.
:rtype: :code:`self`
"""
del self.pins[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`Symbol`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`Symbol`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.drawing_elements
r = r + self.pins.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_pin(efp)
except:
pass
try:
self.remove_drawing_element(efp)
except:
pass
if self.get_description == efp:
self.set_description(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["symbol"] = Symbol
[docs]class Variant(EagleFilePart):
"""
Class representing the contents of a <variant> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`populate`
* :code:`value`
* :code:`technology`
"""
def __init__(self):
"""
Construct an empty :class:`Variant` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.populate=None
self.value=None
self.technology=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Variant` from a :code:`variant` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Variant`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Variant` from a :code:`variant` element. This is useful if you have a subclass of :class:`Variant` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Variant`
"""
if root.tag != "variant":
raise EagleFormatError("Tried to create variant from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.populate=parseByType(parent, "bool", root.get("populate"))
self.value=parseByType(parent, "str", root.get("value"))
self.technology=parseByType(parent, "str", root.get("technology"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.populate)
r = r + str(self.value)
r = r + str(self.technology)
return r
[docs] def get_et(self):
"""
Generate a <variant> element tree for a :class:`Variant`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("variant")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "bool", self.populate)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("populate", v)
## Unparse the values.
v = unparseByType(self, "str", self.value)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("value", v)
## Unparse the values.
v = unparseByType(self, "str", self.technology)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("technology", v)
else:
r.set("technology", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Variant`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Variant`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Variant_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Variant_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Variant`. This corresponds to the :code:`name` attribute of a :code:`<variant>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Variant`. This corresponds to the :code:`name` attribute of a :code:`<variant>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_populate(self):
""" Return the value of :code:`populate` for this :class:`Variant`. This corresponds to the :code:`populate` attribute of a :code:`<variant>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.populate
[docs] def set_populate(self,v):
""" Set the value of :code:`populate` for this :class:`Variant`. This corresponds to the :code:`populate` attribute of a :code:`<variant>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.populate = v
return self
[docs] def with_populate(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`populate`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`populate` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_populate()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.populate == v else None
elif callable(v):
return self if v(self.populate) else None
[docs] def get_value(self):
""" Return the value of :code:`value` for this :class:`Variant`. This corresponds to the :code:`value` attribute of a :code:`<variant>` in an Eagle file.
:rtype: :code:`str`
"""
return self.value
[docs] def set_value(self,v):
""" Set the value of :code:`value` for this :class:`Variant`. This corresponds to the :code:`value` attribute of a :code:`<variant>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.value = v
return self
[docs] def with_value(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`value`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`value` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_value()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.value == v else None
elif callable(v):
return self if v(self.value) else None
[docs] def get_technology(self):
""" Return the value of :code:`technology` for this :class:`Variant`. This corresponds to the :code:`technology` attribute of a :code:`<variant>` in an Eagle file.
:rtype: :code:`str`
"""
return self.technology
[docs] def set_technology(self,v):
""" Set the value of :code:`technology` for this :class:`Variant`. This corresponds to the :code:`technology` attribute of a :code:`<variant>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.technology = v
return self
[docs] def with_technology(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`technology`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`technology` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_technology()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.technology == v else None
elif callable(v):
return self if v(self.technology) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["variant"] = Variant
[docs]class Compatibility(EagleFilePart):
"""
Class representing the contents of a <compatibility> tag in Eagle files.
Attributes:
Collections:
* :code:`note`: List of :class:`Note` objects.
"""
def __init__(self):
"""
Construct an empty :class:`Compatibility` object.
"""
EagleFilePart.__init__(self)
self.notes=[]
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Compatibility` from a :code:`compatibility` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Compatibility`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Compatibility` from a :code:`compatibility` element. This is useful if you have a subclass of :class:`Compatibility` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Compatibility`
"""
if root.tag != "compatibility":
raise EagleFormatError("Tried to create compatibility from " + root.tag)
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
for c in root.xpath("./note"):
self.add_note(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
return r
[docs] def get_et(self):
"""
Generate a <compatibility> element tree for a :class:`Compatibility`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("compatibility")
### Set the tag attributes
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.notes) is not 0:
target = smartAddSubTags(r, "./note")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.notes,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Compatibility`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Compatibility`
"""
n = copy.copy(self)
n.notes = []
for x in self.notes:
n.add_note(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Compatibility_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Compatibility_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_note(self, s):
""" Add a :class:`Note` to the :code:`notes` of this :class:`Compatibility`.
:param s: The :class:`Note` to add.
:rtype: :code:`self`
"""
self.notes.append(s)
s.parent = self
return self
[docs] def get_nth_note(self, n):
""" get then nth :class:`Note` object from the :code:`notes` of this :class:`Compatibility`.
:param n: Index of the item to return.
:rtype: :class:`Note` object
"""
return self.notes[n]
[docs] def get_notes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`notes` list of :class:`Note` objects for this :class:`Compatibility`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Note` objects
:rtype: List of :class:`Note` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.notes
[docs] def clear_notes(self):
"""
Remove all the :class:`Note` objects from the :code:`notes` of this :class:`Compatibility`.
:rtype: :code:`self`
"""
for efp in self.notes:
efp.parent = None
self.notes = []
return self
[docs] def remove_note(self, efp):
"""
Remove a :class:`Note` from the :code:`notes` of this :class:`Compatibility`.
:param efp: The :class:`Note` object to remove.
:rtype: :code:`self`
"""
self.notes = [x for x in self.notes if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.notes
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_note(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["compatibility"] = Compatibility
[docs]class Class(EagleFilePart):
"""
Class representing the contents of a <class> tag in Eagle files.
Attributes:
* :code:`number`
* :code:`name`
* :code:`width`
* :code:`drill`
Collections:
* :code:`clearance`: Map of :class:`Clearance` objects indexed by their :code:`netclass`.
"""
def __init__(self):
"""
Construct an empty :class:`Class` object.
"""
EagleFilePart.__init__(self)
self.number=None
self.name=None
self.width=None
self.drill=None
self.clearances={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Class` from a :code:`class` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Class`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Class` from a :code:`class` element. This is useful if you have a subclass of :class:`Class` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Class`
"""
if root.tag != "class":
raise EagleFormatError("Tried to create class from " + root.tag)
self.number=parseByType(parent, "str", root.get("number"))
self.name=parseByType(parent, "str", root.get("name"))
self.width=parseByType(parent, "float", root.get("width"))
self.drill=parseByType(parent, "float", root.get("drill"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./clearance"):
self.add_clearance(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.number)
r = r + str(self.name)
r = r + str(self.width)
r = r + str(self.drill)
return r
[docs] def get_et(self):
"""
Generate a <class> element tree for a :class:`Class`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("class")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.number)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("number", v)
else:
r.set("number", "")
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "float", self.width)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("width", v)
## Unparse the values.
v = unparseByType(self, "float", self.drill)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("drill", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.clearances) is not 0:
target = smartAddSubTags(r, "./clearance")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.clearances.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Class`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Class`
"""
n = copy.copy(self)
n.clearances = {}
for x in self.clearances.values():
n.add_clearance(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Class_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Class_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_number(self):
""" Return the value of :code:`number` for this :class:`Class`. This corresponds to the :code:`number` attribute of a :code:`<class>` in an Eagle file.
:rtype: :code:`str`
"""
return self.number
[docs] def set_number(self,v):
""" Set the value of :code:`number` for this :class:`Class`. This corresponds to the :code:`number` attribute of a :code:`<class>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.number = v
return self
[docs] def with_number(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`number`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`number` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_number()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.number == v else None
elif callable(v):
return self if v(self.number) else None
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Class`. This corresponds to the :code:`name` attribute of a :code:`<class>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Class`. This corresponds to the :code:`name` attribute of a :code:`<class>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_width(self):
""" Return the value of :code:`width` for this :class:`Class`. This corresponds to the :code:`width` attribute of a :code:`<class>` in an Eagle file.
:rtype: :code:`float`
"""
return self.width
[docs] def set_width(self,v):
""" Set the value of :code:`width` for this :class:`Class`. This corresponds to the :code:`width` attribute of a :code:`<class>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.width = v
return self
[docs] def with_width(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`width`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`width` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_width()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.width == v else None
elif callable(v):
return self if v(self.width) else None
[docs] def get_drill(self):
""" Return the value of :code:`drill` for this :class:`Class`. This corresponds to the :code:`drill` attribute of a :code:`<class>` in an Eagle file.
:rtype: :code:`float`
"""
return self.drill
[docs] def set_drill(self,v):
""" Set the value of :code:`drill` for this :class:`Class`. This corresponds to the :code:`drill` attribute of a :code:`<class>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.drill = v
return self
[docs] def with_drill(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`drill`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`drill` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_drill()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.drill == v else None
elif callable(v):
return self if v(self.drill) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_clearance(self, s):
""" Add a :class:`Clearance` to the :code:`clearances` of this :class:`Class`.
:param s: The :class:`Clearance` to add.
:rtype: :code:`self`
"""
self.clearances[s.netclass] = s
s.parent = self
return self
[docs] def get_nth_clearance(self, n):
""" get then nth :class:`Clearance` object from the :code:`clearances` of this :class:`Class`.
:param n: Index of the item to return.
:rtype: :class:`Clearance` object
"""
return self.clearances.values()[n]
[docs] def get_clearance(self, key):
""" Lookup and return a :class:`Clearance` from the :code:`clearances` of this :class:`Class`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`netclass` of the :class:`Clearance` objects.
:rtype: A :class:`Clearance` object or :code:`None`, if there is no such item.
"""
return self.clearances.get(key)
[docs] def get_clearances(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`clearances` map of :class:`Clearance` objects for this :class:`Class`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Clearance` objects
:rtype: List of :class:`Clearance` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.clearances.values()
[docs] def clear_clearances(self):
"""
Remove all the :class:`Clearance` objects from the :code:`clearances` of this :class:`Class`.
:rtype: :code:`self`
"""
for efp in self.clearances.values():
efp.parent = None
self.clearances = {}
return self
[docs] def remove_clearance(self, efp):
"""
Remove a :class:`Clearance` from the :code:`clearances` of this :class:`Class`.
:param efp: The :class:`Clearance` object to remove.
:rtype: :code:`self`
"""
del self.clearances[efp.netclass]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.clearances.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_clearance(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["class"] = Class
[docs]class Variantdef(EagleFilePart):
"""
Class representing the contents of a <variantdef> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`current`
"""
def __init__(self):
"""
Construct an empty :class:`Variantdef` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.current=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Variantdef` from a :code:`variantdef` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Variantdef`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Variantdef` from a :code:`variantdef` element. This is useful if you have a subclass of :class:`Variantdef` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Variantdef`
"""
if root.tag != "variantdef":
raise EagleFormatError("Tried to create variantdef from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.current=parseByType(parent, "bool", root.get("current"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.current)
return r
[docs] def get_et(self):
"""
Generate a <variantdef> element tree for a :class:`Variantdef`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("variantdef")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "bool", self.current)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("current", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Variantdef`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Variantdef`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Variantdef_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Variantdef_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Variantdef`. This corresponds to the :code:`name` attribute of a :code:`<variantdef>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Variantdef`. This corresponds to the :code:`name` attribute of a :code:`<variantdef>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_current(self):
""" Return the value of :code:`current` for this :class:`Variantdef`. This corresponds to the :code:`current` attribute of a :code:`<variantdef>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.current
[docs] def set_current(self,v):
""" Set the value of :code:`current` for this :class:`Variantdef`. This corresponds to the :code:`current` attribute of a :code:`<variantdef>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.current = v
return self
[docs] def with_current(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`current`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`current` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_current()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.current == v else None
elif callable(v):
return self if v(self.current) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["variantdef"] = Variantdef
class Base_Part(EagleFilePart):
"""
Class representing the contents of a <part> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`library`
* :code:`deviceset`
* :code:`device`
* :code:`technology`
* :code:`value`
Collections:
* :code:`attribute`: Map of :class:`Attribute` objects indexed by their :code:`name`.
* :code:`variant`: Map of :class:`Variant` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Base_Part` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.library=None
self.deviceset=None
self.device=None
self.technology=None
self.value=None
self.attributes={}
self.variants={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Part` from a :code:`part` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Part`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Part` from a :code:`part` element. This is useful if you have a subclass of :class:`Part` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Part`
"""
if root.tag != "part":
raise EagleFormatError("Tried to create part from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.library=parseByType(parent, "str", root.get("library"))
self.deviceset=parseByType(parent, "str", root.get("deviceset"))
self.device=parseByType(parent, "str", root.get("device"))
self.technology=parseByType(parent, "None_is_empty_string", root.get("technology"))
self.value=parseByType(parent, "str", root.get("value"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./attribute"):
self.add_attribute(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./variant"):
self.add_variant(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.library)
r = r + str(self.deviceset)
r = r + str(self.device)
r = r + str(self.technology)
r = r + str(self.value)
return r
def get_et(self):
"""
Generate a <part> element tree for a :class:`Part`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("part")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.library)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("library", v)
else:
r.set("library", "")
## Unparse the values.
v = unparseByType(self, "str", self.deviceset)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("deviceset", v)
else:
r.set("deviceset", "")
## Unparse the values.
v = unparseByType(self, "str", self.device)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("device", v)
else:
r.set("device", "")
## Unparse the values.
v = unparseByType(self, "None_is_empty_string", self.technology)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("technology", v)
## Unparse the values.
v = unparseByType(self, "str", self.value)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("value", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./attribute")
## add a map.
if len(self.attributes) is not 0:
target = smartAddSubTags(r, "./attribute")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.attributes.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.variants) is not 0:
target = smartAddSubTags(r, "./variant")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.variants.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
def clone(self):
"""
Recursively clone this :code:`Part`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Part`
"""
n = copy.copy(self)
n.attributes = {}
for x in self.attributes.values():
n.add_attribute(x.clone())
n.variants = {}
for x in self.variants.values():
n.add_variant(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Part_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Part_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
def get_name(self):
""" Return the value of :code:`name` for this :class:`Part`. This corresponds to the :code:`name` attribute of a :code:`<part>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Part`. This corresponds to the :code:`name` attribute of a :code:`<part>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
def get_library(self):
""" Return the value of :code:`library` for this :class:`Part`. This corresponds to the :code:`library` attribute of a :code:`<part>` in an Eagle file.
:rtype: :code:`str`
"""
return self.library
def set_library(self,v):
""" Set the value of :code:`library` for this :class:`Part`. This corresponds to the :code:`library` attribute of a :code:`<part>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.library = v
return self
def with_library(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`library`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`library` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_library()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.library == v else None
elif callable(v):
return self if v(self.library) else None
def get_deviceset(self):
""" Return the value of :code:`deviceset` for this :class:`Part`. This corresponds to the :code:`deviceset` attribute of a :code:`<part>` in an Eagle file.
:rtype: :code:`str`
"""
return self.deviceset
def set_deviceset(self,v):
""" Set the value of :code:`deviceset` for this :class:`Part`. This corresponds to the :code:`deviceset` attribute of a :code:`<part>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.deviceset = v
return self
def with_deviceset(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`deviceset`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`deviceset` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_deviceset()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.deviceset == v else None
elif callable(v):
return self if v(self.deviceset) else None
def get_device(self):
""" Return the value of :code:`device` for this :class:`Part`. This corresponds to the :code:`device` attribute of a :code:`<part>` in an Eagle file.
:rtype: :code:`str`
"""
return self.device
def set_device(self,v):
""" Set the value of :code:`device` for this :class:`Part`. This corresponds to the :code:`device` attribute of a :code:`<part>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.device = v
return self
def with_device(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`device`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`device` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_device()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.device == v else None
elif callable(v):
return self if v(self.device) else None
def get_technology(self):
""" Return the value of :code:`technology` for this :class:`Part`. This corresponds to the :code:`technology` attribute of a :code:`<part>` in an Eagle file.
:rtype: :code:`None_is_empty_string`
"""
return self.technology
def set_technology(self,v):
""" Set the value of :code:`technology` for this :class:`Part`. This corresponds to the :code:`technology` attribute of a :code:`<part>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.technology = v
return self
def with_technology(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`technology`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`technology` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_technology()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.technology == v else None
elif callable(v):
return self if v(self.technology) else None
def get_value(self):
""" Return the value of :code:`value` for this :class:`Part`. This corresponds to the :code:`value` attribute of a :code:`<part>` in an Eagle file.
:rtype: :code:`str`
"""
return self.value
def set_value(self,v):
""" Set the value of :code:`value` for this :class:`Part`. This corresponds to the :code:`value` attribute of a :code:`<part>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.value = v
return self
def with_value(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`value`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`value` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_value()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.value == v else None
elif callable(v):
return self if v(self.value) else None
##### Lookup functions that return EFPs instead of just attribute values.
def find_library(self):
"""Find the :class:`Library` object refered to by the :code:`library` attribute of this object. This is like
:meth:`get_library`, except it returns the :class:`Library` object instead of its name.
:returns: The object
:rtype: :class:`Library`
"""
f = lambda efp, key: efp.get_parent().get_library(key)
return f(self, self.library)
def find_deviceset(self):
"""Find the :class:`Deviceset` object refered to by the :code:`deviceset` attribute of this object. This is like
:meth:`get_deviceset`, except it returns the :class:`Deviceset` object instead of its name.
:returns: The object
:rtype: :class:`Deviceset`
"""
f = lambda efp, key: efp.find_library().get_deviceset(key)
return f(self, self.deviceset)
def find_device(self):
"""Find the :class:`Device` object refered to by the :code:`device` attribute of this object. This is like
:meth:`get_device`, except it returns the :class:`Device` object instead of its name.
:returns: The object
:rtype: :class:`Device`
"""
f = lambda efp, key: efp.find_deviceset().get_device(key)
return f(self, self.device)
def find_technology(self):
"""Find the :class:`Technology` object refered to by the :code:`technology` attribute of this object. This is like
:meth:`get_technology`, except it returns the :class:`Technology` object instead of its name.
:returns: The object
:rtype: :class:`Technology`
"""
f = lambda efp, key: efp.find_device().get_technology(key)
return f(self, self.technology)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
def add_attribute(self, s):
""" Add a :class:`Attribute` to the :code:`attributes` of this :class:`Part`.
:param s: The :class:`Attribute` to add.
:rtype: :code:`self`
"""
self.attributes[s.name] = s
s.parent = self
return self
def get_nth_attribute(self, n):
""" get then nth :class:`Attribute` object from the :code:`attributes` of this :class:`Part`.
:param n: Index of the item to return.
:rtype: :class:`Attribute` object
"""
return self.attributes.values()[n]
def get_attribute(self, key):
""" Lookup and return a :class:`Attribute` from the :code:`attributes` of this :class:`Part`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Attribute` objects.
:rtype: A :class:`Attribute` object or :code:`None`, if there is no such item.
"""
return self.attributes.get(key)
def get_attributes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`attributes` map of :class:`Attribute` objects for this :class:`Part`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Attribute` objects
:rtype: List of :class:`Attribute` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.attributes.values()
def clear_attributes(self):
"""
Remove all the :class:`Attribute` objects from the :code:`attributes` of this :class:`Part`.
:rtype: :code:`self`
"""
for efp in self.attributes.values():
efp.parent = None
self.attributes = {}
return self
def remove_attribute(self, efp):
"""
Remove a :class:`Attribute` from the :code:`attributes` of this :class:`Part`.
:param efp: The :class:`Attribute` object to remove.
:rtype: :code:`self`
"""
del self.attributes[efp.name]
efp.parent = None
return self
def add_variant(self, s):
""" Add a :class:`Variant` to the :code:`variants` of this :class:`Part`.
:param s: The :class:`Variant` to add.
:rtype: :code:`self`
"""
self.variants[s.name] = s
s.parent = self
return self
def get_nth_variant(self, n):
""" get then nth :class:`Variant` object from the :code:`variants` of this :class:`Part`.
:param n: Index of the item to return.
:rtype: :class:`Variant` object
"""
return self.variants.values()[n]
def get_variant(self, key):
""" Lookup and return a :class:`Variant` from the :code:`variants` of this :class:`Part`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Variant` objects.
:rtype: A :class:`Variant` object or :code:`None`, if there is no such item.
"""
return self.variants.get(key)
def get_variants(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`variants` map of :class:`Variant` objects for this :class:`Part`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Variant` objects
:rtype: List of :class:`Variant` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.variants.values()
def clear_variants(self):
"""
Remove all the :class:`Variant` objects from the :code:`variants` of this :class:`Part`.
:rtype: :code:`self`
"""
for efp in self.variants.values():
efp.parent = None
self.variants = {}
return self
def remove_variant(self, efp):
"""
Remove a :class:`Variant` from the :code:`variants` of this :class:`Part`.
:param efp: The :class:`Variant` object to remove.
:rtype: :code:`self`
"""
del self.variants[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.attributes.values()
r = r + self.variants.values()
return r
def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_attribute(efp)
except:
pass
try:
self.remove_variant(efp)
except:
pass
def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["part"] = Base_Part
[docs]class Grid(EagleFilePart):
"""
Class representing the contents of a <grid> tag in Eagle files.
Attributes:
* :code:`distance`
* :code:`unitdist`
* :code:`unit`
* :code:`style`
* :code:`multiple`
* :code:`display`
* :code:`altdistance`
* :code:`altunitdist`
* :code:`altunit`
"""
def __init__(self):
"""
Construct an empty :class:`Grid` object.
"""
EagleFilePart.__init__(self)
self.distance=None
self.unitdist=None
self.unit=None
self.style=None
self.multiple=None
self.display=None
self.altdistance=None
self.altunitdist=None
self.altunit=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Grid` from a :code:`grid` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Grid`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Grid` from a :code:`grid` element. This is useful if you have a subclass of :class:`Grid` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Grid`
"""
if root.tag != "grid":
raise EagleFormatError("Tried to create grid from " + root.tag)
self.distance=parseByType(parent, "float", root.get("distance"))
self.unitdist=parseByType(parent, "str", root.get("unitdist"))
self.unit=parseByType(parent, "str", root.get("unit"))
self.style=parseByType(parent, "str", root.get("style"))
self.multiple=parseByType(parent, "int", root.get("multiple"))
self.display=parseByType(parent, "bool", root.get("display"))
self.altdistance=parseByType(parent, "float", root.get("altdistance"))
self.altunitdist=parseByType(parent, "str", root.get("altunitdist"))
self.altunit=parseByType(parent, "str", root.get("altunit"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.distance)
r = r + str(self.unitdist)
r = r + str(self.unit)
r = r + str(self.style)
r = r + str(self.multiple)
r = r + str(self.display)
r = r + str(self.altdistance)
r = r + str(self.altunitdist)
r = r + str(self.altunit)
return r
[docs] def get_et(self):
"""
Generate a <grid> element tree for a :class:`Grid`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("grid")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.distance)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("distance", v)
## Unparse the values.
v = unparseByType(self, "str", self.unitdist)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("unitdist", v)
## Unparse the values.
v = unparseByType(self, "str", self.unit)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("unit", v)
## Unparse the values.
v = unparseByType(self, "str", self.style)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("style", v)
## Unparse the values.
v = unparseByType(self, "int", self.multiple)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("multiple", v)
## Unparse the values.
v = unparseByType(self, "bool", self.display)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("display", v)
## Unparse the values.
v = unparseByType(self, "float", self.altdistance)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("altdistance", v)
## Unparse the values.
v = unparseByType(self, "str", self.altunitdist)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("altunitdist", v)
## Unparse the values.
v = unparseByType(self, "str", self.altunit)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("altunit", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Grid`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Grid`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Grid_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Grid_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_distance(self):
""" Return the value of :code:`distance` for this :class:`Grid`. This corresponds to the :code:`distance` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`float`
"""
return self.distance
[docs] def set_distance(self,v):
""" Set the value of :code:`distance` for this :class:`Grid`. This corresponds to the :code:`distance` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.distance = v
return self
[docs] def with_distance(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`distance`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`distance` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_distance()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.distance == v else None
elif callable(v):
return self if v(self.distance) else None
[docs] def get_unitdist(self):
""" Return the value of :code:`unitdist` for this :class:`Grid`. This corresponds to the :code:`unitdist` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`str`
"""
return self.unitdist
[docs] def set_unitdist(self,v):
""" Set the value of :code:`unitdist` for this :class:`Grid`. This corresponds to the :code:`unitdist` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.unitdist = v
return self
[docs] def with_unitdist(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`unitdist`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`unitdist` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_unitdist()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.unitdist == v else None
elif callable(v):
return self if v(self.unitdist) else None
[docs] def get_unit(self):
""" Return the value of :code:`unit` for this :class:`Grid`. This corresponds to the :code:`unit` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`str`
"""
return self.unit
[docs] def set_unit(self,v):
""" Set the value of :code:`unit` for this :class:`Grid`. This corresponds to the :code:`unit` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.unit = v
return self
[docs] def with_unit(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`unit`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`unit` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_unit()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.unit == v else None
elif callable(v):
return self if v(self.unit) else None
[docs] def get_style(self):
""" Return the value of :code:`style` for this :class:`Grid`. This corresponds to the :code:`style` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`str`
"""
return self.style
[docs] def set_style(self,v):
""" Set the value of :code:`style` for this :class:`Grid`. This corresponds to the :code:`style` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.style = v
return self
[docs] def with_style(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`style`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`style` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_style()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.style == v else None
elif callable(v):
return self if v(self.style) else None
[docs] def get_multiple(self):
""" Return the value of :code:`multiple` for this :class:`Grid`. This corresponds to the :code:`multiple` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`int`
"""
return self.multiple
[docs] def set_multiple(self,v):
""" Set the value of :code:`multiple` for this :class:`Grid`. This corresponds to the :code:`multiple` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.multiple = v
return self
[docs] def with_multiple(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`multiple`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`multiple` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_multiple()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.multiple == v else None
elif callable(v):
return self if v(self.multiple) else None
[docs] def get_display(self):
""" Return the value of :code:`display` for this :class:`Grid`. This corresponds to the :code:`display` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.display
[docs] def set_display(self,v):
""" Set the value of :code:`display` for this :class:`Grid`. This corresponds to the :code:`display` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.display = v
return self
[docs] def with_display(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`display`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`display` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_display()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.display == v else None
elif callable(v):
return self if v(self.display) else None
[docs] def get_altdistance(self):
""" Return the value of :code:`altdistance` for this :class:`Grid`. This corresponds to the :code:`altdistance` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`float`
"""
return self.altdistance
[docs] def set_altdistance(self,v):
""" Set the value of :code:`altdistance` for this :class:`Grid`. This corresponds to the :code:`altdistance` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.altdistance = v
return self
[docs] def with_altdistance(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`altdistance`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`altdistance` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_altdistance()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.altdistance == v else None
elif callable(v):
return self if v(self.altdistance) else None
[docs] def get_altunitdist(self):
""" Return the value of :code:`altunitdist` for this :class:`Grid`. This corresponds to the :code:`altunitdist` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`str`
"""
return self.altunitdist
[docs] def set_altunitdist(self,v):
""" Set the value of :code:`altunitdist` for this :class:`Grid`. This corresponds to the :code:`altunitdist` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.altunitdist = v
return self
[docs] def with_altunitdist(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`altunitdist`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`altunitdist` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_altunitdist()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.altunitdist == v else None
elif callable(v):
return self if v(self.altunitdist) else None
[docs] def get_altunit(self):
""" Return the value of :code:`altunit` for this :class:`Grid`. This corresponds to the :code:`altunit` attribute of a :code:`<grid>` in an Eagle file.
:rtype: :code:`str`
"""
return self.altunit
[docs] def set_altunit(self,v):
""" Set the value of :code:`altunit` for this :class:`Grid`. This corresponds to the :code:`altunit` attribute of a :code:`<grid>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.altunit = v
return self
[docs] def with_altunit(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`altunit`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`altunit` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_altunit()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.altunit == v else None
elif callable(v):
return self if v(self.altunit) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["grid"] = Grid
[docs]class Library(EagleFilePart):
"""
Class representing the contents of a <library> tag in Eagle files.
Attributes:
* :code:`name`
Collections:
* :code:`description`: Singleton :class:`Description` object.
* :code:`package`: Map of :class:`Package` objects indexed by their :code:`name`.
* :code:`symbol`: Map of :class:`Symbol` objects indexed by their :code:`name`.
* :code:`deviceset`: Map of :class:`Deviceset` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Library` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.packages={}
self.symbols={}
self.devicesets={}
self.description=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Library` from a :code:`library` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Library`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Library` from a :code:`library` element. This is useful if you have a subclass of :class:`Library` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Library`
"""
if root.tag != "library":
raise EagleFormatError("Tried to create library from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./packages/package"):
self.add_package(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./symbols/symbol"):
self.add_symbol(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./devicesets/deviceset"):
self.add_deviceset(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
x = root.xpath("./description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
return r
[docs] def get_et(self):
"""
Generate a <library> element tree for a :class:`Library`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("library")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./packages/package")
## add a map.
if len(self.packages) is not 0:
target = smartAddSubTags(r, "./packages/package")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.packages.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./symbols/symbol")
## add a map.
if len(self.symbols) is not 0:
target = smartAddSubTags(r, "./symbols/symbol")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.symbols.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./devicesets/deviceset")
## add a map.
if len(self.devicesets) is not 0:
target = smartAddSubTags(r, "./devicesets/deviceset")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.devicesets.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Library`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Library`
"""
n = copy.copy(self)
n.packages = {}
for x in self.packages.values():
n.add_package(x.clone())
n.symbols = {}
for x in self.symbols.values():
n.add_symbol(x.clone())
n.devicesets = {}
for x in self.devicesets.values():
n.add_deviceset(x.clone())
if n.description is not None:
n.description = self.description.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Library_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Library_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Library`. This corresponds to the :code:`name` attribute of a :code:`<library>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Library`. This corresponds to the :code:`name` attribute of a :code:`<library>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_package(self, s):
""" Add a :class:`Package` to the :code:`packages` of this :class:`Library`.
:param s: The :class:`Package` to add.
:rtype: :code:`self`
"""
self.packages[s.name] = s
s.parent = self
return self
[docs] def get_nth_package(self, n):
""" get then nth :class:`Package` object from the :code:`packages` of this :class:`Library`.
:param n: Index of the item to return.
:rtype: :class:`Package` object
"""
return self.packages.values()[n]
[docs] def get_package(self, key):
""" Lookup and return a :class:`Package` from the :code:`packages` of this :class:`Library`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Package` objects.
:rtype: A :class:`Package` object or :code:`None`, if there is no such item.
"""
return self.packages.get(key)
[docs] def get_packages(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`packages` map of :class:`Package` objects for this :class:`Library`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Package` objects
:rtype: List of :class:`Package` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.packages.values()
[docs] def clear_packages(self):
"""
Remove all the :class:`Package` objects from the :code:`packages` of this :class:`Library`.
:rtype: :code:`self`
"""
for efp in self.packages.values():
efp.parent = None
self.packages = {}
return self
[docs] def remove_package(self, efp):
"""
Remove a :class:`Package` from the :code:`packages` of this :class:`Library`.
:param efp: The :class:`Package` object to remove.
:rtype: :code:`self`
"""
del self.packages[efp.name]
efp.parent = None
return self
[docs] def add_symbol(self, s):
""" Add a :class:`Symbol` to the :code:`symbols` of this :class:`Library`.
:param s: The :class:`Symbol` to add.
:rtype: :code:`self`
"""
self.symbols[s.name] = s
s.parent = self
return self
[docs] def get_nth_symbol(self, n):
""" get then nth :class:`Symbol` object from the :code:`symbols` of this :class:`Library`.
:param n: Index of the item to return.
:rtype: :class:`Symbol` object
"""
return self.symbols.values()[n]
[docs] def get_symbol(self, key):
""" Lookup and return a :class:`Symbol` from the :code:`symbols` of this :class:`Library`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Symbol` objects.
:rtype: A :class:`Symbol` object or :code:`None`, if there is no such item.
"""
return self.symbols.get(key)
[docs] def get_symbols(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`symbols` map of :class:`Symbol` objects for this :class:`Library`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Symbol` objects
:rtype: List of :class:`Symbol` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.symbols.values()
[docs] def clear_symbols(self):
"""
Remove all the :class:`Symbol` objects from the :code:`symbols` of this :class:`Library`.
:rtype: :code:`self`
"""
for efp in self.symbols.values():
efp.parent = None
self.symbols = {}
return self
[docs] def remove_symbol(self, efp):
"""
Remove a :class:`Symbol` from the :code:`symbols` of this :class:`Library`.
:param efp: The :class:`Symbol` object to remove.
:rtype: :code:`self`
"""
del self.symbols[efp.name]
efp.parent = None
return self
[docs] def add_deviceset(self, s):
""" Add a :class:`Deviceset` to the :code:`devicesets` of this :class:`Library`.
:param s: The :class:`Deviceset` to add.
:rtype: :code:`self`
"""
self.devicesets[s.name] = s
s.parent = self
return self
[docs] def get_nth_deviceset(self, n):
""" get then nth :class:`Deviceset` object from the :code:`devicesets` of this :class:`Library`.
:param n: Index of the item to return.
:rtype: :class:`Deviceset` object
"""
return self.devicesets.values()[n]
[docs] def get_deviceset(self, key):
""" Lookup and return a :class:`Deviceset` from the :code:`devicesets` of this :class:`Library`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Deviceset` objects.
:rtype: A :class:`Deviceset` object or :code:`None`, if there is no such item.
"""
return self.devicesets.get(key)
[docs] def get_devicesets(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`devicesets` map of :class:`Deviceset` objects for this :class:`Library`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Deviceset` objects
:rtype: List of :class:`Deviceset` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.devicesets.values()
[docs] def clear_devicesets(self):
"""
Remove all the :class:`Deviceset` objects from the :code:`devicesets` of this :class:`Library`.
:rtype: :code:`self`
"""
for efp in self.devicesets.values():
efp.parent = None
self.devicesets = {}
return self
[docs] def remove_deviceset(self, efp):
"""
Remove a :class:`Deviceset` from the :code:`devicesets` of this :class:`Library`.
:param efp: The :class:`Deviceset` object to remove.
:rtype: :code:`self`
"""
del self.devicesets[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`Library`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`Library`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.packages.values()
r = r + self.symbols.values()
r = r + self.devicesets.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_package(efp)
except:
pass
try:
self.remove_symbol(efp)
except:
pass
try:
self.remove_deviceset(efp)
except:
pass
if self.get_description == efp:
self.set_description(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["library"] = Library
[docs]class Pinref(EagleFilePart):
"""
Class representing the contents of a <pinref> tag in Eagle files.
Attributes:
* :code:`part`
* :code:`gate`
* :code:`pin`
"""
def __init__(self):
"""
Construct an empty :class:`Pinref` object.
"""
EagleFilePart.__init__(self)
self.part=None
self.gate=None
self.pin=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Pinref` from a :code:`pinref` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Pinref`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Pinref` from a :code:`pinref` element. This is useful if you have a subclass of :class:`Pinref` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Pinref`
"""
if root.tag != "pinref":
raise EagleFormatError("Tried to create pinref from " + root.tag)
self.part=parseByType(parent, "str", root.get("part"))
self.gate=parseByType(parent, "str", root.get("gate"))
self.pin=parseByType(parent, "str", root.get("pin"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.part)
r = r + str(self.gate)
r = r + str(self.pin)
return r
[docs] def get_et(self):
"""
Generate a <pinref> element tree for a :class:`Pinref`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("pinref")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.part)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("part", v)
else:
r.set("part", "")
## Unparse the values.
v = unparseByType(self, "str", self.gate)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("gate", v)
else:
r.set("gate", "")
## Unparse the values.
v = unparseByType(self, "str", self.pin)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("pin", v)
else:
r.set("pin", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Pinref`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Pinref`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Pinref_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Pinref_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_part(self):
""" Return the value of :code:`part` for this :class:`Pinref`. This corresponds to the :code:`part` attribute of a :code:`<pinref>` in an Eagle file.
:rtype: :code:`str`
"""
return self.part
[docs] def set_part(self,v):
""" Set the value of :code:`part` for this :class:`Pinref`. This corresponds to the :code:`part` attribute of a :code:`<pinref>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.part = v
return self
[docs] def with_part(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`part`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`part` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_part()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.part == v else None
elif callable(v):
return self if v(self.part) else None
[docs] def get_gate(self):
""" Return the value of :code:`gate` for this :class:`Pinref`. This corresponds to the :code:`gate` attribute of a :code:`<pinref>` in an Eagle file.
:rtype: :code:`str`
"""
return self.gate
[docs] def set_gate(self,v):
""" Set the value of :code:`gate` for this :class:`Pinref`. This corresponds to the :code:`gate` attribute of a :code:`<pinref>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.gate = v
return self
[docs] def with_gate(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`gate`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`gate` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_gate()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.gate == v else None
elif callable(v):
return self if v(self.gate) else None
[docs] def get_pin(self):
""" Return the value of :code:`pin` for this :class:`Pinref`. This corresponds to the :code:`pin` attribute of a :code:`<pinref>` in an Eagle file.
:rtype: :code:`str`
"""
return self.pin
[docs] def set_pin(self,v):
""" Set the value of :code:`pin` for this :class:`Pinref`. This corresponds to the :code:`pin` attribute of a :code:`<pinref>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.pin = v
return self
[docs] def with_pin(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`pin`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`pin` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_pin()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.pin == v else None
elif callable(v):
return self if v(self.pin) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_part(self):
"""Find the :class:`Part` object refered to by the :code:`part` attribute of this object. This is like
:meth:`get_part`, except it returns the :class:`Part` object instead of its name.
:returns: The object
:rtype: :class:`Part`
"""
f = lambda efp, key: NotImplemented('Lookup of part from pinref not implemented.')
return f(self, self.part)
[docs] def find_gate(self):
"""Find the :class:`Gate` object refered to by the :code:`gate` attribute of this object. This is like
:meth:`get_gate`, except it returns the :class:`Gate` object instead of its name.
:returns: The object
:rtype: :class:`Gate`
"""
f = lambda efp, key: NotImplemented('Lookup of gate from pinref not implemented.')
return f(self, self.gate)
[docs] def find_pin(self):
"""Find the :class:`Pin` object refered to by the :code:`pin` attribute of this object. This is like
:meth:`get_pin`, except it returns the :class:`Pin` object instead of its name.
:returns: The object
:rtype: :class:`Pin`
"""
f = lambda efp, key: NotImplemented('Lookup of pin from pinref not implemented.')
return f(self, self.pin)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["pinref"] = Pinref
[docs]class Device(EagleFilePart):
"""
Class representing the contents of a <device> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`package`
Collections:
* :code:`connect`: List of :class:`Connect` objects.
* :code:`technology`: Map of :class:`Technology` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Device` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.package=None
self.connects=[]
self.technologies={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Device` from a :code:`device` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Device`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Device` from a :code:`device` element. This is useful if you have a subclass of :class:`Device` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Device`
"""
if root.tag != "device":
raise EagleFormatError("Tried to create device from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.package=parseByType(parent, "str", root.get("package"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./technologies/technology"):
self.add_technology(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./connects/connect"):
self.add_connect(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.package)
return r
[docs] def get_et(self):
"""
Generate a <device> element tree for a :class:`Device`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("device")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
## Unparse the values.
v = unparseByType(self, "str", self.package)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("package", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.connects) is not 0:
target = smartAddSubTags(r, "./connects/connect")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.connects,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.technologies) is not 0:
target = smartAddSubTags(r, "./technologies/technology")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.technologies.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Device`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Device`
"""
n = copy.copy(self)
n.technologies = {}
for x in self.technologies.values():
n.add_technology(x.clone())
n.connects = []
for x in self.connects:
n.add_connect(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Device_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Device_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Device`. This corresponds to the :code:`name` attribute of a :code:`<device>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Device`. This corresponds to the :code:`name` attribute of a :code:`<device>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_package(self):
""" Return the value of :code:`package` for this :class:`Device`. This corresponds to the :code:`package` attribute of a :code:`<device>` in an Eagle file.
:rtype: :code:`str`
"""
return self.package
[docs] def set_package(self,v):
""" Set the value of :code:`package` for this :class:`Device`. This corresponds to the :code:`package` attribute of a :code:`<device>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.package = v
return self
[docs] def with_package(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`package`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`package` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_package()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.package == v else None
elif callable(v):
return self if v(self.package) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_package(self):
"""Find the :class:`Package` object refered to by the :code:`package` attribute of this object. This is like
:meth:`get_package`, except it returns the :class:`Package` object instead of its name.
:returns: The object
:rtype: :class:`Package`
"""
f = lambda efp, key: efp.get_parent().get_parent().get_package(key)
return f(self, self.package)
### Adder/getter/lookup for lists
[docs] def add_connect(self, s):
""" Add a :class:`Connect` to the :code:`connects` of this :class:`Device`.
:param s: The :class:`Connect` to add.
:rtype: :code:`self`
"""
self.connects.append(s)
s.parent = self
return self
[docs] def get_nth_connect(self, n):
""" get then nth :class:`Connect` object from the :code:`connects` of this :class:`Device`.
:param n: Index of the item to return.
:rtype: :class:`Connect` object
"""
return self.connects[n]
[docs] def get_connects(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`connects` list of :class:`Connect` objects for this :class:`Device`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Connect` objects
:rtype: List of :class:`Connect` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.connects
[docs] def clear_connects(self):
"""
Remove all the :class:`Connect` objects from the :code:`connects` of this :class:`Device`.
:rtype: :code:`self`
"""
for efp in self.connects:
efp.parent = None
self.connects = []
return self
[docs] def remove_connect(self, efp):
"""
Remove a :class:`Connect` from the :code:`connects` of this :class:`Device`.
:param efp: The :class:`Connect` object to remove.
:rtype: :code:`self`
"""
self.connects = [x for x in self.connects if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_technology(self, s):
""" Add a :class:`Technology` to the :code:`technologies` of this :class:`Device`.
:param s: The :class:`Technology` to add.
:rtype: :code:`self`
"""
self.technologies[s.name] = s
s.parent = self
return self
[docs] def get_nth_technology(self, n):
""" get then nth :class:`Technology` object from the :code:`technologies` of this :class:`Device`.
:param n: Index of the item to return.
:rtype: :class:`Technology` object
"""
return self.technologies.values()[n]
[docs] def get_technology(self, key):
""" Lookup and return a :class:`Technology` from the :code:`technologies` of this :class:`Device`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Technology` objects.
:rtype: A :class:`Technology` object or :code:`None`, if there is no such item.
"""
return self.technologies.get(key)
[docs] def get_technologies(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`technologies` map of :class:`Technology` objects for this :class:`Device`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Technology` objects
:rtype: List of :class:`Technology` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.technologies.values()
[docs] def clear_technologies(self):
"""
Remove all the :class:`Technology` objects from the :code:`technologies` of this :class:`Device`.
:rtype: :code:`self`
"""
for efp in self.technologies.values():
efp.parent = None
self.technologies = {}
return self
[docs] def remove_technology(self, efp):
"""
Remove a :class:`Technology` from the :code:`technologies` of this :class:`Device`.
:param efp: The :class:`Technology` object to remove.
:rtype: :code:`self`
"""
del self.technologies[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.connects
r = r + self.technologies.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_technology(efp)
except:
pass
try:
self.remove_connect(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["device"] = Device
[docs]class Hole(EagleFilePart):
"""
Class representing the contents of a <hole> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
* :code:`drill`
"""
def __init__(self):
"""
Construct an empty :class:`Hole` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
self.drill=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Hole` from a :code:`hole` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Hole`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Hole` from a :code:`hole` element. This is useful if you have a subclass of :class:`Hole` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Hole`
"""
if root.tag != "hole":
raise EagleFormatError("Tried to create hole from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.drill=parseByType(parent, "float", root.get("drill"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.drill)
return r
[docs] def get_et(self):
"""
Generate a <hole> element tree for a :class:`Hole`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("hole")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.drill)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("drill", v)
else:
r.set("drill", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Hole`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Hole`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Hole_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Hole_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Hole`. This corresponds to the :code:`x` attribute of a :code:`<hole>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Hole`. This corresponds to the :code:`x` attribute of a :code:`<hole>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Hole`. This corresponds to the :code:`y` attribute of a :code:`<hole>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Hole`. This corresponds to the :code:`y` attribute of a :code:`<hole>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_drill(self):
""" Return the value of :code:`drill` for this :class:`Hole`. This corresponds to the :code:`drill` attribute of a :code:`<hole>` in an Eagle file.
:rtype: :code:`float`
"""
return self.drill
[docs] def set_drill(self,v):
""" Set the value of :code:`drill` for this :class:`Hole`. This corresponds to the :code:`drill` attribute of a :code:`<hole>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.drill = v
return self
[docs] def with_drill(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`drill`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`drill` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_drill()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.drill == v else None
elif callable(v):
return self if v(self.drill) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["hole"] = Hole
[docs]class Segment(EagleFilePart):
"""
Class representing the contents of a <segment> tag in Eagle files.
Attributes:
Collections:
* :code:`pinref`: List of :class:`Pinref` objects.
* :code:`portref`: List of :class:`Portref` objects.
* :code:`wire`: List of :class:`Wire` objects.
* :code:`junction`: List of :class:`Junction` objects.
* :code:`label`: List of :class:`Label` objects.
"""
def __init__(self):
"""
Construct an empty :class:`Segment` object.
"""
EagleFilePart.__init__(self)
self.pinrefs=[]
self.portrefs=[]
self.wires=[]
self.junctions=[]
self.labels=[]
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Segment` from a :code:`segment` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Segment`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Segment` from a :code:`segment` element. This is useful if you have a subclass of :class:`Segment` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Segment`
"""
if root.tag != "segment":
raise EagleFormatError("Tried to create segment from " + root.tag)
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
for c in root.xpath("./pinref"):
self.add_pinref(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./portref"):
self.add_portref(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./wire"):
self.add_wire(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./junction"):
self.add_junction(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./label"):
self.add_label(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
return r
[docs] def get_et(self):
"""
Generate a <segment> element tree for a :class:`Segment`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("segment")
### Set the tag attributes
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.pinrefs) is not 0:
target = smartAddSubTags(r, "./pinref")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.pinrefs,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.portrefs) is not 0:
target = smartAddSubTags(r, "./portref")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.portrefs,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.wires) is not 0:
target = smartAddSubTags(r, "./wire")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.wires,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.junctions) is not 0:
target = smartAddSubTags(r, "./junction")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.junctions,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.labels) is not 0:
target = smartAddSubTags(r, "./label")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.labels,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Segment`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Segment`
"""
n = copy.copy(self)
n.pinrefs = []
for x in self.pinrefs:
n.add_pinref(x.clone())
n.portrefs = []
for x in self.portrefs:
n.add_portref(x.clone())
n.wires = []
for x in self.wires:
n.add_wire(x.clone())
n.junctions = []
for x in self.junctions:
n.add_junction(x.clone())
n.labels = []
for x in self.labels:
n.add_label(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Segment_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Segment_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_pinref(self, s):
""" Add a :class:`Pinref` to the :code:`pinrefs` of this :class:`Segment`.
:param s: The :class:`Pinref` to add.
:rtype: :code:`self`
"""
self.pinrefs.append(s)
s.parent = self
return self
[docs] def get_nth_pinref(self, n):
""" get then nth :class:`Pinref` object from the :code:`pinrefs` of this :class:`Segment`.
:param n: Index of the item to return.
:rtype: :class:`Pinref` object
"""
return self.pinrefs[n]
[docs] def get_pinrefs(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`pinrefs` list of :class:`Pinref` objects for this :class:`Segment`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Pinref` objects
:rtype: List of :class:`Pinref` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.pinrefs
[docs] def clear_pinrefs(self):
"""
Remove all the :class:`Pinref` objects from the :code:`pinrefs` of this :class:`Segment`.
:rtype: :code:`self`
"""
for efp in self.pinrefs:
efp.parent = None
self.pinrefs = []
return self
[docs] def remove_pinref(self, efp):
"""
Remove a :class:`Pinref` from the :code:`pinrefs` of this :class:`Segment`.
:param efp: The :class:`Pinref` object to remove.
:rtype: :code:`self`
"""
self.pinrefs = [x for x in self.pinrefs if x != efp]
efp.parent = None
return self
[docs] def add_portref(self, s):
""" Add a :class:`Portref` to the :code:`portrefs` of this :class:`Segment`.
:param s: The :class:`Portref` to add.
:rtype: :code:`self`
"""
self.portrefs.append(s)
s.parent = self
return self
[docs] def get_nth_portref(self, n):
""" get then nth :class:`Portref` object from the :code:`portrefs` of this :class:`Segment`.
:param n: Index of the item to return.
:rtype: :class:`Portref` object
"""
return self.portrefs[n]
[docs] def get_portrefs(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`portrefs` list of :class:`Portref` objects for this :class:`Segment`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Portref` objects
:rtype: List of :class:`Portref` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.portrefs
[docs] def clear_portrefs(self):
"""
Remove all the :class:`Portref` objects from the :code:`portrefs` of this :class:`Segment`.
:rtype: :code:`self`
"""
for efp in self.portrefs:
efp.parent = None
self.portrefs = []
return self
[docs] def remove_portref(self, efp):
"""
Remove a :class:`Portref` from the :code:`portrefs` of this :class:`Segment`.
:param efp: The :class:`Portref` object to remove.
:rtype: :code:`self`
"""
self.portrefs = [x for x in self.portrefs if x != efp]
efp.parent = None
return self
[docs] def add_wire(self, s):
""" Add a :class:`Wire` to the :code:`wires` of this :class:`Segment`.
:param s: The :class:`Wire` to add.
:rtype: :code:`self`
"""
self.wires.append(s)
s.parent = self
return self
[docs] def get_nth_wire(self, n):
""" get then nth :class:`Wire` object from the :code:`wires` of this :class:`Segment`.
:param n: Index of the item to return.
:rtype: :class:`Wire` object
"""
return self.wires[n]
[docs] def get_wires(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`wires` list of :class:`Wire` objects for this :class:`Segment`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Wire` objects
:rtype: List of :class:`Wire` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.wires
[docs] def clear_wires(self):
"""
Remove all the :class:`Wire` objects from the :code:`wires` of this :class:`Segment`.
:rtype: :code:`self`
"""
for efp in self.wires:
efp.parent = None
self.wires = []
return self
[docs] def remove_wire(self, efp):
"""
Remove a :class:`Wire` from the :code:`wires` of this :class:`Segment`.
:param efp: The :class:`Wire` object to remove.
:rtype: :code:`self`
"""
self.wires = [x for x in self.wires if x != efp]
efp.parent = None
return self
[docs] def add_junction(self, s):
""" Add a :class:`Junction` to the :code:`junctions` of this :class:`Segment`.
:param s: The :class:`Junction` to add.
:rtype: :code:`self`
"""
self.junctions.append(s)
s.parent = self
return self
[docs] def get_nth_junction(self, n):
""" get then nth :class:`Junction` object from the :code:`junctions` of this :class:`Segment`.
:param n: Index of the item to return.
:rtype: :class:`Junction` object
"""
return self.junctions[n]
[docs] def get_junctions(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`junctions` list of :class:`Junction` objects for this :class:`Segment`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Junction` objects
:rtype: List of :class:`Junction` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.junctions
[docs] def clear_junctions(self):
"""
Remove all the :class:`Junction` objects from the :code:`junctions` of this :class:`Segment`.
:rtype: :code:`self`
"""
for efp in self.junctions:
efp.parent = None
self.junctions = []
return self
[docs] def remove_junction(self, efp):
"""
Remove a :class:`Junction` from the :code:`junctions` of this :class:`Segment`.
:param efp: The :class:`Junction` object to remove.
:rtype: :code:`self`
"""
self.junctions = [x for x in self.junctions if x != efp]
efp.parent = None
return self
[docs] def add_label(self, s):
""" Add a :class:`Label` to the :code:`labels` of this :class:`Segment`.
:param s: The :class:`Label` to add.
:rtype: :code:`self`
"""
self.labels.append(s)
s.parent = self
return self
[docs] def get_nth_label(self, n):
""" get then nth :class:`Label` object from the :code:`labels` of this :class:`Segment`.
:param n: Index of the item to return.
:rtype: :class:`Label` object
"""
return self.labels[n]
[docs] def get_labels(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`labels` list of :class:`Label` objects for this :class:`Segment`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Label` objects
:rtype: List of :class:`Label` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.labels
[docs] def clear_labels(self):
"""
Remove all the :class:`Label` objects from the :code:`labels` of this :class:`Segment`.
:rtype: :code:`self`
"""
for efp in self.labels:
efp.parent = None
self.labels = []
return self
[docs] def remove_label(self, efp):
"""
Remove a :class:`Label` from the :code:`labels` of this :class:`Segment`.
:param efp: The :class:`Label` object to remove.
:rtype: :code:`self`
"""
self.labels = [x for x in self.labels if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.pinrefs
r = r + self.portrefs
r = r + self.wires
r = r + self.junctions
r = r + self.labels
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_pinref(efp)
except:
pass
try:
self.remove_portref(efp)
except:
pass
try:
self.remove_wire(efp)
except:
pass
try:
self.remove_junction(efp)
except:
pass
try:
self.remove_label(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["segment"] = Segment
[docs]class Net(EagleFilePart):
"""
Class representing the contents of a <net> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`class`
Collections:
* :code:`segment`: List of :class:`Segment` objects.
"""
def __init__(self):
"""
Construct an empty :class:`Net` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.netclass=None
self.segments=[]
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Net` from a :code:`net` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Net`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Net` from a :code:`net` element. This is useful if you have a subclass of :class:`Net` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Net`
"""
if root.tag != "net":
raise EagleFormatError("Tried to create net from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.netclass=parseByType(parent, "str", root.get("class"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
for c in root.xpath("./segment"):
self.add_segment(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.netclass)
return r
[docs] def get_et(self):
"""
Generate a <net> element tree for a :class:`Net`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("net")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.netclass)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("class", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.segments) is not 0:
target = smartAddSubTags(r, "./segment")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.segments,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Net`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Net`
"""
n = copy.copy(self)
n.segments = []
for x in self.segments:
n.add_segment(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Net_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Net_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Net`. This corresponds to the :code:`name` attribute of a :code:`<net>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Net`. This corresponds to the :code:`name` attribute of a :code:`<net>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_class(self):
""" Return the value of :code:`netclass` for this :class:`Net`. This corresponds to the :code:`netclass` attribute of a :code:`<net>` in an Eagle file.
:rtype: :code:`str`
"""
return self.netclass
[docs] def set_class(self,v):
""" Set the value of :code:`netclass` for this :class:`Net`. This corresponds to the :code:`netclass` attribute of a :code:`<net>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.netclass = v
return self
[docs] def with_class(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`netclass`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`netclass` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_class()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.netclass == v else None
elif callable(v):
return self if v(self.netclass) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_segment(self, s):
""" Add a :class:`Segment` to the :code:`segments` of this :class:`Net`.
:param s: The :class:`Segment` to add.
:rtype: :code:`self`
"""
self.segments.append(s)
s.parent = self
return self
[docs] def get_nth_segment(self, n):
""" get then nth :class:`Segment` object from the :code:`segments` of this :class:`Net`.
:param n: Index of the item to return.
:rtype: :class:`Segment` object
"""
return self.segments[n]
[docs] def get_segments(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`segments` list of :class:`Segment` objects for this :class:`Net`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Segment` objects
:rtype: List of :class:`Segment` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.segments
[docs] def clear_segments(self):
"""
Remove all the :class:`Segment` objects from the :code:`segments` of this :class:`Net`.
:rtype: :code:`self`
"""
for efp in self.segments:
efp.parent = None
self.segments = []
return self
[docs] def remove_segment(self, efp):
"""
Remove a :class:`Segment` from the :code:`segments` of this :class:`Net`.
:param efp: The :class:`Segment` object to remove.
:rtype: :code:`self`
"""
self.segments = [x for x in self.segments if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.segments
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_segment(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["net"] = Net
EagleFile.class_map["contactref"] = Contactref
[docs]class Package(EagleFilePart):
"""
Class representing the contents of a <package> tag in Eagle files.
Attributes:
* :code:`name`
Collections:
* :code:`description`: Singleton :class:`Description` object.
* :code:`drawing_element`: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` and :class:`Frame` objects.
* :code:`pad`: Map of :class:`Pad` objects indexed by their :code:`name`.
* :code:`smd`: Map of :class:`Smd` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Package` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.drawing_elements=[]
self.pads={}
self.smds={}
self.description=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Package` from a :code:`package` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Package`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Package` from a :code:`package` element. This is useful if you have a subclass of :class:`Package` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Package`
"""
if root.tag != "package":
raise EagleFormatError("Tried to create package from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./pad"):
self.add_pad(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./smd"):
self.add_smd(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./polygon|./wire|./text|./dimension|./circle|./rectangle|./hole|./frame"):
self.add_drawing_element(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
return r
[docs] def get_et(self):
"""
Generate a <package> element tree for a :class:`Package`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("package")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.drawing_elements) is not 0:
target = smartAddSubTags(r, "./polygon|./wire|./text|./dimension|./circle|./rectangle|./hole|./frame")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.drawing_elements,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.pads) is not 0:
target = smartAddSubTags(r, "./pad")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.pads.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.smds) is not 0:
target = smartAddSubTags(r, "./smd")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.smds.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Package`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Package`
"""
n = copy.copy(self)
n.pads = {}
for x in self.pads.values():
n.add_pad(x.clone())
n.smds = {}
for x in self.smds.values():
n.add_smd(x.clone())
n.drawing_elements = []
for x in self.drawing_elements:
n.add_drawing_element(x.clone())
if n.description is not None:
n.description = self.description.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Package_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Package_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Package`. This corresponds to the :code:`name` attribute of a :code:`<package>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Package`. This corresponds to the :code:`name` attribute of a :code:`<package>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_drawing_element(self, s):
""" Add a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` to the :code:`drawing_elements` of this :class:`Package`.
:param s: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` to add.
:rtype: :code:`self`
"""
self.drawing_elements.append(s)
s.parent = self
return self
[docs] def get_nth_drawing_element(self, n):
""" get then nth :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` object from the :code:`drawing_elements` of this :class:`Package`.
:param n: Index of the item to return.
:rtype: :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` object
"""
return self.drawing_elements[n]
[docs] def get_drawing_elements(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`drawing_elements` list of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` objects for this :class:`Package`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` and :class:`Frame` objects
:rtype: List of :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` and :class:`Frame` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.drawing_elements
[docs] def clear_drawing_elements(self):
"""
Remove all the :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` and :class:`Frame` objects from the :code:`drawing_elements` of this :class:`Package`.
:rtype: :code:`self`
"""
for efp in self.drawing_elements:
efp.parent = None
self.drawing_elements = []
return self
[docs] def remove_drawing_element(self, efp):
"""
Remove a :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` from the :code:`drawing_elements` of this :class:`Package`.
:param efp: The :class:`Polygon`, :class:`Wire`, :class:`Text`, :class:`Dimension`, :class:`Circle`, :class:`Rectangle`, :class:`Hole` or :class:`Frame` object to remove.
:rtype: :code:`self`
"""
self.drawing_elements = [x for x in self.drawing_elements if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_pad(self, s):
""" Add a :class:`Pad` to the :code:`pads` of this :class:`Package`.
:param s: The :class:`Pad` to add.
:rtype: :code:`self`
"""
self.pads[s.name] = s
s.parent = self
return self
[docs] def get_nth_pad(self, n):
""" get then nth :class:`Pad` object from the :code:`pads` of this :class:`Package`.
:param n: Index of the item to return.
:rtype: :class:`Pad` object
"""
return self.pads.values()[n]
[docs] def get_pad(self, key):
""" Lookup and return a :class:`Pad` from the :code:`pads` of this :class:`Package`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Pad` objects.
:rtype: A :class:`Pad` object or :code:`None`, if there is no such item.
"""
return self.pads.get(key)
[docs] def get_pads(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`pads` map of :class:`Pad` objects for this :class:`Package`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Pad` objects
:rtype: List of :class:`Pad` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.pads.values()
[docs] def clear_pads(self):
"""
Remove all the :class:`Pad` objects from the :code:`pads` of this :class:`Package`.
:rtype: :code:`self`
"""
for efp in self.pads.values():
efp.parent = None
self.pads = {}
return self
[docs] def remove_pad(self, efp):
"""
Remove a :class:`Pad` from the :code:`pads` of this :class:`Package`.
:param efp: The :class:`Pad` object to remove.
:rtype: :code:`self`
"""
del self.pads[efp.name]
efp.parent = None
return self
[docs] def add_smd(self, s):
""" Add a :class:`Smd` to the :code:`smds` of this :class:`Package`.
:param s: The :class:`Smd` to add.
:rtype: :code:`self`
"""
self.smds[s.name] = s
s.parent = self
return self
[docs] def get_nth_smd(self, n):
""" get then nth :class:`Smd` object from the :code:`smds` of this :class:`Package`.
:param n: Index of the item to return.
:rtype: :class:`Smd` object
"""
return self.smds.values()[n]
[docs] def get_smd(self, key):
""" Lookup and return a :class:`Smd` from the :code:`smds` of this :class:`Package`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Smd` objects.
:rtype: A :class:`Smd` object or :code:`None`, if there is no such item.
"""
return self.smds.get(key)
[docs] def get_smds(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`smds` map of :class:`Smd` objects for this :class:`Package`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Smd` objects
:rtype: List of :class:`Smd` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.smds.values()
[docs] def clear_smds(self):
"""
Remove all the :class:`Smd` objects from the :code:`smds` of this :class:`Package`.
:rtype: :code:`self`
"""
for efp in self.smds.values():
efp.parent = None
self.smds = {}
return self
[docs] def remove_smd(self, efp):
"""
Remove a :class:`Smd` from the :code:`smds` of this :class:`Package`.
:param efp: The :class:`Smd` object to remove.
:rtype: :code:`self`
"""
del self.smds[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`Package`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`Package`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.drawing_elements
r = r + self.pads.values()
r = r + self.smds.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_pad(efp)
except:
pass
try:
self.remove_smd(efp)
except:
pass
try:
self.remove_drawing_element(efp)
except:
pass
if self.get_description == efp:
self.set_description(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["package"] = Package
[docs]class Designrules(EagleFilePart):
"""
Class representing the contents of a <designrules> tag in Eagle files.
Attributes:
* :code:`name`
Collections:
* :code:`description`: List of :class:`Description` objects.
* :code:`param`: Map of :class:`Param` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Designrules` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.description=[]
self.params={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Designrules` from a :code:`designrules` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Designrules`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Designrules` from a :code:`designrules` element. This is useful if you have a subclass of :class:`Designrules` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Designrules`
"""
if root.tag != "designrules":
raise EagleFormatError("Tried to create designrules from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./param"):
self.add_param(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./description"):
self.add_description(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
return r
[docs] def get_et(self):
"""
Generate a <designrules> element tree for a :class:`Designrules`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("designrules")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./description")
## add a list.
if len(self.description) is not 0:
target = smartAddSubTags(r, "./description")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.description,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.params) is not 0:
target = smartAddSubTags(r, "./param")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.params.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Designrules`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Designrules`
"""
n = copy.copy(self)
n.params = {}
for x in self.params.values():
n.add_param(x.clone())
n.description = []
for x in self.description:
n.add_description(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Designrules_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Designrules_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Designrules`. This corresponds to the :code:`name` attribute of a :code:`<designrules>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Designrules`. This corresponds to the :code:`name` attribute of a :code:`<designrules>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_description(self, s):
""" Add a :class:`Description` to the :code:`description` of this :class:`Designrules`.
:param s: The :class:`Description` to add.
:rtype: :code:`self`
"""
self.description.append(s)
s.parent = self
return self
[docs] def get_nth_description(self, n):
""" get then nth :class:`Description` object from the :code:`description` of this :class:`Designrules`.
:param n: Index of the item to return.
:rtype: :class:`Description` object
"""
return self.description[n]
[docs] def get_description(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`description` list of :class:`Description` objects for this :class:`Designrules`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Description` objects
:rtype: List of :class:`Description` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.description
[docs] def clear_description(self):
"""
Remove all the :class:`Description` objects from the :code:`description` of this :class:`Designrules`.
:rtype: :code:`self`
"""
for efp in self.description:
efp.parent = None
self.description = []
return self
[docs] def remove_description(self, efp):
"""
Remove a :class:`Description` from the :code:`description` of this :class:`Designrules`.
:param efp: The :class:`Description` object to remove.
:rtype: :code:`self`
"""
self.description = [x for x in self.description if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_param(self, s):
""" Add a :class:`Param` to the :code:`params` of this :class:`Designrules`.
:param s: The :class:`Param` to add.
:rtype: :code:`self`
"""
self.params[s.name] = s
s.parent = self
return self
[docs] def get_nth_param(self, n):
""" get then nth :class:`Param` object from the :code:`params` of this :class:`Designrules`.
:param n: Index of the item to return.
:rtype: :class:`Param` object
"""
return self.params.values()[n]
[docs] def get_param(self, key):
""" Lookup and return a :class:`Param` from the :code:`params` of this :class:`Designrules`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Param` objects.
:rtype: A :class:`Param` object or :code:`None`, if there is no such item.
"""
return self.params.get(key)
[docs] def get_params(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`params` map of :class:`Param` objects for this :class:`Designrules`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Param` objects
:rtype: List of :class:`Param` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.params.values()
[docs] def clear_params(self):
"""
Remove all the :class:`Param` objects from the :code:`params` of this :class:`Designrules`.
:rtype: :code:`self`
"""
for efp in self.params.values():
efp.parent = None
self.params = {}
return self
[docs] def remove_param(self, efp):
"""
Remove a :class:`Param` from the :code:`params` of this :class:`Designrules`.
:param efp: The :class:`Param` object to remove.
:rtype: :code:`self`
"""
del self.params[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.description
r = r + self.params.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_param(efp)
except:
pass
try:
self.remove_description(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["designrules"] = Designrules
[docs]class Signal(EagleFilePart):
"""
Class representing the contents of a <signal> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`class`
* :code:`airwireshidden`
Collections:
* :code:`contactref`: List of :class:`Contactref` objects.
* :code:`polygon`: List of :class:`Polygon` objects.
* :code:`wire`: List of :class:`Wire` objects.
* :code:`via`: List of :class:`Via` objects.
"""
def __init__(self):
"""
Construct an empty :class:`Signal` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.netclass=None
self.airwireshidden=None
self.contactrefs=[]
self.polygons=[]
self.wires=[]
self.vias=[]
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Signal` from a :code:`signal` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Signal`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Signal` from a :code:`signal` element. This is useful if you have a subclass of :class:`Signal` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Signal`
"""
if root.tag != "signal":
raise EagleFormatError("Tried to create signal from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.netclass=parseByType(parent, "str", root.get("class"))
self.airwireshidden=parseByType(parent, "bool", root.get("airwireshidden"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
for c in root.xpath("./contactref"):
self.add_contactref(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./polygon"):
self.add_polygon(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./wire"):
self.add_wire(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./via"):
self.add_via(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.netclass)
r = r + str(self.airwireshidden)
return r
[docs] def get_et(self):
"""
Generate a <signal> element tree for a :class:`Signal`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("signal")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.netclass)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("class", v)
## Unparse the values.
v = unparseByType(self, "bool", self.airwireshidden)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("airwireshidden", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.contactrefs) is not 0:
target = smartAddSubTags(r, "./contactref")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.contactrefs,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.polygons) is not 0:
target = smartAddSubTags(r, "./polygon")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.polygons,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.wires) is not 0:
target = smartAddSubTags(r, "./wire")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.wires,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.vias) is not 0:
target = smartAddSubTags(r, "./via")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.vias,key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Signal`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Signal`
"""
n = copy.copy(self)
n.contactrefs = []
for x in self.contactrefs:
n.add_contactref(x.clone())
n.polygons = []
for x in self.polygons:
n.add_polygon(x.clone())
n.wires = []
for x in self.wires:
n.add_wire(x.clone())
n.vias = []
for x in self.vias:
n.add_via(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Signal_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Signal_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Signal`. This corresponds to the :code:`name` attribute of a :code:`<signal>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Signal`. This corresponds to the :code:`name` attribute of a :code:`<signal>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_class(self):
""" Return the value of :code:`netclass` for this :class:`Signal`. This corresponds to the :code:`netclass` attribute of a :code:`<signal>` in an Eagle file.
:rtype: :code:`str`
"""
return self.netclass
[docs] def set_class(self,v):
""" Set the value of :code:`netclass` for this :class:`Signal`. This corresponds to the :code:`netclass` attribute of a :code:`<signal>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.netclass = v
return self
[docs] def with_class(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`netclass`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`netclass` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_class()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.netclass == v else None
elif callable(v):
return self if v(self.netclass) else None
[docs] def get_airwireshidden(self):
""" Return the value of :code:`airwireshidden` for this :class:`Signal`. This corresponds to the :code:`airwireshidden` attribute of a :code:`<signal>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.airwireshidden
[docs] def set_airwireshidden(self,v):
""" Set the value of :code:`airwireshidden` for this :class:`Signal`. This corresponds to the :code:`airwireshidden` attribute of a :code:`<signal>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.airwireshidden = v
return self
[docs] def with_airwireshidden(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`airwireshidden`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`airwireshidden` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_airwireshidden()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.airwireshidden == v else None
elif callable(v):
return self if v(self.airwireshidden) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_class(self):
"""Find the :class:`Class` object refered to by the :code:`netclass` attribute of this object. This is like
:meth:`get_netclass`, except it returns the :class:`Class` object instead of its name.
:returns: The object
:rtype: :class:`Class`
"""
f = lambda efp, key: NotImplemented('class lookup from signal not implemented')
return f(self, self.netclass)
### Adder/getter/lookup for lists
[docs] def add_polygon(self, s):
""" Add a :class:`Polygon` to the :code:`polygons` of this :class:`Signal`.
:param s: The :class:`Polygon` to add.
:rtype: :code:`self`
"""
self.polygons.append(s)
s.parent = self
return self
[docs] def get_nth_polygon(self, n):
""" get then nth :class:`Polygon` object from the :code:`polygons` of this :class:`Signal`.
:param n: Index of the item to return.
:rtype: :class:`Polygon` object
"""
return self.polygons[n]
[docs] def get_polygons(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`polygons` list of :class:`Polygon` objects for this :class:`Signal`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Polygon` objects
:rtype: List of :class:`Polygon` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.polygons
[docs] def clear_polygons(self):
"""
Remove all the :class:`Polygon` objects from the :code:`polygons` of this :class:`Signal`.
:rtype: :code:`self`
"""
for efp in self.polygons:
efp.parent = None
self.polygons = []
return self
[docs] def remove_polygon(self, efp):
"""
Remove a :class:`Polygon` from the :code:`polygons` of this :class:`Signal`.
:param efp: The :class:`Polygon` object to remove.
:rtype: :code:`self`
"""
self.polygons = [x for x in self.polygons if x != efp]
efp.parent = None
return self
[docs] def add_wire(self, s):
""" Add a :class:`Wire` to the :code:`wires` of this :class:`Signal`.
:param s: The :class:`Wire` to add.
:rtype: :code:`self`
"""
self.wires.append(s)
s.parent = self
return self
[docs] def get_nth_wire(self, n):
""" get then nth :class:`Wire` object from the :code:`wires` of this :class:`Signal`.
:param n: Index of the item to return.
:rtype: :class:`Wire` object
"""
return self.wires[n]
[docs] def get_wires(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`wires` list of :class:`Wire` objects for this :class:`Signal`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Wire` objects
:rtype: List of :class:`Wire` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.wires
[docs] def clear_wires(self):
"""
Remove all the :class:`Wire` objects from the :code:`wires` of this :class:`Signal`.
:rtype: :code:`self`
"""
for efp in self.wires:
efp.parent = None
self.wires = []
return self
[docs] def remove_wire(self, efp):
"""
Remove a :class:`Wire` from the :code:`wires` of this :class:`Signal`.
:param efp: The :class:`Wire` object to remove.
:rtype: :code:`self`
"""
self.wires = [x for x in self.wires if x != efp]
efp.parent = None
return self
[docs] def add_via(self, s):
""" Add a :class:`Via` to the :code:`vias` of this :class:`Signal`.
:param s: The :class:`Via` to add.
:rtype: :code:`self`
"""
self.vias.append(s)
s.parent = self
return self
[docs] def get_nth_via(self, n):
""" get then nth :class:`Via` object from the :code:`vias` of this :class:`Signal`.
:param n: Index of the item to return.
:rtype: :class:`Via` object
"""
return self.vias[n]
[docs] def get_vias(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`vias` list of :class:`Via` objects for this :class:`Signal`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Via` objects
:rtype: List of :class:`Via` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.vias
[docs] def clear_vias(self):
"""
Remove all the :class:`Via` objects from the :code:`vias` of this :class:`Signal`.
:rtype: :code:`self`
"""
for efp in self.vias:
efp.parent = None
self.vias = []
return self
[docs] def remove_via(self, efp):
"""
Remove a :class:`Via` from the :code:`vias` of this :class:`Signal`.
:param efp: The :class:`Via` object to remove.
:rtype: :code:`self`
"""
self.vias = [x for x in self.vias if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.contactrefs
r = r + self.polygons
r = r + self.wires
r = r + self.vias
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_contactref(efp)
except:
pass
try:
self.remove_polygon(efp)
except:
pass
try:
self.remove_wire(efp)
except:
pass
try:
self.remove_via(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["signal"] = Signal
[docs]class Vertex(EagleFilePart):
"""
Class representing the contents of a <vertex> tag in Eagle files.
Attributes:
* :code:`x`
* :code:`y`
* :code:`curve`
"""
def __init__(self):
"""
Construct an empty :class:`Vertex` object.
"""
EagleFilePart.__init__(self)
self.x=None
self.y=None
self.curve=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Vertex` from a :code:`vertex` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Vertex`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Vertex` from a :code:`vertex` element. This is useful if you have a subclass of :class:`Vertex` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Vertex`
"""
if root.tag != "vertex":
raise EagleFormatError("Tried to create vertex from " + root.tag)
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.curve=parseByType(parent, "float", root.get("curve"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
return ""
[docs] def get_et(self):
"""
Generate a <vertex> element tree for a :class:`Vertex`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("vertex")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "float", self.curve)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("curve", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Vertex`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Vertex`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Vertex_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Vertex_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Vertex`. This corresponds to the :code:`x` attribute of a :code:`<vertex>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Vertex`. This corresponds to the :code:`x` attribute of a :code:`<vertex>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Vertex`. This corresponds to the :code:`y` attribute of a :code:`<vertex>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Vertex`. This corresponds to the :code:`y` attribute of a :code:`<vertex>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_curve(self):
""" Return the value of :code:`curve` for this :class:`Vertex`. This corresponds to the :code:`curve` attribute of a :code:`<vertex>` in an Eagle file.
:rtype: :code:`float`
"""
return self.curve
[docs] def set_curve(self,v):
""" Set the value of :code:`curve` for this :class:`Vertex`. This corresponds to the :code:`curve` attribute of a :code:`<vertex>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.curve = v
return self
[docs] def with_curve(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`curve`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`curve` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_curve()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.curve == v else None
elif callable(v):
return self if v(self.curve) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["vertex"] = Vertex
[docs]class SchematicFile(EagleFile):
"""
Class representing the contents of a <eagle> tag in Eagle files.
Attributes:
* :code:`version`
Collections:
* :code:`grid`: Singleton :class:`Grid` object.
* :code:`schematic`: Singleton :class:`Schematic` object.
* :code:`description`: Singleton :class:`Description` object.
* :code:`compatibility`: Singleton :class:`Compatibility` object.
* :code:`setting`: List of :class:`Setting` objects.
* :code:`sheet`: List of :class:`Sheet` objects.
* :code:`approved`: List of :class:`Approved` objects.
* :code:`layer`: Map of :class:`Layer` objects indexed by their :code:`name`.
* :code:`library`: Map of :class:`Library` objects indexed by their :code:`name`.
* :code:`attribute`: Map of :class:`Attribute` objects indexed by their :code:`name`.
* :code:`variantdef`: Map of :class:`Variantdef` objects indexed by their :code:`name`.
* :code:`class`: Map of :class:`Class` objects indexed by their :code:`name`.
* :code:`module`: Map of :class:`Module` objects indexed by their :code:`name`.
* :code:`part`: Map of :class:`Part` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`SchematicFile` object.
"""
EagleFile.__init__(self)
self.version=None
self.settings=[]
self.sheets=[]
self.approved_errors=[]
self.layers={}
self.libraries={}
self.attributes={}
self.variantdefs={}
self.classes={}
self.modules={}
self.parts={}
self.grid=None
self.schematic=None
self.description=None
self.compatibility=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`SchematicFile` from a :code:`eagle` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`SchematicFile`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`SchematicFile` from a :code:`eagle` element. This is useful if you have a subclass of :class:`SchematicFile` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`SchematicFile`
"""
if root.tag != "eagle":
raise EagleFormatError("Tried to create eagle from " + root.tag)
self.version=parseByType(parent, "str", root.get("version"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./drawing/layers/layer"):
self.add_layer(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/schematic/libraries/library"):
self.add_library(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/schematic/attributes/attribute"):
self.add_attribute(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/schematic/variantdefs/variantdef"):
self.add_variantdef(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/schematic/classes/class"):
self.add_class(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/schematic/modules/module"):
self.add_module(self.get_class_for_tag(c.tag)._from_et(c, self))
for c in root.xpath("./drawing/schematic/parts/part"):
self.add_part(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./drawing/settings/setting"):
self.add_setting(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./drawing/schematic/sheets/sheet"):
self.add_sheet(self.get_class_for_tag(c.tag)._from_et(c,self))
for c in root.xpath("./drawing/schematic/errors/approved"):
self.add_approved(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./drawing/grid")
if len(x) is not 0:
self.set_grid(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./drawing/schematic")
if len(x) is not 0:
self.set_schematic(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./drawing/schematic/description")
if len(x) is not 0:
self.set_description(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./compatibility")
if len(x) is not 0:
self.set_compatibility(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.version)
return r
[docs] def get_et(self):
"""
Generate a <eagle> element tree for a :class:`SchematicFile`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("eagle")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.version)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("version", v)
else:
r.set("version", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/settings/setting")
## add a list.
if len(self.settings) is not 0:
target = smartAddSubTags(r, "./drawing/settings/setting")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.settings,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.grid is not None:
target = smartAddSubTags(r, "./drawing/grid")
target.append(self.grid.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.layers) is not 0:
target = smartAddSubTags(r, "./drawing/layers/layer")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.layers.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.schematic is not None:
target = smartAddSubTags(r, "./drawing/schematic")
target.append(self.schematic.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/schematic/description")
## or add a singleton.
if self.description is not None:
target = smartAddSubTags(r, "./drawing/schematic/description")
target.append(self.description.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/schematic/libraries/library")
## add a map.
if len(self.libraries) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/libraries/library")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.libraries.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/schematic/attributes/attribute")
## add a map.
if len(self.attributes) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/attributes/attribute")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.attributes.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/schematic/variantdefs/variantdef")
## add a map.
if len(self.variantdefs) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/variantdefs/variantdef")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.variantdefs.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.classes) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/classes/class")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.classes.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.modules) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/modules/module")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.modules.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/schematic/parts/part")
## add a map.
if len(self.parts) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/parts/part")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.parts.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.sheets) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/sheets/sheet")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.sheets,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a list.
if len(self.approved_errors) is not 0:
target = smartAddSubTags(r, "./drawing/schematic/errors/approved")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.approved_errors,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.compatibility is not None:
target = smartAddSubTags(r, "./compatibility")
target.append(self.compatibility.get_et())
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`SchematicFile`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`SchematicFile`
"""
n = copy.copy(self)
n.layers = {}
for x in self.layers.values():
n.add_layer(x.clone())
n.libraries = {}
for x in self.libraries.values():
n.add_library(x.clone())
n.attributes = {}
for x in self.attributes.values():
n.add_attribute(x.clone())
n.variantdefs = {}
for x in self.variantdefs.values():
n.add_variantdef(x.clone())
n.classes = {}
for x in self.classes.values():
n.add_class(x.clone())
n.modules = {}
for x in self.modules.values():
n.add_module(x.clone())
n.parts = {}
for x in self.parts.values():
n.add_part(x.clone())
n.settings = []
for x in self.settings:
n.add_setting(x.clone())
n.sheets = []
for x in self.sheets:
n.add_sheet(x.clone())
n.approved_errors = []
for x in self.approved_errors:
n.add_approved(x.clone())
if n.grid is not None:
n.grid = self.grid.clone()
if n.schematic is not None:
n.schematic = self.schematic.clone()
if n.description is not None:
n.description = self.description.clone()
if n.compatibility is not None:
n.compatibility = self.compatibility.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "SchematicFile_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "SchematicFile_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_version(self):
""" Return the value of :code:`version` for this :class:`SchematicFile`. This corresponds to the :code:`version` attribute of a :code:`<eagle>` in an Eagle file.
:rtype: :code:`str`
"""
return self.version
[docs] def set_version(self,v):
""" Set the value of :code:`version` for this :class:`SchematicFile`. This corresponds to the :code:`version` attribute of a :code:`<eagle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.version = v
return self
[docs] def with_version(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`version`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`version` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_version()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.version == v else None
elif callable(v):
return self if v(self.version) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_setting(self, s):
""" Add a :class:`Setting` to the :code:`settings` of this :class:`SchematicFile`.
:param s: The :class:`Setting` to add.
:rtype: :code:`self`
"""
self.settings.append(s)
s.parent = self
return self
[docs] def get_nth_setting(self, n):
""" get then nth :class:`Setting` object from the :code:`settings` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Setting` object
"""
return self.settings[n]
[docs] def get_settings(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`settings` list of :class:`Setting` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Setting` objects
:rtype: List of :class:`Setting` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.settings
[docs] def clear_settings(self):
"""
Remove all the :class:`Setting` objects from the :code:`settings` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.settings:
efp.parent = None
self.settings = []
return self
[docs] def remove_setting(self, efp):
"""
Remove a :class:`Setting` from the :code:`settings` of this :class:`SchematicFile`.
:param efp: The :class:`Setting` object to remove.
:rtype: :code:`self`
"""
self.settings = [x for x in self.settings if x != efp]
efp.parent = None
return self
[docs] def add_sheet(self, s):
""" Add a :class:`Sheet` to the :code:`sheets` of this :class:`SchematicFile`.
:param s: The :class:`Sheet` to add.
:rtype: :code:`self`
"""
self.sheets.append(s)
s.parent = self
return self
[docs] def get_nth_sheet(self, n):
""" get then nth :class:`Sheet` object from the :code:`sheets` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Sheet` object
"""
return self.sheets[n]
[docs] def get_sheets(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`sheets` list of :class:`Sheet` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Sheet` objects
:rtype: List of :class:`Sheet` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.sheets
[docs] def clear_sheets(self):
"""
Remove all the :class:`Sheet` objects from the :code:`sheets` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.sheets:
efp.parent = None
self.sheets = []
return self
[docs] def remove_sheet(self, efp):
"""
Remove a :class:`Sheet` from the :code:`sheets` of this :class:`SchematicFile`.
:param efp: The :class:`Sheet` object to remove.
:rtype: :code:`self`
"""
self.sheets = [x for x in self.sheets if x != efp]
efp.parent = None
return self
[docs] def add_approved(self, s):
""" Add a :class:`Approved` to the :code:`approved_errors` of this :class:`SchematicFile`.
:param s: The :class:`Approved` to add.
:rtype: :code:`self`
"""
self.approved_errors.append(s)
s.parent = self
return self
[docs] def get_nth_approved(self, n):
""" get then nth :class:`Approved` object from the :code:`approved_errors` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Approved` object
"""
return self.approved_errors[n]
[docs] def get_approved_errors(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`approved_errors` list of :class:`Approved` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Approved` objects
:rtype: List of :class:`Approved` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.approved_errors
[docs] def clear_approved_errors(self):
"""
Remove all the :class:`Approved` objects from the :code:`approved_errors` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.approved_errors:
efp.parent = None
self.approved_errors = []
return self
[docs] def remove_approved(self, efp):
"""
Remove a :class:`Approved` from the :code:`approved_errors` of this :class:`SchematicFile`.
:param efp: The :class:`Approved` object to remove.
:rtype: :code:`self`
"""
self.approved_errors = [x for x in self.approved_errors if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
[docs] def add_library(self, s):
""" Add a :class:`Library` to the :code:`libraries` of this :class:`SchematicFile`.
:param s: The :class:`Library` to add.
:rtype: :code:`self`
"""
self.libraries[s.name] = s
s.parent = self
return self
[docs] def get_nth_library(self, n):
""" get then nth :class:`Library` object from the :code:`libraries` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Library` object
"""
return self.libraries.values()[n]
[docs] def get_library(self, key):
""" Lookup and return a :class:`Library` from the :code:`libraries` of this :class:`SchematicFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Library` objects.
:rtype: A :class:`Library` object or :code:`None`, if there is no such item.
"""
return self.libraries.get(key)
[docs] def get_libraries(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`libraries` map of :class:`Library` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Library` objects
:rtype: List of :class:`Library` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.libraries.values()
[docs] def clear_libraries(self):
"""
Remove all the :class:`Library` objects from the :code:`libraries` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.libraries.values():
efp.parent = None
self.libraries = {}
return self
[docs] def remove_library(self, efp):
"""
Remove a :class:`Library` from the :code:`libraries` of this :class:`SchematicFile`.
:param efp: The :class:`Library` object to remove.
:rtype: :code:`self`
"""
del self.libraries[efp.name]
efp.parent = None
return self
[docs] def add_attribute(self, s):
""" Add a :class:`Attribute` to the :code:`attributes` of this :class:`SchematicFile`.
:param s: The :class:`Attribute` to add.
:rtype: :code:`self`
"""
self.attributes[s.name] = s
s.parent = self
return self
[docs] def get_nth_attribute(self, n):
""" get then nth :class:`Attribute` object from the :code:`attributes` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Attribute` object
"""
return self.attributes.values()[n]
[docs] def get_attribute(self, key):
""" Lookup and return a :class:`Attribute` from the :code:`attributes` of this :class:`SchematicFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Attribute` objects.
:rtype: A :class:`Attribute` object or :code:`None`, if there is no such item.
"""
return self.attributes.get(key)
[docs] def get_attributes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`attributes` map of :class:`Attribute` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Attribute` objects
:rtype: List of :class:`Attribute` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.attributes.values()
[docs] def clear_attributes(self):
"""
Remove all the :class:`Attribute` objects from the :code:`attributes` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.attributes.values():
efp.parent = None
self.attributes = {}
return self
[docs] def remove_attribute(self, efp):
"""
Remove a :class:`Attribute` from the :code:`attributes` of this :class:`SchematicFile`.
:param efp: The :class:`Attribute` object to remove.
:rtype: :code:`self`
"""
del self.attributes[efp.name]
efp.parent = None
return self
[docs] def add_variantdef(self, s):
""" Add a :class:`Variantdef` to the :code:`variantdefs` of this :class:`SchematicFile`.
:param s: The :class:`Variantdef` to add.
:rtype: :code:`self`
"""
self.variantdefs[s.name] = s
s.parent = self
return self
[docs] def get_nth_variantdef(self, n):
""" get then nth :class:`Variantdef` object from the :code:`variantdefs` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Variantdef` object
"""
return self.variantdefs.values()[n]
[docs] def get_variantdef(self, key):
""" Lookup and return a :class:`Variantdef` from the :code:`variantdefs` of this :class:`SchematicFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Variantdef` objects.
:rtype: A :class:`Variantdef` object or :code:`None`, if there is no such item.
"""
return self.variantdefs.get(key)
[docs] def get_variantdefs(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`variantdefs` map of :class:`Variantdef` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Variantdef` objects
:rtype: List of :class:`Variantdef` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.variantdefs.values()
[docs] def clear_variantdefs(self):
"""
Remove all the :class:`Variantdef` objects from the :code:`variantdefs` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.variantdefs.values():
efp.parent = None
self.variantdefs = {}
return self
[docs] def remove_variantdef(self, efp):
"""
Remove a :class:`Variantdef` from the :code:`variantdefs` of this :class:`SchematicFile`.
:param efp: The :class:`Variantdef` object to remove.
:rtype: :code:`self`
"""
del self.variantdefs[efp.name]
efp.parent = None
return self
[docs] def add_class(self, s):
""" Add a :class:`Class` to the :code:`classes` of this :class:`SchematicFile`.
:param s: The :class:`Class` to add.
:rtype: :code:`self`
"""
self.classes[s.name] = s
s.parent = self
return self
[docs] def get_nth_class(self, n):
""" get then nth :class:`Class` object from the :code:`classes` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Class` object
"""
return self.classes.values()[n]
[docs] def get_class(self, key):
""" Lookup and return a :class:`Class` from the :code:`classes` of this :class:`SchematicFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Class` objects.
:rtype: A :class:`Class` object or :code:`None`, if there is no such item.
"""
return self.classes.get(key)
[docs] def get_classes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`classes` map of :class:`Class` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Class` objects
:rtype: List of :class:`Class` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.classes.values()
[docs] def clear_classes(self):
"""
Remove all the :class:`Class` objects from the :code:`classes` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.classes.values():
efp.parent = None
self.classes = {}
return self
[docs] def remove_class(self, efp):
"""
Remove a :class:`Class` from the :code:`classes` of this :class:`SchematicFile`.
:param efp: The :class:`Class` object to remove.
:rtype: :code:`self`
"""
del self.classes[efp.name]
efp.parent = None
return self
[docs] def add_module(self, s):
""" Add a :class:`Module` to the :code:`modules` of this :class:`SchematicFile`.
:param s: The :class:`Module` to add.
:rtype: :code:`self`
"""
self.modules[s.name] = s
s.parent = self
return self
[docs] def get_nth_module(self, n):
""" get then nth :class:`Module` object from the :code:`modules` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Module` object
"""
return self.modules.values()[n]
[docs] def get_module(self, key):
""" Lookup and return a :class:`Module` from the :code:`modules` of this :class:`SchematicFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Module` objects.
:rtype: A :class:`Module` object or :code:`None`, if there is no such item.
"""
return self.modules.get(key)
[docs] def get_modules(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`modules` map of :class:`Module` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Module` objects
:rtype: List of :class:`Module` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.modules.values()
[docs] def clear_modules(self):
"""
Remove all the :class:`Module` objects from the :code:`modules` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.modules.values():
efp.parent = None
self.modules = {}
return self
[docs] def remove_module(self, efp):
"""
Remove a :class:`Module` from the :code:`modules` of this :class:`SchematicFile`.
:param efp: The :class:`Module` object to remove.
:rtype: :code:`self`
"""
del self.modules[efp.name]
efp.parent = None
return self
[docs] def add_part(self, s):
""" Add a :class:`Part` to the :code:`parts` of this :class:`SchematicFile`.
:param s: The :class:`Part` to add.
:rtype: :code:`self`
"""
self.parts[s.name] = s
s.parent = self
return self
[docs] def get_nth_part(self, n):
""" get then nth :class:`Part` object from the :code:`parts` of this :class:`SchematicFile`.
:param n: Index of the item to return.
:rtype: :class:`Part` object
"""
return self.parts.values()[n]
[docs] def get_part(self, key):
""" Lookup and return a :class:`Part` from the :code:`parts` of this :class:`SchematicFile`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Part` objects.
:rtype: A :class:`Part` object or :code:`None`, if there is no such item.
"""
return self.parts.get(key)
[docs] def get_parts(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`parts` map of :class:`Part` objects for this :class:`SchematicFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Part` objects
:rtype: List of :class:`Part` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.parts.values()
[docs] def clear_parts(self):
"""
Remove all the :class:`Part` objects from the :code:`parts` of this :class:`SchematicFile`.
:rtype: :code:`self`
"""
for efp in self.parts.values():
efp.parent = None
self.parts = {}
return self
[docs] def remove_part(self, efp):
"""
Remove a :class:`Part` from the :code:`parts` of this :class:`SchematicFile`.
:param efp: The :class:`Part` object to remove.
:rtype: :code:`self`
"""
del self.parts[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def set_grid(self, s):
""" Set the :class:`Grid` for this :class:`SchematicFile`.
:param s: :class:`Grid` to set.
:rtype: :code:`self`
"""
if self.grid is not None:
self.grid.parent = None
self.grid = s
if self.grid.parent is not None:
self.grid.parent = self
return self
[docs] def get_grid(self):
""" Get the grid from this :class:`SchematicFile`.
:rtype: :class:`Grid` object
"""
return self.grid
[docs] def set_schematic(self, s):
""" Set the :class:`Schematic` for this :class:`SchematicFile`.
:param s: :class:`Schematic` to set.
:rtype: :code:`self`
"""
if self.schematic is not None:
self.schematic.parent = None
self.schematic = s
if self.schematic.parent is not None:
self.schematic.parent = self
return self
[docs] def get_schematic(self):
""" Get the schematic from this :class:`SchematicFile`.
:rtype: :class:`Schematic` object
"""
return self.schematic
[docs] def set_description(self, s):
""" Set the :class:`Description` for this :class:`SchematicFile`.
:param s: :class:`Description` to set.
:rtype: :code:`self`
"""
if self.description is not None:
self.description.parent = None
self.description = s
if self.description.parent is not None:
self.description.parent = self
return self
[docs] def get_description(self):
""" Get the description from this :class:`SchematicFile`.
:rtype: :class:`Description` object
"""
return self.description
[docs] def set_compatibility(self, s):
""" Set the :class:`Compatibility` for this :class:`SchematicFile`.
:param s: :class:`Compatibility` to set.
:rtype: :code:`self`
"""
if self.compatibility is not None:
self.compatibility.parent = None
self.compatibility = s
if self.compatibility.parent is not None:
self.compatibility.parent = self
return self
[docs] def get_compatibility(self):
""" Get the compatibility from this :class:`SchematicFile`.
:rtype: :class:`Compatibility` object
"""
return self.compatibility
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.settings
r = r + self.sheets
r = r + self.approved_errors
r = r + self.layers.values()
r = r + self.libraries.values()
r = r + self.attributes.values()
r = r + self.variantdefs.values()
r = r + self.classes.values()
r = r + self.modules.values()
r = r + self.parts.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_layer(efp)
except:
pass
try:
self.remove_library(efp)
except:
pass
try:
self.remove_attribute(efp)
except:
pass
try:
self.remove_variantdef(efp)
except:
pass
try:
self.remove_class(efp)
except:
pass
try:
self.remove_module(efp)
except:
pass
try:
self.remove_part(efp)
except:
pass
try:
self.remove_setting(efp)
except:
pass
try:
self.remove_sheet(efp)
except:
pass
try:
self.remove_approved(efp)
except:
pass
if self.get_grid == efp:
self.set_grid(None)
if self.get_schematic == efp:
self.set_schematic(None)
if self.get_description == efp:
self.set_description(None)
if self.get_compatibility == efp:
self.set_compatibility(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["eagle"] = SchematicFile
[docs]class Element(EagleFilePart):
"""
Class representing the contents of a <element> tag in Eagle files.
Attributes:
* :code:`name`
* :code:`library`
* :code:`package`
* :code:`value`
* :code:`x`
* :code:`y`
* :code:`locked`
* :code:`populate`
* :code:`smashed`
* :code:`rot`
Collections:
* :code:`attribute`: Map of :class:`Attribute` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Element` object.
"""
EagleFilePart.__init__(self)
self.name=None
self.library=None
self.package=None
self.value=None
self.x=None
self.y=None
self.locked=None
self.populate=None
self.smashed=None
self.rot=None
self.attributes={}
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Element` from a :code:`element` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Element`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Element` from a :code:`element` element. This is useful if you have a subclass of :class:`Element` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Element`
"""
if root.tag != "element":
raise EagleFormatError("Tried to create element from " + root.tag)
self.name=parseByType(parent, "str", root.get("name"))
self.library=parseByType(parent, "str", root.get("library"))
self.package=parseByType(parent, "str", root.get("package"))
self.value=parseByType(parent, "str", root.get("value"))
self.x=parseByType(parent, "float", root.get("x"))
self.y=parseByType(parent, "float", root.get("y"))
self.locked=parseByType(parent, "bool", root.get("locked"))
self.populate=parseByType(parent, "bool", root.get("populate"))
self.smashed=parseByType(parent, "str", root.get("smashed"))
self.rot=parseByType(parent, "str", root.get("rot"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./attribute"):
self.add_attribute(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.name)
r = r + str(self.library)
r = r + str(self.package)
r = r + str(self.value)
r = r + str(self.x)
r = r + str(self.y)
r = r + str(self.locked)
r = r + str(self.populate)
r = r + str(self.smashed)
r = r + str(self.rot)
return r
[docs] def get_et(self):
"""
Generate a <element> element tree for a :class:`Element`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("element")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.name)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("name", v)
else:
r.set("name", "")
## Unparse the values.
v = unparseByType(self, "str", self.library)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("library", v)
else:
r.set("library", "")
## Unparse the values.
v = unparseByType(self, "str", self.package)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("package", v)
else:
r.set("package", "")
## Unparse the values.
v = unparseByType(self, "str", self.value)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("value", v)
else:
r.set("value", "")
## Unparse the values.
v = unparseByType(self, "float", self.x)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x", v)
else:
r.set("x", "")
## Unparse the values.
v = unparseByType(self, "float", self.y)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y", v)
else:
r.set("y", "")
## Unparse the values.
v = unparseByType(self, "bool", self.locked)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("locked", v)
## Unparse the values.
v = unparseByType(self, "bool", self.populate)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("populate", v)
## Unparse the values.
v = unparseByType(self, "str", self.smashed)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("smashed", v)
## Unparse the values.
v = unparseByType(self, "str", self.rot)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("rot", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./attribute")
## add a map.
if len(self.attributes) is not 0:
target = smartAddSubTags(r, "./attribute")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.attributes.values(),key=lambda x: x.sortkey())])
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Element`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Element`
"""
n = copy.copy(self)
n.attributes = {}
for x in self.attributes.values():
n.add_attribute(x.clone())
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Element_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Element_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_name(self):
""" Return the value of :code:`name` for this :class:`Element`. This corresponds to the :code:`name` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`str`
"""
return self.name
[docs] def set_name(self,v):
""" Set the value of :code:`name` for this :class:`Element`. This corresponds to the :code:`name` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.name = v
return self
[docs] def with_name(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`name`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`name` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_name()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.name == v else None
elif callable(v):
return self if v(self.name) else None
[docs] def get_library(self):
""" Return the value of :code:`library` for this :class:`Element`. This corresponds to the :code:`library` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`str`
"""
return self.library
[docs] def set_library(self,v):
""" Set the value of :code:`library` for this :class:`Element`. This corresponds to the :code:`library` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.library = v
return self
[docs] def with_library(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`library`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`library` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_library()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.library == v else None
elif callable(v):
return self if v(self.library) else None
[docs] def get_package(self):
""" Return the value of :code:`package` for this :class:`Element`. This corresponds to the :code:`package` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`str`
"""
return self.package
[docs] def set_package(self,v):
""" Set the value of :code:`package` for this :class:`Element`. This corresponds to the :code:`package` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.package = v
return self
[docs] def with_package(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`package`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`package` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_package()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.package == v else None
elif callable(v):
return self if v(self.package) else None
[docs] def get_value(self):
""" Return the value of :code:`value` for this :class:`Element`. This corresponds to the :code:`value` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`str`
"""
return self.value
[docs] def set_value(self,v):
""" Set the value of :code:`value` for this :class:`Element`. This corresponds to the :code:`value` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.value = v
return self
[docs] def with_value(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`value`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`value` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_value()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.value == v else None
elif callable(v):
return self if v(self.value) else None
[docs] def get_x(self):
""" Return the value of :code:`x` for this :class:`Element`. This corresponds to the :code:`x` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x
[docs] def set_x(self,v):
""" Set the value of :code:`x` for this :class:`Element`. This corresponds to the :code:`x` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x = v
return self
[docs] def with_x(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x == v else None
elif callable(v):
return self if v(self.x) else None
[docs] def get_y(self):
""" Return the value of :code:`y` for this :class:`Element`. This corresponds to the :code:`y` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y
[docs] def set_y(self,v):
""" Set the value of :code:`y` for this :class:`Element`. This corresponds to the :code:`y` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y = v
return self
[docs] def with_y(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y == v else None
elif callable(v):
return self if v(self.y) else None
[docs] def get_locked(self):
""" Return the value of :code:`locked` for this :class:`Element`. This corresponds to the :code:`locked` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.locked
[docs] def set_locked(self,v):
""" Set the value of :code:`locked` for this :class:`Element`. This corresponds to the :code:`locked` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.locked = v
return self
[docs] def with_locked(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`locked`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`locked` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_locked()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.locked == v else None
elif callable(v):
return self if v(self.locked) else None
[docs] def get_populate(self):
""" Return the value of :code:`populate` for this :class:`Element`. This corresponds to the :code:`populate` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.populate
[docs] def set_populate(self,v):
""" Set the value of :code:`populate` for this :class:`Element`. This corresponds to the :code:`populate` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.populate = v
return self
[docs] def with_populate(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`populate`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`populate` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_populate()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.populate == v else None
elif callable(v):
return self if v(self.populate) else None
[docs] def get_smashed(self):
""" Return the value of :code:`smashed` for this :class:`Element`. This corresponds to the :code:`smashed` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`str`
"""
return self.smashed
[docs] def set_smashed(self,v):
""" Set the value of :code:`smashed` for this :class:`Element`. This corresponds to the :code:`smashed` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.smashed = v
return self
[docs] def with_smashed(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`smashed`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`smashed` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_smashed()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.smashed == v else None
elif callable(v):
return self if v(self.smashed) else None
[docs] def get_rot(self):
""" Return the value of :code:`rot` for this :class:`Element`. This corresponds to the :code:`rot` attribute of a :code:`<element>` in an Eagle file.
:rtype: :code:`str`
"""
return self.rot
[docs] def set_rot(self,v):
""" Set the value of :code:`rot` for this :class:`Element`. This corresponds to the :code:`rot` attribute of a :code:`<element>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.rot = v
return self
[docs] def with_rot(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`rot`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`rot` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_rot()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.rot == v else None
elif callable(v):
return self if v(self.rot) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_library(self):
"""Find the :class:`Library` object refered to by the :code:`library` attribute of this object. This is like
:meth:`get_library`, except it returns the :class:`Library` object instead of its name.
:returns: The object
:rtype: :class:`Library`
"""
f = lambda efp, key: efp.get_parent().get_library(key)
return f(self, self.library)
[docs] def find_package(self):
"""Find the :class:`Package` object refered to by the :code:`package` attribute of this object. This is like
:meth:`get_package`, except it returns the :class:`Package` object instead of its name.
:returns: The object
:rtype: :class:`Package`
"""
f = lambda efp, key: efp.find_library().get_package(key)
return f(self, self.package)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
[docs] def add_attribute(self, s):
""" Add a :class:`Attribute` to the :code:`attributes` of this :class:`Element`.
:param s: The :class:`Attribute` to add.
:rtype: :code:`self`
"""
self.attributes[s.name] = s
s.parent = self
return self
[docs] def get_nth_attribute(self, n):
""" get then nth :class:`Attribute` object from the :code:`attributes` of this :class:`Element`.
:param n: Index of the item to return.
:rtype: :class:`Attribute` object
"""
return self.attributes.values()[n]
[docs] def get_attribute(self, key):
""" Lookup and return a :class:`Attribute` from the :code:`attributes` of this :class:`Element`.
:param key: A :code:`str` to use for the lookup. The lookup uses the :code:`name` of the :class:`Attribute` objects.
:rtype: A :class:`Attribute` object or :code:`None`, if there is no such item.
"""
return self.attributes.get(key)
[docs] def get_attributes(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`attributes` map of :class:`Attribute` objects for this :class:`Element`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Attribute` objects
:rtype: List of :class:`Attribute` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented")
return self.attributes.values()
[docs] def clear_attributes(self):
"""
Remove all the :class:`Attribute` objects from the :code:`attributes` of this :class:`Element`.
:rtype: :code:`self`
"""
for efp in self.attributes.values():
efp.parent = None
self.attributes = {}
return self
[docs] def remove_attribute(self, efp):
"""
Remove a :class:`Attribute` from the :code:`attributes` of this :class:`Element`.
:param efp: The :class:`Attribute` object to remove.
:rtype: :code:`self`
"""
del self.attributes[efp.name]
efp.parent = None
return self
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.attributes.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_attribute(efp)
except:
pass
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["element"] = Element
[docs]class Base_LibraryFile(EagleFile):
"""
Class representing the contents of a <eagle> tag in Eagle files.
Attributes:
* :code:`version`
Collections:
* :code:`grid`: Singleton :class:`Grid` object.
* :code:`library`: Singleton :class:`Library` object.
* :code:`compatibility`: Singleton :class:`Compatibility` object.
* :code:`setting`: List of :class:`Setting` objects.
* :code:`layer`: Map of :class:`Layer` objects indexed by their :code:`name`.
"""
def __init__(self):
"""
Construct an empty :class:`Base_LibraryFile` object.
"""
EagleFile.__init__(self)
self.version=None
self.settings=[]
self.layers={}
self.grid=None
self.library=None
self.compatibility=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`LibraryFile` from a :code:`eagle` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`LibraryFile`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`LibraryFile` from a :code:`eagle` element. This is useful if you have a subclass of :class:`LibraryFile` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`LibraryFile`
"""
if root.tag != "eagle":
raise EagleFormatError("Tried to create eagle from " + root.tag)
self.version=parseByType(parent, "str", root.get("version"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
for c in root.xpath("./drawing/layers/layer"):
self.add_layer(self.get_class_for_tag(c.tag)._from_et(c, self))
### Do the same for the lists
for c in root.xpath("./drawing/settings/setting"):
self.add_setting(self.get_class_for_tag(c.tag)._from_et(c,self))
### And the singletons
x = root.xpath("./drawing/grid")
if len(x) is not 0:
self.set_grid(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./drawing/library")
if len(x) is not 0:
self.set_library(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
x = root.xpath("./compatibility")
if len(x) is not 0:
self.set_compatibility(self.get_class_for_tag(x[0].tag)._from_et(x[0],self))
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.version)
return r
[docs] def get_et(self):
"""
Generate a <eagle> element tree for a :class:`LibraryFile`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("eagle")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.version)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("version", v)
else:
r.set("version", "")
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
smartAddSubTags(r, "./drawing/settings/setting")
## add a list.
if len(self.settings) is not 0:
target = smartAddSubTags(r, "./drawing/settings/setting")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.settings,key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.grid is not None:
target = smartAddSubTags(r, "./drawing/grid")
target.append(self.grid.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## add a map.
if len(self.layers) is not 0:
target = smartAddSubTags(r, "./drawing/layers/layer")
# add them in sorted order. This gives us a simple canonicalization that makes it feasible to use diff to compare files.
target.extend([i.get_et() for i in sorted(self.layers.values(),key=lambda x: x.sortkey())])
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.library is not None:
target = smartAddSubTags(r, "./drawing/library")
target.append(self.library.get_et())
## For some tags, Eagle generates empty tags when there's no contant
## rather than just leaving the tag out. We mark these with
## Tag.requireTag in GenerateSwoop.py and force their generation
## here.
## or add a singleton.
if self.compatibility is not None:
target = smartAddSubTags(r, "./compatibility")
target.append(self.compatibility.get_et())
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`LibraryFile`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`LibraryFile`
"""
n = copy.copy(self)
n.layers = {}
for x in self.layers.values():
n.add_layer(x.clone())
n.settings = []
for x in self.settings:
n.add_setting(x.clone())
if n.grid is not None:
n.grid = self.grid.clone()
if n.library is not None:
n.library = self.library.clone()
if n.compatibility is not None:
n.compatibility = self.compatibility.clone()
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "LibraryFile_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "LibraryFile_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_version(self):
""" Return the value of :code:`version` for this :class:`LibraryFile`. This corresponds to the :code:`version` attribute of a :code:`<eagle>` in an Eagle file.
:rtype: :code:`str`
"""
return self.version
[docs] def set_version(self,v):
""" Set the value of :code:`version` for this :class:`LibraryFile`. This corresponds to the :code:`version` attribute of a :code:`<eagle>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.version = v
return self
[docs] def with_version(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`version`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`version` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_version()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.version == v else None
elif callable(v):
return self if v(self.version) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
[docs] def add_setting(self, s):
""" Add a :class:`Setting` to the :code:`settings` of this :class:`LibraryFile`.
:param s: The :class:`Setting` to add.
:rtype: :code:`self`
"""
self.settings.append(s)
s.parent = self
return self
[docs] def get_nth_setting(self, n):
""" get then nth :class:`Setting` object from the :code:`settings` of this :class:`LibraryFile`.
:param n: Index of the item to return.
:rtype: :class:`Setting` object
"""
return self.settings[n]
[docs] def get_settings(self, attrs=None, type=None):
"""Return (and possibly filter) items in the the :code:`settings` list of :class:`Setting` objects for this :class:`LibraryFile`.
This functions provides a mechanism for filtering the items as well.
The keys in :code:`attrs` are taken as attributes names and the
values are requested values. Items in the list that have all the
requested values for the corresponding attributes will be returned.
A if :code:`type` is not :code:`None`, the item will match if it is an
instance of the type provided.
:param attrs: A set of key-value pairs that represent a filter to apply to the item's attributes.
:param type: A type to filter on. Only items that are an instance of this type will be returned.
:returns: A List of :class:`Setting` objects
:rtype: List of :class:`Setting` objects
"""
if attrs is not None or type is not None:
raise NotImplementedError("filtered get not implemented.")
return self.settings
[docs] def clear_settings(self):
"""
Remove all the :class:`Setting` objects from the :code:`settings` of this :class:`LibraryFile`.
:rtype: :code:`self`
"""
for efp in self.settings:
efp.parent = None
self.settings = []
return self
[docs] def remove_setting(self, efp):
"""
Remove a :class:`Setting` from the :code:`settings` of this :class:`LibraryFile`.
:param efp: The :class:`Setting` object to remove.
:rtype: :code:`self`
"""
self.settings = [x for x in self.settings if x != efp]
efp.parent = None
return self
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def set_grid(self, s):
""" Set the :class:`Grid` for this :class:`LibraryFile`.
:param s: :class:`Grid` to set.
:rtype: :code:`self`
"""
if self.grid is not None:
self.grid.parent = None
self.grid = s
if self.grid.parent is not None:
self.grid.parent = self
return self
[docs] def get_grid(self):
""" Get the grid from this :class:`LibraryFile`.
:rtype: :class:`Grid` object
"""
return self.grid
[docs] def set_library(self, s):
""" Set the :class:`Library` for this :class:`LibraryFile`.
:param s: :class:`Library` to set.
:rtype: :code:`self`
"""
if self.library is not None:
self.library.parent = None
self.library = s
if self.library.parent is not None:
self.library.parent = self
return self
[docs] def get_library(self):
""" Get the library from this :class:`LibraryFile`.
:rtype: :class:`Library` object
"""
return self.library
[docs] def set_compatibility(self, s):
""" Set the :class:`Compatibility` for this :class:`LibraryFile`.
:param s: :class:`Compatibility` to set.
:rtype: :code:`self`
"""
if self.compatibility is not None:
self.compatibility.parent = None
self.compatibility = s
if self.compatibility.parent is not None:
self.compatibility.parent = self
return self
[docs] def get_compatibility(self):
""" Get the compatibility from this :class:`LibraryFile`.
:rtype: :class:`Compatibility` object
"""
return self.compatibility
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
r = r + self.settings
r = r + self.layers.values()
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
try:
self.remove_layer(efp)
except:
pass
try:
self.remove_setting(efp)
except:
pass
if self.get_grid == efp:
self.set_grid(None)
if self.get_library == efp:
self.set_library(None)
if self.get_compatibility == efp:
self.set_compatibility(None)
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["eagle"] = Base_LibraryFile
[docs]class Clearance(EagleFilePart):
"""
Class representing the contents of a <clearance> tag in Eagle files.
Attributes:
* :code:`class`
* :code:`value`
"""
def __init__(self):
"""
Construct an empty :class:`Clearance` object.
"""
EagleFilePart.__init__(self)
self.netclass=None
self.value=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Clearance` from a :code:`clearance` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Clearance`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Clearance` from a :code:`clearance` element. This is useful if you have a subclass of :class:`Clearance` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Clearance`
"""
if root.tag != "clearance":
raise EagleFormatError("Tried to create clearance from " + root.tag)
self.netclass=parseByType(parent, "str", root.get("class"))
self.value=parseByType(parent, "float", root.get("value"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.netclass)
r = r + str(self.value)
return r
[docs] def get_et(self):
"""
Generate a <clearance> element tree for a :class:`Clearance`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("clearance")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "str", self.netclass)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("class", v)
else:
r.set("class", "")
## Unparse the values.
v = unparseByType(self, "float", self.value)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("value", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Clearance`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Clearance`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Clearance_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Clearance_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_class(self):
""" Return the value of :code:`netclass` for this :class:`Clearance`. This corresponds to the :code:`netclass` attribute of a :code:`<clearance>` in an Eagle file.
:rtype: :code:`str`
"""
return self.netclass
[docs] def set_class(self,v):
""" Set the value of :code:`netclass` for this :class:`Clearance`. This corresponds to the :code:`netclass` attribute of a :code:`<clearance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.netclass = v
return self
[docs] def with_class(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`netclass`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`netclass` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_class()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.netclass == v else None
elif callable(v):
return self if v(self.netclass) else None
[docs] def get_value(self):
""" Return the value of :code:`value` for this :class:`Clearance`. This corresponds to the :code:`value` attribute of a :code:`<clearance>` in an Eagle file.
:rtype: :code:`float`
"""
return self.value
[docs] def set_value(self,v):
""" Set the value of :code:`value` for this :class:`Clearance`. This corresponds to the :code:`value` attribute of a :code:`<clearance>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.value = v
return self
[docs] def with_value(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`value`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`value` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_value()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.value == v else None
elif callable(v):
return self if v(self.value) else None
##### Lookup functions that return EFPs instead of just attribute values.
[docs] def find_class(self):
"""Find the :class:`Class` object refered to by the :code:`netclass` attribute of this object. This is like
:meth:`get_netclass`, except it returns the :class:`Class` object instead of its name.
:returns: The object
:rtype: :class:`Class`
"""
f = lambda efp, key: NotImplemented('Lookup of class from clearance not implemented.')
return f(self, self.netclass)
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["clearance"] = Clearance
[docs]class Dimension(EagleFilePart):
"""
Class representing the contents of a <dimension> tag in Eagle files.
Attributes:
* :code:`x1`
* :code:`y1`
* :code:`x2`
* :code:`y2`
* :code:`x3`
* :code:`y3`
* :code:`layer`
* :code:`dtype`
* :code:`width`
* :code:`extwidth`
* :code:`extlength`
* :code:`extoffset`
* :code:`textsize`
* :code:`textratio`
* :code:`unit`
* :code:`precision`
* :code:`visible`
"""
def __init__(self):
"""
Construct an empty :class:`Dimension` object.
"""
EagleFilePart.__init__(self)
self.x1=None
self.y1=None
self.x2=None
self.y2=None
self.x3=None
self.y3=None
self.layer=None
self.dtype=None
self.width=None
self.extwidth=None
self.extlength=None
self.extoffset=None
self.textsize=None
self.textratio=None
self.unit=None
self.precision=None
self.visible=None
@classmethod
def _from_et(cls,root,parent):
"""
Create a :class:`Dimension` from a :code:`dimension` element.
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
:rtype: :class:`Dimension`
"""
## Call the constructor
n = cls()
n. _init_from_et(root,parent)
return n
def _init_from_et(self, root, parent):
"""
Initialized a :class:`Dimension` from a :code:`dimension` element. This is useful if you have a subclass of :class:`Dimension` .
:param root: The element tree tree to parse.
:param parent: :class:`EagleFilePart` that will become the parent of :code:`this` .
:rtype: :class:`Dimension`
"""
if root.tag != "dimension":
raise EagleFormatError("Tried to create dimension from " + root.tag)
self.x1=parseByType(parent, "float", root.get("x1"))
self.y1=parseByType(parent, "float", root.get("y1"))
self.x2=parseByType(parent, "float", root.get("x2"))
self.y2=parseByType(parent, "float", root.get("y2"))
self.x3=parseByType(parent, "float", root.get("x3"))
self.y3=parseByType(parent, "float", root.get("y3"))
self.layer=parseByType(parent, "layer_string", root.get("layer"))
self.dtype=parseByType(parent, "str", root.get("dtype"))
self.width=parseByType(parent, "float", root.get("width"))
self.extwidth=parseByType(parent, "float", root.get("extwidth"))
self.extlength=parseByType(parent, "float", root.get("extlength"))
self.extoffset=parseByType(parent, "float", root.get("extoffset"))
self.textsize=parseByType(parent, "float", root.get("textsize"))
self.textratio=parseByType(parent, "int", root.get("textratio"))
self.unit=parseByType(parent, "str", root.get("unit"))
self.precision=parseByType(parent, "int", root.get("precision"))
self.visible=parseByType(parent, "bool", root.get("visible"))
self.parent = parent
### populate the maps by searching for elements that match xpath and generating objects for them.
### Do the same for the lists
### And the singletons
### And, finally, if the objects wants the text from the tag.
def sortkey(self):
r = ""
r = r + str(self.x1)
r = r + str(self.y1)
r = r + str(self.x2)
r = r + str(self.y2)
r = r + str(self.x3)
r = r + str(self.y3)
r = r + str(self.layer)
r = r + str(self.dtype)
r = r + str(self.width)
r = r + str(self.extwidth)
r = r + str(self.extlength)
r = r + str(self.extoffset)
r = r + str(self.textsize)
r = r + str(self.textratio)
r = r + str(self.unit)
r = r + str(self.precision)
r = r + str(self.visible)
return r
[docs] def get_et(self):
"""
Generate a <dimension> element tree for a :class:`Dimension`.
:rtype: :class:`ElementTree`.
"""
r = ET.Element("dimension")
### Set the tag attributes
## Unparse the values.
v = unparseByType(self, "float", self.x1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x1", v)
else:
r.set("x1", "")
## Unparse the values.
v = unparseByType(self, "float", self.y1)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y1", v)
else:
r.set("y1", "")
## Unparse the values.
v = unparseByType(self, "float", self.x2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x2", v)
else:
r.set("x2", "")
## Unparse the values.
v = unparseByType(self, "float", self.y2)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y2", v)
else:
r.set("y2", "")
## Unparse the values.
v = unparseByType(self, "float", self.x3)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("x3", v)
else:
r.set("x3", "")
## Unparse the values.
v = unparseByType(self, "float", self.y3)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("y3", v)
else:
r.set("y3", "")
## Unparse the values.
v = unparseByType(self, "layer_string", self.layer)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("layer", v)
else:
r.set("layer", "")
## Unparse the values.
v = unparseByType(self, "str", self.dtype)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("dtype", v)
## Unparse the values.
v = unparseByType(self, "float", self.width)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("width", v)
## Unparse the values.
v = unparseByType(self, "float", self.extwidth)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("extwidth", v)
## Unparse the values.
v = unparseByType(self, "float", self.extlength)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("extlength", v)
## Unparse the values.
v = unparseByType(self, "float", self.extoffset)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("extoffset", v)
## Unparse the values.
v = unparseByType(self, "float", self.textsize)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("textsize", v)
else:
r.set("textsize", "")
## Unparse the values.
v = unparseByType(self, "int", self.textratio)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("textratio", v)
## Unparse the values.
v = unparseByType(self, "str", self.unit)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("unit", v)
## Unparse the values.
v = unparseByType(self, "int", self.precision)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("precision", v)
## Unparse the values.
v = unparseByType(self, "bool", self.visible)
## For required attributes None becomes "". For optional attributes, we just leave the attribute out.
if v is not None:
r.set("visible", v)
### process the sections in order. They have to be in section order,
### because eagle files are order dependent.
## set the text, if its needed.
return r
[docs] def clone(self):
"""
Recursively clone this :code:`Dimension`. It will be identical to the original, but it's parent will be :code:`None`.
:rtype: :class:`Dimension`
"""
n = copy.copy(self)
n.parent = None
return n
def accept_preorder_visitor(self, visitor):
try:
pre = getattr(visitor, "Dimension_pre")
return pre(self)
except AttributeError:
return visitor.default_pre(self)
def accept_postorder_visitor(self, visitor, context):
try:
post = getattr(visitor, "Dimension_post")
post(self,context)
except AttributeError:
visitor.default_post(self,context)
### Getters/Setters for attribute values
[docs] def get_x1(self):
""" Return the value of :code:`x1` for this :class:`Dimension`. This corresponds to the :code:`x1` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x1
[docs] def set_x1(self,v):
""" Set the value of :code:`x1` for this :class:`Dimension`. This corresponds to the :code:`x1` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x1 = v
return self
[docs] def with_x1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x1 == v else None
elif callable(v):
return self if v(self.x1) else None
[docs] def get_y1(self):
""" Return the value of :code:`y1` for this :class:`Dimension`. This corresponds to the :code:`y1` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y1
[docs] def set_y1(self,v):
""" Set the value of :code:`y1` for this :class:`Dimension`. This corresponds to the :code:`y1` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y1 = v
return self
[docs] def with_y1(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y1`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y1` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y1()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y1 == v else None
elif callable(v):
return self if v(self.y1) else None
[docs] def get_x2(self):
""" Return the value of :code:`x2` for this :class:`Dimension`. This corresponds to the :code:`x2` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x2
[docs] def set_x2(self,v):
""" Set the value of :code:`x2` for this :class:`Dimension`. This corresponds to the :code:`x2` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x2 = v
return self
[docs] def with_x2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x2 == v else None
elif callable(v):
return self if v(self.x2) else None
[docs] def get_y2(self):
""" Return the value of :code:`y2` for this :class:`Dimension`. This corresponds to the :code:`y2` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y2
[docs] def set_y2(self,v):
""" Set the value of :code:`y2` for this :class:`Dimension`. This corresponds to the :code:`y2` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y2 = v
return self
[docs] def with_y2(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y2`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y2` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y2()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y2 == v else None
elif callable(v):
return self if v(self.y2) else None
[docs] def get_x3(self):
""" Return the value of :code:`x3` for this :class:`Dimension`. This corresponds to the :code:`x3` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.x3
[docs] def set_x3(self,v):
""" Set the value of :code:`x3` for this :class:`Dimension`. This corresponds to the :code:`x3` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.x3 = v
return self
[docs] def with_x3(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`x3`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`x3` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_x3()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.x3 == v else None
elif callable(v):
return self if v(self.x3) else None
[docs] def get_y3(self):
""" Return the value of :code:`y3` for this :class:`Dimension`. This corresponds to the :code:`y3` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.y3
[docs] def set_y3(self,v):
""" Set the value of :code:`y3` for this :class:`Dimension`. This corresponds to the :code:`y3` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.y3 = v
return self
[docs] def with_y3(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`y3`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`y3` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_y3()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.y3 == v else None
elif callable(v):
return self if v(self.y3) else None
[docs] def get_layer(self):
""" Return the value of :code:`layer` for this :class:`Dimension`. This corresponds to the :code:`layer` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`layer_string`
"""
return self.layer
[docs] def set_layer(self,v):
""" Set the value of :code:`layer` for this :class:`Dimension`. This corresponds to the :code:`layer` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.layer = v
return self
[docs] def with_layer(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`layer`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`layer` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_layer()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.layer == v else None
elif callable(v):
return self if v(self.layer) else None
[docs] def get_dtype(self):
""" Return the value of :code:`dtype` for this :class:`Dimension`. This corresponds to the :code:`dtype` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`str`
"""
return self.dtype
[docs] def set_dtype(self,v):
""" Set the value of :code:`dtype` for this :class:`Dimension`. This corresponds to the :code:`dtype` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.dtype = v
return self
[docs] def with_dtype(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`dtype`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`dtype` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_dtype()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.dtype == v else None
elif callable(v):
return self if v(self.dtype) else None
[docs] def get_width(self):
""" Return the value of :code:`width` for this :class:`Dimension`. This corresponds to the :code:`width` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.width
[docs] def set_width(self,v):
""" Set the value of :code:`width` for this :class:`Dimension`. This corresponds to the :code:`width` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.width = v
return self
[docs] def with_width(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`width`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`width` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_width()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.width == v else None
elif callable(v):
return self if v(self.width) else None
[docs] def get_extwidth(self):
""" Return the value of :code:`extwidth` for this :class:`Dimension`. This corresponds to the :code:`extwidth` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.extwidth
[docs] def set_extwidth(self,v):
""" Set the value of :code:`extwidth` for this :class:`Dimension`. This corresponds to the :code:`extwidth` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.extwidth = v
return self
[docs] def with_extwidth(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`extwidth`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`extwidth` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_extwidth()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.extwidth == v else None
elif callable(v):
return self if v(self.extwidth) else None
[docs] def get_extlength(self):
""" Return the value of :code:`extlength` for this :class:`Dimension`. This corresponds to the :code:`extlength` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.extlength
[docs] def set_extlength(self,v):
""" Set the value of :code:`extlength` for this :class:`Dimension`. This corresponds to the :code:`extlength` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.extlength = v
return self
[docs] def with_extlength(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`extlength`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`extlength` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_extlength()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.extlength == v else None
elif callable(v):
return self if v(self.extlength) else None
[docs] def get_extoffset(self):
""" Return the value of :code:`extoffset` for this :class:`Dimension`. This corresponds to the :code:`extoffset` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.extoffset
[docs] def set_extoffset(self,v):
""" Set the value of :code:`extoffset` for this :class:`Dimension`. This corresponds to the :code:`extoffset` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.extoffset = v
return self
[docs] def with_extoffset(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`extoffset`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`extoffset` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_extoffset()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.extoffset == v else None
elif callable(v):
return self if v(self.extoffset) else None
[docs] def get_textsize(self):
""" Return the value of :code:`textsize` for this :class:`Dimension`. This corresponds to the :code:`textsize` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`float`
"""
return self.textsize
[docs] def set_textsize(self,v):
""" Set the value of :code:`textsize` for this :class:`Dimension`. This corresponds to the :code:`textsize` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.textsize = v
return self
[docs] def with_textsize(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`textsize`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`textsize` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_textsize()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.textsize == v else None
elif callable(v):
return self if v(self.textsize) else None
[docs] def get_unit(self):
""" Return the value of :code:`unit` for this :class:`Dimension`. This corresponds to the :code:`unit` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`str`
"""
return self.unit
[docs] def set_unit(self,v):
""" Set the value of :code:`unit` for this :class:`Dimension`. This corresponds to the :code:`unit` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.unit = v
return self
[docs] def with_unit(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`unit`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`unit` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_unit()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.unit == v else None
elif callable(v):
return self if v(self.unit) else None
[docs] def get_precision(self):
""" Return the value of :code:`precision` for this :class:`Dimension`. This corresponds to the :code:`precision` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`int`
"""
return self.precision
[docs] def set_precision(self,v):
""" Set the value of :code:`precision` for this :class:`Dimension`. This corresponds to the :code:`precision` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.precision = v
return self
[docs] def with_precision(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`precision`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`precision` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_precision()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.precision == v else None
elif callable(v):
return self if v(self.precision) else None
[docs] def get_visible(self):
""" Return the value of :code:`visible` for this :class:`Dimension`. This corresponds to the :code:`visible` attribute of a :code:`<dimension>` in an Eagle file.
:rtype: :code:`bool`
"""
return self.visible
[docs] def set_visible(self,v):
""" Set the value of :code:`visible` for this :class:`Dimension`. This corresponds to the :code:`visible` attribute of a :code:`<dimension>` in an Eagle file.
:param v: :class:`EagleFilePart` to set.
:rtype: :code:`self`
"""
self.visible = v
return self
[docs] def with_visible(self,v):
"""
Filter this :code:`EagleFilePart` object based on the value of :code:`visible`. For use in combination with :class:`From` objects.
Return :code:`self` if one of the following is true:
1. :code:`visible` equals :code:`v`
2. :code:`v` is callable and :code:`v(self.get_visible()` is :code:`True`
This is useful in combination with :class:`From` object.
:param t: The value to check for or a callable object.
:returns: :code:`self` if the criteria above are met and :code:`None` otherwise.
:rtype: :class:`EagelFilePart` or :code:`None`
"""
if type(v) in [str, int, float]:
return self if self.visible == v else None
elif callable(v):
return self if v(self.visible) else None
##### Lookup functions that return EFPs instead of just attribute values.
### Adder/getter/lookup for lists
### Add, lookup, and get for maps
### Getter/Setter for singletons.
[docs] def get_children(self):
"""
Get all the children of this :class:`EagleFilePart`.
:rtype: List of :class:`EagleFilePart` objects
"""
r = []
return r
[docs] def remove_child(self, efp):
"""
Remove a child :class:`EagleFilePart` object.
:param efp: the class:`EagleFilePart` object to remove.
:return: Nothing
"""
[docs] def dump(self, indent="", increment=" "):
"""
Recursive debug dump.
:param indent: Indentation string. The output will be indented by this much.
:param increment: This will be appendeded to :code:`indent` on recursive invocations.
:rtype: :code:`None`
"""
print indent + str(self.__class__.__name__)
for c in self.get_children():
c.dump(indent + " ")
EagleFile.class_map["dimension"] = Dimension
[docs]class Part (Base_Part):
"""Extra functions for Parts. Sanity checks, and facilities for find the
symbols, devices, etc. for a part.
"""
def __init__(self):
Base_Part.__init__(self)
# def is_child(self, f):
# if f == "schematic":
# return False
# else:
# return EagleFilePart.is_child(self,f)
def check_sanity(self):
#assert self.get_device() is not None
try:
assert self.find_library() is not None
except Exception as e:
raise SwoopError("Library '" + self.library + "' missing for " + str(self.name))
try:
assert self.find_deviceset() is not None
except Exception as e:
raise SwoopError("DeviceSet '" + self.find_library().name + ":" + self.deviceset + "' missing for " + str(self.name))
try:
assert self.find_device() is not None
except Exception as e:
raise SwoopError("Device '" + self.find_library().name + ":" + self.find_deviceset().name + ":" + self.device + "' missing for " + str(self.name))
EagleFilePart.check_sanity(self)
[docs] def find_library(self):
"""
Get the library that contains this part
"""
lib = self.get_root().libraries.get(self.library)
return lib
[docs] def find_deviceset(self):
"""
Get the deviceset for this part.
"""
lib = self.find_library();
deviceset = lib.devicesets.get(self.deviceset)
return deviceset
[docs] def find_device(self):
"""
Get the library entry for this part
"""
deviceset = self.find_deviceset()
device = deviceset.devices.get(self.device)
return device
[docs] def find_technology(self):
"""
Get the library entry for this part
"""
device = self.find_device()
tech = device.technologies.get(self.technology)
return tech
def set_device(self, library=None, deviceset=None, device=None):
if library is not None:
self.library = library
if deviceset is not None:
self.deviceset = deviceset
if device is not None:
self.device = device
return self
[docs] def find_package(self):
"""
Get the library entry for this part
"""
device = self.find_device();
lib = self.find_library();
if device.package is not None:
package = lib.packages.get(device.package);
else:
package = None
return package
# def get_library_attributes(self):
# """
# Get attribute values for this part that come from the library.
# """
# return {k:v for (k,v) in self.attributes.iteritems() if v.from_library}
def set_attribute(self,name, value):
if name in self.attributes:
self.attributes[name].set_value(value)
else:
self.add_attribute(Attribute().
set_name(name).
set_value(value).
set_in_library(False))
return self
# def get_attribute(self,name):
# return self.attributes.get(name).value
# def remove_attribute(self,name):
# self.attributes[name].parent = None
# del self.attributes[name]
EagleFile.class_map["part"] = Part
[docs]class Attribute (Base_Attribute):
"""Extra functionality for Attributes. Attributes are used in many places in
eagle files and they require different attributes in some cases.
"""
def __init__(self):
Base_Attribute.__init__(self)
self.in_library = False
def __str__(self):
return self.name + " = '" + self.value + "' [const=" + str(self.constant) + ";lib=" + str(self.from_library) +"]";
@classmethod
def _from_et (cls, attribute_root, parent):
n = Attribute()
n. _init_from_et(attribute_root, parent)
if attribute_root.getparent().tag == "technology":
from_library = True;
elif attribute_root.getparent().tag == "part":
from_library = False
elif attribute_root.getparent().tag == "instance":
from_library = False
elif attribute_root.getparent().tag == "element":
from_library = False
elif attribute_root.getparent().tag == "attributes":
from_library = False
else:
raise SwoopError("Unexpectedly found attribute in '" + attribute_root.getparent().tag +"' tag.")
n.in_library = from_library
return n
def set_in_library(self, v):
self.in_library = v
return self
def get_in_libbrary(self):
return self.in_library()
def get_et (self):
n = Base_Attribute.get_et(self)
if not self.in_library:
if "constant" in n.attrib:
del n.attrib["constant"]
return n
EagleFile.class_map["attribute"] = Attribute
#### Extra methods for DeviceSets
def convertToExternal(self):
"""
This converts the :class:`Deviceset` into an external deviceset. This means that it
has no associated package. It can, however, have attributes, and those
are stored in the "" device. You can't just delete all the packages,
since you'd lose the attributes. This copies them from the first
package.
"""
if len(self.get_devices()) > 0:
d = self.get_devices()[0]
self.clear_devices()
d.set_name("").set_package(None).clear_connects()
else:
d = (Device().
set_name("").
set_package(None).
add_technology(Technology().
set_name("")))
self.add_device(d)
From(d).get_technologies().add_attribute(Attribute().set_name("_EXTERNAL_"))
setattr(Deviceset, "convertToExternal", convertToExternal)
class LibraryFile(Base_LibraryFile):
def __init__(self):
Base_LibraryFile.__init__(self)
@classmethod
def _from_et (cls,et, parent, filename):
"""
Loads a Library file from an ElementTree.Element representation.
"""
r = cls()
r. _init_from_et(et, parent)
if r.get_library().name is None:
r.get_library().set_name(os.path.basename(filename)[:-4])
return r
# def get_library_copy(self):
# return copy.deepcopy(self.library)
#print EagleFile.class_map