This method should be called to ensure all cached attributes
        are in sync with the metadata at runtime.
        This happens because attributes could store mutable objects and be
        modified outside the scope of this class.
        The most common idiom that isn't automagically caught is mutating a list
        or dictionary. Lets say 'user' object have an attribute named 'friends'
        containing a list, calling 'user.friends.append(new_friend)' only get the
        attribute, Wrapper isn't aware that the object returned was modified
        and the cached data is not updated.

def update(self):
        """
        This method should be called to ensure all cached attributes
        are in sync with the metadata at runtime.
        This happens because attributes could store mutable objects and be
        modified outside the scope of this class.
        The most common idiom that isn't automagically caught is mutating a list
        or dictionary. Lets say 'user' object have an attribute named 'friends'
        containing a list, calling 'user.friends.append(new_friend)' only get the
        attribute, Wrapper isn't aware that the object returned was modified
        and the cached data is not updated.
        """
        for key, value in self.__dict__.iteritems():
            key = self._compose(key)
            if self._validate_key(key):
                if not self.obj.hasAttr(key):
                    pm.addAttr(self.obj, ln=key, dt="string")
                self.obj.attr(key).set(encode(value))