Remove usage of HistoryManager and replace with simplistic Undo logic

This commit is contained in:
Xevion
2021-09-03 20:06:53 -05:00
parent 925a5517b2
commit efb1b711be
3 changed files with 32 additions and 23 deletions

View File

@@ -17,6 +17,7 @@ from tzlocal import get_localzone
# If modifying these scopes, delete the file token.json. # If modifying these scopes, delete the file token.json.
from bulk_reminders import undo from bulk_reminders import undo
from bulk_reminders.undo import IDPair
SCOPES = ['https://www.googleapis.com/auth/calendar'] SCOPES = ['https://www.googleapis.com/auth/calendar']
TIME_REGEX = re.compile(r'\d{2}:\d{2}(?:AM|PM)') TIME_REGEX = re.compile(r'\d{2}:\d{2}(?:AM|PM)')
@@ -118,14 +119,14 @@ class Event(object):
self.summary, self.start, self.end, self.description, self.status = summary, start, end, description, status self.summary, self.start, self.end, self.description, self.status = summary, start, end, description, status
@classmethod @classmethod
def from_api(cls, event: dict, history: Optional[undo.HistoryManager]) -> 'Event': def from_api(cls, event: dict, history: List[IDPair]) -> 'Event':
"""Returns a Event object from a Google API Engine item.""" """Returns a Event object from a Google API Engine item."""
undo_stage = history.exists(event.get('id')) if history is not None else -1 in_history = any(pair.eventID == event.get('id') for pair in history)
return Event(summary=event.get('summary'), return Event(summary=event.get('summary'),
start=isoparse(event['start'].get('dateTime', event['start'].get('date'))), start=isoparse(event['start'].get('dateTime', event['start'].get('date'))),
end=isoparse(event['end'].get('dateTime', event['end'].get('date'))), end=isoparse(event['end'].get('dateTime', event['end'].get('date'))),
description=event.get('description'), description=event.get('description'),
status=f'Stage {undo_stage}' if undo_stage != -1 else 'Foreign') status='Undoable' if in_history else 'Foreign')
@property @property
def body(self) -> dict: def body(self) -> dict:

View File

