Changeset 5595


Ignore:
Timestamp:
10/08/09 16:38:03 (10 years ago)
Author:
pjkersha
Message:

Tidying etree implementation + includ etree utils from ndg.security.common.utils.etree

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.saml/saml/xml/etree.py

    r5589 r5595  
    3737    import cElementTree, ElementTree 
    3838 
    39 from ndg.security.common.saml import SAMLObject, Conditions, Assertion, \ 
    40     Attribute, AttributeStatement, AttributeValue, XSStringAttributeValue, \ 
    41     XSGroupRoleAttributeValue, Response, AttributeQuery, Subject, NameID, \ 
    42     Issuer, SAMLVersion, Response, Status, StatusCode 
    43      
    44 from ndg.security.common.saml.xml import XMLObject, IssueInstantXMLObject, \ 
    45     XMLObjectParseError, SAMLConstants 
    46  
    47 from ndg.security.common.utils.etree import QName, getLocalName, prettyPrint 
    48  
    49 class SAMLElementTree(XMLObject): 
    50     """Implement methods generic to all ElementTree SAML object representations 
    51     """        
    52 #    def parse(self, source): 
    53 #        """Read in the XML from source 
    54 #        @type source: basestring/file 
    55 #        @param source: file path to XML file or file object 
    56 #        """ 
    57 #        tree = ElementTree.parse(source) 
    58 #        self.__elem = tree.getroot() 
    59 #         
    60 #        return self.__elem 
    61 #    
    62     @staticmethod      
    63     def serialize(elem): 
    64         """Serialise element tree into string""" 
    65         return cElementTree.tostring(elem) 
    66     
     39from saml import SAMLObject, Conditions, Assertion, Attribute, \ 
     40    AttributeStatement, AttributeValue, XSStringAttributeValue, \ 
     41    Response, AttributeQuery, Subject, NameID, Issuer, SAMLVersion, Response, \ 
     42    Status, StatusCode, XSGroupRoleAttributeValue 
     43     
     44from saml.xml import XMLObject, IssueInstantXMLObject, XMLObjectParseError, \ 
     45    SAMLConstants 
     46 
     47# Generic Helper classes 
     48class QName(ElementTree.QName): 
     49    """Extend ElementTree implementation for improved attribute access support 
     50    """  
     51    def __init__(self, namespaceURI, tag=None, prefix=None): 
     52        ElementTree.QName.__init__(self, namespaceURI, tag=tag) 
     53         
     54        if tag: 
     55            self.namespaceURI = namespaceURI 
     56            self.localPart = tag 
     57        else: 
     58            self.namespaceURI = QName.getNs(self.text) 
     59            self.localPart = QName.getLocalName(self.text) 
     60             
     61        self.prefix = prefix 
     62 
     63    getNs = staticmethod(lambda elem: elem.tag.split('}')[0][1:]) 
     64    getLocalName = staticmethod(lambda elem: elem.tag.rsplit('}',1)[-1]) 
     65     
     66#    @staticmethod 
     67#    def getNs(tag): 
     68#        return tag.split('}')[0][1:] 
     69# 
     70#    @staticmethod 
     71#    def getLocalName(tag): 
     72#        return tag.rsplit('}',1)[-1] 
     73     
     74    def _getPrefix(self): 
     75        return self.__prefix 
     76 
     77    def _setPrefix(self, value): 
     78        self.__prefix = value 
     79     
     80    prefix = property(_getPrefix, _setPrefix, None, "Prefix") 
     81 
     82    def _getLocalPart(self): 
     83        return self.__localPart 
     84     
     85    def _setLocalPart(self, value): 
     86        self.__localPart = value 
     87         
     88    localPart = property(_getLocalPart, _setLocalPart, None, "LocalPart") 
     89 
     90    def _getNamespaceURI(self): 
     91        return self.__namespaceURI 
     92 
     93    def _setNamespaceURI(self, value): 
     94        self.__namespaceURI = value 
     95   
     96    namespaceURI = property(_getNamespaceURI, _setNamespaceURI, None,  
     97                            "Namespace URI'") 
     98     
     99     
     100def prettyPrint(*arg, **kw): 
     101    '''Lightweight pretty printing of ElementTree elements''' 
     102     
     103    # Keep track of namespace declarations made so they're not repeated 
     104    declaredNss = [] 
     105     
     106    _prettyPrint = PrettyPrint(declaredNss) 
     107    return _prettyPrint(*arg, **kw) 
     108 
     109 
     110class PrettyPrint(object): 
     111    def __init__(self, declaredNss): 
     112        self.declaredNss = declaredNss 
     113     
    67114    @staticmethod 
    68     def prettyPrint(elem): 
    69         """Basic pretty printing separating each element on to a new line""" 
    70         return prettyPrint(elem) 
    71  
    72  
     115    def estrip(elem): 
     116        ''' Just want to get rid of unwanted whitespace ''' 
     117        if elem is None: 
     118            return '' 
     119        else: 
     120            # just in case the elem is another simple type - e.g. int -  
     121            # wrapper it as a string 
     122            return str(elem).strip() 
     123         
     124    def __call__(self, elem, indent='', html=0, space=' '*4): 
     125        '''Most of the work done in this wrapped function - wrapped so that 
     126        state can be maintained for declared namespace declarations during 
     127        recursive calls using "declaredNss" above'''   
     128        strAttrib = ''.join([' %s="%s"' % (att, attVal)  
     129                             for att, attVal in elem.attrib.items()]) 
     130         
     131        namespace = getNs(elem) 
     132        nsPrefix = ElementTree._namespace_map.get(namespace) 
     133        if nsPrefix is None: 
     134            raise KeyError('prettyPrint: missing namespace "%s" for '  
     135                           'ElementTree._namespace_map' % namespace) 
     136             
     137        tag = "%s:%s" % (nsPrefix, getLocalName(elem)) 
     138         
     139        # Put in namespace declaration if one doesn't already exist 
     140        # FIXME: namespace declaration handling is wrong for handling child 
     141        # element scope 
     142        if namespace in self.declaredNss: 
     143            nsDeclaration = '' 
     144        else: 
     145            nsDeclaration = ' xmlns:%s="%s"' % (nsPrefix, namespace) 
     146            self.declaredNss.append(namespace) 
     147             
     148        result = '%s<%s%s%s>%s' % (indent, tag, nsDeclaration, strAttrib,  
     149                                   PrettyPrint.estrip(elem.text)) 
     150         
     151        children = len(elem) 
     152        if children: 
     153            for child in elem: 
     154                declaredNss = self.declaredNss[:] 
     155                _prettyPrint = PrettyPrint(declaredNss) 
     156                result += '\n'+ _prettyPrint(child, indent=indent+space)  
     157                 
     158            result += '\n%s%s</%s>' % (indent, 
     159                                       PrettyPrint.estrip(child.tail), 
     160                                       tag) 
     161        else: 
     162            result += '</%s>' % tag 
     163             
     164        return result 
     165 
     166 
     167# ElementTree SAML wrapper classes 
    73168class ConditionsElementTree(Conditions, IssueInstantXMLObject): 
    74169    """ElementTree based XML representation of Conditions class 
     
    162257 
    163258   
    164 class AttributeStatementElementTree(SAMLElementTree): 
     259class AttributeStatementElementTree(AttributeStatement): 
    165260    """ElementTree XML representation of AttributeStatement""" 
    166261     
     
    173268                                                           attributeStatement)) 
    174269             
    175         elem = ElementTree.Element( 
    176                                 str(AttributeStatement.DEFAULT_ELEMENT_NAME)) 
    177         ElementTree._namespace_map[ 
    178             AttributeStatement.DEFAULT_ELEMENT_NAME.namespaceURI 
    179         ] = AttributeStatement.DEFAULT_ELEMENT_NAME.prefix  
     270        elem = ElementTree.Element(str(cls.DEFAULT_ELEMENT_NAME)) 
     271        ElementTree._namespace_map[cls.DEFAULT_ELEMENT_NAME.namespaceURI 
     272                                   ] = cls.DEFAULT_ELEMENT_NAME.prefix  
    180273 
    181274        for attribute in attributeStatement.attributes: 
     
    188281     
    189282 
    190 class AttributeElementTree(SAMLElementTree): 
     283class AttributeElementTree(Attribute): 
    191284    """ElementTree XML representation of SAML Attribute object.  Extend 
    192285    to make Attribute types"""  
     
    202295             
    203296        elem = ElementTree.Element(str(Attribute.DEFAULT_ELEMENT_NAME)) 
    204         ElementTree._namespace_map[ 
    205             Attribute.DEFAULT_ELEMENT_NAME.namespaceURI 
    206         ] = Attribute.DEFAULT_ELEMENT_NAME.prefix  
    207          
    208              
     297        ElementTree._namespace_map[cls.DEFAULT_ELEMENT_NAME.namespaceURI 
     298                                   ] = cls.DEFAULT_ELEMENT_NAME.prefix  
     299         
    209300        if attribute.friendlyName: 
    210             elem.set(Attribute.FRIENDLY_NAME_ATTRIB_NAME, 
    211                      attribute.friendlyName)  
     301            elem.set(cls.FRIENDLY_NAME_ATTRIB_NAME, attribute.friendlyName)  
    212302              
    213303        if attribute.name: 
    214             elem.set(Attribute.NAME_ATTRIB_NAME, attribute.name) 
     304            elem.set(cls.NAME_ATTRIB_NAME, attribute.name) 
    215305         
    216306        if attribute.nameFormat: 
    217             elem.set(Attribute.NAME_FORMAT_ATTRIB_NAME, attribute.nameFormat) 
     307            elem.set(cls.NAME_FORMAT_ATTRIB_NAME, attribute.nameFormat) 
    218308 
    219309        for attributeValue in attribute.attributeValues: 
     
    241331                            (ElementTree.Element, elem)) 
    242332 
    243         if getLocalName(elem) != Attribute.DEFAULT_ELEMENT_LOCAL_NAME: 
     333        if getLocalName(elem) != cls.DEFAULT_ELEMENT_LOCAL_NAME: 
    244334            raise XMLObjectParseError("No \"%s\" element found" % 
    245                                         Attribute.DEFAULT_ELEMENT_LOCAL_NAME) 
     335                                      cls.DEFAULT_ELEMENT_LOCAL_NAME) 
    246336             
    247337        attribute = Attribute() 
    248338             
    249         name = elem.attrib.get(Attribute.NAME_ATTRIB_NAME) 
     339        name = elem.attrib.get(cls.NAME_ATTRIB_NAME) 
    250340        if name is not None: 
    251341            attribute.name = name 
    252342             
    253         friendlyName = elem.attrib.get(Attribute.FRIENDLY_NAME_ATTRIB_NAME) 
     343        friendlyName = elem.attrib.get(cls.FRIENDLY_NAME_ATTRIB_NAME) 
    254344        if friendlyName is not None: 
    255345            attribute.friendlyName = friendlyName 
    256346             
    257         nameFormat = elem.attrib.get(Attribute.NAME_FORMAT_ATTRIB_NAME)     
     347        nameFormat = elem.attrib.get(cls.NAME_FORMAT_ATTRIB_NAME)     
    258348        if nameFormat is not None: 
    259349            attribute.nameFormat = nameFormat 
     
    261351        for childElem in elem: 
    262352            localName = getLocalName(childElem) 
    263             if localName != AttributeValue.DEFAULT_ELEMENT_LOCAL_NAME: 
     353            if localName != cls.DEFAULT_ELEMENT_LOCAL_NAME: 
    264354                raise XMLObjectParseError('Expecting "%s" element; found ' 
    265                                     '"%s"' % 
    266                                     (AttributeValue.DEFAULT_ELEMENT_LOCAL_NAME, 
    267                                      localName)) 
     355                                          '"%s"' % 
     356                                          (cls.DEFAULT_ELEMENT_LOCAL_NAME, 
     357                                           localName)) 
    268358             
    269359            # Find XML type attribute to key which AttributeValue sub type to  
     
    290380         
    291381     
    292 class AttributeValueElementTreeBase(SAMLElementTree): 
     382class AttributeValueElementTreeBase(AttributeValue): 
    293383    """Base class ElementTree XML representation of SAML Attribute Value"""  
    294384     
     
    301391                                                           attributeValue)) 
    302392             
    303         elem = ElementTree.Element(str(AttributeValue.DEFAULT_ELEMENT_NAME)) 
    304         ElementTree._namespace_map[ 
    305             AttributeValue.DEFAULT_ELEMENT_NAME.namespaceURI 
    306         ] = AttributeValue.DEFAULT_ELEMENT_NAME.prefix 
     393        elem = ElementTree.Element(str(cls.DEFAULT_ELEMENT_NAME)) 
     394        ElementTree._namespace_map[cls.DEFAULT_ELEMENT_NAME.namespaceURI 
     395                                   ] = cls.DEFAULT_ELEMENT_NAME.prefix 
    307396 
    308397        return elem 
     
    484573 
    485574         
    486 class IssuerElementTree(SAMLElementTree, Issuer): 
     575class IssuerElementTree(Issuer): 
    487576    """Represent a SAML Issuer element in XML using ElementTree""" 
    488577     
     
    518607        if issuerFormat is None: 
    519608            raise XMLObjectParseError('No "%s" attribute found in "%s" ' 
    520                                         'element' % 
    521                                         (issuerFormat, 
    522                                          cls.DEFAULT_ELEMENT_LOCAL_NAME)) 
     609                                      'element' % 
     610                                      (issuerFormat, 
     611                                       cls.DEFAULT_ELEMENT_LOCAL_NAME)) 
    523612        issuer = Issuer() 
    524613        issuer.format = issuerFormat 
     
    528617 
    529618         
    530 class NameIdElementTree(SAMLElementTree, NameID): 
     619class NameIdElementTree(NameID): 
    531620    """Represent a SAML Name Identifier in XML using ElementTree""" 
    532621     
     
    572661                                      cls.DEFAULT_ELEMENT_LOCAL_NAME) 
    573662             
    574         format = elem.attrib.get(NameID.FORMAT_ATTRIB_NAME) 
     663        format = elem.attrib.get(cls.FORMAT_ATTRIB_NAME) 
    575664        if format is None: 
    576665            raise XMLObjectParseError('No "%s" attribute found in "%s" ' 
     
    585674 
    586675 
    587 class SubjectElementTree(SAMLElementTree, Subject): 
     676class SubjectElementTree(Subject): 
    588677    """Represent a SAML Subject in XML using ElementTree""" 
    589678     
     
    600689                                                           type(subject))) 
    601690             
    602         elem = ElementTree.Element(str(Subject.DEFAULT_ELEMENT_NAME)) 
     691        elem = ElementTree.Element(str(cls.DEFAULT_ELEMENT_NAME)) 
    603692         
    604693        ElementTree._namespace_map[cls.DEFAULT_ELEMENT_NAME.namespaceURI 
Note: See TracChangeset for help on using the changeset viewer.