Changeset 115

Show
Ignore:
Timestamp:
04/21/02 13:47:10 (6 years ago)
Author:
sholloway
Message:

Unified XMLBuilder architecture, allowing for delegate building of Objectified nodes.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/RBFoundation/RBFoundation/XMLBuilder.py

    r94 r115  
    5858        pass 
    5959 
     60    def _xmlChildFactory(self, owner, parent, namespace, node, attributes): 
     61        return None 
     62 
    6063#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    6164 
     
    6871 
    6972    def _GetElementFactory(self, owner, element, namespace, node, attributes): 
    70         raise self.e_no_class_registered, '%s %s' % (namespace, node) 
     73        raise KeyError, '%s: %s %s' % (self.e_no_class_registered, namespace, node) 
    7174 
    7275    def _GetOwner(self): 
  • trunk/RBFoundation/RBFoundation/XMLClassBuilder.py

    r98 r115  
    4242#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4343 
    44 class XMLClassBuilder(XMLBuilder.XMLBuilder):  
     44class ModuleByNamespaceMixin(object): 
     45    def _GetModuleClass(self, namespace, node): 
     46        # Simple construction to convert an XML namespace and node to a python import 
     47        return ('%s.%s' % (namespace, node), node) 
     48 
     49        ## Another plausable import scheme would be.  However, I don't care for the 
     50        ## directory structure that this creates; but, since this is an arbitrary 
     51        ## opinion...  You can do whatever you please.  =) 
     52        ## return (namespace, node) 
     53 
     54#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     55 
     56class ModuleByDictionaryMixin(object): 
     57    ModuleNamespaces = {} 
     58 
     59    def AddModuleNamespaces(self, dictModuleNamespaces): 
     60        # Did they send us a real change? 
     61        if dictModuleNamespaces: 
     62            # Are we working on the class dictionary? 
     63            if self.ModuleNamespaces is ModuleByDictionaryMixin.ModuleNamespaces: 
     64                # If so, lets get an instance copy 
     65                self.ModuleNamespaces = self.ModuleNamespaces.copy() 
     66            # And now update with what they gave us 
     67            self.ModuleNamespaces.update(dictModuleNamespaces) 
     68  
     69    def _GetModuleClass(self, namespace, node): 
     70        try: 
     71            # Try returning the entry in the dictionary 
     72            return '%s.%s' % (self.ModuleNamespaces[namespace], node), node 
     73        except KeyError: 
     74            try: 
     75                # Try asking the "next" class in line via super 
     76                self.__super._GetModuleClass 
     77            except AttributeError: 
     78                # Oops... there didnt seem to be a next class in line 
     79                raise KeyError, 'Could not find class for %r' % ((namespace, node),) 
     80            else: 
     81                # Ok, there is a next class in line, and their errors are their own 
     82                return self.__super._GetModuleClass(namespace, node) 
     83 
     84ModuleByDictionaryMixin._ModuleByDictionaryMixin__super = super(ModuleByDictionaryMixin) 
     85   
     86#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     87 
     88class XMLClassBuilderMixin(XMLBuilder.XMLBuilder):  
    4589    seperator = '.' 
    46     Build = XMLBuilder.XMLBuilder.Parse 
    47     BuildFile = XMLBuilder.XMLBuilder.ParseFile 
    48  
    49     def _GetModuleClass(self, namespace, node): 
    50         return ('%s.%s' % (namespace, node), node) 
     90    _CachedElementFactories = {} 
    5191 
    5292    def _GetElementFactory(self, owner, parent, namespace, node, attributes): 
    5393        result = None 
    54  
    5594        if self._elements: 
    5695            # Try to get a factory from the parent 
    57             factory = getattr(self._elements[-1], '_xmlChildFactory', None) 
    58             result = factory and factory(owner, parent, namespace, node, attributes) 
    59  
     96            result = self._elements[-1]._xmlChildFactory(owner, parent, namespace, node, attributes) 
    6097        if not result: 
    61             strModule, strClass = self._GetModuleClass(namespace, node) 
    62             module = __import__(strModule, globals(), {}, [strClass]) 
    63             result = getattr(module, strClass) 
    64  
     98            # Otherwise, try to load it from the disk 
     99            result = self._LoadModule(self._GetModuleClass(namespace, node)) 
     100        elif isinstance(result, tuple): 
     101            # Instead of returning a factory, they returned a way to find the factory 
     102            # So, lets find it 
     103            result = self._LoadModule(result) 
    65104        return result 
    66105 
     106    def _LoadModule(self, tupleModuleClass): 
     107        result = self._CachedElementFactories.get(tupleModuleClass, None) 
     108        if not result: 
     109            # Import the module 
     110            module = __import__(tupleModuleClass[0], globals(), {}, [tupleModuleClass[1]]) 
     111            # Get the class factory 
     112            result = getattr(module, tupleModuleClass[1]) 
     113            # Cache this class factory 
     114            self._CachedElementFactories[tupleModuleClass] = result 
     115        return result 
     116 
     117#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     118 
     119class XMLClassBuilderByNamespace(ModuleByNamespaceMixin, XMLClassBuilderMixin):  
     120    Build = XMLClassBuilderMixin.Parse 
     121    BuildFile = XMLClassBuilderMixin.ParseFile 
     122 
     123class XMLClassBuilderByDictionary(ModuleByDictionaryMixin, XMLClassBuilderMixin):  
     124    Build = XMLClassBuilderMixin.Parse 
     125    BuildFile = XMLClassBuilderMixin.ParseFile 
     126 
     127class XMLClassBuilderByBoth(ModuleByDictionaryMixin, ModuleByNamespaceMixin, XMLClassBuilderMixin):  
     128    Build = XMLClassBuilderMixin.Parse 
     129    BuildFile = XMLClassBuilderMixin.ParseFile 
     130 
     131XMLClassBuilder = XMLClassBuilderByBoth 
     132 
  • trunk/RBFoundation/RBFoundation/XMLObjectify.py

    r112 r115  
    3131##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3232 
     33"""Builds a Python object tree from an XML stream. 
     34 
     35History 
     36 
     37    XMLObjectify found its conceptual roots in a similar tool created by David Mertz <mertz@gnosis.cx> 
     38    named objectify.py, which is still extremely useful and can still be found at http://gnosis.cx .   
     39    Futher history of his module can be found there.  Now I say conceptual roots can be found there,  
     40    because the present state of XMLObjectify represents a 2nd rewrite of that code to serve the new  
     41    requirements.   
     42 
     43    One new requirement is the ability to "build" a python object tree by instantiating python classes 
     44    from modules found on disk, and subsequently raising an exception if a suitable module is not found. 
     45    (Raising that exception is one of the essential reasons for the 2nd rewrite, as I did not factor it 
     46    in the 1st.)  This requirement provides the Foundation of the Skinning framework found in the  
     47    RuneBlade distribution, as well as XMLClassBuilder module 
     48""" 
     49 
    3350#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3451#~ Imports                                            
     
    4259#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4360 
    44 class _Objectified(object): 
     61class ObjectifiedXML(XMLBuilder.XMLBuilderObjectBase): 
    4562    _default_attributes = {} 
    4663  
     
    6279            if result: 
    6380                return result 
    64         return object.__getattribute__(self, name) 
     81        return XMLBuilder.XMLBuilderObjectBase.__getattribute__(self, name) 
    6582 
    6683    def __setattr__(self, name, value): 
     
    7087            self._attributes[xmlName] = value 
    7188        else: 
    72             return object.__setattr__(self, name, value) 
     89            return XMLBuilder.XMLBuilderObjectBase.__setattr__(self, name, value) 
    7390         
    7491    def __delattr__(self, name): 
     
    7996                del self._attributes[xmlName] 
    8097                return 
    81         object.__delattr__(self, name) 
     98        XMLBuilder.XMLBuilderObjectBase.__delattr__(self, name) 
    8299        return 
    83100         
     
    104121 
    105122    def __repr__(self): 
    106         result = object.__repr__(self) 
     123        result = XMLBuilder.XMLBuilderObjectBase.__repr__(self) 
    107124        return '<%s %r %r>' % (result[1:-1], self.__namespace__, self.__node__) 
    108125         
     
    111128        return self._elements[-1] 
    112129 
    113     def _addObjectifiedElement(self, object): 
    114         return self._addElement(object.__namespace__, object.__node__, object) 
     130    def _addObjectifiedElement(self, obj): 
     131        return self._addElement(obj.__namespace__, obj.__node__, object) 
    115132 
    116133    def _addNewElement(self, namespace, node, **attributes): 
    117134        namespace = namespace or self.__namespace__ 
    118         return self._addElement(namespace, node, _Objectified(self, self, namespace, node, attributes)) 
     135        return self._addElement(namespace, node, ObjectifiedXML(self, self, namespace, node, attributes)) 
    119136         
    120137    def _addData(self, data): 
     
    151168    _childrenToPrettyXML = _childrenToXML 
    152169     
    153     def _xmlInitStarted(self): 
    154         pass #print '%r started' % self 
    155  
    156     def _xmlInitComplete(self): 
    157         pass #print '%r complete' % self 
    158  
    159170#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    160171     
    161172class Objectifier(XMLBuilder.XMLBuilder):  
    162     objectified_class = _Objectified  
     173    objectified_class = ObjectifiedXML 
    163174    Objectify = XMLBuilder.XMLBuilder.Parse 
    164175    ObjectifyFile = XMLBuilder.XMLBuilder.ParseFile 
     
    167178        return self.objectified_class 
    168179 
     180#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     181#~ Functional Definitions  
    169182#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    170183 
     
    173186ObjectifyFile = _defaultObjectifier.ObjectifyFile 
    174187 
    175 if __name__ == '__main__': 
     188#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     189#~ Testing  
     190#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     191 
     192def _Test_XMLObjectify(): 
    176193    from pprint import pprint 
    177194    xml = open('test_objectify.xml', 'r') 
     
    181198    print ' ~ ' * 20 
    182199    pprint (obj._toXML()) 
     200 
     201#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     202 
     203if __name__=='__main__': 
     204    print "Testing..." 
     205    _Test_XMLObjectify()  
     206    print "Test complete." 
     207 
     208 
  • trunk/RBJabber/RBJabber/Client.py

    r110 r115  
    4545#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4646 
    47 class JabberNode(XMLObjectify._Objectified): 
     47class JabberNode(XMLObjectify.ObjectifiedXML): 
    4848    def __init__(self, client, parent, namespace, node, attributes): 
    4949        self._client = weakref.proxy(client) 
    50         XMLObjectify._Objectified.__init__(self, client, parent, namespace, node, attributes) 
     50        XMLObjectify.ObjectifiedXML.__init__(self, client, parent, namespace, node, attributes) 
    5151 
    5252    def Content(self): 
  • trunk/RBJabber/RBJabber/JabberConnection.py

    r102 r115  
    117117 
    118118    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    119     #~ Private Methods  
     119    #~ XMLBuilding Private Methods  
    120120    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    121121 
     
    128128 
    129129    def _GetElementFactory(self, owner, parent, namespace, node, attributes): 
    130         result = self.JabberNodeMap.get((namespace, node), self.DefaultJabberNode) 
     130        result = None 
     131 
     132        if self._elements: 
     133            # Try to get a factory from the parent 
     134            result = self._elements[-1]._xmlChildFactory(owner, parent, namespace, node, attributes) 
     135 
     136        if not result: 
     137            # Otherwise, try to load it from the disk 
     138            result = self.JabberNodeMap.get((namespace, node), self.DefaultJabberNode) 
     139 
    131140        return result 
     141 
     142    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     143    #~ Smart Select Private Methods  
     144    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    132145 
    133146    def _NeedsRead(self): return self._socket and 1 
     
    143156        self._sendData = self._sendData[nSent:] 
    144157 
     158    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     159    #~ Other Private Methods  
     160    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     161 
    145162    def _SendXMLImmediate(self, xmlData): 
    146163        self._sendData += xmlData 
  • trunk/RBSkinning/RBSkinning/SkinObject.py

    r66 r115  
    3535#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    3636 
     37from Foundation.XMLBuilder import XMLBuilderObjectBase 
    3738import SkinContext 
    3839import weakref 
     
    4647#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4748 
    48 class SkinObject(object): 
     49class SkinObject(XMLBuilderObjectBase): 
    4950    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    5051    #~ Constants / Variables / Etc.  
  • trunk/RBSkinning/RBSkinning/XMLSkinner.py

    r113 r115  
    3636 
    3737from xml.parsers.expat import ParserCreate, ExpatError 
    38 from Foundation.XMLBuilder import XMLBuilder 
     38from Foundation.XMLClassBuilder import XMLClassBuilderByDictionary 
    3939from Foundation.WeakBind import BindCallable 
    4040import SkinContext 
     
    4747#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    4848 
    49 class XMLSkinner(XMLBuilder): 
    50     DefaultSkinNamespaces = { 
     49class XMLSkinner(XMLClassBuilderByDictionary): 
     50     
     51    ModuleNamespaces = XMLClassBuilderByDictionary.ModuleNamespaces.copy() 
     52    ModuleNamespaces.update({ 
     53        ## Long names 
    5154        'http://namespaces.runeblade.com/skin': 'Foundation.Skinning.skin', 
    5255        'http://namespaces.runeblade.com/wxPythonSkin': 'Foundation.Skinning.wxPythonSkin', 
    5356        'http://namespaces.runeblade.com/xmlPython': 'Foundation.Skinning.xmlPython', 
    5457        'http://namespaces.runeblade.com/wxogl': 'Foundation.Skinning.wxOGLSkin', 
    55         } 
    56     _CachedElementFactories = {} 
     58 
     59        ## Short names 
     60        'skin': 'Foundation.Skinning.skin', 
     61        'wxPythonSkin': 'Foundation.Skinning.wxPythonSkin', 
     62        'xmlPython': 'Foundation.Skinning.xmlPython', 
     63        'wxogl': 'Foundation.Skinning.wxOGLSkin', 
     64        }) 
    5765     
    5866    def __init__(self, mapSupportedSkinNamespaces={}, rootPath=''): 
    5967        self.rootPath = rootPath 
    60         XMLBuilder.__init__(self) 
    61         self.SkinNamespaces = self.DefaultSkinNamespaces.copy() 
    62         self.SkinNamespaces.update(mapSupportedSkinNamespaces) 
     68        XMLClassBuilderByDictionary.__init__(self) 
     69        self.AddModuleNamespaces(mapSupportedSkinNamespaces) 
    6370 
    64     def _GetModuleClass(self, namespace, node): 
    65         try: 
    66             return '%s.%s' % (self.SkinNamespaces[namespace], node), node 
    67         except KeyError: 
    68             raise KeyError, 'Could not find class for %r' % ((namespace, node),) 
     71    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    6972 
    70     def _GetElementFactory(self, owner, parent, namespace, node, attributes): 
    71         strModule, strClass = self._GetModuleClass(namespace, node) 
    72         result = self._CachedElementFactories.get((strModule, strClass), None) 
    73         if not result: 
    74             module = __import__(strModule, globals(), {}, [strClass]) 
    75             result = getattr(module, strClass) 
    76             self._CachedElementFactories[(strModule, strClass)] = result 
    77         return result 
    78      
    7973    def _PreParse(self): 
    8074        parser = ParserCreate('ASCII', self._seperator)