@@ -1,15 +1,15 @@
import logging import logging
from typing import Iterator, List from typing import Any, List, Set
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QMessageBox from PyQt5.QtWidgets import QMainWindow, QMessageBox
from bulk_reminders import api, undo from bulk_reminders import api
from bulk_reminders.api import Event from bulk_reminders.api import Event
from bulk_reminders.gui_base import Ui_MainWindow from bulk_reminders.gui_base import Ui_MainWindow
from bulk_reminders.load import LoadDialog from bulk_reminders.load import LoadDialog
from bulk_reminders.oauth import OAuthDialog from bulk_reminders.oauth import OAuthDialog
from bulk_reminders.undo import IDPair, Stage from bulk_reminders.undo import IDPair
logging.basicConfig(format='[%(asctime)s] [%(levelname)s] [%(threadName)s] %(message)s') logging.basicConfig(format='[%(asctime)s] [%(levelname)s] [%(threadName)s] %(message)s')
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
@@ -60,7 +60,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.undoButton.clicked.connect(self.undo) self.undoButton.clicked.connect(self.undo)
self.submitButton.clicked.connect(self.submit) self.submitButton.clicked.connect(self.submit)
self.history = undo.HistoryManager('history.json') self.history: List[IDPair] = []
self.historyCalendarID: str = ''
# Disable the undo button until undo stages are available # Disable the undo button until undo stages are available
if len(self.history) == 0: if len(self.history) == 0:
@@ -86,31 +87,31 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def undo(self) -> None: def undo(self) -> None:
"""Get the latest undo stage and delete all events in that stage""" """Get the latest undo stage and delete all events in that stage"""
latest = self.history.pop() logging.info(f'Deleting {len(self.history)} Events from Calendar {self.historyCalendarID}')
logging.info(f'Deleting {len(latest.events)} Events from Calendar {latest.commonCalendar}')
self.progressBar.show() self.progressBar.show()
self.progressBar.setMaximum(len(latest.events)) self.progressBar.setMaximum(len(self.history))
for i, entry in enumerate(latest.events): for i, entry in enumerate(self.history):
logging.debug(f'Deleting Event {entry.eventID}') logging.debug(f'Deleting Event {entry.eventID}')
self.calendar.service.events().delete(calendarId=entry.calendarID, eventId=entry.eventID).execute() self.calendar.service.events().delete(calendarId=entry.calendarID, eventId=entry.eventID).execute()
self.progressBar.setValue(i + 1) self.progressBar.setValue(i + 1)
self.progressBar.hide() self.progressBar.hide()
# Disable the undo button until undo stages are available # Disable the undo button until undo stages are available
self.history = []
self.undoButton.setDisabled(len(self.history) == 0) self.undoButton.setDisabled(len(self.history) == 0)
self.populate() # Refresh self.populate() # Refresh
def getForeign(self) -> Iterator[IDPair]: def getForeign(self) -> Set[Any]:
"""Returns all events currently tracked that are not stored in the undo.""" """Returns all events currently tracked that are not stored in the undo."""
undoableIDs = set(self.history.all_pairs()) foreign = {event.get('id'): event for event in self.apiEvents}
for apiEvent in self.apiEvents: undoableIDs = set(pair.eventID for pair in self.history)
pair = IDPair(calendarID=self.currentCalendarID, eventID=apiEvent['id']) return {foreign[eventID] for eventID in undoableIDs.difference(foreign.keys())}
if pair not in undoableIDs:
yield pair
def submit(self) -> None: def submit(self) -> None:
newStage = Stage(index=self.history.nextIndex(), commonCalendar=self.currentCalendarID) self.historyCalendarID = self.currentCalendarID
self.history = []
logger.info(f'Submitting {len(self.readyEvents)} events to API') logger.info(f'Submitting {len(self.readyEvents)} events to API')
self.progressBar.show() self.progressBar.show()
@@ -118,13 +119,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
for i, event in enumerate(self.readyEvents): for i, event in enumerate(self.readyEvents):
logger.debug(f'Submitting "{event.summary}" scheduled to start on {event.start.isoformat()}....') logger.debug(f'Submitting "{event.summary}" scheduled to start on {event.start.isoformat()}....')
result = self.calendar.service.events().insert(calendarId=self.currentCalendarID, body=event.body).execute() result = self.calendar.service.events().insert(calendarId=self.currentCalendarID, body=event.body).execute()
newStage.events.append(IDPair(self.currentCalendarID, result.get('id'))) self.history.append(IDPair(self.currentCalendarID, result.get('id')))
self.progressBar.setValue(i + 1) self.progressBar.setValue(i + 1)
self.undoButton.setDisabled(len(self.history) == 0)
self.readyEvents.clear() self.readyEvents.clear()
self.progressBar.hide() self.progressBar.hide()
self.history.addStage(newStage)
self.populate() self.populate()
def populate(self) -> None: def populate(self) -> None:
@@ -134,9 +135,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
events = list(self.readyEvents) events = list(self.readyEvents)
events.extend([Event.from_api(event, self.history) for event in self.apiEvents]) events.extend([Event.from_api(event, self.history) for event in self.apiEvents])
ready, undoable, stage, foreign = len(self.readyEvents), self.history.getTotal(), len(self.history), len(list(self.getForeign())) ready, undoable, foreign = len(self.readyEvents), len(self.history), len(list(self.getForeign()))
total = ready + undoable + foreign total = ready + undoable + foreign
self.eventCountLabel.setText(f'{len(self.readyEvents)} ready, {undoable} undoable in {stage} stages, {foreign} foreign ({total})') self.eventCountLabel.setText(f'{len(self.readyEvents)} ready, {undoable} undoable, {foreign} foreign ({total})')
self.eventsView.setRowCount(len(events)) self.eventsView.setRowCount(len(events))
logger.debug(f'Populating table with {self.eventsView.rowCount()} events.') logger.debug(f'Populating table with {self.eventsView.rowCount()} events.')

View File

@@ -1,6 +1,6 @@
import logging import logging
import os import os
from typing import Iterator, List from typing import Any, Iterator, List
import jsonpickle import jsonpickle
@@ -68,6 +68,13 @@ class HistoryManager(object):
self.stages.insert(0, newStage) self.stages.insert(0, newStage)
self.save() self.save()
def verify(self, calendarID: str, known_events: List[Any]) -> None:
"""Given a calendar ID and a list of events from this calendar, make sure there are no IDPairs in storage that no longer exist any more."""
pass
def collapse(self) -> None:
pass
class Stage(object): class Stage(object):
def __init__(self, index: int, commonCalendar: str) -> None: def __init__(self, index: int, commonCalendar: str) -> None: