class Registration(object):
    """An object that registers a znode with ZooKeeper."""

    def __init__(self, zk, path, data=None, state=True):
        # Create our logger
        self.log = logging.getLogger('%s.Registration.%s' % (__name__, path))

        # Set our local variables
        self._zk = zk
        self._path = path
        self._state = state

        # Store both encdoed-string and decoded-dict versions of our 'data'
        # for comparison purposes later.
        self._data = data
        self._encoded_data = funcs.encode(data)
        self._decoded_data = funcs.decode(self._encoded_data)

        # Make sure that we have a watcher on the path we care about
        self._watcher = Watcher(self._zk,
                                path=self._path,
                                watch_children=False,
                                callback=self._update)

    def data(self):
        """Returns live node data from Watcher object."""
        return self._watcher.data()

    def get(self):
        """Returns live node information from Watcher object."""
        return self._watcher.get()

    def set_data(self, data):
        """Sets self._data.

        Args:
            data: String or Dict of data to register with this object."""

        if not data == self._data:
            self._data = data
            self._encoded_data = funcs.encode(data)
            self._decoded_data = funcs.decode(self._encoded_data)
            self._update_data()

    def _update_data(self):
        try:
            self._zk.retry(self._zk.set, self._path, value=self._encoded_data)
            self.log.debug('Updated with data: %s' % self._encoded_data)
        except kazoo.exceptions.NoAuthError, e:
            self.log.error('No authorization to set node.')
            pass
        except Exception, e:
            self.log.error('Received exception. Moving on, will re-attempt '
                           'when Watcher notifies us of a state change: %s '
                           % e)
            pass