Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

I'm trying to run a python application but keep getting the following error: File /Users/Holly/Documents/UMUC/SDEV300/lab2.py, line 286, in ui.mainloop() AttributeError: 'UI' object has no attribute

I'm trying to run a python application but keep getting the following error:

File "/Users/Holly/Documents/UMUC/SDEV300/lab2.py", line 286, in

ui.mainloop()

AttributeError: 'UI' object has no attribute 'mainloop'

Here are the sections giving me trouble:

def mainloop(self) -> None:

"""Run the program."""

print("Welcome to the", colored("Really Purposeful Program (RPP):", "red"))

while not self.stop:

self._print_main_menu()

uin = input(">>> ")

while not self._validate_menu_input(uin):

print("I didn't understand that! ")

self._print_main_menu()

uin = input(">>> ")

self._run(uin)

self.stop = self._continue_msg()

self.exit()

if __name__ == "__main__":

ui = UI()

try:

ui.mainloop()

except KeyboardInterrupt:

ui.exit()

When I change the attribute to a different method, such as ui._print_main_menu, the error message goes away but the program ends without printing or taking input.

Essentially, I'm not sure how I should code the main method. The application is supposed to create a menu-driven Python program with options like generating a password and doing different math computations.

Here's the full code:

# pylint: disable=too-few-public-methods, unsubscriptable-object, no-self-use, ungrouped-imports

try:

import colorama

from termcolor import colored

except ImportError:

import subprocess

subprocess.call(["pip", "install", "-U", "colorama", "termcolor"])

finally:

import colorama

from termcolor import colored

import sys

import re

import math

import string

import datetime

import secrets

from functools import partial

from typing import Any, Callable, Dict, List, Optional, Tuple

# init color terminal output

colorama.init()

class Utility:

"""Class for utilities"""

"""Utilities are software programs that add functionality to your computer or help your computer perform better"""

@classmethod

def get_int(cls, message: str) -> int:

"print message and get an integer"

uin = input(message)

while not all(ltr.isdigit() for ltr in uin):

print("Please enter a whole number.")

uin = input(message)

return int(uin)

@classmethod

def get_float(cls, message: str) -> float:

"print message and get a float"

uin = input(message)

while not all(ltr.isdigit() or ltr == "." for ltr in uin):

print("Please enter a valid integer.")

uin = input(message)

return float(uin)

@classmethod

def get_valid(cls, message: str, validator: Callable) -> str:

"print message and verify input with validator()"

uin = input(message)

while not validator(uin):

print("Please try again.")

uin = input(message)

return uin

@classmethod

def password(cls, length: int, makeup: str) -> None:

"""A. Generate secure password"""

inds = {"1": "lower", "2": "upper", "3": "numbers", "4": "symbols"}

types = {

"lower": string.ascii_lowercase,

"upper": string.ascii_uppercase,

"numbers": string.digits,

"symbols": "".join(

letter

for letter in string.printable

if not letter

in string.ascii_letters + string.digits + string.whitespace

),

}

# generate a string for secrets to choose from

choices = "".join(types[inds[num]] for num in makeup)

# print out that password

print()

print(colored("Secure password: ", "green"), end="")

print(

colored("".join(secrets.choice(choices) for _ in range(length)), "blue"),

end=" ",

)

@classmethod

def percentage(cls, num: int, denom: int, prec: int) -> None:

"""B. Calculate and Format a Percentage"""

"""Calculate the percentage of `num/denom` to `prec` digits of precision."""

print()

print(

colored("Percentage:", "green"),

colored(f"{num/denom : .0{prec}%}", "blue"),

end=" ",

)

@classmethod

def days(cls) -> None:

"""C. How many days from today until July 4, 2025?"""

"""Get the number of days until July 4, 2025"""

print()

print(

colored(

f"{(datetime.datetime(2025, 7, 4) - datetime.datetime.today()).days}",

"blue",

),

colored("days until", "green"),

colored("July 4, 2025", "red"),

end=" ",

)

@classmethod

def triangle(cls, side_b: int, side_c: int, angle_a: int, prec: int = 3) -> None:

"""D. Use the Law of Cosines to calculate the leg of a triangle."""

"""

On a triangle with angles A, B, C, input two of

the sides and the angle between them to return

the third side.

"""

answer = math.sqrt(

side_b ** 2 + side_c ** 2 - (2 * side_b * side_c * math.cos(angle_a))

)

print()

print(

colored("Side a:", "green"),

colored(f"{answer : .0{prec}}", "blue"), end=" ",

)

@classmethod

def cylinder(cls, radius: int, height: int, prec: int = 3) -> None:

"""E.. Calculate the volume of a Right Circular Cylinder"""

"""Calculate the volume of a cylinder based on a supplied radius and height"""

print()

print(

colored("Volume of the cylinder:", "green"),

colored(f"{(math.pi * (radius ** 2)) * height : ,.0{prec}f}", "blue"),

end=" ",

)

class UI:

"""User interface class"""

def __init__(self) -> None:

self.stop: bool = False # flag for self.mainloop()

# self.needs is a dict of:

# {

# menu selection :

# [(input message, validator func), ...]

# }

# that self._run collects and uses with the appropriate

# utility from the _Utilities class.

self.needs: Dict[str, List[Tuple[str, Callable]]] = {

"1": [

("How long should the password be?", Utility.get_int),

(

(

"What should the makeup of the password be?"

" (ex: 123 for lower, upper, and nums)"

" 1 - lower case letters"

" 2 - upper case letters"

" 3 - numbers"

" 4 - symbols"

),

partial(

Utility.get_valid,

validator=lambda msg: all(ltr in "1234" for ltr in msg),

),

),

],

"2": [

("What is the numerator?", Utility.get_int),

("What is the denominator?", Utility.get_int),

("Calculate to how many decimal places?", Utility.get_int),

],

"3": [("", print)],

"4": [

(

(

"In the triangle:"

" angle A /| "

" / | "

" / | side c"

" side b / | "

" / | "

" / | "

" -------- "

" side a"

),

print,

),

("What is the length of side b?", Utility.get_int),

("What is the length of side c?", Utility.get_int),

("What is the measure of angle A (in degrees)?", Utility.get_float),

],

"5": [

("What is the radius of the base?", Utility.get_int),

("What is the height of the cylnder?", Utility.get_int),

],

}

# self.run is a dict that contains

# { menu selection : utility function }

# the utility function is what self._run

# feeds the collected arguments to.

self.functions = {

"1": Utility.password,

"2": Utility.percentage,

"3": Utility.days,

"4": Utility.triangle,

"5": Utility.cylinder,

}

def _print_main_menu(self) -> None:

"""See function name"""

print(

"""

Options:

1 - Generate a password

2 - Calculate a percentage

3 - How many days until July 4, 2025

4 - Find the missing side of a triangle

5 - Calculate the volume of a cylinder

6 - Exit

"""

)

def _validate_menu_input(self, m_choice: str) -> bool:

"""Validate menu input"""

# remove spaces and dots

u_str = re.sub('[\s\.]+', '', m_choice)

if u_str == "6" or not u_str:

print("Are you sure? (y/n)")

yes_no = input(">>> ")

if yes_no.lower().startswith("y"):

self.exit()

return False

if len(u_str) > 1 or not u_str in "".join([str(i) for i in range(1, 6)]):

return False

return True

def exit(self) -> None:

"Prints thank you message, cleans up terminal, and exits"

self.stop = True # useless but makes pylint stop yelling

print()

print(colored("Thank you!", "red", "on_blue"))

print(

colored("Thanks for using the", "blue")

+ colored(" Really Purposeful Program (RPP)", "red")

+ "!"

)

colorama.deinit()

sys.exit()

def _run(self, num: str) -> Optional[Any]:

"""

Collects arguments based on messages and validation functions in

self.needs. Feeds collected args to the function in self.functions

that corresponds to the user supplied selection from the menu.

"""

args = [] # collected arguments

for msg, func in self.needs.get(

num

): # grabs message and validator from self.needs

args.append(func(msg + " >>> ")) # appends the arg from the validator

# runs the corresponding function using the collected args

self.functions[num](*[arg for arg in args if arg])

def _continue_msg(self) -> bool:

"Prints continue message"

print("Continue? (y/n)")

yes_no = input(">>> ")

if yes_no.lower().startswith("y"):

return False

return True

def mainloop(self) -> None:

"""Run the program."""

print("Welcome to the", colored("Really Purposeful Program (RPP):", "red"))

while not self.stop:

self._print_main_menu()

uin = input(">>> ")

while not self._validate_menu_input(uin):

print("I didn't understand that! ")

self._print_main_menu()

uin = input(">>> ")

self._run(uin)

self.stop = self._continue_msg()

self.exit()

if __name__ == "__main__":

ui = UI()

try:

ui.mainloop()

except KeyboardInterrupt:

ui.exit()

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Financial management theory and practice

Authors: Eugene F. Brigham and Michael C. Ehrhardt

12th Edition

978-0030243998, 30243998, 324422695, 978-0324422696

Students also viewed these Programming questions