0

I have the following code.

import datetime
import re


class Entry:
    task_name = None
    minutes = None
    notes = None
    created_at = None

    def __init__(self, task_name=None, minutes=None,
                 created_at=None, notes=None):
        if task_name:
            self.task_name = task_name
            self.minutes = int(minutes)
            self.created_at = datetime.datetime.strptime(
                                                    created_at,
                                                    "%Y-%m-%d %H:%M:%S.%f")
            self.notes = notes
        else:
            self.get_task_details()

    # get task name, num of minutes and notes if required
    def get_task_details(self):
        self.task_name = input("Enter the name of the task: ")
        self.minutes = self.get_minutes()
        self.notes = self.get_notes()
        self.created_at = datetime.datetime.now()

    # get num of minutes and verify it
    # the user should enter a valid input
    def get_minutes(self):
        while True:
            minutes = input("Enter the number of minutes spent on the task: ")
            if minutes:
                try:
                    minutes = int(minutes)
                    return minutes
                except ValueError:
                    print("Please Enter a valid num of minutes")
            else:
                print("Please enter a valid input. ex 12")

    # print task info
    def get_task_info(self):
        print("You created your task at")
        created_at_formatted = self.created_at.strftime("%m/%d/%Y %H:%M")
        print("{}".format(created_at_formatted))

    # get notes if the user wants to
    # else: leave it with a value of None
    def get_notes(self):
        answer = input("Do you want to write any note on this task ? N/y >>> ")
        if answer.lower() == "y":
            note = input("Enter your note >>> ")
            return note
        else:
            self.notes = None
            print("Alright. No notes are added")

    def __str__(self):
        return """
        Task Name: {}
        Created At: {}
        Minutes Spend: {}
        Notes: {}
        """.format(self.task_name, self.created_at, self.minutes, self.notes)

class Log:
    e = Entry()
    entries = []
    entries.append(e)

    def find_by_pattern(self):
        """find by regex pattern"""
        regex = input("Enter your regex >>> ")
        try:
            regex = re.compile(r'{}'.format(regex), re.X)
        except sre_constants.error:
            print("Invalid regex")
            regex = None
        entries_found = []
        # check if the user entered a regex
        if regex:
            for entry in self.entries:
                if (re.findall(regex, entry.task_name) or
                        re.findall(regex, entry.notes)):
                        entries_found.append(entry)
        else:
            print("Please enter a  valid regex")

        if entries_found:
            if entries_found:
                print("We found the following entries")
                for entry in entries_found:
                    print("{}".format(entry))
        else:
            print("No entries were found based on your pattern")

if __name__ == "__main__":
    l = Log()
    l.find_by_pattern()

When I run the program and enter a regex of : '\w{4}'; It crashes However, If I run the program and enter the same regex but without quotes: \w{r}, it doesn't crash. Here is a more clear picture of what I am trying to do:

enter image description here

2 Answers 2

3

This is not crashing because of the regex but because of entry.notes being None while findall expects a string.

It works in the first example because the regex matches entry.task_name and thus the other part of the condition lines 88-89 is skipped.
However, when entering the quotes, the regex does not match the first part (it expects the quotes) and crashes on the latter being None.

You can verify this by entering a note, it won't crash, although it may be wiser to initialise those attributes to empty strings.

PS : Be aware that in get_notes you return the notes if any, but in the other case you may want to return the actual value (or the value will be erased when the function returns and set None anyway on line 27)

Here is a quickly/poorly fixed version :

import datetime
import re


class Entry:
    task_name = ""
    minutes = None
    notes = ""
    created_at = None

    def __init__(self, task_name=None, minutes=None,
                 created_at=None, notes=""):
        if task_name:
            self.task_name = task_name
            self.minutes = int(minutes)
            self.created_at = datetime.datetime.strptime(
                                                    created_at,
                                                    "%Y-%m-%d %H:%M:%S.%f")
            self.notes = notes
        else:
            self.get_task_details()

    # get task name, num of minutes and notes if required
    def get_task_details(self):
        self.task_name = input("Enter the name of the task: ")
        self.minutes = self.get_minutes()
        self.notes = self.get_notes()
        self.created_at = datetime.datetime.now()

    # get num of minutes and verify it
    # the user should enter a valid input
    def get_minutes(self):
        while True:
            minutes = input("Enter the number of minutes spent on the task: ")
            if minutes:
                try:
                    minutes = int(minutes)
                    return minutes
                except ValueError:
                    print("Please Enter a valid num of minutes")
            else:
                print("Please enter a valid input. ex 12")

    # print task info
    def get_task_info(self):
        print("You created your task at")
        created_at_formatted = self.created_at.strftime("%m/%d/%Y %H:%M")
        print("{}".format(created_at_formatted))

    # get notes if the user wants to
    # else: leave it with a value of None
    def get_notes(self):
        answer = input("Do you want to write any note on this task ? N/y >>> ")
        if answer.lower() == "y":
            note = input("Enter your note >>> ")
            return note
        else:
            return ""
            print("Alright. No notes are added")

    def __str__(self):
        return """
        Task Name: {}
        Created At: {}
        Minutes Spend: {}
        Notes: {}
        """.format(self.task_name, self.created_at, self.minutes, self.notes)

class Log:
    e = Entry()
    entries = []
    entries.append(e)

    def find_by_pattern(self):
        """find by regex pattern"""
        regex = input("Enter your regex >>> ")
        try:
            regex = re.compile(r'{}'.format(regex), re.X)
        except sre_constants.error:
            print("Invalid regex")
            regex = None
        entries_found = []
        # check if the user entered a regex
        if regex:
            for entry in self.entries:
                if (re.findall(regex, entry.task_name) or
                        re.findall(regex, entry.notes)):
                        entries_found.append(entry)
        else:
            print("Please enter a  valid regex")

        if entries_found:
            if entries_found:
                print("We found the following entries")
                for entry in entries_found:
                    print("{}".format(entry))
        else:
            print("No entries were found based on your pattern")

if __name__ == "__main__":
    l = Log()
    l.find_by_pattern()
Sign up to request clarification or add additional context in comments.

Comments

0

Based on the error:

expected string or bytes-like object

You just need to transfer the later part as string type of data using str():

if (re.findall(regex, str(entry.task_name)) or
                        re.findall(regex, str(entry.notes))):
                        entries_found.append(entry)

Or you can try to add b'xxx' in front of the second parameter for findall function. Not the variable, it is the original string.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.