<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>Tuke/elementref.py</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -20,4 +20,5 @@
 from repr_helper import repr_helper,non_evalable_repr_helper
 
 from id import Id,rndId
-from element import Element,ElementRef,SingleElement,load_Element,save_element_to_file,load_element_from_file
+from element import Element,ReprableByArgsElement,SingleElement
+from elementref import ElementRef,ElementRefContainer</diff>
      <filename>Tuke/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,9 +17,13 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
+from __future__ import with_statement
+
+from collections import deque
+
 import Tuke
-from Tuke import Id,rndId,repr_helper,non_evalable_repr_helper
-from xml.dom.minidom import Document,parse
+from Tuke import Id,rndId,Netlist,repr_helper,non_evalable_repr_helper
+from repr_helper import shortest_class_name
 
 class Element(object):
     &quot;&quot;&quot;Base element class.
@@ -87,8 +91,8 @@ class Element(object):
         &quot;&quot;&quot;Iterate through sub-elements.&quot;&quot;&quot;
 
         for i in self.__dict__.itervalues():
-            if isinstance(i,subelement_wrapper):
-                yield i
+            if isinstance(i,Tuke.ElementRefContainer):
+                yield i 
 
     def _element_id_to_dict_key(self,id):
         &quot;&quot;&quot;Returns the dict key that Element id should be stored under.
@@ -99,31 +103,29 @@ class Element(object):
         assert len(id) &lt;= 1
 
         n = str(id)
-        if hasattr(self,n) and not isinstance(getattr(self,n),subelement_wrapper):
+        if hasattr(self,n) \
+           and not isinstance(getattr(self,n),Tuke.ElementRefContainer):
             n = '_attr_collided_' + n
         return n
 
     def __getitem__(self,id):
-        &quot;&quot;&quot;Get sub-element by Id
+        &quot;&quot;&quot;Get element by Id
 
-        An alternative to the foo.bar lookups.
+        Id can refer to subelements, or, if the Element has a parent, super
+        elements. '../' refers to the parent for instance.
         &quot;&quot;&quot;
         id = Id(id)
 
-        if not len(id):
-            raise KeyError, &quot;Id('') is an invalid key&quot;
-
         r = None
-        try:
+        if not id:
+            return self
+        elif id[0] == '..' or len(id) &gt; 1:
+            r = Tuke.ElementRef(self,id)
+        else:
             r = self.__dict__[self._element_id_to_dict_key(id[0])]
 
-            if len(id) &gt; 1:
-                r = subelement_wrapper(self,r[id[1:]])
-        except KeyError:
-            # Everything wrapped in a KeyError catch, so that inner KeyErrors
-            # will give error messages relative to the outermost element.
-            raise KeyError, &quot;No sub-elements found matching '%s' in '%s'&quot; % (str(id),str(self.id))
-
+        # Element[] should raise a KeyError immediately if the element doesn't exist, so force a dereference
+        r._deref()
         return r
 
     class IdCollisionError(IndexError):
@@ -139,56 +141,25 @@ class Element(object):
 
         Raises Element.IdCollisionError on id collission.
         &quot;&quot;&quot;
-
-        if obj.__class__ == subelement_wrapper:
-            raise TypeError, 'Can only add unwrapped Elements, IE, foo.add(foo.bar) is invalid.'
-
+        if isinstance(obj,Tuke.ElementRef):
+            raise TypeError, 'Can only add bare Elements, IE, foo.add(foo.bar) is invalid.'
         if not isinstance(obj,Element):
             raise TypeError, &quot;Can only add Elements to Elements, not %s&quot; % type(obj)
 
+        if obj.parent:
+            raise ValueError, &quot;'%s' already has parent '%s'&quot; % (obj,obj.parent)
+
         n = self._element_id_to_dict_key(obj.id)
 
         if hasattr(self,n):
             raise self.IdCollisionError,&quot;'%s' already exists&quot; % str(obj.id)
 
-        obj = self._wrap_subelement(obj)
-        setattr(self,n,obj)
-
         obj.parent = self
+        obj = Tuke.ElementRefContainer(self,obj)
+        setattr(self,n,obj)
 
         return obj
 
-    def isinstance(self,cls):
-        &quot;&quot;&quot;Return isinstance(self,cls)
-
-        Due to the behind the scenes element wrapping this must be used instead
-        of isinstance.
-        &quot;&quot;&quot;
-        return isinstance(self,cls)
-
-    def save(self,doc):
-        &quot;&quot;&quot;Returns an XML minidom object representing the Element&quot;&quot;&quot;
-        r = doc.createElement(self.__module__ + '.' + self.__class__.__name__)
-
-        for n,v in self.__dict__.iteritems():
-            if n in set(('parent','_parent','parent_set_callback','parent_unset_callback')):
-                continue
-            if v.__class__  == subelement_wrapper: 
-                r.appendChild(v.save(doc))
-            else:
-                r.setAttribute(n,repr(v))
-
-        return r
-
-    def _wrap_subelement(self,obj):
-        &quot;&quot;&quot;Wrap a subelement's id and transform attrs.
-
-        Used so that a callee sees a consistant view of id and transform in
-        sub-elements. For instance foo.bar.id == 'foo/bar'
-        &quot;&quot;&quot;
-
-        return subelement_wrapper(self,obj)
-
     def iterlayout(self,layer_mask = None):
         &quot;&quot;&quot;Iterate through layout.
 
@@ -205,7 +176,7 @@ class Element(object):
 
         for s in self:
             from Tuke.geometry import Geometry
-            if s.isinstance(Geometry):
+            if isinstance(s,Geometry):
                 if s.layer in layer_mask:
                     yield s
             else:
@@ -236,6 +207,13 @@ class Element(object):
     class VersionError(ValueError):
         pass
 
+    def __enter__(self):
+        &quot;&quot;&quot;Context manager support&quot;&quot;&quot;
+        return self
+    def __exit__(self,exc_type,exc_value,traceback):
+        # reraise
+        return False
+
     @classmethod 
     def from_older_version(cls,other):
         if not cls == other.__class__:
@@ -245,260 +223,110 @@ class Element(object):
         else:
             return other
 
-    @non_evalable_repr_helper
+    @repr_helper
     def __repr__(self):
-        return {'id':str(self.id)}
+        kwargs = self._get_kwargs()
+        return ((),kwargs)
 
-class ElementRef(object):
-    &quot;&quot;&quot;A persistant pointer to an element.
-    
-    ElementRefs, once created, act almost identically to the original element
-    in the same fashion as a weakref.proxy acts. The exceptions being that
-    ref.__class__ is still ElementRef and repr() returns the string for a new
-    ElementRef rather than the target elements repr. These changes are so the
-    Element load and save code works.
-
-    Note that ElementRefs are *not* weakrefs, and *will* increment the targets
-    reference count.
-    &quot;&quot;&quot;
-
-    class NotResolvedError(Exception):
-        &quot;&quot;&quot;ElementRef accessed before target resolved.&quot;&quot;&quot;
-        pass
-
-    def __init__(self_real,target_id,target = None):
-        &quot;&quot;&quot;Create a ElementRef pointing to target
+    def _get_kwargs(self,a_kwargs = {}):
+        &quot;&quot;&quot;Return the kwargs required to represent the Element
         
-        target_id - What the target element's id should be stored as.
-        target - The actual target Element obj, None if not yet available.
+        Subclasses should define this function, have have it call their base
+        classes _get_kwargs(), adding additional kwargs to the dict as needed.
 
-        ElementRef's can be created without target set, this is for load and
-        save routines that may not have the Element instance that target refers
-        to available at initalization.
         &quot;&quot;&quot;
-        self = lambda n: object.__getattribute__(self_real,n)
-
-        object.__setattr__(self_real,'_ref_target_id',Id(target_id))
-
-        self('set_target')(target)
-
-    def set_target(self,target):
-        &quot;&quot;&quot;Set target object.&quot;&quot;&quot;
-        assert isinstance(target,(Element,subelement_wrapper,type(None)))
 
-        object.__setattr__(self,'_ref_target',target)
+        kwargs = {'id':self.id}
+        kwargs.update(a_kwargs)
 
-    def __getattribute__(self_real,n):
-        self = lambda n: object.__getattribute__(self_real,n)
+        return kwargs 
 
-        if n == '__class__':
-            return self('__class__')
-        elif n == '__repr__':
-            return self('__repr__')
+    def _serialize(self,r,indent,root=False,full=False):
+        r.append('%s%s = %s; ' % (indent,self.id,repr(self)))
+        if not root:
+            r.append('_.add(%s)\n' % (self.id))
         else:
-            if self('_ref_target') is None:
-                if n == 'set_target':
-                     return self('set_target')
-                else:
-                    raise ElementRef.NotResolvedError, 'ElementRef not yet resolved.'
-            else:
-                return getattr(self('_ref_target'),n)
-
-    def __setattr__(self_real,n,v):
-        setattr(object.__getattribute__(self_real,'_ref_target'),n,v)
-
-    @repr_helper
-    def __repr__(self):
-        return ((object.__getattribute__(self,'_ref_target_id'),),{})
+            r.append('__root = %s\n' % (self.id))
 
+        if not isinstance(self,ReprableByArgsElement) or full:
+            subs = []
+            for e in self: 
+                if isinstance(e,Tuke.ElementRefContainer):
+                    subs.append(e)
+            subs.sort(key=lambda e: e.id)
 
-# Cache of subelement_wrappers, stored with (id(base),id(obj)) as keys.
-#
-# Possible bug... Could potentially return a value, if base and object are both
-# deleted and others end up at the same address, seems unlikely though.
-import weakref
-subelement_wrapper_cache = weakref.WeakValueDictionary()
+            if subs:
+                r.append('%swith %s as _:\n' % (indent,self.id))
+                for e in subs:
+                    with e as e:
+                        e._serialize(r,indent + '    ')
 
-class subelement_wrapper(object):
-    &quot;&quot;&quot;Class to wrap a sub-Element's id and transform attrs.
-    
-    This is the magic that allows foo.bar.id to be 'foo/bar', even though
-    seperately foo.id == 'foo' and bar.id == 'bar'
+    def serialize(self,full=False):
+        &quot;&quot;&quot;Serialize the Element and it's sub-Elements.&quot;&quot;&quot;
 
-    &quot;&quot;&quot;
-    def __new__(cls,base,obj):
-        &quot;&quot;&quot;Create a new subelement_wrapper
-
-        base - base element
-        obj - wrapped element
-
-        A subtle point is that for any given (id(base),id(obj)) only one
-        subelement_wrapper object will be created, subsequent calls will return
-        the same object. This is required not just for performence reasons, but
-        to maintain the following invarient:
-            
-        a.b.add(Element('c')) == a.b.c
-        &quot;&quot;&quot;
+        r = deque()
 
-        cache_key = (id(base),id(obj))
-        try:
-            return subelement_wrapper_cache[cache_key]
-        except KeyError:
-            self = super(subelement_wrapper,cls).__new__(cls)
-
-            assert(isinstance(base,Element))
-            assert(isinstance(obj,(Element,subelement_wrapper)))
-            object.__setattr__(self,'_base',base)
-            object.__setattr__(self,'_obj',obj)
-
-            subelement_wrapper_cache[cache_key] = self
-            return self
-
-    def isinstance(self,cls):
-        return self._obj.isinstance(cls)
-
-    def add(self,obj):
-        return subelement_wrapper(self._base,
-                self._obj.add(obj))
-
-    def _wrapper_get_id(self):
-        return self._base.id + self._obj.id
-    id = property(_wrapper_get_id)
-
-    def _wrapper_get_transform(self):
-        return self._base.transform * self._obj.transform
-    def _wrapper_set_transform(self,value):
-        # The code setting transform will be dealing with the transform
-        # relative to the wrapper, however _obj.transform needs to be stored
-        # relative to _obj. So apply the inverse of the base transformation
-        # before storing the value to undo.
-        self._obj.transform = self._base.transform.I * value
-
-    transform = property(_wrapper_get_transform,_wrapper_set_transform)
-
-    def __getattr__(self,n):
-        r = getattr(self._obj,n)
-        if r.__class__ == subelement_wrapper: 
-            r = subelement_wrapper(self._base,r)
-        return r
-
-    def __setattr__(self,n,v):
-        # Ugh, this is really ugly.
-        #
-        # For __getattr__ the transform property is called as you would expect,
-        # but __setattr__ bypasses this, so we have to handle it manually.
-        if n != 'transform':
-            setattr(self._obj,n,v)
-        else:
-            self._wrapper_set_transform(v) 
-
-    def __iter__(self):
-        for v in self._obj:
-            yield subelement_wrapper(self._base,v)
-
-    def iterlayout(self,*args,**kwargs):
-        for l in self._obj.iterlayout(*args,**kwargs):
-            yield subelement_wrapper(self._base,l)
+        r.append(&quot;&quot;&quot;\
+from __future__ import with_statement
+import Tuke
 
-    def __getitem__(self,key):
-        return self._obj[key]
+&quot;&quot;&quot;)
 
-    @non_evalable_repr_helper
-    def __repr__(self):
-        return {'id':str(self._base.id + self._obj.id)}
+        self._serialize(r,'',root=True,full=full)
 
+        return ''.join(r)
 
-def load_Element(dom):
-    &quot;&quot;&quot;Loads elements from a saved minidom&quot;&quot;&quot;
 
+class ReprableByArgsElement(Element):
+    &quot;&quot;&quot;Base class for Elements representable by their arguments.&quot;&quot;&quot;
 
-    # Since the xml is saved as a tree, and elements depend on their
-    # subelements, the load operation must be done in a depth-first recursive
-    # manner.
+    def __init__(self,kwargs,required=(),defaults={}):
+        &quot;&quot;&quot;Initialize from kwargs
 
-    subs = []
-    for sub in dom.childNodes:
-        s = load_Element(sub)
-        if s:
-            subs.append(s)
+        All key/value pairs in kwargs will be adde to self.__dict__ Default
+        arguments can be provided in defaults
+        
+        If a key is present in required, but not in kwargs, a TypeError will be
+        raised. If a key is present in kwargs, but not in required or defaults,
+        a TypeError will be raised.
+        &quot;&quot;&quot;
 
-    # An actual dom from the disk will include a number of node types we don't
-    # need, like text nodes and comment nodes, ignore everything but element
-    # nodes.
-    if dom.nodeType != dom.ELEMENT_NODE:
-        if dom.nodeType == dom.DOCUMENT_NODE:
-            # Ooops, special case here. The dom is wrapped by a
-            # &quot;document_node&quot;, which has children that we need to return.
-            assert len(subs) == 1
-            return subs[0]
-        return None 
-    
-    # De-repr() the element attributes to generate a dict.
-    attr = {}
-    for n,v in dom.attributes.items():
-        v = eval(v)
-        attr[n] = v
+        Element.__init__(self,id=kwargs.get('id',''))
 
+        self._kwargs_keys = kwargs.keys()
 
-    # Create an instance of the class referred to by the tagName
-    import sys
+        d = {'id':''}
+        d.update(defaults)
+        defaults = d
 
-    # First split up the module part of tagName from the trailing class part.
-    module = dom.tagName.split('.')
-    name = module[-1]
-    module = reduce(lambda a,b: a + '.' + b,module[0:-1])
+        kw = defaults.copy()
+        kw.update(kwargs)
+        try:
+            del kw['id']
+        except KeyError:
+            pass
 
-    # Load the required module and get the correct class object.
-    __import__(module)
+        required = set(required)
+        valid = required | set(defaults.keys())
 
-    mod = sys.modules[module]
-    
-    klass = getattr(mod,name)
-   
-    # Create a new object of the correct class.
-    #
-    # Not really sure why obj = object() doesn't work, gives an odd error:
-    # &quot;__class__ assignment: only for heap types&quot;
-    obj = _EmptyClass() 
-    obj.__class__ = klass
+        if set(kwargs.keys()) &amp; required != required:
+            raise TypeError, 'Missing required arguments %s' % str(required.difference(set(kwargs.keys())))
 
-    # FIXME: ugly hack, will go away when we make non-xml switch to eval()able
-    # representations.
-    obj.parent_set_callback = []
-    obj.parent_unset_callback = []
-    obj._parent = None
+        extra = set(kwargs.keys()).difference(valid)
+        if extra:
+            raise TypeError, 'Extra arguments %s' % str(extra)
 
-    # Setup attributes
-    for n,v in attr.iteritems():
-        setattr(obj,n,v)
+        self.__dict__.update(kw)
 
-    # Finally load the add sub-elements, this must be done second, as add()
-    # depends on the attributes id and transform
-    for s in subs:
-        obj.add(s)
+    def _get_kwargs(self,a_kwargs = {}):
+        kwargs = {}
+        for k in self._kwargs_keys:
+            kwargs[k] = self.__dict__[k]
 
-    return obj
+        kwargs.update(a_kwargs)
+        return Element._get_kwargs(self,kwargs)
 
-class _EmptyClass(object):
-    pass
 
 class SingleElement(Element):
     &quot;&quot;&quot;Base class for elements without subelements.&quot;&quot;&quot;
     add = None
-    def __init__(self,id=Id()):
-        Element.__init__(self,id=id)
-
-def save_element_to_file(elem,f):
-    &quot;&quot;&quot;Save element to file object f&quot;&quot;&quot;
-
-    doc = Document()
-
-    f.write(elem.save(doc).toprettyxml(indent=&quot;  &quot;))
-
-def load_element_from_file(f):
-    &quot;&quot;&quot;Load the element represented by file object f&quot;&quot;&quot;
-
-    doc = parse(f)
-
-    e = load_Element(doc)
-    return e</diff>
      <filename>Tuke/element.py</filename>
    </modified>
    <modified>
      <diff>@@ -28,10 +28,10 @@ import re
 class Footprint(Tuke.pcb.footprint.Footprint):
     &quot;&quot;&quot;Wrapper for gEDA/PCB footprints&quot;&quot;&quot;
 
-    def __init__(self,file,id=Id()):
-        Element.__init__(self,id=id)
+    def __init__(self,**kwargs):
+        Tuke.pcb.footprint.Footprint.__init__(self,kwargs,required=('file',))
 
-        f = open(file,&quot;r&quot;)
+        f = open(self.file,&quot;r&quot;)
 
         for l in f:
             l = l.strip()
@@ -84,7 +84,11 @@ class Footprint(Tuke.pcb.footprint.Footprint):
 
                     pin_number = Id('_' + pin_number[1:-1]) # remove quotes
 
-                    p = Pin(dia,thickness,clearance,mask,id=pin_number)
+                    p = Pin(dia=dia,
+                            thickness=thickness,
+                            clearance=clearance,
+                            mask=mask,
+                            id=pin_number)
                     translate(p,V(x,y))
 
                     self.add(p)
@@ -107,5 +111,9 @@ class Footprint(Tuke.pcb.footprint.Footprint):
 
                     pad_number = Id('_' + pad_number[1:-1]) # remove quotes
 
-                    p = Pad((x1,y1),(x2,y2),thickness,clearance,mask,id=pad_number)
+                    p = Pad(a=(x1,y1),b=(x2,y2),
+                            thickness=thickness,
+                            clearance=clearance,
+                            mask=mask,
+                            id=pad_number)
                     self.add(p)</diff>
      <filename>Tuke/geda/footprint.py</filename>
    </modified>
    <modified>
      <diff>@@ -40,15 +40,14 @@ def arc_points(a,b,r,segments):
 class Circle(Geometry):
     &quot;&quot;&quot;A circle with a specified diameter.&quot;&quot;&quot;
 
