Lynn Rees avatar Lynn Rees committed a24e7b4

- more comments

Comments (0)

Files changed (3)

 '''Library for PSI maps'''
 
+__title__ = 'psilib'
 __version__ = '0.03-test'
 __author__  = 'L. C. Rees (xanimal@users.sf.net)'
+
+'''Base init class for psilib'''
+
+# PSI namespace
+namespaceURI = u'urn:psilib:PSI:0:4:core'
 ## Copyright (c) 1999 - 2003 L. C. Rees.  All rights reserved.
 ## See COPYRIGHT file for license terms.
 
-'''DOM extension for building sites with PSI'''
-
+__title__ = 'som'
 __version__ = '0.03-test'
 __author__  = 'L. C. Rees (xanimal@users.sf.net)'
 
-from xml.dom.minidom import Element
+'''SOM (Site Object Model) is a DOM wrapper for building PSI maps. SOM
+completely implements the current PSI data model (0.41). Each PSI element has a
+corresponding class that ensures correct PSI output.'''
 
+## Element and Document classes from DOM
+from xml.dom.minidom import Element, Document
+
+class Root(Document):
+
+    '''Adds creates a document to add PSI markup too'''
+
+    def __init__(self):
+        '''Initializes base Document DOM class'''
+        Document.__init__(self)
+
+    def __repr__(self):
+        '''Returns representation of instance as XML'''
+        return self.toprettyxml('  ')
+        
 
 class Base(Element):
 
-    '''Base class providing utility functions and subclassing DOM'''    
-
-    ## PSI namespace
-    namespaceURI = u'urn:psilib:PSI:0:4:core'
+    '''Base class providing utility functions.'''    
 
     def __init__(self, nodeName):
         '''Initializes base Element DOM class
         Element.__init__(self, nodeName, None)        
     
     def __repr__(self):
-        '''Returns representation of object as XML'''
+        '''Returns representation of instance as XML'''
         return self.toprettyxml('  ')
 
     def _add(self, Class, *vargs):
         Class -- class for individual PSI node
         vargs -- attributes (amount can vary)'''
         node = Class(*vargs)
-        if self.hasChildNodes():
-            ## Insert nodes in front of parameter, result & exception
+        ## Insert nodes in front of parameter, result & exception elements
+        if self.hasChildNodes():            
             try:                
                 if self.parameters:
                    self.insertBefore(node, self.parameters[0])
                     self.insertBefore(node, self.exceptions[0])
                 else: self.appendChild(node)
             except AttributeError: self.appendChild(node)
+        ## Otherwise append child to end
         else: self.appendChild(node)
         return node
 
-    def _attchecker(self, name, value, msg, rl):
+    def _attchecker(self, name, value, msg, av):
+        '''Verifies attribute has acceptable values
+
+        name -- name of attribute
+        value -- value of attribute
+        msg -- message raised if value is not acceptable
+        av -- list of acceptable values'''
+        ## Set the class attribute
         setattr(self, name, value)
         ## Raise error if unacceptable value entered
-        if value not in rl:
-            raise AttributeError, msg
-        else:
-            self.setAttributeNS(None, name, value)         
+        if value not in av: raise AttributeError, msg
+        ## Otherwise, set the DOM attribute
+        else: self.setAttribute(name, value)         
 
     def removeChildren(self, childList=None):
         '''Removes unwanted child nodes
 
         Arguments:
         childList -- list of specific nodes (default: None)'''
+        ## If a element has a list of children, delete the list
         if childList:
-            for child in childList:
-                self._remove(child)
+            for child in childList: self._remove(child)
+        ## Otherwise, delete any and all child nodes
         else:
             for child in self.childNodes:
                 self.childNodes.remove(child)
             Arguments:
             name -- name of PSI node'''
             self.name = name
-            self.setAttributeNS(None, u'name', name)
+            self.setAttribute(u'name', name)
 
         def _removeByName(self, childList, name):
             '''Removes unwanted child nodes by name
 
             Arguments:
             childlist -- list of specific nodes
-            child -- specific child node'''
+            name -- specific child node'''
             for i in childList:
                 if i.getAttributeNS(None, u'name') == name:
                     childList.remove(i)
             childlist -- list of specific nodes
             child -- specific child node'''
             for i in childList:
-                if i.getAttributeNS(None, u'name') == name:
-                    return i
+                if i.getAttributeNS(None, u'name') == name: return i
         
     class Ref:
 
             Arguments:
             ref -- reference to another PSI node'''
             self.ref = ref
-            self.setAttributeNS(None, u'ref', ref)
+            self.setAttribute(u'ref', ref)
             
     class Class:
 
             Arguments:
             Class -- A node charateristics are inherited from'''
             self.parentClass = Class
-            self.setAttributeNS(None, u'class', Class)
+            self.setAttribute(u'class', Class)
 
     class NCR(Name, Ref, Class):
 
             Arguments:
             start -- a PSI node's start time'''
             self.start = start
-            self.setAttributeNS(None, u'start', start)
+            self.setAttribute(u'start', start)
 
         def setEnd(self, end):
             '''Sets the end attribute of a PSI node
             Arguments:
             end -- a PSI node's end time'''
             self.end = end
-            self.setAttributeNS(None, u'end', end)
+            self.setAttribute(u'end', end)
             
     class Match:
 
             Arguments:
             match -- a value a PSI node must match'''
             self.match = match
-            self.setAttributeNS(None, u'match', match)
+            self.setAttribute(u'match', match)
             
     class State:
 
             
             Arguments:
             state -- a PSI node's state (default: "planned")'''
-            rl = ('planned', 'readlock', 'writelock', 'nolock')
+            av = ('planned', 'readlock', 'writelock', 'nolock')
             msg = '''value must be string "planned", "readlock", 
                 "writelock", or "nolock"'''
-            self._attchecker(u'state', state, msg, rl)          
+            self._attchecker(u'state', state, msg, av)          
 
     class AT:
 
             
             Arguments:
             type -- a PSI node's type (default: "read")'''
-            rl = ('read', 'write', 'create', 'delete', 'acl')
+            av = ('read', 'write', 'create', 'delete', 'acl')
             msg = '''value must be string "read", "write", "create" 
                     "delete", or "acl"'''
             ## Raise error if unacceptable value entered
-            self._attchecker(u'type', type, msg, rl)
+            self._attchecker(u'type', type, msg, av)
 
     class IfBase:
 
 
         def removeLinks(self):
             '''Removes all child fields'''
-            self.removeChildren(self.links)            
+            self.removeChildren(self.links)
+
+    class CollectionBase:
+
+        nodeName = u'psi:collection'
         
+        ## Placeholders for child elements
+        collections = []
+
+        def addCollection(self, name, Class=None, ref=None):
+            '''Creates and adds a collection to a PSI structure node
+                
+            Arguments:
+            name -- the name of the collection
+            Class -- the class of the collection (default: None)
+            ref -- reference to another node (default: None)'''
+            node = Collection(name, Class, ref)
+            if self.hasChildNodes():
+                if self.collections:
+                    self.insertBefore(node, self.collections[-1].nextSibling)
+                elif self.filters:
+                    self.insertBefore(node, self.filters[-1].nextSibling)
+                elif self.metadata:
+                    self.insertBefore(node, self.metadata.nextSibling)
+                else: self.insertBefore(node, self.firstChild)
+            else: self.appendChild(node)
+            ## Add to collections list
+            self.collections.append(node)
+    
+        def getCollectionByName(self, name):
+            '''Retrieves a collection
+    
+            Arguments:
+            name -- name of collection'''
+            return self._getByName(self.collections, name)        
+    
+        def removeCollectionByName(self, name):
+            '''Removes a collection
+    
+            Arguments:
+            name -- name of collection to be removed'''
+            self._removeByName(self.collections, name)
+    
+        def removeCollections(self):
+            '''Removes all collections'''
+            self.removeChildren(self.collections)         
+            
     class ResourceBase(StructureBase):
 
         '''Base class for PSI resource nodes'''
         def removeTextNodes(self):
             '''Removes all text nodes'''
             self.removeChildren(self.textnodes)            
+
+
+class Psi(Base, Ent.CollectionBase):
+
+    '''Creates the root of a PSI document'''
+
+    nodeName = u'psi:psi'
+    ## PSI namespace
+    namespace = u'urn:psilib:PSI:0:4:core'    
+
+    def __init__(self):
+        Base.__init__(self, self.nodeName)
+        self.setAttribute(u'xmlns:psi', self.namespace)       
+        
     
+class Collection(Ent.CollectionBase, Ent.StructureBase):
+
+    '''Class for building PSI collection nodes'''
     
-class Collection(Ent.StructureBase):
-
-    '''Class for building PSI collection nodes'''    
-
-    nodeName = u'psi:collection'
-    ## Placeholders for child elements
-    collections, resources = [], []
-
-    def addCollection(self, name, Class=None, ref=None):
-        '''Creates and adds a collection to a PSI structure node
-            
-        Arguments:
-        name -- the name of the collection
-        Class -- the class of the collection (default: None)
-        ref -- reference to another node (default: None)'''
-        node = Collection(name, Class, ref)
-        if self.hasChildNodes():
-            if self.collections:
-                self.insertBefore(node, self.collections[-1].nextSibling)
-            elif self.filters:
-                self.insertBefore(node, self.filters[-1].nextSibling)
-            elif self.metadata:
-                self.insertBefore(node, self.metadata.nextSibling)
-            else: self.insertBefore(node, self.firstChild)
-        else: self.appendChild(node)
-        ## Add to collections list
-        self.collections.append(node)
-
-    def getCollectionByName(self, name):
-        '''Retrieves a collection
-
-        Arguments:
-        name -- name of collection'''
-        return self._getByName(self.collections, name)        
-
-    def removeCollectionByName(self, name):
-        '''Removes a collection
-
-        Arguments:
-        name -- name of collection to be removed'''
-        self._removeByName(self.collections, name)
-
-    def removeCollections(self):
-        '''Removes all collections'''
-        self.removeChildren(self.collections)        
+    resources = []           
 
     def addResource(self, name, Class=None, ref=None):
         '''Creates and adds a resource to a PSI structure node
             
         Arguments:
         ws -- the whitespace attribute'''
-        rl = (u'default', u'preserve')
+        av = (u'default', u'preserve')
         msg = 'value must be string "default" or "preserve"'
         ## Ensure proper value is used
-        self.whitespace = ws
-        if ws not in rl: raise AttributeError, msg
-        else: self.setAttributeNS(None, u'xml:space', ws)
+        self._attchecker(u'xml:space', ws, msg, av)
           
         
 class Resource(Ent.ResourceBase):
         Class -- the class of the parameter (default: None)
         ref -- the next filter in a parameter (default: None)'''
         node = Parameter(name, Class=None, ref=None)
+        ## Make sure parameter is last but before result or exception elements
         if self.hasChildNodes():
             if self.parameters:
                 self.insertBefore(node, self.parameters[-1].nextSibling)
         Class -- the class of the result (default: None)
         ref -- reference to another node (default: None)'''
         node = Result(name, Class=None, ref=None)
+        ## Ensure result is inserted between any parameters or exceptions
         if self.hasChildNodes():
             if self.results:
                 self.insertBefore(node, self.results[0])
         Class -- the class of the exception (default: None)
         ref -- reference to another node (default: None)'''
         node = Exception(name, Class=None, ref=None)
+        ## Exceptions are always last
         self.appendChild(node)
         ## Add to exceptions list
         self.exceptions.append(node)
             
         Arguments:
         req -- sets if a parameter is required'''
-        rl = ('true', 'false', 'optional')
+        av = ('true', 'false', 'optional')
         msg = 'value must be string "true", "false", or "optional"'
-        self._attchecker(u'required', req, msg, rl)     
+        self._attchecker(u'required', req, msg, av)     
 
 
 class Result(Ent.ResourceBase):
         Class -- verification mechanism
         ref -- node to which access rule applies'''
         node = Access(type, Class, ref)
-        ## Ensure proper order is maintained
+        ## Ensure access rules come first
         if self.hasChildNodes():
             if self.firstChild.tagName == u'psi:time':
                 try: self.insertBefore(node, self.firstChild.nextSibling)
         type -- sets sort order
         ref -- sets node sort order is defined against (default: None)'''
         node = Sort(type, ref)
+        ## Ensure sort falls before all other children of filter
         if self.hasChildNodes():
             if self.sorts:
                 self.insertBefore(node, self.sorts[0])
         Class -- class of action
         ref -- node to which action applies'''
         node = Action(type, Class, ref)
+        ## Ensure rules action comes after sort rules and before version rules
         if self.hasChildNodes():
             if self.actions:
                 self.insertBefore(node, self.actions[0])
         type -- type of versioning
         mark -- sets how versions of a node are indicated (default: None)'''
         node = Version(type, mark)
