[Zope-Checkins] CVS: Zope3/lib/python/Interface - pyskel.py:1.1.2.7

Stephan Richter srichter@cbu.edu
Fri, 29 Mar 2002 00:56:12 -0500


Update of /cvs-repository/Zope3/lib/python/Interface
In directory cvs.zope.org:/tmp/cvs-serv6297

Modified Files:
      Tag: Zope-3x-branch
	pyskel.py 
Log Message:
Resolved Issue 14.

After Shane sent me some great and simple file parser code so that I could 
retrieve the order of the methods, I was able to incorporate it quickly 
into pyskel.py.

While I was doing that I also added support for Attributes to pyskel.py.


=== Zope3/lib/python/Interface/pyskel.py 1.1.2.6 => 1.1.2.7 ===
 """
 
-import sys, os
+import sys, os, re
 
 sys.path.insert(0, os.getcwd())
 
 from types import ModuleType
 from Interface.Method import Method
+from Interface.Attribute import Attribute
+
+class_re = re.compile(r'\s*class\s+([a-zA-Z_][a-zA-Z0-9_]*)')
+def_re = re.compile(r'\s*def\s+([a-zA-Z_][a-zA-Z0-9_]*)')
+attr_re = re.compile(r'\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*Attribute')
+
 
 def rskel(iface, print_iface=1):
     name = "%s.%s" % (iface.__module__, iface.__name__)
 
-    namesAndDescriptions = list(iface.namesAndDescriptions())
+    file = resolve(iface.__module__).__file__[:-1]
+    order = guessOrder(open(file))
+    namesAndDescriptions =  getAttributesInOrder(iface, order)
 
     if namesAndDescriptions and print_iface:
         print
         print "    ######################################"
         print "    # from:", name
 
-    # XXX it would be better to keep the original order, but interfaces don't
-    # preserve this, so we'll just sort for now.
-    namesAndDescriptions.sort() 
     for aname, ades in namesAndDescriptions:
         if isinstance(ades, Method):
             sig = ades.getSignatureString()[1:-1]
@@ -55,8 +60,14 @@
             print "    def %s(%s):" % (aname, sig)
             print "        'See %s'" % name
 
+        elif isinstance(ades, Attribute):
+            print
+            print "    # See %s" % name
+            print "    %s = None" %aname
+
     for base in iface.__bases__:
-        rskel(base)
+        if base.__name__ not in ('Interface',):
+            rskel(base)
 
 def skel(name):
     iface = resolve(name)
@@ -72,6 +83,7 @@
 
     rskel(iface, 0)
 
+    print
     print "    #"
     print "    ############################################################"
     
@@ -100,6 +112,49 @@
             if not repeat or (type(a) is not ModuleType):
                 return a
         mod += '.' + last
+
+
+def guessOrder(source_file):
+    order = {}  # { class name -> list of methods }
+    lines = source_file.readlines()
+    class_name = None
+    for line in lines:
+        m = class_re.match(line)
+        if m and m.groups():
+            class_name = m.groups()[0]
+        else:
+            for m in (def_re.match(line),
+                      attr_re.match(line)):
+                if m and m.groups():
+                    def_name = m.groups()[0]
+                    name_order = order.get(class_name)
+                    if name_order is None:
+                        name_order = []
+                        order[class_name] = name_order
+                    name_order.append(def_name)
+
+    return order
+
+
+def getAttributesInOrder(interface, order):
+    # order is the dictionary returned from guessOrder().
+    # interface is a metaclass-based interface object.
+    name_order = order.get(interface.__name__)
+
+    if name_order is None:
+        # Something's wrong.  Oh well.
+        return interface.__dict__.values()
+    else:
+        items = []
+        for key, value in interface.namesAndDescriptions():
+            if key in name_order:
+                items.append((name_order.index(key), key, value))
+            else:
+                items.append((99999, value))  # Go to end.
+        items.sort()
+        return map(lambda item: item[1:], items)
+
+
         
 if __name__ == '__main__':
     for a in sys.argv[1:]: