docs: def Upgrade(self, aff4_class):
      """Upgrades this object to the type specified.
  
      AFF4 Objects can be upgraded on the fly to other type - As long as the new
      type is derived from the current type. This feature allows creation of
      placeholder objects which can later be upgraded to the fully featured
      object.
  
      Note: It is not allowed to downgrade an object if that would result in a
      loss of information (since the new object has a smaller schema). This method
      tries to store the new object with its new attributes and will fail if any
      attributes can not be mapped.
  
      Args:
         aff4_class: A string representing the new class.
  
      Returns:
         an instance of the new class with all the same attributes as this current
         object.
  
      Raises:
         ValueError: When the object to upgrade is locked.
         AttributeError: When the new object can not accept some of the old
         attributes.
         InstantiationError: When we cannot instantiate the object type class.
      """
      _ValidateAFF4Type(aff4_class)
  
      # We are already of the required type
      if self.__class__ == aff4_class:
        return self
  
      # Check that we have the right type.
      if not isinstance(aff4_class, type):
        raise InstantiationError("aff4_class=%s must be a type" % aff4_class)
      if not issubclass(aff4_class, AFF4Object):
        raise InstantiationError(
            "aff4_class=%s must be a subclass of AFF4Object." % aff4_class)
  
      # It's not allowed to downgrade the object
      if isinstance(self, aff4_class):
        # TODO(user): check what we should do here:
        #                 1) Nothing
        #                 2) raise
        #                 3) return self
        # Option 3) seems ok, but we need to be sure that we don't use
        # Create(mode='r') anywhere where code actually expects the object to be
        # downgraded.
        return self
  
      # NOTE: It is possible for attributes to become inaccessible here if the old
      # object has an attribute which the new object does not have in its
      # schema. The values of these attributes will not be available any longer in
      # the new object - usually because old attributes do not make sense in the
      # context of the new object.
  
      # Instantiate the class
      result = aff4_class(
          self.urn,
          mode=self.mode,
          clone=self,
          parent=self.parent,
          token=self.token,
          age=self.age_policy,
          object_exists=self.object_exists,
          follow_symlinks=self.follow_symlinks,
          aff4_type=self.aff4_type,
          mutation_pool=self.mutation_pool,
          transaction=self.transaction)
      result.symlink_urn = self.urn
      result.Initialize()
  
      return result