From dd8399f2016889827c39da70b61a6644698f56fc Mon Sep 17 00:00:00 2001 From: Jacob Daniel Bennett Date: Wed, 14 Oct 2020 14:05:47 -0400 Subject: [PATCH] More generalized error statements, refactored error parsing dictionary to include got, expected, file_path, and line_num keys --- api/ECNQueue.py | 196 +++++++++++++++++++----------------------------- 1 file changed, 76 insertions(+), 120 deletions(-) diff --git a/api/ECNQueue.py b/api/ECNQueue.py index c42942d..1093734 100644 --- a/api/ECNQueue.py +++ b/api/ECNQueue.py @@ -508,28 +508,20 @@ def __editParsing(self, line: str, lineNum: int) -> dict: formattedDateTime = "" editedBy = "" - if not line.endswith(" ***\n"): - - columnNum = len(line) - 1 - errorMessage = "Expected the delimiter to end with \" ***\n\"" - - return self.__errorParsing(line, lineNum, columnNum, errorMessage) - # Parses for the author of the edit, which is located between the "*** Edited by: " and " at:" substrings - editedBy = (re.search("(?<=\*{3} Edited by: )(.*)(?= at:)", line)).group() - - # ece23 + try: + editedBy = (re.search("(?<=\*{3} Edited by: )(.*)(?= at:)", line)).group() + except: + errorMessage = "*** Edited by: [username] at: [date and time] ***\n" + return self.__errorParsing(line, lineNum, errorMessage) + try: # Parses for the date and time of the edit, which is located between the " at: " and "***\n" substrings dateTimeString = (re.search("(?<= at: )(.*)(?= \*\*\*\n)", line)).group() - except: # Returns an error message if there is no space after "at:" - - columnNum = line.find("at:") + 3 - errorMessage = "Expected a space after \"at:\" followed by the date which is followed by \" ***\n\"" - - return self.__errorParsing(line, lineNum, columnNum, errorMessage) + errorMessage = "*** Edited by: [username] at: [date and time] ***\n" + return self.__errorParsing(line, lineNum, errorMessage) # Attempts to format the date and time into utc format formattedDateTime = self.__getFormattedDate(dateTimeString) @@ -554,19 +546,20 @@ def __replyToParsing(self, line: str, lineNum: int) -> dict: repliedBy = "" #tech112 - # Checks for malformed delimiter - if not line.endswith(" ***\n"): - - columnNum = len(line) - 1 - errorMessage = "Expected the delimiter to end with \" ***\n\"" - - return self.__errorParsing(line, lineNum, columnNum, errorMessage) - # Parses for the author of the reply, which is located between the "*** Replied by: " and " at:" substrings - repliedBy = (re.search("(?<=\*{3} Replied by: )(.*)(?= at:)", line)).group() + try: + # Parses for the author of the reply, which is located between the "*** Replied by: " and " at:" substrings + repliedBy = (re.search("(?<=\*{3} Replied by: )(.*)(?= at:)", line)).group() + except: + errorMessage = "*** Replied by: [username] at: [date and time] ***\n" + return self.__errorParsing(line, lineNum, errorMessage) # Parses for the date and time of the reply, which is located between the " at: " and "***\n" substrings - dateTimeString = (re.search("(?<= at: )(.*)(?= \*\*\*\n)", line)).group() + try: + dateTimeString = (re.search("(?<= at: )(.*)(?= \*\*\*\n)", line)).group() + except: + errorMessage = "*** Replied by: [username] at: [date and time] ***\n" + return self.__errorParsing(line, lineNum, errorMessage) # Formats date to UTC formattedDateTime = self.__getFormattedDate(dateTimeString) @@ -591,18 +584,20 @@ def __statusParsing(self, line: str, lineNum: int) -> dict: updatedBy = "" # Parses for the author of the status change, which is located between the "*** Status updated by: " and " at:" substrings - updatedBy = (re.search("(?<=\*{3} Status updated by: )(.*)(?= at:)", line)).group() - - # tech 56 - if not line.endswith(" ***\n"): - - columnNum = len(line) - 1 - errorMessage = "Expected the delimiter to end with \" ***\n\"" + try: + updatedBy = (re.search("(?<=\*{3} Status updated by: )(.*)(?= at:)", line)).group() + except: + errorMessage = "*** Status updated by: [username] at: [date and time] ***\n" - return self.__errorParsing(line, lineNum, columnNum, errorMessage) + return self.__errorParsing(line, lineNum, errorMessage) # Parses for the date and time of the status change, which is located between the " at: " and "***\n" substrings - dateTimeString = re.search("(?<= at: )(.*)(?= \*\*\*\n)", line).group() + try: + dateTimeString = re.search("(?<= at: )(.*)(?= \*\*\*\n)", line).group() + except: + errorMessage = "*** Status updated by: [username] at: [date and time] ***\n" + + return self.__errorParsing(line, lineNum, errorMessage) # Formats the date to UTC formattedDateTime = self.__getFormattedDate(dateTimeString) @@ -622,85 +617,64 @@ def __userReplyParsing(self, replyContent: list, lineNumber: int) -> dict: Returns: dictionary: "type": "replyFromUser", datetime, subject, userName, userEmail, content, ccRecipients """ - formattedDateTime = "" - repliedByName = "" - repliedByEmail = "" - subject = "" - ccRecipientsList = [] + replyFromInfo = { + "type": "reply_from_user", + "datetime": "", + "from_name": "", + "from_email": "", + "cc": [], + "content": [] + } + newLineCounter = 0 endingDelimiterCount = 0 + # Delimiter information line numbers to remove from reply from user linesToRemove =[] - # Parses the section content looking for any line that starts with a metadata, also tracks the line # number with the enumerate function for lineNum, line in enumerate(replyContent): - + #Checks for a newline and breaks for loop on second occurance of a newline if line == "\n": - newLineCounter = newLineCounter + 1 - - if line.startswith("===="): - - endingDelimiterCount = endingDelimiterCount + 1 - - if endingDelimiterCount > 1: - - errorMessage = "Encountered two reply-from-user ending delimiters and expected only one" - - return self.__errorParsing(line, lineNumber + lineNum + 1, 0, errorMessage) + if newLineCounter == 2: + break elif endingDelimiterCount == 0 and lineNum == len(replyContent) - 1: - errorMessage = "Did not encounter a reply-from-user ending delimiter" + return self.__errorParsing(line, lineNumber + lineNum + 1, errorMessage) - return self.__errorParsing(line, lineNumber + lineNum + 1, 0, errorMessage) - - # Checks for lines starting with Subject, From, Date and CC - elif line.startswith("Subject: ") and newLineCounter < 2: - - # Matches everything after "Subject: " in the line - subject = (re.search("(?<=Subject: )(.*)", line)).group() - - linesToRemove.append(lineNum) - - elif line.startswith("From: ") and newLineCounter < 2: - - # Returns a list of tuples with name and email information + elif line.startswith("From: "): + # Returns a list of one tuples with a name stored in the first index of the tuple and an email stored in the second index of the tuple emailList = email.utils.getaddresses([line]) - - # The name in stored in the first index of the tuple - repliedByName = emailList[0][0] - - # The email is stored in the second index of the tuple - repliedByEmail = emailList[0][1] + replyFromInfo["from_name"] = emailList[0][0] + replyFromInfo["from_email"] = emailList[0][1] linesToRemove.append(lineNum) - elif line.startswith("Date: ") and newLineCounter < 2: - + elif line.startswith("Date: "): # Matches everything after "Date: " + try: + dateStr = (re.search("(?<=Date: )(.*)", line)).group() + except: + errorMessage = "\"Date: [datetime]\"" + return self.__errorParsing(line, lineNumber + lineNum + 1, errorMessage) - dateStr = (re.search("(?<=Date: )(.*)", line)).group() - - dateStr = "" # Formatts the date to UTC - formattedDateTime = self.__getFormattedDate(dateStr) + replyFromInfo["datetime"] = self.__getFormattedDate(dateStr) linesToRemove.append(lineNum) - elif line.startswith("Cc: ") and newLineCounter < 2: - + elif line.startswith("Cc: "): # Returns a list of tuples with email information recipientsList = email.utils.getaddresses([line]) # Parses through the cc tuple list for cc in recipientsList: - # Stores the cc information in a dictionary and appends it to the ccRecipientsList - ccRecipientsList.append( + replyFromInfo["cc"].append( {"name":cc[0], "email":cc[1]} ) @@ -712,16 +686,7 @@ def __userReplyParsing(self, replyContent: list, lineNumber: int) -> dict: replyContent.pop(lineNum) # Strips any unnecessary newlines or any delimiters frm the message content - replyContent = self.__getFormattedMessageContent(replyContent) - - replyFromInfo = { - "type": "reply_from_user", - "datetime": formattedDateTime, - "from_name": repliedByName, - "from_email": repliedByEmail, - "cc": ccRecipientsList, - "content": replyContent - } + replyFromInfo["content"] = self.__getFormattedMessageContent(replyContent) return replyFromInfo @@ -731,38 +696,29 @@ def __getFormattedMessageContent(self, messageContent: list) -> list: Returns: list: formattedMessageContent """ - # Parses looking for the reply-from-user ending delimiter adn removes the first line that contains the ending delimiter. - - - # Continually loops while looking at the first line of messageContent, removing it from messageContent - # if its a newline. Doesn't run if there is only one line in message content. + # Continually removes the first line of messageContent if it is a newline or delimiter in each iteration while len(messageContent) > 1: if messageContent[0] == "\n" or messageContent[0].startswith("***") or messageContent[0].startswith("===") : messageContent.pop(0) - else: - # Breaks the loop if the first line isn't a newline + # Breaks the loop if the first line isn't a newline or delimiter break - + + # Continually removes the last line of messageContent if it is a newline or delimiter in each iteration while len(messageContent) > 1: - # Initializes the Length of messageContent each iteration of the loop messagecontentLength = len(messageContent) - # Checks if the last line is a newline if messageContent[messagecontentLength -1] == "\n" or messageContent[messagecontentLength -1].startswith("===="): - - # Deletes the last line if it is a newline messageContent.pop(messagecontentLength - 1) - else: - # Breaks the loop if the last line isn't a newline + # Breaks the loop if the last line isn't a newline or delimiter break return messageContent - def __errorParsing(self, line: str, lineNum: int, lineColumn: int, errorMessage: str) -> dict: + def __errorParsing(self, line: str, lineNum: int, expectedSyntax: str) -> dict: """Returns a dictionary with error parse information Returns: @@ -779,17 +735,23 @@ def __errorParsing(self, line: str, lineNum: int, lineColumn: int, errorMessage: errorDictionary = { "type": "parse_error", "datetime": self.__getFormattedDate(str(datetime.datetime.now())), - "content": [] + "file_path": "", + "expected": "", + "got": "", + "line_num": 0 } - # Error message with itemm line and column numbers - errorMessage = errorMessage + " at " + str(lineNum) + ":" + str(lineColumn) + # Filepath + errorDictionary["file_path"] = self.__path - # Appends the error message to the content list in the error dictionary - errorDictionary["content"].append(errorMessage) + # Error message with itemm line and column numbers + errorDictionary["expected"] = expectedSyntax # Appends the item line to the content list in the error dictionary - errorDictionary["content"].append(line) + errorDictionary["got"] = line + + # Apeends error num to the dictonary + errorDictionary["line_num"] = lineNum # returns the error dictionary return errorDictionary @@ -983,9 +945,3 @@ def getQueues() -> list: queues.append(Queue(file)) return queues -if __name__ == "__main__": - item = Item("aae", 2) - print() -# for queue in getQueues(): -# for item in queue.items: -# print(f"${item.queue} ${item.number}") \ No newline at end of file