-    def __init__(self,dia,layer=None,id=''):
-        Geometry.__init__(self,layer=layer,id=id)
+    def __init__(self,**kwargs):
+        Geometry.__init__(self,kwargs,
+                required=('dia',))
 
-        if not dia &gt; 0:
+        self.dia = float(self.dia)
+        if not self.dia &gt; 0:
             raise ValueError, 'Diameter must be greater than zero: %d' % dia
 
-        self.dia = float(dia)
-
-
     def render(self):
         v = arc_points(0,2*pi,self.dia / 2,32)
 </diff>
      <filename>Tuke/geometry/circle.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,11 +17,11 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
-from Tuke import SingleElement,Id
+from Tuke import ReprableByArgsElement,SingleElement,Id
 
 from Tuke.geometry import Layer
 
-class Geometry(SingleElement):
+class Geometry(ReprableByArgsElement,SingleElement):
     &quot;&quot;&quot;Base geometry class.
 
     Geometry elements define layout data such as polygons, lines and holes. All
@@ -33,6 +33,8 @@ class Geometry(SingleElement):
     See the Polygon and Hole classes for more info.
     &quot;&quot;&quot;
 
-    def __init__(self,layer = '*',id = ''):
-        SingleElement.__init__(self,id = id)
-        self.layer = Layer(layer)
+    def __init__(self,kwargs,required=set(),defaults={}):
+        d = {'layer':'*',id:''}
+        d.update(defaults)
+        ReprableByArgsElement.__init__(self,kwargs,required,d) 
+        self.layer = Layer(self.layer)</diff>
      <filename>Tuke/geometry/geometry.py</filename>
    </modified>
    <modified>
      <diff>@@ -20,11 +20,10 @@
 from Tuke.geometry import Geometry
 
 class Hole(Geometry):
+    def __init__(self,**kwargs):
+        Geometry.__init__(self,kwargs,
+                required=('dia',),
+                defaults={'layer':'pcb.*.drill'})
 
-    def __init__(self,dia,id='',layer='pcb.*.drill'):
-        Geometry.__init__(self,layer=layer,id=id)
-
-        if not dia &gt; 0:
+        if not self.dia &gt; 0:
             raise ValueError, 'Hole diameter must be greater than zero: %d' % dia
-
-        self.dia = dia</diff>
      <filename>Tuke/geometry/hole.py</filename>
    </modified>
    <modified>
      <diff>@@ -44,16 +44,13 @@ def make_line_vertexes(a,b,thickness,segments):
 class Line(Geometry):
     &quot;&quot;&quot;A line with a specified thickness.&quot;&quot;&quot;
 
-    def __init__(self,a,b,thickness,layer='',id=''):
-        Geometry.__init__(self,layer=layer,id=id)
+    def __init__(self,**kwargs):
+        Geometry.__init__(self,kwargs,
+                required=('a','b','thickness'))
 
-        if not thickness &gt; 0:
+        if not self.thickness &gt; 0:
             raise ValueError, 'Thickness must be greater than zero: %d' % thickness
 
-        self.a = a
-        self.b = b
-        self.thickness = thickness
-
     def render(self):
         v = make_line_vertexes(self.a,self.b,self.thickness,16)
 </diff>
      <filename>Tuke/geometry/line.py</filename>
    </modified>
    <modified>
      <diff>@@ -22,26 +22,17 @@ from Tuke.geometry import Geometry,Transformation
 class Polygon(Geometry):
     &quot;&quot;&quot;A polygon&quot;&quot;&quot;
     
-    def __init__(self,*args,**kwargs):
-        &quot;&quot;&quot;Polygon(external-coords,[internal-coords],layer='',id='')
+    def __init__(self,**kwargs):
+        &quot;&quot;&quot;Polygon
 
-        external_coords - ((x,y),(x,y),...)
-        internal_coords - (
-                           ((x,y),(x,y),...)
-                           ((x,y),(x,y),...))
+        ext - ((x,y),(x,y),...)
+        int - (((x,y),(x,y),...),
+               ((x,y),(x,y),...))
         &quot;&quot;&quot;
 
-        Geometry.__init__(self,
-                layer=kwargs.setdefault('layer',''),
-                id=kwargs.setdefault('id',''))
-
-        assert(0 &lt; len(args) &lt; 3)
-
-        self.external_coords = args[0]
-        if len(args) == 2:
-            self.internal_coords = args[1]
-        else:
-            self.internal_coords = ()
+        Geometry.__init__(self,kwargs,
+                required=('ext',),
+                defaults={'int':()})
 
     def render(self):
-        return (self.external_coords,self.internal_coords)
+        return (self.ext,self.int)</diff>
      <filename>Tuke/geometry/polygon.py</filename>
    </modified>
    <modified>
      <diff>@@ -22,14 +22,7 @@ from Tuke.pcb import Footprint,Pin
 from Tuke.geometry import translate,V
 
 class Dil(Footprint):
-    def __init__(self,
-                 n,
-                 width=300 * MIL,
-                 spacing=100 * MIL,
-                 pad=16 * MIL,
-                 drill=28 * MIL,
-                 clearance=10 * MIL,
-                 mask=60 * MIL):
+    def __init__(self,**kwargs):
         &quot;&quot;&quot;Create new dual-inline package footprint.
 
         n - number of pins
@@ -41,17 +34,16 @@ class Dil(Footprint):
         mask - diameter of the mask, independent of other values
         &quot;&quot;&quot;
 
-        Footprint.__init__(self)
+        Footprint.__init__(self,kwargs,
+                required=('n',),
+                defaults={'width':300 * MIL,
+                          'spacing':100 * MIL,
+                          'pad':16 * MIL,
+                          'drill':28 * MIL,
+                          'clearance':10 * MIL,
+                          'mask':60 * MIL})
 
-        assert not n % 2
-        self.n = n
-
-        self.width = width
-        self.spacing = spacing
-        self.pad = pad
-        self.drill = drill
-        self.clearance = clearance
-        self.mask = mask
+        assert not self.n % 2
 
         # Generate the pins
         for i in xrange(self.n):
@@ -64,7 +56,7 @@ class Dil(Footprint):
                     clearance=self.clearance,
                     mask=self.mask,
                     square=square,
-                    id=str(i + 1))
+                    id='_' + str(i + 1))
 
 
             x = None</diff>
      <filename>Tuke/library/footprint/dil.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,9 +17,9 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
-from Tuke import Element
+from Tuke import ReprableByArgsElement
 
-class Footprint(Element):
+class Footprint(ReprableByArgsElement):
     &quot;&quot;&quot;Defines a Footprint.
   
     A footprint is the holder for the geometry data comprising a pcb footprint.
@@ -29,5 +29,7 @@ class Footprint(Element):
 
     Footprints always have an id of 'footprint'
     &quot;&quot;&quot;
-    def __init__(self):
-        Element.__init__(self,id='footprint')
+    def __init__(self,kwargs,required=(),defaults={}):
+        assert not kwargs.has_key('id')
+        kwargs['id'] = 'footprint'
+        ReprableByArgsElement.__init__(self,kwargs,required,defaults)</diff>
      <filename>Tuke/pcb/footprint.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,13 +17,13 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
-from Tuke import Element,Id
+from Tuke import ReprableByArgsElement,Id
 from Tuke.geometry import Polygon,V
 
-class Pad(Element):
+class Pad(ReprableByArgsElement):
     &quot;&quot;&quot;Defines a pad&quot;&quot;&quot;
 
-    def __init__(self,a,b,thickness,clearance,mask,id=Id()):
+    def __init__(self,**kwargs):
         &quot;&quot;&quot;Create a pad.
 
         a - First point of line segment
@@ -31,17 +31,10 @@ class Pad(Element):
         thickness - Width of metal surrounding line segment
         clearance - Separation of pad from other conductors
         mask - Width of solder mask relief
-
-        id - Id name
         &quot;&quot;&quot;
 
-        Element.__init__(self,id=id)
-
-        self.a = a
-        self.b = b
-        self.thickness = thickness
-        self.clearance = clearance
-        self.mask = mask
+        ReprableByArgsElement.__init__(self,kwargs,
+                required=('a','b','thickness','clearance','mask'))
 
         self.add(self.from_ab(self.thickness,id='pad',layer='top.pad'))
         self.add(self.from_ab(self.thickness + (self.clearance * 2),id='clearance',layer='top.clearance'))
@@ -55,7 +48,7 @@ class Pad(Element):
         For makng pads, clearances etc.
         &quot;&quot;&quot;
 
