Coverage for ion/core/object/gpb_wrapper : 86.69%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
|
#!/usr/bin/env python @file ion/core/object/gpb_wrapper.py @brief Wrapper for Google Protocol Buffer Message Classes. These classes are the lowest level of the object management stack @author David Stuebe @author TODO: """
sha1_to_hex, ObjectUtilException, create_type_identifier, get_gpb_class_from_type_id, OOIObjectError
# Get the object decorators used on all wrapper methods!
""" Data descriptor (like a property) for passing through GPB enums from the Wrapper. """
raise AttributeError('Can not delete a Wrapper property for an ION Object field')
""" Metaclass that automatically generates subclasses of Wrapper with corresponding enums and pass-through properties for each field in the protobuf descriptor. """
# Cache the custom-built classes
else:
# Also set the enum descriptors _after_ building the class so the descriptor doesn't go away #if hasattr(descriptor, 'enum_values_by_name'): # for k,v in descriptor.enum_values_by_name.iteritems(): # setattr(clsType, k, WrappedEnum(v.number))
# Finally allow the instantiation to occur, but slip in our new class type
''' A Class for GPB Enum access '''
""" Instantiate a class with properties to get GPB Enum Values """
pass self.field_type = "TYPE_FIXED32" self.field_type = "TYPE_FIXED64" self.field_type = "TYPE_GROUP" self.field_type = "TYPE_INT64" self.field_type = "TYPE_FLOAT" self.field_type = 'TYPE_SFIXED32' self.field_type = 'TYPE_SFIXED64' else: raise OOIObjectError('Unknow field type "%s" in property constructor.' % field_type)
raise NotImplementedError('Abstract base class for property wrappers: __get__')
raise NotImplementedError('Abstract base class for property wrappers: _get_backdoor')
raise NotImplementedError('Abstract base class for property wrappers: __set__')
raise NotImplementedError('Abstrat base class for property wrappers: __delete__')
""" Data descriptor (like a property) for passing through GPB properties of Type Message from the Wrapper. """
# This may be the result we were looking for, in the case of a simple scalar field
log.error(wrapper.Debug()) raise OOIObjectError('Can not get message (composite) property - %s -in a wrapper which is invalidated.' % self.name) # This may be the result we were looking for, in the case of a simple scalar field
log.error(wrapper.Debug()) raise OOIObjectError('Can not set message (composite) property - %s - in a wrapper which is invalidated.' % self.name)
raise OOIObjectError('This object wrapper is read only!')
raise AttributeError('Can not delete a Wrapper property for an ION Object field')
""" Data descriptor (like a property) for passing through GPB properties of Type Repeated Scalar from the Wrapper. """
log.error(wrapper.Debug()) raise OOIObjectError('Can not get repeated scalar property - %s - in a wrapper which is invalidated.'% self.name) # This may be the result we were looking for, in the case of a simple scalar field
raise AttributeError('Assignment is not allowed for field name "%s" of type Repeated Scalar in ION Object' % self.name)
raise AttributeError('Can not delete a Wrapper property for an ION Object field')
""" Data descriptor (like a property) for passing through GPB properties of Type Repeated Composite from the Wrapper. """
log.error(wrapper.Debug()) raise OOIObjectError('Can not "get" from a repeated composite property - %s - in a wrapper which is invalidated.' % self.name)
# This may be the result we were looking for, in the case of a simple scalar field
log.error(wrapper.Debug()) raise OOIObjectError( 'Can not get_backdoor from a repeated composite property - %s - in a wrapper which is invalidated.' % self.name)
# This may be the result we were looking for, in the case of a simple scalar field
raise AttributeError( 'Assignment is not allowed for field name - "%s" - of type Repeated Composite in ION Object' % self.name)
raise AttributeError('Can not delete a Wrapper property for an ION Object field')
""" Data descriptor (like a property) for passing through GPB properties of Type Scalar from the Wrapper. """
# This may be the result we were looking for, in the case of a simple scalar field log.error(wrapper.Debug()) raise OOIObjectError('Can not get scalar property - %s - in a wrapper which is invalidated.' % self.name)
log.error(wrapper.Debug()) raise OOIObjectError('Can not set scalar property - %s -in a wrapper which is invalidated.' % self.name)
# Set this object and it parents to be modified
""" Class used to count the number of recursive calls to commit a data structure """
""" Metaclass that automatically generates subclasses of Wrapper with corresponding enums and pass-through properties for each field in the protobuf descriptor.
This approach is generally applicable to wrap data structures. It is extremely powerful! """
# Cache the custom-built classes
else: # Check that the object we are wrapping is a Google Message object raise OOIObjectError('Wrapper init argument must be an instance of a GPB message')
# Get the class name
# Now setup the properties to map through to the GPB object
# Add the enums of the message class
# Add the property wrappers for each of the fields of the message
# Add any enums for the fields the message contains
field_enum=field_enum) else: field_enum=field_enum) else: field_enum=field_enum) else: field_enum=field_enum)
# Set the object type: version=mti._VERSION) else: version=1) # the obj_type can now be used for adding special methods to the Wrapper for certain types
# Special methods for certain object types:
raise AttributeError(\ '''Cant add properties to the ION object wrapper for object Class "%s".\n''' '''Unknown property name - "%s"; value - "%s"''' % (self._GPBClass, k, v))
# Finally allow the instantiation to occur, but slip in our new class type
#--------------------------------------------------------------# # Attach specialized methods to object class dictionaries here # #--------------------------------------------------------------#
self._set_parents_modified()
def copy_link(self,link):
log.error(link.Debug()) log.error(self.Debug()) raise OOIObjectError('Can not copy_link from an object that is not a link!')
# Allow the DataType enum to be accessible by this Wrapper... #------------------------------------------------------------------------# # Additional helper methods for attaching specialized attributes/methods # #------------------------------------------------------------------------# # Get a handle to the data_type field from the variable class
# Add the enum definitions from the data_type field (can only be one - DataType)
# clsDict['SetValue'] = _get_attribute_values # clsDict['SetValues'] = _get_attribute_values
''' A Wrapper class for intercepting access to protocol buffers message fields. For instance, in the example below I can create a wrapper which is read-only.
To make the wrapper general - apply to more than one kind of protobuffer - we can not use descriptors (properties) to transparently intercept a get or set request because they are class attributes - shared between all instances of the wrapper class. If we add properties each time we create a wrapper instance for a new kind of protobuf, new properties will be added to all wrapper instances.
The solution I can up with is clunky! Override the __getattribute__ and _setattr__ method to preemptively check a list of fields to get from the protocol buffer message. If the key is in the list get/set the deligated protocol buffer rather than the wrapper class. The problem is that now we can not use the default get/set to initialize our own class or get the list of fields!
Organization: The meat of the class is at the top - Init and class methods are at the top along with overrides for __getattribute__ and __setattr__ which are the heart of the wrapper.
Below that are all of the methods of protobuffers exposed by the wrapper.
TODO: What about name conflicts between wrapper methods and GPB Fields?
'''
""" Initialize the Wrapper class and set up it message type.
"""
""" The gpbMessage is the data object which this instance of wrapper provides proxy access to. This wrapper controls both the message object and its nested child objects in the case of a composite message. Each child in the nested object is returned as a wrapped object all of which are subordinate to the wrapper for the root of the composite message. """
""" A reference to the root object wrapper for this protobuffer A composit protobuffer object may return """
""" Used to determine whether the wrapper is a currently valid object in the version framework. Invalid states can be created when old references to an object remain after a differnt version is checked out - similar to having a file or directory open that does not exist in the currently checked out branch of a source repository. """
# This filed now comes from the metaclass #self._gpb_type = None """ The Type ID object for the wrapped object of this class """
""" Used in _load_element to create a proxy object. The bytes are not loaded parsed until the object is needed! """
""" A list of all the other wrapper objects which link to me """
""" A list of my child link wrappers """
""" A container for all the wrapper objects which are rewrapped, derived from a root object wrapper """
""" The name for this object - the SHA1 if it is already hashed or the object counter value if it is still in the workspace. """
""" Is this wrapper object modified or commited """
""" Set this to be a read only wrapper! Used for commit objects and a history checkout... it is only set in the root object """
""" Need to carry a reference to the repository I am in. """
""" To avoid invalidating during when there is a hash conflict in the workspace - set the twin... """
# Hack to prevent setting properties in a class instance
#frame = sys._getframe(2) #frames = [] #for i in range(6): # frames.append(frame) # frame = frame.f_back #print 'Name: %s, Caller names: ' % type(self), [frame.f_code.co_name for frame in frames]
def _create_object(cls, msgtype): """ This is a convience method to create unattached wrapper objects. Generally this method should not be used - it is a hook for testing. """
def Invalid(self):
pass
#log.debug('Invalidating self:\n%s' % self.Debug())
#log.debug('Invalidating self with Other:\n%s \n\n' % other.Debug())
log.error(self.Debug()) raise OOIObjectError('It is unexpected to try and invalidate an object with a new source a second time')
log.error(self.Debug()) raise OOIObjectError( 'It is unexpected to try and invalidate an object which already has an alternate source')
log.error(self.Debug()) raise OOIObjectError('Can not invalidate by passing a wrapper from another repository')
log.error('Error while invalidating self - other is invalid too!\nSelf: %s\nOther: %s'% (self.Debug(), other.Debug())) raise OOIObjectError('Can not invalidate self with other when other is already invalid')
else: #log.debug('Invalidating self:\n%s' % self.Debug())
#if self._invalid:
# If we are doing an invalidate to other...
# If this is a straight invalidation - clear the derived wrappers if root
# Source must always be set to self or another gpb_wrapper object!
# Do not clear root or Repository
raise OOIObjectError('The back door property getter failed!')
# Make sure to get the derive object not what it links to!
else:
def ObjectClass(self):
def DESCRIPTOR(self):
def Root(self): """ Access to the root object of the nested GPB object structure """
def IsRoot(self): """ Is this wrapped object the root of a GPB Message? GPBs are also tree structures and each element must be wrapped """
def ObjectType(self): """ Could just replace the attribute with the capital name? """
def GPBMessage(self): """ If this is a proxy object which references its serialized value load it! """
def Repository(self):
def DerivedWrappers(self):
def _get_myid(self):
def _set_myid(self, value):
def _get_parent_links(self): """ A list of all the wrappers which link to me """
def _set_parent_links(self, value): """ A list of all the wrappers which link to me """
def _get_child_links(self): """ A list of all the wrappers which I link to """
def _set_child_links(self, value): """ A list of all the wrappers which I link to """ self._child_links = value
def _get_readonly(self):
def _set_readonly(self, value):
def _get_modified(self):
def _set_modified(self, value):
def SetLinkByName(self, linkname, value):
def GetLink(self, linkname):
raise OOIObjectError('The field "%s" is not a link!' % linkname)
def InParents(self, value): ''' Check recursively to make sure the object is not already its own parent! ''' raise OOIObjectError('Can not test lineage of object that is not a root object')
def SetStructureReadOnly(self): """ Set these objects to be read only """
except KeyError: # we're just setting things read only, don't worry if we couldn't get part of it. # this is intentionally happening in ingestion pass
def SetStructureReadWrite(self): """ Set these object to be read write! """
self.ReadOnly = False for link in self.ChildLinks: child = self.Repository.get_linked_object(link) child.SetStructureReadWrite()
def RecurseCommit(self, structure): """ Recursively build up the serialized structure elements which are needed to commit this wrapper and reset all the links using its CAS name. """
# Should this error if called on a non root object? raise OOIObjectError('Can not call Recurse Commit on a non root object wrapper.')
(local_cnt, type(self), len(self.ChildLinks), len(structure), self.Modified))
# This object is already committed!
# Create the Structure Element in which the binary blob will be stored
log.error('Link in child links is invalid!') log.debug('Current Wrapper: %s' % self.Debug()) log.debug('Invalid Link %s' % link.Debug())
# Test to see if it is already serialized! #child_se = repo.index_hash.get(link.key, None)
#log.debug('Setting child Link: %s' % str(child_se)) # Set the links is leaf property
else: # if isleaf set, type set, and the key is an actual SHA1 - we don't need to recurse into it or do anything, really. pass else:
# Determine whether this is a leaf node else:
# Save the link info as a convience for sending!
#se.key = sha1hex(se.value)
# Structure element wrapper provides for setting type!
# Calculate the sha1 from the serialized value and type! # Sha1 is a property - not a method...
# Determine whether I am a leaf else:
# Done setting up the Structure Element # It does not matter if we are replacing an existing se with the same key - the content - including the child links must be identical!
# This will be true for any object which is not a core object such as a commit # We don't want to worry about what is in the workspace - that is the repositories job. # if I am currently in the work space the commited version of me should be too! # Remove my old name
# Now deal with some nastyness # Possible DAG structure created by hash conflict - two wrappers of the same type with the same value in one data structure # If this is true we have just done a lot of extra work to create the Structure element - but there is no way to know before creating it!
# Get the other object with the same name that is already committed...
#print "Self Plinks:",self.ParentLinks #print "Other Plinks:",other.ParentLinks
#print "Other Plinks After:",other.ParentLinks
# Invalidate ourself
else: # Now add it back the workspace under the new name
# Test to see if we need to set MyId - don't mess up the case where self now points to another source which is already commited.
# Set the key value for parent links! # This will only be reached once for a given child object. Set all parents # now and the child will return as unmodified when the other parents ask it # to recurse commit.
#log.debug('Current Wrapper: %s' % self.Debug())
#cnt = 1 #for link in self.ParentLinks: # log.debug('Parrent Link # %d \n%s' % (cnt, link.Debug())) # cnt += 1
log.error('Link in parent links is invalid!') log.debug('Current Wrapper: %s' % self.Debug()) log.debug('Invalid Link %s' % link.Debug())
def FindChildLinks(self): """ Find all of the links in this composit structure All of the objects worked on in this method are raw proto buffers messages! """
# For each field in the protobuffer message # if the field is a composite - another message # Get the field of type message
# If it is a repeated container type else:
# IF it is a standard message field else: # if it is an optional field which is not initialized # it can not hold any links!
else:
def AddParentLink(self, link): #if self.Invalid:
else:
def _rewrap(self, gpbMessage): ''' Factory method to return a new instance of wrapper for a gpbMessage from self - used for access to composite structures, it has all the same shared variables as the parent wrapper '''
# Check the root wrapper objects list of derived wrappers
# Else make a new one...
# Add it to the list of objects which derive from the root wrapper
def _set_parents_modified(self): """ This method recursively changes an objects parents to a modified state All links are reset as they are no longer hashed values """
# Be clear about what we are doing here! # If it has already been modified we are done. else:
# Get the repository
# When you hit the commit ref - stop! # The commit is no longer really your parent!
else: # Tricky - set the message directly and call modified! #link.GPBMessage.key = self.MyId #link._set_parents_modified()
def __eq__(self, other):
def __ne__(self, other): # Can't just say self != other_msg, since that would infinitely recurse. :)
""" Since str is used in debugging it should never return an exception - no matter the state of the wrapper object """
''' # Too complex - don't do things that might raise errors in str method! if self._gpb_type == LINK_TYPE: key = self._gpbMessage.key try: key = sha1_to_hex(self._gpbMessage.key) except struct.error, er: pass msg = '\nkey: %s \ntype { %s }' % (key, self._gpbMessage.type) else: msg = '\n' +self._gpbMessage.__str__() '''
return 'GPB NO STRING!'
#log.critical('HOLY SHIT STILL HERE!')
else:
""" Since Debug is for debugging it should never return an exception - no matter the state of the wrapper object """
pass
# This is dangerous - this can result in an exception loop! else:
# DO NOT UNCOMMENT THE FOLLOWING LINES unless you know what you are doing and you will recomment them! # They are more expensive than you can possibly imagine #output += 'Wrapper current value:\n' #output += str(self) + '\n' else:
def IsInitialized(self): """Checks if the message is initialized.
Returns: The method returns True if the message is initialized (i.e. all of its required fields are set). """ return self.GPBMessage.IsInitialized()
def SerializeToString(self): """Serializes the protocol message to a binary string.
Returns: A binary string representation of the message if all of the required fields in the message are set (i.e. the message is initialized).
Raises: message.EncodeError if the message isn't initialized. """
except message.EncodeError, ex: log.info(ex) raise OOIObjectError( 'Could not serialize object - likely due to unset required field in a core object: %s' % str(self))
def ParseFromString(self, serialized): """Clear the message and read from serialized."""
# Do not use the GPBMessage method - it will recurse!
def ListSetFields(self): """Returns a list of (FieldDescriptor, value) tuples for all fields in the message which are not empty. A singular field is non-empty if IsFieldSet() would return true, and a repeated field is non-empty if it contains at least one element. The fields are ordered by field number"""
def IsFieldSet(self, field_name): # Get the raw GPB field except AttributeError, ex: raise OOIObjectError('The "%s" object definition does not have a field named "%s"' %\ (str(self.ObjectClass), field_name))
else:
else:
log.warn('HasField is depricated because the name is confusing. Use IsFieldSet') return self.IsFieldSet(field_name)
def ClearField(self, field_name):
#if not GPBMessage.IsFieldSet(field_name): # # Nothing to clear # return
# Get the raw GPB field except AttributeError, ex: raise OOIObjectError('The "%s" object definition does not have a field named "%s"' %\ (str(self.ObjectClass), field_name))
del self.DerivedWrappers[GPBField] # Nothing to do - just clear the field. It can not contain a link
# Nothing to be done for scalar fields - just clear it.
#Now clear the field # Set this object and it parents to be modified
def _clear_derived_message(self): """ Helper method for ClearField """ # Remove this link from the list of parents
# This is the only one, remove it as a child
# Recursively remove all
#def HasExtension(self, extension_handle): # return self.GPBMessage.HasExtension(extension_handle)
#def ClearExtension(self, extension_handle): # return self.GPBMessage.ClearExtension(extension_handle)
def ByteSize(self): """Returns the serialized size of this message. Recursively calls ByteSize() on all contained messages. """ return self.GPBMessage.ByteSize()
except KeyError, ke: log.debug('KeyError during get field: %s' % ke)
fid.write('''%s{Field Name - "%s" : Field Type - %s : %s} \n''' % ( offset, name, field.field_type, 'KeyError - object not found in local workbench')) continue
except AttributeError, ae: log.debug('Unset CasRef Field Name: %s: Catching Attribute Error: %s ' % (name, ae)) val = 'Field Value - None' except Exception, ex: log.exception('Unexpected state in a WrappedMessageProperty.') fid.write('%s Exception while printing field name - %s, Exception - %s\n' % (offset, name, ex)) continue
except Exception, ex: log.exception('Unexpected state in a WrappedRepeatedCompositeProperty.') fid.write('%s Exception while printing field name - %s, Exception - %s\n' % (offset, name, ex)) continue
val = '# of Values - %i: Field Values - "%s"... truncated at 20 values!' % ( len(scalars), str(scalars[:20])) else:
else:
except Exception, ex: log.exception('Unexpected Exception in PPrint Wrapper!') fid.write('Exception! %s' % ex)
finally:
""" This class is only for use with containers.RepeatedCompositeFieldContainer It is not needed for repeated scalars! """
# Be careful - this is a hard link raise OOIObjectError('The Container Wrapper is only for use with Repeated Composite Field Containers')
''' print 'GPB INVALID CW' print 'func name', func_name, func print 'args', args print 'kwargs', kwargs ''' log.error(wrapper.Debug()) raise OOIObjectError('Can not access Invalidated Container Wrapper Object in function "%s"' % func_name)
def factory(cls, wrapper, gpbcontainer): #print cls, type(wrapper), type(gpbcontainer) #objhash = hash(gpbcontainer)
# Add it to the list of objects which derive from the root wrapper
def Root(self):
def Invalid(self):
self._source = source
def __setitem__(self, key, value): """ Sets the item in the specified position. """
raise OOIObjectError('To set an item in a repeated field container, the value must be a Wrapper')
else: raise OOIObjectError( 'It is illegal to set a value of a repeated composite field unless it is a CASRef - Link')
raise OOIObjectError('To set an item in a repeated field container, the value must be a Wrapper')
else: raise OOIObjectError( 'It is illegal to set a value of a repeated composit field unless it is a CASRef - Link')
def __getitem__(self, key): """Retrieves item by the specified key."""
def GetLink(self, key):
def GetLinks(self):
def __len__(self): """Returns the number of elements in the container."""
def __ne__(self, other): """Checks if another instance isn't equal to this one."""
return not self._gpbcontainer == other._gpbcontainer
def __eq__(self, other): """Compares the current instance with another one."""
if self is other: return True
if not isinstance(other, self.__class__): raise OOIObjectError('Can only compare repeated composite fields against other repeated composite fields.') return self._gpbcontainer == other._gpbcontainer
def __str__(self): """Need to improve this!"""
# Composite specific methods: def add(self):
def __getslice__(self, start, stop): """Retrieves the subset of items from between the specified indices."""
# Does it make sense to return a list?
def __delitem__(self, key): """Deletes the item at the specified position."""
def __delslice__(self, start, stop): """Deletes the subset of items from between the specified indices."""
def __iter__(self):
else:
#n = min(10, length)
# Print all repeated composites #log.debug('Printing field # %d' % i)
except AttributeError, ae: log.debug('Attribute error while calling pprint on repeated composite: %s' % ae) fid.write('''%s%s# %i - %s \n''' % (offset, name, i, 'Repeated Link Not Set!'))
except KeyError, ke: log.debug('KeyError while calling pprint on repeated composite: %s' % ke) fid.write('''%s%s# %i - %s \n''' % (offset, name, i, 'Repeated Link object not found!!'))
except Exception, ex: log.exception('Unexpected Exception while calling pprint on repeated composite') fid.write('''%s%s# %i - Exception: %s \n''' % (offset, name, i, ex))
#if length > 10: # msg += offset + '... truncated printing list at 10 items!\n'
except Exception, ex: log.exception('Unexpected Exception in PPrint CompositeContainer!') fid.write('Exception! %s' % ex)
finally:
""" This class is only for use with containers.RepeatedCompositeFieldContainer It is not needed for repeated scalars! """
# Be careful - this is a hard link raise OOIObjectError('The Container Wrapper is only for use with Repeated Composit Field Containers')
def factory(cls, wrapper, gpbcontainer): # Check the root wrapper objects list of derived wrappers before making a new one #objhash = hash(gpbcontainer)
# Add it to the list of objects which derive from the root wrapper
''' print 'GPB INVALID CW' print 'func name', func_name, func print 'args', args print 'kwargs', kwargs ''' log.error(wrapper.Debug()) raise OOIObjectError( 'Can not access Invalidated Scalar Container Wrapper Object in function "%s"' % func_name)
def Root(self):
def Invalid(self):
self._source = source
def append(self, value): """Appends an item to the list. Similar to list.append()."""
def insert(self, key, value): """Inserts the item at the specified position. Similar to list.insert()."""
def extend(self, elem_seq): """Extends by appending the given sequence. Similar to list.extend()."""
def remove(self, elem): """Removes an item from the list. Similar to list.remove()."""
def __getslice__(self, start, stop): """Retrieves the subset of items from between the specified indices."""
def __len__(self): """Returns the number of elements in the container."""
def __getitem__(self, key): """Retrieves the subset of items from between the specified indices."""
def __setitem__(self, key, value): """Sets the item on the specified position."""
def __setslice__(self, start, stop, values): """Sets the subset of items from between the specified indices."""
def __delitem__(self, key): """Deletes the item at the specified position."""
def __delslice__(self, start, stop): """Deletes the subset of items from between the specified indices."""
def __eq__(self, other): """Compares the current instance with another one."""
return True # Special case for the same type which should be common and fast. return other._gpbcontainer._values == self._gpbcontainer._values # We are presumably comparing against some other sequence type.
def __ne__(self, other): """Checks if another instance isn't equal to this one.""" # The concrete classes should define __eq__. return not self == other
def __str__(self):
def __iter__(self):
""" An error class for structure elements """
""" @brief Wrapper for the container structure element. These are the objects stored in the hashed elements table. Mostly convience methods are provided here. A set provides references to the child objects so that the content need not be decoded to find them. """
else:
def parse_structure_element(cls, blob):
log.error('The sha1 key does not match the value. The data is corrupted! \n' +\ 'Element key %s, Calculated key %s' % (sha1_to_hex(instance.key), sha1_to_hex(instance.sha1))) raise StructureElementError('Error reading serialized structure element. Sha1 value does not match.')
def sha1(self): """ Make the sha1 safe for empty contents but also type safe. Take use the sha twice so that we don't need to concatinate long strings! """ ################# ## This is the method that you can compare in Java ################# ## Get the length of the binary arrays #sha_len = 20 #type_len = self.type.ByteSize() # ## Convert to signed integer bytes #fmt = '!%db' % type_len #type_bytes = struct.unpack('!%db' % type_len , self.type.SerializeToString()) # ## Convert the sha1 of the content to signed integer bytes #c_sha_bytes = struct.unpack('!20b', sha1bin(self.value)) # ## Concatinate the the byte arrays as integers #cat_bytes = list(c_sha_bytes) + list(type_bytes) # ## Get the length of the concatination and convert to byte array #fmt = '!%db' % (type_len+sha_len) #sha_cat = struct.pack(fmt, *cat_bytes) # ##print 'sha1hex(sha_cat):',sha1hex(sha_cat) ##print 'sha1hex(sha1bin(self.value) + self.type.SerializeToString()):',sha1hex(sha1bin(self.value) + self.type.SerializeToString()) # ## Return the sha1 of the byte array #return sha1bin(sha_cat) ################# # This does the same thing much faster and shorter! #################
#@property
#@type.setter
#@property
#@value.setter
#@property #return sha1_to_hex(self._element.key)
#@key.setter
msg = '' if len(self._element.key) == 20: msg = 'Key: ' + sha1_to_hex(self._element.key) + '\n' msg = msg + 'Type: ' + str(self._element.type) + '\n' msg = msg + 'IsLeaf: ' + str(self._element.isleaf) + '\n' msg = msg + 'El Len: ' + str(self.__sizeof__()) return msg
#size = len(self._element.value) + 34 #print 'Esimtate: ', size #print 'GPB Size: ', self._element.ByteSize()
|