+        
         self.appendChild(node)
         ## Add to versions list
         self.versions.append(node)
             
         Arguments:
         type -- type of right (default: deny)'''
-        rl = ('grant', 'deny')
+        av = ('grant', 'deny')
         msg = '''value must be string "grant" or "deny"'''
         ## Ensure correct value
-        self._attchecker(u'type', type, msg, rl)      
+        self._attchecker(u'type', type, msg, av)      
 
 
 class Right(Base, Ent.AT):
             
         Arguments:
         type -- type of sorting order (default: seq)'''
-        rl = ('root', 'seq', 'choice', 'par')
+        av = ('root', 'seq', 'choice', 'par')
         msg = '''value must be string "root", "seq", "choice", or "par"'''
-        self._attchecker(u'type', type, msg, rl)
+        self._attchecker(u'type', type, msg, av)
 
     
 class If(Base, Ent.Match):
         Arguments:
         value -- the condition evaluated'''
         self.value = value
-        self.setAttributeNS(None, u'value', value)
+        self.setAttribute(u'value', value)
         
 
 class Action(Base, Ent.Ref, Ent.Class, Ent.IfBase, Ent.TimeBase):
             
         Arguments:
         type -- type of action'''
-        rl = ('read', 'write', 'create', 'delete', 'jump',
+        av = ('read', 'write', 'create', 'delete', 'jump',
               'pass', 'pause', 'stop')
         msg = '''value must be string "read", "write", "create" 
                 "delete", "jump", "pass", "pause", or "stop"'''
-        self._attchecker(u'type', type, msg, rl)     
+        self._attchecker(u'type', type, msg, av)     
 
 
 class Time(Base, Ent.SE):
             
         Arguments:
         type -- the time measurement'''
-        rl = ('month', 'week', 'day', 'hour', 'min', 'sec', 'mil')
+        av = ('month', 'week', 'day', 'hour', 'min', 'sec', 'mil')
         msg = '''value must be string "month", "week", "day" 
                 "hour", "min", "sec", or "mil"'''
-        self._attchecker(u'type', type, msg, rl)        
+        self._attchecker(u'type', type, msg, av)        
 
     def setLength(self, length):
         '''Sets the length of time
         Arguments:
         length -- the length of the type of time'''
         self.length = length
-        self.setAttributeNS(None, u'length', length)        
+        self.setAttribute(u'length', length)        
 
     def setLoop(self, loop):
         '''Sets how many times a PSI node should loop
         Arguments:
         loop -- how many times a PSI node should loop'''
         self.loop = loop
-        self.setAttributeNS(None, u'loop', loop)    
+        self.setAttribute(u'loop', loop)    
 
     
 class Version(Base):
             
         Arguments:
         type -- type of version control action'''
-        rl = ('replace', 'fork', 'archive', 'stop')
+        av = ('replace', 'fork', 'archive', 'stop')
         msg = '''value must be string "replace", "fork", "day" 
                 "archive", or "stop"'''
-        self._attchecker(u'type', type, msg, rl)
+        self._attchecker(u'type', type, msg, av)
 
     def setMark(self, mark):
         '''Sets how new versions of a node are indicated
             
         Arguments:
         mark -- sets how versions of a node are indicated'''
-        rl = ('seq', 'start', 'end')
+        av = ('seq', 'start', 'end')
         msg = '''value must be string "seq", "start", or "end"'''
-        self._attchecker(u'mark', mark, msg, rl)
+        self._attchecker(u'mark', mark, msg, av)
 
 
 class Change(Base, Ent.Match):
         
         Arguments:
         type -- the tie breaker in a version conflict'''
-        rl = ('name', 'class', 'ref', 'state', 'action', 'start', 'end')
+        av = ('name', 'class', 'ref', 'state', 'action', 'start', 'end')
         msg = '''value must be string "name", "class", "ref"
                 "state", "action", "start", or "end"'''
-        self._attchecker(u'type', type, msg, rl)  
+        self._attchecker(u'type', type, msg, av)  
 from som import *
 
 def testSom():
-    '''Test if SOM is functioning properly.'''
+    '''Test if all of SOM is functioning properly'''
+    d = Root()
+    p = Psi()
     e = Collection('test', 'test', 'test')
+    p.appendChild(e)
     e.addFilter('test', 'test', 'test')
     e.filters[0].addAction('read', 'test', 'test')
     e.filters[0].addAccess('grant', 'test', 'test')
     e.resources[0].addResult('test3')
     e.setMetadata()
     e.addCollection('test3')
-    print e        
+    d.appendChild(p)
+    print d       
 
 if __name__ == '__main__': testSom()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.