-        return Polygon((V(self.a[0] - thickness/2,self.a[1] - thickness/2),
+        return Polygon(ext=(V(self.a[0] - thickness/2,self.a[1] - thickness/2),
             V(self.b[0] + thickness/2,self.b[1] - thickness/2),
             V(self.b[0] + thickness/2,self.b[1] + thickness/2),
             V(self.a[0] - thickness/2,self.a[1] + thickness/2)),id=id,layer=layer)</diff>
      <filename>Tuke/pcb/pad.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,13 +17,13 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
-from Tuke import Element,Id
+from Tuke import ReprableByArgsElement,Id
 from Tuke.geometry import Circle,Hole,Polygon,V
 
-class Pin(Element):
+class Pin(ReprableByArgsElement):
     &quot;&quot;&quot;Defines a pin&quot;&quot;&quot;
 
-    def __init__(self,dia,thickness,clearance,mask,square=False,id=Id()):
+    def __init__(self,**kwargs): #dia,thickness,clearance,mask,square=False,id=Id()):
         &quot;&quot;&quot;Create a pin
 
         dia - diameter of the hole
@@ -32,22 +32,20 @@ class Pin(Element):
         mask - diameter of the mask, independent of other values
         square - square flag
         &quot;&quot;&quot;
-        Element.__init__(self,id = id)
+        ReprableByArgsElement.__init__(self,kwargs,
+                required=('dia','thickness','clearance','mask'),
+                defaults={'square':False})
 
-        self.dia = dia
-        self.thickness = thickness
-        self.clearance = clearance
-        self.mask = mask
-        self.square = square
+        self.square = bool(self.square)
 
         def gen_pad_shape(dia,id,layer=None):
             if self.square:
                 r = dia / 2
-                return Polygon((V(-r,-r),V(r,-r),V(r,r),V(-r,r)),id=id,layer=layer)
+                return Polygon(ext=(V(-r,-r),V(r,-r),V(r,r),V(-r,r)),id=id,layer=layer)
             else:
-                return Circle(dia,id=id,layer=layer)
+                return Circle(dia=dia,id=id,layer=layer)
 
-        self.add(Hole(self.dia,id=Id()))
+        self.add(Hole(dia=self.dia,id=Id()))
 
         self.add(gen_pad_shape(self.dia + (self.thickness * 2),id='pad',layer='top.pad'))
         self.add(gen_pad_shape(self.mask,id='mask',layer='top.mask'))</diff>
      <filename>Tuke/pcb/pin.py</filename>
    </modified>
    <modified>
      <diff>@@ -49,7 +49,7 @@ class BaseTrace(Element):
         def __str__(self):
             def t(elem):
                 # FIXME: breaks layering in a nasty way... stupid
-                # subelement_wrappers
+                # ElementWrappers
                 try:
                     return type(elem._obj)
                 except AttributeError:
@@ -74,10 +74,7 @@ class BaseTrace(Element):
 
         bad_endpoints = []
         for e in (a,b):
-            try:
-                if not e.isinstance(self.valid_endpoint_types):
-                    bad_endpoints.append(e)
-            except AttributeError:
+            if not isinstance(e,self.valid_endpoint_types):
                 bad_endpoints.append(e)
         if bad_endpoints:
             raise BaseTrace.InvalidEndpointTypeError(self.__class__,set(bad_endpoints))</diff>
      <filename>Tuke/pcb/trace/basetrace.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,6 +17,40 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
+def shortest_class_name(cls):
+    &quot;&quot;&quot;Returns the shortest class name for cls&quot;&quot;&quot;
+
+    class_name = cls.__name__
+    module_name = cls.__module__
+
+    # Try to find a shorter representation of the module name.
+    #
+    # Often you'll get stuff like Tuke.element.Element, where the Tuke
+    # __init__ code has a from element import Element line, find those
+    # cases.
+    t = module_name
+    while True:
+        t = t.split('.')[:-1]
+        t = '.'.join(t)
+
+        if not t:
+            break
+
+
+        # The from_list has to be set to something, or __import__ will only
+        # return the top level module, IE, Tuke when asked for Tuke.geometry
+        m = __import__(t,{},{},[class_name])
+
+        try:
+            if m.__dict__[class_name] is cls:
+                module_name = t
+                break
+        except KeyError:
+            continue
+
+    return module_name + '.' + class_name 
+
+
 def repr_helper(fn):
     &quot;&quot;&quot;Decorator to make writin __repr__ functions easier.
 
@@ -24,10 +58,6 @@ def repr_helper(fn):
     to eval() is relatively involved, with subtle issues like what is the full
     name of the class. This decorator allows the __repr__ function to simply
     return a (args,kwargs) tuple instead, the decorator will handle the rest.
-
-    As a special case, if the repr function needs to change the class name, set
-    '_repr_helper_class_name_override' This is useful if there are alternate,
-    more legible, ways of creating the object.
     &quot;&quot;&quot;
 
     def f(self):
@@ -38,23 +68,15 @@ def repr_helper(fn):
         if not kwargs:
             kwargs = {}
 
-        class_name = None
-        try:
-            class_name = kwargs['_repr_helper_class_name_override']
-            del kwargs['_repr_helper_class_name_override']
-        except:
-            class_name = self.__class__.__name__
-
         # positional arguments are easy, just repr each one
         args = [repr(a) for a in args] 
 
         # keyword arguments get transformed into name = value syntax
-        kwargs = ['%s = %s' % (n,repr(v)) for (n,v) in kwargs.iteritems()]
+        kwargs = ['%s = %s' % (n,repr(v)) for (n,v) in sorted(kwargs.iteritems())]
 
         args_str = ','.join(args + kwargs)
 
-        return '%s.%s(%s)' % (self.__class__.__module__,class_name,
-                              args_str)
+        return '%s(%s)' % (shortest_class_name(self.__class__),args_str)
 
     return f
 
@@ -84,6 +106,6 @@ def non_evalable_repr_helper(fn):
             return rpr
         else:
             return rpr[:-1] + ', ' \
-                   + ', '.join(['%s=%s' % (n,repr(v)) for n,v in kw.iteritems()]) \
+                   + ', '.join(['%s=%s' % (n,repr(v)) for n,v in sorted(kw.iteritems())]) \
                    + '&gt;'
     return f</diff>
      <filename>Tuke/repr_helper.py</filename>
    </modified>
    <modified>
      <diff>@@ -44,10 +44,7 @@ class Component(Element):
         Element.__init__(self,id=id)
 
         for p in pins:
-            try:
-                if not p.isinstance(Pin):
-                    raise AttributeError
-            except AttributeError:
+            if not isinstance(p,Pin):
                 p = Pin(p)
             self.add(p)
 
@@ -66,11 +63,9 @@ class Component(Element):
             except TypeError:
                 # Second case, an actual Pin objects, just return the id, minus
                 # self.id
-                try:
-                    if not i.isinstance(Pin):
-                        raise AttributeError
+                if isinstance(i,Pin):
                     return i.id[len(self.id):]
-                except AttributeError:
+                else:
                     raise TypeError, 'link() got %s instead of Pin' % repr(i)
 
         a = deref(a)</diff>
      <filename>Tuke/sch/component.py</filename>
    </modified>
    <modified>
      <diff>@@ -17,14 +17,13 @@
 # along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.
 # ### BOILERPLATE ###
 
-from Tuke import Element,Id
+from Tuke import ReprableByArgsElement,Id
 
-class Pin(Element):
+class Pin(ReprableByArgsElement):
     &quot;&quot;&quot;Defines a Pin of a Component&quot;&quot;&quot;
 
-    def __init__(self,name):
-        &quot;&quot;&quot;Create a pin.
-
-        name - Pins name, must also be valid object attribute name.
-        &quot;&quot;&quot;
-        Element.__init__(self,id=Id(name))
+    def __init__(self,*args,**kwargs):
+        &quot;&quot;&quot;Create a pin.&quot;&quot;&quot;
+        if len(args) == 1 and not kwargs:
+            kwargs['id'] = args[0]
+        ReprableByArgsElement.__init__(self,kwargs)</diff>
      <filename>Tuke/sch/pin.py</filename>
    </modified>
    <modified>
      <diff>@@ -39,14 +39,11 @@ class Symbol(Component):
 
         Component.__init__(self,id=id)
 
-        assert footprint.isinstance(Footprint)
+        assert isinstance(footprint,Footprint)
         self.add(footprint)
 
         for p in pins:
-            try:
-                if not p.isinstance(Pin):
-                    raise AttributeError
-            except AttributeError: 
+            if not isinstance(p,Pin):
                 p = Pin(p)
             self.add(p)
 
@@ -61,4 +58,4 @@ class Symbol(Component):
         &quot;&quot;&quot;
 
         for i,p in enumerate(pins):
-            self.link(p,Id('%s/%s/%d' % (self.id,self.footprint.id,i)))
+            self.link(p,Id('%s/%s/_%d' % (self.id,self.footprint.id,i)))</diff>
      <filename>Tuke/sch/symbol.py</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,8 @@
 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 # PURPOSE.
 
+from __future__ import with_statement
+
 import os
 import shutil
 
@@ -15,7 +17,7 @@ import common
 
 from unittest import TestCase
 import Tuke
-from Tuke import load_Element,Element,ElementRef,Id,rndId
+from Tuke import Element,ElementRef,Id,rndId
 
 from Tuke.geometry import Geometry,V,Transformation,Translation,translate,centerof
 
@@ -63,7 +65,6 @@ class ElementTest(TestCase):
         T(a.b is r)
 
         r = a.b.add(Element('c'))
-        print r,a.b.c
         T(a.b.c is r)
 
     def testElementAddCollisions(self):
@@ -104,11 +105,8 @@ class ElementTest(TestCase):
         def T(elem,id_set):
             ids = set() 
             for e in elem:
-                try:
-                    e.isinstance(Element)
+                if isinstance(e,Element):
                     ids.add(e.id)
-                except AttributeError:
-                    pass
             id_set = set([Id(i) for i in id_set])
             self.assert_(ids == id_set,'got: %s expected: %s' % (ids,id_set))
 
@@ -121,15 +119,18 @@ class ElementTest(TestCase):
         T(a,set(('a/_1','a/_2','a/_3')))
 
     def testElement_isinstance(self):
-        &quot;&quot;&quot;Element.isinstance()&quot;&quot;&quot;
+        &quot;&quot;&quot;Element isinstance()&quot;&quot;&quot;
 
         def T(x):
             self.assert_(x)
 
         a = Element('a')
-        T(a.isinstance(Element))
+        T(isinstance(a,Element))
+        T(not isinstance(a,ElementRef))
+
         a.add(Element('b'))
-        T(a.b.isinstance(Element))
+        T(isinstance(a.b,Element))
+        T(isinstance(a.b,ElementRef))
 
     def testElement__getitem__(self):
         &quot;&quot;&quot;Element[] lookups&quot;&quot;&quot;
@@ -141,7 +142,7 @@ class ElementTest(TestCase):
             self.assertRaises(ex,lambda: elem[key])
 
         a = Element('a')
-        R(a,Id(),KeyError)
+        T(a,'',a)
         R(a,'foo',KeyError)
         R(a,Id('foo'),KeyError)
 
@@ -156,6 +157,9 @@ class ElementTest(TestCase):
         T(a,'b',b)
         T(a,'b/d',d)
 
+        #T(b,'..',a)
+        #T(b,'../b',b)
+        #T(b,'../d',d)
 
         e = Element('e')
         e2 = a.add(e)
@@ -174,8 +178,8 @@ class ElementTest(TestCase):
 
         e.add(Element(id = 'chip'))
         e.chip.add(Element(id = 'pad'))
-        e.chip.add(Geometry(layer = 'sch.lines',id = 'sym'))
-        e.chip.pad.add(Geometry(layer = 'top.copper',id = 'pad'))
+        e.chip.add(Geometry({'layer':'sch.lines','id':'sym'}))
+        e.chip.pad.add(Geometry({'layer':'top.copper','id':'pad'}))
 
         # Check returned objects and Id auto-mangling
         T(set([elem.id for elem in e.iterlayout()]),
@@ -201,6 +205,16 @@ class ElementTest(TestCase):
         T(set([elem.id for elem in e.iterlayout(layer_mask='sch.*')]),
           set((Id('base/chip/sym'),)))
 
+    def testElement_with(self):
+        &quot;&quot;&quot;with Element()&quot;&quot;&quot;
+
+        a = Element('a')
+        b = Element('b')
+        a.add(b)
+
+        with a.b as b2:
+            self.assert_(b is b2)
+
     def testElementIdAttr(self):
         &quot;&quot;&quot;Auto-magical attribute lookup from sub-element Id's&quot;&quot;&quot;
 
@@ -226,28 +240,6 @@ class ElementTest(TestCase):
         a.foo.bar = 'bar'
         self.assert_(a.foo.bar is foo.bar)
 
-    def testElementRef(self):
-        &quot;&quot;&quot;ElementRef&quot;&quot;&quot;
-
-        def T(got,expected = True):
-            self.assert_(expected == got,'got: %s  expected: %s' % (got,expected))
-
-        a = Element('a')
-        b = a.add(Element('b'))
-
-        ref_b_orig = ElementRef('b',None)
-
-        for ref_b in (ref_b_orig,eval(repr(ref_b_orig))):
-            T(isinstance(ref_b,ElementRef))
-            self.assertRaises(ElementRef.NotResolvedError,lambda:ref_b.id)
-            ref_b.set_target(b)
-
-            T(ref_b.id,'a/b')
-            b.foo = 'foo'
-            T(ref_b.foo == 'foo')
-            ref_b.bar = 'bar'
-            T(b.bar == 'bar')
-
     def testElementVersionChecking(self):
         &quot;&quot;&quot;Element __version__ checking&quot;&quot;&quot;
         class elem(Element):
@@ -283,8 +275,8 @@ class ElementTest(TestCase):
         R((0,'sdf'))
         R([0,'sdf'])
 
-    def testElementSave(self):
-        &quot;&quot;&quot;Element.save()&quot;&quot;&quot;
+    def testElementSerialize(self):
+        &quot;&quot;&quot;Element.serialize()&quot;&quot;&quot;
 
         doc = Document()
 
@@ -304,15 +296,9 @@ class ElementTest(TestCase):
 
         from Tuke.geda import Footprint
         common.load_dataset('geda_footprints')
-        f1 = Footprint(common.tmpd + '/plcc4-rgb-led',Id('plcc4'))
-        f2 = Footprint(common.tmpd + '/supercap_20mm',Id('supercap'))
-        a.add(f1)
-        a.add(f2)
-
-        dom = a.save(doc)
-
-        print a.save(doc).toprettyxml(indent=&quot;  &quot;)
-
-        doc = Document()
-        print load_Element(dom).save(doc).toprettyxml(indent=&quot;  &quot;)
-        
+        f1 = Footprint(file=common.tmpd + '/plcc4-rgb-led')
+        f2 = Footprint(file=common.tmpd + '/supercap_20mm')
+      
+        print f1.serialize(full=True)
+        print f2.serialize(full=True)
+        # FIXME: more needed here...</diff>
      <filename>Tuke/tests/element.py</filename>
    </modified>
    <modified>
      <diff>@@ -26,5 +26,5 @@ class GedaFootprintTest(TestCase):
 
         common.load_dataset('geda_footprints')
 
-        f = Footprint(common.tmpd + '/plcc4-rgb-led',Id('plcc4'))
-        f = Footprint(common.tmpd + '/supercap_20mm',Id('supercap'))
+        f = Footprint(file=common.tmpd + '/plcc4-rgb-led')
+        f = Footprint(file=common.tmpd + '/supercap_20mm')</diff>
      <filename>Tuke/tests/geda/footprint.py</filename>
    </modified>
    <modified>
      <diff>@@ -61,5 +61,5 @@ class GeometryCircleTest(TestCase):
     def testGeometryCircle(self):
         &quot;&quot;&quot;geometry.Circle()&quot;&quot;&quot;
 
-        a = Circle(2,layer='foo')
-        a = Circle(1,layer='foo')
+        a = Circle(dia=2,layer='foo')
+        a = Circle(dia=1,layer='foo')</diff>
      <filename>Tuke/tests/geometry/circle.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,4 +24,4 @@ class GeometryHoleTest(TestCase):
     def testGeometryHole(self):
         &quot;&quot;&quot;Basic tests&quot;&quot;&quot;
 
-        a = Hole(1)
+        a = Hole(dia=1)</diff>
      <filename>Tuke/tests/geometry/hole.py</filename>
    </modified>
    <modified>
      <diff>@@ -63,10 +63,10 @@ class GeometryLineTest(TestCase):
     def testLine(self):
         &quot;&quot;&quot;geometry.Line&quot;&quot;&quot;
 
-        p = Line(V(-1,2),V(3,4),0.234,layer='foo')
+        p = Line(a=V(-1,2),b=V(3,4),thickness=0.234,layer='foo')
         self.assert_(p.render())
 
     def testThinLine(self):
         &quot;&quot;&quot;geometry.ThinLine&quot;&quot;&quot;
-        p = ThinLine(V(-10,2.5),V(34,4.3),2.2,layer='foo')
+        p = ThinLine(a=V(-10,2.5),b=V(34,4.3),thickness=2.2,layer='foo')
         self.assert_(p.render())</diff>
      <filename>Tuke/tests/geometry/line.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,4 +24,4 @@ class GeometryPolygonTest(TestCase):
     def testGeometryPolygon(self):
         &quot;&quot;&quot;Basic tests&quot;&quot;&quot;
 
-        a = Polygon(((0,0),(1,1),(1,0)),layer='front.solder')
+        a = Polygon(ext=((0,0),(1,1),(1,0)),layer='front.solder')</diff>
      <filename>Tuke/tests/geometry/polygon.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,4 +24,7 @@ class PcbFootprintPadTest(TestCase):
     def testPcbFootprintPad(self):
         &quot;&quot;&quot;Basic tests&quot;&quot;&quot;
 
-        a = Pad((0,0),(1,1),0.5,0.2,0.6)
+        a = Pad(a=(0,0),b=(1,1),
+                thickness=0.5,
+                clearance=0.2,
+                mask=0.6)</diff>
      <filename>Tuke/tests/pcb/pad.py</filename>
    </modified>
    <modified>
      <diff>@@ -23,4 +23,8 @@ class PcbFootprintPinTest(TestCase):
     def testPcbFootprintPin(self):
         &quot;&quot;&quot;Basic tests&quot;&quot;&quot;
 
-        a = Pin(1,1,1,1,id='_1')
+        a = Pin(dia=1,
+                thickness=1,
+                clearance=1,
+                mask=1,
+                id='_1')</diff>
      <filename>Tuke/tests/pcb/pin.py</filename>
    </modified>
    <modified>
      <diff>@@ -37,23 +37,6 @@ class repr_helperTest(TestCase):
 
         self.assert_(repr(f) == 'Tuke.tests.repr_helper.foo(1,2,goo = \'green\')')
 
-    def testrepr_helper_class_name_override(self):
-        &quot;&quot;&quot;repr_helper class name override&quot;&quot;&quot;
-
-        class foo:
-            def __init__(self,a,b,goo = 'green'):
-                self.a = a
-                self.b = b
-                self.goo = goo
-
-            @repr_helper
-            def __repr__(self):
-                return ((self.a,self.b),{'goo':self.goo,'_repr_helper_class_name_override':'bar'})
-
-        
-        f = foo(1,2)
-        self.assert_(repr(f) == 'Tuke.tests.repr_helper.bar(1,2,goo = \'green\')')
-
     def testnon_evalable_repr_helper(self):
         &quot;&quot;&quot;non_evalable_repr_helper decorator&quot;&quot;&quot;
         class foo(object):</diff>
      <filename>Tuke/tests/repr_helper.py</filename>
    </modified>
    <modified>
      <diff>@@ -27,6 +27,14 @@ unchanged, modify others, and also have isinstance() work correctly. This
 script has a few different ways of implementing that, and shows the performence
 differences and coding impact between them.
 
+
+Note that there is currently a fatal flaw in the subclassing implementation. If
+the wrapped object has any functions with names not also in the wrapping
+clsases dict the method resolution order will fail to find the function in the
+wrapper, then try the wrapped objects class. This will succeed, and the
+function will be called with self set to the *wrapped* object, rather than the
+*unwrapped* object that it expects. Unfortunately __mro__ is readonly, perhaps
+a C extension can fix this problem.
 &quot;&quot;&quot;
 
 import timeit</diff>
      <filename>doc/experiments/object_proxying_test</filename>
    </modified>
    <modified>
      <diff>@@ -39,7 +39,7 @@ class Led(Symbol):
     def __init__(self,id):
         Symbol.__init__(self,
                 pins = (Pin('anode'),Pin('cathode')),
-                footprint = Dil(2),
+                footprint = Dil(n=2),
                 id = id)
 
 class LedGrid(Component):
@@ -54,7 +54,7 @@ class LedGrid(Component):
         for x in xrange(cols):
             prev = None
             for y in xrange(rows):
-                l = Led(id=Id('LED%s-%s' % (str(x),str(y))))
+                l = Led(id=Id('LED%s_%s' % (str(x),str(y))))
                 translate(l,V((x * spacing) - ((cols - 1) * spacing / 2),(y * spacing) - ((rows - 1) * spacing / 2)))
                 l = self.add(l)
 </diff>
      <filename>examples/LedGrid/ledgrid.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python2.5
 # vim: tabstop=4 expandtab shiftwidth=4 fileencoding=utf8
 # ### BOILERPLATE ###
 # Tuke - Electrical Design Automation toolset
@@ -32,7 +32,7 @@ stdout.
 
 import iam_tuke_example
 
-from Tuke import rndId,save_element_to_file
+from Tuke import rndId
 from Tuke.units import *
 from LedGrid import Led,LedGrid
 
@@ -44,4 +44,4 @@ if __name__ == &quot;__main__&quot;:
 
     grid = LedGrid(rows,cols,spacing=0.5 * IN, id=rndId())
 
-    save_element_to_file(grid,sys.stdout)
+    print grid.serialize(full=True),</diff>
      <filename>examples/led_grid</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python2.5
 # vim: tabstop=4 expandtab shiftwidth=4 fileencoding=utf8
 # ### BOILERPLATE ###
 # Tuke - Electrical Design Automation toolset</diff>
      <filename>tuke</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>1e1c38ed22813b8ac165ea0e92154a88c52ff4a3</id>
    </parent>
  </parents>
  <author>
    <name>tailor</name>
    <email>pete@petertodd.org</email>
  </author>
  <url>http://github.com/retep/tuke/commit/94f61388932dae40d98999b1a8005049c07c6254</url>
  <id>94f61388932dae40d98999b1a8005049c07c6254</id>
  <committed-date>2008-03-16T18:15:09-07:00</committed-date>
  <authored-date>2008-03-16T18:15:09-07:00</authored-date>
  <message>[tuke @ 36537559aa52a7b34dddf835c59b5f477261d1b7]
merge of 'dcd4e0a6aafdf2f4ff4a5ca2bdcfbf1e039e5437'
     and 'e77b3b1f31a610b63d4dbb26f7eb730abe2042e5'</message>
  <tree>906d9222d88e1953a5ef5afda7291f4c63f255b9</tree>
  <committer>
    <name>tailor</name>
    <email>pete@petertodd.org</email>
  </committer>
</commit>
