How to search meal by name using Mealdb API for Python - python

In my objects.py I have this code for meals:
class Meal:
def __init__(self, meal_id, meal_name, meal_thumb):
self.__meal_id = meal_id
self.__meal_name = meal_name
self.__meal_thumb = meal_thumb
def get_meal_id(self):
return self.__meal_id
def set_meal_id(self, meal_id):
self.__meal_id = meal_id
def get_name(self):
return self.__meal_name
def set_name(self, meal_name):
self.__meal_name = meal_name
def get_meal_thumb(self):
return self.__meal_thumb
def set_meal_thumb(self, meal_thumb):
self.__meal_thumb = meal_thumb
In my requests.py I came up with:
def get_all_meals():
url = "https://www.themealdb.com/api/json/v1/1/search.php?f=a"
f = request.urlopen(url)
all_meals = []
try:
data = json.loads(f.read().decode('utf-8'))
for meal_data in data['meals']:
meal = Meal(meal_data['strMeal'],
meal_data['strMeal'],
meal_data['strMealThumb'])
all_meals.append(meal)
except(ValueError, KeyError, TypeError):
return None
return all_meals
def get_meal_by_name(meal):
url = "https://www.themealdb.com/api/json/v1/1/search.php?s=" + parse.quote(meal)
f = request.urlopen(url)
try:
data = json.loads(f.read().decode('utf-8'))
for meal_data in data['meals']:
meal = Meal(meal_data['idMeal'],
meal_data['strMeal'],
meal_data['strMealThumb'])
except(ValueError, KeyError, TypeError):
return None
return meal
I'm not sure if need get_all_meals() or just get_meal_by_name(meal).
In my recipes.py I have:
def list_meal_by_name():
lookup_meal = input("Enter Meal Name: ")
all_meals = requests.get_all_meals()
found = False
if all_meals is None:
print("Technical difficulties, please try again later.")
else:
for i in range(len(all_meals)):
meal = all_meals[i]
if meal.get_meal_id().lower() == lookup_meal.lower():
found = True
break
if found:
meal = lookup_meal
recipe = requests.get_meal_by_name(meal)
my_wrap = textwrap.TextWrapper(width=80)
wrap_list = my_wrap.wrap("Instructions: " + recipe.get_instructions())
for line in wrap_list:
print(line)
else:
print("Invalid meal name. Please try again.")
print()
I was trying to run the user input through the list of all meals in the Mealdb API. If that was found I wanted the meal and instructions to print, but it jumps to the else statement and prints "Invalid meal name. Please try again." I'm not sure what to code in the if statement to make it run and print properly. Also, the "recipe.get_instructions()" is a hint given for this project so I'm not sure what I need to do to make it work.

Related

How can I prevent my JSON file from getting overwritten in Python?

I am currently building a school homework project - a contact manager, using classes in Python.
I was able to assemble all the needed parts to make my code work, yet upon exiting the program with Terminal, the data inside of my JSON file keep being overwritten.
I've tried changing the with open attribute to "w" and "a", sadly nothing works.
Main Code:
from colorama import Fore, Style
from LoadAndSave import load_file, save_file
from ContactBook import ContactBook
contacts = []
DATA_FILE = "contactbook.json"
def menu():
print(Fore.RED + "Welcome to Contacts Manager v2.0.0!" + Style.RESET_ALL)
print(Fore.LIGHTCYAN_EX + "Please enter your selection according to the menu." + Style.RESET_ALL)
print("a - Add a contact")
print("r - Remove a contact")
print("s - Search for a contact")
print("p - Print a list of all contacts")
print("x - Exit")
user_selection = input(Fore.GREEN + "Your selection: " + Style.RESET_ALL)
return user_selection
def main():
load_file(DATA_FILE)
contactbook = ContactBook()
user_selection = ""
while user_selection != "x":
user_selection = menu() # As long as user did not select "x", program will always run.
if user_selection == "a":
contactbook.add_contact(input("Please enter contact's name: "), int(input("Please enter contact's number: ")))
if user_selection == "r":
contactbook.remove_contact(contactbook.search_contact(input("Contact's Name? ")))
if user_selection == "s":
contactbook.search_contact(input("Contact's name?"))
print(Fore.GREEN + "Success!" + Style.RESET_ALL)
if user_selection == "p":
print(contactbook)
print(Fore.GREEN + "Success!" + Style.RESET_ALL)
print(Fore.MAGENTA + "Thank you for using my software. Bye!")
save_file(contactbook.make_contact_json(), DATA_FILE)
if __name__ == "__main__":
main()
Load and save:
import json
def load_file(DATA_FILE): # Loading JSON file with all information
with open (DATA_FILE) as file:
return json.load(file)
def save_file(json_list, DATA_FILE):
with open (DATA_FILE, "w") as file:
json.dump(json_list, file, indent = 4)
Contact & ContactBook classes:
import json
class Contact:
name = ""
tel = 0
def __init__(self, name = "", tel = 0):
self.name = name
self.tel = tel
def __str__(self):
return json.dumps({"contact_info":[{"name": self.name, "tel": self.tel}]})
from colorama import Fore, Style, Back
from Contact import Contact
import json
class ContactBook:
contacts = []
def __init__(self):
pass
def add_contact(self, name = "", tel = 0):
self.contacts.append(Contact(name, tel))
print(Fore.GREEN + "Success!" + Style.RESET_ALL)
def remove_contact(self, contact_name):
self.contacts.remove(contact_name)
print(Fore.RED + "Removed.\n" + Style.RESET_ALL)
def search_contact(self, contact_name):
for contact in self.contacts:
if type(contact) is Contact:
if contact.name == contact_name:
return contact
return (Back.RED + "\nThere is no contact with that name." + Style.RESET_ALL + "\n")
def make_contact_json(self):
result = []
for contact in self.contacts:
result.append(json.loads(contact.__str__()))
return result
def __str__(self) -> str:
result = ""
for contact in self.contacts:
result += contact.__str__()
return result
JSON File:
[
[
{
"name": "sdfgh",
"tel": 654321
}
]
]
Thanks in advance to all helpers!
Your contacts are getting overwritten because every time you run your program, you are creating a fresh ContactBook
contactbook = ContactBook() # In your Main Code
This in turn initializes an empty contacts list
contacts = [] # Inside Class ContactBook
I suggest that you add an __init__ logic to you ContactBook Class that initialises your contacts list with the existing ones
Something Like
class ContactBook:
def __init__(self, existing_contacts=None):
self.contacts = [] if existing_contacts is None else existing_contacts
Also while creating the ContactBook object in you main code please pass the existing contacts.
try:
existing_contacts = load_file(DATA_FILE)
except FileNotFoundError:
existing_contacts = None
contactbook = ContactBook(existing_contacts)
Also please make sure that you are saving the contacts correctly. It seems to currently be a list of list of objects where as it should ideally be a list of objects
Hope you get good grades. Peace out.

How to turn my 'shopping cart' function into an object oriented program using Class() and __init__?

def userQty():
name = input("Quantity: ")
return name
def userAdd():
add = input("What would you like to add do your cart? ")
return add
def userInfo():
data = {}
while True:
result = input(
"Make your shopping list. Please type (Show/Add/Delete/Clear/Quit). ")
if result.lower() == 'add':
data[userQty()] = userAdd()
elif result.lower() == 'show':
print(data)
elif result.lower() == 'delete':
print("Still working on that, use 'clear' for now please.")
# Could not figure out how to remove one item
elif result.lower() == 'clear':
dLi = input("Clear your list?: [y/n] ").lower()
if dLi in ["y", "yes"]:
data = {}
print("Your list has been cleared.")
print(data)
elif dLi in ["n", "no"]:
print("Action Abandoned.")
elif result.lower() == 'quit':
break
else:
print(
'Oops! Something went wrong. Please type "(Show/Add/Delete/Clear/Quit)"')
print(data)
return data
userInfo()
I am fairly new to programming as a whole so I'm sorry if the code is sloppy or if I am not being specific enough?
I tried adding:
def __init__(self):
return #something
I am lost as far as where to go from here.
You could add:
class Somthing():
def __init__(self):
code
and add the variables to self, like this:
self.name = name
also put (self): in the function parentheses.
One approach might be to make your different menu items methods on your object:
class ShoppingCart:
def __init__(self):
self.data = {}
def add(self):
i = input("What would you like to add to your cart? ")
self.data[i] = input("Quantity: ")
def clear(self):
if input("Clear your list? [y/n] ").lower().startswith("y"):
self.data = {}
print("Your list has been cleared.")
else:
print("Action abandoned.")
def delete(self):
print("Still working on that, use 'clear' for now please.")
def menu_loop(self):
while True:
i = input(
"Make your shopping list. "
"Please type (Show/Add/Delete/Clear/Quit). "
).lower()
if i == "quit":
break
try:
getattr(self, i)()
except AttributeError:
print(
'Oops! Something went wrong. '
'Please type "(Show/Add/Delete/Clear/Quit)"'
)
cart = ShoppingCart()
cart.menu_loop()
print(cart.data)

Using var() to instantiate object from user input. Syntax error

I've made these classes and now I'm trying to make a function that allows you to instantiate a new object from data a user inputs. But I'm getting syntax errors with using var()
The class structure is that there is one main with two sub-classes. The main, "Gokemon" is:
class Gokemon:
def __init__(self,NAME,TYPE,HEALTH,POWER): #Contructor #Mayb think about using dict key words
self._Name = str(NAME)
self._Type = str(TYPE) #Water, Earth, Fire or Flying. Used in Battle() to allow adders
self._HP = int(HEALTH) #Health Points
self._DP = int(POWER) #Power Points - attacking power
and the two sub-classes are named "Tame" and "Wild".
class Tame(Gokemon):
def __init__(self,NAME,TYPE,HEALTH,POWER):
Gokemon.__init__(self,NAME,TYPE,HEALTH,POWER)
self._Owner = ""
self._Time = 0 #How long have they owned it
class Wild(Gokemon):
def __init__(self,NAME,TYPE,HEALTH,POWER):
Gokemon.__init__(self,NAME,TYPE,HEALTH,POWER)
The function for making the new object by user input is as follows:
def NewGokemon():
n = input("What's its name?: ")
while True:
t = input("what's its type?: ")
if t == "Water" or t == "Fire" or t=="Earth" or t =="Flying":
break
else:
print("please try again, the types include:\nFire\nWater\nEarth\nFlying")
while True:
h = input("How many Health Points(HP) does it have")
try:
int(h)/2
except ValueError:
print("Sorry please input a numerical value")
else:
break
while True:
p = input("How many Health Points(HP) does it have")
try:
int(p)/2
except ValueError:
print("Sorry please input a numerical value")
else:
break
while True:
dom = input("Is the Gokemon tame(input t) or wild(input w)?")
if dom =="t":
return var()[n] = Tame(n,t,h,p)
if dom == 'w':
return var()[n] = Wild(n,t,h,p)
The function is fine until at the bottom, when im compiling to execute my Editor (VS code) says.
File "c:\Users\rufar\Desktop\python\little projects\Gokemon - learning class\Gokemon.py", line 38
return var()[n] = Tame(n,t,h,p)
^
SyntaxError: invalid syntax
What am i doing wrong? Is there a better way of doing this?
replaced the whole bit with vars() with this:
while True:
dom = input("Is the Gokemon tame(input t) or wild(input w)?")
if dom =="t":
globals()[n] = Tame(n,t,h,p)
return n
elif dom == 'w':
globals()[n] = Wild(n,t,h,p)
return n
else:
print("Did not understand input")
And now it works fine.

Writing and retrieving pickled object to a file

I'm doing creating a address book for a computer science class, where we are supposed to have a list of objects "contact" written to a file when the program closes and read from the file when the program starts. However, after the data is written to the file, once it is read it does not seem to keep its object form.
import pickle
class Contact:
#Creating the class with the attributes I want
def __init__(self, firstname, lastname, number, areacode, city):
self.firstname = firstname
self.lastname = lastname
self.number = number
self.areacode = areacode
self.city = city
def __str__(self):
return "({0} {1}, {2}, {3}, {4})".format(self.firstname, self.lastname, self.number, self.areacode, self.city)
#reading the object
def opendata():
readable = []
addresses = []
A = open("Address_book", "rb+")
addresses = A.read()
A.close
B = len(addresses)
if B != 0:
readable = pickle.loads(addresses)
return readable
else:
return addresses
def savedata(file):
addresses = open("Address_book", "wb+")
temp = pickle.dumps(file)
addresses.write(temp)
addresses.close()
def Address_manager():
Address = []
fromfile = opendata()
Address.append(fromfile)
while True:
print("add = add contact, modify = modify contact, search = search contacts, end = close program, print = print full list")
A = input("What do you want to do?: ")
if A == "end":
savedata(Address)
break
else:
if A == "print":
for i in Address:
print(str(i))
print("")
continue
elif A == "add":
Address.append(add_contact())
print("")
continue
elif A == "search":
lists2 = search_contact(Address)
A = 0
for i in lists2:
A += 1
print(A, str(i))
print("")
print("")
continue
elif A == "modify":
modified = modify_contact(Address)
Address.append(modified)
print("")
continue
def add_contact():
while True:
try:
A = Contact(input("First name: "), input("Last name: "), input("Phone Number: "), input("Area Code: "), input("City: "))
print(str(A))
B = input("Is this right?: (y/n)")
if B == "y":
print("Well done?")
return A
else:
print("Try Again")
continue
except:
print("bad data")
If I try to "print" the list after getting it from the file it prints them in the wrong form. What am I doing wrong and why?
Edit 1: I apologize for the less than efficient code.
Edit 2: Added function to add contact

