Returns a list of `Event`s detected from differences in state
        between the current snapshot and the Kindle Library.

        `books` and `progress` attributes will be set with the latest API
        results upon successful completion of the function.

        Returns:
            If failed to retrieve progress, None
            Else, the list of `Event`s

def detect_events(self, max_attempts=3):
        """Returns a list of `Event`s detected from differences in state
        between the current snapshot and the Kindle Library.

        `books` and `progress` attributes will be set with the latest API
        results upon successful completion of the function.

        Returns:
            If failed to retrieve progress, None
            Else, the list of `Event`s
        """
        # Attempt to retrieve current state from KindleAPI
        for _ in xrange(max_attempts):
            try:
                with KindleCloudReaderAPI\
                        .get_instance(self.uname, self.pword) as kcr:
                    self.books = kcr.get_library_metadata()
                    self.progress = kcr.get_library_progress()
            except KindleAPIError:
                continue
            else:
                break
        else:
            return None

        # Calculate diffs from new progress
        progress_map = {book.asin: self.progress[book.asin].locs[1]
                                                for book in self.books}
        new_events = self._snapshot.calc_update_events(progress_map)

        update_event = UpdateEvent(datetime.now().replace(microsecond=0))
        new_events.append(update_event)

        self._event_buf.extend(new_events)
        return new_events