Ticket #198: class_definition_reverse_lookup.diff

File class_definition_reverse_lookup.diff, 6.6 KB (added by nick, 11 months ago)

Patch that stores a reverse lookup for class definitions in AMF3

  • pyamf/tests/test_amf3.py

     
    728728        self.assertFalse(is_ref) 
    729729        self.assertTrue(isinstance(class_def, amf3.ClassDefinition)) 
    730730        self.assertTrue(class_def.getClass(), Spam) 
     731        self.assertTrue(class_def.klass, Spam) 
    731732        self.assertTrue(class_def.name, 'abc.xyz') 
    732733        self.assertEquals(class_def.encoding, amf3.ObjectEncoding.STATIC) 
    733734 
    734735        self.assertTrue(class_def in self.context.classes) 
     736        self.assertTrue(id(class_def) in self.context.rev_classes) 
    735737 
    736738        self.context.classes.remove(class_def) 
    737739        self.buf.write('\x0fabc.xyz') 
  • pyamf/amf3.py

     
    658658        pyamf.BaseContext.clear(self) 
    659659 
    660660        self.strings = [] 
     661 
    661662        self.classes = [] 
     663        self.rev_classes = {} 
    662664        self.class_defs = {} 
     665        self.rev_class_defs = {} 
     666 
    663667        self.legacy_xml = [] 
     668        self.rev_legacy_xml = {} 
    664669 
    665670    def getString(self, ref): 
    666671        """ 
     
    676681        try: 
    677682            return self.strings[ref] 
    678683        except IndexError: 
    679             raise pyamf.ReferenceError("String reference %d not found" % ref) 
     684            raise pyamf.ReferenceError, "String reference %d not found" % ref 
    680685 
    681686    def getStringReference(self, s): 
    682687        """ 
     
    691696        try: 
    692697            return self.strings.index(s) 
    693698        except ValueError: 
    694             raise pyamf.ReferenceError("Reference for string %r not found" % s) 
     699            raise pyamf.ReferenceError, "Reference for string %r not found" % s 
    695700 
    696701    def addString(self, s): 
    697702        """ 
     
    705710        @rtype: C{int} 
    706711        @return: The reference index. 
    707712        """ 
     713        if not isinstance(s, basestring): 
     714            raise TypeError 
     715 
    708716        if len(s) == 0: 
    709717            # do not store empty string references 
    710718            raise ValueError, "Cannot store a reference to an empty string" 
     
    728736        try: 
    729737            return self.classes[ref] 
    730738        except IndexError: 
    731             raise pyamf.ReferenceError("Class reference %d not found" % ref) 
     739            raise pyamf.ReferenceError, "Class reference %d not found" % ref 
    732740 
    733741    def getClassDefinitionReference(self, class_def): 
    734742        """ 
    735743        Return class definition reference. 
    736744 
    737         @type class_def: L{ClassDefinition} 
     745        @type class_def: L{ClassDefinition} or C{instance} or C{class} 
    738746        @param class_def: The class definition reference to be found. 
    739747        @raise ReferenceError: The reference could not be found. 
    740748        @return: The reference to C{class_def}. 
    741749        @rtype: C{int} 
    742750        """ 
    743         if not isinstance(class_def, ClassDefinition) and isinstance(class_def, (type, types.ClassType)): 
     751        if not isinstance(class_def, ClassDefinition): 
     752            if isinstance(class_def, (type, types.ClassType)): 
     753                try: 
     754                    return self.rev_class_defs[class_def] 
     755                except KeyError: 
     756                    raise pyamf.ReferenceError("Reference for class definition for %s not found" % 
     757                        class_def) 
     758            elif isinstance(class_def, (types.InstanceType, types.ObjectType)): 
     759                try: 
     760                    return self.class_defs[class_def.__class__] 
     761                except KeyError: 
     762                    raise pyamf.ReferenceError("Reference for class definition for %s not found" % 
     763                        class_def.__class__) 
     764 
     765            raise TypeError, 'unable to determine class for %r' % class_def 
     766        else: 
    744767            try: 
    745                 return self.class_defs[class_def.__class__] 
    746             except KeyError: 
    747                 raise pyamf.ReferenceError("Reference for class %s not found" % 
    748                     class_def.__class__) 
     768                return self.rev_class_defs[id(class_def)] 
     769            except ValueError: 
     770                raise pyamf.ReferenceError, "Reference for class %s not found" % kl 
    749771 
    750         try: 
    751             return self.classes.index(class_def) 
    752         except ValueError: 
    753             raise pyamf.ReferenceError("Reference for class %s not found" % 
    754                 class_def.__class__) 
    755  
    756772    def addClassDefinition(self, class_def): 
    757773        """ 
    758774        Creates a reference to C{class_def}. 
    759775        """ 
    760776        try: 
    761             return self.classes.index(class_def) 
    762         except ValueError: 
     777            return self.rev_class_defs[id(class_def)] 
     778        except KeyError: 
    763779            self.classes.append(class_def) 
     780            idx = len(self.classes) - 1 
     781 
     782            self.rev_classes[id(class_def)] = idx 
    764783            self.class_defs[class_def.__class__] = class_def 
     784            self.rev_class_defs[id(class_def.__class__)] = idx 
    765785 
    766             return len(self.classes) - 1 
     786            return idx 
    767787 
    768788    def getLegacyXML(self, ref): 
    769789        """ 
     
    793813        @rtype: C{int} 
    794814        """ 
    795815        try: 
    796             return self.legacy_xml.index(doc) 
    797         except ValueError: 
     816            return self.rev_legacy_xml[id(doc)] 
     817        except KeyError: 
    798818            raise pyamf.ReferenceError, "Reference for document %r not found" % doc 
    799819 
    800820    def addLegacyXML(self, doc): 
     
    810830        @return: The reference to C{doc}. 
    811831        """ 
    812832        try: 
    813             return self.legacy_xml.index(doc) 
    814         except ValueError: 
     833            return self.rev_legacy_xml[id(doc)] 
     834        except KeyError: 
    815835            self.legacy_xml.append(doc) 
    816836 
    817             return len(self.legacy_xml) - 1 
     837            idx = len(self.legacy_xml) - 1 
     838            self.rev_legacy_xml[id(doc)] = idx 
    818839 
     840            return idx 
     841 
    819842    def __copy__(self): 
    820843        return self.__class__() 
    821844 
     
    11611184        # Unsupported types go first 
    11621185        ((types.BuiltinFunctionType, types.BuiltinMethodType,), 
    11631186            "writeUnsupported"), 
    1164         ((lambda x: x == pyamf.Undefined,), "writeUndefined"), 
     1187        ((lambda x: x is pyamf.Undefined,), "writeUndefined"), 
    11651188        ((bool,), "writeBoolean"), 
    11661189        ((int,long), "writeInteger"), 
    11671190        ((float,), "writeNumber"), 
     
    15621585 
    15631586            self._writeInteger(ref | class_def.encoding << 2 | REFERENCE_BIT << 1 | REFERENCE_BIT) 
    15641587            self._writeString(class_def.name) 
     1588        else: 
     1589            class_def = self._getClassDefinition(obj) 
    15651590 
    15661591        if class_def.encoding in (ObjectEncoding.EXTERNAL, ObjectEncoding.PROXY): 
    15671592            obj.__writeamf__(DataOutput(self))