[Zope3-checkins] CVS: Zope3/src/zope/fssync - metadata.py:1.6

Fred L. Drake, Jr. fred@zope.com
Fri, 25 Jul 2003 16:19:22 -0400


Update of /cvs-repository/Zope3/src/zope/fssync
In directory cvs.zope.org:/tmp/cvs-serv29324/fssync

Modified Files:
	metadata.py 
Log Message:
Use a more concise and readable format for @@Zope/Entries.xml,
while still supporting loading of the XML pickle format (so
existing checkouts are still valid).


=== Zope3/src/zope/fssync/metadata.py 1.5 => 1.6 ===
--- Zope3/src/zope/fssync/metadata.py:1.5	Thu Jun  5 10:04:25 2003
+++ Zope3/src/zope/fssync/metadata.py	Fri Jul 25 16:18:48 2003
@@ -26,9 +26,10 @@
 import os
 import copy
 
+from cStringIO import StringIO
 from os.path import exists, isdir, isfile, split, join, realpath, normcase
-
-from zope.xmlpickle import loads, dumps
+from xml.sax import ContentHandler, parseString
+from xml.sax.saxutils import quoteattr
 
 case_insensitive = (normcase("ABC") == normcase("abc"))
 
@@ -85,7 +86,7 @@
                     data = f.read()
                 finally:
                     f.close()
-                self.cache[key] = entries = loads(data)
+                self.cache[key] = entries = load_entries(data)
             else:
                 self.cache[key] = entries = {}
             self.originals[key] = copy.deepcopy(entries)
@@ -115,7 +116,7 @@
             zdir = join(key, "@@Zope")
             efile = join(zdir, "Entries.xml")
             if exists(efile) or live:
-                data = dumps(live)
+                data = dump_entries(live)
                 if not exists(zdir):
                     os.makedirs(zdir)
                 f = open(efile, "w")
@@ -124,3 +125,84 @@
                 finally:
                     f.close()
             self.originals[key] = copy.deepcopy(live)
+
+
+def dump_entries(entries):
+    sio = StringIO()
+    sio.write("<?xml version='1.0' encoding='utf-8'?>\n")
+    sio.write("<entries>\n")
+    names = entries.keys()
+    names.sort()
+    for name in names:
+        entry = entries[name]
+        sio.write("  <entry name=")
+        sio.write(quoteattr(name).encode('utf-8'))
+        for k, v in entry.iteritems():
+            if v is None:
+                continue
+            sio.write("\n         %s=%s"
+                      % (k.encode('utf-8'), quoteattr(v).encode('utf-8')))
+        sio.write("\n         />\n")
+    sio.write("</entries>\n")
+    return sio.getvalue()
+
+def load_entries(text):
+    ch = EntriesHandler()
+    try:
+        parseString(text, ch)
+    except FoundXMLPickle:
+        from zope.xmlpickle import loads
+        return loads(text)
+    else:
+        return ch.entries
+
+
+class EntriesHandler(ContentHandler):
+    def __init__(self):
+        self.first = True
+        self.stack = []
+        self.entries = {}
+
+    def startElement(self, name, attrs):
+        if self.first:
+            if name == "pickle":
+                raise FoundXMLPickle()
+            elif name != "entries":
+                raise InvalidEntriesFile()
+            else:
+                self.first = False
+        if name == "entry":
+            if self.stack[-1] != "entries":
+                raise InvalidEntriesFile("illegal element nesting")
+            else:
+                entryname = attrs.getValue("name")
+                entry = {}
+                for n in attrs.getNames():
+                    if n != "name":
+                        entry[n] = attrs.getValue(n)
+                self.entries[entryname] = entry
+        elif name == "entries":
+            if self.stack:
+                raise InvalidEntriesFile(
+                    "<entries> must be the document element")
+        else:
+            raise InvalidEntriesFile("unknown element <%s>" % name)
+        self.stack.append(name)
+
+    def endElement(self, name):
+        old = self.stack.pop()
+        assert name == old, "%r != %r" % (name, old)
+
+    def characters(self, data):
+        if data.strip():
+            raise InvalidEntriesFile(
+                "arbitrary character data not supported: %r" % data.strip())
+
+
+class FoundXMLPickle(Exception):
+    """Raised by EntriesHandler when the document appears to be an XML
+    pickle."""
+
+class InvalidEntriesFile(Exception):
+    """Raised by EntriesHandler when the document has an unsupposed
+    document element."""