Saving of Information in Python Along with Retrieving It

The purpose of the two programs is to have twitter.py manage tweet.py by having the 5 most recent tweets that are saved in the program twitter.py to show up once you search and find it. There are four options, make a tweet, view recents tweets, search a tweet and quit. I'm having trouble saving because it keeps saying no recent tweets are found. Also I'm having trouble with the fact that I can't search for my tweets but that is probably the same reason as my first problem because they aren't being saved correctly. Thank you please help!!
tweet.py
import time
class tweet:
def __init__(self, author, text):
self.__author = author
self.__text = text
self.__age = time.time()
def get_author(self):
return self.__author
def get_text(self):
return self.__text
def get_age(self):
now = time.time()
difference = now - self.__time
hours = difference // 3600
difference = difference % 3600
minutes = difference // 60
seconds = difference % 60
# Truncate units of time and convert them to strings for output
hours = str(int(hours))
minutes = str(int(minutes))
seconds = str(int(seconds))
# Return formatted units of time
return hours + ":" + minutes + ":" + seconds
twitter.py
import tweet
import pickle
MAKE=1
VIEW=2
SEARCH=3
QUIT=4
FILENAME = 'tweets.dat'
def main():
mytweets = load_tweets()
choice = 0
while choice != QUIT:
choice = get_menu_choice()
if choice == MAKE:
add(mytweets)
elif choice == VIEW:
recent(mytweets)
elif choice == SEARCH:
find(mytweets)
else:
print("\nThanks for using the Twitter manager!")
save_tweets(mytweets)
def load_tweets():
try:
input_file = open(FILENAME, 'rb')
tweet_dct = pickle.load(input_file)
input_file.close()
except IOError:
tweet_dct = {}
return tweet_dct
def get_menu_choice():
print()
print('Tweet Menu')
print("----------")
print("1. Make a Tweet")
print("2. View Recent Tweets")
print("3. Search Tweets")
print("4. Quit")
print()
try:
choice = int(input("What would you like to do? "))
if choice < MAKE or choice > QUIT:
print("\nPlease select a valid option.")
except ValueError:
print("\nPlease enter a numeric value.")
return choice
def add(mytweets):
author = input("\nWhat is your name? ")
while True:
text = input("what would you like to tweet? ")
if len(text) > 140:
print("\ntweets can only be 140 characters!")
continue
else:
break
entry = tweet.tweet(author, text)
print("\nYour tweet has been saved!")
def recent(mytweets):
print("\nRecent Tweets")
print("-------------")
if len(mytweets) == 0:
print("There are no recent tweets. \n")
else:
for tweets in mytweets[-5]:
print(tweets.get_author, "-", tweets.get_age)
print(tweets.get_text, "\n")
def find(mytweets):
author = input("What would you like to search for? ")
if author in mytweets:
print("\nSearch Results")
print("----------------")
print(tweet.tweet.get_author(), - tweet.tweet.get_age())
print(tweet.tweet.get_text())
else:
print("\nSearch Results")
print("--------------")
print("No tweets contained ", author)
def save_tweets(mytweets):
output_file = open(FILENAME, 'wb')
pickle.dump(mytweets, output_file)
output_file.close()
main()
In twitter.py:add_tweets, mytweets is passed into the function and entry is created, but it is never added to mytweets. The created entry is lost after the function returns.
Your question was:
I'm having trouble saving because it keeps saying no recent tweets are
found.
Function add does not seem to be adding tweets anywhere. It creates a tweet.tweet instance, but it does not do anything with it.
You probably want to add the tweet to mytweets?
Another problem:
You initialize mytweets as a dicionary (tweet_dct = {}), but later you use it as a list (mytweets[-5]). It should be a list from start. And you probably want last five tweets (mytweets[-5:]), not just the fifth from the end.
On the sidenotes:
What you have here is not "two programs" - it is one program in two python files, or "modules"
Although there is nothing wrong with having getters (functions like get_author), there is no need for them in Python (see How does the #property decorator work?). Do youself a favour and keep it simple, e.g.:
class Tweet:
def __init__(self, author, text):
self.author = author
self.text = text
self.creation_time = time.time()
def get_age_as_string(self):
# your code from get_age
There will be time when you need private variables. When that happens, use a single leading underscore (self._author) until you fully understand what double underscore does and why.
Pickle is probably not the best way to store information here, but it is a good start for learning.

Categories

Resources