From 935a141d9c94e71999df6bee38c52ae358c61905 Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Mon, 11 Feb 2019 00:01:18 -0800 Subject: [PATCH 001/367] Create Lesson4 --- students/WooseokJ/Lesson4 | 1 + 1 file changed, 1 insertion(+) create mode 100644 students/WooseokJ/Lesson4 diff --git a/students/WooseokJ/Lesson4 b/students/WooseokJ/Lesson4 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/students/WooseokJ/Lesson4 @@ -0,0 +1 @@ + From c08c36ccb32dd54f9fccadae00e3a21339d2b844 Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Mon, 11 Feb 2019 00:02:03 -0800 Subject: [PATCH 002/367] Lesson 4 submission --- students/WooseokJ/MailP2fixedWJ.py | 111 +++++++++++++++++++++++++++++ students/WooseokJ/TrigramWJ.py | 50 +++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 students/WooseokJ/MailP2fixedWJ.py create mode 100644 students/WooseokJ/TrigramWJ.py diff --git a/students/WooseokJ/MailP2fixedWJ.py b/students/WooseokJ/MailP2fixedWJ.py new file mode 100644 index 00000000..ebd196af --- /dev/null +++ b/students/WooseokJ/MailP2fixedWJ.py @@ -0,0 +1,111 @@ + +# coding: utf-8 + +# In[3]: + + +# print of the main menu +import sys +import datetime +import operator + +def menu(): + print(''''Menu + Please choose from below options: + 1 - Send a Thank You + 2 - Create a Report + 3 - Exit the program + 4 - Print thank you letter to all current doners''') +#first it will ask to choose a name whoom you would want to send the mail +#along side that when typing list it will give you all the names on the current list +#second if the name is not in the list then it will prompt to add the name into the data base +#lastly it will print the message of the email +# have a problem here where when asked for the amount of donation if the value type is not a number we get a error how to loop around this? +def send_a_thankyou(): + donor_list = [] + for donor in donor_db: + donor_list.append(donor.lower()) + while True: + fullname = input("Enter the full name of the donor typing list will give the names of current doners ") + if fullname.lower() == 'list': + for donor in donor_db: + print(donor) + elif fullname.lower() not in donor_list: + print(f'{fullname} does not exist in the donor data, ' + f'we will add {fullname} to the donor data.') + amount = float(input("Please enter the donation amount: ")) + donor_db.append((fullname, [amount, 1])) + print(f"{amount} has been added to {fullname}'s donation history.") + break + elif fullname.lower() in donor_list: + fullname = donor_list.index(fullname.lower()) + amount = float(input("Please Enter the donation amount: ")) + donor_db[fullname][1][0] = donor_db[fullname][1][0] + amount + donor_db[fullname][1][1] = donor_db[fullname][1][1] + 1 + print(f"{amount} has been added to {fullname}'s donation history.") + break + print("Creating a Thank You email:") + print(f'Thank you {fullname} for your donation of {amount:^10.2f}!') + print() + menu() +#this prints out the database of the donors with their total amaounts and average amount donated +def create_a_report(): + sorted_donor_db = sorted(donor_db.items(), key=operator.itemgetter(1), reverse=True) + print("Printing report:") + title = ('Donor Name', 'Total Given', "Num Gifts", 'Average Gift') + print("{:<19} | {:^13} | {:^13} | {:^11}".format(*title)) + print("-"*70) + for i, row in enumerate(donor_db): + print("{:<21} ${:>13.2f} {:>13} ${:>12.2f}" + .format(donor_db[i][0], donor_db[i][1][0], donor_db[i][1][1], + donor_db[i][1][0]/donor_db[i][1][1])) + print() + menu() + +def sort_total_donation(number): + return number[1][0] +#this makes a text that has the thankyou message to all the current doners on the list +#the title of the file has the date and the name of the person on the list +def send_letters_to_all_donors(): + '''generate thankyou letter to all donors''' + for key in donor_db: + with open(key+"_"+str(datetime.date.today())+".txt", 'w') as f: + f.write("Dear {name},\n" + "\n" + " Thank you for your very kind donation of ${amount:10.2f}.\n" + "\n" + " It will be put to very good use.\n" + "\n" + " Sincerely\n" + " -The Team".format(name=key, amount=donor_db[key][0])) + print("Thank you letters to all donors have been generated in the local disk.\n") + +def exit_program(): + print("Exiting the program") + sys.exit() + +def main(): + choice = '' + while True: + choice = int(input(menu())) + if choice in main_menu: + main_menu[choice]() + else: + print("Not a valid option, try again.") +#the main frame of the console +main_menu = {1: send_a_thankyou, + 2: create_a_report, + 3: exit_program, + 4: send_letters_to_all_donors + } + +if __name__ == "__main__": + + donor_db = {"William Gates, III": [ 653784.49, 2], + "Mark Zuckerberg": [16396.10, 3], + "Jeff Bezos": [877.33, 1], + "Paul Allen": [708.42, 3], + } + + main() + diff --git a/students/WooseokJ/TrigramWJ.py b/students/WooseokJ/TrigramWJ.py new file mode 100644 index 00000000..c6f762a7 --- /dev/null +++ b/students/WooseokJ/TrigramWJ.py @@ -0,0 +1,50 @@ + +# coding: utf-8 + +# In[3]: + + +import sys +import random + +#takes the words from the given file and returns it in a list +def words_from_file(filename): + with open(filename, 'r') as textfile: + return [word.strip('\n') for l in textfile.readlines() + for word in l.split(' ')] +#from the list makes a dictiondary to mix it in the next process +def build_trigrams_dict(words): + trigrams = {} + for i, w in enumerate(words): + if i + 2 < len(words): + first = w.strip() + second = words[i + 1].strip() + third = words[i + 2].strip() + mix = '{} {}'.format(first, second) + if mix not in trigrams.keys(): + trigrams[mix] = [] + trigrams[mix].append(third) + return trigrams +#this mixes the words to create the trigram +def build_text(trigrams, num, new_words=[]): + if len(new_words) >= int(num) or int(num) < 3: + return ' '.join(new_words) + if not new_words: + second_start = random.choice(list(trigrams.keys())) + new_words.extend(second_start.split(' ')) + if len(new_words) > 1: + mix = '{} {}'.format(new_words[-2], new_words[-1]) + if mix not in trigrams.keys(): + mix = random.choice(list(trigrams.keys())) + third = random.choice(trigrams[mix]) + new_words.append(third) +#this is a promot that asks for the file that we want to scramble make sure to add .txt at the end of the file + return build_text(trigrams, num, new_words) +if __name__ == '__main__': + filename = input('Please enter a filename:\n--->') + length = 178 + words = words_from_file(filename) + trigrams = build_trigrams_dict(words) + new_text = build_text(trigrams,length) + print (new_text) + From 548651e9a0779e3a9808c87fd0d6d813c60c1b8b Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Mon, 11 Feb 2019 19:19:52 -0800 Subject: [PATCH 003/367] Update TrigramWJ.py i tried something else to make the code more compact and tried to stick more to the example given on the site but can't seem to fix the problem where the output is super short --- students/WooseokJ/TrigramWJ.py | 55 +++++++++++++--------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/students/WooseokJ/TrigramWJ.py b/students/WooseokJ/TrigramWJ.py index c6f762a7..17996cbe 100644 --- a/students/WooseokJ/TrigramWJ.py +++ b/students/WooseokJ/TrigramWJ.py @@ -1,9 +1,3 @@ - -# coding: utf-8 - -# In[3]: - - import sys import random @@ -15,36 +9,29 @@ def words_from_file(filename): #from the list makes a dictiondary to mix it in the next process def build_trigrams_dict(words): trigrams = {} - for i, w in enumerate(words): - if i + 2 < len(words): - first = w.strip() - second = words[i + 1].strip() - third = words[i + 2].strip() - mix = '{} {}'.format(first, second) - if mix not in trigrams.keys(): - trigrams[mix] = [] - trigrams[mix].append(third) - return trigrams -#this mixes the words to create the trigram -def build_text(trigrams, num, new_words=[]): - if len(new_words) >= int(num) or int(num) < 3: - return ' '.join(new_words) - if not new_words: - second_start = random.choice(list(trigrams.keys())) - new_words.extend(second_start.split(' ')) - if len(new_words) > 1: - mix = '{} {}'.format(new_words[-2], new_words[-1]) - if mix not in trigrams.keys(): - mix = random.choice(list(trigrams.keys())) - third = random.choice(trigrams[mix]) - new_words.append(third) + for i in range(len(words)-2): + pair = tuple(words[i:i + 2]) + follower = words[i + 2] + if pair not in trigrams: + trigrams[pair] = [follower] + else: + trigrams[pair] += [follower] + return trigrams +#this mixes the words to create the new text +def build_text(pairs): + random_text = [] + while len(random_text) < len(pairs): + random_key = random.choice(list(pairs.keys())) + value = pairs.get(random_key) + random_text.append(list(random_key)) + random_text.append(value) + new_list = [item for fixedlist in random_text for item in fixedlist] + clean_text = " ".join(new_list) #this is a promot that asks for the file that we want to scramble make sure to add .txt at the end of the file - return build_text(trigrams, num, new_words) + return clean_text if __name__ == '__main__': - filename = input('Please enter a filename:\n--->') - length = 178 + filename = input('Please enter a filename:') words = words_from_file(filename) trigrams = build_trigrams_dict(words) - new_text = build_text(trigrams,length) + new_text = build_text(trigrams) print (new_text) - From ca82472f08b43934691b2ceb269a841395f57a35 Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 17 Feb 2019 16:43:40 -0800 Subject: [PATCH 004/367] code review for fixed mail_p2 before adding in p3 every error should have been fixed before adding in codes for p3 --- students/WooseokJ/MailP2fixedWJFixed.py | 121 ++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 students/WooseokJ/MailP2fixedWJFixed.py diff --git a/students/WooseokJ/MailP2fixedWJFixed.py b/students/WooseokJ/MailP2fixedWJFixed.py new file mode 100644 index 00000000..d23086f9 --- /dev/null +++ b/students/WooseokJ/MailP2fixedWJFixed.py @@ -0,0 +1,121 @@ + +# coding: utf-8 + +# In[ ]: + + +import sys +import datetime +import operator + + +def menu(): + print(''''Menu + Please choose from below options: + 1 - Send a Thank You + 2 - Create a Report + 3 - Exit the program + 4 - Print thank you letter to all current donors''') + + +# first it will ask to choose a name whoom you would want to send the mail +# along side that when typing list it will give you all the names on the current list +# second if the name is not in the list then it will prompt to add the name into the data base +# lastly it will print the message of the email +def send_a_thankyou(): + donor_list = [] + for donor in donor_db: + donor_list.append(donor.lower()) + while True: + fullname = input("Enter the full name of the donor typing list will give the names of current doners ") + if fullname.lower() == 'list': + for donor in donor_db: + print(donor) + elif fullname.lower() not in donor_list: + print(f'{fullname} does not exist in the donor data, ' + f'we will add {fullname} to the donor data.') + amount = float(input("Please enter the donation amount: ")) + donor_db[fullname] = [amount, 1] + print(f"{amount} has been added to {fullname}'s donation history.") + break + elif fullname.lower() in donor_list: + amount = float(input("Please Enter the donation amount: ")) + donor_db[fullname][0] = donor_db[fullname][0] + amount + donor_db[fullname][1] = donor_db[fullname][1] + 1 + print(f"{amount} has been added to {fullname}'s donation history.") + break + print("Creating a Thank You email:") + print(f'Thank you {fullname} for your donation of {amount:^10.2f}!') + print() + menu() + + +# this prints out the database of the donors with their total amaounts and average amount donated +def create_a_report(): + print("Printing report:") + title = ("Donor Name", "| Total Given", "| Num Gifts", "| Average Gift") + row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*title) + length = len(row) + print("\n" + row) + print("=" * length) + for key, value in sorted(donor_db.items()): + given = str(sum(value)) + gift = str(len(value)) + average = str(sum(value) / (len(value))) + row_format = (key, "$" + given, gift, "$" + average) + donor_row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*row_format) + print(donor_row) + print("\n") + +def sort_total_donation(number): + return number[1][0] + + +# this makes a text that has the thankyou message to all the current doners on the list +# the title of the file has the date and the name of the person on the list +def send_letters_to_all_donors(): + '''generate thank you letter to all donors''' + for key in donor_db: + with open(key + "_" + str(datetime.date.today()) + ".txt", 'w') as f: + f.write("Dear {name},\n" + "\n" + " Thank you for your very kind donation of ${amount:10.2f}.\n" + "\n" + " It will be put to very good use.\n" + "\n" + " Sincerely\n" + " -The Team".format(name=key, amount=donor_db[key][0])) + print("Thank you letters to all donors have been generated in the local disk.\n") + + +def exit_program(): + print("Exiting the program") + sys.exit() + + +def main(): + choice = '' + while True: + choice = int(input(menu())) + if choice in main_menu: + main_menu[choice]() + else: + print("Not a valid option, try again.") + + +# the main frame of the console +main_menu = {1: send_a_thankyou, + 2: create_a_report, + 3: exit_program, + 4: send_letters_to_all_donors + } + +if __name__ == "__main__": + donor_db = {"William Gates, III": [653784.49, 2], + "Mark Zuckerberg": [16396.10, 3], + "Jeff Bezos": [877.33, 1], + "Paul Allen": [708.42, 3], + } + + main() + From 2614cac60f91757365f5a2c420af11e55b2aa48b Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 17 Feb 2019 21:35:00 -0800 Subject: [PATCH 005/367] Lesson 5 submission --- students/WooseokJ/MailP3exceptWJ.py | 134 ++++++++++++++++++++++++++++ students/WooseokJ/exceptWJ.py | 59 ++++++++++++ students/WooseokJ/except_test.py | 41 +++++++++ 3 files changed, 234 insertions(+) create mode 100644 students/WooseokJ/MailP3exceptWJ.py create mode 100644 students/WooseokJ/exceptWJ.py create mode 100644 students/WooseokJ/except_test.py diff --git a/students/WooseokJ/MailP3exceptWJ.py b/students/WooseokJ/MailP3exceptWJ.py new file mode 100644 index 00000000..ca1b6bfe --- /dev/null +++ b/students/WooseokJ/MailP3exceptWJ.py @@ -0,0 +1,134 @@ + +# coding: utf-8 + +# In[12]: + + +import sys +import datetime +import operator + + +def menu(): + print(''''Menu + Please choose from below options: + 1 - Send a Thank You + 2 - Create a Report + 3 - Exit the program + 4 - Print thank you letter to all current donors''') + + +# first it will ask to choose a name whoom you would want to send the mail +# along side that when typing list it will give you all the names on the current list +# second if the name is not in the list then it will prompt to add the name into the data base +# lastly it will print the message of the email +#added excepts to close off any errors that has to do with input errors +def send_a_thankyou(): + donor_list = [] + for donor in donor_db: + donor_list.append(donor.lower()) + while True: + fullname = input("Enter the full name of the donor typing list will give the names of current doners ") + if fullname.lower() == 'list': + for donor in donor_db: + print(donor) + elif fullname.lower() not in donor_list: + print(f'{fullname} does not exist in the donor data, ' + f'we will add {fullname} to the donor data.') + while True: + try: + amount = float(input("Please enter the donation amount: ")) + break + except ValueError: + print("Invalid input please try again") + donor_db[fullname] = [amount, 1] + print(f"{amount} has been added to {fullname}'s donation history.") + break + elif fullname.lower() in donor_list: + while True: + try: + amount = float(input("Please Enter the donation amount: ")) + break + except ValueError: + print("Invalid input please try again") + donor_db[fullname][0] = donor_db[fullname][0] + amount + donor_db[fullname][1] = donor_db[fullname][1] + 1 + print(f"{amount} has been added to {fullname}'s donation history.") + break + print("Creating a Thank You email:") + print(f'Thank you {fullname} for your donation of {amount:^10.2f}!') + print() + menu() + + +# this prints out the database of the donors with their total amaounts and average amount donated +def create_a_report(): + print("Printing report:") + title = ("Donor Name", "| Total Given", "| Num Gifts", "| Average Gift") + row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*title) + length = len(row) + print("\n" + row) + print("=" * length) + for key, value in sorted(donor_db.items()): + given = str(sum(value)) + gift = str(len(value)) + average = str(sum(value) / (len(value))) + row_format = (key, "$" + given, gift, "$" + average) + donor_row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*row_format) + print(donor_row) + print("\n") + +def sort_total_donation(number): + return number[1][0] + + +# this makes a text that has the thankyou message to all the current doners on the list +# the title of the file has the date and the name of the person on the list +def send_letters_to_all_donors(): + '''generate thank you letter to all donors''' + for key in donor_db: + with open(key + "_" + str(datetime.date.today()) + ".txt", 'w') as f: + f.write("Dear {name},\n" + "\n" + " Thank you for your very kind donation of ${amount:10.2f}.\n" + "\n" + " It will be put to very good use.\n" + "\n" + " Sincerely\n" + " -The Team".format(name=key, amount=donor_db[key][0])) + print("Thank you letters to all donors have been generated in the local disk.\n") + + +def exit_program(): + print("Exiting the program") + sys.exit() + + +def main(): + while True: + try: + choice = '' + choice = int(input(menu())) + if choice in main_menu: + main_menu[choice]() + else: + print("Not a valid option, try again.") + except ValueError: + print("Selection has to be a number, try again.\n") + +# the main frame of the console +main_menu = {1: send_a_thankyou, + 2: create_a_report, + 3: exit_program, + 4: send_letters_to_all_donors + } + +if __name__ == "__main__": + donor_db = {"William Gates, III": [653784.49, 2], + "Mark Zuckerberg": [16396.10, 3], + "Jeff Bezos": [877.33, 1], + "Paul Allen": [708.42, 3], + } + + main() + diff --git a/students/WooseokJ/exceptWJ.py b/students/WooseokJ/exceptWJ.py new file mode 100644 index 00000000..b23b6d28 --- /dev/null +++ b/students/WooseokJ/exceptWJ.py @@ -0,0 +1,59 @@ + +# coding: utf-8 + +# In[ ]: + + +#!/usr/bin/python + +""" +An exercise in playing with Exceptions. +Make lots of try/except blocks for fun and profit. + +Make sure to catch specifically the error you find, rather than all errors. +""" + +from except_test import fun, more_fun, last_fun + + +# Figure out what the exception is, catch it and while still +# in that catch block, try again with the second item in the list +first_try = ['spam', 'cheese', 'mr death'] +try: + joke = fun(first_try[0]) +except NameError: + joke = fun(first_try[1]) + +# Here is a try/except block. Add an else that prints not_joke +try: + not_joke = fun(first_try[2]) +except SyntaxError: + print('Run Away!') +else: + print(not_joke) +# What did that do? You can think of else in this context, as well as in +# loops as meaning: "else if nothing went wrong" +# (no breaks in loops, no exceptions in try blocks) + +# Figure out what the exception is, catch it and in that same block +# +# try calling the more_fun function with the 2nd language in the list, +# again assigning it to more_joke. +# +# If there are no exceptions, call the more_fun function with the last +# language in the list + +# Finally, while still in the try/except block and regardless of whether +# there were any exceptions, call the function last_fun with no +# parameters. (pun intended) + +langs = ['java', 'c', 'python'] +try: + more_joke= more_fun(langs[0]) +except IndexError: + more_joke = more_fun(langs[1]) +else: + more_joke = more_fun(langs[2]) +finally: + last_fun() + diff --git a/students/WooseokJ/except_test.py b/students/WooseokJ/except_test.py new file mode 100644 index 00000000..905dd675 --- /dev/null +++ b/students/WooseokJ/except_test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 + +""" +silly little test module that is designed to trigger Exceptions when +run from the except_exercise.py file +""" + +import time + +conclude = "And what leads you to that conclusion?" +district = "Finest in the district, sir." +cheese = "It's certainly uncontaminated by cheese." +clean = "Well, it's so clean." +shop = "Not much of a cheese shop really, is it?" +cust = "Customer: " +clerk = "Shopkeeper: " + + +def fun(reaper): + if reaper == 'spam': + print(s) + elif reaper == 'cheese': + print() + print('Spam, Spam, Spam, Spam, Beautiful Spam') + elif reaper == 'mr death': + print() + return('{}{}\n{}{}'.format(cust, shop, clerk, district)) + + +def more_fun(language): + if language == 'java': + test = [1, 2, 3] + test[5] = language + elif language == 'c': + print('{}{}\n{}{}'.format(cust, conclude, clerk, clean)) + + +def last_fun(): + print(cust, cheese) + time.sleep(1) + import antigravity From 34a4ee6ed68b763126f46b64838ed301f9c3ae12 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Sat, 23 Feb 2019 19:29:57 -0800 Subject: [PATCH 006/367] adding mailroom4 and test_mailroom4 --- students/mjchang/session06/mailroom4.py | 122 +++++++++++++++++++ students/mjchang/session06/test_mailroom4.py | 65 ++++++++++ 2 files changed, 187 insertions(+) create mode 100644 students/mjchang/session06/mailroom4.py create mode 100644 students/mjchang/session06/test_mailroom4.py diff --git a/students/mjchang/session06/mailroom4.py b/students/mjchang/session06/mailroom4.py new file mode 100644 index 00000000..23feff98 --- /dev/null +++ b/students/mjchang/session06/mailroom4.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 + +import os +import datetime +import sys +import unittest + +donor_db = {"Eliza Sommers": [4000, 250, 70], + "Tao Chien": [350, 1000, 225], + "Joaquin Andieta": [100, 25], + "Paulina Rodriguez": [50000], + "Jacob Todd": [75, 80]} + +def thank_you_one(): # adding a new vendor + while True: + name = input("Please enter a full name (or 'list' for a list of current donors): ") + name = name.title() #keeps capitalization format the same + if name.lower() == "list": + print('\n'.join(donor_db.keys())) #displays list of donors + + elif name not in donor_db.keys(): #adding new donor + print("Adding {} to the donor list".format(name)) + #adding exception for donation input that isn't a number + try: + donation = input("Enter the donation amount from {}: ".format(name)) #adding donation from new donor + donation = float(donation) #converting to a float + except (ValueError, EOFError): + print("Donation amount must be a number") + continue + donor_db.setdefault(name, []).append(donation) + break + + elif name in donor_db.keys(): #adding donation for existing donor + name = name.title() #keep capitalization same as keys + #adding exception for scenario where input isn't a number + try: + donation = input("Enter the new donation amount: ") + donation = float(donation) + except (ValueError, EOFError): + print("Donation amount must be a number") + continue + donor_db[name].append(donation) + print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) + break + + +# send the thank you letter to one donor + print("\n \n Generating the letter for {}\n \n".format(name)) + print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) + + +# send the thank you letter to all donors +def thank_you_all(): + path = os.getcwd() + folder = path + '/donor_letters/' + os.mkdir(folder) + os.chdir(folder) + for key in donor_db: + timestamp = str(datetime.date.today()) + with open(key + '_' + timestamp + ".txt", "w+") as f: + f.write("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation. \n You have helped make a big impact on the community!".format(key)) + f.close() + + print("Letters to all donors were generated.") + + +# set up for donor report +def sort_key(data): + return data[1] + +# create a report of donors and amounts +def donor_report(): + #using a list comprehension to simplify building the donor report + spreadsheet = [(name, sum(gifts), len(gifts), sum(gifts)/len(gifts)) + for name, gifts in donor_db.items()] + + #sort the report by total donation + spreadsheet.sort(key = sort_key) + + print("{:<30} | {:<12} | {:>15} | {:12}".format("Donor Name", "Total Given", "Number of Gifts", "Average Gift")) #print the header + print("-"*79) #print the dashed line + for data in spreadsheet: + print("{:<30} ${:12.2f} {:>15} ${:12.2f}".format(data[0], data[1], data[2], data[3])) + + + +def quit_program(): + sys.exit() + + + +def main(): + while True: + response = '' + response = int(input(""" + Please enter a number from the following options: + 1 - Send a Thank You to One Donor + 2 - Send a Thank You to All Donors + 3 - Create a Report + 4 - Quit + """)) + selection = {1: thank_you_one, + 2: thank_you_all, + 3: donor_report, + 4: quit_program + } + #adding exception to handle responses other than 1-4 + try: + if response in selection.keys(): + selection.get(response)() + else: + print("Please make a valid selection") + except (ValueError, EOFError): + print("Please select from the available options") + continue + + +if __name__ == "__main__": + + donor_db = donor_db() + + main() \ No newline at end of file diff --git a/students/mjchang/session06/test_mailroom4.py b/students/mjchang/session06/test_mailroom4.py new file mode 100644 index 00000000..b70ed622 --- /dev/null +++ b/students/mjchang/session06/test_mailroom4.py @@ -0,0 +1,65 @@ +#!/usr/bon/env python3 + + +import os +import sys +import unittest + +import mailroom4 + +mr4.donor_db = mailroom4.donor_db() + +def test_donor_list(): + """ test to see if donors are showing up in list""" + donors = mr4.donor_db.keys() + assert len(donors.split('\n')) == 5 + assert "Tao Chien" in donors + assert "Eliza Sommers" in donors + + +def test_no_donor_search(): + """ test that a new donor doesn't show up""" + donor = mr4.donor_db.keys() + assert donor is None + + + +def test_donor_search(): + """ test that an existing donor is there +also test if existing donor can be found using different capitalization inputs""" + donor = mr4.donor_db.keys() + assert donor[2] == "Joaquin Andieta" + assert donor[4] == "Jacob Todd" + + + +def test_gen_single_letter(): + """test that the donor letter/message is generated""" + pass + + +def test_donor_addition(): + """ test that new donor is added""" + pass + + +def test_create_report(): + """ test that the donor report is created and displayed correctly""" + pass + + +def test_gen_letters(): + """ test that letters were generated and saved to the specified folder""" + pass + + +if __name__ == "__main__": + test_donor_list() + test_no_donor_search() + test_donor_search() + test_gen_single_letter() + test_donor_addition() + test_create_report() + test_gen_letters() + print("All the tests passed!") + From 0b56d035aa03b04daaa5b400de9a5a75d3ecfdc3 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Sun, 24 Feb 2019 17:50:05 -0800 Subject: [PATCH 007/367] split thank_you_one function into 4 parts --- students/mjchang/session06/mailroom4.py | 103 +++++++++++++++++------- 1 file changed, 72 insertions(+), 31 deletions(-) diff --git a/students/mjchang/session06/mailroom4.py b/students/mjchang/session06/mailroom4.py index 23feff98..7f10c8f8 100644 --- a/students/mjchang/session06/mailroom4.py +++ b/students/mjchang/session06/mailroom4.py @@ -5,48 +5,89 @@ import sys import unittest -donor_db = {"Eliza Sommers": [4000, 250, 70], + +def donor_db(): #defining donor database to make it easier to test + return {"Eliza Sommers": [4000, 250, 70], "Tao Chien": [350, 1000, 225], "Joaquin Andieta": [100, 25], "Paulina Rodriguez": [50000], "Jacob Todd": [75, 80]} +def donor_list(): + print('\n'.join(donor_db.keys())) #displays list of donors + + +def add_new_donor(name): + print("Adding {} to the donor list".format(name)) + #adding exception for donation input that isn't a number + try: + donation = input("Enter the donation amount from {}: ".format(name)) #adding donation from new donor + donation = float(donation) #converting to a float + except (ValueError, EOFError): + print("Donation amount must be a number") + continue + donor_db.setdefault(name, []).append(donation) + break + + +def add_new_donation(): + try: + donation = input("Enter the new donation amount: ") + donation = float(donation) + except (ValueError, EOFError): + print("Donation amount must be a number") + continue + donor_db[name].append(donation) + print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) + break + + +def ty_message_one(name, donation): + + print("\n \n Generating the letter for {}\n \n".format(name)) + print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) + + + def thank_you_one(): # adding a new vendor while True: name = input("Please enter a full name (or 'list' for a list of current donors): ") name = name.title() #keeps capitalization format the same if name.lower() == "list": - print('\n'.join(donor_db.keys())) #displays list of donors + donor_list() - elif name not in donor_db.keys(): #adding new donor - print("Adding {} to the donor list".format(name)) - #adding exception for donation input that isn't a number - try: - donation = input("Enter the donation amount from {}: ".format(name)) #adding donation from new donor - donation = float(donation) #converting to a float - except (ValueError, EOFError): - print("Donation amount must be a number") - continue - donor_db.setdefault(name, []).append(donation) - break + elif name not in donor_db.keys(): + add_new_donor(name) + #adding new donor + # print("Adding {} to the donor list".format(name)) + # #adding exception for donation input that isn't a number + # try: + # donation = input("Enter the donation amount from {}: ".format(name)) #adding donation from new donor + # donation = float(donation) #converting to a float + # except (ValueError, EOFError): + # print("Donation amount must be a number") + # continue + # donor_db.setdefault(name, []).append(donation) + # break elif name in donor_db.keys(): #adding donation for existing donor - name = name.title() #keep capitalization same as keys + # name = name.title() #keep capitalization same as keys #adding exception for scenario where input isn't a number - try: - donation = input("Enter the new donation amount: ") - donation = float(donation) - except (ValueError, EOFError): - print("Donation amount must be a number") - continue - donor_db[name].append(donation) - print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) - break - - -# send the thank you letter to one donor - print("\n \n Generating the letter for {}\n \n".format(name)) - print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) + add_new_donation() + # try: + # donation = input("Enter the new donation amount: ") + # donation = float(donation) + # except (ValueError, EOFError): + # print("Donation amount must be a number") + # continue + # donor_db[name].append(donation) + # print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) + # break + # send the thank you letter to one donor + ty_message_one() + # print("\n \n Generating the letter for {}\n \n".format(name)) + # print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) + # send the thank you letter to all donors @@ -83,12 +124,11 @@ def donor_report(): print("{:<30} ${:12.2f} {:>15} ${:12.2f}".format(data[0], data[1], data[2], data[3])) - def quit_program(): + print("Goodbye!\n") sys.exit() - def main(): while True: response = '' @@ -117,6 +157,7 @@ def main(): if __name__ == "__main__": - donor_db = donor_db() + + donor_db = donor_db() main() \ No newline at end of file From d126293d9bc2af18ca565fb6832ca30b845af08a Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Sun, 24 Feb 2019 20:53:00 -0800 Subject: [PATCH 008/367] adding mailroom4.1 - cleaned up thank_you_one function --- students/mjchang/session06/mailroom4.1.py | 124 ++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 students/mjchang/session06/mailroom4.1.py diff --git a/students/mjchang/session06/mailroom4.1.py b/students/mjchang/session06/mailroom4.1.py new file mode 100644 index 00000000..45eaf7d3 --- /dev/null +++ b/students/mjchang/session06/mailroom4.1.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +import os +import datetime +import sys +import unittest + + +def donor_db(): #defining donor database to make it easier to test + return {"Eliza Sommers": [4000, 250, 70], + "Tao Chien": [350, 1000, 225], + "Joaquin Andieta": [100, 25], + "Paulina Rodriguez": [50000], + "Jacob Todd": [75, 80]} + +def donor_list(): #splitting thank_you_one function into multiple parts in mailroom4 + print('\n'.join(donor_db.keys())) #displays list of donors + + + +def thank_you_one(): # adding a new vendor + while True: + name = input("Please enter a full name (or 'list' for a list of current donors): ") + name = name.title() #keeps capitalization format the same + if name.lower() == "list": + donor_list() + else: + break + + if name not in donor_db.keys(): #adding new donor + print("Adding {} to the donor list".format(name)) + donor_db.setdefault(name, []) + break + + + while True: + name = name.title() #keep capitalization same as keys + #adding exception for scenario where input isn't a number + try: + donation = input("Enter the new donation amount: ") + donation = float(donation) + except (ValueError, EOFError): + print("Donation amount must be a number") + continue + donor_db[name].append(donation) + break + print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) + +# send the thank you letter to one donor + print("\n \n Generating the letter for {}\n \n".format(name)) + print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) + + +# send the thank you letter to all donors +def thank_you_all(): + path = os.getcwd() + folder = path + '/donor_letters/' + os.mkdir(folder) + os.chdir(folder) + for key in donor_db: + timestamp = str(datetime.date.today()) + with open(key + '_' + timestamp + ".txt", "w+") as f: + f.write("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation. \n You have helped make a big impact on the community!".format(key)) + f.close() + + print("Letters to all donors were generated.") + + +# set up for donor report +def sort_key(data): + return data[1] + +# create a report of donors and amounts +def donor_report(): + #using a list comprehension to simplify building the donor report + spreadsheet = [(name, sum(gifts), len(gifts), sum(gifts)/len(gifts)) + for name, gifts in donor_db.items()] + + #sort the report by total donation + spreadsheet.sort(key = sort_key) + + print("{:<30} | {:<12} | {:>15} | {:12}".format("Donor Name", "Total Given", "Number of Gifts", "Average Gift")) #print the header + print("-"*79) #print the dashed line + for data in spreadsheet: + print("{:<30} ${:12.2f} {:>15} ${:12.2f}".format(data[0], data[1], data[2], data[3])) + + +def quit_program(): + print("Goodbye!\n") + sys.exit() + + +def main(): + while True: + response = '' + response = int(input(""" + Please enter a number from the following options: + 1 - Send a Thank You to One Donor + 2 - Send a Thank You to All Donors + 3 - Create a Report + 4 - Quit + """)) + selection = {1: thank_you_one, + 2: thank_you_all, + 3: donor_report, + 4: quit_program + } + #adding exception to handle responses other than 1-4 + try: + if response in selection.keys(): + selection.get(response)() + else: + print("Please make a valid selection") + except (ValueError, EOFError): + print("Please select from the available options") + continue + + +if __name__ == "__main__": + + + donor_db = donor_db() + + main() \ No newline at end of file From 45ddd7b9910d3245d684a56e4fadb4906f1b0d00 Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 24 Feb 2019 22:24:10 -0800 Subject: [PATCH 009/367] lessons 6 submission added fixes commented on lessons 5 as well --- students/WooseokJ/MailP4WJ.py | 149 ++++++++++++++++++++++++++++++ students/WooseokJ/MailP4testWJ.py | 29 ++++++ 2 files changed, 178 insertions(+) create mode 100644 students/WooseokJ/MailP4WJ.py create mode 100644 students/WooseokJ/MailP4testWJ.py diff --git a/students/WooseokJ/MailP4WJ.py b/students/WooseokJ/MailP4WJ.py new file mode 100644 index 00000000..ccbc7652 --- /dev/null +++ b/students/WooseokJ/MailP4WJ.py @@ -0,0 +1,149 @@ + +# coding: utf-8 + +# In[12]: + + +import sys +import datetime +import operator + + +def menu(): + return(''''Menu + Please choose from below options: + 1 - Send a Thank You + 2 - Create a Report + 3 - Exit the program + 4 - Print thank you letter to all current donors''') + + +# first it will ask to choose a name whoom you would want to send the mail +# along side that when typing list it will give you all the names on the current list +# second if the name is not in the list then it will prompt to add the name into the data base +# lastly it will print the message of the email +#added excepts to close off any errors that has to do with input errors +def send_a_thankyou(): + while True: + fullname = input("Enter the full name of the donor typing list will give the names of current doners ") + if fullname.lower() == 'list': + for donor in donor_db: + print(donor) + else: + while True: + try: + amount = float(input("Please enter the donation amount: ")) + break + except ValueError: + print("Invalid input please try again") + send_a_thankyou(fullname, amount, donor_db) + print(f"${amount} has been updated to {fullname}'s donation history.") + break + print(f'Thank you {fullname} for your donation of ${amount:^10.2f}!') + print() + menu() + + +def send_thankyou_test(fullname, amount, donor_list): + donor_list = [donor.lower() for donor in donor_list] + if fullname.lower() not in donor_list: + print(f'{fullname} does not exist in the donor data, ' + f'we will add {fullname} to the donor data.') + donor_list[fullname] = [amount,1] + elif fullname.lower() in donor_list: + donor_list[fullname][0] = donor_list[fullname][0] + amount + donor_list[fullname][1] = donor_list[fullname][1] + 1 + return fullname, donor_list[fullname] + + +# this prints out the database of the donors with their total amaounts and average amount donated +def create_a_report(): + print("Printing report:") + title = ("Donor Name", "| Total Given", "| Num Gifts", "| Average Gift") + row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*title) + length = len(row) + print("\n" + row) + print("=" * length) + for key, value in sorted(donor_db.items()): + given = str(sum(value)) + gift = str(len(value)) + average = str(sum(value) / (len(value))) + row_format = (key, "$" + given, gift, "$" + average) + donor_row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*row_format) + print(donor_row) + print("\n") + + +def create_a_report_test(): + print("Printing report:") + title = ("Donor Name", "| Total Given", "| Num Gifts", "| Average Gift") + row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*title) + length = len(row) + print("\n" + row) + print("=" * length) + for key, value in sorted(donor_db.items()): + given = sum(value[1]) + gift = len(value[1]) + average = sum(value[1]) / (len(value[1])) + row_format = (key, "$" + given, gift, "$" + average) + donor_row = " ".join(["{:<19} | {:^13} | {:^13} | {:^11}"]).format(*row_format) + print(donor_row) + print("\n") + + +def sort_total_donation(number): + return number[1][0] + + +# this makes a text that has the thankyou message to all the current doners on the list +# the title of the file has the date and the name of the person on the list +def send_letters_to_all_donors(): + '''generate thank you letter to all donors''' + for key in donor_db: + with open(key + "_" + str(datetime.date.today()) + ".txt", 'w') as f: + f.write(send_letter_to_all_donors_test(key,donor_db)) + print("Thank you letters to all donors have been generated in the local disk.\n") + + +def send_letter_to_all_donors_test(key, donor_list): + return ("Dear {name},\n" + "\n" + " Thank you for your very kind donation of ${amount:10.2f}.\n" + "\n" + " It will be put to very good use.\n" + "\n" + " Sincerely\n" + " -The Team".format(name=key, amount=donor_list[key][0])) + +def exit_program(): + print("Exiting the program") + sys.exit() + + +def main(): + while True: + try: + choice = '' + choice = int(input(menu())) + if choice in main_menu: + main_menu[choice]() + else: + print("Not a valid option, try again.") + except ValueError: + print("Selection has to be a number, try again.\n") + +# the main frame of the console +main_menu = {1: send_a_thankyou, + 2: create_a_report, + 3: exit_program, + 4: send_letters_to_all_donors + } + +if __name__ == "__main__": + donor_db = {"William Gates, III": [653784.49, 2], + "Mark Zuckerberg": [16396.10, 3], + "Jeff Bezos": [877.33, 1], + "Paul Allen": [708.42, 3], + } + + main() \ No newline at end of file diff --git a/students/WooseokJ/MailP4testWJ.py b/students/WooseokJ/MailP4testWJ.py new file mode 100644 index 00000000..c643184e --- /dev/null +++ b/students/WooseokJ/MailP4testWJ.py @@ -0,0 +1,29 @@ +# import from the MailP4WJ file to test +from MailP4WJ import send_thankyou_test +from MailP4WJ import create_a_report_test +from MailP4WJ import send_letter_to_all_donors_test + +donor_db = {"William Gates, III": [653784.49, 2], + "Mark Zuckerberg": [16396.10, 3], + "Jeff Bezos": [877.33, 1], + "Paul Allen": [708.42, 3], + } + +# tests the sending the thank you test +def test_thankyou(): + expected = ('Paul Allen', [708.42, 3]) + assert send_thankyou_test('Paul Allen' , 100, donor_db) == expected + +# tests the making the report function +def test_report(): + expected = "Paul Allen | $711.42 | 2 | $355.71 " + assert create_a_report_test('Paul Allen', [711.42, 2]) == expected + +# tests the contents of the letter created +def test_letter(): + expected = "Dear Paul Allen ,\n\n" \ + " Thank you for your very kind donation of $ 711.42.\n" \ + "\n" \ + " Sincerely\n" \ + " -The Team" + assert send_letter_to_all_donors_test() == expected From bdd42d0f69b2fe69813bfa820946a06cc0e386a4 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Sun, 24 Feb 2019 22:41:05 -0800 Subject: [PATCH 010/367] updated mailroom4 to match naming used in test_mailroom4 --- students/mjchang/session06/mailroom4.1.py | 3 +- students/mjchang/session06/mailroom4.py | 63 ++++++----------------- 2 files changed, 18 insertions(+), 48 deletions(-) diff --git a/students/mjchang/session06/mailroom4.1.py b/students/mjchang/session06/mailroom4.1.py index 45eaf7d3..2c683c20 100644 --- a/students/mjchang/session06/mailroom4.1.py +++ b/students/mjchang/session06/mailroom4.1.py @@ -30,7 +30,8 @@ def thank_you_one(): # adding a new vendor if name not in donor_db.keys(): #adding new donor print("Adding {} to the donor list".format(name)) donor_db.setdefault(name, []) - break + else: + pass while True: diff --git a/students/mjchang/session06/mailroom4.py b/students/mjchang/session06/mailroom4.py index 7f10c8f8..fc932d45 100644 --- a/students/mjchang/session06/mailroom4.py +++ b/students/mjchang/session06/mailroom4.py @@ -13,40 +13,35 @@ def donor_db(): #defining donor database to make it easier to test "Paulina Rodriguez": [50000], "Jacob Todd": [75, 80]} -def donor_list(): +def donor_list(): #splitting thank_you_one function into multiple parts in mailroom4 print('\n'.join(donor_db.keys())) #displays list of donors +def gen_letter(name, donation): + print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) + print("\n \n Generating the letter for {}\n \n".format(name)) + print("Dear {}, \n\n On behalf of all of us, we thank you for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) + + def add_new_donor(name): print("Adding {} to the donor list".format(name)) - #adding exception for donation input that isn't a number + #adding exception for donation input that isn't a number try: donation = input("Enter the donation amount from {}: ".format(name)) #adding donation from new donor donation = float(donation) #converting to a float except (ValueError, EOFError): - print("Donation amount must be a number") - continue + print("Donation amount must be a number") donor_db.setdefault(name, []).append(donation) - break - + gen_letter(name, donation) -def add_new_donation(): +def add_new_donation(name): try: donation = input("Enter the new donation amount: ") donation = float(donation) except (ValueError, EOFError): print("Donation amount must be a number") - continue donor_db[name].append(donation) - print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) - break - - -def ty_message_one(name, donation): - - print("\n \n Generating the letter for {}\n \n".format(name)) - print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) - + gen_letter(name, donation) def thank_you_one(): # adding a new vendor @@ -56,39 +51,13 @@ def thank_you_one(): # adding a new vendor if name.lower() == "list": donor_list() - elif name not in donor_db.keys(): + elif name not in donor_db.keys(): #adding new donor add_new_donor(name) - #adding new donor - # print("Adding {} to the donor list".format(name)) - # #adding exception for donation input that isn't a number - # try: - # donation = input("Enter the donation amount from {}: ".format(name)) #adding donation from new donor - # donation = float(donation) #converting to a float - # except (ValueError, EOFError): - # print("Donation amount must be a number") - # continue - # donor_db.setdefault(name, []).append(donation) - # break + break elif name in donor_db.keys(): #adding donation for existing donor - # name = name.title() #keep capitalization same as keys - #adding exception for scenario where input isn't a number - add_new_donation() - # try: - # donation = input("Enter the new donation amount: ") - # donation = float(donation) - # except (ValueError, EOFError): - # print("Donation amount must be a number") - # continue - # donor_db[name].append(donation) - # print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) - # break - # send the thank you letter to one donor - ty_message_one() - # print("\n \n Generating the letter for {}\n \n".format(name)) - # print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) - - + add_new_donation(name) + break # send the thank you letter to all donors def thank_you_all(): From b7cf1c8abbdadc103159b34281a72d8242f6ceb3 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Mon, 25 Feb 2019 22:02:05 -0800 Subject: [PATCH 011/367] got test_create_report to work --- students/mjchang/session06/test_mailroom4.py | 53 ++++++++++++-------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/students/mjchang/session06/test_mailroom4.py b/students/mjchang/session06/test_mailroom4.py index b70ed622..9f401d39 100644 --- a/students/mjchang/session06/test_mailroom4.py +++ b/students/mjchang/session06/test_mailroom4.py @@ -1,56 +1,69 @@ #!/usr/bon/env python3 - import os import sys +import datetime import unittest -import mailroom4 +import mailroom4 as mr4 -mr4.donor_db = mailroom4.donor_db() +mr4.donor_db = mr4.donor_db() def test_donor_list(): """ test to see if donors are showing up in list""" donors = mr4.donor_db.keys() - assert len(donors.split('\n')) == 5 + assert len(donors) == 5 assert "Tao Chien" in donors assert "Eliza Sommers" in donors def test_no_donor_search(): """ test that a new donor doesn't show up""" - donor = mr4.donor_db.keys() + donor = mr4.donor_db.get("Mama Fresia") assert donor is None - def test_donor_search(): - """ test that an existing donor is there -also test if existing donor can be found using different capitalization inputs""" - donor = mr4.donor_db.keys() - assert donor[2] == "Joaquin Andieta" - assert donor[4] == "Jacob Todd" - + """ test that an existing donor is there""" + donors = mr4.donor_db.keys() + assert "Joaquin Andieta" in donors def test_gen_single_letter(): - """test that the donor letter/message is generated""" - pass + """test that the donor letter/message is generated + bring in a test donor, then check the letter""" + expected = "Dear Jacob Todd, \n\n Thank you for your generous donation of $ 100.00. \n You have helped make a big impact on the community!" + assert mr4.generate_letter("Jacob Todd", 100.00) == expected + def test_donor_addition(): - """ test that new donor is added""" - pass + """ test that new donor is added + created a test new donor and donation, then check that new donor is in the donor_db""" + name = "Isabel Allende" + donation = 2500 + mr4.donor_db.setdefault(name, []).append(donation) + donors = mr4.donor_db.keys() + don_amt = mr4.donor_db.values() + assert "Isabel Allende" in donors + assert mr4.donor_db.get("Isabel Allende") == [2500] def test_create_report(): - """ test that the donor report is created and displayed correctly""" - pass + """ test that the donor report is created + using a random line from the report to test that it displays correctly""" + expected = "Paulina Rodriguez $ 50000.00 1 $ 50000.00" + assert mr4.report_line(["Paulina Rodriguez", 50000, 1, 50000]) == expected def test_gen_letters(): - """ test that letters were generated and saved to the specified folder""" - pass + """ test that letters were generated to separate files""" + timestamp = str(datetime.date.today()) + assert os.path.isfile('Tao Chien_'+timestamp+'.txt') + assert os.path.isfile('Joaquin Andieta_'+timestamp+'.txt') + +def test_get_letter_text(): + expected = "" if __name__ == "__main__": From f00c90ecbdab10ee21a909be76dd30539d16852c Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Mon, 25 Feb 2019 22:33:05 -0800 Subject: [PATCH 012/367] adding mailroom4 and test_mailroom4 for submission --- students/mjchang/session06/mailroom4.py | 22 ++++++++++++-------- students/mjchang/session06/test_mailroom4.py | 10 ++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/students/mjchang/session06/mailroom4.py b/students/mjchang/session06/mailroom4.py index fc932d45..fc2c73bb 100644 --- a/students/mjchang/session06/mailroom4.py +++ b/students/mjchang/session06/mailroom4.py @@ -17,11 +17,9 @@ def donor_list(): #splitting thank_you_one function into multiple parts in mailr print('\n'.join(donor_db.keys())) #displays list of donors -def gen_letter(name, donation): - print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) - print("\n \n Generating the letter for {}\n \n".format(name)) - print("Dear {}, \n\n On behalf of all of us, we thank you for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) - +def generate_letter(name, donation): + message = "Dear {}, \n\n Thank you for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation) + return message def add_new_donor(name): print("Adding {} to the donor list".format(name)) @@ -32,7 +30,7 @@ def add_new_donor(name): except (ValueError, EOFError): print("Donation amount must be a number") donor_db.setdefault(name, []).append(donation) - gen_letter(name, donation) + print(generate_letter(name, donation)) def add_new_donation(name): try: @@ -41,7 +39,7 @@ def add_new_donation(name): except (ValueError, EOFError): print("Donation amount must be a number") donor_db[name].append(donation) - gen_letter(name, donation) + print(generate_letter(name, donation)) def thank_you_one(): # adding a new vendor @@ -59,6 +57,9 @@ def thank_you_one(): # adding a new vendor add_new_donation(name) break +def thank_you_all_text(key): + return "Dear {}, \n\n On behalf of all of us, we thank your for your generous donation. \n You have helped make a big impact on the community!".format(key) + # send the thank you letter to all donors def thank_you_all(): path = os.getcwd() @@ -68,7 +69,7 @@ def thank_you_all(): for key in donor_db: timestamp = str(datetime.date.today()) with open(key + '_' + timestamp + ".txt", "w+") as f: - f.write("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation. \n You have helped make a big impact on the community!".format(key)) + f.write(thank_you_all_text(key)) f.close() print("Letters to all donors were generated.") @@ -78,6 +79,9 @@ def thank_you_all(): def sort_key(data): return data[1] +def report_line(data): + return "{:<30} ${:12.2f} {:>15} ${:12.2f}".format(data[0], data[1], data[2], data[3]) + # create a report of donors and amounts def donor_report(): #using a list comprehension to simplify building the donor report @@ -90,7 +94,7 @@ def donor_report(): print("{:<30} | {:<12} | {:>15} | {:12}".format("Donor Name", "Total Given", "Number of Gifts", "Average Gift")) #print the header print("-"*79) #print the dashed line for data in spreadsheet: - print("{:<30} ${:12.2f} {:>15} ${:12.2f}".format(data[0], data[1], data[2], data[3])) + print(report_line(data)) def quit_program(): diff --git a/students/mjchang/session06/test_mailroom4.py b/students/mjchang/session06/test_mailroom4.py index 9f401d39..c0ef5957 100644 --- a/students/mjchang/session06/test_mailroom4.py +++ b/students/mjchang/session06/test_mailroom4.py @@ -34,7 +34,6 @@ def test_gen_single_letter(): bring in a test donor, then check the letter""" expected = "Dear Jacob Todd, \n\n Thank you for your generous donation of $ 100.00. \n You have helped make a big impact on the community!" assert mr4.generate_letter("Jacob Todd", 100.00) == expected - def test_donor_addition(): @@ -58,13 +57,18 @@ def test_create_report(): def test_gen_letters(): """ test that letters were generated to separate files""" + path = os.getcwd() + folder = path + '/donor_letters/' + os.chdir(folder) timestamp = str(datetime.date.today()) assert os.path.isfile('Tao Chien_'+timestamp+'.txt') assert os.path.isfile('Joaquin Andieta_'+timestamp+'.txt') def test_get_letter_text(): - expected = "" - + """ test that content of generated letters is pulling in the name correctly + we don't want the letter to be addressed to the wrong person""" + expected = "Dear Eliza Sommers, \n\n On behalf of all of us, we thank your for your generous donation. \n You have helped make a big impact on the community!" + assert mr4.thank_you_all_text('Eliza Sommers') == expected if __name__ == "__main__": test_donor_list() From 0d96c0b40562325ff4184723312a115394f5378d Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Mon, 25 Feb 2019 22:35:25 -0800 Subject: [PATCH 013/367] submitting an updated version of test_mailroom4 --- students/mjchang/session06/test_mailroom4.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/students/mjchang/session06/test_mailroom4.py b/students/mjchang/session06/test_mailroom4.py index c0ef5957..4ee12240 100644 --- a/students/mjchang/session06/test_mailroom4.py +++ b/students/mjchang/session06/test_mailroom4.py @@ -56,7 +56,8 @@ def test_create_report(): def test_gen_letters(): - """ test that letters were generated to separate files""" + """ test that letters were generated to separate files + mailroom4.py, option 2 has to be run first otherwise there's nothing to test against""" path = os.getcwd() folder = path + '/donor_letters/' os.chdir(folder) From 3501da99b3b03d2b41864e7fcb5d4aea8d144431 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Mon, 25 Feb 2019 22:39:24 -0800 Subject: [PATCH 014/367] Removing mailroom4.1.py I overthought a few things and tried to make them work, but ended up reverting back to my previous file and used mailroom4 for the exercise. --- students/mjchang/session06/mailroom4.1.py | 125 ---------------------- 1 file changed, 125 deletions(-) delete mode 100644 students/mjchang/session06/mailroom4.1.py diff --git a/students/mjchang/session06/mailroom4.1.py b/students/mjchang/session06/mailroom4.1.py deleted file mode 100644 index 2c683c20..00000000 --- a/students/mjchang/session06/mailroom4.1.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 - -import os -import datetime -import sys -import unittest - - -def donor_db(): #defining donor database to make it easier to test - return {"Eliza Sommers": [4000, 250, 70], - "Tao Chien": [350, 1000, 225], - "Joaquin Andieta": [100, 25], - "Paulina Rodriguez": [50000], - "Jacob Todd": [75, 80]} - -def donor_list(): #splitting thank_you_one function into multiple parts in mailroom4 - print('\n'.join(donor_db.keys())) #displays list of donors - - - -def thank_you_one(): # adding a new vendor - while True: - name = input("Please enter a full name (or 'list' for a list of current donors): ") - name = name.title() #keeps capitalization format the same - if name.lower() == "list": - donor_list() - else: - break - - if name not in donor_db.keys(): #adding new donor - print("Adding {} to the donor list".format(name)) - donor_db.setdefault(name, []) - else: - pass - - - while True: - name = name.title() #keep capitalization same as keys - #adding exception for scenario where input isn't a number - try: - donation = input("Enter the new donation amount: ") - donation = float(donation) - except (ValueError, EOFError): - print("Donation amount must be a number") - continue - donor_db[name].append(donation) - break - print("\n \n The ${:.2f} donation from {} was added".format(donation, name)) - -# send the thank you letter to one donor - print("\n \n Generating the letter for {}\n \n".format(name)) - print("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation of ${:10.2f}. \n You have helped make a big impact on the community!".format(name, donation)) - - -# send the thank you letter to all donors -def thank_you_all(): - path = os.getcwd() - folder = path + '/donor_letters/' - os.mkdir(folder) - os.chdir(folder) - for key in donor_db: - timestamp = str(datetime.date.today()) - with open(key + '_' + timestamp + ".txt", "w+") as f: - f.write("Dear {}, \n\n On behalf of all of us, we thank your for your generous donation. \n You have helped make a big impact on the community!".format(key)) - f.close() - - print("Letters to all donors were generated.") - - -# set up for donor report -def sort_key(data): - return data[1] - -# create a report of donors and amounts -def donor_report(): - #using a list comprehension to simplify building the donor report - spreadsheet = [(name, sum(gifts), len(gifts), sum(gifts)/len(gifts)) - for name, gifts in donor_db.items()] - - #sort the report by total donation - spreadsheet.sort(key = sort_key) - - print("{:<30} | {:<12} | {:>15} | {:12}".format("Donor Name", "Total Given", "Number of Gifts", "Average Gift")) #print the header - print("-"*79) #print the dashed line - for data in spreadsheet: - print("{:<30} ${:12.2f} {:>15} ${:12.2f}".format(data[0], data[1], data[2], data[3])) - - -def quit_program(): - print("Goodbye!\n") - sys.exit() - - -def main(): - while True: - response = '' - response = int(input(""" - Please enter a number from the following options: - 1 - Send a Thank You to One Donor - 2 - Send a Thank You to All Donors - 3 - Create a Report - 4 - Quit - """)) - selection = {1: thank_you_one, - 2: thank_you_all, - 3: donor_report, - 4: quit_program - } - #adding exception to handle responses other than 1-4 - try: - if response in selection.keys(): - selection.get(response)() - else: - print("Please make a valid selection") - except (ValueError, EOFError): - print("Please select from the available options") - continue - - -if __name__ == "__main__": - - - donor_db = donor_db() - - main() \ No newline at end of file From 41797f47496d0a27fbb13c11c9e3ad47fd5d276a Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 28 Feb 2019 10:50:01 -0800 Subject: [PATCH 015/367] Update get value function --- students/jeff_shabani/session06/mailroom_4.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/students/jeff_shabani/session06/mailroom_4.py b/students/jeff_shabani/session06/mailroom_4.py index b4feaf40..64cdcd25 100644 --- a/students/jeff_shabani/session06/mailroom_4.py +++ b/students/jeff_shabani/session06/mailroom_4.py @@ -34,22 +34,6 @@ def get_value(text, check_type): print("Invalid value. Please try again") continue -def get_input(text): - return input(text) - -def get_value_test(text, check_type): - def get_value_test(text, check_type): - """ - Catch non-numeric entries for donation amount. - """ - text = get_input('Please enter a value') - try: - value = check_type(text) - return True - except ValueError: - return False - - def view_donor_names(): [print(name) for name in donors] From 2af98192c3377116ffb2a28c131c260cc4d70311 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 28 Feb 2019 11:06:19 -0800 Subject: [PATCH 016/367] Update testing to accept mock input. --- students/jeff_shabani/session06/test_mailroom_4.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/students/jeff_shabani/session06/test_mailroom_4.py b/students/jeff_shabani/session06/test_mailroom_4.py index 96ee7008..affe2db7 100644 --- a/students/jeff_shabani/session06/test_mailroom_4.py +++ b/students/jeff_shabani/session06/test_mailroom_4.py @@ -1,9 +1,8 @@ #!/usr/bin/env python3 +import mock import unittest from pathlib import Path -from unittest.mock import patch - from students.jeff_shabani.session06 import mailroom_4 ANSWER = 'New_Donor' @@ -59,13 +58,9 @@ def test_membership_in_dictionary(self): self.assertIn('Bobby', mailroom_4.create_new_donors_dict()) - @patch('students.jeff_shabani.session06.mailroom_4.get_value_test') - def test_correct_input(self, mock_input): - """ - test for correct input. Not currently working. - """ - mock_input.return_value = 6 - self.assertEqual(mailroom_4.get_value_test('Enter', int), 6) + @mock.patch('mailroom_4.get_value.input', mock.Mock(return_value='54')) + def test_correct_input(self): + self.assertEqual(mailroom_4.get_value('Enter a value:', int), 'Invalid') if __name__ == '__main__': From c1f768fe1de96d3263f50c1bab364013100fc5cf Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 28 Feb 2019 11:08:05 -0800 Subject: [PATCH 017/367] Update to html_render assignment --- students/jeff_shabani/session07/html_render.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 0739e75e..1f3e2b80 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -9,7 +9,10 @@ class Element(object): def __init__(self, content=None): - self.content = str(content) + if content: + self.content = content + else: + self.content = '' def append(self, new_content): result = list() From f420277b8d1356d27e3c5ba95efbca7306370777 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 28 Feb 2019 15:28:48 -0800 Subject: [PATCH 018/367] Session07 files --- students/jeff_shabani/session07/html_render.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 1f3e2b80..8944947d 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -23,9 +23,12 @@ def append(self, new_content): def render(self, out_file): - out_file.write("just something as a place holder...") + outtext = f'\n{self.content}\n' + out_file.write(outtext) -e=Element() -e.append('Wulliam\nB') +e=Element('Erst Line') +e.append('\nWulliam\nB') +with open('test.html', 'w') as outf: + e.render(outf) print(e.content) From 56c13bca742592ae4a29a03e876d3c72d66a139b Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Thu, 28 Feb 2019 16:43:36 -0800 Subject: [PATCH 019/367] Update to html_render --- students/jeff_shabani/session07/html_render.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 8944947d..c8bdbf54 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -18,17 +18,19 @@ def append(self, new_content): result = list() result.append(new_content) for i in result: - self.content +=i + self.content += i return self.content + def tag(self, tag): + self.tag = '' def render(self, out_file): outtext = f'\n{self.content}\n' out_file.write(outtext) -e=Element('Erst Line') + +e = Element('Erst Line') e.append('\nWulliam\nB') with open('test.html', 'w') as outf: e.render(outf) print(e.content) - From 266c629cbcd1e91b14c66e6d480008dd2f08d17c Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:07:23 -0800 Subject: [PATCH 020/367] First attempt at html_render. --- students/jeff_shabani/session07/html_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 69734249..94301f76 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -24,5 +24,5 @@ def render(self, out_file): e=Element() e.append('Line1\nLine2') -print(e.content) +#print(e.content) From d51976dbedbd0545dd31d8af2ace861d164efa53 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:07:50 -0800 Subject: [PATCH 021/367] First attempt at html_render. --- students/jeff_shabani/session06/test_mailroom_4.py | 1 + 1 file changed, 1 insertion(+) diff --git a/students/jeff_shabani/session06/test_mailroom_4.py b/students/jeff_shabani/session06/test_mailroom_4.py index 96ee7008..42832d99 100644 --- a/students/jeff_shabani/session06/test_mailroom_4.py +++ b/students/jeff_shabani/session06/test_mailroom_4.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import mock import unittest from pathlib import Path From 8777b94b61c8ee987a116043cde411cb17b5d082 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:12:23 -0800 Subject: [PATCH 022/367] Merge branch 'master' of https://github.com/Rockwell70/GP_Python210B_Winter_2019 # Conflicts: # students/jeff_shabani/session07/html_render.py --- students/jeff_shabani/session07/html_render.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index c8bdbf54..098164f8 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -21,11 +21,15 @@ def append(self, new_content): self.content += i return self.content - def tag(self, tag): - self.tag = '' + def tag(self): + tag = '' + return tag + + + def render(self, out_file): - outtext = f'\n{self.content}\n' + outtext = f'{self.tag()}\n{self.content}\n' out_file.write(outtext) From 3072e526a822c07b241b67f0ba22cedc91dd167b Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:12:43 -0800 Subject: [PATCH 023/367] Merge branch 'master' of https://github.com/Rockwell70/GP_Python210B_Winter_2019 # Conflicts: # students/jeff_shabani/session07/html_render.py --- students/jeff_shabani/session06/mailroom_4.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/students/jeff_shabani/session06/mailroom_4.py b/students/jeff_shabani/session06/mailroom_4.py index b4feaf40..64cdcd25 100644 --- a/students/jeff_shabani/session06/mailroom_4.py +++ b/students/jeff_shabani/session06/mailroom_4.py @@ -34,22 +34,6 @@ def get_value(text, check_type): print("Invalid value. Please try again") continue -def get_input(text): - return input(text) - -def get_value_test(text, check_type): - def get_value_test(text, check_type): - """ - Catch non-numeric entries for donation amount. - """ - text = get_input('Please enter a value') - try: - value = check_type(text) - return True - except ValueError: - return False - - def view_donor_names(): [print(name) for name in donors] From 7beba59331145b8625a489d2795880032b3215a5 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:12:57 -0800 Subject: [PATCH 024/367] Merge branch 'master' of https://github.com/Rockwell70/GP_Python210B_Winter_2019 # Conflicts: # students/jeff_shabani/session07/html_render.py --- students/jeff_shabani/session06/test_mailroom_4.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/students/jeff_shabani/session06/test_mailroom_4.py b/students/jeff_shabani/session06/test_mailroom_4.py index 42832d99..affe2db7 100644 --- a/students/jeff_shabani/session06/test_mailroom_4.py +++ b/students/jeff_shabani/session06/test_mailroom_4.py @@ -3,8 +3,6 @@ import unittest from pathlib import Path -from unittest.mock import patch - from students.jeff_shabani.session06 import mailroom_4 ANSWER = 'New_Donor' @@ -60,13 +58,9 @@ def test_membership_in_dictionary(self): self.assertIn('Bobby', mailroom_4.create_new_donors_dict()) - @patch('students.jeff_shabani.session06.mailroom_4.get_value_test') - def test_correct_input(self, mock_input): - """ - test for correct input. Not currently working. - """ - mock_input.return_value = 6 - self.assertEqual(mailroom_4.get_value_test('Enter', int), 6) + @mock.patch('mailroom_4.get_value.input', mock.Mock(return_value='54')) + def test_correct_input(self): + self.assertEqual(mailroom_4.get_value('Enter a value:', int), 'Invalid') if __name__ == '__main__': From 094d698e5d0412b7844f1a7b78ba3b8c4b79cfbe Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Fri, 1 Mar 2019 07:42:46 -0800 Subject: [PATCH 025/367] html_render update --- students/jeff_shabani/session07/html_render.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 098164f8..b87fdcf1 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -22,14 +22,11 @@ def append(self, new_content): return self.content def tag(self): - tag = '' + tag = 'body' return tag - - - def render(self, out_file): - outtext = f'{self.tag()}\n{self.content}\n' + outtext = f'<{self.tag()}>\n{self.content}\n' out_file.write(outtext) From adcd448ab91eef2b2df0772341c43625cf9b55b1 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Fri, 1 Mar 2019 09:42:51 -0800 Subject: [PATCH 026/367] Session07 files --- .../jeff_shabani/session07/html_render.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index b87fdcf1..58907e15 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -8,30 +8,39 @@ # This is the framework for the base class class Element(object): - def __init__(self, content=None): + def __init__(self, content=None, tag=None): + if tag: + self.tag = tag + else: + self.tag = '' if content: self.content = content else: self.content = '' + def append(self, new_content): result = list() result.append(new_content) for i in result: - self.content += i + self.content += f'\n{i}\n' return self.content - def tag(self): - tag = 'body' - return tag def render(self, out_file): - outtext = f'<{self.tag()}>\n{self.content}\n' + outtext = f'<{self.tag}>\n{self.content}\n' out_file.write(outtext) -e = Element('Erst Line') -e.append('\nWulliam\nB') +e = Element('First Line', 'body') +e.append('Second Line\nThird line') + with open('test.html', 'w') as outf: e.render(outf) -print(e.content) + +# """ +# Step 2 part A +# """ +# html_sub = Element('HTML subclass 1st line', 'html') +# html_sub.append('') + From 037398853ef6606eeaf1b61ec1dc45c754994997 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Fri, 1 Mar 2019 09:51:33 -0800 Subject: [PATCH 027/367] html_render update --- .../jeff_shabani/session07/html_render.py | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 58907e15..b9969bf9 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -23,24 +23,28 @@ def append(self, new_content): result = list() result.append(new_content) for i in result: - self.content += f'\n{i}\n' + self.content += i return self.content - def render(self, out_file): + # def render(self, out_file): + # outtext = f'<{self.tag}>\n{self.content}\n' + # out_file.write(outtext) + + def render2(self, file_name, open_method): outtext = f'<{self.tag}>\n{self.content}\n' - out_file.write(outtext) + with open(f'{file_name}.html', open_method) as file: + file.write(outtext) e = Element('First Line', 'body') e.append('Second Line\nThird line') +e.render2('test', 'w') -with open('test.html', 'w') as outf: - e.render(outf) - -# """ -# Step 2 part A -# """ -# html_sub = Element('HTML subclass 1st line', 'html') -# html_sub.append('') +""" +Step 2 part A +""" +html_sub = Element('HTML subclass 1st line', 'html') +html_sub.append('\nHTML subclass 2nd line') +html_sub.render2('html_subclass', 'w') From b3fbaad36312864d6e45a8b6813a5c8101cc599b Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Fri, 1 Mar 2019 15:37:22 -0800 Subject: [PATCH 028/367] Session07 files --- .../jeff_shabani/session07/html_render.py | 64 ++++++++++++++----- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index b9969bf9..97fdcf3b 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -8,7 +8,8 @@ # This is the framework for the base class class Element(object): - def __init__(self, content=None, tag=None): + def __init__(self, content=None, tag=None, **attrs): + self.attrs = attrs if tag: self.tag = tag else: @@ -23,28 +24,61 @@ def append(self, new_content): result = list() result.append(new_content) for i in result: - self.content += i + self.content += f'\n{i}\n' return self.content - # def render(self, out_file): - # outtext = f'<{self.tag}>\n{self.content}\n' - # out_file.write(outtext) - - def render2(self, file_name, open_method): - outtext = f'<{self.tag}>\n{self.content}\n' + def render(self, file_name, open_method='w'): + head = f'{self.tag} ' + for k,v in self.attrs.items(): + head += f'{k}={v}' + #outtext = f'<{self.tag}>\n{self.content}\n' + outtext = f'<{head}>\n{self.content}\n' with open(f'{file_name}.html', open_method) as file: file.write(outtext) -e = Element('First Line', 'body') -e.append('Second Line\nThird line') -e.render2('test', 'w') +""" +Step 2 part B +""" +class HTML(Element): + tag = 'html' + + +class PTag(Element): + tag = 'p' + """ -Step 2 part A +Step 3 """ -html_sub = Element('HTML subclass 1st line', 'html') -html_sub.append('\nHTML subclass 2nd line') -html_sub.render2('html_subclass', 'w') +class OneLineTag(Element): + def render(self, file_name, open_method='w'): + outtext = f'<{self.tag}> {self.content} ' + with open(f'{file_name}.html', open_method) as file: + file.write(outtext) + + +if __name__ == '__main__': + # e = Element("this is some text", 'body') + # e.append("and this is some more text") + # e.render('test') + + #html sub-class + # html_sub = HTML('HTML subclass 1st line', 'html') + # print(html_sub.tag) + # html_sub.append('HTML subclass 2nd line') + # html_sub.render('html_subclass') + # + # #p subclass + # p_sub = PTag('p subclass 1st line', 'p') + # p_sub.append('p subclass 2nd line') + # p_sub.render('p_subclass') + # + # olt = OneLineTag('PythonClass - oneliner', 'title') + # olt.render('OneLingTagTest') + + attrs_test = Element('kwargs test', 'html',style='text-align', id='intro') + attrs_test.append('kwargstest line 2') + attrs_test.render('kwargs_test') From ea0bd7cb8b7fe39a7c766bf49a15e89b4778eca9 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Fri, 1 Mar 2019 17:54:14 -0800 Subject: [PATCH 029/367] html_render update --- students/jeff_shabani/session07/html_render.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 97fdcf3b..91733a7a 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -29,9 +29,9 @@ def append(self, new_content): def render(self, file_name, open_method='w'): - head = f'{self.tag} ' + head = f'{self.tag.ljust(len(self.tag)+1)}' for k,v in self.attrs.items(): - head += f'{k}={v}' + head += f'{k.rjust(len(k)+1)}="{v}"' #outtext = f'<{self.tag}>\n{self.content}\n' outtext = f'<{head}>\n{self.content}\n' with open(f'{file_name}.html', open_method) as file: From b75d11e4ac5c913ec823cdc4021fb7c462918ef8 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:00:28 -0800 Subject: [PATCH 030/367] html_render update --- students/jeff_shabani/session07/html_render.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 91733a7a..cbf8a618 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -54,7 +54,10 @@ class PTag(Element): """ class OneLineTag(Element): def render(self, file_name, open_method='w'): - outtext = f'<{self.tag}> {self.content} ' + head = f'{self.tag.ljust(len(self.tag)+1)}' + for k,v in self.attrs.items(): + head += f'{k.rjust(len(k)+1)}="{v}"' + outtext = f'<{head}>\n{self.content}\n' with open(f'{file_name}.html', open_method) as file: file.write(outtext) @@ -78,6 +81,10 @@ def render(self, file_name, open_method='w'): # olt = OneLineTag('PythonClass - oneliner', 'title') # olt.render('OneLingTagTest') + """ + step 4 + """ + attrs_test = Element('kwargs test', 'html',style='text-align', id='intro') attrs_test.append('kwargstest line 2') attrs_test.render('kwargs_test') From aa5d94350a721a992c5d27b89cc7034a88336297 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Fri, 1 Mar 2019 19:40:30 -0800 Subject: [PATCH 031/367] html_render update --- .../jeff_shabani/session07/html_render.py | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index cbf8a618..10457699 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -53,6 +53,7 @@ class PTag(Element): Step 3 """ class OneLineTag(Element): + def render(self, file_name, open_method='w'): head = f'{self.tag.ljust(len(self.tag)+1)}' for k,v in self.attrs.items(): @@ -61,6 +62,27 @@ def render(self, file_name, open_method='w'): with open(f'{file_name}.html', open_method) as file: file.write(outtext) +""" +Step 5 +""" +class SelfClosingTag(Element): + + + def render(self, file_name, open_method='w'): + if self.content: + return TypeError + else: + self.content ='' + return self.content + + head = f'{self.tag.ljust(len(self.tag)+1)}' + for k,v in self.attrs.items(): + head += f'{k.rjust(len(k)+1)}="{v}"' + outtext = f'<{head}/>' + with open(f'{file_name}.html', open_method) as file: + file.write(outtext) + + if __name__ == '__main__': # e = Element("this is some text", 'body') @@ -78,14 +100,23 @@ def render(self, file_name, open_method='w'): # p_sub.append('p subclass 2nd line') # p_sub.render('p_subclass') # - # olt = OneLineTag('PythonClass - oneliner', 'title') + """ + Step 3 + """ + # olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') # olt.render('OneLingTagTest') + # + # """ + # step 4 + # """ + # attrs_test = Element('kwargs test', 'html',style='text-align', id='intro') + # attrs_test.append('kwargstest line 2') + # attrs_test.render('kwargs_test') """ - step 4 + step 5 """ - - attrs_test = Element('kwargs test', 'html',style='text-align', id='intro') - attrs_test.append('kwargstest line 2') - attrs_test.render('kwargs_test') + #sct_test = SelfClosingTag('html',style='text-align', id='intro') + sct_test = SelfClosingTag('html') + sct_test.render('sct_test') From c13f342319ca9b14a7745d76e90ca1cb71a94765 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Sat, 2 Mar 2019 00:19:57 -0800 Subject: [PATCH 032/367] adding html_render through step 3 --- students/mjchang/session07/html_render.py | 58 ++++ .../mjchang/session07/test_html_render.py | 290 ++++++++++++++++++ 2 files changed, 348 insertions(+) create mode 100644 students/mjchang/session07/html_render.py create mode 100644 students/mjchang/session07/test_html_render.py diff --git a/students/mjchang/session07/html_render.py b/students/mjchang/session07/html_render.py new file mode 100644 index 00000000..291351f3 --- /dev/null +++ b/students/mjchang/session07/html_render.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +""" +A class-based system for rendering html. +""" + + +# This is the framework for the base class +class Element(object): + + tag = "html" + + def __init__(self, content=None): + self.contents = [] + if content: + self.contents.append(content) + + def append(self, new_content): + self.contents.append(new_content) + + def render(self, out_file): + for content in self.contents: #adding contents to file + out_file.write("<{}>\n".format(self.tag)) + try: + content.render(out_file) + except AttributeError: + out_file.write(content) + out_file.write("\n") #newline to keep it readable + out_file.write("\n".format(self.tag)) + +class OneLineTag(Element): + def render(self, out_file,): + for content in self.contents: + out_file.write("<{}>".format(self.tag)) #removed newline + try: + content.render(out_file) + except AttributeError: + out_file.write(content) #removed newline from Element + out_file.write("\n".format(self.tag)) + + def append(self, content): + raise NotImplementedError + + +class Html(Element): + tag = "html" + +class Body(Element): + tag = "body" + +class P(Element): + tag = "p" + +class Head(Element): + tag = "head" + +class Title(OneLineTag): + tag = "title" diff --git a/students/mjchang/session07/test_html_render.py b/students/mjchang/session07/test_html_render.py new file mode 100644 index 00000000..f1228939 --- /dev/null +++ b/students/mjchang/session07/test_html_render.py @@ -0,0 +1,290 @@ +""" +test code for html_render.py + +This is just a start -- you will need more tests! +""" + +import io +import pytest + +# import * is often bad form, but makes it easier to test everything in a module. +from html_render import * + + +# utility function for testing render methods +# needs to be used in multiple tests, so we write it once here. +def render_result(element, ind=""): + """ + calls the element's render method, and returns what got rendered as a + string + """ + # the StringIO object is a "file-like" object -- something that + # provides the methods of a file, but keeps everything in memory + # so it can be used to test code that writes to a file, without + # having to actually write to disk. + outfile = io.StringIO() + # this so the tests will work before we tackle indentation + if ind: + element.render(outfile, ind) + else: + element.render(outfile) + return outfile.getvalue() + +######## +# Step 1 +######## + +def test_init(): + """ + This only tests that it can be initialized with and without + some content -- but it's a start + """ + e = Element() + + e = Element("this is some text") + + +def test_append(): + """ + This tests that you can append text + + It doesn't test if it works -- + that will be covered by the render test later + """ + e = Element("this is some text") + e.append("some more text") + + +def test_render_element(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + + It is not testing whether indentation or line feeds are correct. + """ + e = Element("this is some text") + e.append("and this is some more text") + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") + + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + +# Uncomment this one after you get the one above to pass +# Does it pass right away? +def test_render_element2(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + + It is not testing whether indentation or line feeds are correct. + """ + e = Element() + e.append("this is some text") + e.append("and this is some more text") + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") + + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + + + +# ######## +# # Step 2 +# ######## + +# tests for the new tags +def test_html(): + e = Html("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + print(file_contents) + assert file_contents.endswith("") + + +def test_body(): + e = Body("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("") + assert file_contents.endswith("") + + +def test_p(): + e = P("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("

") + assert file_contents.endswith("

") + + +def test_sub_element(): + """ + tests that you can add another element and still render properly + """ + page = Html() + page.append("some plain text.") + page.append(P("A simple paragraph of text")) + page.append("Some more plain text.") + + file_contents = render_result(page) + print(file_contents) # so we can see it if the test fails + + # note: The previous tests should make sure that the tags are getting + # properly rendered, so we don't need to test that here. + assert "some plain text" in file_contents + assert "A simple paragraph of text" in file_contents + assert "Some more plain text." in file_contents + assert "some plain text" in file_contents + # but make sure the embedded element's tags get rendered! + assert "" in file_contents + assert "" in file_contents + + + + +####### +# Step 3 +####### + +def test_head(): + e = Head("this is a text header") + + file_contents = render_result(e).strip() + + assert("this is a text header") in file_contents + assert file_contents.startswith("") + assert file_contents.endswith("") + +def test_title(): + e = Title("This is a Title") + # print(file_contents) + file_contents = render_result(e).strip() + + assert("This is a Title") in file_contents + assert file_contents.startswith("") + assert file_contents.endswith("") + assert "\n" not in file_contents + + +def test_one_line_tag_append(): + e = OneLineTag("initial content") + with pytest.raises(NotImplementedError): #disallow appending text + e.append("more content") + + file_contents = render_result(e).strip() + + +##################### +# indentation testing +# Uncomment for Step 9 -- adding indentation +##################### + + +# def test_indent(): +# """ +# Tests that the indentation gets passed through to the renderer +# """ +# html = Html("some content") +# file_contents = render_result(html, ind=" ").rstrip() #remove the end newline + +# print(file_contents) +# lines = file_contents.split("\n") +# assert lines[0].startswith(" <") +# print(repr(lines[-1])) +# assert lines[-1].startswith(" <") + + +# def test_indent_contents(): +# """ +# The contents in a element should be indented more than the tag +# by the amount in the indent class attribute +# """ +# html = Element("some content") +# file_contents = render_result(html, ind="") + +# print(file_contents) +# lines = file_contents.split("\n") +# assert lines[1].startswith(Element.indent) + + +# def test_multiple_indent(): +# """ +# make sure multiple levels get indented fully +# """ +# body = Body() +# body.append(P("some text")) +# html = Html(body) + +# file_contents = render_result(html) + +# print(file_contents) +# lines = file_contents.split("\n") +# for i in range(3): # this needed to be adapted to the tag +# assert lines[i + 1].startswith(i * Element.indent + "<") + +# assert lines[4].startswith(3 * Element.indent + "some") + + +# def test_element_indent1(): +# """ +# Tests whether the Element indents at least simple content + +# we are expecting to to look like this: + +# +# this is some text +# <\html> + +# More complex indentation should be tested later. +# """ +# e = Element("this is some text") + +# # This uses the render_results utility above +# file_contents = render_result(e).strip() + +# # making sure the content got in there. +# assert("this is some text") in file_contents + +# # break into lines to check indentation +# lines = file_contents.split('\n') +# # making sure the opening and closing tags are right. +# assert lines[0] == "" +# # this line should be indented by the amount specified +# # by the class attribute: "indent" +# assert lines[1].startswith(Element.indent + "thi") +# assert lines[2] == "" +# assert file_contents.endswith("") From 575826301b424f63310f512ff5c92210fe5350ec Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Sat, 2 Mar 2019 09:44:34 -0800 Subject: [PATCH 033/367] html_render update --- .../jeff_shabani/session07/html_render.py | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 10457699..66d942c8 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -19,7 +19,6 @@ def __init__(self, content=None, tag=None, **attrs): else: self.content = '' - def append(self, new_content): result = list() result.append(new_content) @@ -27,12 +26,10 @@ def append(self, new_content): self.content += f'\n{i}\n' return self.content - def render(self, file_name, open_method='w'): - head = f'{self.tag.ljust(len(self.tag)+1)}' - for k,v in self.attrs.items(): - head += f'{k.rjust(len(k)+1)}="{v}"' - #outtext = f'<{self.tag}>\n{self.content}\n' + head = f'{self.tag.ljust(len(self.tag) + 1)}' + for k, v in self.attrs.items(): + head += f'{k.rjust(len(k) + 1)}="{v}"' outtext = f'<{head}>\n{self.content}\n' with open(f'{file_name}.html', open_method) as file: file.write(outtext) @@ -41,6 +38,8 @@ def render(self, file_name, open_method='w'): """ Step 2 part B """ + + class HTML(Element): tag = 'html' @@ -50,46 +49,48 @@ class PTag(Element): """ -Step 3 +Step 3: print on one line """ + + class OneLineTag(Element): def render(self, file_name, open_method='w'): - head = f'{self.tag.ljust(len(self.tag)+1)}' - for k,v in self.attrs.items(): - head += f'{k.rjust(len(k)+1)}="{v}"' + head = f'{self.tag.ljust(len(self.tag) + 1)}' + for k, v in self.attrs.items(): + head += f'{k.rjust(len(k) + 1)}="{v}"' outtext = f'<{head}>\n{self.content}\n' with open(f'{file_name}.html', open_method) as file: file.write(outtext) + """ -Step 5 +Step 5: Self closing tag """ -class SelfClosingTag(Element): +class SelfClosingTag(Element): + def render(self, file_name, open_method='w'): if self.content: - return TypeError + print('Self closing tags do not have content') else: - self.content ='' - return self.content + self.content = '' - head = f'{self.tag.ljust(len(self.tag)+1)}' - for k,v in self.attrs.items(): - head += f'{k.rjust(len(k)+1)}="{v}"' + head = f'{self.tag.ljust(len(self.tag) + 1)}' + for k, v in self.attrs.items(): + head += f'{k.rjust(len(k) + 1)}="{v}"' outtext = f'<{head}/>' with open(f'{file_name}.html', open_method) as file: file.write(outtext) - if __name__ == '__main__': # e = Element("this is some text", 'body') # e.append("and this is some more text") # e.render('test') - #html sub-class + # html sub-class # html_sub = HTML('HTML subclass 1st line', 'html') # print(html_sub.tag) # html_sub.append('HTML subclass 2nd line') @@ -114,9 +115,9 @@ def render(self, file_name, open_method='w'): # attrs_test.render('kwargs_test') """ - step 5 + step 5 test for self closing tag """ - #sct_test = SelfClosingTag('html',style='text-align', id='intro') - sct_test = SelfClosingTag('html') + # sct_test = SelfClosingTag('html',style='text-align', id='intro') + sct_test = SelfClosingTag('_', 'html') sct_test.render('sct_test') - + # print(dir(sct_test)) From b91b6ada9a21697f9084807a0bf2ef1eafd6570f Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Sat, 2 Mar 2019 09:52:05 -0800 Subject: [PATCH 034/367] html_render update --- students/jeff_shabani/session07/html_render.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 66d942c8..f76644e4 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -72,8 +72,13 @@ def render(self, file_name, open_method='w'): class SelfClosingTag(Element): def render(self, file_name, open_method='w'): + """ + if conent is entered this tells user that self closing tags + can't have conent and resets the conent to an empty string. + """ + if self.content: - print('Self closing tags do not have content') + print('Self closing tags cannot have content') else: self.content = '' From fbe4eab95883ff36c2b4b71c646a21f3dde20b74 Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Sat, 2 Mar 2019 18:18:01 -0800 Subject: [PATCH 035/367] html_render update --- students/jeff_shabani/session07/html_render.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index f76644e4..26a511ee 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -56,10 +56,11 @@ class PTag(Element): class OneLineTag(Element): def render(self, file_name, open_method='w'): + self.tag = f'{self.tag}>' head = f'{self.tag.ljust(len(self.tag) + 1)}' for k, v in self.attrs.items(): head += f'{k.rjust(len(k) + 1)}="{v}"' - outtext = f'<{head}>\n{self.content}\n' + outtext = f'<{head}{self.content}' with open(f'{file_name}.html', open_method) as file: file.write(outtext) @@ -109,8 +110,8 @@ def render(self, file_name, open_method='w'): """ Step 3 """ - # olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') - # olt.render('OneLingTagTest') + olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') + olt.render('OneLingTagTest') # # """ # step 4 @@ -123,6 +124,6 @@ def render(self, file_name, open_method='w'): step 5 test for self closing tag """ # sct_test = SelfClosingTag('html',style='text-align', id='intro') - sct_test = SelfClosingTag('_', 'html') - sct_test.render('sct_test') + # sct_test = SelfClosingTag('_', 'html') + # sct_test.render('sct_test') # print(dir(sct_test)) From 8c059b266d68e6c2169561a31b4e0af3783ee90f Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Sun, 3 Mar 2019 01:12:38 -0800 Subject: [PATCH 036/367] adding html_render through step 5 --- students/mjchang/session07/html_render.py | 58 ++++- students/mjchang/session07/run_html_render.py | 231 ++++++++++++++++++ .../mjchang/session07/test_html_render.py | 54 ++++ 3 files changed, 337 insertions(+), 6 deletions(-) create mode 100644 students/mjchang/session07/run_html_render.py diff --git a/students/mjchang/session07/html_render.py b/students/mjchang/session07/html_render.py index 291351f3..7c27a67f 100644 --- a/students/mjchang/session07/html_render.py +++ b/students/mjchang/session07/html_render.py @@ -10,7 +10,8 @@ class Element(object): tag = "html" - def __init__(self, content=None): + def __init__(self, content=None, **kwargs): + self.attributes = kwargs self.contents = [] if content: self.contents.append(content) @@ -18,18 +19,33 @@ def __init__(self, content=None): def append(self, new_content): self.contents.append(new_content) + def render(self, out_file): - for content in self.contents: #adding contents to file - out_file.write("<{}>\n".format(self.tag)) + out_file.write(self._open_tag()) + out_file.write("\n") + for content in self.contents: try: content.render(out_file) except AttributeError: out_file.write(content) - out_file.write("\n") #newline to keep it readable - out_file.write("\n".format(self.tag)) + out_file.write("\n") + out_file.write(self._close_tag()) + out_file.write("\n") + + def _open_tag(self): + open_tag = ["<{}".format(self.tag)] + for key, value in self.attributes.items(): + open_tag.append(' {}="{}"'.format(key, value)) + open_tag.append(">") + return "".join(open_tag) + + def _close_tag(self): + return "\n".format(self.tag) + + class OneLineTag(Element): - def render(self, out_file,): + def render(self, out_file): for content in self.contents: out_file.write("<{}>".format(self.tag)) #removed newline try: @@ -42,6 +58,26 @@ def append(self, content): raise NotImplementedError +class SelfClosingTag(Element): + def __init__(self, content=None, **kwargs): + if content is not None: + raise TypeError("SelfClosingTag cannot contain any content") + super().__init__(content=content, **kwargs) + + def render(self, out_file): + tag = self._open_tag()[:-1] + " />\n" + out_file.write(tag) + + def append(self, *args): + raise TypeError("You cannot add content to SelfClosingTag") + + +class Hr(SelfClosingTag): + tag = "hr" + +class Br(SelfClosingTag): + tag = "br" + class Html(Element): tag = "html" @@ -56,3 +92,13 @@ class Head(Element): class Title(OneLineTag): tag = "title" + +class Ul(Element): + tag = "ul" + +class List(Element): + tag = "li" + +class Anchor(Element): + tag = "a" + diff --git a/students/mjchang/session07/run_html_render.py b/students/mjchang/session07/run_html_render.py new file mode 100644 index 00000000..05e5453b --- /dev/null +++ b/students/mjchang/session07/run_html_render.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 + +""" +a simple script can run and test your html rendering classes. + +Uncomment the steps as you add to your rendering. + +""" + +from io import StringIO + +# importing the html_rendering code with a short name for easy typing. +import html_render as hr + + +# writing the file out: +def render_page(page, filename, indent=None): + """ + render the tree of elements + + This uses StringIO to render to memory, then dump to console and + write to file -- very handy! + """ + + f = StringIO() + if indent is None: + page.render(f) + else: + page.render(f, indent) + + print(f.getvalue()) + with open(filename, 'w') as outfile: + outfile.write(f.getvalue()) + + +# # Step 1 +# ######### + +# page = hr.Element() + +# page.append("Here is a paragraph of text -- there could be more of them, " +# "but this is enough to show that we can do some text") + +# page.append("And here is another piece of text -- you should be able to add any number") + +# render_page(page, "test_html_output1.html") + +# # The rest of the steps have been commented out. +# # Uncomment them as you move along with the assignment. + +## Step 2 +########## + +page = hr.Html() + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text")) + +body.append(hr.P("And here is another piece of text -- you should be able to add any number")) + +page.append(body) + +render_page(page, "test_html_output2.html") + +# Step 3 +########## + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text")) +body.append(hr.P("And here is another piece of text -- you should be able to add any number")) + +page.append(body) + +render_page(page, "test_html_output3.html") + +# Step 4 +########## + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +page.append(body) + +render_page(page, "test_html_output4.html") + +# Step 5 +######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +page.append(body) + +render_page(page, "test_html_output5.html") + +# # Step 6 +# ######### + +# page = hr.Html() + +# head = hr.Head() +# head.append(hr.Title("PythonClass = Revision 1087:")) + +# page.append(head) + +# body = hr.Body() + +# body.append(hr.P("Here is a paragraph of text -- there could be more of them, " +# "but this is enough to show that we can do some text", +# style="text-align: center; font-style: oblique;")) + +# body.append(hr.Hr()) + +# body.append("And this is a ") +# body.append( hr.A("http://google.com/", "link") ) +# body.append("to google") + +# page.append(body) + +# render_page(page, "test_html_output6.html") + +# # Step 7 +# ######### + +# page = hr.Html() + +# head = hr.Head() +# head.append(hr.Title("PythonClass = Revision 1087:")) + +# page.append(head) + +# body = hr.Body() + +# body.append( hr.H(2, "PythonClass - Class 6 example") ) + +# body.append(hr.P("Here is a paragraph of text -- there could be more of them, " +# "but this is enough to show that we can do some text", +# style="text-align: center; font-style: oblique;")) + +# body.append(hr.Hr()) + +# list = hr.Ul(id="TheList", style="line-height:200%") + +# list.append( hr.Li("The first item in a list") ) +# list.append( hr.Li("This is the second item", style="color: red") ) + +# item = hr.Li() +# item.append("And this is a ") +# item.append( hr.A("http://google.com/", "link") ) +# item.append("to google") + +# list.append(item) + +# body.append(list) + +# page.append(body) + +# render_page(page, "test_html_output7.html") + +# # Step 8 and 9 +# ############## + +# page = hr.Html() + + +# head = hr.Head() +# head.append( hr.Meta(charset="UTF-8") ) +# head.append(hr.Title("PythonClass = Revision 1087:")) + +# page.append(head) + +# body = hr.Body() + +# body.append( hr.H(2, "PythonClass - Example") ) + +# body.append(hr.P("Here is a paragraph of text -- there could be more of them, " +# "but this is enough to show that we can do some text", +# style="text-align: center; font-style: oblique;")) + +# body.append(hr.Hr()) + +# list = hr.Ul(id="TheList", style="line-height:200%") + +# list.append( hr.Li("The first item in a list") ) +# list.append( hr.Li("This is the second item", style="color: red") ) + +# item = hr.Li() +# item.append("And this is a ") +# item.append( hr.A("http://google.com/", "link") ) +# item.append("to google") + +# list.append(item) + +# body.append(list) + +# page.append(body) + +# render_page(page, "test_html_output8.html") diff --git a/students/mjchang/session07/test_html_render.py b/students/mjchang/session07/test_html_render.py index f1228939..ac8dc97d 100644 --- a/students/mjchang/session07/test_html_render.py +++ b/students/mjchang/session07/test_html_render.py @@ -208,6 +208,60 @@ def test_one_line_tag_append(): file_contents = render_result(e).strip() +####### +# Step 4 +####### + + +def test_attributes(): + e = P("A paragraph of text", style="text-align: center", id="intro") + file_contents = render_result(e).strip() + print(file_contents) + assert "A paragraph of text" in file_contents + assert file_contents.endswith("

") + assert file_contents.startswith("

because open tag more complex + # assert False + assert 'style="text-align: center"' in file_contents + assert 'id="intro"' in file_contents + assert file_contents[:-1].index(">") > file_contents.index('id="intro"') + assert file_contents[:file_contents.index(">")].count(" ") == 3 + + +####### +# Step 5 +####### + +def test_hr(): + hr = Hr() + file_contents = render_result(hr) + print(file_contents) + assert file_contents == '


\n' + + +def test_hr_attr(): + hr = Hr(width=400) + file_contents = render_result(hr) + print(file_contents) + assert file_contents == '
\n' + + +def test_br(): + br = Br() + file_contents = render_result(br) + print(file_contents) + assert file_contents == "
\n" + +def test_content_in_br(): + with pytest.raises(TypeError): + br = Br("some content") + +def test_append_content_in_br(): + with pytest.raises(TypeError): + br = Br() + br.append("some content") + + + ##################### # indentation testing # Uncomment for Step 9 -- adding indentation From 068cb80d75b2766a403b30e1d68069d62bf3d710 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Sun, 3 Mar 2019 10:16:46 -0800 Subject: [PATCH 037/367] added session8 files --- students/douglas_klos/.gitignore | 13 +++++ .../session8/examples/index_slicing.py | 50 +++++++++++++++++ .../session8/examples/properties_example.py | 30 ++++++++++ .../session8/examples/quadratic.py | 36 ++++++++++++ .../session8/examples/sort_key.py | 56 +++++++++++++++++++ .../douglas_klos/session8/examples/vector.py | 51 +++++++++++++++++ students/douglas_klos/session8/lab/circle.py | 23 ++++++++ 7 files changed, 259 insertions(+) create mode 100755 students/douglas_klos/session8/examples/index_slicing.py create mode 100755 students/douglas_klos/session8/examples/properties_example.py create mode 100755 students/douglas_klos/session8/examples/quadratic.py create mode 100755 students/douglas_klos/session8/examples/sort_key.py create mode 100755 students/douglas_klos/session8/examples/vector.py create mode 100755 students/douglas_klos/session8/lab/circle.py diff --git a/students/douglas_klos/.gitignore b/students/douglas_klos/.gitignore index 595c358f..62537ae9 100644 --- a/students/douglas_klos/.gitignore +++ b/students/douglas_klos/.gitignore @@ -1,3 +1,16 @@ *.swp *.back .vscode +../.vscode/ +session7/execution_times.txt +session7/html_render.zip +session7/test_html_output1.html +session7/test_html_output2.html +session7/test_html_output3.html +session7/test_html_output4.html +session7/test_html_output5.html +session7/test_html_output6.html +session7/test_html_output7.html +session7/test_html_output8.html +session7/test_html_output9.html + diff --git a/students/douglas_klos/session8/examples/index_slicing.py b/students/douglas_klos/session8/examples/index_slicing.py new file mode 100755 index 00000000..dedd464c --- /dev/null +++ b/students/douglas_klos/session8/examples/index_slicing.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +""" +examples / test code for __getindex__ + +Doesn't really do anything, but you can see what happens with different indexing. +""" + +import operator + + +class IndexTest: + + def __getitem__(self, index): + # print("In getindex, indexes is:", index) + if isinstance(index, slice): + print("it's a single slice:", index) + elif isinstance(index, tuple): + print("it's a multi-dimensional slice:", index) + else: + try: + ind = operator.index(index) # this converts arbitrary objects to an int. + print("it's an index: ", ind) + except TypeError: # not a simple index + raise + print("It's a simple index") + + +if __name__ == "__main__": + + it = IndexTest() + + print("calling with simple index") + it[4] + + print("calling with single slice") + it[3:4] + + print("calling with two slices") + it[3:4, 7:8] + + print("calling with an invalid index") + it["this"] + + + + + + + diff --git a/students/douglas_klos/session8/examples/properties_example.py b/students/douglas_klos/session8/examples/properties_example.py new file mode 100755 index 00000000..f70760e9 --- /dev/null +++ b/students/douglas_klos/session8/examples/properties_example.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +""" +Example code for properties + +NOTE: if your getters and setters are this simple: don't do this! + +""" + + +class C: + def __init__(self): + self._x = None + @property + def x(self): + print("in getter") + return self._x + @x.setter + def x(self, value): + print("in setter", value) + self._x = value + @x.deleter + def x(self): + del self._x + +if __name__ == "__main__": + c = C() + c.x = 5 + print(c.x) + diff --git a/students/douglas_klos/session8/examples/quadratic.py b/students/douglas_klos/session8/examples/quadratic.py new file mode 100755 index 00000000..96dc1569 --- /dev/null +++ b/students/douglas_klos/session8/examples/quadratic.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +""" +A quaratic function evaluator + +used to demonstrate callable classes +""" + +class Quadratic: + """ + Class to evaluate quadratic equations + + Each instance wil have a certain set of coefficients + """ + + def __init__(self, A, B, C): + self.A = A + self.B = B + self.C = C + + def __call__(self, x): + return self.A * x**2 + self.B * x + self.C + + + +def main(): + q1 = Quadratic(3,4,5) + print(q1(1)) + print(q1(5)) + + + + + +if __name__ == '__main__': + main() diff --git a/students/douglas_klos/session8/examples/sort_key.py b/students/douglas_klos/session8/examples/sort_key.py new file mode 100755 index 00000000..0fe61c89 --- /dev/null +++ b/students/douglas_klos/session8/examples/sort_key.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +""" +demonstration of defining a sort_key method for sorting +""" + +import random +import time + + +class Simple: + """ + simple class to demonstrate a simple sorting key method + """ + + def __init__(self, val): + self.val = val + + def sort_key(self): + """ + sorting key function --used to pass in to sort functions + to get faster sorting + + Example:: + + sorted(list_of_simple_objects, key=Simple.sort_key) + + """ + return self.val + + def __lt__(self, other): + """ + less than --required for regular sorting + """ + return self.val < other.val + + def __repr__(self): + return "Simple({})".format(self.val) + + +if __name__ == "__main__": + N = 10000 + a_list = [Simple(random.randint(0, 10000)) for i in range(N)] + # print("Before sorting:", a_list) + + print("Timing for {} items".format(N)) + start = time.clock() + sorted(a_list) + reg_time = time.clock() - start + print("regular sort took: {:.4g}s".format(reg_time)) + + start = time.clock() + sorted(a_list, key=Simple.sort_key) + key_time = time.clock() - start + print("key sort took: {:.4g}s".format(key_time)) + + print("performance improvement factor: {:.4f}".format((reg_time / key_time))) diff --git a/students/douglas_klos/session8/examples/vector.py b/students/douglas_klos/session8/examples/vector.py new file mode 100755 index 00000000..adf0061d --- /dev/null +++ b/students/douglas_klos/session8/examples/vector.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +""" +Vector type with +, * redefined as Vector addition and dot product +""" + + +class Vector(list): + def __repr__(self): + """ + String representation, uses list (superclass) representation + """ + return 'Vector({})'.format(super().__repr__()) + + def __add__(self, v): + """ + redefine + as element-wise Vector sum + """ + if len(self) != len(v): + raise TypeError("Vector can only be added to a sequence of the same length") + else: + return Vector([x1 + x2 for x1, x2 in zip(self, v)]) + + def __mul__(self, v): + """ + redefine * as Vector dot product + """ + if len(self) != len(v): + raise TypeError("Vector can only be multiplied with a sequence of the same length") + else: + return sum([x1 * x2 for x1, x2 in zip(self, v)]) + + +if __name__ == '__main__': + l1 = [1, 2, 3] + l2 = [4, 5, 6] + v1 = Vector(l1) + v2 = Vector(l2) + + print('l1') + print(l1) + print('l1 + l2') + print(l1 + l2) + # print(l1 * l2) # TypeError + print('zip(l1, l2)') + print(zip(l1, l2)) + print('v1') + print(v1) + print('v1 + v2') + print(v1 + v2) + print('v1 * v2') + print(v1 * v2) diff --git a/students/douglas_klos/session8/lab/circle.py b/students/douglas_klos/session8/lab/circle.py new file mode 100755 index 00000000..dbea7cb1 --- /dev/null +++ b/students/douglas_klos/session8/lab/circle.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +import math + +class Circle(): + """ Circle class """ + + def __init__(self, radius): + self.radius = radius + + def __call__(self): + return 2 * math.pi * self.radius ** 2 + + +def main(): + c1 = Circle(5) + c2 = Circle(10) + + print(c1()) + print(c2()) + +if __name__ == '__main__': + main() From 6a97d999dc26fe389bdf97a3b0e962c052d6a08c Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 3 Mar 2019 10:17:32 -0800 Subject: [PATCH 038/367] html_render through step 6 --- .../jeff_shabani/session07/html_render.py | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 26a511ee..31e50cae 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -73,6 +73,7 @@ def render(self, file_name, open_method='w'): class SelfClosingTag(Element): def render(self, file_name, open_method='w'): + """ if conent is entered this tells user that self closing tags can't have conent and resets the conent to an empty string. @@ -90,6 +91,26 @@ def render(self, file_name, open_method='w'): with open(f'{file_name}.html', open_method) as file: file.write(outtext) +""" +Step 6 +""" + +class A(Element): + + def __init__(self, link, content): + self.link = link + self.content = content + super(Element).__init__() + + def render(self, file_name, open_method='w'): + head = 'a href=' + tail = 'a' + outtext = f'<{head}"{self.link}">{self.content}' + with open(f'{file_name}.html', open_method) as file: + file.write(outtext) + + + if __name__ == '__main__': # e = Element("this is some text", 'body') @@ -110,8 +131,8 @@ def render(self, file_name, open_method='w'): """ Step 3 """ - olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') - olt.render('OneLingTagTest') + # olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') + # olt.render('OneLingTagTest') # # """ # step 4 @@ -127,3 +148,9 @@ def render(self, file_name, open_method='w'): # sct_test = SelfClosingTag('_', 'html') # sct_test.render('sct_test') # print(dir(sct_test)) + + """ + step 6 test for A class + """ + A = A("http://google.com/", "link to google") + A.render('google_test') From 6765ef7f21e1080f3757f4dd02b784a6d860f6e4 Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 3 Mar 2019 11:35:15 -0800 Subject: [PATCH 039/367] html_render through step 7 --- .../jeff_shabani/session07/html_render.py | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 31e50cae..d225896b 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -41,10 +41,16 @@ def render(self, file_name, open_method='w'): class HTML(Element): + """ + html sublcass + """ tag = 'html' class PTag(Element): + """ + p subclass + """ tag = 'p' @@ -109,6 +115,24 @@ def render(self, file_name, open_method='w'): with open(f'{file_name}.html', open_method) as file: file.write(outtext) +""" +Step 7: Ul class +""" + +class Ul(Element): + ul = [] + +class Li(Element): + list_element = '' + +class Header(OneLineTag): + + def __init__(self, level, content, tag=None, **attrs): + self.level = level + self.content = content + self.tag = f'h{level}' + self.attrs = attrs + super(OneLineTag).__init__(list, tag, **attrs) @@ -131,6 +155,9 @@ def render(self, file_name, open_method='w'): """ Step 3 """ + + # p = PTag('p') + # p.render('ptag') # olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') # olt.render('OneLingTagTest') # @@ -152,5 +179,11 @@ def render(self, file_name, open_method='w'): """ step 6 test for A class """ - A = A("http://google.com/", "link to google") - A.render('google_test') + # A = A("http://google.com/", "link to google") + # A.render('google_test') + + """ + step 7 tests + """ + h=Header(3, 'Dies ist Kopfebene') + h.render('header_test') From 9eab5d715bdbdb0904bbf9ba198f1b1bf6c9936c Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Sun, 3 Mar 2019 11:49:13 -0800 Subject: [PATCH 040/367] circle.py steps 1-5 and tests --- students/douglas_klos/session8/lab/circle.py | 60 +++++++++++++++---- .../douglas_klos/session8/lab/test_circle.py | 60 +++++++++++++++++++ 2 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 students/douglas_klos/session8/lab/test_circle.py diff --git a/students/douglas_klos/session8/lab/circle.py b/students/douglas_klos/session8/lab/circle.py index dbea7cb1..0f6d3bb9 100755 --- a/students/douglas_klos/session8/lab/circle.py +++ b/students/douglas_klos/session8/lab/circle.py @@ -2,22 +2,60 @@ import math + class Circle(): """ Circle class """ - def __init__(self, radius): - self.radius = radius + def __init__(self, radius=0): + self._radius = radius - def __call__(self): - return 2 * math.pi * self.radius ** 2 + def __lt__(self, other): + return self._radius < other.radius + + def __le__(self, other): + return self._radius <= other.radius + + def __eq__(self, other): + return self._radius == other.radius + + def __ge__(self, other): + return self._radius >= other.radius + + def __gt__(self, other): + return self._radius > other.radius + def __ne__(self, other): + return self._radius != other.radius -def main(): - c1 = Circle(5) - c2 = Circle(10) + def __str__(self): + return f'Circle with radius: {self.radius}' - print(c1()) - print(c2()) + @property + def radius(self): + return self._radius + + @radius.setter + def radius(self, value): + self._radius = value + + @radius.deleter + def radius(self): + del self._radius + + @property + def diameter(self): + return self._radius * 2 + + @diameter.setter + def diameter(self, value): + self._radius = .5 * value + + @property + def area(self): + return 2 * math.pi * self.radius ** 2 -if __name__ == '__main__': - main() + @classmethod + def from_diameter(cls, diameter): + self = cls() + self._radius = diameter * .5 + return self diff --git a/students/douglas_klos/session8/lab/test_circle.py b/students/douglas_klos/session8/lab/test_circle.py new file mode 100644 index 00000000..edcb564f --- /dev/null +++ b/students/douglas_klos/session8/lab/test_circle.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +import math +import pytest +from circle import * + + +def test_set_radius_init(): + """ Tests that you can set the radius of a circle during init """ + + circle1 = Circle() + assert circle1.radius == 0 + assert circle1.diameter == 0 + + circle2 = Circle(5) + assert circle2.radius == 5 + assert circle2.diameter == 10 + + +def test_set_diameter(): + """ Tests that you can set the diameter of circle and that radius updates """ + + circle1 = Circle() + circle1.diameter = 10 + + assert circle1.radius == 5 + assert circle1.diameter == 10 + + +def test_area(): + + circle1 = Circle(10) + + assert circle1.radius == 10 + assert circle1.diameter == 20 + assert circle1.area == 2 * math.pi * circle1.radius ** 2 + +def test_set_area(): + """ Tests that setting the area fails and returns an AttributeError """ + + circle1 = Circle(10) + + with pytest.raises(AttributeError): + circle1.area = 100 + +def test_from_diameter(): + """ Tests that a circle can be created from a diameter """ + + circle1 = Circle.from_diameter(10) + + assert circle1.radius == 5 + assert circle1.diameter == 10 + assert circle1.area == 2 * math.pi * circle1.radius ** 2 + +def test_str(): + """ Tests that __str__ is working """ + + circle1 = Circle(10) + + assert 'Circle with radius: 10' == str(circle1) From 71f418763dd2ffb34aa4a6957de70f646206088c Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 3 Mar 2019 16:10:08 -0800 Subject: [PATCH 041/367] html_render through step 7 --- .../jeff_shabani/session07/html_render.py | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index d225896b..7d8fdf4a 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -46,6 +46,15 @@ class HTML(Element): """ tag = 'html' + def render(self, file_name, open_method = 'w'): + head = f'!DOCTYPE {self.tag.ljust(len(self.tag) + 1)}' + #super().render(file_name) + for k, v in self.attrs.items(): + head += f'{k.rjust(len(k) + 1)}="{v}"' + outtext = f'<{head}>\n{self.content}\n' + with open(f'{file_name}.html', open_method) as file: + file.write(outtext) + class PTag(Element): """ @@ -134,6 +143,8 @@ def __init__(self, level, content, tag=None, **attrs): self.attrs = attrs super(OneLineTag).__init__(list, tag, **attrs) +class Meta(SelfClosingTag): + tag = 'meta' if __name__ == '__main__': @@ -141,7 +152,7 @@ def __init__(self, level, content, tag=None, **attrs): # e.append("and this is some more text") # e.render('test') - # html sub-class + #html sub-class # html_sub = HTML('HTML subclass 1st line', 'html') # print(html_sub.tag) # html_sub.append('HTML subclass 2nd line') @@ -171,9 +182,8 @@ def __init__(self, level, content, tag=None, **attrs): """ step 5 test for self closing tag """ - # sct_test = SelfClosingTag('html',style='text-align', id='intro') - # sct_test = SelfClosingTag('_', 'html') - # sct_test.render('sct_test') + sct_test = SelfClosingTag('_','html') + sct_test.render('sct_test') # print(dir(sct_test)) """ @@ -185,5 +195,8 @@ def __init__(self, level, content, tag=None, **attrs): """ step 7 tests """ - h=Header(3, 'Dies ist Kopfebene') - h.render('header_test') + # h=Header(3, 'Dies ist Kopfebene') + # h.render('header_test') + # + # meta_test = Meta('_','meta charset="UTF-8"') + # meta_test.render('meta_test') From f5339987836d8057b5f92f3032be7ec3aa1e4303 Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 3 Mar 2019 16:42:41 -0800 Subject: [PATCH 042/367] html_render through step 8 --- .../jeff_shabani/session07/html_render.py | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 7d8fdf4a..e4ba41e4 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -8,6 +8,8 @@ # This is the framework for the base class class Element(object): + indent = " "*2 + def __init__(self, content=None, tag=None, **attrs): self.attrs = attrs if tag: @@ -26,12 +28,14 @@ def append(self, new_content): self.content += f'\n{i}\n' return self.content - def render(self, file_name, open_method='w'): + def render(self, file_name, cur_indent=''): + if cur_indent: + cur_indent = ' '*cur_indent head = f'{self.tag.ljust(len(self.tag) + 1)}' for k, v in self.attrs.items(): head += f'{k.rjust(len(k) + 1)}="{v}"' - outtext = f'<{head}>\n{self.content}\n' - with open(f'{file_name}.html', open_method) as file: + outtext = f'<{cur_indent}{head}>\n{self.content}\n' + with open(f'{file_name}.html', 'w') as file: file.write(outtext) @@ -46,19 +50,19 @@ class HTML(Element): """ tag = 'html' - def render(self, file_name, open_method = 'w'): + def render(self, file_name): head = f'!DOCTYPE {self.tag.ljust(len(self.tag) + 1)}' #super().render(file_name) for k, v in self.attrs.items(): head += f'{k.rjust(len(k) + 1)}="{v}"' outtext = f'<{head}>\n{self.content}\n' - with open(f'{file_name}.html', open_method) as file: + with open(f'{file_name}.html', 'w') as file: file.write(outtext) class PTag(Element): """ - p subclass + class for p tag """ tag = 'p' @@ -70,13 +74,13 @@ class PTag(Element): class OneLineTag(Element): - def render(self, file_name, open_method='w'): + def render(self, file_name): self.tag = f'{self.tag}>' head = f'{self.tag.ljust(len(self.tag) + 1)}' for k, v in self.attrs.items(): head += f'{k.rjust(len(k) + 1)}="{v}"' outtext = f'<{head}{self.content}' - with open(f'{file_name}.html', open_method) as file: + with open(f'{file_name}.html', 'w') as file: file.write(outtext) @@ -87,7 +91,7 @@ def render(self, file_name, open_method='w'): class SelfClosingTag(Element): - def render(self, file_name, open_method='w'): + def render(self, file_name): """ if conent is entered this tells user that self closing tags @@ -103,7 +107,7 @@ def render(self, file_name, open_method='w'): for k, v in self.attrs.items(): head += f'{k.rjust(len(k) + 1)}="{v}"' outtext = f'<{head}/>' - with open(f'{file_name}.html', open_method) as file: + with open(f'{file_name}.html', 'w') as file: file.write(outtext) """ @@ -117,21 +121,23 @@ def __init__(self, link, content): self.content = content super(Element).__init__() - def render(self, file_name, open_method='w'): + def render(self, file_name): head = 'a href=' tail = 'a' outtext = f'<{head}"{self.link}">{self.content}' - with open(f'{file_name}.html', open_method) as file: + with open(f'{file_name}.html', 'w') as file: file.write(outtext) -""" -Step 7: Ul class -""" - class Ul(Element): + """ + Step 7: Ul class + """ ul = [] class Li(Element): + """ + Step 7: Li class + """ list_element = '' class Header(OneLineTag): @@ -144,13 +150,18 @@ def __init__(self, level, content, tag=None, **attrs): super(OneLineTag).__init__(list, tag, **attrs) class Meta(SelfClosingTag): - tag = 'meta' + """ + add meta tag + """ + + def __init__(self, content=None, tag = 'meta charset="UTF-8"'): + super().__init__(content, tag) if __name__ == '__main__': - # e = Element("this is some text", 'body') - # e.append("and this is some more text") - # e.render('test') + e = Element("this is some text", 'body') + e.append("and this is some more text") + e.render('test') #html sub-class # html_sub = HTML('HTML subclass 1st line', 'html') @@ -182,8 +193,8 @@ class Meta(SelfClosingTag): """ step 5 test for self closing tag """ - sct_test = SelfClosingTag('_','html') - sct_test.render('sct_test') + # sct_test = SelfClosingTag('_','html') + # sct_test.render('sct_test') # print(dir(sct_test)) """ @@ -198,5 +209,5 @@ class Meta(SelfClosingTag): # h=Header(3, 'Dies ist Kopfebene') # h.render('header_test') # - # meta_test = Meta('_','meta charset="UTF-8"') + # meta_test = Meta() # meta_test.render('meta_test') From af7780efd482254648fe8a2939ab7f1579095f42 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Sun, 3 Mar 2019 17:55:34 -0800 Subject: [PATCH 043/367] html_render update --- students/jeff_shabani/session07/html_render.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index e4ba41e4..c7021b50 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -159,13 +159,12 @@ def __init__(self, content=None, tag = 'meta charset="UTF-8"'): if __name__ == '__main__': - e = Element("this is some text", 'body') - e.append("and this is some more text") - e.render('test') + # e = Element("this is some text", 'body') + # e.append("and this is some more text") + # e.render('test') #html sub-class # html_sub = HTML('HTML subclass 1st line', 'html') - # print(html_sub.tag) # html_sub.append('HTML subclass 2nd line') # html_sub.render('html_subclass') # @@ -191,20 +190,20 @@ def __init__(self, content=None, tag = 'meta charset="UTF-8"'): # attrs_test.render('kwargs_test') """ - step 5 test for self closing tag + step 5 self closing tag """ # sct_test = SelfClosingTag('_','html') # sct_test.render('sct_test') # print(dir(sct_test)) """ - step 6 test for A class + step 6 A class """ # A = A("http://google.com/", "link to google") # A.render('google_test') """ - step 7 tests + step 7 """ # h=Header(3, 'Dies ist Kopfebene') # h.render('header_test') From 14f5ee708fb57567e9df3295316f4efa0813a463 Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 3 Mar 2019 22:48:16 -0800 Subject: [PATCH 044/367] Create Lesson 7 --- students/WooseokJ/Lesson 7 | 1 + 1 file changed, 1 insertion(+) create mode 100644 students/WooseokJ/Lesson 7 diff --git a/students/WooseokJ/Lesson 7 b/students/WooseokJ/Lesson 7 new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/students/WooseokJ/Lesson 7 @@ -0,0 +1 @@ + From f7d9e354cddf98f615725faaa4dd28472f5888fd Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 3 Mar 2019 22:49:03 -0800 Subject: [PATCH 045/367] Delete Lesson 7 --- students/WooseokJ/Lesson 7 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 students/WooseokJ/Lesson 7 diff --git a/students/WooseokJ/Lesson 7 b/students/WooseokJ/Lesson 7 deleted file mode 100644 index 8b137891..00000000 --- a/students/WooseokJ/Lesson 7 +++ /dev/null @@ -1 +0,0 @@ - From fed674d74563a3e9fabb7f9b77576ab839a41d9d Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 3 Mar 2019 22:51:08 -0800 Subject: [PATCH 046/367] Create test --- students/WooseokJ/Lesson 7/test | 1 + 1 file changed, 1 insertion(+) create mode 100644 students/WooseokJ/Lesson 7/test diff --git a/students/WooseokJ/Lesson 7/test b/students/WooseokJ/Lesson 7/test new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/students/WooseokJ/Lesson 7/test @@ -0,0 +1 @@ + From f29713c7a3b140a92f1db0c4ee52b2de07eed15e Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 3 Mar 2019 22:51:50 -0800 Subject: [PATCH 047/367] Add files via upload --- students/WooseokJ/Lesson 7/html_render.py | 144 +++++++ students/WooseokJ/Lesson 7/run_html_render.py | 226 +++++++++++ .../WooseokJ/Lesson 7/test_html_render.py | 351 ++++++++++++++++++ 3 files changed, 721 insertions(+) create mode 100644 students/WooseokJ/Lesson 7/html_render.py create mode 100644 students/WooseokJ/Lesson 7/run_html_render.py create mode 100644 students/WooseokJ/Lesson 7/test_html_render.py diff --git a/students/WooseokJ/Lesson 7/html_render.py b/students/WooseokJ/Lesson 7/html_render.py new file mode 100644 index 00000000..db438415 --- /dev/null +++ b/students/WooseokJ/Lesson 7/html_render.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 + +""" +A class-based system for rendering html. +""" + + +# Base class +class Element(): + tag = 'html' + indent = ' ' + + def __init__(self, content=None, **kwargs): + self.attributes = kwargs + self.contents = [] + if content is not None: + self.contents = [content] + + def append(self, new_content): + self.contents.append(new_content) + + def attrib(self): + attribs = "".join([' {}="{}"'.format(key, val) + for key, val in self.attributes.items()] + ) + return attribs + + def open_tag(self, cur_ind=""): + open_tag = "<{}{}>".format(self.tag, self.attrib()) + return cur_ind + open_tag + + def render(self, out_file, cur_ind=""): + out_file.write(cur_ind) + out_file.write(self.make_open_tag()) + out_file.write("\n") + for content in self.contents: + try: + content.render(out_file, cur_ind + self.indent) + except AttributeError: + out_file.write(cur_ind + self.indent) + out_file.write(str(content) + "\n") + out_file.write(cur_ind) + out_file.write("\n".format(self.tag)) + + +# Process HTML tags +class OneLineTag(Element): + tag = 'onelinetag' + + def append(self, new_content): + raise NotImplementedError + + def _open_tag(self): + open_tag = ["<{}".format(self.tag)] + for key, value in self.attributes.items(): + open_tag.append(' ' + key + '="' + str(value) + '"') + open_tag.append(">") + return "".join(open_tag) + + def _close_tag(self): + return "".format(self.tag) + + def render(self, out_file, cur_ind=""): + out_file.write(cur_ind + self._open_tag()) + out_file.write(self.contents[0]) + out_file.write(self._close_tag()) + out_file.write('\n') + + +# Render tags without content +class SelfClosingTag(Element): + def __init__(self, content=None, **kwargs): + if content is not None: + raise TypeError("SelfClosingTag can not contain any content") + super().__init__(content=content, **kwargs) + + def render(self, outfile, cur_ind=""): + tag = cur_ind + self._open_tag()[:-1] + " />\n" + outfile.write(tag) + + def append(self, *args): + raise TypeError("You can not add content to a SelfClosingTag") + + +class Title(OneLineTag): + tag = "title" + + +class Br(SelfClosingTag): + + tag = "br" + + +class Hr(SelfClosingTag): + + tag = "hr" + + +class Html(Element): + tag = 'html' + + def render(self, out_file, cur_ind=""): + out_file.write(cur_ind + "\n") + super().render(out_file, cur_ind) + + +class Body(Element): + tag = 'body' + + +class P(Element): + tag = 'p' + + +class Head(Element): + tag = 'head' + + +class A(OneLineTag): + tag = "a" + + def __init__(self, link, content=None, **kwargs): + kwargs['href'] = link + super().__init__(content, **kwargs) + + +class H(OneLineTag): + tag = 'H' + + def __init__(self, level, content=None, **kwargs): + self.tag = "h" + str(int(level)) + super().__init__(content, **kwargs) + + +class Ul(Element): + tag = 'Ul' + + +class Li(Element): + tag = 'Li' + + +class Meta(SelfClosingTag): + tag = "meta" \ No newline at end of file diff --git a/students/WooseokJ/Lesson 7/run_html_render.py b/students/WooseokJ/Lesson 7/run_html_render.py new file mode 100644 index 00000000..b7b8451b --- /dev/null +++ b/students/WooseokJ/Lesson 7/run_html_render.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 + +#a simple script can run and test your html rendering classes. +#Uncomment the steps as you add to your rendering. + +from io import StringIO + +# importing the html_rendering code with a short name for easy typing. +import html_render as hr + + +# writing the file out: +def render_page(page, filename, indent=None): + """ + render the tree of elements + This uses StringIO to render to memory, then dump to console and + write to file -- very handy! + """ + + f = StringIO() + if indent is None: + page.render(f) + else: + page.render(f, indent) + + print(f.getvalue()) + with open(filename, 'w') as outfile: + outfile.write(f.getvalue()) + + +# Step 1 +######### + +page = hr.Element() + +page.append("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text") + +page.append("And here is another piece of text -- you should be able to add any number") + +render_page(page, "test_html_output1.html") + +# The rest of the steps have been commented out. +# Uncomment them as you move along with the assignment. + +## Step 2 +########## + +page = hr.Html() + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text")) + +body.append(hr.P("And here is another piece of text -- you should be able to add any number")) + +page.append(body) + +render_page(page, "test_html_output2.html") + +# # Step 3 +# ########## + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text")) +body.append(hr.P("And here is another piece of text -- you should be able to add any number")) + +page.append(body) + +render_page(page, "test_html_output3.html") + +# # Step 4 +# ########## + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +page.append(body) + +render_page(page, "test_html_output4.html") + +# # Step 5 +# ######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +page.append(body) + +render_page(page, "test_html_output5.html") + +# # Step 6 +# ######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +body.append("And this is a ") +body.append( hr.A("http://google.com/", "link") ) +body.append("to google") + +page.append(body) + +render_page(page, "test_html_output6.html") + +# # Step 7 +# ######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append( hr.H(2, "PythonClass - Class 6 example") ) + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +list = hr.Ul(id="TheList", style="line-height:200%") + +list.append( hr.Li("The first item in a list") ) +list.append( hr.Li("This is the second item", style="color: red") ) + +item = hr.Li() +item.append("And this is a ") +item.append( hr.A("http://google.com/", "link") ) +item.append("to google") + +list.append(item) + +body.append(list) + +page.append(body) + +render_page(page, "test_html_output7.html") + +# # Step 8 and 9 +# ############## + +page = hr.Html() + + +head = hr.Head() +head.append( hr.Meta(charset="UTF-8") ) +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append( hr.H(2, "PythonClass - Example") ) + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +list = hr.Ul(id="TheList", style="line-height:200%") + +list.append( hr.Li("The first item in a list") ) +list.append( hr.Li("This is the second item", style="color: red") ) + +item = hr.Li() +item.append("And this is a ") +item.append( hr.A("http://google.com/", "link") ) +item.append("to google") + +list.append(item) + +body.append(list) + +page.append(body) + +render_page(page, "test_html_output8.html") diff --git a/students/WooseokJ/Lesson 7/test_html_render.py b/students/WooseokJ/Lesson 7/test_html_render.py new file mode 100644 index 00000000..f1ab51da --- /dev/null +++ b/students/WooseokJ/Lesson 7/test_html_render.py @@ -0,0 +1,351 @@ +''' +test code for html_render.py +This is just a start -- you will need more tests! +''' + +import io +import pytest + +# import * is often bad form, but makes it easier to test everything in a module. +from html_render import * + + +# utility function for testing render methods +# needs to be used in multiple tests, so we write it once here. +def render_result(element, ind=''): + ''' + calls the element's render method, and returns what got rendered as a + string + ''' + # the StringIO object is a 'file-like' object -- something that + # provides the methods of a file, but keeps everything in memory + # so it can be used to test code that writes to a file, without + # having to actually write to disk. + outfile = io.StringIO() + # this so the tests will work before we tackle indentation + if ind: + element.render(outfile, ind) + else: + element.render(outfile) + return outfile.getvalue() + +######## +# Step 1 +######## + + +def test_init(): + ''' + This only tests that it can be initialized with and without + some content -- but it's a start + ''' + e = Element() + + e = Element('this is some text') + + +def test_append(): + ''' + This tests that you can append text + It doesn't test if it works -- + that will be covered by the render test later + ''' + e = Element('this is some text') + e.append('some more text') + + +def test_render_element(): + e = Element('this is some text') + e.append('and this is some more text') + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert'this is some text' in file_contents + assert'and this is some more text' in file_contents + + # make sure it's in the right order + assert file_contents.index('this is') < file_contents.index('and this') + + # making sure the opening and closing tags are right. + assert file_contents.startswith('') + assert file_contents.endswith('') + assert file_contents.count('') == 1 + assert file_contents.count('') == 1 + +# Uncomment this one after you get the one above to pass +# Does it pass right away? +def test_render_element2(): + ''' + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + It is not testing whether indentation or line feeds are correct. + ''' + e = Element() + e.append('this is some text') + e.append('and this is some more text') + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert'this is some text' in file_contents + assert'and this is some more text' in file_contents + + # make sure it's in the right order + assert file_contents.index('this is') < file_contents.index('and this') + + # making sure the opening and closing tags are right. + assert file_contents.startswith('') + assert file_contents.endswith('') + + +# ######## +# # Step 2 +# ######## + +# tests for the new tags +def test_html(): + e = Html('this is some text') + e.append('and this is some more text') + + file_contents = render_result(e).strip() + + assert'this is some text' in file_contents + assert'and this is some more text' in file_contents + print(file_contents) + assert file_contents.endswith('') + + +def test_body(): + e = Body('this is some text') + e.append('and this is some more text') + + file_contents = render_result(e).strip() + + assert'this is some text' in file_contents + assert'and this is some more text' in file_contents + + assert file_contents.startswith('') + assert file_contents.endswith('') + + +def test_p(): + e = P('this is some text') + e.append('and this is some more text') + + file_contents = render_result(e).strip() + + assert'this is some text' in file_contents + assert'and this is some more text' in file_contents + + assert file_contents.startswith('

') + assert file_contents.endswith('

') + + +def test_sub_element(): + ''' + tests that you can add another element and still render properly + ''' + page = Html() + page.append('some plain text.') + page.append(P('A simple paragraph of text')) + page.append('Some more plain text.') + + file_contents = render_result(page) + print(file_contents) # so we can see it if the test fails + + # note: The previous tests should make sure that the tags are getting + # properly rendered, so we don't need to test that here. + assert 'some plain text' in file_contents + assert 'A simple paragraph of text' in file_contents + assert 'Some more plain text.' in file_contents + assert 'some plain text' in file_contents + # but make sure the embedded element's tags get rendered! + assert '

' in file_contents + assert '

' in file_contents + + +######## +# Step 3 +######## + +def test_head(): + e = Head('this is some text') + e.append('and this is some more text') + + file_contents = render_result(e).strip() + + assert'this is some text' in file_contents + assert'and this is some more text' in file_contents + + assert file_contents.startswith('') + assert file_contents.endswith('') + + +def test_title(): + e = Title('This is a Title') + + file_contents = render_result(e).strip() + + assert'This is a Title' in file_contents + print(file_contents) + assert file_contents.startswith('') + assert file_contents.endswith('') + assert '\n' not in file_contents + + +def test_one_line_tag_append(): + """ + You should not be able to append content to a OneLineTag + """ + e = OneLineTag("the initial content") + with pytest.raises(NotImplementedError): + e.append("some more content") + + +def test_attributes(): + ''' + Testing attribute passing + ''' + e = P('A paragraph of text', style='text-align: center', id='intro') + + file_contents = render_result(e).strip() + print(file_contents) # so we can see it if the test fails + + # note: The previous tests should make sure that the tags are getting + # properly rendered, so we don't need to test that here. + # so using only a 'P' tag is fine + assert 'A paragraph of text' in file_contents + # but make sure the embedded element's tags get rendered! + # first test the end tag is there -- same as always: + assert file_contents.endswith('

') + + # but now the opening tag is far more complex + # but it starts the same: + assert file_contents.startswith('") > file_contents.index('id="intro"') + assert file_contents[:file_contents.index(">")].count(" ") == 3 + assert file_contents.startswith("

\n' + + +def test_hr_attr(): + """a horizontal rule with an attribute""" + hr = Hr(width=400) + file_contents = render_result(hr) + print(file_contents) + assert file_contents == '


\n' + + +def test_br(): + br = Br() + file_contents = render_result(br) + print(file_contents) + assert file_contents == "
\n" + + +def test_content_in_br(): + with pytest.raises(TypeError): + br = Br("some content") + + +def test_append_content_in_br(): + with pytest.raises(TypeError): + br = Br() + br.append("some content") + +def test_anchor(): + a = A("http://google.com/", "link to google") + file_contents = render_result(a) + print(file_contents) + assert file_contents.startswith(' tag + assert lines[i + 1].startswith(i * Element.indent + '<') + + assert lines[4].startswith(3 * Element.indent + 'some') + + +def test_element_indent1(): + ''' + Tests whether the Element indents at least simple content + we are expecting to to look like this: + + this is some text + <\html> + More complex indentation should be tested later. + ''' + e = Element('this is some text') + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert'this is some text' in file_contents + + # break into lines to check indentation + lines = file_contents.split('\n') + # making sure the opening and closing tags are right. + assert lines[0] == '' + # this line should be indented by the amount specified + # by the class attribute: 'indent' + assert lines[1].startswith(Element.indent + 'thi') + assert lines[2] == '' + assert file_contents.endswith('') \ No newline at end of file From 2edbcd7ab5d7959d455495cbd490daf505cb2af4 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 4 Mar 2019 08:40:05 -0800 Subject: [PATCH 048/367] Session07 files --- students/jeff_shabani/session07/html_render.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index c7021b50..106637ba 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -8,7 +8,8 @@ # This is the framework for the base class class Element(object): - indent = " "*2 + indent = '' + tag = 'html' def __init__(self, content=None, tag=None, **attrs): self.attrs = attrs @@ -17,16 +18,12 @@ def __init__(self, content=None, tag=None, **attrs): else: self.tag = '' if content: - self.content = content + self.content = [content] else: - self.content = '' + self.content = [] def append(self, new_content): - result = list() - result.append(new_content) - for i in result: - self.content += f'\n{i}\n' - return self.content + self.content.append(new_content) def render(self, file_name, cur_indent=''): if cur_indent: From 6a4866e4c5bb396c284baf1cfe700ef4aa46d813 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Mon, 4 Mar 2019 10:28:40 -0800 Subject: [PATCH 049/367] circle.py through step8, reflected numerics --- students/douglas_klos/session8/lab/circle.py | 33 ++++- .../douglas_klos/session8/lab/run_circle.py | 59 ++++++++ .../douglas_klos/session8/lab/test_circle.py | 131 ++++++++++++++++-- 3 files changed, 213 insertions(+), 10 deletions(-) create mode 100755 students/douglas_klos/session8/lab/run_circle.py mode change 100644 => 100755 students/douglas_klos/session8/lab/test_circle.py diff --git a/students/douglas_klos/session8/lab/circle.py b/students/douglas_klos/session8/lab/circle.py index 0f6d3bb9..d7362180 100755 --- a/students/douglas_klos/session8/lab/circle.py +++ b/students/douglas_klos/session8/lab/circle.py @@ -30,6 +30,33 @@ def __ne__(self, other): def __str__(self): return f'Circle with radius: {self.radius}' + def __repr__(self): + return f'Circle({self.radius})' + + def __add__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius + other.radius) + return self.__class__(self.radius + other) + + def __radd__(self, other): + return self.__class__(other + self.radius) + + def __sub__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius - other.radius) + return self.__class__(self.radius - other) + + def __rsub__(self, other): + return self.__class__(other - self._radius) + + def __mul__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius * other.radius) + return self.__class__(self.radius * other) + + def __rmul__(self, other): + return self.__class__(other * self._radius) + @property def radius(self): return self._radius @@ -44,7 +71,7 @@ def radius(self): @property def diameter(self): - return self._radius * 2 + return self._radius * 2 @diameter.setter def diameter(self, value): @@ -52,10 +79,12 @@ def diameter(self, value): @property def area(self): + """ Returns the area """ return 2 * math.pi * self.radius ** 2 @classmethod def from_diameter(cls, diameter): + """ Initializes class from diameter instead of radius """ self = cls() - self._radius = diameter * .5 + self.radius = diameter * .5 return self diff --git a/students/douglas_klos/session8/lab/run_circle.py b/students/douglas_klos/session8/lab/run_circle.py new file mode 100755 index 00000000..e70eeb32 --- /dev/null +++ b/students/douglas_klos/session8/lab/run_circle.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +from circle import * + + +def main(): + c1 = Circle(5) + c2 = Circle(10) + c3 = c1 * c2 + + print("---------------str--------------------") + + print(c1) + print(c2) + + print(str(c1)) + print(str(c2)) + + print("---------------repr-------------------") + + print(repr(c1)) + print(repr(c2)) + + print("---------------sort-------------------") + + c_list = [c2, c3, c1] + circle_list = [Circle(5), Circle(10), Circle(2)] + + print(c_list) + c_list.sort() + print(c_list) + + print(circle_list) + circle_list.sort() + print(circle_list) + + print("---------------add--------------------") + + print(3 + c1) + print(c1 + 3) + print(c1 + c2) + + print("---------------sub--------------------") + + print(c1 - 2) + print(10 - c1) + print(c2 - c1) + + print("---------------mul--------------------") + + print(5 * c1) + print(c1 * c2) + print(c1 * 5.0) + print(10.2 * c1) + + +if __name__ == '__main__': + main() + \ No newline at end of file diff --git a/students/douglas_klos/session8/lab/test_circle.py b/students/douglas_klos/session8/lab/test_circle.py old mode 100644 new mode 100755 index edcb564f..cfce851e --- a/students/douglas_klos/session8/lab/test_circle.py +++ b/students/douglas_klos/session8/lab/test_circle.py @@ -7,19 +7,17 @@ def test_set_radius_init(): """ Tests that you can set the radius of a circle during init """ - circle1 = Circle() + circle2 = Circle(5) + assert circle1.radius == 0 assert circle1.diameter == 0 - - circle2 = Circle(5) assert circle2.radius == 5 assert circle2.diameter == 10 def test_set_diameter(): """ Tests that you can set the diameter of circle and that radius updates """ - circle1 = Circle() circle1.diameter = 10 @@ -28,33 +26,150 @@ def test_set_diameter(): def test_area(): - + """ Tests that the area of a circle is computed properly """ circle1 = Circle(10) assert circle1.radius == 10 assert circle1.diameter == 20 assert circle1.area == 2 * math.pi * circle1.radius ** 2 + def test_set_area(): """ Tests that setting the area fails and returns an AttributeError """ - circle1 = Circle(10) with pytest.raises(AttributeError): circle1.area = 100 + def test_from_diameter(): """ Tests that a circle can be created from a diameter """ - circle1 = Circle.from_diameter(10) assert circle1.radius == 5 assert circle1.diameter == 10 assert circle1.area == 2 * math.pi * circle1.radius ** 2 + def test_str(): """ Tests that __str__ is working """ - circle1 = Circle(10) assert 'Circle with radius: 10' == str(circle1) + + +def test_repr(): + """ Tests that __repr__ is working """ + circle1 = Circle(10) + + assert 'Circle(10)' == repr(circle1) + + +def test_addition(): + """ Tests that __add___ is working """ + circle1 = Circle(10) + circle2 = Circle(20) + circle3 = circle1 + circle2 + + assert circle3.radius == 30 + assert circle1 + 5 == Circle(15) + + +def test_radd(): + """ Tests that reflected addition works """ + circle1 = Circle(2) + circle2 = Circle(4) + + assert circle1 + 2 == 2 + circle1 + assert 2 + circle1 == circle2 + assert 5 + circle1 == Circle(7) + + +def test_subtraction(): + """ Tests that __sub___ is working """ + circle1 = Circle(10) + circle2 = Circle(6) + circle3 = circle1 - circle2 + + assert circle3.radius == 4 + assert circle1 - 5 == Circle(5) + assert circle2 - 2 == Circle(4) + + +def test_rsub(): + circle1 = Circle(10) + circle2 = Circle(6) + + assert 10 - circle1 == circle1 - 10 + assert 10 - circle2 == Circle(4) + assert 10.0 - circle2 == Circle(4) + + +def test_multiplication(): + """ Tests that __mul__ is working """ + circle1 = Circle(2) + circle2 = Circle(4) + circle3 = circle1 * circle2 + + assert circle3.radius == 8 + assert circle1 * 2 == Circle(4) + assert circle2 * 2 == Circle(8) + + +def test_rmul(): + circle1 = Circle(2) + circle2 = Circle(4) + + assert 2 * circle1 == circle1 * 2 + assert 2 * circle1 == Circle(4) + assert 2 * circle2 == Circle(8) + + +def test_comparisons1(): + """ Tests comparison operations when circle1 is less than circle 2 """ + circle1 = Circle(2) + circle2 = Circle(4) + + assert not circle1 > circle2 + assert not circle1 >= circle2 + assert circle1 < circle2 + assert circle1 <= circle2 + assert not circle1 == circle2 + assert circle1 != circle2 + + +def test_comparisons2(): + """ Tests comparison operations when circle1 is greater than circle 2 """ + circle1 = Circle(4) + circle2 = Circle(2) + + assert circle1 > circle2 + assert circle1 >= circle2 + assert not circle1 < circle2 + assert not circle1 <= circle2 + assert not circle1 == circle2 + assert circle1 != circle2 + + +def test_comparisons3(): + """ Tests comparison operations when circle1 is equal to circle 2 """ + circle1 = Circle(2) + circle2 = Circle(2) + + assert not circle1 > circle2 + assert circle1 >= circle2 + assert not circle1 < circle2 + assert circle1 <= circle2 + assert circle1 == circle2 + assert not circle1 != circle2 + + +def test_sort(): + """ Tests that .sort() functions properly """ + circle1 = Circle(10) + circle2 = Circle(5) + circle3 = Circle(2) + circle_list = [circle1, circle2, circle3] + circle_list.sort() + + assert circle_list == [circle3, circle2, circle1] From c020c0ddab1f0e72af8f91164edc31f6dfd6022f Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 4 Mar 2019 10:55:54 -0800 Subject: [PATCH 050/367] Session07 files --- .../jeff_shabani/session07/html_render.py | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 106637ba..89479027 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -8,32 +8,34 @@ # This is the framework for the base class class Element(object): - indent = '' + indent = ' '*2 tag = 'html' - def __init__(self, content=None, tag=None, **attrs): + def __init__(self, content=None, **attrs): self.attrs = attrs - if tag: - self.tag = tag - else: - self.tag = '' if content: self.content = [content] else: self.content = [] + def front_tag(self): + """Creates the front tag""" + return f'<{self.tag}>' + + def end_tag(self): + """Creates the ending tag""" + return f'' + + def append(self, new_content): self.content.append(new_content) def render(self, file_name, cur_indent=''): - if cur_indent: - cur_indent = ' '*cur_indent - head = f'{self.tag.ljust(len(self.tag) + 1)}' - for k, v in self.attrs.items(): - head += f'{k.rjust(len(k) + 1)}="{v}"' - outtext = f'<{cur_indent}{head}>\n{self.content}\n' - with open(f'{file_name}.html', 'w') as file: - file.write(outtext) + file_name.write(f'{self.front_tag()}\n') + for content_line in self.content: + file_name.write(f'{content_line}\n') + file_name.write(f'{self.end_tag()}\n') + """ @@ -41,7 +43,7 @@ def render(self, file_name, cur_indent=''): """ -class HTML(Element): +class Html(Element): """ html sublcass """ @@ -156,12 +158,12 @@ def __init__(self, content=None, tag = 'meta charset="UTF-8"'): if __name__ == '__main__': - # e = Element("this is some text", 'body') - # e.append("and this is some more text") - # e.render('test') + e = Element("this is some text") + e.append("and this is some more text") + e.render(e,'test') #html sub-class - # html_sub = HTML('HTML subclass 1st line', 'html') + # html_sub = Html('HTML subclass 1st line') # html_sub.append('HTML subclass 2nd line') # html_sub.render('html_subclass') # From d0f7594ad5e2bbd4a4d2349fe8d5c4a8a64deb70 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 4 Mar 2019 13:20:51 -0800 Subject: [PATCH 051/367] html_render update --- .../jeff_shabani/session07/html_render.py | 240 +++++++----------- 1 file changed, 90 insertions(+), 150 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 89479027..8135ef7e 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -7,8 +7,7 @@ # This is the framework for the base class class Element(object): - - indent = ' '*2 + indent = ' ' * 2 tag = 'html' def __init__(self, content=None, **attrs): @@ -18,29 +17,24 @@ def __init__(self, content=None, **attrs): else: self.content = [] - def front_tag(self): - """Creates the front tag""" + def _front_tag(self): + """Creates the front/opening tag""" return f'<{self.tag}>' - def end_tag(self): + def _end_tag(self): """Creates the ending tag""" return f'' - def append(self, new_content): self.content.append(new_content) def render(self, file_name, cur_indent=''): - file_name.write(f'{self.front_tag()}\n') + # Writes the opening tag + file_name.write(f'{self._front_tag()}\n') for content_line in self.content: file_name.write(f'{content_line}\n') - file_name.write(f'{self.end_tag()}\n') - - - -""" -Step 2 part B -""" + # Writes the ending tag + file_name.write(f'{self._end_tag()}\n') class Html(Element): @@ -50,162 +44,108 @@ class Html(Element): tag = 'html' def render(self, file_name): - head = f'!DOCTYPE {self.tag.ljust(len(self.tag) + 1)}' - #super().render(file_name) - for k, v in self.attrs.items(): - head += f'{k.rjust(len(k) + 1)}="{v}"' - outtext = f'<{head}>\n{self.content}\n' - with open(f'{file_name}.html', 'w') as file: - file.write(outtext) + file_name.write(f'\n') + super().render(file_name) -class PTag(Element): +class P(Element): """ class for p tag """ tag = 'p' +class Body(Element): + """ + class for p tag + """ + tag = 'body' + + """ Step 3: print on one line """ - -class OneLineTag(Element): - - def render(self, file_name): - self.tag = f'{self.tag}>' - head = f'{self.tag.ljust(len(self.tag) + 1)}' - for k, v in self.attrs.items(): - head += f'{k.rjust(len(k) + 1)}="{v}"' - outtext = f'<{head}{self.content}' - with open(f'{file_name}.html', 'w') as file: - file.write(outtext) +# class OneLineTag(Element): +# +# def render(self, file_name): +# self.tag = f'{self.tag}>' +# head = f'{self.tag.ljust(len(self.tag) + 1)}' +# for k, v in self.kwargs.items(): +# head += f'{k.rjust(len(k) + 1)}="{v}"' +# outtext = f'<{head}{self.content}' +# with open(f'{file_name}.html', 'w') as file: +# file.write(outtext) """ Step 5: Self closing tag """ - -class SelfClosingTag(Element): - - def render(self, file_name): - - """ - if conent is entered this tells user that self closing tags - can't have conent and resets the conent to an empty string. - """ - - if self.content: - print('Self closing tags cannot have content') - else: - self.content = '' - - head = f'{self.tag.ljust(len(self.tag) + 1)}' - for k, v in self.attrs.items(): - head += f'{k.rjust(len(k) + 1)}="{v}"' - outtext = f'<{head}/>' - with open(f'{file_name}.html', 'w') as file: - file.write(outtext) +# class SelfClosingTag(Element): +# +# def render(self, file_name): +# +# """ +# if conent is entered this tells user that self closing tags +# can't have conent and resets the conent to an empty string. +# """ +# +# if self.content: +# print('Self closing tags cannot have content') +# else: +# self.content = '' +# +# head = f'{self.tag.ljust(len(self.tag) + 1)}' +# for k, v in self.kwargs.items(): +# head += f'{k.rjust(len(k) + 1)}="{v}"' +# outtext = f'<{head}/>' +# with open(f'{file_name}.html', 'w') as file: +# file.write(outtext) """ Step 6 """ -class A(Element): - - def __init__(self, link, content): - self.link = link - self.content = content - super(Element).__init__() - - def render(self, file_name): - head = 'a href=' - tail = 'a' - outtext = f'<{head}"{self.link}">{self.content}' - with open(f'{file_name}.html', 'w') as file: - file.write(outtext) - -class Ul(Element): - """ - Step 7: Ul class - """ - ul = [] - -class Li(Element): - """ - Step 7: Li class - """ - list_element = '' - -class Header(OneLineTag): - - def __init__(self, level, content, tag=None, **attrs): - self.level = level - self.content = content - self.tag = f'h{level}' - self.attrs = attrs - super(OneLineTag).__init__(list, tag, **attrs) - -class Meta(SelfClosingTag): - """ - add meta tag - """ - - def __init__(self, content=None, tag = 'meta charset="UTF-8"'): - super().__init__(content, tag) - - -if __name__ == '__main__': - e = Element("this is some text") - e.append("and this is some more text") - e.render(e,'test') - - #html sub-class - # html_sub = Html('HTML subclass 1st line') - # html_sub.append('HTML subclass 2nd line') - # html_sub.render('html_subclass') - # - # #p subclass - # p_sub = PTag('p subclass 1st line', 'p') - # p_sub.append('p subclass 2nd line') - # p_sub.render('p_subclass') - # - """ - Step 3 - """ - - # p = PTag('p') - # p.render('ptag') - # olt = OneLineTag('PythonClass - oneliner', 'title', style='text-align') - # olt.render('OneLingTagTest') - # - # """ - # step 4 - # """ - # attrs_test = Element('kwargs test', 'html',style='text-align', id='intro') - # attrs_test.append('kwargstest line 2') - # attrs_test.render('kwargs_test') - - """ - step 5 self closing tag - """ - # sct_test = SelfClosingTag('_','html') - # sct_test.render('sct_test') - # print(dir(sct_test)) - - """ - step 6 A class - """ - # A = A("http://google.com/", "link to google") - # A.render('google_test') - - """ - step 7 - """ - # h=Header(3, 'Dies ist Kopfebene') - # h.render('header_test') - # - # meta_test = Meta() - # meta_test.render('meta_test') +# class A(Element): +# +# def __init__(self, link, content): +# self.link = link +# self.content = content +# super(Element).__init__() +# +# def render(self, file_name): +# head = 'a href=' +# tail = 'a' +# outtext = f'<{head}"{self.link}">{self.content}' +# with open(f'{file_name}.html', 'w') as file: +# file.write(outtext) +# +# class Ul(Element): +# """ +# Step 7: Ul class +# """ +# ul = [] +# +# class Li(Element): +# """ +# Step 7: Li class +# """ +# list_element = '' +# +# class Head(OneLineTag): +# +# def __init__(self, level, content, tag=None, **kwargs): +# self.level = level +# self.content = content +# self.tag = f'h{level}' +# self.kwargs = kwargs +# super(OneLineTag).__init__(list, tag, **kwargs) +# +# class Meta(SelfClosingTag): +# """ +# add meta tag +# """ +# +# def __init__(self, content=None, tag = 'meta charset="UTF-8"'): +# super().__init__(content, tag) From 2e7dbf1ca6a9c696d34993780d5a300fab3dbc5c Mon Sep 17 00:00:00 2001 From: UncleanlyCleric Date: Mon, 4 Mar 2019 17:11:23 -0800 Subject: [PATCH 052/367] Initial commit --- students/jesse_miller/session08/circle.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 students/jesse_miller/session08/circle.py diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py new file mode 100644 index 00000000..2b0716b8 --- /dev/null +++ b/students/jesse_miller/session08/circle.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 +''' +Class based circle calculation exercise +''' + +''' +Setting this space for the modules I'm certainly importing +''' + +class Circle: + def __init__(self, radius): + self.radius = radius From 2c3e33f36ac297e9b7965b53f46fbb86b960091b Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Mon, 4 Mar 2019 18:36:23 -0800 Subject: [PATCH 053/367] Session8 done with requirements + optionals --- students/douglas_klos/session8/lab/circle.py | 83 +++++- .../douglas_klos/session8/lab/run_circle.py | 3 + .../douglas_klos/session8/lab/test_circle.py | 239 +++++++++++++++++- 3 files changed, 312 insertions(+), 13 deletions(-) diff --git a/students/douglas_klos/session8/lab/circle.py b/students/douglas_klos/session8/lab/circle.py index d7362180..5ed9e966 100755 --- a/students/douglas_klos/session8/lab/circle.py +++ b/students/douglas_klos/session8/lab/circle.py @@ -1,10 +1,26 @@ #!/usr/bin/env python3 +#pylint: disable=E1101 + +""" Circle class """ + +# Douglas Klos +# March 4th, 2019 +# Python 210, Session 8 +# circle.py + import math class Circle(): - """ Circle class """ + """ + Circle class + + Properties: + radius The radius of the circle + diameter Returns the diameter calculated from radius + area Returns the area calculated from radius + """ def __init__(self, radius=0): self._radius = radius @@ -41,6 +57,11 @@ def __add__(self, other): def __radd__(self, other): return self.__class__(other + self.radius) + def __iadd__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius + other.radius) + return self.__class__(self.radius + other) + def __sub__(self, other): if hasattr(other, '_radius'): return self.__class__(self._radius - other.radius) @@ -49,6 +70,11 @@ def __sub__(self, other): def __rsub__(self, other): return self.__class__(other - self._radius) + def __isub__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius - other.radius) + return self.__class__(self.radius - other) + def __mul__(self, other): if hasattr(other, '_radius'): return self.__class__(self._radius * other.radius) @@ -57,8 +83,40 @@ def __mul__(self, other): def __rmul__(self, other): return self.__class__(other * self._radius) + def __imul__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius * other.radius) + return self.__class__(self.radius * other) + + def __truediv__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius / other.radius) + return self.__class__(self.radius / other) + + def __rtruediv__(self, other): + return self.__class__(other / self._radius) + + def __itruediv__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius / other.radius) + return self.__class__(self.radius / other) + + def __floordiv__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius // other.radius) + return self.__class__(self.radius // other) + + def __rfloordiv__(self, other): + return self.__class__(other // self._radius) + + def __ifloordiv__(self, other): + if hasattr(other, '_radius'): + return self.__class__(self._radius // other.radius) + return self.__class__(self.radius // other) + @property def radius(self): + """ Sets or returns the radius """ return self._radius @radius.setter @@ -71,6 +129,7 @@ def radius(self): @property def diameter(self): + """ Returns the diameter calculated from radius """ return self._radius * 2 @diameter.setter @@ -79,7 +138,7 @@ def diameter(self, value): @property def area(self): - """ Returns the area """ + """ Returns the area calculated from radius """ return 2 * math.pi * self.radius ** 2 @classmethod @@ -88,3 +147,23 @@ def from_diameter(cls, diameter): self = cls() self.radius = diameter * .5 return self + + +class Sphere(Circle): + """ Sphere class, inherits from Circle """ + + def __str__(self): + return f'Sphere with radius: {self.radius}' + + def __repr__(self): + return f'Sphere({self.radius})' + + @Circle.area.getter + def area(self): + """ Returns the area of the sphere """ + return 4 * math.pi * self.radius ** 2 + + @property + def volume(self): + """ Returns the Volume of the sphere """ + return (4/3) * math.pi * self.radius ** 3 diff --git a/students/douglas_klos/session8/lab/run_circle.py b/students/douglas_klos/session8/lab/run_circle.py index e70eeb32..cfb1a503 100755 --- a/students/douglas_klos/session8/lab/run_circle.py +++ b/students/douglas_klos/session8/lab/run_circle.py @@ -53,6 +53,9 @@ def main(): print(c1 * 5.0) print(10.2 * c1) + del(c1) + + if __name__ == '__main__': main() diff --git a/students/douglas_klos/session8/lab/test_circle.py b/students/douglas_klos/session8/lab/test_circle.py index cfce851e..679a9729 100755 --- a/students/douglas_klos/session8/lab/test_circle.py +++ b/students/douglas_klos/session8/lab/test_circle.py @@ -1,8 +1,17 @@ #!/usr/bin/env python3 +#pylint: disable=C0113 + +""" Pytest file for circle.py """ + +# Douglas Klos +# March 4th, 2019 +# Python 210, Session 8 +# test_circle.py + import math import pytest -from circle import * +from circle import Circle, Sphere def test_set_radius_init(): @@ -37,7 +46,7 @@ def test_area(): def test_set_area(): """ Tests that setting the area fails and returns an AttributeError """ circle1 = Circle(10) - + with pytest.raises(AttributeError): circle1.area = 100 @@ -46,7 +55,7 @@ def test_from_diameter(): """ Tests that a circle can be created from a diameter """ circle1 = Circle.from_diameter(10) - assert circle1.radius == 5 + assert circle1.radius == 5 assert circle1.diameter == 10 assert circle1.area == 2 * math.pi * circle1.radius ** 2 @@ -54,23 +63,23 @@ def test_from_diameter(): def test_str(): """ Tests that __str__ is working """ circle1 = Circle(10) - - assert 'Circle with radius: 10' == str(circle1) - + assert str(circle1) == 'Circle with radius: 10' + + def test_repr(): """ Tests that __repr__ is working """ circle1 = Circle(10) - assert 'Circle(10)' == repr(circle1) - + assert repr(circle1) == 'Circle(10)' + def test_addition(): """ Tests that __add___ is working """ circle1 = Circle(10) circle2 = Circle(20) circle3 = circle1 + circle2 - + assert circle3.radius == 30 assert circle1 + 5 == Circle(15) @@ -85,25 +94,48 @@ def test_radd(): assert 5 + circle1 == Circle(7) +def test_iadd(): + """ Tests that += works """ + circle1 = Circle(2) + circle2 = Circle(4) + circle1 += circle2 + circle2 += 2 + + assert circle1 == Circle(6) + assert circle2 == Circle(6) + + def test_subtraction(): """ Tests that __sub___ is working """ circle1 = Circle(10) circle2 = Circle(6) circle3 = circle1 - circle2 - + assert circle3.radius == 4 assert circle1 - 5 == Circle(5) assert circle2 - 2 == Circle(4) def test_rsub(): + """ Tests that reflected subtractions works """ circle1 = Circle(10) circle2 = Circle(6) assert 10 - circle1 == circle1 - 10 assert 10 - circle2 == Circle(4) assert 10.0 - circle2 == Circle(4) - + + +def test_isub(): + """ Tests that -= works """ + circle1 = Circle(2) + circle2 = Circle(4) + circle2 -= circle1 + circle1 -= 1 + + assert circle1 == Circle(1) + assert circle2 == Circle(2) + def test_multiplication(): """ Tests that __mul__ is working """ @@ -117,6 +149,7 @@ def test_multiplication(): def test_rmul(): + """ Tests that reflected multiplication works """ circle1 = Circle(2) circle2 = Circle(4) @@ -125,6 +158,101 @@ def test_rmul(): assert 2 * circle2 == Circle(8) +def test_imul(): + """ Tests that *= works """ + circle1 = Circle(2) + circle2 = Circle(4) + circle2 *= circle1 + circle1 *= 5 + + assert circle1 == Circle(10) + assert circle2 == Circle(8) + + +def test_truediv(): + """ Tests that division works """ + circle1 = Circle(10) + circle2 = Circle(5) + circle3 = circle1 / circle2 + circle4 = circle2 / circle1 + circle5 = circle1 / 5 + circle6 = circle2 / 10 + + assert circle1 / circle2 == Circle(2) + assert circle2 / circle1 == Circle(.5) + assert circle3.radius == 2 + assert circle4.radius == .5 + assert circle5.radius == 2 + assert circle6.radius == .5 + + +def test_rtruediv(): + """ Tests that reflected division works """ + circle1 = Circle(10) + circle2 = Circle(5) + circle3 = 5 / circle1 + circle4 = 10 / circle2 + + assert 2 / circle1 == Circle(0.2) + assert circle3 == Circle(.5) + assert circle3.radius == 0.5 + assert circle4 == Circle(2) + assert circle4.radius == 2 + + +def test_itruediv(): + """ Tests that /= works """ + circle1 = Circle(2) + circle2 = Circle(4) + circle2 /= circle1 + circle1 /= 10 + + assert circle1 == Circle(.2) + assert circle2 == Circle(2) + + +def test_floordiv(): + """ Tests that classical floor division works """ + circle1 = Circle(10) + circle2 = Circle(5) + circle3 = circle1 // circle2 + circle4 = circle2 // circle1 + circle5 = circle1 // 5 + circle6 = circle2 // 10 + + assert circle3 == Circle(2) + assert circle4 == Circle(0) + assert circle3.radius == 2 + assert circle4.radius == 0 + assert circle5.radius == 2 + assert circle6.radius == 0 + + +def test_rfloordiv(): + """ Tests that reflected classical floor division works """ + circle1 = Circle(10) + circle2 = Circle(5) + circle3 = 5 // circle1 + circle4 = 10 // circle2 + + assert 2 // circle1 == Circle(0) + assert circle3.radius == 0 + assert circle3 == Circle(0) + assert circle4.radius == 2 + assert circle4 == Circle(2) + + +def test_ifloordiv(): + """ Tests that //= works """ + circle1 = Circle(2) + circle2 = Circle(4) + circle2 //= circle1 + circle1 //= 10 + + assert circle1 == Circle(0) + assert circle2 == Circle(2) + + def test_comparisons1(): """ Tests comparison operations when circle1 is less than circle 2 """ circle1 = Circle(2) @@ -173,3 +301,92 @@ def test_sort(): circle_list.sort() assert circle_list == [circle3, circle2, circle1] + + +def test_deleter(): + """ Tests that the deleter works for radius """ + circle1 = Circle(10) + del circle1.radius + + with pytest.raises(AttributeError): + print(circle1.radius) + + +def test_sphere_init(): + """ Tests that a Sphere object can be created """ + sphere1 = Sphere() + sphere2 = Sphere(10) + + assert sphere1.radius == 0 + assert sphere1.diameter == 0 + assert sphere2.radius == 10 + assert sphere2.diameter == 20 + + +def test_sphere_area(): + """ Tests that the area of the sphere is calculated correctly """ + sphere1 = Sphere(10) + + assert sphere1.area == 4 * math.pi * 10 ** 2 + + +def test_sphere_volume(): + """ Tests that the volume of the sphere is calculated correctly """ + sphere1 = Sphere(10) + + assert sphere1.volume == (4/3) * math.pi * 10 ** 3 + + +def test_sphere_str(): + """ Tests that __str__ is working """ + sphere1 = Sphere(10) + + print(str(sphere1)) + assert str(sphere1) == 'Sphere with radius: 10' + + +def test_sphere_repr(): + """ Tests that __repr__ is working """ + sphere1 = Sphere(10) + + print(repr(sphere1)) + assert repr(sphere1) == 'Sphere(10)' + + +def test_sphere_from_diameter(): + """ Tests you can create a sphere from diameter """ + sphere1 = Sphere.from_diameter(10) + + assert sphere1.radius == 5 + + +def test_sphere_math(): + """ Tests that operators work on spheres """ + sphere1 = Sphere(10) + sphere2 = Sphere(20) + + assert sphere1 + sphere2 == Sphere(30) + assert sphere2 - sphere1 == Sphere(10) + assert sphere1 * sphere2 == Sphere(200) + assert sphere1 / sphere2 == Sphere(0.5) + assert sphere1 // sphere2 == Sphere(0) + + assert 10 + sphere1 == Sphere(20) + assert 20 - sphere1 == Sphere(10) + assert 10 * sphere2 == Sphere(200) + assert 10 / sphere2 == Sphere(.5) + assert 10 // sphere2 == Sphere(0) + + +def test_sphere_comparisons(): + """ Tests that comparisons work on spheres """ + sphere1 = Sphere(10) + sphere2 = Sphere(20) + sphere3 = Sphere(20) + + assert sphere1 < sphere2 + assert sphere1 <= sphere2 + assert sphere2 > sphere1 + assert sphere2 >= sphere1 + assert sphere2 == sphere3 + assert sphere1 != sphere2 From 9365b2e6270c62a4bffdcf03baf0af6bb0864959 Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Mon, 4 Mar 2019 21:40:03 -0800 Subject: [PATCH 054/367] adding html_render through step 7 --- students/mjchang/session07/html_render.py | 18 +++-- students/mjchang/session07/run_html_render.py | 78 +++++++++---------- .../mjchang/session07/test_html_render.py | 46 +++++++++++ 3 files changed, 98 insertions(+), 44 deletions(-) diff --git a/students/mjchang/session07/html_render.py b/students/mjchang/session07/html_render.py index 7c27a67f..b507d974 100644 --- a/students/mjchang/session07/html_render.py +++ b/students/mjchang/session07/html_render.py @@ -47,12 +47,12 @@ def _close_tag(self): class OneLineTag(Element): def render(self, out_file): for content in self.contents: - out_file.write("<{}>".format(self.tag)) #removed newline + out_file.write(self._open_tag()) #removed newline try: content.render(out_file) except AttributeError: out_file.write(content) #removed newline from Element - out_file.write("\n".format(self.tag)) + out_file.write(self._close_tag()) def append(self, content): raise NotImplementedError @@ -93,12 +93,20 @@ class Head(Element): class Title(OneLineTag): tag = "title" +class A(OneLineTag): + tag = "a" + + def __init__(self, link, content=None, **kwargs): + kwargs['href'] = link + super().__init__(content, **kwargs) + class Ul(Element): tag = "ul" class List(Element): tag = "li" -class Anchor(Element): - tag = "a" - +class H(OneLineTag): + def __init__(self, level, content, **kwargs): + self.tag = "h{}".format(level) + super().__init__(content, **kwargs) \ No newline at end of file diff --git a/students/mjchang/session07/run_html_render.py b/students/mjchang/session07/run_html_render.py index 05e5453b..054cb8e3 100644 --- a/students/mjchang/session07/run_html_render.py +++ b/students/mjchang/session07/run_html_render.py @@ -126,69 +126,69 @@ def render_page(page, filename, indent=None): render_page(page, "test_html_output5.html") -# # Step 6 -# ######### +# Step 6 +######### -# page = hr.Html() +page = hr.Html() -# head = hr.Head() -# head.append(hr.Title("PythonClass = Revision 1087:")) +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) -# page.append(head) +page.append(head) -# body = hr.Body() +body = hr.Body() -# body.append(hr.P("Here is a paragraph of text -- there could be more of them, " -# "but this is enough to show that we can do some text", -# style="text-align: center; font-style: oblique;")) +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) -# body.append(hr.Hr()) +body.append(hr.Hr()) -# body.append("And this is a ") -# body.append( hr.A("http://google.com/", "link") ) -# body.append("to google") +body.append("And this is a ") +body.append( hr.A("http://google.com/", "link") ) +body.append("to google") -# page.append(body) +page.append(body) -# render_page(page, "test_html_output6.html") +render_page(page, "test_html_output6.html") -# # Step 7 -# ######### +# Step 7 +######### -# page = hr.Html() +page = hr.Html() -# head = hr.Head() -# head.append(hr.Title("PythonClass = Revision 1087:")) +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) -# page.append(head) +page.append(head) -# body = hr.Body() +body = hr.Body() -# body.append( hr.H(2, "PythonClass - Class 6 example") ) +body.append( hr.H(2, "PythonClass - Class 6 example") ) -# body.append(hr.P("Here is a paragraph of text -- there could be more of them, " -# "but this is enough to show that we can do some text", -# style="text-align: center; font-style: oblique;")) +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) -# body.append(hr.Hr()) +body.append(hr.Hr()) -# list = hr.Ul(id="TheList", style="line-height:200%") +list = hr.Ul(id="TheList", style="line-height:200%") -# list.append( hr.Li("The first item in a list") ) -# list.append( hr.Li("This is the second item", style="color: red") ) +list.append( hr.Li("The first item in a list") ) +list.append( hr.Li("This is the second item", style="color: red") ) -# item = hr.Li() -# item.append("And this is a ") -# item.append( hr.A("http://google.com/", "link") ) -# item.append("to google") +item = hr.Li() +item.append("And this is a ") +item.append( hr.A("http://google.com/", "link") ) +item.append("to google") -# list.append(item) +list.append(item) -# body.append(list) +body.append(list) -# page.append(body) +page.append(body) -# render_page(page, "test_html_output7.html") +render_page(page, "test_html_output7.html") # # Step 8 and 9 # ############## diff --git a/students/mjchang/session07/test_html_render.py b/students/mjchang/session07/test_html_render.py index ac8dc97d..9566f211 100644 --- a/students/mjchang/session07/test_html_render.py +++ b/students/mjchang/session07/test_html_render.py @@ -262,6 +262,52 @@ def test_append_content_in_br(): +####### +# Step 6 +####### + +def test_anchor(): + a = A("http://google.com/", "link to Google") + file_contents = render_result(a) + print(file_contents) + assert file_contents.startswith("") + + e2 = List("This is the second item", style="color: red") + file_contents = render_result(e2).strip() + print(file_contents) + assert ("This is the second item") in file_contents + assert ('
  • \n') in file_contents + + +def test_unordered_list(): + e = Ul("This is the second item") + # print(file_contents) + file_contents = render_result(e).strip() + + assert("This is the second item") in file_contents + assert file_contents.startswith("
      ") + assert file_contents.endswith("
    ") + +def test_header(): + e = H(2, "PythonClass - Class 6 example") + file_contents = render_result(e).strip() + print(file_contents) + assert file_contents.startswith("

    ") + assert ("PythonClass - Class 6 example") in file_contents + + ##################### # indentation testing # Uncomment for Step 9 -- adding indentation From f3ae584183502ef136bc0bac784c1bb500478734 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Tue, 5 Mar 2019 07:49:01 -0800 Subject: [PATCH 055/367] Update to html_render --- students/jeff_shabani/session07/html_render.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 8135ef7e..d3a09347 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -31,9 +31,12 @@ def append(self, new_content): def render(self, file_name, cur_indent=''): # Writes the opening tag file_name.write(f'{self._front_tag()}\n') + for content_line in self.content: - file_name.write(f'{content_line}\n') - # Writes the ending tag + if hasattr(content_line, 'render'): + content_line.render(file_name) + else: + file_name.write(f'{content_line}\n') file_name.write(f'{self._end_tag()}\n') From 83126b40d8369bc5aad422ff3979e7942d56ff99 Mon Sep 17 00:00:00 2001 From: UncleanlyCleric Date: Tue, 5 Mar 2019 08:06:08 -0800 Subject: [PATCH 056/367] Yea, I'm still not sure I get OO programming at all. This is very complicated to me. --- students/jesse_miller/session08/circle.py | 31 ++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index 2b0716b8..c01ae371 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -3,10 +3,35 @@ Class based circle calculation exercise ''' +from math import pi ''' -Setting this space for the modules I'm certainly importing +Imported the math module for calculation ''' -class Circle: +class Circle(object): + ''' + Defining the circle class + ''' def __init__(self, radius): - self.radius = radius + self.radius = radius + + @property + def diameter(self): + ''' + Defining diameter, I think I'm doing this right. + ''' + return self.radius * 2 + + @diameter.setter + def diameter(self, value): + ''' + This seems like the right time to use a setter + ''' + self.radius = value / 2 + + @property + def area(self): + ''' + Defining area, I'm a tad more confident in this one + ''' + return pi * self.radius**2 From 59aee24d44ecd3551bcf0af4a13cd46f36de8acb Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Tue, 5 Mar 2019 09:18:02 -0800 Subject: [PATCH 057/367] Began work on SparseArray class --- .../{lab => exercises/circle}/circle.py | 0 .../{lab => exercises/circle}/run_circle.py | 4 +- .../{lab => exercises/circle}/test_circle.py | 0 .../exercises/sparsearray/sparsearray.py | 34 +++++++++++++++++ .../exercises/sparsearray/test_sparsearray.py | 38 +++++++++++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) rename students/douglas_klos/session8/{lab => exercises/circle}/circle.py (100%) rename students/douglas_klos/session8/{lab => exercises/circle}/run_circle.py (89%) rename students/douglas_klos/session8/{lab => exercises/circle}/test_circle.py (100%) create mode 100755 students/douglas_klos/session8/exercises/sparsearray/sparsearray.py create mode 100755 students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py diff --git a/students/douglas_klos/session8/lab/circle.py b/students/douglas_klos/session8/exercises/circle/circle.py similarity index 100% rename from students/douglas_klos/session8/lab/circle.py rename to students/douglas_klos/session8/exercises/circle/circle.py diff --git a/students/douglas_klos/session8/lab/run_circle.py b/students/douglas_klos/session8/exercises/circle/run_circle.py similarity index 89% rename from students/douglas_klos/session8/lab/run_circle.py rename to students/douglas_klos/session8/exercises/circle/run_circle.py index cfb1a503..f2a20ebc 100755 --- a/students/douglas_klos/session8/lab/run_circle.py +++ b/students/douglas_klos/session8/exercises/circle/run_circle.py @@ -2,6 +2,8 @@ from circle import * +# This file was briefly used for testing. +# It's not part of the assignment requirements and can be safely ignored. def main(): c1 = Circle(5) @@ -53,7 +55,7 @@ def main(): print(c1 * 5.0) print(10.2 * c1) - del(c1) + diff --git a/students/douglas_klos/session8/lab/test_circle.py b/students/douglas_klos/session8/exercises/circle/test_circle.py similarity index 100% rename from students/douglas_klos/session8/lab/test_circle.py rename to students/douglas_klos/session8/exercises/circle/test_circle.py diff --git a/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py b/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py new file mode 100755 index 00000000..312f56e8 --- /dev/null +++ b/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +""" SparseArray Class """ + +# Douglas Klos +# March 5th, 2019 +# Python 210, Session 8 +# sparsearray.py + + +class SparseArray(): + """ SparseArray class """ + + def __init__(self, values): + self.array = {} + self.length = len(values) + + for i in range(len(values)): + if values[i] != 0: + self.array[i] = values[i] + + def __str__(self): + values = [value for key, value in sorted(self.array.items())] + return str(values) + + def __len__(self): + return self.length + + def __getitem__(self, key): + return self.array[key] + + def __setitem__(self, key, value): + if value: + self.array[key] = value diff --git a/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py b/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py new file mode 100755 index 00000000..afa0c5df --- /dev/null +++ b/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +""" Pytest file for sparsearray.py """ + +# Douglas Klos +# March 5th, 2019 +# Python 210, Session 8 +# test_sparsearray.py + + +import pytest +from sparsearray import SparseArray + + +def test_sparsearray_init(): + """ Tests that a sparsearray can be initialized """ + sa = SparseArray([1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]) + print(sa.array) + assert sa.array[0] == sa.array[4] == sa.array[5] == sa.array[10] == sa.array[14] == 1 + + +def test_sparsearray_len(): + list1 = [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] + sa = SparseArray([1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]) + print(sa) + assert len(sa) == len(list1) + assert False + + +def test_sparsearray_set_value(): + list1 = [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] + sa = SparseArray(list1) + + print(sa) + sa[1] = 2 + sa[2] = 0 + print(sa) + assert False \ No newline at end of file From e044b38e97918b9ec524cb65b7028edc93b9db9b Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Tue, 5 Mar 2019 10:12:58 -0800 Subject: [PATCH 058/367] Update to html_render --- .../jeff_shabani/session07/html_render.py | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index d3a09347..441b4f17 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -69,16 +69,26 @@ class for p tag Step 3: print on one line """ -# class OneLineTag(Element): -# -# def render(self, file_name): -# self.tag = f'{self.tag}>' -# head = f'{self.tag.ljust(len(self.tag) + 1)}' -# for k, v in self.kwargs.items(): -# head += f'{k.rjust(len(k) + 1)}="{v}"' -# outtext = f'<{head}{self.content}' -# with open(f'{file_name}.html', 'w') as file: -# file.write(outtext) +class OneLineTag(Element): + + def render(self, file_name, cur_indent=''): + # Writes the opening tag + file_name.write(f'{self._front_tag().ljust(len(self._front_tag()+1))}') + for k, v in self.attrs.items(): + file_name.write(f'{k.rjust(len(k) + 1)}="{v}"') + file_name.write(f'{self._end_tag()}\n') + + + + + # def render_alt(self, file_name): + # self.tag = f'{self.tag}>' + # head = f'{self.tag.ljust(len(self.tag) + 1)}' + # for k, v in self.kwargs.items(): + # head += f'{k.rjust(len(k) + 1)}="{v}"' + # outtext = f'<{head}{self.content}' + # with open(f'{file_name}.html', 'w') as file: + # file.write(outtext) """ From b9b655eef4f9c4f24e3fd60803369c1ebcbdf328 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Tue, 5 Mar 2019 10:14:27 -0800 Subject: [PATCH 059/367] Update to html_render --- students/jeff_shabani/session07/html_render.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 441b4f17..53928996 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -72,7 +72,11 @@ class for p tag class OneLineTag(Element): def render(self, file_name, cur_indent=''): - # Writes the opening tag + """ + Renders elements on a single line. + :param file_name: + :param cur_indent: + """ file_name.write(f'{self._front_tag().ljust(len(self._front_tag()+1))}') for k, v in self.attrs.items(): file_name.write(f'{k.rjust(len(k) + 1)}="{v}"') From d7e97a9f060125b892bf06b41ef01b6d7b4046eb Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Tue, 5 Mar 2019 10:53:01 -0800 Subject: [PATCH 060/367] Update to html_render --- students/jeff_shabani/session07/html_render.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 53928996..8330de62 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -71,16 +71,22 @@ class for p tag class OneLineTag(Element): + + def append(self, new_content): + raise BaseException + def render(self, file_name, cur_indent=''): """ Renders elements on a single line. :param file_name: :param cur_indent: """ - file_name.write(f'{self._front_tag().ljust(len(self._front_tag()+1))}') + file_name.write(f'{self._front_tag()} ') for k, v in self.attrs.items(): - file_name.write(f'{k.rjust(len(k) + 1)}="{v}"') - file_name.write(f'{self._end_tag()}\n') + file_name.write(f'{k}="{v}"') + file_name.write(f'{self._front_tag()}') + file_name.write(f'{self.content[0]}') + file_name.write(f'{self._end_tag()}') @@ -166,3 +172,8 @@ def render(self, file_name, cur_indent=''): # # def __init__(self, content=None, tag = 'meta charset="UTF-8"'): # super().__init__(content, tag) + +# if __name__ == '__main__': +# +# olt = OneLineTag('this is william') +# olt.render(olt, 'tag') From 34800447393a7030a7dd80c502a25b6e65ea2a25 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Tue, 5 Mar 2019 12:05:40 -0800 Subject: [PATCH 061/367] Update to html_render --- students/jeff_shabani/session07/html_render.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 8330de62..c0e224ce 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -3,7 +3,7 @@ """ A class-based system for rendering html. """ - +import functools # This is the framework for the base class class Element(object): @@ -68,12 +68,9 @@ class for p tag """ Step 3: print on one line """ - class OneLineTag(Element): - - def append(self, new_content): - raise BaseException + Tag = 'Title' def render(self, file_name, cur_indent=''): """ @@ -88,6 +85,9 @@ def render(self, file_name, cur_indent=''): file_name.write(f'{self.content[0]}') file_name.write(f'{self._end_tag()}') + def append(self, new_content): + raise NotImplementedError + From d7cb909589d7f5222598a42f91c7880fc155f078 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Tue, 5 Mar 2019 13:58:57 -0800 Subject: [PATCH 062/367] Dictionary based SparseArray working --- .../exercises/sparsearray/sparsearray.py | 46 +++++++++-- .../exercises/sparsearray/test_sparsearray.py | 79 ++++++++++++++++--- 2 files changed, 107 insertions(+), 18 deletions(-) diff --git a/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py b/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py index 312f56e8..8f9f2bbd 100755 --- a/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py +++ b/students/douglas_klos/session8/exercises/sparsearray/sparsearray.py @@ -15,20 +15,54 @@ def __init__(self, values): self.array = {} self.length = len(values) - for i in range(len(values)): - if values[i] != 0: - self.array[i] = values[i] + for key, value in enumerate(values): + if value: + self.array[key] = value + + def full_array(self): + """ Returns the sparse array including 0's """ + return_array = [] + sorted_values = {key: value for key, value in sorted(self.array.items())} + for counter in range(self.length): + try: + return_array.append(sorted_values[counter]) + except KeyError: + return_array.append(0) + return return_array def __str__(self): - values = [value for key, value in sorted(self.array.items())] - return str(values) + return str(self.full_array()) + + def __repr__(self): + return str(self.full_array()) def __len__(self): return self.length def __getitem__(self, key): - return self.array[key] + if isinstance(key, slice): + return self.full_array()[key.start:key.stop:key.step] + if key > self.length: + raise IndexError + try: + return self.array[key] + except KeyError: + return 0 def __setitem__(self, key, value): + if key > self.length: + raise IndexError if value: self.array[key] = value + elif key in self.array: + del self.array[key] + + def __delitem__(self, key): + del self.array[key] + + def append(self, values): + """ Appends new values to the end of the sparse array """ + for key, value in enumerate(values): + if value: + self.array[key + self.length] = value + self.length += len(values) diff --git a/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py b/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py index afa0c5df..3cace501 100755 --- a/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py +++ b/students/douglas_klos/session8/exercises/sparsearray/test_sparsearray.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 - +#pylint: disable=C0103 """ Pytest file for sparsearray.py """ # Douglas Klos @@ -11,28 +11,83 @@ import pytest from sparsearray import SparseArray +LIST1 = [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] +LIST2 = [2, 0, 0] + def test_sparsearray_init(): """ Tests that a sparsearray can be initialized """ - sa = SparseArray([1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]) + sa = SparseArray(LIST1) print(sa.array) assert sa.array[0] == sa.array[4] == sa.array[5] == sa.array[10] == sa.array[14] == 1 def test_sparsearray_len(): - list1 = [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] - sa = SparseArray([1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]) + """ Tests that length is returned properly """ + sa = SparseArray(LIST1) print(sa) - assert len(sa) == len(list1) - assert False - + assert len(sa) == len(LIST1) -def test_sparsearray_set_value(): - list1 = [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] - sa = SparseArray(list1) - print(sa) +def test_sparsearray_set_get_value(): + """ Tests that you can get and set values to the sparse array """ + sa = SparseArray(LIST1) sa[1] = 2 sa[2] = 0 + + with pytest.raises(IndexError): + print(sa[20]) + with pytest.raises(IndexError): + sa[20] = 10 + + sa[0] = 0 + assert sa[0] == 0 + + assert sa[1] == 2 + assert sa[2] == 0 + + +def test_sparsearray_str(): + """ Tests that str(SparseArray) is correctly implemented """ + sa = SparseArray(LIST1) + + assert str(sa) == str(LIST1) + + +def test_sparsearray_repr(): + """ Tests that repr(SparseArray) is correctly implemented """ + sa = SparseArray(LIST1) + + print(repr(LIST1)) + assert repr(sa) == repr(LIST1) + + +def test_sparsearray_append(): + """ Tests that you can append to the sparse array """ + sa = SparseArray(LIST1) + sa.append(LIST2) + + assert str(sa) == str(LIST1 + LIST2) + assert len(sa) == 21 + + +def test_sparsearray_del(): + """ Tests that you can delete an element from the sparse array """ + sa = SparseArray(LIST1) + del sa[4] print(sa) - assert False \ No newline at end of file + + assert sa[4] == 0 + assert len(sa) == 18 + + +def test_sparsearray_slice(): + """ Tests that you can get slices from the sparse array """ + sa = SparseArray(LIST1) + sa.append(LIST2) + list3 = LIST1 + LIST2 + + assert sa[0:4] == list3[0:4] + assert sa[5:10] == list3[5:10] + assert sa[10:21] == list3[10:21] + assert sa[-1::2] == list3[-1::2] From 4e9a6a79c2eec7431a59196b349b4b2037d094d5 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Tue, 5 Mar 2019 14:29:36 -0800 Subject: [PATCH 063/367] Update to html_render --- .../jeff_shabani/session07/html_render.py | 96 +++++++++---------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index c0e224ce..23aaba5a 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -70,7 +70,7 @@ class for p tag """ class OneLineTag(Element): - Tag = 'Title' + tag = 'Title' def render(self, file_name, cur_indent=''): """ @@ -89,60 +89,63 @@ def append(self, new_content): raise NotImplementedError +class Head(Element): + tag = "head" - # def render_alt(self, file_name): - # self.tag = f'{self.tag}>' - # head = f'{self.tag.ljust(len(self.tag) + 1)}' - # for k, v in self.kwargs.items(): - # head += f'{k.rjust(len(k) + 1)}="{v}"' - # outtext = f'<{head}{self.content}' - # with open(f'{file_name}.html', 'w') as file: - # file.write(outtext) """ Step 5: Self closing tag """ -# class SelfClosingTag(Element): -# -# def render(self, file_name): -# -# """ -# if conent is entered this tells user that self closing tags -# can't have conent and resets the conent to an empty string. -# """ -# -# if self.content: -# print('Self closing tags cannot have content') -# else: -# self.content = '' -# -# head = f'{self.tag.ljust(len(self.tag) + 1)}' -# for k, v in self.kwargs.items(): -# head += f'{k.rjust(len(k) + 1)}="{v}"' -# outtext = f'<{head}/>' -# with open(f'{file_name}.html', 'w') as file: -# file.write(outtext) +class SelfClosingTag(Element): + tag = 'br' + + def append(self, new_content): + raise NotImplementedError + + def render(self, file_name): + + """ + if conent is entered this tells user that self closing tags + can't have conent and resets the conent to an empty string. + """ + + if self.content: + raise TypeError + file_name.write(f'{self._front_tag()[:-1]}') + for k, v in self.attrs.items(): + file_name.write(f'{k.rjust(len(k) + 1)}="{v}" />') """ Step 6 """ -# class A(Element): -# -# def __init__(self, link, content): -# self.link = link -# self.content = content -# super(Element).__init__() -# -# def render(self, file_name): -# head = 'a href=' -# tail = 'a' -# outtext = f'<{head}"{self.link}">{self.content}' -# with open(f'{file_name}.html', 'w') as file: -# file.write(outtext) +class A(OneLineTag): + + tag = 'a' + + def __init__(self, link, content=None, **attrs): + if not (content and link): raise TypeError + + attrs['href'] = link + super().__init__(content, **attrs) + + tag = 'a' + + # def __init__(self, link, content): + # self.link = link + # self.content = content + # #super(Element).__init__() + # + # def render(self, file_name): + # filename.write() + # head = 'a href=' + # tail = 'a' + # outtext = f'<{head}"{self.link}">{self.content}' + # with open(f'{file_name}.html', 'w') as file: + # file.write(outtext) # # class Ul(Element): # """ @@ -156,14 +159,7 @@ def append(self, new_content): # """ # list_element = '' # -# class Head(OneLineTag): -# -# def __init__(self, level, content, tag=None, **kwargs): -# self.level = level -# self.content = content -# self.tag = f'h{level}' -# self.kwargs = kwargs -# super(OneLineTag).__init__(list, tag, **kwargs) + # # class Meta(SelfClosingTag): # """ From fac9bea042ac2801eb049478166e7489b54a58ae Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Tue, 5 Mar 2019 17:32:52 -0800 Subject: [PATCH 064/367] session 08 material --- students/jeff_shabani/session08/Circle.py | 15 +++++++++++++++ students/jeff_shabani/session08/__init__.py | 0 students/jeff_shabani/session08/test_circle.py | 6 ++++++ 3 files changed, 21 insertions(+) create mode 100644 students/jeff_shabani/session08/Circle.py create mode 100644 students/jeff_shabani/session08/__init__.py create mode 100644 students/jeff_shabani/session08/test_circle.py diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py new file mode 100644 index 00000000..7619efa8 --- /dev/null +++ b/students/jeff_shabani/session08/Circle.py @@ -0,0 +1,15 @@ + + + + + +class Circle(object): + def __init__(self, radius): + self.radius = radius + + def __repr__(self): + return f'The radius is {self.radius}' + + +c = Circle(5) +print(c) \ No newline at end of file diff --git a/students/jeff_shabani/session08/__init__.py b/students/jeff_shabani/session08/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py new file mode 100644 index 00000000..a5ba9adf --- /dev/null +++ b/students/jeff_shabani/session08/test_circle.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import io +import pytest + +from Circle import * \ No newline at end of file From f524f0d22c982cd7598cd2d485a808d6ca12bca5 Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Tue, 5 Mar 2019 17:55:24 -0800 Subject: [PATCH 065/367] session 08 material --- students/jeff_shabani/session08/Circle.py | 5 +++-- .../jeff_shabani/session08/test_circle.py | 20 ++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 7619efa8..02c9a178 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -11,5 +11,6 @@ def __repr__(self): return f'The radius is {self.radius}' -c = Circle(5) -print(c) \ No newline at end of file +if __name__ =='__main__': + c = Circle(5) + print(c) \ No newline at end of file diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index a5ba9adf..ef3f53d5 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -2,5 +2,23 @@ import io import pytest +import unittest -from Circle import * \ No newline at end of file +from Circle import * + + +def test_init(): + c = Circle(5) + + assert print(c) == 6, 'Not equal' + +# c = Circle(8) +# print(c.radius) +# class mailroomTests(unittest.TestCase): +# +# def test_init(self): +# c=Circle(5) +# self.assertEqual(print(c.radius), 5) +# +# if __name__ == '__main__': +# unittest.main() \ No newline at end of file From 11f9b59b9f07ec36d1ec38e48d4ad6af38c6d55e Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Tue, 5 Mar 2019 18:18:06 -0800 Subject: [PATCH 066/367] html_render update --- .../jeff_shabani/session08/test_circle.py | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index ef3f53d5..a7edb78b 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -7,18 +7,14 @@ from Circle import * -def test_init(): - c = Circle(5) - - assert print(c) == 6, 'Not equal' - -# c = Circle(8) -# print(c.radius) -# class mailroomTests(unittest.TestCase): -# -# def test_init(self): -# c=Circle(5) -# self.assertEqual(print(c.radius), 5) -# -# if __name__ == '__main__': -# unittest.main() \ No newline at end of file +c=Circle(5) + +class mailroomTests(unittest.TestCase): + + + def test_init(self): + #c=Circle(5) + self.assertEqual(c.radius, 5) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From 48fbdab47df7367dfea0a7acc0f2fb3d85ead20b Mon Sep 17 00:00:00 2001 From: mjchang14 Date: Tue, 5 Mar 2019 19:39:00 -0800 Subject: [PATCH 067/367] adding completed HTML assignment --- students/mjchang/session07/html_render.py | 34 ++-- students/mjchang/session07/run_html_render.py | 48 +++--- .../mjchang/session07/test_html_render.py | 148 ++++++++++-------- 3 files changed, 133 insertions(+), 97 deletions(-) diff --git a/students/mjchang/session07/html_render.py b/students/mjchang/session07/html_render.py index b507d974..a2f4454e 100644 --- a/students/mjchang/session07/html_render.py +++ b/students/mjchang/session07/html_render.py @@ -9,6 +9,7 @@ class Element(object): tag = "html" + indent = " " def __init__(self, content=None, **kwargs): self.attributes = kwargs @@ -20,16 +21,16 @@ def append(self, new_content): self.contents.append(new_content) - def render(self, out_file): - out_file.write(self._open_tag()) + def render(self, out_file, cur_ind=""): + out_file.write(cur_ind + self._open_tag()) out_file.write("\n") for content in self.contents: try: - content.render(out_file) + content.render(out_file, cur_ind + self.indent) except AttributeError: - out_file.write(content) + out_file.write(cur_ind + self.indent + content) out_file.write("\n") - out_file.write(self._close_tag()) + out_file.write(cur_ind + self._close_tag()) out_file.write("\n") def _open_tag(self): @@ -45,11 +46,11 @@ def _close_tag(self): class OneLineTag(Element): - def render(self, out_file): + def render(self, out_file, cur_ind=""): for content in self.contents: - out_file.write(self._open_tag()) #removed newline + out_file.write(cur_ind + self._open_tag()) #removed newline try: - content.render(out_file) + content.render(out_file, cur_ind) except AttributeError: out_file.write(content) #removed newline from Element out_file.write(self._close_tag()) @@ -64,8 +65,8 @@ def __init__(self, content=None, **kwargs): raise TypeError("SelfClosingTag cannot contain any content") super().__init__(content=content, **kwargs) - def render(self, out_file): - tag = self._open_tag()[:-1] + " />\n" + def render(self, out_file, cur_ind=""): + tag = cur_ind + self._open_tag()[:-1] + " />\n" out_file.write(tag) def append(self, *args): @@ -80,6 +81,12 @@ class Br(SelfClosingTag): class Html(Element): tag = "html" + doctype = "" + + def render(self, out_file, cur_ind=""): + out_file.write(cur_ind + self.doctype) + out_file.write("\n") + super().render(out_file, cur_ind) class Body(Element): tag = "body" @@ -103,10 +110,13 @@ def __init__(self, link, content=None, **kwargs): class Ul(Element): tag = "ul" -class List(Element): +class Li(Element): tag = "li" class H(OneLineTag): def __init__(self, level, content, **kwargs): self.tag = "h{}".format(level) - super().__init__(content, **kwargs) \ No newline at end of file + super().__init__(content, **kwargs) + +class Meta(SelfClosingTag): + tag = 'meta charset="UTF-8"' \ No newline at end of file diff --git a/students/mjchang/session07/run_html_render.py b/students/mjchang/session07/run_html_render.py index 054cb8e3..718ec63b 100644 --- a/students/mjchang/session07/run_html_render.py +++ b/students/mjchang/session07/run_html_render.py @@ -190,42 +190,42 @@ def render_page(page, filename, indent=None): render_page(page, "test_html_output7.html") -# # Step 8 and 9 -# ############## +# Step 8 and 9 +############## -# page = hr.Html() +page = hr.Html() -# head = hr.Head() -# head.append( hr.Meta(charset="UTF-8") ) -# head.append(hr.Title("PythonClass = Revision 1087:")) +head = hr.Head() +head.append( hr.Meta(charset="UTF-8") ) +head.append(hr.Title("PythonClass = Revision 1087:")) -# page.append(head) +page.append(head) -# body = hr.Body() +body = hr.Body() -# body.append( hr.H(2, "PythonClass - Example") ) +body.append( hr.H(2, "PythonClass - Example") ) -# body.append(hr.P("Here is a paragraph of text -- there could be more of them, " -# "but this is enough to show that we can do some text", -# style="text-align: center; font-style: oblique;")) +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) -# body.append(hr.Hr()) +body.append(hr.Hr()) -# list = hr.Ul(id="TheList", style="line-height:200%") +list = hr.Ul(id="TheList", style="line-height:200%") -# list.append( hr.Li("The first item in a list") ) -# list.append( hr.Li("This is the second item", style="color: red") ) +list.append( hr.Li("The first item in a list") ) +list.append( hr.Li("This is the second item", style="color: red") ) -# item = hr.Li() -# item.append("And this is a ") -# item.append( hr.A("http://google.com/", "link") ) -# item.append("to google") +item = hr.Li() +item.append("And this is a ") +item.append( hr.A("http://google.com/", "link") ) +item.append("to google") -# list.append(item) +list.append(item) -# body.append(list) +body.append(list) -# page.append(body) +page.append(body) -# render_page(page, "test_html_output8.html") +render_page(page, "test_html_output8.html") diff --git a/students/mjchang/session07/test_html_render.py b/students/mjchang/session07/test_html_render.py index 9566f211..3dc0ae16 100644 --- a/students/mjchang/session07/test_html_render.py +++ b/students/mjchang/session07/test_html_render.py @@ -277,14 +277,14 @@ def test_anchor(): ####### def test_list(): - e = List("The first item is a list") + e = Li("The first item is a list") # print(file_contents) file_contents = render_result(e).strip() print(file_contents) assert ("The first item is a list") in file_contents assert file_contents.startswith("
  • ") - e2 = List("This is the second item", style="color: red") + e2 = Li("This is the second item", style="color: red") file_contents = render_result(e2).strip() print(file_contents) assert ("This is the second item") in file_contents @@ -308,83 +308,109 @@ def test_header(): assert ("PythonClass - Class 6 example") in file_contents -##################### +####### +# Step 8 +####### + +def test_doctype(): + e = Html("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + print(file_contents) + assert("") in file_contents + assert file_contents.endswith("") + + + +def test_meta(): + meta = Meta() + file_contents = render_result(meta) + print(file_contents) + assert file_contents == '\n' + + + +#################### # indentation testing # Uncomment for Step 9 -- adding indentation -##################### +#################### -# def test_indent(): -# """ -# Tests that the indentation gets passed through to the renderer -# """ -# html = Html("some content") -# file_contents = render_result(html, ind=" ").rstrip() #remove the end newline +def test_indent(): + """ + Tests that the indentation gets passed through to the renderer + """ + html = Html("some content") + file_contents = render_result(html, ind=" ").rstrip() #remove the end newline -# print(file_contents) -# lines = file_contents.split("\n") -# assert lines[0].startswith(" <") -# print(repr(lines[-1])) -# assert lines[-1].startswith(" <") + print(file_contents) + lines = file_contents.split("\n") + assert lines[0].startswith(" <") + print(repr(lines[-1])) + assert lines[-1].startswith(" <") -# def test_indent_contents(): -# """ -# The contents in a element should be indented more than the tag -# by the amount in the indent class attribute -# """ -# html = Element("some content") -# file_contents = render_result(html, ind="") +def test_indent_contents(): + """ + The contents in a element should be indented more than the tag + by the amount in the indent class attribute + """ + html = Element("some content") + file_contents = render_result(html, ind="") -# print(file_contents) -# lines = file_contents.split("\n") -# assert lines[1].startswith(Element.indent) + print(file_contents) + lines = file_contents.split("\n") + assert lines[1].startswith(Element.indent) -# def test_multiple_indent(): -# """ -# make sure multiple levels get indented fully -# """ -# body = Body() -# body.append(P("some text")) -# html = Html(body) +def test_multiple_indent(): + """ + make sure multiple levels get indented fully + """ + body = Body() + body.append(P("some text")) + html = Html(body) -# file_contents = render_result(html) + file_contents = render_result(html) -# print(file_contents) -# lines = file_contents.split("\n") -# for i in range(3): # this needed to be adapted to the tag -# assert lines[i + 1].startswith(i * Element.indent + "<") + print(file_contents) + lines = file_contents.split("\n") + for i in range(3): # this needed to be adapted to the tag + assert lines[i + 1].startswith(i * Element.indent + "<") -# assert lines[4].startswith(3 * Element.indent + "some") + assert lines[4].startswith(3 * Element.indent + "some") -# def test_element_indent1(): -# """ -# Tests whether the Element indents at least simple content +def test_element_indent1(): + """ + Tests whether the Element indents at least simple content -# we are expecting to to look like this: + we are expecting to to look like this: -# -# this is some text -# <\html> + + this is some text + <\html> -# More complex indentation should be tested later. -# """ -# e = Element("this is some text") + More complex indentation should be tested later. + """ + e = Element("this is some text") -# # This uses the render_results utility above -# file_contents = render_result(e).strip() + # This uses the render_results utility above + file_contents = render_result(e).strip() -# # making sure the content got in there. -# assert("this is some text") in file_contents + # making sure the content got in there. + assert("this is some text") in file_contents -# # break into lines to check indentation -# lines = file_contents.split('\n') -# # making sure the opening and closing tags are right. -# assert lines[0] == "" -# # this line should be indented by the amount specified -# # by the class attribute: "indent" -# assert lines[1].startswith(Element.indent + "thi") -# assert lines[2] == "" -# assert file_contents.endswith("") + # break into lines to check indentation + lines = file_contents.split('\n') + # making sure the opening and closing tags are right. + assert lines[0] == "" + # this line should be indented by the amount specified + # by the class attribute: "indent" + assert lines[1].startswith(Element.indent + "thi") + assert lines[2] == "" + assert file_contents.endswith("") From f1e90c5b6c06e4c034da5482ebf7d5a3a475080f Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Tue, 5 Mar 2019 19:43:09 -0800 Subject: [PATCH 068/367] circle class --- students/jeff_shabani/session08/Circle.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 02c9a178..b9358927 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,16 +1,29 @@ +#!/usr/bin/env python3 +class Circle(object): + def __init__(self, radius): + self.radius = radius + self.diameter = radius * 2 + @property + def diameter(self): + return self.radius * 2 + @diameter.setter + def diameter(self, value): + self.diameter = value + #@diameter.getter -class Circle(object): - def __init__(self, radius): - self.radius = radius def __repr__(self): - return f'The radius is {self.radius}' + return f'The radius is {self.radius} & diamer is {self.diameter}' if __name__ =='__main__': c = Circle(5) - print(c) \ No newline at end of file + + print(c) + + c.diameter = 20 + print(c.diameter) \ No newline at end of file From 0d6b25285bdb74d95248fff8596485aa669c30d2 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Tue, 5 Mar 2019 19:43:20 -0800 Subject: [PATCH 069/367] circle class --- students/jeff_shabani/session08/test_circle.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index a7edb78b..1ffa7c0a 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -13,8 +13,15 @@ class mailroomTests(unittest.TestCase): def test_init(self): - #c=Circle(5) + """test for instantiation""" self.assertEqual(c.radius, 5) + def test_diameter_calc(self): + self.assertEqual(c.diameter, c.radius*2) + + def test_diameter_setter(self): + c.diameter = 24 + self.assertEqual(c.diameter, 24) + if __name__ == '__main__': unittest.main() \ No newline at end of file From 91ea877904c45ac84f98d7ed4977455d2ed5a913 Mon Sep 17 00:00:00 2001 From: Elaine Xu Date: Tue, 5 Mar 2019 21:29:28 -0800 Subject: [PATCH 070/367] code review --- .../elaine_x/session08/circle_exercise_ex.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 students/elaine_x/session08/circle_exercise_ex.py diff --git a/students/elaine_x/session08/circle_exercise_ex.py b/students/elaine_x/session08/circle_exercise_ex.py new file mode 100644 index 00000000..6b0ae0ea --- /dev/null +++ b/students/elaine_x/session08/circle_exercise_ex.py @@ -0,0 +1,86 @@ +''' +########################## +#Python 210 +#Session 07 - Circle Exercise +#Elaine Xu +#Mar 5, 2019 +########################### +''' +import math +############################# +#Step 1 create class called circle +############################# +class Circle(object): + def __init__(self, radius): + self.radius = radius + +############################# +#Step 2 add diameter property +############################# + @property + def diameter(self): + print("in getter") + return self.radius * 2 + +############################# +# Step 3 set up diameter property setter +############################# + @diameter.setter + def diameter(self, value): + print("in setter", value) + self.radius = value / 2 + +############################# +# Step 4 add an area property +############################# + @property + def area(self): + return math.pi * self.radius**2 + +############################# +# Step 5 add an alternate constructor that create circle directly with the diameter +############################# + +# @classmethod +# def from_diameter(cls, diameter): +# self = cls(self) +# self.diameter = diameter +# self.radius = diameter/2 +# return self.diameter + + +############################# +# Step 6 add __str__ and __repr__ methods +############################# + def __str__(self): + return "Circle with radius: " + str(self.radius) + + def __repr__(self): + return "Circle({})".format(self.radius) + + +############################# +# Step 7 add numerical protocol +############################# + def __add__(self, other): + return "Circle({})".format(self.radius + other.radius) + + def __mul__(self, other): + return "Circle({})".format(self.radius * other) + +############################# +# Step 8 add ability to compare two circles +############################# + +############################# +# Step 9 sphere subclassing +############################# +'''c = Circle(4) +c = Circle.from_diameter(8) +print(c.diameter) +''' +c1 = Circle(2) +c2 = Circle(4) +print(c1+c2) +print(c2 * 3) +#print(3 * c2) \ No newline at end of file From 7240d38c9c7fecbe0941a68b91c24399f7d63c2f Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 06:55:58 -0800 Subject: [PATCH 071/367] Update to html_render --- .../session07/test_html_render.py | 194 +++++++++++++----- 1 file changed, 137 insertions(+), 57 deletions(-) diff --git a/students/jeff_shabani/session07/test_html_render.py b/students/jeff_shabani/session07/test_html_render.py index 9f6bc769..559d69ed 100644 --- a/students/jeff_shabani/session07/test_html_render.py +++ b/students/jeff_shabani/session07/test_html_render.py @@ -6,6 +6,7 @@ import io import pytest +import unittest # import * is often bad form, but makes it easier to test everything in a module. from html_render import * @@ -33,28 +34,28 @@ def render_result(element, ind=""): ######## # Step 1 ######## - -def test_init(): - """ - This only tests that it can be initialized with and without - some content -- but it's a start - """ - e = Element() - - e = Element("this is some text") - - -def test_append(): - """ - This tests that you can append text - - It doesn't test if it works -- - that will be covered by the render test later - """ - e = Element("this is some text") - e.append("some more text") - - +# +# def test_init(): +# """ +# This only tests that it can be initialized with and without +# some content -- but it's a start +# """ +# e = Element() +# +# e = Element("this is some text") +# +# +# def test_append(): +# """ +# This tests that you can append text +# +# It doesn't test if it works -- +# that will be covered by the render test later +# """ +# e = Element("this is some text") +# e.append("some more text") +# +# # def test_render_element(): # """ # Tests whether the Element can render two pieces of text @@ -78,79 +79,94 @@ def test_append(): # # making sure the opening and closing tags are right. # assert file_contents.startswith("") # assert file_contents.endswith("") - -# # Uncomment this one after you get the one above to pass -# # Does it pass right away? +# +# # # Uncomment this one after you get the one above to pass +# # # Does it pass right away? # def test_render_element2(): # """ # Tests whether the Element can render two pieces of text # So it is also testing that the append method works correctly. - +# # It is not testing whether indentation or line feeds are correct. # """ # e = Element() # e.append("this is some text") # e.append("and this is some more text") - +# # # This uses the render_results utility above # file_contents = render_result(e).strip() - +# # # making sure the content got in there. # assert("this is some text") in file_contents # assert("and this is some more text") in file_contents - +# # # make sure it's in the right order # assert file_contents.index("this is") < file_contents.index("and this") - +# # # making sure the opening and closing tags are right. # assert file_contents.startswith("") # assert file_contents.endswith("") - - - -# # ######## -# # # Step 2 -# # ######## - +# +# +# +# # # ######## +# # # # Step 2 +# # # ######## +# # # tests for the new tags # def test_html(): # e = Html("this is some text") # e.append("and this is some more text") - +# # file_contents = render_result(e).strip() - +# # assert("this is some text") in file_contents # assert("and this is some more text") in file_contents # print(file_contents) # assert file_contents.endswith("") - - +# +# # def test_body(): # e = Body("this is some text") # e.append("and this is some more text") - +# # file_contents = render_result(e).strip() - +# # assert("this is some text") in file_contents # assert("and this is some more text") in file_contents - +# # assert file_contents.startswith("") # assert file_contents.endswith("") - - +# +# +# def test_head(): +# """ Tests that you can add the tag """ +# +# head = Head("this is some text") +# head.append("and this is some more text") +# +# file_contents = render_result(head).strip() +# print(file_contents) +# +# assert "this is some text" in file_contents +# assert "and this is some more text" in file_contents +# assert file_contents.startswith("") +# assert file_contents.endswith("") +# +# # def test_p(): # e = P("this is some text") # e.append("and this is some more text") - +# # file_contents = render_result(e).strip() - +# # assert("this is some text") in file_contents # assert("and this is some more text") in file_contents - +# # assert file_contents.startswith("

    ") # assert file_contents.endswith("

    ") - - +# +# # def test_sub_element(): # """ # tests that you can add another element and still render properly @@ -159,10 +175,10 @@ def test_append(): # page.append("some plain text.") # page.append(P("A simple paragraph of text")) # page.append("Some more plain text.") - +# # file_contents = render_result(page) # print(file_contents) # so we can see it if the test fails - +# # # note: The previous tests should make sure that the tags are getting # # properly rendered, so we don't need to test that here. # assert "some plain text" in file_contents @@ -172,15 +188,79 @@ def test_append(): # # but make sure the embedded element's tags get rendered! # assert "

    " in file_contents # assert "

    " in file_contents +# +# ####### +# # Step 3 +# ######## +# +# # Add your tests here! +# +# def test_one_line_tag(): +# """Test proper implementation""" +# olt = OneLineTag("the initial content") +# file_contents = render_result(olt).strip() +# print(file_contents) +# +# assert file_contents.startswith("") +# assert file_contents.endswith("") +# assert "the initial content" in file_contents +# assert "some more content" not in file_contents + +####### +# Step 5 +######## +def test_self_closing_tag(): + sct = SelfClosingTag(width=400) + file_contents = render_result(sct) + print('This is the result:',file_contents) -######## -# Step 3 -######## + assert file_contents.startswith('
    ') + assert f'
    ' in file_contents -# Add your tests here! + +def test_self_closing_tag_2(): + """Test that conent cannot be appended to the self closing tag""" + sct = SelfClosingTag() + + with pytest.raises(NotImplementedError): + sct.append("This should not append") + + file_contents = render_result(sct).strip() + print(file_contents) + + assert "This should not append" not in file_contents + + +def test_class_a(): + ca = A("http://google.com/", "link to google") + file_contents = render_result(ca) + print(file_contents) + + assert f'
    link to google' in file_contents + + +# def test_ul_li(): +# """ Tests that you can add unordered lists and list items """ +# with pytest.raises(TypeError): +# ul = Ul("Should fail") +# +# ul = Ul(style='list-style-type:disc;') +# ul.append(Li("List item 1")) +# ul.append(Li("List item 2")) +# +# file_contents = render_result(ul).strip() +# print(file_contents) +# +# assert file_contents.startswith("
      ") +# assert "List item 1" in file_contents +# assert "List item 2" in file_contents +# assert file_contents.count("
    • ") == 2 +# assert file_contents.count("
    • ") == 2 # ##################### # # indentation testing From 184611091da9ede775d62c9b84b52181eda10e0c Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 06:58:04 -0800 Subject: [PATCH 072/367] Update to html_render --- students/jeff_shabani/session07/html_render.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 23aaba5a..17374899 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -132,8 +132,6 @@ def __init__(self, link, content=None, **attrs): attrs['href'] = link super().__init__(content, **attrs) - tag = 'a' - # def __init__(self, link, content): # self.link = link # self.content = content From 737a99da2b7f650029d30f9a5f49ebaf67ab52bb Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 07:44:38 -0800 Subject: [PATCH 073/367] Update to Circle --- students/jeff_shabani/session08/Circle.py | 22 ++++++++++--------- .../jeff_shabani/session08/test_circle.py | 12 ++++++++-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index b9358927..ffab09d9 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -3,15 +3,15 @@ class Circle(object): def __init__(self, radius): self.radius = radius - self.diameter = radius * 2 + @property def diameter(self): - return self.radius * 2 + return self.radius *2 @diameter.setter def diameter(self, value): - self.diameter = value + self.radius = value / 2 #@diameter.getter @@ -20,10 +20,12 @@ def __repr__(self): return f'The radius is {self.radius} & diamer is {self.diameter}' -if __name__ =='__main__': - c = Circle(5) - - print(c) - - c.diameter = 20 - print(c.diameter) \ No newline at end of file +# if __name__ =='__main__': +# c = Circle(5) +# print(c) +# +# c.radius=6 +# print(c) +# +# c.diameter = 40 +# print(c) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 1ffa7c0a..9f17840d 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -7,21 +7,29 @@ from Circle import * -c=Circle(5) -class mailroomTests(unittest.TestCase): + +class circleTests(unittest.TestCase): + def test_init(self): """test for instantiation""" + c = Circle(5) self.assertEqual(c.radius, 5) + del c def test_diameter_calc(self): + c = Circle(4) self.assertEqual(c.diameter, c.radius*2) + del c def test_diameter_setter(self): + c=Circle(5) + self.assertEqual(c.diameter, 10) c.diameter = 24 self.assertEqual(c.diameter, 24) + del c if __name__ == '__main__': unittest.main() \ No newline at end of file From 08a0e66c7c11c2c8a2a0b82a78f7da95fafab6b4 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 08:28:20 -0800 Subject: [PATCH 074/367] Update to html_render --- students/jeff_shabani/session08/Circle.py | 29 +++++++++++-------- .../jeff_shabani/session08/test_circle.py | 6 ++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index ffab09d9..36e889fb 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import math class Circle(object): def __init__(self, radius): @@ -13,19 +14,23 @@ def diameter(self): def diameter(self, value): self.radius = value / 2 + @property + def area(self): + return math.pi * pow(self.radius,2) + #@diameter.getter def __repr__(self): - return f'The radius is {self.radius} & diamer is {self.diameter}' - - -# if __name__ =='__main__': -# c = Circle(5) -# print(c) -# -# c.radius=6 -# print(c) -# -# c.diameter = 40 -# print(c) + return f'The radius is {self.radius} & diamer is {self.diameter}. Area ist {self.area}' + + +if __name__ =='__main__': + c = Circle(5) + print(c) + + c.radius=6 + print(c) + + c.diameter = 40 + print(c) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 9f17840d..89317833 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import io +import math import pytest import unittest @@ -29,7 +30,12 @@ def test_diameter_setter(self): self.assertEqual(c.diameter, 10) c.diameter = 24 self.assertEqual(c.diameter, 24) + self.assertEqual(c.radius, 12) del c + def test_area(self): + c = Circle(5) + self.assertEqual(c.area, math.pi * pow(c.radius,2)) + if __name__ == '__main__': unittest.main() \ No newline at end of file From 340740b132f499e2b046020a3b2418de02ca1bd5 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 08:57:41 -0800 Subject: [PATCH 075/367] Circle updates --- students/jeff_shabani/session08/Circle.py | 14 ++++++++++++-- students/jeff_shabani/session08/test_circle.py | 7 +++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 36e889fb..6a6aefb3 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -18,8 +18,10 @@ def diameter(self, value): def area(self): return math.pi * pow(self.radius,2) - #@diameter.getter - + @classmethod + def from_diameter(cls, value): + radius = value / 2 + return cls(radius) def __repr__(self): return f'The radius is {self.radius} & diamer is {self.diameter}. Area ist {self.area}' @@ -28,9 +30,17 @@ def __repr__(self): if __name__ =='__main__': c = Circle(5) print(c) + #del c c.radius=6 print(c) + #del c + c.diameter = 40 print(c) + del c + + nc = Circle.from_diameter(2) + print(nc) + diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 89317833..1f414919 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -36,6 +36,13 @@ def test_diameter_setter(self): def test_area(self): c = Circle(5) self.assertEqual(c.area, math.pi * pow(c.radius,2)) + del c + + def test_from_diameter(self): + c = Circle.from_diameter(6) + self.assertEqual(c.radius, 3) + self.assertEqual(c.diameter, 6) + if __name__ == '__main__': unittest.main() \ No newline at end of file From c8ddbc8d7eaad1e7be208347a8287aadf7d843e2 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 09:20:27 -0800 Subject: [PATCH 076/367] Update to html_render --- students/jeff_shabani/session08/Circle.py | 6 +++++- students/jeff_shabani/session08/test_circle.py | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 6a6aefb3..9b2f616c 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -24,7 +24,10 @@ def from_diameter(cls, value): return cls(radius) def __repr__(self): - return f'The radius is {self.radius} & diamer is {self.diameter}. Area ist {self.area}' + return f'Circle with radius of {self.radius}' + + def __str__(self): + return f'Circle with radius of {self.radius}' if __name__ =='__main__': @@ -43,4 +46,5 @@ def __repr__(self): nc = Circle.from_diameter(2) print(nc) + print(repr(nc)) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 1f414919..b3c86799 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -42,6 +42,11 @@ def test_from_diameter(self): c = Circle.from_diameter(6) self.assertEqual(c.radius, 3) self.assertEqual(c.diameter, 6) + del c + + def test_print(self): + c = Circle(8) + self.assertEqual(repr(c), 'Circle with radius of 8') if __name__ == '__main__': From 08043f63710a55789fe7dc44bdf056a3bac28dc7 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 09:39:11 -0800 Subject: [PATCH 077/367] Circle update --- students/jeff_shabani/session08/test_circle.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index b3c86799..d3938f00 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -47,6 +47,12 @@ def test_from_diameter(self): def test_print(self): c = Circle(8) self.assertEqual(repr(c), 'Circle with radius of 8') + del c + + def test_math(self): + c1 = Circle(2) + c2 = Circle(3) + self.assertEqual(c1 + c2, 5.0) if __name__ == '__main__': From 5885aa105bf237273a43e2ef228ac736b7ad5201 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 09:48:07 -0800 Subject: [PATCH 078/367] Circle update --- students/jeff_shabani/session08/Circle.py | 14 ++++++++++++++ students/jeff_shabani/session08/test_circle.py | 3 +++ 2 files changed, 17 insertions(+) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 9b2f616c..31480b66 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -23,6 +23,14 @@ def from_diameter(cls, value): radius = value / 2 return cls(radius) + def __add__(self, other): + return self.radius + other.radius + + def __mul__(self, other): + return self.radius * other + + __rmul__ = __mul__ + def __repr__(self): return f'Circle with radius of {self.radius}' @@ -48,3 +56,9 @@ def __str__(self): print(nc) print(repr(nc)) + c2 = Circle(2) + print(nc + c2) + print(nc * 3) + print(3 * nc) + + diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index d3938f00..fa736eca 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -53,6 +53,9 @@ def test_math(self): c1 = Circle(2) c2 = Circle(3) self.assertEqual(c1 + c2, 5.0) + self.assertEqual(c1 * 5, 10.0) + #this tests argument reversal in mult function + self.assertEqual(5 * c1, 10.0) if __name__ == '__main__': From e0f9ea769753506da907887e10c61f9b828ca453 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 10:09:13 -0800 Subject: [PATCH 079/367] Circle updates --- students/jeff_shabani/session08/Circle.py | 24 ++++++++++++++++--- .../jeff_shabani/session08/test_circle.py | 12 ++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 31480b66..3277957f 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 import math + class Circle(object): def __init__(self, radius): self.radius = radius - @property def diameter(self): - return self.radius *2 + return self.radius * 2 @diameter.setter def diameter(self, value): @@ -16,7 +16,7 @@ def diameter(self, value): @property def area(self): - return math.pi * pow(self.radius,2) + return math.pi * pow(self.radius, 2) @classmethod def from_diameter(cls, value): @@ -31,6 +31,18 @@ def __mul__(self, other): __rmul__ = __mul__ + def __lt__(self, other): + return self.radius < other.radius + + def __gt__(self, other): + return self.radius > other.radius + + def __eq__(self, other): + return self.radius == other.radius + + def __ne__(self, other): + return self.radius != other.radius + def __repr__(self): return f'Circle with radius of {self.radius}' @@ -60,5 +72,11 @@ def __str__(self): print(nc + c2) print(nc * 3) print(3 * nc) + del nc + c1 = Circle(5) + c3 = Circle(5) + print(c1 < c2) + print(c2 * c1) + print(c2 != c1) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index fa736eca..f8687818 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -56,6 +56,18 @@ def test_math(self): self.assertEqual(c1 * 5, 10.0) #this tests argument reversal in mult function self.assertEqual(5 * c1, 10.0) + del c1, c2 + + def test_compare_circles(self): + c1 = Circle(2) + c2 = Circle(3) + c3 = Circle(3) + self.assertEqual(c1 > c2, False) + self.assertEqual(c1 < c2, True) + self.assertEqual(c1 != c2, True) + self.assertEqual(c3 == c2, True) + self.assertEqual(c1 * c2, 6.0) + if __name__ == '__main__': From 261da5c7e7350fbdf5045468dc51c6fab466f8d0 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Wed, 6 Mar 2019 10:47:11 -0800 Subject: [PATCH 080/367] Made some tests based off of the instructions. So far so good. --- .../jesse_miller/session08/test_circle.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 students/jesse_miller/session08/test_circle.py diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py new file mode 100644 index 00000000..a2a955ff --- /dev/null +++ b/students/jesse_miller/session08/test_circle.py @@ -0,0 +1,51 @@ +# Tests for Circle Class + +import pytest +from math import pi +from circle import Circle + + +# Step 1 +def test_empty(): + with pytest.raises(TypeError): + Circle() + + +def test_new(): + Circle(1) + + +def test_radius(): + c = Circle(2) + + assert c.radius == 2 + + +# Step 2 +def test_diameter(): + c = Circle(3) + + assert c.diameter == 6 + + +# Step 3 +def test_diameter_set(): + c = Circle(4) + c.diameter = 5 + + assert c.diameter == 5 + assert c.radius == 2.5 + + +# Step 4 +def test_area(): + c = Circle(6) + + assert c.area == pi * 36 + + +def test_area_set(): + c = Circle(7) + + with pytest.raises(AttributeError): + c.area = 10 From 6a980668fdd78b2538510d805ceaa4e2361b1c5a Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 11:09:03 -0800 Subject: [PATCH 081/367] Update to html_render --- students/jeff_shabani/session08/Circle.py | 60 ++++++++++--------- .../jeff_shabani/session08/test_circle.py | 18 ++---- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 3277957f..4e2eb3f8 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,10 +1,19 @@ #!/usr/bin/env python3 import math +import weakref +from weakref import WeakSet + +from collections import defaultdict +import gc class Circle(object): + + instances = [] + def __init__(self, radius): self.radius = radius + Circle.instances.append(self) @property def diameter(self): @@ -50,33 +59,30 @@ def __str__(self): return f'Circle with radius of {self.radius}' + if __name__ =='__main__': - c = Circle(5) - print(c) - #del c - - c.radius=6 - print(c) - #del c - - - c.diameter = 40 - print(c) - del c - - nc = Circle.from_diameter(2) - print(nc) - print(repr(nc)) - - c2 = Circle(2) - print(nc + c2) - print(nc * 3) - print(3 * nc) - del nc - c1 = Circle(5) - c3 = Circle(5) - print(c1 < c2) - print(c2 * c1) - print(c2 != c1) + + c1 = Circle(1) + c2 = Circle(5) + c3 = Circle(3) + c4 = Circle(4) + c5 = Circle(2) + + for i in Circle.instances: + print(i) + + + + + + + + + + + + + + diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index f8687818..9bd82cee 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -1,19 +1,12 @@ #!/usr/bin/env python3 -import io -import math -import pytest import unittest from Circle import * - - class circleTests(unittest.TestCase): - - def test_init(self): """test for instantiation""" c = Circle(5) @@ -22,11 +15,11 @@ def test_init(self): def test_diameter_calc(self): c = Circle(4) - self.assertEqual(c.diameter, c.radius*2) + self.assertEqual(c.diameter, c.radius * 2) del c def test_diameter_setter(self): - c=Circle(5) + c = Circle(5) self.assertEqual(c.diameter, 10) c.diameter = 24 self.assertEqual(c.diameter, 24) @@ -35,7 +28,7 @@ def test_diameter_setter(self): def test_area(self): c = Circle(5) - self.assertEqual(c.area, math.pi * pow(c.radius,2)) + self.assertEqual(c.area, math.pi * pow(c.radius, 2)) del c def test_from_diameter(self): @@ -54,7 +47,7 @@ def test_math(self): c2 = Circle(3) self.assertEqual(c1 + c2, 5.0) self.assertEqual(c1 * 5, 10.0) - #this tests argument reversal in mult function + # this tests argument reversal in mult function self.assertEqual(5 * c1, 10.0) del c1, c2 @@ -69,6 +62,5 @@ def test_compare_circles(self): self.assertEqual(c1 * c2, 6.0) - if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() From 1344d3a89ea4bf7d5d4be13fc4aafe8c7cafee93 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 11:10:03 -0800 Subject: [PATCH 082/367] Circle updates --- students/jeff_shabani/session08/Circle.py | 25 +------------------ .../jeff_shabani/session08/test_circle.py | 1 - 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 4e2eb3f8..ab7b636b 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,14 +1,8 @@ #!/usr/bin/env python3 import math -import weakref -from weakref import WeakSet - -from collections import defaultdict -import gc class Circle(object): - instances = [] def __init__(self, radius): @@ -59,8 +53,7 @@ def __str__(self): return f'Circle with radius of {self.radius}' - -if __name__ =='__main__': +if __name__ == '__main__': c1 = Circle(1) c2 = Circle(5) @@ -70,19 +63,3 @@ def __str__(self): for i in Circle.instances: print(i) - - - - - - - - - - - - - - - - diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 9bd82cee..18e4d7ff 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - import unittest from Circle import * From c7d69a417aec1bece115fe410cc5dbaa49553341 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 11:29:25 -0800 Subject: [PATCH 083/367] Circle updates --- students/jeff_shabani/session08/Circle.py | 6 ++++++ students/jeff_shabani/session08/test_circle.py | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index ab7b636b..378cbbf2 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -29,6 +29,12 @@ def from_diameter(cls, value): def __add__(self, other): return self.radius + other.radius + def __iadd__(self, other): + return self.radius + other.radius + + def __ipow__(self, other): + return self.radius ** other + def __mul__(self, other): return self.radius * other diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 18e4d7ff..9a142b97 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -59,6 +59,19 @@ def test_compare_circles(self): self.assertEqual(c1 != c2, True) self.assertEqual(c3 == c2, True) self.assertEqual(c1 * c2, 6.0) + self.assertEqual(c1 * 10, 20) + self.assertEqual(c1 * 10 == 10 * c1, True) + del c1, c2, c3 + + def test_extended_assignment(self): + c1 = Circle(12) + c2 = Circle(10) + c2 += c1 + c3 = c1.radius ** 2 + self.assertEqual(c2, 22) + self.assertEqual(c3, 144) + + if __name__ == '__main__': From 146149596a6056e06861c4eb2514c3e9f912accf Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 11:48:14 -0800 Subject: [PATCH 084/367] Circle updates --- students/jeff_shabani/session08/Circle.py | 24 +++++++++++++++++-- .../jeff_shabani/session08/test_circle.py | 2 -- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 378cbbf2..95562010 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -59,6 +59,22 @@ def __str__(self): return f'Circle with radius of {self.radius}' +class Sphere(Circle): + + def volume(self): + return (4/3)*math.pi*(self.radius**3) + + def area(self): + return 4 * math.pi * (self.radius**2) + + def __repr__(self): + return f'Sphere with radius of {self.radius} and volume of {self.volume()}' + + def __str__(self): + return f'Sphere with radius of {self.radius} and volume of {self.volume()}. Surface area is {self.area()}' + + + if __name__ == '__main__': c1 = Circle(1) @@ -66,6 +82,10 @@ def __str__(self): c3 = Circle(3) c4 = Circle(4) c5 = Circle(2) + s=Sphere(5) + sfd = Sphere.from_diameter(3) + print(sfd) + + + - for i in Circle.instances: - print(i) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 9a142b97..c3aec2d9 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -72,7 +72,5 @@ def test_extended_assignment(self): self.assertEqual(c3, 144) - - if __name__ == '__main__': unittest.main() From 69868c2b99ed37dca364da13ce630d4870d5e281 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 12:04:28 -0800 Subject: [PATCH 085/367] Circle update --- students/jeff_shabani/session08/Circle.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 95562010..284d3526 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -68,10 +68,10 @@ def area(self): return 4 * math.pi * (self.radius**2) def __repr__(self): - return f'Sphere with radius of {self.radius} and volume of {self.volume()}' + return f'Sphere with radius of {self.radius} volume of {self.volume()} & surface area of {self.area()}' def __str__(self): - return f'Sphere with radius of {self.radius} and volume of {self.volume()}. Surface area is {self.area()}' + return f'Sphere with radius of {self.radius} volume of {self.volume()} & surface area of {self.area()}' @@ -82,9 +82,9 @@ def __str__(self): c3 = Circle(3) c4 = Circle(4) c5 = Circle(2) - s=Sphere(5) - sfd = Sphere.from_diameter(3) - print(sfd) + s=Sphere(10) + sfd = Sphere.from_diameter(4) + print(s) From 9cca0c360ff4bff6acedbcd057ce4ca48f476710 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 12:04:42 -0800 Subject: [PATCH 086/367] Update to html_render --- students/jeff_shabani/session08/test_circle.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index c3aec2d9..df995f61 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -71,6 +71,22 @@ def test_extended_assignment(self): self.assertEqual(c2, 22) self.assertEqual(c3, 144) + def test_sphere_volume(self): + s = Sphere(1) + self.assertEqual(s.volume(), 4.1887902047863905) + del s + + def test_sphere_get_from_diameter(self): + s = Sphere.from_diameter(4) + self.assertEqual(s.volume(), 33.510321638291124) + del s + + def test_spehere_printing(self): + s = Sphere(10) + self.assertEqual(repr(s),'Sphere with radius of 10 volume of 4188.790204786391 & surface area of 1256.6370614359173') + + + if __name__ == '__main__': unittest.main() From f83a2b24bc0c80b3f72fb22b5d4a03e30e8788b1 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Wed, 6 Mar 2019 13:33:41 -0800 Subject: [PATCH 087/367] Adding Session9 & extra files. Roman/Arabic numeral converter working --- .../extra/context/raising_an_assert.py | 13 + .../douglas_klos/extra/lambda/test_lambda.py | 50 ++++ .../douglas_klos/extra/numerals/numerals.py | 119 ++++++++ .../extra/numerals/test_numerals.py | 78 ++++++ .../douglas_klos/session9/examples/diamond.py | 87 ++++++ .../session9/examples/diamond_super.py | 84 ++++++ .../session9/examples/object_canvas.py | 173 ++++++++++++ .../session9/examples/super_test.py | 264 ++++++++++++++++++ .../examples/test_images/blue_background.png | Bin 0 -> 2089 bytes .../session9/examples/test_images/circle.png | Bin 0 -> 3797 bytes .../examples/test_images/polyline.png | Bin 0 -> 3208 bytes .../session9/examples/test_object_canvas.py | 77 +++++ 12 files changed, 945 insertions(+) create mode 100644 students/douglas_klos/extra/context/raising_an_assert.py create mode 100644 students/douglas_klos/extra/lambda/test_lambda.py create mode 100755 students/douglas_klos/extra/numerals/numerals.py create mode 100755 students/douglas_klos/extra/numerals/test_numerals.py create mode 100755 students/douglas_klos/session9/examples/diamond.py create mode 100755 students/douglas_klos/session9/examples/diamond_super.py create mode 100755 students/douglas_klos/session9/examples/object_canvas.py create mode 100755 students/douglas_klos/session9/examples/super_test.py create mode 100644 students/douglas_klos/session9/examples/test_images/blue_background.png create mode 100644 students/douglas_klos/session9/examples/test_images/circle.png create mode 100644 students/douglas_klos/session9/examples/test_images/polyline.png create mode 100755 students/douglas_klos/session9/examples/test_object_canvas.py diff --git a/students/douglas_klos/extra/context/raising_an_assert.py b/students/douglas_klos/extra/context/raising_an_assert.py new file mode 100644 index 00000000..0ea86ea5 --- /dev/null +++ b/students/douglas_klos/extra/context/raising_an_assert.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +""" +examples of forcing and an AssertionError +""" + + +def test_raise_assertion(): + raise AssertionError("this was done with a direct raise") + + +def test_trasditional_assert(): + assert False, "this was done with a forced assert" diff --git a/students/douglas_klos/extra/lambda/test_lambda.py b/students/douglas_klos/extra/lambda/test_lambda.py new file mode 100644 index 00000000..4992afd3 --- /dev/null +++ b/students/douglas_klos/extra/lambda/test_lambda.py @@ -0,0 +1,50 @@ +""" +Some simple tests for the "lambda and keyword magic" +function builder + +designed to run with py.test +""" + +from lambda_keyword import function_builder +# uncomment to test second version +# from lambda_keyword import function_builder2 as function_builder + + +def test_length(): + """ + the function should return a list of the length input + """ + assert len(function_builder(0)) == 0 + + assert len(function_builder(3)) == 3 + + assert len(function_builder(5)) == 5 + + +def test_increment(): + """ + the functions in the list should increment the input values + """ + func_list = function_builder(5) + + assert func_list[0](3) == 3 + + assert func_list[1](3) == 4 + + assert func_list[2](3) == 5 + + assert func_list[3](3) == 6 + + +def test_increment2(): + """ + the functions in the list should increment the input values + """ + + func_list = function_builder(10) + + assert func_list[0](12) == 12 + + assert func_list[1](10) == 11 + + assert func_list[9](3) == 12 diff --git a/students/douglas_klos/extra/numerals/numerals.py b/students/douglas_klos/extra/numerals/numerals.py new file mode 100755 index 00000000..6ddc344d --- /dev/null +++ b/students/douglas_klos/extra/numerals/numerals.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +#pylint: disable=R0912 + +""" Class to convert between Roman and Arabic numerals """ + +# Douglas Klos +# March 6th, 2019 +# Python 210, Session 8 +# numerals.py + + +class Numerals(): + """ + Class to convert between Roman and Arabic numerals + + Subtractive roman numerals with a standard upper limit of 4999 + """ + + ROMAN_NUMERAL_LIST = {'M': 1000, + 'D': 500, + 'C': 100, + 'L': 50, + 'X': 10, + 'V': 5, + 'I': 1} + + def __init__(self, value=0): + if isinstance(value, int): + if value > 4999: + raise ValueError + self._arabic = value + + if isinstance(value, str): + self._arabic = self.convert_to_arabic(value) + + def __str__(self): + return str(self.arabic) + + def convert_to_arabic(self, value): + """ Given an input Roman Numeral, conert to arabic and set self._arabic """ + return_arabic = 0 + + for i in range(len(value)-1): + if self.ROMAN_NUMERAL_LIST[value[i]] < self.ROMAN_NUMERAL_LIST[value[i + 1]]: + return_arabic -= self.ROMAN_NUMERAL_LIST[value[i]] + else: + return_arabic += self.ROMAN_NUMERAL_LIST[value[i]] + self.arabic = return_arabic + self.ROMAN_NUMERAL_LIST[value[-1]] + if self.arabic < 5000: + return self.arabic + raise ValueError + + @property + def arabic(self): + """ Returns the roman numerals """ + return self._arabic + + @arabic.setter + def arabic(self, value): + self._arabic = value + + @property + def roman(self): + """ Returns the roman numeral for self._arabic """ + number = self._arabic + roman_numeral = '' + while number >= 1000: + roman_numeral += 'M' + number -= 1000 + + while number >= 900: + roman_numeral += 'CM' + number -= 900 + + while number >= 500: + roman_numeral += 'D' + number -= 500 + + while number >= 400: + roman_numeral += 'CD' + number -= 400 + + while number >= 100: + roman_numeral += 'C' + number -= 100 + + while number >= 90: + roman_numeral += 'XC' + number -= 90 + + while number >= 50: + roman_numeral += 'L' + number -= 50 + + while number >= 40: + roman_numeral += 'XL' + number -= 40 + + while number >= 10: + roman_numeral += 'X' + number -= 10 + + while number >= 9: + roman_numeral += 'IX' + number -= 10 + + while number >= 5: + roman_numeral += 'V' + number -= 5 + + while number >= 4: + roman_numeral += 'IV' + number -= 4 + + while number >= 1: + roman_numeral += 'I' + number -= 1 + + return roman_numeral diff --git a/students/douglas_klos/extra/numerals/test_numerals.py b/students/douglas_klos/extra/numerals/test_numerals.py new file mode 100755 index 00000000..dbdb6941 --- /dev/null +++ b/students/douglas_klos/extra/numerals/test_numerals.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +#pylint: disable=C0103,W0612 + +""" Test cases for numerals.py """ + +# Douglas Klos +# March 6th, 2019 +# Python 210, Session 8 +# numerals.py + + +import pytest +from numerals import Numerals + + +def test_numerals_arabic_init(): + """ Tests that Numerals class can be initialized with arabic numbers """ + n0 = Numerals(4999) + n1 = Numerals(1999) + n2 = Numerals(1949) + n3 = Numerals(444) + n4 = Numerals(14) + n5 = Numerals(79) + n6 = Numerals(225) + n7 = Numerals(845) + n8 = Numerals(2022) + + with pytest.raises(ValueError): + n9 = Numerals(5000) + + +def test_numerals_roman_init(): + """ Tests that Numerals class can be initialized with roman numerals """ + n0 = Numerals('MMMMCMXCIX') # 4999 + n1 = Numerals('MCMXCIX') # 1999 + n2 = Numerals('MCMXLIX') # 1949 + n3 = Numerals('CDXLIV') # 444 + n4 = Numerals('XIV') # 14 + n5 = Numerals('LXXIX') # 79 + n6 = Numerals('CCXXV') # 225 + n7 = Numerals('DCCCXLV') # 845 + n8 = Numerals('MMXXII') # 2022 + + with pytest.raises(ValueError): + n9 = Numerals('MMMMM') + + assert n0.arabic == 4999 + assert n1.arabic == 1999 + assert n2.arabic == 1949 + assert n3.arabic == 444 + assert n4.arabic == 14 + assert n5.arabic == 79 + assert n6.arabic == 225 + assert n7.arabic == 845 + assert n8.arabic == 2022 + + +def test_convert_to_roman(): + """ Tests that converting arabic to roman numerals functions correctly """ + n0 = Numerals(4999) + n1 = Numerals(1999) + n2 = Numerals(1949) + n3 = Numerals(444) + n4 = Numerals(14) + n5 = Numerals(79) + n6 = Numerals(225) + n7 = Numerals(845) + n8 = Numerals(2022) + + assert n0.roman == 'MMMMCMXCIX' + assert n1.roman == 'MCMXCIX' + assert n2.roman == 'MCMXLIX' + assert n3.roman == 'CDXLIV' + assert n4.roman == 'XIV' + assert n5.roman == 'LXXIX' + assert n6.roman == 'CCXXV' + assert n7.roman == 'DCCCXLV' + assert n8.roman == 'MMXXII' diff --git a/students/douglas_klos/session9/examples/diamond.py b/students/douglas_klos/session9/examples/diamond.py new file mode 100755 index 00000000..b994c3ad --- /dev/null +++ b/students/douglas_klos/session9/examples/diamond.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +""" +example of the classic "diamond problem" + +In this case, class A is at the root of the class hierarchy + +B and C both inherit from A + +D inherits from B and C + +ASCII art that shows this: + + ----- + | A | + ----- + / \ + / \ +----- ----- +| B | | C | +----- ----- + \ / + \ / + ----- + | D | + ----- + +So what's the problem? + +If you call a method on D -- it calls B and C's method -- and each +of them call A's method. So A's method gets called twice! + +The reason this is a tricky is that when you write the D class, you may not +know that B and C both inherit from A. And you may indeed *need* to call both +B and C's method. + +""" + + +class A(object): + def do_your_stuff(self): + print("doing A's stuff") + + +class Default(A): + def do_your_stuff(self): + print('doing Default stuff') + + +class B(A): + def do_your_stuff(self): + A.do_your_stuff(self) + print("doing B's stuff") + + +class C(A): + def do_your_stuff(self): + A.do_your_stuff(self) + print("doing C's stuff") + + +class D(B, C): + def do_your_stuff(self): + B.do_your_stuff(self) + C.do_your_stuff(self) + print("doing D's stuff") + + +if __name__ == '__main__': + a = A() + print("\ncalling A's method") + a.do_your_stuff() + + default = Default() + print("\ncalling Default's method") + default.do_your_stuff() + + print("\ncalling B's method") + b = B() + b.do_your_stuff() + + print("\ncalling C's method") + c = C() + c.do_your_stuff() + + print("\ncalling D's method") + d = D() + d.do_your_stuff() diff --git a/students/douglas_klos/session9/examples/diamond_super.py b/students/douglas_klos/session9/examples/diamond_super.py new file mode 100755 index 00000000..ca5d929b --- /dev/null +++ b/students/douglas_klos/session9/examples/diamond_super.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +""" +Example of solving the classic "diamond problem" using super() + +In this case, class A is at the root of the class hierarchy + +B and C both inherit from A + +D inherits from B and C + +ASCII art that shows this: + + ----- + | A | + ----- + / \ + / \ +----- ----- +| B | | C | +----- ----- + \ / + \ / + ----- + | D | + ----- + +So what's the problem? + +If you call a method on D -- it calls B and C's method -- and each +of them call A's method. So A's method gets called twice! + +But using super() makes sure all the methods get called, but none of them twice. +""" + + +class A(object): + def do_your_stuff(self): + print("doing A's stuff") + + +class Default(A): + def do_your_stuff(self): + print('doing Default stuff') + + +class B(A): + def do_your_stuff(self): + super().do_your_stuff() + print("doing B's stuff") + + +class C(A): + def do_your_stuff(self): + super().do_your_stuff() + print("doing C's stuff") + + +class D(B, C): + def do_your_stuff(self): + super().do_your_stuff() + print("doing D's stuff") + + +if __name__ == '__main__': + a = A() + print("\ncalling A's method") + a.do_your_stuff() + + default = Default() + print("\ncalling Default's method") + default.do_your_stuff() + + print("\ncalling B's method") + b = B() + b.do_your_stuff() + + print("\ncalling C's method") + c = C() + c.do_your_stuff() + + print("\ncalling D's method") + d = D() + d.do_your_stuff() diff --git a/students/douglas_klos/session9/examples/object_canvas.py b/students/douglas_klos/session9/examples/object_canvas.py new file mode 100755 index 00000000..8c28631f --- /dev/null +++ b/students/douglas_klos/session9/examples/object_canvas.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python + +""" +object canvas: an example of multiple inheritance and mix-ins + +This is a simplified version of FloatCanvas -- an extension to the +wxPython desktop GUI library + +FloatCanvas is a system for handling zoomable and scalable graphics in +a object-persistant way. That is, graphic objects like circles and +rectangles and what not can be created ahead of time, and then the Canvas +can render them accoding to the current zoom level and pan position, etc. + +This lets the user think about their graphics object should look like, +and not have to worry about exactly how to draw them -- or their pixel +coordinates, or anything else. + +If you want to see all this in all its full complexity, the FloatCanvas +code in part of the wxPython project, and can be seen here: + +https://github.com/wxWidgets/Phoenix/tree/master/wx/lib/floatcanvas + +This code: object_canvas is a simplified version. It doesn't allow scaling +or zooming, and only renders in pixel coordinates. But it does allow +object-persistance, and is a nice demo of the use of mixins. + +This version requires the Python Imaging Library to do the rendering. + +You can get it by installing the "pillow" package from PyPi: + +python -m pip install pillow + +Its docs are here: + +https://pillow.readthedocs.io/en/4.3.x/index.html + +""" +from math import ceil + +from PIL import Image, ImageDraw + + +class ObjectCanvas(): + """ + An object-oriented canvas for drawing things + """ + + def __init__(self, + size=(500, 500), + background=(255, 255, 255, 0) + ): + self.size = size + self.draw_objects = [] + self.background = background + + def add_object(self, draw_object, position="top"): + #fixme: maybe overload the inplace addition operator? + """ + Add a new object to the canvas. + + :param: draw_object -- DrawObject to add + + :param position="top": Position to add the object. "top" puts + the object on top of teh other objects. + "bottom" puts them on the bottom of the stack. + A integer puts it in that place in the order + -- 0 is the bottom. + """ + if position == "top": + self.draw_objects.append(draw_object) + elif position == "bottom": + self.draw_objects.insert(0, draw_object) + else: + self.draw_objects.insert(position, draw_object) + + def render(self, filename): + """ + render the drawing to a file with the given name + """ + image = Image.new('RGBA', self.size, color=self.background) + drawer = ImageDraw.Draw(image) + + for do in self.draw_objects: + do.draw(drawer) + image.save(filename) + + +class DrawObject: + """ + base class for all draw objects + """ + + def __init__(self, *args, **kwargs): + print("in DrawObject __init__", kwargs) + # do nothing, but to make super happy + super().__init__(*args, **kwargs) + + +class LineObject: + """ + mixin for classes with a line + """ + + def __init__(self, + line_color='black', + line_width=1, + **kwargs, + ): + print("in LineObject __init__", kwargs) + super().__init__(**kwargs) + self.line_color = line_color + self.line_width = line_width + + +class FillObject: + """ + mixin for classes with a fill + """ + + def __init__(self, + fill_color=None, + **kwargs + ): + print("in FillObject __init__", kwargs) + self.fill_color = fill_color + + +class PolyLine(DrawObject, LineObject): + def __init__(self, + vertices, + **kwargs + ): + self.vertices = vertices + print("in PolyLine init", kwargs) + super().__init__(**kwargs) + + def draw(self, drawer): + """ + draw the object + + :param drawer: PIL.ImageDraw object to draw to + """ + drawer.line(self.vertices, fill=self.line_color, width=self.line_width) + + +class Circle(DrawObject, LineObject, FillObject): + def __init__(self, center, diameter, **kwargs): + self.center = center + self.diameter = diameter + super().__init__(**kwargs) + + def draw(self, drawer): + """ + Draw the object + :param drawer: PIL.ImageDraw object to draw to + """ + r = self.diameter // 2 + c = self.center + # PIL doesn't support different line widths for ellipses, + # so we fake it. + lw2 = self.line_width / 2 + bounds = ((c[0] - r, c[1] - r), (c[0] + r, c[1] + r)) + drawer.ellipse(bounds, fill=self.fill_color, outline=None) + for i in range(int(ceil(lw2)), int(-lw2), -1): + r = self.diameter // 2 + i + bounds = ((c[0] - r, c[1] - r), (c[0] + r, c[1] + r)) + drawer.ellipse(bounds, fill=None, outline=self.line_color) + + + + + + diff --git a/students/douglas_klos/session9/examples/super_test.py b/students/douglas_klos/session9/examples/super_test.py new file mode 100755 index 00000000..0a73e93f --- /dev/null +++ b/students/douglas_klos/session9/examples/super_test.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python3 + +""" +Some example code demonstrating some super() behaviour +""" + +# Define a multiple inheritance scheme: +class A(): + def __init__(self): + print("in A __init__") + print("self's class is:", self.__class__) + s = super().__init__() + + +class B(): + def __init__(self): + print("in B.__init__") + s = super().__init__() + + +class C(): + def __init__(self): + print("in C.__init__") + s = super().__init__() + + +class D(C, B, A): + def __init__(self): + print("self's class is:", self.__class__) + super().__init__() + +# print our D's method resoluton order +# Is it what you expect? +print("\nD's mro:") +print( D.__mro__) +# see what happens when you create a D object: +print("\ninitializing a D object:") +d = D() + + +# ## super's parameters +# To do its thing, super() needs to know two things: +# +# ``super(type, obj)`` +# +# It needs to know that type (class) that you want the super-classes of, +# AND it needs to know the actual object instance at the time it is called. +# +# python3 fills these in for you at run time, but in python2, you needed to +# specify them: +# +# ``` +# class A(object): +# def __init__(self): +# super(A, self).__init__() +# ``` +# +# But why do you need BOTH `A` and `self`? -- isn't `self` an instance of `A`? +# +# Not neccesarily -- if A's method is being called from a subclass, then +# `self` will be an instance of the subclass. `super()` requires that the object be an instance of the class (or a subclass). +# +# This distiction will come up later.... +# +# Again, py3 takes care of this for you, though you CAN still spell it out. + +# see what you get with super by itself: +s_c = super(C, d) +print("\n the super object of super(C, d) itself") +print(s_c) + + +# This works because `d` is a `D` object, which is a subclass of `C`. + +# create a C instance: +c = C() + +# and try to create a super with the missmatch +print("\n the super object of super(D, c)") +try: + super(D, c) +except TypeError as err: + print(err) +# But this gives a TypeError: `C` is NOT a subclass of `D` + +# it doesn't have to be an exact intance, jsust a subclass: + +print("\n the super object of super(A, d)") +s_a = super(A, d) +print(s_a) + + +print("\n the super object of super(B, d)") +s_b = super(B, d) +print(s_b) + +print("\nD inherits from both A and B, so that worked...") + +print("\nD's MRO:") +print(D.__mro__) + + +# An Example of why you want to use super() everywhere. + +# Classes without super() + +class A(): + def this(self): + print("in A.this") + +class B(): + def this(self): + print("in B.this") + +class C(A,B): + def this(self): + print("in C.this") + A.this(self) + B.this(self) + +print("\nRunning without super()") +print("Creating a C instance without super() -- and calling it's this method:") +c = C() +c.this() + +print("C's `this` explicitly called both A and B's methods -- so they all get called.") + +# Using super in just C: + +print("\n using super() in C, but not everywhere...") + +class A(): + def this(self): + print("in A.this") + +class B(A): + def this(self): + print("in B.this") + +class C(B): + def this(self): + print("in C.this") + super().this() + + +print("\n C's MRO") +print(C.__mro__) + +print("\ncreating a C instance and calling it's this() method:") +c = C() +c.this() + +print("**NOTE: `A.this` did NOT get called!") + +# **Note:** `A.this` did NOT get called! +# +# Even though it is in in the MRO. +# +# Python stopped when it found the method in B. + +# ### Using super everywhere: + +print("using super everywhere:") + +class Base(): + def this(self): + pass # just so there is a base that has the method + +class A(Base): + def this(self): + print("in A.this") + super().this() + +class B(Base): + def this(self): + print("in B.this") + super().this() +class C(A,B): + def this(self): + print("in C.this") + super().this() + + +print("\nnow create a C instance and call its this() method:") +c = C() +c.this() + +print("Now both A and B's methods get called -- probably what you want.") + +print("\nAnd the MRO of the base class") +print(Base.__mro__) + +# But if you don't want both called -- better to just be Explicit, rather than use super(): + +class Base(): + def this(self): + pass # just so there is a base that has the method + +class A(Base): + def this(self): + print("in A.this") + super().this() + +class B(Base): + def this(self): + print("in B.this") + super().this() + +class C(A,B): + def this(self): + print("in C.this") + A.this(self) + +print("\nIf you want total control of what methods get called --don't use super" + "and be explicit") + +c = C() +c.this() + + +print("**Whoa** -- A and B's method DID get called! -- why?") + +print("A's MRO:") +print(A.__mro__) + + +print("B is not there") + +print("\nBut if we print the class of each instance when this() is called") + +class Base(): + def this(self): + pass # just so there is a base that has the method + +class A(Base): + def this(self): + print("in A.this") + print("self's class in A's this method:", self.__class__) + super().this() + +class B(Base): + def this(self): + print("in B.this") + super().this() + +class C(A,B): + def this(self): + print("in C.this") + A.this(self) + + +print("and create a c instance and call this():") +c = C() +c.this() + +print("In A's this method -- self is a C object") + +print("C's MRO:") +print(C.__mro__) + +print("\nRemember, `super()` is dynamic -- what it calls is determined at run time.") +print("That's how it knows to call ``B``'s method too.") +print("Which is why we say that using `super()` is *part* of the interface of" + "the class.") diff --git a/students/douglas_klos/session9/examples/test_images/blue_background.png b/students/douglas_klos/session9/examples/test_images/blue_background.png new file mode 100644 index 0000000000000000000000000000000000000000..4ed988fb7dce99496b7910d38d4757c585da5fd7 GIT binary patch literal 2089 zcmeAS@N?(olHy`uVBq!ia0y~yVEh8Y9Be?5)7S2IF)*-y@N{tushIQj>PFrJ20RB0 z%>Vy?BX?18g+tr|-}7hQF)-{e%VTF?xG!nNz#=hx2uVnRfXL86 z=8y==prW+QVi;tq1xd;vAO-`93|St zC-W;e2Ss@;c>n+u9Z%SM0)UKQ=Yz^gR|cLuzXAa8Qb&7?cS7khhm(J+MJxTcItR|S z2~O`$`O|XyVc~cqo%p376%lAm z*~(OCdeZ#!ZlyzV7}B`eSU$Ghd*JgWpbMOQ8(z8ckIGoGU%Szztejx~Umr(ztls<* zFmq)Gj3o}@%HesA>;M(j)uL+9OBDg`;aMBCSh6(biIDf3SoU~of0Drxum>zj5frkH zTey?YQHbui0Ihmzjkg!dwjZ1v+F8i5M=$~?MCZY+pWpyTMUduEwK};luf#rpp%*!k z>UDuLDgy1w5z-xyE$O}D1S2eZvb|4@4RNlZrMLfMxBYQe5o+5-u;~m``f*7ndp)>`c6j8hwn(>Dk)S-|zbmc%2iN zcs+@ckR>C26T2qEZVkOvvfcNIY$p#)ip)0Pt=b~pi?UksyvaIqLJW<7b#ZcuP8R!cyU{HqJn;aIL4(M9#z0V zUOjwsobNs4qaYflS4*KlQix%BM$EOEr0h^cAdP`cBO$`wy+m3bkacG^AC^t9+fnjO z2?L$?>DrAQrMPHH`>PEi!ERJ7ct>s$Sn?gY+VH*3lr2BoQRhe5B4f!WP^Ka{h1XgW zB{*bqSc%2MDKaqeZB!Nk*`KKC0g?M`!56Q(rot<^7mY?}USmX_d_6iaKkASr3LjmS z>oZv3i*pEJL6OS|2XRgiIsFBC%OoYzau`4-E*V;h^vAsZ~!d%Vs=+&j@4XQXWRz1{RKiZ+ zgPGE6)_n+y&ONQSm-f;ApZbz+xs)PoNb#D?FpR*zc=DFX9SvotKeFgmOEg41G#m5W zdYzfq@7(r3d)U(#Yt`iYbtTpD$bu&dul$i)Z1bgZYv@;y8=Mo9ONtrtJJf`ef8p1peX8oA!C9cS$w;CuR_opJv$+@*E z!6xNiHB|vzt0Yzhe-4B_e7&kQvv>c_x#qL6XOGr`EKRRh?J-ss+9medZw)S)7ClL! zK?!w&08QVl!~uJR`4tnPcb6~UI(@UOO~dcoWXE>+ zEp*f&b0;(&CO(1678_f?s`nUDnK}cnRib?r2*4&}QCxQv`g^8;# z(tOIEMCRfeq%LF~$+f1~+?T6bQ_s2XSc&J#VCGrlJx!|bJY9C!dV|8u(|e_Cji)lN zDP&$K8cx|wjL43SpN;P6X;F_JStJo_Jrda7IwyJ8E*W$H+^Vdtz{cs z{GTp$Dq^aPbTcjwih;1d(Bq0d2k>k9W{-EGXs^d^dGhOaQvIP>x-^QD&uf{wqPI=O z9DWDUTDduHd-H-~04Yc~tKT&)ZL>+-4`@*j!cc;c+`NvJr?YTQ-JF|mc-!-_o_SU; zqWFRxHJz!pVxnPJ;!kRyP>l=u9!6_2Zu;JVHXNY1tnzyGo0n;b;@RM^hGU=m%P)B^ z1!-6!JKlXKe4FyvWuXDbHjOc`Ybi~$6 z>@(Lb8|zg)Cj&`s(f)Fs;d?Qt)Fna!q~Z=5(%}DipP>aD~9?-%|HNmG)ty1r@8* zm%QEw%`pkRoUDBAygp;M0sj8jNQ0#m+S3-uA5c1O?8SbX(Y>l_kd7mJ(V6O@7mA`6 z4bLP|+(;K`JnQ}AgbCcDDLoTa>dam|1sM^qBplBag*U9G9e|;deKQFPL6I|>#pj%; zSSU);R{u$WlVuRZ{9D%bA8_YotztIfdmuBqZzu8QWsDydA2sn*qFvX!u6-sst%sqW zNj{SdL}gg09|+pUQ<|7$ zaintY+`1drwZIk|-r8N}GVh*f4$qm1`DjR@GS_ofgkK+>NMm$ktd!&Fu_?hH^Z2Lp zR#YCkW5d;`_kO1b81c^YwkNaue%HZ|d9ADJl>{o0CGT+7&(KuPhwSEsMiRZ(K))(} zq9o$w_}7LL*WSA)Rqbj!$4V^f-UCMDMBywGN2@v3kyFccmLC{)Fio4ro#84|;D%Ze zQ^_B$S0|Kvd67r!Zk5J-893UjGi3O_$eCRr*Tu@1mOk$=rdTsjX9O?Qd*&_Pj&C8P z?0Xd@uZAiOZD`4kYmd^$P~`;elIe}NSXp0QRNA##p{MvMk)-*}h(+nIsqj+?%5DCY zXH2P0h3uJ&2%G)$GUg$<46K4~cvr#j@n>|NPKJfwulbe@T*qDarqeZILg+Ar&+0iJ zv*8O_Z9n73^kvryoM(ItiKW&F{fZ*=E%MdiA+t7w}ZQ? z;TIkkMQcPaq%*LroQ$>%YylYY{R6cG87g#V=1ux(*WZ5N{g|P@?Ogx=GXM9UaqH;9 Yqqp<_8I$)&`dkGZkGa|3wF{*D8yQ2X2mk;8 literal 0 HcmV?d00001 diff --git a/students/douglas_klos/session9/examples/test_images/polyline.png b/students/douglas_klos/session9/examples/test_images/polyline.png new file mode 100644 index 0000000000000000000000000000000000000000..238a7cadf258e1b2cb6eeba6df3feba1ed5de81c GIT binary patch literal 3208 zcmeH~TYS`H8iz9^keNc$OhyicsZ0;k0@k*%f+TpDuhRpCcG?9GpcdMAC@d<~gtaQ@ zG>V;}SYek#fN6;?T2Qy!{S6BXv^d%k*(I`BkL!ZAqNYKV*6pAaMD|U0@Aqo&_F^uc zdH(PFe)%$AewlD}pe#9QY7&NF$>sBl7h#w!VSVi5;F}X4_iezi3039A==R3Qcb^?< zz3vE8f-dx4xw`y(ePkb5Uh~SCO{X_@t<2hVY|M&Hs|N=MZ^CLHzPjrc3~OjpaUX`r zASP3ojYz}B*m;bgCCu(IG1{lwJh5lWQjYfYJh6xhR(;;r*Z1IGWBJX`K7C}V8+)_6 zr>AFC(e<6DZF5VsRg8pDuHnN(TF@Wwo`cB#GGWuuG_n)&Z^qZw$W-jRU%7@qa`2dNEexKMW26#kwf70_egLnr6u>XEmjPrN zI{-3;_JsiH#-{+d&|an6-VTpkOQd-eWe{qL!XwK7HYtNp^LA*Y9U!C(LQPR<ThGTf}(k#|e zLGiR$3hG!q0=uN9v-Oh@xuRIx0ct8OJ_xEM9!Vn7`p2*xNr-IRtSknEA2`0oHVId?U)0OgmTaS8ql!Ne z=G-}^uUw!8?0j{r()$Fc3}a|2BL6~*jc_2mA@1HxGbRbtCl0<~tKy#~Qx%zp-m2n@ zL)?C^8EX)z??7!){L^J>0w`FAKg1=xrtfiqy5ivVtxE3{nUXS%0;sA9aT`I20`(=R zElRIjrfviURh1!5gN6?X)UbnZ2rK?%nd+|4UZN1WEW@a7QSpv2_aUrira;YxgrfN2 zsJKDxQt{guac`C0)Dd@o>@j10fjUP^{dsKjAMO0m3rg>kMB2q-t*%n0e)1Y!d5C=E z;4Y>28zPMs;dpm(Z1V(}n&uLZr<+|f+2&jTMm(NrcBQh-6#!20xYz7*u+0wv(BknN zlMZNgDKhm|-2FqkNiWdq@@1+CAk(BvwYn;qLI7TqF4F2&%akqdrllnj1wXh;?R`J) zzUbHMej!k6v&=3JOCDvUB^wp|M?0TetTmMpX_L~8SfNafr^WspnR+M8H9V*K>jcW} zHLJHMc)gv!Cd-H|1r_3kl2CI|+}*fU^*aUX-gL7%sNi=w_=;@9H(sV(VNTzm_GSsx z{w%YgNx^^T;3t5Bwd0^#)LxH3B|t${kAs)8jhJ1g(!yN92GySh)@GOWeJ;SpQ&1!Ta7>LoLXNMXc3&z2JA9w$~ zNp(Sk8aw|7fUxQ+*P1@F^N#{-R$V1v96SrKLv_&sN+VKoLj2TT&USvUD5(Z42neC zV{v!?&8XuVmTY`MUHrU)cL(&DNV9c1rB_{I@Ep;$FYZ>8QT^_Ki~tIK|*jqOBJad1!zJRjH3` zR`3sV%$vOiwu+Xng)3TP=N}JqvAc=3)iC82`6T>Wy0XzgK1(jyu8K!KgKyW!tqM-i ziTA>sZyf4V6#OeXQ3)^!^=$%hCf*BizHHPN0$>vG2=L88eek3D%9Vg8OBab!vJLDq zou~$wj8d`yoQVQ}9Fzjvf0;?p05_o&kAc}Qor$}Hrz-XBQ1er|*}{m}txRHUn8TJk zE(zeCBG#n~R4h|IYG=v*RJ0r>4Y^Q$K(oy)(#OLMZ)FlML$HwOfpgiPi}Fh~TjP3l zGR*2;ptsN>)=4MEK;m^`-3=_MjzzoYYqk|7dX7`X?q(7WP#+WP3P6!)Iw-S5CqX^Q zB;Xkk{G8}1WXW0r4T73dqR#_W$|NXIeCtaPAPHo|^nFo?Bxc`I&D-Vpf zV8!be>^tDF;Gq@^&YpQT&%nO*@Fq0K6GkEH1`8fJBU@(1EDJh?QOM1(;QTggPV5Yt zEMgZQ_|$6iQ}llQ9XEFCJ$Vqo`mUcSv1IV_HfvDqzJ)}MX6rxn&(ZwSvsT`{c#ai( zck2Wz!F_FYZ&zk~OljV>I!>smqryf18R0TMl1srm#fLf8I8O|Lt}3|ABwMmj93U bq5o=K{)~AC5A{3^|1hxfl0b21QLX$h)3d4- literal 0 HcmV?d00001 diff --git a/students/douglas_klos/session9/examples/test_object_canvas.py b/students/douglas_klos/session9/examples/test_object_canvas.py new file mode 100755 index 00000000..f88a58c6 --- /dev/null +++ b/students/douglas_klos/session9/examples/test_object_canvas.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +""" +test code for the object_canvas + +Note: Testing image generation is hard. So for now, this mostly just + tests that the rendering function runs. + And during development, you can look at the resulting files. + + One could store "properly" rendered results for future tests to + check against. +""" + +# import os +import pathlib +import object_canvas as oc + +SAVE_ALL=True # save all the temp files? + + +def render_to_file(canvas, filename="test_image.png", save=False): + """ + utility to render a canvas to a file + + :param filename: name of file to render to it will be put in a test_images dir. + + :param remove=True: whether to remove the file after rendering. + """ + path = pathlib.Path("test_images") + path.mkdir(exist_ok=True) + path /= filename + canvas.render(str(path)) + assert path.is_file() + if not (SAVE_ALL or save): + path.unlink() + + +def test_init(): + canvas = oc.ObjectCanvas() + + assert canvas + +def test_backgound(): + canvas = oc.ObjectCanvas(background='blue') + render_to_file(canvas, "blue_background.png") + +def test_polyline(): + """ + can we draw a polyline? + """ + canvas = oc.ObjectCanvas() + points = ((10, 10), # this should be a triangle + (10, 400), + (400, 10), + (10, 10), + ) + + pl = oc.PolyLine(points) + canvas.add_object(pl) + render_to_file(canvas, "polyline.png") + + +def test_circle(): + canvas = oc.ObjectCanvas() + center = (100, 100) + diameter = 75 + for line_width in range(1, 5): + c = oc.Circle(center, + diameter, + line_color="red", + fill_color="blue", + line_width=line_width, + ) + canvas.add_object(c) + center = (center[0] + 50, center[0] + 50) + render_to_file(canvas, "circle.png") + From de7bc9fd7caac7191d3712fa757563a6d77dc0a0 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 14:27:38 -0800 Subject: [PATCH 088/367] Circle update --- students/jeff_shabani/session08/Circle.py | 33 +++++++++---------- .../jeff_shabani/session08/test_circle.py | 8 ++++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 284d3526..a8de1765 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -6,9 +6,19 @@ class Circle(object): instances = [] def __init__(self, radius): - self.radius = radius + self._radius = radius Circle.instances.append(self) + @property + def radius(self): + return self._radius + + @radius.setter + def radius(self, val): + if val < 0: + raise ValueError('Radius cannot be less than zero') + self._radius = val + @property def diameter(self): return self.radius * 2 @@ -62,10 +72,10 @@ def __str__(self): class Sphere(Circle): def volume(self): - return (4/3)*math.pi*(self.radius**3) + return (4 / 3) * math.pi * (self.radius ** 3) def area(self): - return 4 * math.pi * (self.radius**2) + return 4 * math.pi * (self.radius ** 2) def __repr__(self): return f'Sphere with radius of {self.radius} volume of {self.volume()} & surface area of {self.area()}' @@ -74,18 +84,7 @@ def __str__(self): return f'Sphere with radius of {self.radius} volume of {self.volume()} & surface area of {self.area()}' - if __name__ == '__main__': - - c1 = Circle(1) - c2 = Circle(5) - c3 = Circle(3) - c4 = Circle(4) - c5 = Circle(2) - s=Sphere(10) - sfd = Sphere.from_diameter(4) - print(s) - - - - + c1 = Circle(-11) + c1.radius = -1 + print(c1) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index df995f61..2a608ac1 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -70,6 +70,13 @@ def test_extended_assignment(self): c3 = c1.radius ** 2 self.assertEqual(c2, 22) self.assertEqual(c3, 144) + del c1, c2, c3 + + @unittest.expectedFailure + def test_negative_radius(self): + c1 = Circle(2) + c1.radius = -1 + self.assertEqual(c1, -1) def test_sphere_volume(self): s = Sphere(1) @@ -87,6 +94,5 @@ def test_spehere_printing(self): - if __name__ == '__main__': unittest.main() From e7865bc9085aceb7833c0e7bc9fdccd773eff31b Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Wed, 6 Mar 2019 14:29:46 -0800 Subject: [PATCH 089/367] Circle test update --- students/jeff_shabani/session08/test_circle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 2a608ac1..f9319795 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -72,6 +72,7 @@ def test_extended_assignment(self): self.assertEqual(c3, 144) del c1, c2, c3 + #test for negative radius @unittest.expectedFailure def test_negative_radius(self): c1 = Circle(2) From 05ae8033c15042f1bfed3e85d1c37e8e1e221041 Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Wed, 6 Mar 2019 15:41:17 -0800 Subject: [PATCH 090/367] Circle update --- students/jeff_shabani/session08/Circle.py | 18 ++++++------------ students/jeff_shabani/session08/test_circle.py | 4 ++-- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index a8de1765..5ba832e6 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -6,19 +6,13 @@ class Circle(object): instances = [] def __init__(self, radius): + if radius < 0: + raise ValueError('Radius cannot be less than zero') + else: + self.radius = radius self._radius = radius Circle.instances.append(self) - @property - def radius(self): - return self._radius - - @radius.setter - def radius(self, val): - if val < 0: - raise ValueError('Radius cannot be less than zero') - self._radius = val - @property def diameter(self): return self.radius * 2 @@ -85,6 +79,6 @@ def __str__(self): if __name__ == '__main__': - c1 = Circle(-11) - c1.radius = -1 + c1 = Circle(1) + # c1.radius = -1 print(c1) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index f9319795..7925fde2 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -75,9 +75,9 @@ def test_extended_assignment(self): #test for negative radius @unittest.expectedFailure def test_negative_radius(self): - c1 = Circle(2) - c1.radius = -1 + c1 = Circle(-1) self.assertEqual(c1, -1) + del c1 def test_sphere_volume(self): s = Sphere(1) From 179fe8aecce14ebd2a9c08d27452afaa65614c58 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Wed, 6 Mar 2019 16:44:40 -0800 Subject: [PATCH 091/367] rot13 function working --- .../douglas_klos/extra/numerals/numerals.py | 3 ++- students/douglas_klos/extra/rot13/rot13.py | 27 +++++++++++++++++++ .../douglas_klos/extra/rot13/test_rot13.py | 20 ++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100755 students/douglas_klos/extra/rot13/rot13.py create mode 100755 students/douglas_klos/extra/rot13/test_rot13.py diff --git a/students/douglas_klos/extra/numerals/numerals.py b/students/douglas_klos/extra/numerals/numerals.py index 6ddc344d..49b23912 100755 --- a/students/douglas_klos/extra/numerals/numerals.py +++ b/students/douglas_klos/extra/numerals/numerals.py @@ -45,7 +45,8 @@ def convert_to_arabic(self, value): return_arabic -= self.ROMAN_NUMERAL_LIST[value[i]] else: return_arabic += self.ROMAN_NUMERAL_LIST[value[i]] - self.arabic = return_arabic + self.ROMAN_NUMERAL_LIST[value[-1]] + + self.arabic = return_arabic + self.ROMAN_NUMERAL_LIST[value[-1]] if self.arabic < 5000: return self.arabic raise ValueError diff --git a/students/douglas_klos/extra/rot13/rot13.py b/students/douglas_klos/extra/rot13/rot13.py new file mode 100755 index 00000000..9cb11bb1 --- /dev/null +++ b/students/douglas_klos/extra/rot13/rot13.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +""" Class to convert rot13 'encrypt' """ + +# Douglas Klos +# March 6th, 2019 +# Python 210, Session 8 +# rot13.py + +# a - z == 97 - 122 +# A - Z == 65 - 90 +# We'll ignore other characters such as punctuation + + +def rot13(value): + """ Function to perform rot13 on input """ + + output = '' + for letter in value: + if ord(letter) >= 97 and ord(letter) <= 122: + output += chr(ord(letter) - 13) if ord(letter) >= 110 else chr(ord(letter) + 13) + elif ord(letter) >= 65 and ord(letter) <= 90: + output += chr(ord(letter) - 13) if ord(letter) >= 78 else chr(ord(letter) + 13) + else: + output += letter + print(output) + return output diff --git a/students/douglas_klos/extra/rot13/test_rot13.py b/students/douglas_klos/extra/rot13/test_rot13.py new file mode 100755 index 00000000..d0e9fbde --- /dev/null +++ b/students/douglas_klos/extra/rot13/test_rot13.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +""" Test cases for rot13.py """ + +# Douglas Klos +# March 6th, 2019 +# Python 210, Session 8 +# test_rot13.py + +import rot13 + + +def test_rot13(): + """ Basic test cases for rot13 """ + assert rot13.rot13('abcdefghijklm') == 'nopqrstuvwxyz' + assert rot13.rot13('nopqrstuvwxyz') == 'abcdefghijklm' + assert rot13.rot13('abcdefghijklm'.upper()) == 'nopqrstuvwxyz'.upper() + assert rot13.rot13('nopqrstuvwxyz'.upper()) == 'abcdefghijklm'.upper() + + assert rot13.rot13(rot13.rot13('This is a test')) == 'This is a test' From 72460c2f4e1fb36f115bc44ab53ad8e78462ac4e Mon Sep 17 00:00:00 2001 From: UncleanlyCleric Date: Wed, 6 Mar 2019 19:26:51 -0800 Subject: [PATCH 092/367] Small problem with rmul --- students/jesse_miller/session08/circle.py | 29 +++++- .../jesse_miller/session08/test_circle.py | 88 ++++++++++++++++--- 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index c01ae371..787e2df1 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -8,11 +8,12 @@ Imported the math module for calculation ''' -class Circle(object): +class Circle(): ''' Defining the circle class ''' def __init__(self, radius): + self.radius = radius @property @@ -35,3 +36,29 @@ def area(self): Defining area, I'm a tad more confident in this one ''' return pi * self.radius**2 + + @classmethod + def from_diameter(cls, value): + ''' + Attempting to do step five from the assignment, create a circle from + entering the diameter, not the radius. + ''' + return cls(value/2) + + def __str__(self): + return f'{self.__class__.__name__} with radius: {self.radius}' + + def __repr__(self): + return f'{self.__class__.__name__}({self.radius})' + + def __add__(self, other): + return Circle(self.radius + other.radius) + + def __rmul__(self, value): + return Circle(self.radius * value) + + def __mul__(self, value): + try: + return Circle(self.radius * value) + except TypeError: + rmul(self, value) diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index a2a955ff..79e680a2 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -1,35 +1,56 @@ -# Tests for Circle Class - -import pytest +''' +Tests for Circle program +You'll note that this is chock full of pylint disables. This is because I use +Atom's pylinter plugin, and while it's fantastic at helping me with problems +while I'm going, unit testing is going to have linting problems, so I disable +them as they come up, that way I know when I'm doing something bad. +''' from math import pi +import pytest from circle import Circle -# Step 1 -def test_empty(): +def test_empty_circle(): + ''' + Test 1: No values insertered. + ''' + #pylint: disable=E1120 with pytest.raises(TypeError): Circle() -def test_new(): +def test_new_circle(): + ''' + Test 2: Testing a value for the circle. + ''' Circle(1) def test_radius(): + ''' + Test 3: Testing inserting a radius. + ''' + #pylint: disable=C0103 c = Circle(2) assert c.radius == 2 -# Step 2 def test_diameter(): + ''' + Test 4: Testing diameter calculation. + ''' + #pylint: disable=C0103 c = Circle(3) assert c.diameter == 6 -# Step 3 -def test_diameter_set(): +def test_set_diameter(): + ''' + Test 5: Testing manually setting a diameter. + ''' + #pylint: disable=C0103 c = Circle(4) c.diameter = 5 @@ -37,15 +58,60 @@ def test_diameter_set(): assert c.radius == 2.5 -# Step 4 def test_area(): + ''' + Test 6: Testing area calculation. + ''' + #pylint: disable=C0103 c = Circle(6) assert c.area == pi * 36 -def test_area_set(): +def test_set_area(): + ''' + Test 7: Testing AttributeError + ''' + #pylint: disable=C0103 c = Circle(7) with pytest.raises(AttributeError): c.area = 10 + + +def test_from_diameter(): + ''' + Test 8: Testing calculating circle from diameter insertion + ''' + #pylint: disable=C0103 + c = Circle.from_diameter(8) + + assert c.diameter == 8 + assert c.radius == 4 + + +def test_string(): + ''' + Test 9: String insertion and formatted print + ''' + #pylint: disable=C0103 + c = Circle(9) + assert str(c) == "Circle with radius: 9" + +def test_string_representation(): + ''' + Test 10: Testing string representation, turns out it's a lot like string + ''' + #pylint: disable=C0103 + c = Circle(12) + assert repr(c) == "Circle(12)" + +def test_add_circles(): + ''' + Test 11: Testing adding circles + ''' + #pylint: disable=C0103 + c1 = Circle(4) + c2 = Circle(6) + + assert c1 + c2 == Circle(10) From 16278c55bbc3d37edc87afc00c0c77714ef18a50 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Wed, 6 Mar 2019 20:52:45 -0800 Subject: [PATCH 093/367] fun with lambda --- .../extra/lambda/lambda_keyword.py | 42 +++++++++++++++++++ .../douglas_klos/extra/lambda/test_lambda.py | 17 ++++---- 2 files changed, 49 insertions(+), 10 deletions(-) create mode 100755 students/douglas_klos/extra/lambda/lambda_keyword.py mode change 100644 => 100755 students/douglas_klos/extra/lambda/test_lambda.py diff --git a/students/douglas_klos/extra/lambda/lambda_keyword.py b/students/douglas_klos/extra/lambda/lambda_keyword.py new file mode 100755 index 00000000..1b20ee6b --- /dev/null +++ b/students/douglas_klos/extra/lambda/lambda_keyword.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +# Douglas Klos +# March 6th, 2019 +# Python 210, Session 8 +# lambda_keyword.py + + +def function_builder(value): + + # This is the working line with list comprehension + # return [(lambda y: (lambda x: y + x))(i) for i in (range(value))] + + # This is the working multiline + return_list = [] + for i in range(value): + return_list.append((lambda y: (lambda x: y + x))(i)) + return return_list + + # These were the failures that look like they should work + + # return_list = [] + # for i in range(value): + # print(i) + # return_list.append(lambda x: x + i) + # return return_list + + # return [lambda x: x+i for i in range(value)] + + +def main(): + + func_list = function_builder(10) + + print(func_list[0](0)) + print(func_list[1](0)) + print(func_list[2](0)) + print(func_list[3](0)) + print(func_list[4](0)) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/students/douglas_klos/extra/lambda/test_lambda.py b/students/douglas_klos/extra/lambda/test_lambda.py old mode 100644 new mode 100755 index 4992afd3..0d4789e1 --- a/students/douglas_klos/extra/lambda/test_lambda.py +++ b/students/douglas_klos/extra/lambda/test_lambda.py @@ -1,3 +1,10 @@ +#!/usr/bin/env python3 + +# Douglas Klos +# March 6th, 2019 +# Python 210, Session 8 +# lambda_keyword.py + """ Some simple tests for the "lambda and keyword magic" function builder @@ -6,8 +13,6 @@ """ from lambda_keyword import function_builder -# uncomment to test second version -# from lambda_keyword import function_builder2 as function_builder def test_length(): @@ -15,9 +20,7 @@ def test_length(): the function should return a list of the length input """ assert len(function_builder(0)) == 0 - assert len(function_builder(3)) == 3 - assert len(function_builder(5)) == 5 @@ -28,11 +31,8 @@ def test_increment(): func_list = function_builder(5) assert func_list[0](3) == 3 - assert func_list[1](3) == 4 - assert func_list[2](3) == 5 - assert func_list[3](3) == 6 @@ -40,11 +40,8 @@ def test_increment2(): """ the functions in the list should increment the input values """ - func_list = function_builder(10) assert func_list[0](12) == 12 - assert func_list[1](10) == 11 - assert func_list[9](3) == 12 From 53931d0882dc17131dad8f66b2a2dce6ab2bea91 Mon Sep 17 00:00:00 2001 From: Luis Conejo-Alpizar Date: Wed, 6 Mar 2019 23:36:50 -0800 Subject: [PATCH 094/367] Revert "Revert "lesson 07"" --- students/marsha_w/lesson_07/html_render.py | 197 ++++++++ .../marsha_w/lesson_07/run_html_render.py | 231 ++++++++++ students/marsha_w/lesson_07/sample_html.html | 27 ++ .../marsha_w/lesson_07/test_html_render.py | 422 ++++++++++++++++++ 4 files changed, 877 insertions(+) create mode 100644 students/marsha_w/lesson_07/html_render.py create mode 100644 students/marsha_w/lesson_07/run_html_render.py create mode 100644 students/marsha_w/lesson_07/sample_html.html create mode 100644 students/marsha_w/lesson_07/test_html_render.py diff --git a/students/marsha_w/lesson_07/html_render.py b/students/marsha_w/lesson_07/html_render.py new file mode 100644 index 00000000..57fab671 --- /dev/null +++ b/students/marsha_w/lesson_07/html_render.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 + +""" +A class-based system for rendering html. +""" + + +# This is the framework for the base class +class Element(object): + + tag = 'html' # this is a class object + + indent = ' ' + + def __init__(self, content=None, **kwargs): + self.contents = [content] # contents to an ordered list + self.attributes = kwargs + + def append(self, new_content): + '''append new content to the content list''' + self.contents.append(new_content) + + def _open_tag(self): + return '<{}'.format(self.tag) + + def _close_tag(self): + return '\n'.format(self.tag) + + def render(self, out_file, cur_ind=""): + '''loop through the list of contents''' + open_tag = [self._open_tag()] + for keys, values in self.attributes.items(): + element_attributes = ' ' + keys + '=' + '"' + str(values) + '"' # this is clunky + open_tag.append(element_attributes) + open_tag.append('>\n') + + out_file.write(cur_ind) + out_file.write("".join(open_tag)) + + for content in self.contents: + if content is not None: + try: + content.render(out_file) + except AttributeError: + out_file.write(content) + out_file.write('\n') + out_file.write(cur_ind) + out_file.write(self._close_tag()) + + +class Html(Element): + tag = 'html' + + def render(self, out_file, cur_ind=""): + + '''loop through the list of contents''' + + out_file.write('\n') + open_tag = [self._open_tag()] + + for keys, values in self.attributes.items(): + element_attributes = ' ' + keys + '=' + '"' + str(values) + '"' # this is clunky + open_tag.append(element_attributes) + open_tag.append('>\n') + + out_file.write(cur_ind) + out_file.write("".join(open_tag)) + + for content in self.contents: + if content is not None: + try: + content.render(out_file) + except AttributeError: + out_file.write(content) + out_file.write('\n') + + out_file.write(cur_ind) + out_file.write(self._close_tag()) + + +class Body(Element): + tag = 'body' + + + +class P(Element): + tag = 'p' + + +class Head(Element): + tag = 'head' + + +class OneLineTag(Element): + def render(self, out_file, cur_ind=""): + open_tag = [self._open_tag()] + open_tag.append('> ') + + out_file.write(cur_ind) + out_file.write("".join(open_tag)) + out_file.write(self.contents[0]) + out_file.write(cur_ind) + out_file.write(self._close_tag()) + + def append(self, content): + raise NotImplementedError + + +class Title(OneLineTag): + tag = 'title' + + +class H2(OneLineTag): + tag = 'h2' + + +class SelfClosingTag(Element): + + def __init__(self, content=None, **kwargs): + if content is not None: + raise TypeError("SelfClosingTag can not contain any content") + super().__init__(content=content, **kwargs) + + def append(self, *args): + raise TypeError("You can not add content to a SelfClosingTag") + + +class Hr(SelfClosingTag): + tag = 'hr' + + def render(self, out_file, cur_ind=""): + tag = [self._open_tag()] + for keys, values in self.attributes.items(): + element_attributes = ' ' + keys + '=' + '"' + str(values) + '"' # this is clunky + tag.append(element_attributes) + tag.append(" />\n") + + out_file.write(cur_ind) + out_file.write("".join(tag)) + + +class Br(Hr): + tag = 'br' + +class Meta(Hr): + tag = 'meta' + + +class A(OneLineTag): + tag = 'a' + + def __init__(self, link, content=None, **kwargs): + kwargs['href'] = link + super().__init__(content, **kwargs) + + def render(self, out_file, cur_ind=""): + open_tag = [self._open_tag()] + for keys, values in self.attributes.items(): + element_attributes = ' ' + keys + '=' + '"' + str(values) + '"' # this is clunky + open_tag.append(element_attributes) + open_tag.append('>') + + out_file.write(cur_ind) + out_file.write("".join(open_tag)) + out_file.write(self.contents[0]) + + out_file.write(cur_ind) + out_file.write(self._close_tag()) + + +class Li(Element): + tag = 'li' + + +class Ul(Element): + tag = 'ul' + + +class H(OneLineTag): + + tag = 'h' + + def __init__(self, level, content=None, **kwargs): + self.tag = '{}{}'.format('h', str(level)) + super().__init__(content, **kwargs) + + + + + + + + + + + + diff --git a/students/marsha_w/lesson_07/run_html_render.py b/students/marsha_w/lesson_07/run_html_render.py new file mode 100644 index 00000000..dec60d88 --- /dev/null +++ b/students/marsha_w/lesson_07/run_html_render.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 + +""" +a simple script can run and test your html rendering classes. + +Uncomment the steps as you add to your rendering. + +""" + +from io import StringIO + +# importing the html_rendering code with a short name for easy typing. +import html_render as hr + + +# writing the file out: +def render_page(page, filename, indent=None): + """ + render the tree of elements + + This uses StringIO to render to memory, then dump to console and + write to file -- very handy! + """ + + f = StringIO() + if indent is None: + page.render(f) + else: + page.render(f, indent) + + print(f.getvalue()) + with open(filename, 'w') as outfile: + outfile.write(f.getvalue()) + + +# Step 1 +######### + +page = hr.Element() + +page.append("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text") + +page.append("And here is another piece of text -- you should be able to add any number") + +render_page(page, "test_html_output1.html") + +# The rest of the steps have been commented out. +# Uncomment them as you move along with the assignment. + +## Step 2 +########## + +page = hr.Html() + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text")) + +body.append(hr.P("And here is another piece of text -- you should be able to add any number")) + +page.append(body) + +render_page(page, "test_html_output2.html") + +# # Step 3 +# ########## + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text")) +body.append(hr.P("And here is another piece of text -- you should be able to add any number")) + +page.append(body) + +render_page(page, "test_html_output3.html") + +# # Step 4 +# ########## + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +page.append(body) + +render_page(page, "test_html_output4.html") + +# # Step 5 +# ######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +page.append(body) + +render_page(page, "test_html_output5.html") + +# # Step 6 +# ######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +body.append("And this is a ") +body.append( hr.A("http://google.com/", "link") ) +body.append("to google") + +page.append(body) + +render_page(page, "test_html_output6.html") + +# # Step 7 +# ######### + +page = hr.Html() + +head = hr.Head() +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append( hr.H(2, "PythonClass - Class 6 example") ) + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +list = hr.Ul(id="TheList", style="line-height:200%") + +list.append( hr.Li("The first item in a list") ) +list.append( hr.Li("This is the second item", style="color: red") ) + +item = hr.Li() +item.append("And this is a ") +item.append( hr.A("http://google.com/", "link")) +item.append("to google") + +list.append(item) + +body.append(list) + +page.append(body) + +render_page(page, "test_html_output7.html") + +# # Step 8 and 9 +# ############## + +page = hr.Html() + + +head = hr.Head() +head.append(hr.Meta(charset="UTF-8")) +head.append(hr.Title("PythonClass = Revision 1087:")) + +page.append(head) + +body = hr.Body() + +body.append( hr.H(2, "PythonClass - Example") ) + +body.append(hr.P("Here is a paragraph of text -- there could be more of them, " + "but this is enough to show that we can do some text", + style="text-align: center; font-style: oblique;")) + +body.append(hr.Hr()) + +list = hr.Ul(id="TheList", style="line-height:200%") + +list.append( hr.Li("The first item in a list") ) +list.append( hr.Li("This is the second item", style="color: red") ) + +item = hr.Li() +item.append("And this is a ") +item.append( hr.A("http://google.com/", "link") ) +item.append("to google") + +list.append(item) + +body.append(list) + +page.append(body) + +render_page(page, "test_html_output8.html") diff --git a/students/marsha_w/lesson_07/sample_html.html b/students/marsha_w/lesson_07/sample_html.html new file mode 100644 index 00000000..9c2e675d --- /dev/null +++ b/students/marsha_w/lesson_07/sample_html.html @@ -0,0 +1,27 @@ + + + + + Python Class Sample page + + +

      Python Class - Html rendering example

      +

      + Here is a paragraph of text -- there could be more of them, but this is enough to show that we can do some text +

      +
      +
        +
      • + The first item in a list +
      • +
      • + This is the second item +
      • +
      • + And this is a + link + to google +
      • +
      + + \ No newline at end of file diff --git a/students/marsha_w/lesson_07/test_html_render.py b/students/marsha_w/lesson_07/test_html_render.py new file mode 100644 index 00000000..790c25f2 --- /dev/null +++ b/students/marsha_w/lesson_07/test_html_render.py @@ -0,0 +1,422 @@ +""" +test code for html_render.py + +This is just a start -- you will need more tests! +""" + +import io +import pytest + +# import * is often bad form, but makes it easier to test everything in a module. +from html_render import * + + +# utility function for testing render methods +# needs to be used in multiple tests, so we write it once here. +def render_result(element, ind=""): + """ + calls the element's render method, and returns what got rendered as a + string + """ + # the StringIO object is a "file-like" object -- something that + # provides the methods of a file, but keeps everything in memory + # so it can be used to test code that writes to a file, without + # having to actually write to disk. + outfile = io.StringIO() + # this so the tests will work before we tackle indentation + if ind: + element.render(outfile, ind) + else: + element.render(outfile) + return outfile.getvalue() + +######## +# Step 1 +######## + +def test_init(): + """ + This only tests that it can be initialized with and without + some content -- but it's a start + """ + e = Element() + + e = Element("this is some text") + + +def test_append(): + """ + This tests that you can append text + + It doesn't test if it works -- + that will be covered by the render test later + """ + e = Element("this is some text") + e.append("some more text") + + +def test_render_element(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + + It is not testing whether indentation or line feeds are correct. + """ + e = Element("this is some text") + e.append("and this is some more text") + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") + + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + + # make sure only one html is printed + assert file_contents.count("") == 1 + assert file_contents.count("") == 1 + + + + + +# Uncomment this one after you get the one above to pass +# Does it pass right away? + +def test_render_element2(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + + It is not testing whether indentation or line feeds are correct. + """ + e = Element() + e.append("this is some text") + e.append("and this is some more text") + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + +# # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") + +# # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + + +# ######## +# # Step 2 +# ######## + +# tests for the new tags +def test_html(): + e = Html("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + print(file_contents) + + assert ("") in file_contents + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + assert file_contents.endswith("") + + + +def test_body(): + e = Body("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("") + assert file_contents.endswith("") + + + +def test_p(): + e = P("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("

      ") + assert file_contents.endswith("

      ") + + +def test_sub_element(): + """ + tests that you can add another element and still render properly + """ + page = Html() + page.append("some plain text.") + page.append(P("A simple paragraph of text")) + page.append("Some more plain text.") + + file_contents = render_result(page) + print(file_contents) # so we can see it if the test fails + + # note: The previous tests should make sure that the tags are getting + # properly rendered, so we don't need to test that here. + assert "some plain text" in file_contents + assert "A simple paragraph of text" in file_contents + assert "Some more plain text." in file_contents + assert "some plain text" in file_contents + # but make sure the embedded element's tags get rendered! + assert "

      " in file_contents + assert "

      " in file_contents + + +######## +# Step 3 +######## + + +def test_head(): + e = Head("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("") + assert file_contents.endswith("") + + +def test_one_line_tag(): + e = OneLineTag("this is some text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + with pytest.raises(NotImplementedError): + e.append("some more content") + + assert file_contents.startswith("") + assert file_contents.endswith("") + + assert '\n' not in file_contents + + +def test_title(): + e = Title("Python Class Sample page") + + file_contents = render_result(e).strip() + + assert("Python Class Sample page") in file_contents + + assert file_contents.startswith("") + assert file_contents.endswith("") + +def test_h2(): + e = H2("Python Class Sample page") + + file_contents = render_result(e).strip() + + assert("Python Class Sample page") in file_contents + + assert file_contents.startswith("

      ") + assert file_contents.endswith("

      ") + + +######### +#Step 4 +########## + + +def test_attributes(): + e = P("A paragraph of text", style="text-align: center", id="intro") + + file_contents = render_result(e).strip() + + assert "A paragraph of text" in file_contents + assert 'style="text-align: center"' in file_contents + assert 'id="intro"' in file_contents + assert file_contents.endswith("

      ") + assert file_contents.startswith("

      ")].count(" ") == 3 + assert file_contents.count("\n") == 2 + +######### +#Step 5 +########## + + +def test_hr(): + """a simple horizontal rule with no attributes""" + hr = Hr() + file_contents = render_result(hr) + + assert file_contents == '


      \n' + + +def test_hr_attr(): + """a horizontal rule with an attribute""" + hr = Hr(width=400) + file_contents = render_result(hr) + print(file_contents) + assert file_contents == '
      \n' + + +def test_br(): + br = Br() + file_contents = render_result(br) + print(file_contents) + assert file_contents == "
      \n" + + +def test_content_in_br(): + with pytest.raises(TypeError): + br = Br("some content") + + +def test_append_content_in_br(): + with pytest.raises(TypeError): + br = Br() + br.append("some content") + +######### +#Step 6 +########## + + +def test_a(): + a = A("http://google.com/", "link to google") + + file_contents = render_result(a).strip() + print(file_contents) + + assert "http://google.com/" in file_contents + + assert file_contents.startswith("") + + assert '\n' not in file_contents + +######### +#Step 7 +########## + +def test_li(): + e = Li("This is the second item", style="color: red") + + file_contents = render_result(e).strip() + print(file_contents) + + assert "This is the second item" in file_contents + assert 'style="color: red"' in file_contents + assert file_contents.endswith("") + assert file_contents.startswith("
    • ") + assert file_contents.startswith("
        ") + assert file_contents.startswith("

        ") + + +##################### +# indentation testing +# Uncomment for Step 9 -- adding indentation +##################### + + +def test_indent(): + """ + Tests that the indentation gets passed through to the renderer + """ + html = Html("some content") + file_contents = render_result(html, ind=" ").rstrip() #remove the end newline + + print(file_contents) + lines = file_contents.split("\n") + assert lines[1].startswith(" <") + print(repr(lines[-1])) + assert lines[-1].startswith(" <") + + +def test_indent_contents(): + """ + The contents in a element should be indented more than the tag + by the amount in the indent class attribute + """ + html = Element("some content") + file_contents = render_result(html, ind="") + + print(file_contents) + lines = file_contents.split("\n") + assert lines[1].startswith(Element.indent) + + +def test_multiple_indent(): + """ + make sure multiple levels get indented fully + """ + body = Body() + body.append(P("some text")) + html = Html(body) + + file_contents = render_result(html) + + print(file_contents) + lines = file_contents.split("\n") + for i in range(3): # this needed to be adapted to the tag + assert lines[i + 1].startswith(i * Element.indent + "<") + + assert lines[4].startswith(3 * Element.indent + "some") + + +def test_element_indent1(): + e = Element("this is some text") + + # This uses the render_results utility above + file_contents = render_result(e).strip() + + # making sure the content got in there. + assert("this is some text") in file_contents + + # break into lines to check indentation + lines = file_contents.split('\n') + # making sure the opening and closing tags are right. + assert lines[0] == "" + # this line should be indented by the amount specified + # by the class attribute: "indent" + assert lines[1].startswith(Element.indent + "thi") + assert lines[2] == "" + assert file_contents.endswith("") From d459f6bbdf292d4bd582f0578e627f59489dca8d Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 7 Mar 2019 06:01:13 -0800 Subject: [PATCH 095/367] circle class --- students/jeff_shabani/session08/Circle.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 5ba832e6..98dfa0d6 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,6 +1,12 @@ #!/usr/bin/env python3 import math +""" +Framework for a circular object. +Validation prevents user from entering a +negative radius value. +""" + class Circle(object): instances = [] @@ -42,6 +48,7 @@ def __ipow__(self, other): def __mul__(self, other): return self.radius * other + #allow for reversal of arguments __rmul__ = __mul__ def __lt__(self, other): From dc540f19eb45aba208a6beab01b265cde87097d3 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 07:56:47 -0800 Subject: [PATCH 096/367] Working through the rest of the circle. I'll start on sphere before I submit --- students/jesse_miller/session08/circle.py | 30 ++++++++- .../jesse_miller/session08/test_circle.py | 66 ++++++++++++++++++- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index 787e2df1..1ae91f9e 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -52,13 +52,37 @@ def __repr__(self): return f'{self.__class__.__name__}({self.radius})' def __add__(self, other): - return Circle(self.radius + other.radius) + return self.radius + other.radius def __rmul__(self, value): - return Circle(self.radius * value) + return self.radius * value def __mul__(self, value): try: - return Circle(self.radius * value) + return self.radius * value except TypeError: + #pylint: disable=E0602 + ''' + I have no idea why this works, but is getting a linter error over + unassigned variables. + ''' rmul(self, value) + + def __lt__(self, other): + if self.radius < other.radius: + return True + return False + + def __gt__(self, other): + if self.radius > other.radius: + return True + return False + + def __eq__(self, other): + pass + + def sort_var(self): + ''' + This one wants a doc string for sorting, so this method sorts + ''' + return self.radius diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index 79e680a2..d014d49c 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -111,7 +111,69 @@ def test_add_circles(): Test 11: Testing adding circles ''' #pylint: disable=C0103 + c1 = Circle(6) + c2 = Circle(4) + + assert c1 + c2 == 10 + +def test_multiply_circles(): + ''' + Test 12: Testing multiplication + ''' + #pylint: disable=C0103 c1 = Circle(4) - c2 = Circle(6) + c2 = Circle(2) + + assert c1 * c2 == 8 + +def test_rmul_circles(): + ''' + Test 13: Testing the rmul function + ''' + #pylint: disable=C0103 + c1 = Circle(2) + + assert 4 * c1 == 8 + +def test_greater_than(): + ''' + Test 14: Testing greater than + ''' + #pylint: disable=C0103 + c1 = Circle(2) + c2 = Circle(5) + + assert (c1 > c2) is False + + +def test_less_than(): + ''' + Test 15: Less than + ''' + #pylint: disable=C0103 + c1 = Circle(2) + c2 = Circle(5) + + assert (c1 < c2) is True + + +def test_equal_to(): + ''' + Testing equal to function + ''' + #pylint: disable=C0103 + c1 = Circle(3) + c2 = Circle(3) + + assert (c1 == c2) is True + + +def test_sort(): + ''' + Testing the sorting function + ''' + #pylint: disable=C0103 + circles = [Circle(4), Circle(1), Circle(3), Circle(2), Circle(5)] + circles.sort() - assert c1 + c2 == Circle(10) + assert circles == [Circle(1), Circle(2), Circle(3), Circle(4), Circle(5)] From d6760f754083d3773f6405726181e1f9dd01e9af Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 07:57:42 -0800 Subject: [PATCH 097/367] Sorting is going to be a thing, I can tell already --- students/jesse_miller/session08/circle.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index 1ae91f9e..09cf2577 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -74,12 +74,14 @@ def __lt__(self, other): return False def __gt__(self, other): - if self.radius > other.radius: + if self.radius < other.radius: return True return False def __eq__(self, other): - pass + if self.radius == other.radius: + return True + return False def sort_var(self): ''' From 01dccd8267d638f2decc34677f38e9b55f3ca4de Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 08:18:06 -0800 Subject: [PATCH 098/367] Well, I learned that what I would expect to be div, is actually truediv. --- students/jesse_miller/session08/circle.py | 18 ++++++++++++ .../jesse_miller/session08/test_circle.py | 28 ++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index 09cf2577..e8657e00 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -68,6 +68,20 @@ def __mul__(self, value): ''' rmul(self, value) + def __rtruediv__(self, value): + return self.radius / value + + def __truediv__(self, value): + try: + return self.radius / value + except TypeError: + #pylint: disable=E0602 + ''' + I have no idea why this works, but is getting a linter error over + unassigned variables. + ''' + rdiv(self, value) + def __lt__(self, other): if self.radius < other.radius: return True @@ -88,3 +102,7 @@ def sort_var(self): This one wants a doc string for sorting, so this method sorts ''' return self.radius + + @staticmethod + def __sort__(circle_list): + return circle_list.sort(key=Circle.sort_var) diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index d014d49c..19dd48a5 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -140,8 +140,8 @@ def test_greater_than(): Test 14: Testing greater than ''' #pylint: disable=C0103 - c1 = Circle(2) - c2 = Circle(5) + c1 = Circle(5) + c2 = Circle(2) assert (c1 > c2) is False @@ -159,7 +159,7 @@ def test_less_than(): def test_equal_to(): ''' - Testing equal to function + Test 16: Testing equal to function ''' #pylint: disable=C0103 c1 = Circle(3) @@ -170,10 +170,30 @@ def test_equal_to(): def test_sort(): ''' - Testing the sorting function + Test 17: Testing the sorting function ''' #pylint: disable=C0103 circles = [Circle(4), Circle(1), Circle(3), Circle(2), Circle(5)] circles.sort() assert circles == [Circle(1), Circle(2), Circle(3), Circle(4), Circle(5)] + + +def test_reflected_numerics(): + ''' + Test 18: Testing relected numerics + ''' + #pylint: disable=C0103 + c1 = Circle(3) + + assert c1 * 3 == 3 * c1 + + +def test_dividing_reflected_numerics(): + ''' + Test 19: Testing dividing relected numerics + ''' + #pylint: disable=C0103 + c1 = Circle(3) + + assert c1 / 3 == 3 / c1 From 5ce966c5596c79fdb2b304251e2ef5a3d34d9d39 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 7 Mar 2019 08:30:46 -0800 Subject: [PATCH 099/367] Circle update --- students/jeff_shabani/session08/Circle.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 98dfa0d6..32f868d6 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -48,7 +48,7 @@ def __ipow__(self, other): def __mul__(self, other): return self.radius * other - #allow for reversal of arguments + # allow for reversal of arguments __rmul__ = __mul__ def __lt__(self, other): @@ -71,6 +71,9 @@ def __str__(self): class Sphere(Circle): + """ + Sublclass of Circle + """ def volume(self): return (4 / 3) * math.pi * (self.radius ** 3) @@ -79,13 +82,9 @@ def area(self): return 4 * math.pi * (self.radius ** 2) def __repr__(self): - return f'Sphere with radius of {self.radius} volume of {self.volume()} & surface area of {self.area()}' + return f'Sphere with radius of {self.radius} volume of ' \ + f'{self.volume()} & surface area of {self.area()}' def __str__(self): - return f'Sphere with radius of {self.radius} volume of {self.volume()} & surface area of {self.area()}' - - -if __name__ == '__main__': - c1 = Circle(1) - # c1.radius = -1 - print(c1) + return f'Sphere with radius of {self.radius} volume of ' \ + f'{self.volume()} & surface area of {self.area()}' From 4b7d32b94cbc0d13a2ce94e4607947a56695972d Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 7 Mar 2019 08:42:29 -0800 Subject: [PATCH 100/367] Circle update --- .../jeff_shabani/session08/{Circle.py => circle.py} | 12 ++++++++++++ students/jeff_shabani/session08/test_circle.py | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) rename students/jeff_shabani/session08/{Circle.py => circle.py} (84%) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/circle.py similarity index 84% rename from students/jeff_shabani/session08/Circle.py rename to students/jeff_shabani/session08/circle.py index 32f868d6..47a0b08c 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/circle.py @@ -27,39 +27,49 @@ def diameter(self): def diameter(self, value): self.radius = value / 2 + # make area non-settable @property def area(self): return math.pi * pow(self.radius, 2) + # method to create a circle with the diameter @classmethod def from_diameter(cls, value): radius = value / 2 return cls(radius) + # simple add method def __add__(self, other): return self.radius + other.radius + # augmented assignment add method def __iadd__(self, other): return self.radius + other.radius + # augmented assigment exponential method def __ipow__(self, other): return self.radius ** other + # multiplication method def __mul__(self, other): return self.radius * other # allow for reversal of arguments __rmul__ = __mul__ + # less than comparison def __lt__(self, other): return self.radius < other.radius + # greater than comparison def __gt__(self, other): return self.radius > other.radius + # equality method def __eq__(self, other): return self.radius == other.radius + # non-equality method def __ne__(self, other): return self.radius != other.radius @@ -75,9 +85,11 @@ class Sphere(Circle): Sublclass of Circle """ + # override Circle volume method def volume(self): return (4 / 3) * math.pi * (self.radius ** 3) + # override Circle area method def area(self): return 4 * math.pi * (self.radius ** 2) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index 7925fde2..f10fa0d7 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 import unittest -from Circle import * +from circle import * -class circleTests(unittest.TestCase): +class CircleTests(unittest.TestCase): def test_init(self): """test for instantiation""" @@ -72,7 +72,7 @@ def test_extended_assignment(self): self.assertEqual(c3, 144) del c1, c2, c3 - #test for negative radius + # test for negative radius @unittest.expectedFailure def test_negative_radius(self): c1 = Circle(-1) @@ -89,10 +89,10 @@ def test_sphere_get_from_diameter(self): self.assertEqual(s.volume(), 33.510321638291124) del s - def test_spehere_printing(self): + def test_sphere_printing(self): s = Sphere(10) - self.assertEqual(repr(s),'Sphere with radius of 10 volume of 4188.790204786391 & surface area of 1256.6370614359173') - + self.assertEqual(repr(s), + 'Sphere with radius of 10 volume of 4188.790204786391 & surface area of 1256.6370614359173') if __name__ == '__main__': From 583277e39a9b208d0454a6c7151a727de3acd982 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 09:07:42 -0800 Subject: [PATCH 101/367] Almost done I think --- students/jesse_miller/session08/circle.py | 34 +++++++++++++++++++ .../jesse_miller/session08/test_circle.py | 15 ++++++++ 2 files changed, 49 insertions(+) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index e8657e00..86f40bcf 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -45,18 +45,23 @@ def from_diameter(cls, value): ''' return cls(value/2) + def __str__(self): return f'{self.__class__.__name__} with radius: {self.radius}' + def __repr__(self): return f'{self.__class__.__name__}({self.radius})' + def __add__(self, other): return self.radius + other.radius + def __rmul__(self, value): return self.radius * value + def __mul__(self, value): try: return self.radius * value @@ -68,9 +73,11 @@ def __mul__(self, value): ''' rmul(self, value) + def __rtruediv__(self, value): return self.radius / value + def __truediv__(self, value): try: return self.radius / value @@ -82,27 +89,54 @@ def __truediv__(self, value): ''' rdiv(self, value) + def __lt__(self, other): if self.radius < other.radius: return True return False + def __gt__(self, other): if self.radius < other.radius: return True return False + def __eq__(self, other): if self.radius == other.radius: return True return False + def sort_var(self): ''' This one wants a doc string for sorting, so this method sorts ''' return self.radius + @staticmethod def __sort__(circle_list): return circle_list.sort(key=Circle.sort_var) + +class Sphere(Circle): + ''' + Here goes spheres, we'll see how that works + ''' + @property + def sphere_area(self): + ''' + Calculating the area of the sphere + ''' + try: + return 4 * pi * self.radius ** 2 + except NotImplementedError: + print("This is not implemented") + + @property + def sphere_volume(self): + ''' + Determining the volume of said sphere, geometry isn't my strong suit + so I'm basically assuming that the math is right here. + ''' + return 4 / 3 * pi * self.radius ** 3 diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index 19dd48a5..df004f85 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -197,3 +197,18 @@ def test_dividing_reflected_numerics(): c1 = Circle(3) assert c1 / 3 == 3 / c1 + + +def test_augmented_assignments(): + ''' + Test 20: Let's test augmented assignment I guess + ''' + #pylint: disable=C0103 + c1 = Circle(3) + c2 = Circle(3) + + c1 += c2 + assert c1 == 6 + + c1 *= 2 + assert c1 == 12 From f0a8a3a6232381dd0215b17919685f82c48fa051 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 09:13:13 -0800 Subject: [PATCH 102/367] It helps if you import the functions --- students/jesse_miller/session08/circle.py | 10 ++++++++-- students/jesse_miller/session08/test_circle.py | 12 +++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/students/jesse_miller/session08/circle.py b/students/jesse_miller/session08/circle.py index 86f40bcf..bc6f0aa8 100644 --- a/students/jesse_miller/session08/circle.py +++ b/students/jesse_miller/session08/circle.py @@ -119,12 +119,17 @@ def sort_var(self): def __sort__(circle_list): return circle_list.sort(key=Circle.sort_var) + +''' +------------------------------------------------------------------------------- +''' + class Sphere(Circle): ''' Here goes spheres, we'll see how that works ''' @property - def sphere_area(self): + def area(self): ''' Calculating the area of the sphere ''' @@ -133,8 +138,9 @@ def sphere_area(self): except NotImplementedError: print("This is not implemented") + @property - def sphere_volume(self): + def volume(self): ''' Determining the volume of said sphere, geometry isn't my strong suit so I'm basically assuming that the math is right here. diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index df004f85..681e8017 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -7,7 +7,7 @@ ''' from math import pi import pytest -from circle import Circle +from circle import Circle, Sphere def test_empty_circle(): @@ -212,3 +212,13 @@ def test_augmented_assignments(): c1 *= 2 assert c1 == 12 + +''' +Spheres! +''' + +def test_new_sphere(): + ''' + Here goes this test + ''' + Sphere(4) From 4f012dca10d5255950e5e745bf0c8a48d5d11d29 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 09:19:45 -0800 Subject: [PATCH 103/367] So far so good --- .../jesse_miller/session08/test_circle.py | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index 681e8017..2f705877 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -219,6 +219,44 @@ def test_augmented_assignments(): def test_new_sphere(): ''' - Here goes this test + Test 21: Here goes this test ''' Sphere(4) + +def test_empty_sphere(): + ''' + Test 22: No values insertered. + ''' + #pylint: disable=E1120 + with pytest.raises(TypeError): + Sphere() + + +def test_str_sphere(): + ''' + Test 23: Testing string insertion. + ''' + #pylint: disable=E1120, C0103 + s = Sphere(13) + assert str(s) == "Sphere with radius: 13" + + +def test_repr_sphere(): + ''' + Test 24: Testing repr fuctionality. + ''' + #pylint: disable=E1120, C0103 + s = Sphere(12) + assert repr(s) == "Sphere(12)" + + +def test_sphere_volume(): + pass + + +def test_sphere_area(): + pass + + +def test_sphere_set_diameter(): + pass From 97cb8630538950bad70690e179cf4541a2817d54 Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Thu, 7 Mar 2019 09:11:54 -0800 Subject: [PATCH 104/367] Timer() contextmanager seems to work --- students/douglas_klos/.gitignore | 1 - .../extra/context/raising_an_assert.py | 13 ----- .../extra/context/run_timer_context.py | 58 +++++++++++++++++++ .../extra/context/timer_context.py | 25 ++++++++ .../extra/lambda/lambda_keyword.py | 2 +- .../douglas_klos/extra/lambda/test_lambda.py | 4 +- .../douglas_klos/extra/numerals/numerals.py | 2 +- .../extra/numerals/test_numerals.py | 4 +- students/douglas_klos/extra/rot13/rot13.py | 4 +- .../douglas_klos/extra/rot13/test_rot13.py | 2 +- 10 files changed, 92 insertions(+), 23 deletions(-) delete mode 100644 students/douglas_klos/extra/context/raising_an_assert.py create mode 100755 students/douglas_klos/extra/context/run_timer_context.py create mode 100755 students/douglas_klos/extra/context/timer_context.py diff --git a/students/douglas_klos/.gitignore b/students/douglas_klos/.gitignore index 62537ae9..5e5a6e9c 100644 --- a/students/douglas_klos/.gitignore +++ b/students/douglas_klos/.gitignore @@ -1,7 +1,6 @@ *.swp *.back .vscode -../.vscode/ session7/execution_times.txt session7/html_render.zip session7/test_html_output1.html diff --git a/students/douglas_klos/extra/context/raising_an_assert.py b/students/douglas_klos/extra/context/raising_an_assert.py deleted file mode 100644 index 0ea86ea5..00000000 --- a/students/douglas_klos/extra/context/raising_an_assert.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python - -""" -examples of forcing and an AssertionError -""" - - -def test_raise_assertion(): - raise AssertionError("this was done with a direct raise") - - -def test_trasditional_assert(): - assert False, "this was done with a forced assert" diff --git a/students/douglas_klos/extra/context/run_timer_context.py b/students/douglas_klos/extra/context/run_timer_context.py new file mode 100755 index 00000000..c7ed28e1 --- /dev/null +++ b/students/douglas_klos/extra/context/run_timer_context.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +#pylint: disable=C0103 + +# Douglas Klos +# March 7th, 2019 +# Python 210, Extra +# run_timer_context.py + +""" Run file for context manager testing """ + +import io +import time +from contextlib import contextmanager +import timer_context as tc + + + +@contextmanager +def local_timer(out_file, name=''): + """ Context manager that returns execution time """ + local_time = time.time() + try: + yield local_time + finally: + local_time = time.time() - local_time + out_file.write(f'{name} execution took {local_time} seconds') + + +def timer_test(): + """ Runs a loop with context manager and prints execution time """ + outfile = io.StringIO() + + with tc.Timer(outfile, 'timer_test'): + for i in range(1000000): + i = i ** 20 + + print(outfile.getvalue()) + + +def timer_test2(): + """ Runs a loop with context manager and prints execution time """ + outfile = io.StringIO() + + with local_timer(outfile, 'timer_test2'): + for i in range(1000000): + i = i ** 20 + + print(outfile.getvalue()) + + +def main(): + """ Main, calls different tests """ + timer_test() + timer_test2() + + +if __name__ == '__main__': + main() diff --git a/students/douglas_klos/extra/context/timer_context.py b/students/douglas_klos/extra/context/timer_context.py new file mode 100755 index 00000000..b0200032 --- /dev/null +++ b/students/douglas_klos/extra/context/timer_context.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +# Douglas Klos +# March 7th, 2019 +# Python 210, Extra +# timer_context.py + +""" A simple class based context manager to calculate execution time """ + +import time + + +class Timer(): + """ A simple class based context manager to calculate execution time """ + def __init__(self, file_name, name=''): + self.file_obj = file_name + self.name = name + self.start = time.time + + def __enter__(self): + self.start = time.time() + + def __exit__(self, exeception_type, exeception_value, traceback): + self.file_obj.write(f'{self.name} execution took {time.time() - self.start} seconds') + return self.file_obj diff --git a/students/douglas_klos/extra/lambda/lambda_keyword.py b/students/douglas_klos/extra/lambda/lambda_keyword.py index 1b20ee6b..80f64455 100755 --- a/students/douglas_klos/extra/lambda/lambda_keyword.py +++ b/students/douglas_klos/extra/lambda/lambda_keyword.py @@ -2,7 +2,7 @@ # Douglas Klos # March 6th, 2019 -# Python 210, Session 8 +# Python 210, Extra # lambda_keyword.py diff --git a/students/douglas_klos/extra/lambda/test_lambda.py b/students/douglas_klos/extra/lambda/test_lambda.py index 0d4789e1..00d70f47 100755 --- a/students/douglas_klos/extra/lambda/test_lambda.py +++ b/students/douglas_klos/extra/lambda/test_lambda.py @@ -2,8 +2,8 @@ # Douglas Klos # March 6th, 2019 -# Python 210, Session 8 -# lambda_keyword.py +# Python 210, Extra +# test_lambda.py """ Some simple tests for the "lambda and keyword magic" diff --git a/students/douglas_klos/extra/numerals/numerals.py b/students/douglas_klos/extra/numerals/numerals.py index 49b23912..344a340f 100755 --- a/students/douglas_klos/extra/numerals/numerals.py +++ b/students/douglas_klos/extra/numerals/numerals.py @@ -5,7 +5,7 @@ # Douglas Klos # March 6th, 2019 -# Python 210, Session 8 +# Python 210, Extra # numerals.py diff --git a/students/douglas_klos/extra/numerals/test_numerals.py b/students/douglas_klos/extra/numerals/test_numerals.py index dbdb6941..bc20abb0 100755 --- a/students/douglas_klos/extra/numerals/test_numerals.py +++ b/students/douglas_klos/extra/numerals/test_numerals.py @@ -5,8 +5,8 @@ # Douglas Klos # March 6th, 2019 -# Python 210, Session 8 -# numerals.py +# Python 210, Extra +# test_numerals.py import pytest diff --git a/students/douglas_klos/extra/rot13/rot13.py b/students/douglas_klos/extra/rot13/rot13.py index 9cb11bb1..46e9f14b 100755 --- a/students/douglas_klos/extra/rot13/rot13.py +++ b/students/douglas_klos/extra/rot13/rot13.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 -""" Class to convert rot13 'encrypt' """ +""" Function to convert rot13 'encrypt' """ # Douglas Klos # March 6th, 2019 -# Python 210, Session 8 +# Python 210, Extra # rot13.py # a - z == 97 - 122 diff --git a/students/douglas_klos/extra/rot13/test_rot13.py b/students/douglas_klos/extra/rot13/test_rot13.py index d0e9fbde..563b5821 100755 --- a/students/douglas_klos/extra/rot13/test_rot13.py +++ b/students/douglas_klos/extra/rot13/test_rot13.py @@ -4,7 +4,7 @@ # Douglas Klos # March 6th, 2019 -# Python 210, Session 8 +# Python 210, Extra # test_rot13.py import rot13 From 5d0e6c9c3ee5fb7ccd99a7bc74abf3e4e50884f5 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Thu, 7 Mar 2019 09:32:15 -0800 Subject: [PATCH 105/367] Circle update --- students/jeff_shabani/session08/circle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/students/jeff_shabani/session08/circle.py b/students/jeff_shabani/session08/circle.py index 47a0b08c..f4a1ebd4 100644 --- a/students/jeff_shabani/session08/circle.py +++ b/students/jeff_shabani/session08/circle.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import coverage import math """ From 9a1a79d1129c80ececc70a83dfcfb67a222753e3 Mon Sep 17 00:00:00 2001 From: UncleanlyCleric Date: Thu, 7 Mar 2019 09:51:43 -0800 Subject: [PATCH 106/367] Volume test is go --- students/jesse_miller/session08/test_circle.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index 2f705877..c8ef9a52 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -251,12 +251,22 @@ def test_repr_sphere(): def test_sphere_volume(): - pass + ''' + Test 24: Testing sphere volume fuctionality. + ''' + s = Sphere(4) + assert s.volume == 4 / 3 * pi * 4 ** 3 def test_sphere_area(): + ''' + Test 24: Testing sphere area fuctionality. + ''' pass def test_sphere_set_diameter(): + ''' + Test 24: Testing set diameter fuctionality. + ''' pass From 2c49640b0b5d377f681a8b2d341bb23504646a2e Mon Sep 17 00:00:00 2001 From: Douglas Klos Date: Thu, 7 Mar 2019 10:14:02 -0800 Subject: [PATCH 107/367] Raises() contextmanager class --- .../extra/context/raises/raises_context.py | 26 ++++++++++++ .../context/raises/test_raises_context.py | 42 +++++++++++++++++++ .../context/{ => timer}/run_timer_context.py | 1 - .../context/{ => timer}/timer_context.py | 0 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100755 students/douglas_klos/extra/context/raises/raises_context.py create mode 100755 students/douglas_klos/extra/context/raises/test_raises_context.py rename students/douglas_klos/extra/context/{ => timer}/run_timer_context.py (99%) rename students/douglas_klos/extra/context/{ => timer}/timer_context.py (100%) diff --git a/students/douglas_klos/extra/context/raises/raises_context.py b/students/douglas_klos/extra/context/raises/raises_context.py new file mode 100755 index 00000000..9137bb1b --- /dev/null +++ b/students/douglas_klos/extra/context/raises/raises_context.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# Douglas Klos +# March 7th, 2019 +# Python 210, Extra +# raises_context.py + +""" A simple class based context manager to calculate execution time """ + +# This seems entirely too simple... Yet it seems to work... +# Am I missing something? + + +class Raises(): + """ A simple class based context manager to calculate execution time """ + def __init__(self, value): + self.value = value + + def __enter__(self): + pass + + def __exit__(self, exception_type, exeception_value, traceback): + if exception_type == self.value: + return True + return False + \ No newline at end of file diff --git a/students/douglas_klos/extra/context/raises/test_raises_context.py b/students/douglas_klos/extra/context/raises/test_raises_context.py new file mode 100755 index 00000000..40630d07 --- /dev/null +++ b/students/douglas_klos/extra/context/raises/test_raises_context.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +#pylint: disable=C0103,W0104, W0107 + +# Douglas Klos +# March 7th, 2019 +# Python 210, Extra +# test_raises_context.py + +""" Run file for context manager testing """ + +import raises_context as rc + + +def test1(): + """ Tests AssertionError """ + with rc.Raises(AssertionError): + raise AssertionError + + +def test2(): + """ Tests ZeroDivisionError """ + with rc.Raises(ZeroDivisionError): + 1 / 0 + + +def test3(): + """ Tests that Raises fails properly """ + # We expcet the next line to fail, and it does + # with rc.Raises(AssertionError): + # raise ZeroDivisionError + pass + + +def main(): + """ Main, calls different tests """ + test1() + test2() + test3() + + +if __name__ == '__main__': + main() diff --git a/students/douglas_klos/extra/context/run_timer_context.py b/students/douglas_klos/extra/context/timer/run_timer_context.py similarity index 99% rename from students/douglas_klos/extra/context/run_timer_context.py rename to students/douglas_klos/extra/context/timer/run_timer_context.py index c7ed28e1..81098db3 100755 --- a/students/douglas_klos/extra/context/run_timer_context.py +++ b/students/douglas_klos/extra/context/timer/run_timer_context.py @@ -14,7 +14,6 @@ import timer_context as tc - @contextmanager def local_timer(out_file, name=''): """ Context manager that returns execution time """ diff --git a/students/douglas_klos/extra/context/timer_context.py b/students/douglas_klos/extra/context/timer/timer_context.py similarity index 100% rename from students/douglas_klos/extra/context/timer_context.py rename to students/douglas_klos/extra/context/timer/timer_context.py From 0576a3f07ce448a86c77827ad5ca30c88550e7f0 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 10:15:19 -0800 Subject: [PATCH 108/367] Finished with test_circle.py and circle.py --- students/jesse_miller/session08/test_circle.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/students/jesse_miller/session08/test_circle.py b/students/jesse_miller/session08/test_circle.py index c8ef9a52..70f01cc5 100644 --- a/students/jesse_miller/session08/test_circle.py +++ b/students/jesse_miller/session08/test_circle.py @@ -254,6 +254,7 @@ def test_sphere_volume(): ''' Test 24: Testing sphere volume fuctionality. ''' + #pylint: disable=E1120, C0103 s = Sphere(4) assert s.volume == 4 / 3 * pi * 4 ** 3 @@ -262,11 +263,17 @@ def test_sphere_area(): ''' Test 24: Testing sphere area fuctionality. ''' - pass + #pylint: disable=E1120, C0103 + s = Sphere(6) + assert s.area == 4 * pi * 6 ** 2 def test_sphere_set_diameter(): ''' Test 24: Testing set diameter fuctionality. ''' - pass + #pylint: disable=E1120, C0103 + s = Sphere.from_diameter(8) + + assert s.area == 4 * pi * 4 ** 2 + assert s.volume == 4 / 3 * pi * 4 ** 3 From 2206f427800829278b8cf6639e231150f2bd86bb Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 10:38:55 -0800 Subject: [PATCH 109/367] Initial commit. I... I'm going to have to framework this first if I want it installable. --- students/jesse_miller/session09/mailroom.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 students/jesse_miller/session09/mailroom.py diff --git a/students/jesse_miller/session09/mailroom.py b/students/jesse_miller/session09/mailroom.py new file mode 100644 index 00000000..4a9b90a1 --- /dev/null +++ b/students/jesse_miller/session09/mailroom.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +''' +Well, here it goes. An object oriented verion of my mailroom program. This, +is going to be complicated for me because I'm already used to how the old one +works. (Of course, having said old one, I am now dubbing this implementation +Cthulu in my head.) +''' From b2c3d6f2041eec02c48d836a84801a88d0b1b0cf Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 10:57:20 -0800 Subject: [PATCH 110/367] Okay, here's the structure I think I'll need. Don't be surprised if this changes though. It's supposed to be installable, so... --- students/jesse_miller/session09/donor_info.py | 1 + students/jesse_miller/session09/mail_function.py | 1 + students/jesse_miller/session09/mail_menu.py | 1 + students/jesse_miller/session09/test_mailroom.py | 1 + 4 files changed, 4 insertions(+) create mode 100644 students/jesse_miller/session09/donor_info.py create mode 100644 students/jesse_miller/session09/mail_function.py create mode 100644 students/jesse_miller/session09/mail_menu.py create mode 100644 students/jesse_miller/session09/test_mailroom.py diff --git a/students/jesse_miller/session09/donor_info.py b/students/jesse_miller/session09/donor_info.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/donor_info.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/students/jesse_miller/session09/mail_function.py b/students/jesse_miller/session09/mail_function.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/mail_function.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/students/jesse_miller/session09/mail_menu.py b/students/jesse_miller/session09/mail_menu.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/mail_menu.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/students/jesse_miller/session09/test_mailroom.py b/students/jesse_miller/session09/test_mailroom.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/test_mailroom.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 From 74921636ad2be72439444ecf9c399d48128dcd0a Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Thu, 7 Mar 2019 11:32:51 -0800 Subject: [PATCH 111/367] finished step 7 --- students/shirin_ak/Session08/Circle.py | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 students/shirin_ak/Session08/Circle.py diff --git a/students/shirin_ak/Session08/Circle.py b/students/shirin_ak/Session08/Circle.py new file mode 100644 index 00000000..8fa6a7bd --- /dev/null +++ b/students/shirin_ak/Session08/Circle.py @@ -0,0 +1,46 @@ + +import math +class Circle(): + def __init__(self, radius): + # STEP 1 The radius is a required parameter + self.radius = radius + # STEP 2 Add a 'diameter' property + @property + def diameter(self): + return self.radius*2 + + #STEP 3 set up the diameter property + @diameter.setter + def diameter(self, value): + self.diameter = value + self.radius = value/2 + + #STEP 4 Add an area property + @property + def area(self): + return math.pi * (self.radius ** 2) + + # STEP 5 Add an “alternate constructor” that + #lets the user create a Circle directly with the diameter: + @classmethod + def from_diameter(class_object, diameter): + radius = diameter/2 + return class_object(radius) + + #STEP 6 Add __str__ and __repr__ methods to your Circle class. + + def __str__(self): + return "Circle with radius: {:.6f}".format(self.radius) + + def __repr__(self): + return "Circle({r})".format(r=self.radius) + #STEP 7 Add two circles and multiply one by a number + def ___add__(self, other): + c1 = self.radius + c2 = other.radius + return Circle(c1+c2) +# def __mul__(self, other): + + + + From 451f4d6978016ec04392b5f1a7f8df5937c60d0b Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Thu, 7 Mar 2019 11:46:18 -0800 Subject: [PATCH 112/367] added files --- students/shirin_ak/Session08/test_Circle.py | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 students/shirin_ak/Session08/test_Circle.py diff --git a/students/shirin_ak/Session08/test_Circle.py b/students/shirin_ak/Session08/test_Circle.py new file mode 100644 index 00000000..655c8287 --- /dev/null +++ b/students/shirin_ak/Session08/test_Circle.py @@ -0,0 +1,29 @@ +import pytest + +from Circle import Circle + + +def test_radius(): + c = Circle(4) + assert c.radius == 4 + +def test_diameter(): + c = Circle(4) + assert c.diameter == 8 + + +def test_set_diameter(): + c = Circle(4) + c.diameter = 10 + assert c.diameter == 10 + assert c.radius == 5 + +def test_area(): + c = Circle(1) + + assert c.area == 3.141592653589793 + +def test_constructor(): + c = Circle.from_diameter(4) + assert c.diameter == 4 + assert c.radius == 2 From c940164de3985099a5783d382a0877dfc6b0040d Mon Sep 17 00:00:00 2001 From: J Miller Date: Thu, 7 Mar 2019 11:54:20 -0800 Subject: [PATCH 113/367] Renaming --- students/jesse_miller/session09/mail_menu.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 students/jesse_miller/session09/mail_menu.py diff --git a/students/jesse_miller/session09/mail_menu.py b/students/jesse_miller/session09/mail_menu.py deleted file mode 100644 index e5a0d9b4..00000000 --- a/students/jesse_miller/session09/mail_menu.py +++ /dev/null @@ -1 +0,0 @@ -#!/usr/bin/env python3 From f5a68393bfdd369f5b8fffe19ca5bae4f0afc7e8 Mon Sep 17 00:00:00 2001 From: J Miller Date: Thu, 7 Mar 2019 11:54:31 -0800 Subject: [PATCH 114/367] Renaming --- students/jesse_miller/session09/mail_function.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 students/jesse_miller/session09/mail_function.py diff --git a/students/jesse_miller/session09/mail_function.py b/students/jesse_miller/session09/mail_function.py deleted file mode 100644 index e5a0d9b4..00000000 --- a/students/jesse_miller/session09/mail_function.py +++ /dev/null @@ -1 +0,0 @@ -#!/usr/bin/env python3 From 17c27840e40b413de7e94d407b908a0f79a3ee92 Mon Sep 17 00:00:00 2001 From: J Miller Date: Thu, 7 Mar 2019 11:54:45 -0800 Subject: [PATCH 115/367] Renaming Simplicity is key --- students/jesse_miller/session09/donor_info.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 students/jesse_miller/session09/donor_info.py diff --git a/students/jesse_miller/session09/donor_info.py b/students/jesse_miller/session09/donor_info.py deleted file mode 100644 index e5a0d9b4..00000000 --- a/students/jesse_miller/session09/donor_info.py +++ /dev/null @@ -1 +0,0 @@ -#!/usr/bin/env python3 From 95094a9479946a6881a41fca6641f5b44f30acd4 Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 11:55:09 -0800 Subject: [PATCH 116/367] Renamed files for simplicity --- students/jesse_miller/session09/donors.py | 1 + students/jesse_miller/session09/mailings.py | 1 + students/jesse_miller/session09/menus.py | 1 + 3 files changed, 3 insertions(+) create mode 100644 students/jesse_miller/session09/donors.py create mode 100644 students/jesse_miller/session09/mailings.py create mode 100644 students/jesse_miller/session09/menus.py diff --git a/students/jesse_miller/session09/donors.py b/students/jesse_miller/session09/donors.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/donors.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/students/jesse_miller/session09/mailings.py b/students/jesse_miller/session09/mailings.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/mailings.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 diff --git a/students/jesse_miller/session09/menus.py b/students/jesse_miller/session09/menus.py new file mode 100644 index 00000000..e5a0d9b4 --- /dev/null +++ b/students/jesse_miller/session09/menus.py @@ -0,0 +1 @@ +#!/usr/bin/env python3 From 623a3d421438397bcaa912cf1d8bc1acaef5007d Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 7 Mar 2019 11:58:07 -0800 Subject: [PATCH 117/367] Committing before starting on Lesson 08 Circle Class assignment. --- .../lesson07_exercise/html_renderer.zip | Bin 0 -> 5265 bytes .../lesson08_exercise/circle_class.py | 0 .../lesson08_exercise/properties_example.py | 33 ++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 students/jeremy_m/lesson07_exercise/html_renderer.zip create mode 100644 students/jeremy_m/lesson08_exercise/circle_class.py create mode 100644 students/jeremy_m/lesson08_exercise/properties_example.py diff --git a/students/jeremy_m/lesson07_exercise/html_renderer.zip b/students/jeremy_m/lesson07_exercise/html_renderer.zip new file mode 100644 index 0000000000000000000000000000000000000000..4405593a26e8de90db3340f6a46b91db49c5c842 GIT binary patch literal 5265 zcmZ{oWmFWt52RQ$IihT(Oxy6j1`N`@BWX*%_9V1C?8O$jT-mb61jWY!b^zR}Z zq8@`JqUIhp`!pUdf_R3#KVk1+)>}YeJk~4kZhPA-Tw^dQ;j;LxM(RXEX25I%L(F&E zFKfG~B?H>Vn!aa&93OL*LPiQ&je~wq$Y_$I?J zxE2ZO^_~_hpr0U3#TxR}8|tX_8o=lZ8Rf-?=Q9;`9?(9cBwqV(l2ct9p)ylmQAW$H zw8y`HH+pM2|GX1Ji*9&LZe^!2mnKc^+4ZWnR0w?CqH^~WncBwP7LA;O6A8F$yk?r? z_U^4LcZo52bg*sCNS+-}{pVv0Pej1?67PNsk5}{iS=o7*f+(yE&Pla~C83YVq%5^o zg?u=Ljltw@Q?RAUE$I(8$&ACx_?fnt*mjNF&t`m!M<$}W{v=q|VEDZwJqTtJvL5wW z{N=Vjq(U)a+5g%O6&1$ifHwF@QG<^EWmkD_>CxtwY2(9%gH!>DmRY$dKQM@Iv0rTz zQab0Z-rZidkRBd`_4aQxXjAw#V8e7| z{fC|CHHWCatmUZwA}el#`khNABll}AVG5$L&Ys7zA+9Wsn-=EqL#xKrsW-mM&|zDk zQo%FfZANs(p|MNq%4Qm4qH(yv)be7b^95NL`mfxee9FZhv{B1ij`iNGSf^2Kp;?Vr zfdxc4Mj|;pG=}8q(XWx8->miLHi(x@pk_50kAqKh(fgO@if>)!{ii$n*GLiqUTO(1 z{Ior7j(yZ_aA$AvDCRcTHA;Q&!ey}fsh(y_@z23>r=F_?-`y6RKeXI0aW9`?UJKvZ zUqeR6Y+GQrxGLi8`p~h|j?y>G_8xUj>qTXiyn&TkgZkK7-_q;G;>k15+15v~+vRoI z=%vJLH&>)DiPJk{XNZRM&G4F;XMh1c4Hk0{*#Mag3DQ>GCs)b7#9~GU8JfgbizXdm zZzR15SBp+`ZP-sPCK$3;Z|cQ?XFxgcZbx5mWg-EC;~Ppjm{8Hmg?FJVAAS(SXz0sVxQ?TStnTieM9m=UHFo2V<)P7_&nl^0^>D#N zOD9JuD?*xN5U&9htqBc5eBy~B*nSIx@yr$*+8|scWc+0@bo2EN-wK!j*R*H{aVL}H zLZA-3bIH|u0tGwUSi--HnwvyGHp`iKdEP4#dO)-EsEBC@8CZ1kh<_4X`~C9k?M(Gw9R)2X&x@m7%d6qs?o!l-`o{7_h$!q7bU zZoer&7eSMtp2o%}$Al;8!8#hjG+=P`xIWtdedPqBy$-jw8DA;BK5GUse0MM<@f!?U zM>&zOCv^%k=`ViN4+!g`YE9yQJK#c_`QDnr`+4fL@Gj^>KEm;e7S8A3{B~2vBxWc_ z{;oJHK%Lt@Yeqen+gztv-c7!JE}8mCAL|AgQtkvfa9;k4A>-x;1?wOCs8H;(qD949iS^?)4 zFej-yqqLF1uczMpML1=nE+C5(YKh>2IuD^{lE^oc&%1NWMDQ8t2V*IE@q60J7ri}T z6HZ(G>}EDuH?3XXnujRSKhi!+N2njmzz1paMzXfL^{MfQeHhBXg=oN6Xm8(4r;7RT$Q)M8N)mPf8dli$MG&kY!WvszVZpmTBpHZra#b^Gae0oLcj3KRXL$PdYBpY=J(U4<(rFqwfytd3Td)pi&eM;TqwtAVicC$f-Jz z+T^B(QDuT2`)JCY(Jf#%`D{E@l8V_soS}PQ1&O4iW&GBQ;&Y9OSbejO67zY9<$dCe zd+X)mOtNEAopnX>PsNZYSZW;Kb9LMh007wB0Kk*Kit(^^_xN|m&@3b`^_}Lt=I@dY z()G$8E?0#^i?_JoWEsW_zvMs_i!_*W7HXs@8lv<9{Jk39R8%j>SOFl-Td4 zqXburJTA8M5mfK_ys=$+ww~)pg)ICW-Rz0o=NZDNz%N38UPDBa$l*o^LbrRij>CXc zz7MWS7#_K=REXyizg4ac;7EI@SX?`p*o|!t>yOkMiQ`y^eWUE}IcgJU&ecIKGs*YW zfm28@norP`_o8pB&X~^-lZz`&I80g5y$Wvf87ug)wnOZTqJ>YsIwgwb$)WPd$bN(Y zeo93p(3ZSJFW zZ*+Ygl%_U29J&Tz5UuC*G2O6c)C`f8L7D-rnJtY-Ou5>zM|XC+%?!Jz*zy1|!3y9T zB1DF}aUHOyKkG$pAC<(Al^s-*91R9KF;@jkoe#=p`kM-2UNhu0<08)&Bcr7p^cA<9 zIr?*66jM8kQQ}mCAewO9NjC@JGK(+s%MfAM)Rvt|TA@VHTU9)m8%aZhJc*}Do)VGp zeNGx_^LNwe*kP8?=}402?>v70(8IB(PR;9!Y z1@SAThhC~xKdmTI#!+A{16-Nvgqpihq6zlmLKWpTEJXrxEVPS-%=J;b-t7^ziX90?fL7JetmH-dwO& zU&+T!DVEBRBlZT(dP7CluoThBKHfwFJV7e>r{#C5H3cQw<=eaQbbKO~X=A-z$aB=P zw5L|mH~9Ek;+8}fl_h!jgoJ4DXY3#25_^SpGe;Y&#_(f^j!{sm9d)nX1;z`)r=)pR ztDq&=T8Iw)>+_KhSN%KZ4;gFA@jbk?H*D~iyl~D9aRlMLQq}PJJ?*u%gM{!_rw`|B zk1cIVpxAGWdU;R|&d#}%xAEQoU z*h|U$R;^3*i**e_{BIiFB>7f8vmMdObS^q9UE}kx9lhfiq!6`?AN}-FKQg5G@tBpf zhzqVgxU@jq9wLVaKE0OX&UQBpO~$?<%YY>WKjJ zx~S_D=A1Jj*S^XnC)WzyOo2`8u}kPoM1_R-R^4IZB8fAdNawoL$67CnK3&Aj(~7JC z0n(0~twe@e{$J&O(}iKK?wPa%nZciysR`P4iEu{eX(OLRQXdh;0ez;+%0k{y`PgAt ziEH)mCeTuPh4kW4p@QmJdOuSOgfr%Ac|#td-B}iIL`)Z$&CAQ<5H4XgC*b^gL^Jng z^37F%{yvI)fEe5EPG6p$%;bcBE7{j|0~fExbT+01JHeo$e~^Ee<;3;;Cu+Y42HT{+ zyz^c|m^c{8`FYK^YTwc4IbCDk%8l&dVXy=7W$aC4Ycv$CX~;nH1c`{H;@)vIF{Xwg z5%v9MzidydO{;5v8Znj-;!J{J(E@6yxgPm zT|*st`MS1&zw=kJJ{_nQx$)@Gq&MDU#5$ICh+6kf6%SN4jH?Wiv4yixluND`G7G4~ zmm{0n$y|%V+lD<~HOM#DW-Pg~U8p{M(!PsJOmghd+83vFavh#eyFLHLTInNmFgFqB z;GvHU7H6tb9Iwt)XD-nyCn)AMoUu*ZOmkjuvCaFj1QI`%NsyWF9Xq^)1ZFCFVzsm? zr-6cucusnx;yV0p8g59}ixq9o>@M!u?%(@x{%qo>>E4*joR8r(6vF+`RJyHXyJ~7* z>xYK&e;#;zT`b4=B*54gLLRV`1Y-J{PJw*75}rDh!Aov%z^Y3hq=cW7P#QeG*&n|* z7*tI971iHfmDRXiUB8@u3$-Re5gH!=l+3trDRCv}79fLWG>x+f?WdLk0f&x^DMy?6 zb@98ScfE0W>BA$6$Wov_WQoplUQA;c*LRR{wO>TM|{_ zfzW}Y=rtaRq;6(27kq9zq$o}~?;%Nqd+UE;Fvc;6J_hR>1z@+IvRpQ^dNpGk-CbW1 zL|lXB4hNHR*<_i1WYBkzNVp+|mr%|A=AzTiephR@xm)#!j=0l$$3Hf7HFF16`O^iY zD&=sq_G{h?E(ShP?zPR!uf9V<^`B1PDH2mqGXy~p_8mtgYs59-KKIT|avr^g)xF5Y zq%(u?O(`#uH(_eUHaby|n25eE4D;^4f%}O2g>HWD+{U~leuNS?y>Zd@tK(0kCu^WbUop^hdGp4_ zqMucH^DKNi8+TdP^!Yu8&|muV+=4N{XW};x#=2IkS3u}aW8lKMU8a~PwGp0=PJSl1 za=P4bt0T}Wg}fa_9I^V{<#PO(93!qM3|x7g^ugIs_t>AFm0zVHyWIj2?x&g&13nD~ z=|>CaRx3K)=1m-OVawIEXQ-Gwos2D968N-N30-^m8;eBk!shfb#wRBWCM^k(r-y&6 zND14hWa}M1cFyH}UGx`eS=cZK9)!yXI`^K48H_?-!aS6haVe3-?*tmMy)vqF5Gl=L zJ?j-A51m8wQ${!q(MWLNFZ9v8dS&9Lad*K#_Gk4ML@4^CS z!o*;b_T`lw%v7pxva3355^fBCqzAsfo&1RXvB~ZVG?D^7au2CyeDCv%g5z7m8q_Bt zo#`RsrS|(}gq|*v7)KfTsxPG-`N8e{<=TkmYW-g7?}PiG9M+;S6(AY%WzwA2IBOl; z>^6Yw z^pElP{O@M|uk3&7^8X Date: Thu, 7 Mar 2019 12:55:23 -0800 Subject: [PATCH 118/367] Obviously, I just copied the functions from the old program into the new programs. This is not the solution to the problem, this is reference material --- students/jesse_miller/session09/donors.py | 68 +++++++++++++++++++++ students/jesse_miller/session09/mailings.py | 57 +++++++++++++++++ students/jesse_miller/session09/menus.py | 40 ++++++++++++ 3 files changed, 165 insertions(+) diff --git a/students/jesse_miller/session09/donors.py b/students/jesse_miller/session09/donors.py index e5a0d9b4..c3a68350 100644 --- a/students/jesse_miller/session09/donors.py +++ b/students/jesse_miller/session09/donors.py @@ -1 +1,69 @@ #!/usr/bin/env python3 + +donors = {'Robert Smith': [435.56, 125.23, 357.10], + 'JD Cronise': [123.12], + 'Chris Stapleton': [243.87, 111.32], + 'Dave Lombardo': [63.23, 422.87, 9432.01], + 'Randy Blythe': [223.50, 8120.32], + 'Devin Townsand': [431.12, 342.92, 5412.45], + } + + +def donor_list(): + ''' + This when done properly, will print the list of donor names + ''' + print(f"\n{'-'*15}\nList of Donors:\n{'-'*15}") + for donor in donors: + print(donor) + print(f"{'-'*15}\n") + + +def donor_report(): + ''' + This will be the donation report section + ''' + summary = [] + headers = ['Donor Name', 'Total Given', 'Times Donated', 'Average Gift'] + + print(f"\n{'-'*80}\n{{:17}} | {{:<19}} | {{:<15}} | {{:<19}}\n{'-'*80}"\ + .format(headers[0], headers[1], headers[2], headers[3])) + + for k, v in donors.items(): + summary.append([k, (sum(v)), (len(v)), (sum(v) / len(v))]) + summary.sort(key=lambda d: d[1], reverse=True) + + for x_value in summary: + print('{:17} | ${:<18,.2f} | {:<15} | ${:<16,.2f}'.format + (x_value[0], x_value[1], x_value[2], x_value[3])) + print(f"{'-'*80}\n") + + +def donor_add(current_donor): + ''' + This allows addition of new donors + ''' + donors[current_donor] = [] + while True: + try: + d_num = int(input('How many donations were made: ')) + while d_num > 0: + new_don = float(input('Enter their donation: ')) + donors[current_donor].append(new_don) + d_num -= 1 + mail_send(current_donor) + except (KeyboardInterrupt, EOFError, ValueError): + break + + +def donor_del(): + ''' + This section allows the user to delete a donor + ''' + try: + donor_list() + del_donor = str(input('Enter the name of the donor to remove: ')) + del donors[del_donor] + donor_list() + except (KeyboardInterrupt, EOFError, ValueError): + safe_input() diff --git a/students/jesse_miller/session09/mailings.py b/students/jesse_miller/session09/mailings.py index e5a0d9b4..723f223f 100644 --- a/students/jesse_miller/session09/mailings.py +++ b/students/jesse_miller/session09/mailings.py @@ -1 +1,58 @@ #!/usr/bin/env python3 + +import datetime + +MAIL = ('\nHello {}, \n' + '\n' + 'We are writing to thank you for you generous donation\n' + 'to our foundation. Your contributions for the year \n' + 'total ${:,.2f} in {} disbursements. \n' + '\n' + 'Again, the foundation thanks you for your support, \n' + 'and we hope to remain in contact with you in this new \n' + 'year.\n' + '\n' + 'Sincerely, \n' + 'Ecumenical Slobs LLC \n') + + +def mail_send(current_donor): + ''' + This function now contains both the singular and the all mails. I am + planning on rewriting it to print to terminal and mail for single or all. + ''' + path = os.getcwd() + + if current_donor in donors: + donor_math = donors[current_donor] + directory = path + '/donors/' + current_donor + '/' + filename = current_donor + ' - ' \ + + datetime.datetime.now().strftime('%s') + '.txt' + mail_format(current_donor, donor_math, directory, filename) + print('\nFile created\n') + + else: + for k in donors: + current_donor = k + donor_math = donors[current_donor] + directory = path + '/donors/' + current_donor + '/' + filename = current_donor + ' - ' \ + + datetime.datetime.now().strftime('%s') + '.txt' + mail_format(current_donor, donor_math, directory, filename) + print('\nFiles created\n') + + +def mail_format(current_donor, donor_math, directory, filename): + ''' + This is the formating for the mail print and file. This allows us to + have both files and terminal output for single donors as well as multiple + ''' + print('\n') + print(MAIL.format(current_donor, (sum(donor_math)), (len(donor_math)))) + + if not os.path.exists(directory): + os.makedirs(directory) + + with open(directory + filename, 'w+') as outfile: + outfile.write('{}\n'.format(MAIL.format(current_donor,\ + (sum(donor_math)), (len(donor_math))))) diff --git a/students/jesse_miller/session09/menus.py b/students/jesse_miller/session09/menus.py index e5a0d9b4..29eb2b51 100644 --- a/students/jesse_miller/session09/menus.py +++ b/students/jesse_miller/session09/menus.py @@ -1 +1,41 @@ #!/usr/bin/env python3 + +def goodbye(): + ''' + Gracefully exits + ''' + print('Goodbye!') + sys.exit() + + +MENU_CHOICE = {'report': donor_report, + 'send': donor_mail_choice, + 'list': donor_list, + 'delete': donor_del, + 'quit': goodbye + } + + +def safe_input(): + ''' + This will be for handling keyboard exceptions + ''' + return None + + +def donor_mail_choice(): + ''' + This section allows the user to mail a donor + ''' + current_donor = '' + donor_list() + try: + current_donor = str(input('Who would you like to mail (all for all): ')) + if current_donor in donors: + mail_send(current_donor) + elif current_donor == 'all': + mail_send(current_donor) + else: + donor_add(current_donor) + except (KeyboardInterrupt, EOFError, ValueError): + safe_input() From d2c99660b64971c869024190b51332becaa98bbd Mon Sep 17 00:00:00 2001 From: UncleanlyClericr Date: Thu, 7 Mar 2019 15:56:54 -0800 Subject: [PATCH 119/367] Starting on framework --- students/jesse_miller/session09/donors.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/students/jesse_miller/session09/donors.py b/students/jesse_miller/session09/donors.py index c3a68350..e6d2205e 100644 --- a/students/jesse_miller/session09/donors.py +++ b/students/jesse_miller/session09/donors.py @@ -1,4 +1,13 @@ #!/usr/bin/env python3 +''' +This is where we start. Building out the donor database and manipulation +Everything else in this program will be dependent on this one. +''' +class Donor(): + + def __init__(self, name): + self.name = name + self.donation = {} donors = {'Robert Smith': [435.56, 125.23, 357.10], 'JD Cronise': [123.12], From cbed41e4f7ec3c1e4e4a38255baa8786efc1e8ac Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 7 Mar 2019 18:01:29 -0800 Subject: [PATCH 120/367] html_render update --- students/jeff_shabani/session07/html_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 17374899..7ca21f97 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -78,7 +78,7 @@ def render(self, file_name, cur_indent=''): :param file_name: :param cur_indent: """ - file_name.write(f'{self._front_tag()} ') + file_name.write(f'{self._front_tag()[:-1]} ') for k, v in self.attrs.items(): file_name.write(f'{k}="{v}"') file_name.write(f'{self._front_tag()}') From 651432643270828d87e1e584c27528afbb04d245 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Thu, 7 Mar 2019 18:01:40 -0800 Subject: [PATCH 121/367] html_render update --- .../session07/test_html_render_unittest.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 students/jeff_shabani/session07/test_html_render_unittest.py diff --git a/students/jeff_shabani/session07/test_html_render_unittest.py b/students/jeff_shabani/session07/test_html_render_unittest.py new file mode 100644 index 00000000..731bb6ee --- /dev/null +++ b/students/jeff_shabani/session07/test_html_render_unittest.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import io +import unittest + +from html_render import * + +def render_result(element, ind=""): + """ + calls the element's render method, and returns what got rendered as a + string + """ + # the StringIO object is a "file-like" object -- something that + # provides the methods of a file, but keeps everything in memory + # so it can be used to test code that writes to a file, without + # having to actually write to disk. + outfile = io.StringIO() + # this so the tests will work before we tackle indentation + if ind: + element.render(outfile, ind) + else: + element.render(outfile) + return outfile.getvalue() + + +class HTMLRenderTests(unittest.TestCase): + + def test_a(self): + ca = A("http://google.com/", "link to google") + file_contents = render_result(ca) + print(file_contents) + + self.assertEqual(file_contents, f'link to google') + + +if __name__ == '__main__': + unittest.main() From 74c77f4bfa3994acdb588e74f730af6a9afb7083 Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Fri, 8 Mar 2019 08:54:42 -0800 Subject: [PATCH 122/367] html_render update --- .../jeff_shabani/session07/html_render.py | 42 +++++------- .../session07/test_html_render.py | 68 +++++++++---------- .../session07/test_html_render_unittest.py | 18 ++++- 3 files changed, 68 insertions(+), 60 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 7ca21f97..2a94ee57 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -81,7 +81,7 @@ def render(self, file_name, cur_indent=''): file_name.write(f'{self._front_tag()[:-1]} ') for k, v in self.attrs.items(): file_name.write(f'{k}="{v}"') - file_name.write(f'{self._front_tag()}') + file_name.write(f'>') file_name.write(f'{self.content[0]}') file_name.write(f'{self._end_tag()}') @@ -132,30 +132,22 @@ def __init__(self, link, content=None, **attrs): attrs['href'] = link super().__init__(content, **attrs) - # def __init__(self, link, content): - # self.link = link - # self.content = content - # #super(Element).__init__() - # - # def render(self, file_name): - # filename.write() - # head = 'a href=' - # tail = 'a' - # outtext = f'<{head}"{self.link}">{self.content}' - # with open(f'{file_name}.html', 'w') as file: - # file.write(outtext) -# -# class Ul(Element): -# """ -# Step 7: Ul class -# """ -# ul = [] -# -# class Li(Element): -# """ -# Step 7: Li class -# """ -# list_element = '' + +class Ul(Element): + """ + Step 7: Ul class + """ + tag = 'ul' + + def __init__(self, content=None, **attrs): + self.content = [] + self.attrs = attrs + +class Li(Element): + """ + Step 7: Li class + """ + list_element = '' # # diff --git a/students/jeff_shabani/session07/test_html_render.py b/students/jeff_shabani/session07/test_html_render.py index 559d69ed..a67097a5 100644 --- a/students/jeff_shabani/session07/test_html_render.py +++ b/students/jeff_shabani/session07/test_html_render.py @@ -14,22 +14,22 @@ # utility function for testing render methods # needs to be used in multiple tests, so we write it once here. -def render_result(element, ind=""): - """ - calls the element's render method, and returns what got rendered as a - string - """ - # the StringIO object is a "file-like" object -- something that - # provides the methods of a file, but keeps everything in memory - # so it can be used to test code that writes to a file, without - # having to actually write to disk. - outfile = io.StringIO() - # this so the tests will work before we tackle indentation - if ind: - element.render(outfile, ind) - else: - element.render(outfile) - return outfile.getvalue() +# def render_result(element, ind=""): +# """ +# calls the element's render method, and returns what got rendered as a +# string +# """ +# # the StringIO object is a "file-like" object -- something that +# # provides the methods of a file, but keeps everything in memory +# # so it can be used to test code that writes to a file, without +# # having to actually write to disk. +# outfile = io.StringIO() +# # this so the tests will work before we tackle indentation +# if ind: +# element.render(outfile, ind) +# else: +# element.render(outfile) +# return outfile.getvalue() ######## # Step 1 @@ -243,24 +243,24 @@ def test_class_a(): assert f'link to google' in file_contents -# def test_ul_li(): -# """ Tests that you can add unordered lists and list items """ -# with pytest.raises(TypeError): -# ul = Ul("Should fail") -# -# ul = Ul(style='list-style-type:disc;') -# ul.append(Li("List item 1")) -# ul.append(Li("List item 2")) -# -# file_contents = render_result(ul).strip() -# print(file_contents) -# -# assert file_contents.startswith("
          ") -# assert "List item 1" in file_contents -# assert "List item 2" in file_contents -# assert file_contents.count("
        • ") == 2 -# assert file_contents.count("
        • ") == 2 +def test_ul_li(): + """ Tests that you can add unordered lists and list items """ + with pytest.raises(TypeError): + ul = Ul("Should fail") + + ul = Ul(style='list-style-type:disc;') + ul.append(Li("List item 1")) + ul.append(Li("List item 2")) + + file_contents = render_result(ul).strip() + print(file_contents) + + assert file_contents.startswith("
            ") + assert "List item 1" in file_contents + assert "List item 2" in file_contents + assert file_contents.count("
          • ") == 2 + assert file_contents.count("
          • ") == 2 # ##################### # # indentation testing diff --git a/students/jeff_shabani/session07/test_html_render_unittest.py b/students/jeff_shabani/session07/test_html_render_unittest.py index 731bb6ee..a8157548 100644 --- a/students/jeff_shabani/session07/test_html_render_unittest.py +++ b/students/jeff_shabani/session07/test_html_render_unittest.py @@ -27,9 +27,25 @@ class HTMLRenderTests(unittest.TestCase): def test_a(self): ca = A("http://google.com/", "link to google") file_contents = render_result(ca) + expected = f'link to google' print(file_contents) - self.assertEqual(file_contents, f'link to google') + self.assertEqual(expected, f'link to google') + + def test_ul(self): + ul = Ul(style='list-style-type:disc;') + ul.append(Li("List item 1")) + ul.append(Li("List item 2")) + + file_contents = render_result(ul).strip() + print(file_contents) + + self.assertEqual(file_contents[:3], "") + assert f'\nList item 1\n' in file_contents + assert f'\nList item 2\n' in file_contents + + if __name__ == '__main__': From 62420bee990ba3f169e922264294517d2196bdcc Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Fri, 8 Mar 2019 09:52:03 -0800 Subject: [PATCH 123/367] html_render update --- .../jeff_shabani/session07/html_render.py | 66 ++++++++++--------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 2a94ee57..6ea6c44b 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -5,9 +5,10 @@ """ import functools + # This is the framework for the base class class Element(object): - indent = ' ' * 2 + indent = '' tag = 'html' def __init__(self, content=None, **attrs): @@ -28,15 +29,15 @@ def _end_tag(self): def append(self, new_content): self.content.append(new_content) - def render(self, file_name, cur_indent=''): + def render(self, file_name, indent='', ind_count=0): # Writes the opening tag file_name.write(f'{self._front_tag()}\n') for content_line in self.content: if hasattr(content_line, 'render'): - content_line.render(file_name) + content_line.render(file_name, indent, ind_count + 1) else: - file_name.write(f'{content_line}\n') + file_name.write(f'{self.indent}{indent}{content_line}\n') file_name.write(f'{self._end_tag()}\n') @@ -46,9 +47,10 @@ class Html(Element): """ tag = 'html' - def render(self, file_name): + def render(self, file_name, indent="", ind_count=0): + self.indent = indent file_name.write(f'\n') - super().render(file_name) + super().render(file_name, indent) class P(Element): @@ -68,17 +70,20 @@ class for p tag """ Step 3: print on one line """ -class OneLineTag(Element): + +class OneLineTag(Element): tag = 'Title' - def render(self, file_name, cur_indent=''): + def render(self, file_name, indent="", ind_count=0): """ Renders elements on a single line. - :param file_name: - :param cur_indent: + :param file_name: Rendered object destination + :param indent: Indentation level + :param ind_count: Number of times indentation is to be applied """ - file_name.write(f'{self._front_tag()[:-1]} ') + self.indent = indent * ind_count + file_name.write(f'{self.indent}{self._front_tag()[:-1]} ') for k, v in self.attrs.items(): file_name.write(f'{k}="{v}"') file_name.write(f'>') @@ -90,44 +95,47 @@ def append(self, new_content): class Head(Element): - tag = "head" - """ Step 5: Self closing tag """ + class SelfClosingTag(Element): tag = 'br' def append(self, new_content): raise NotImplementedError - def render(self, file_name): + def render(self, file_name, indent="", ind_count=0): """ if conent is entered this tells user that self closing tags can't have conent and resets the conent to an empty string. """ + self.indent = indent * ind_count + if self.content: raise TypeError - file_name.write(f'{self._front_tag()[:-1]}') + file_name.write(f'{self.indent}{self._front_tag()[:-1]}') for k, v in self.attrs.items(): file_name.write(f'{k.rjust(len(k) + 1)}="{v}" />') + """ Step 6 """ -class A(OneLineTag): +class A(OneLineTag): tag = 'a' def __init__(self, link, content=None, **attrs): - if not (content and link): raise TypeError + if not (content and link): + raise TypeError attrs['href'] = link super().__init__(content, **attrs) @@ -143,23 +151,17 @@ def __init__(self, content=None, **attrs): self.content = [] self.attrs = attrs + class Li(Element): """ Step 7: Li class """ list_element = '' -# - -# -# class Meta(SelfClosingTag): -# """ -# add meta tag -# """ -# -# def __init__(self, content=None, tag = 'meta charset="UTF-8"'): -# super().__init__(content, tag) - -# if __name__ == '__main__': -# -# olt = OneLineTag('this is william') -# olt.render(olt, 'tag') + + +class Meta(SelfClosingTag): + """ + add meta tag + """ + + tag = 'meta' From 19dd2d5a4790aaaa42ee704f6de1d337d271c533 Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Fri, 8 Mar 2019 10:10:15 -0800 Subject: [PATCH 124/367] updated Circle file --- students/shirin_ak/Session08/Circle.py | 42 +++++++++++++++++++------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/students/shirin_ak/Session08/Circle.py b/students/shirin_ak/Session08/Circle.py index 8fa6a7bd..f80044d6 100644 --- a/students/shirin_ak/Session08/Circle.py +++ b/students/shirin_ak/Session08/Circle.py @@ -1,9 +1,11 @@ import math + class Circle(): def __init__(self, radius): # STEP 1 The radius is a required parameter self.radius = radius + # STEP 2 Add a 'diameter' property @property def diameter(self): @@ -12,7 +14,7 @@ def diameter(self): #STEP 3 set up the diameter property @diameter.setter def diameter(self, value): - self.diameter = value + # self.diameter = value self.radius = value/2 #STEP 4 Add an area property @@ -23,23 +25,41 @@ def area(self): # STEP 5 Add an “alternate constructor” that #lets the user create a Circle directly with the diameter: @classmethod - def from_diameter(class_object, diameter): - radius = diameter/2 - return class_object(radius) + def from_diameter(cls, diameter): + return cls(diameter/2) #STEP 6 Add __str__ and __repr__ methods to your Circle class. def __str__(self): - return "Circle with radius: {:.6f}".format(self.radius) + return "Circle with radius: {:.4f}".format(self.radius) def __repr__(self): - return "Circle({r})".format(r=self.radius) + return "Circle({})".format(self.radius) + + #STEP 7 Add two circles and multiply one by a number - def ___add__(self, other): - c1 = self.radius - c2 = other.radius - return Circle(c1+c2) -# def __mul__(self, other): + def __add__(self, other): + + return Circle(self.radius + other.radius) + + def __mul__(self, other): + return Circle(self.radius * other) + + #STEP 8 Add the ability to compare two circles + #Once the comparing is done, you should be able to sort a list of circles + def __greater__(self, other): + return self.radius > other.radius + + def __less__(self, other): + return self.radius < other.radius + + def __equal__(self, other): + return self.radius == other.radius + + def sort_key(self): + return self.radius + + From b86af91a06da7a129bd22be828304201f0410791 Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Fri, 8 Mar 2019 10:16:11 -0800 Subject: [PATCH 125/367] updated test_Circle file --- students/shirin_ak/Session08/test_Circle.py | 58 ++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/students/shirin_ak/Session08/test_Circle.py b/students/shirin_ak/Session08/test_Circle.py index 655c8287..98edc122 100644 --- a/students/shirin_ak/Session08/test_Circle.py +++ b/students/shirin_ak/Session08/test_Circle.py @@ -4,10 +4,12 @@ def test_radius(): + """Test that the radius is the radius""" c = Circle(4) assert c.radius == 4 -def test_diameter(): +def test_diameter(): + """ test that diameter is calculated correctly""" c = Circle(4) assert c.diameter == 8 @@ -19,11 +21,65 @@ def test_set_diameter(): assert c.radius == 5 def test_area(): + """test that area gets calculated properly""" c = Circle(1) assert c.area == 3.141592653589793 def test_constructor(): + """Test that the alternate constructor of from_diameter() works""" + c = Circle.from_diameter(4) assert c.diameter == 4 assert c.radius == 2 + +def test_str(): + """Test that a Circle class object prints the string""" + c = Circle(4) + s = str(c) + assert s == "Circle with radius: 4.0000" + +def test_repr(): + c = Circle(4) + d = repr(c) + assert d == 'Circle(4)' + +def test_add(): + """ + Testing that adding two Circle classes together yields a + Circle class with sums of their radius + """ + c1 = Circle(2) + c2 = Circle(4) + print(c1 + c2) + assert(c1+c2) == Circle(6) + +def test_mul(): + c1 = Circle(4) + assert (c1 * 3) == Circle(12) + +def test_less(): + """ Test that the Circles can be compared with less than statement""" + c1 = Circle(3) + c2 = Circle(5) + assert c1.radius < c2.radius + + +def test_greater(): + """ Test that the Circles can be compared with greater than statement""" + c1 = Circle(5) + c2 = Circle(3) + assert c1.radius > c2.radius + +def test_equal(): + """Test that the Circles can be compared with equal statement""" + c1 = Circle(6) + c2 = Circle(6) + assert c1.radius == c2.radius + + +def test_sort_key(): + circles = [Circle(6), Circle(8), Circle(7), Circle(4), Circle(0), Circle(2)] + circles.sort() + assert circles == [Circle(0), Circle(2), Circle(4), Circle(6), Circle(7), Circle(8)] + From ed692764c36ae05aa3c2e7a84104d772e783b3ce Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Fri, 8 Mar 2019 10:25:25 -0800 Subject: [PATCH 126/367] sparse_array --- students/jeff_shabani/session08/sparse_array.py | 13 +++++++++++++ .../jeff_shabani/session08/test_sparse_array.py | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 students/jeff_shabani/session08/sparse_array.py create mode 100644 students/jeff_shabani/session08/test_sparse_array.py diff --git a/students/jeff_shabani/session08/sparse_array.py b/students/jeff_shabani/session08/sparse_array.py new file mode 100644 index 00000000..f11ffebf --- /dev/null +++ b/students/jeff_shabani/session08/sparse_array.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +class SparseArray(object): + + def __init__(self, sequence): + self.sequence = sequence + + def __repr__(self): + return f'{self.sequence}' + +spa = SparseArray([1,2,3]) + +print(spa) diff --git a/students/jeff_shabani/session08/test_sparse_array.py b/students/jeff_shabani/session08/test_sparse_array.py new file mode 100644 index 00000000..d3fb7311 --- /dev/null +++ b/students/jeff_shabani/session08/test_sparse_array.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import unittest + +from sparse_array import * + +class SparseArrayTest(unittest.TestCase): + + def test_init(self): + spa = SparseArray([1, 2, 3]) + self.assertEqual(repr(spa), '[1, 2, 3]') + + +if __name__ == '__main__': + unittest.main() From 75638bd6b860ab75361ea1a1ef316f35ae42b5ed Mon Sep 17 00:00:00 2001 From: dac2229 Date: Fri, 8 Mar 2019 14:43:55 -0800 Subject: [PATCH 127/367] start of lesson 08 --- students/daniel_carrasco/session08/circle.py | 10 +++++++ .../daniel_carrasco/session08/test_circle.py | 27 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 students/daniel_carrasco/session08/circle.py create mode 100644 students/daniel_carrasco/session08/test_circle.py diff --git a/students/daniel_carrasco/session08/circle.py b/students/daniel_carrasco/session08/circle.py new file mode 100644 index 00000000..00494d6a --- /dev/null +++ b/students/daniel_carrasco/session08/circle.py @@ -0,0 +1,10 @@ +class Circle(): + + def __init__(self,the_radius): + self.radius = the_radius + self.diameter = self.radius*2 + + +c = Circle(4) +print(c.radius) +print(c.diameter) \ No newline at end of file diff --git a/students/daniel_carrasco/session08/test_circle.py b/students/daniel_carrasco/session08/test_circle.py new file mode 100644 index 00000000..e665754d --- /dev/null +++ b/students/daniel_carrasco/session08/test_circle.py @@ -0,0 +1,27 @@ +import io +import pytest + +from circle import * + +def test_init(): + """ + This only tests that it can be initialized with and without + some content -- but it's a start + """ + c = Circle(4) + + +def test_radius(): + + "check to see if it outputs correct radius" + c = Circle(5) + # making sure radius outputs correctly. + assert c.radius == 5 + +def test_diameter(): + + "check to see if it outputs correct radius" + c = Circle(5) + # making sure radius outputs correctly. + assert c.diameter == 10 + assert c.diameter == c.radius*2 \ No newline at end of file From 757a1e09f2fc9080eca0422bf2ae83b7a8ddb4e8 Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Fri, 8 Mar 2019 18:57:17 -0800 Subject: [PATCH 128/367] session 7 --- .../session07/test_html_render.py | 186 +++++++++--------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/students/jeff_shabani/session07/test_html_render.py b/students/jeff_shabani/session07/test_html_render.py index 9f6bc769..235bdb8e 100644 --- a/students/jeff_shabani/session07/test_html_render.py +++ b/students/jeff_shabani/session07/test_html_render.py @@ -55,123 +55,123 @@ def test_append(): e.append("some more text") -# def test_render_element(): -# """ -# Tests whether the Element can render two pieces of text -# So it is also testing that the append method works correctly. -# -# It is not testing whether indentation or line feeds are correct. -# """ -# e = Element("this is some text") -# e.append("and this is some more text") -# -# # This uses the render_results utility above -# file_contents = render_result(e).strip() -# -# # making sure the content got in there. -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# # make sure it's in the right order -# assert file_contents.index("this is") < file_contents.index("and this") -# -# # making sure the opening and closing tags are right. -# assert file_contents.startswith("") -# assert file_contents.endswith("") +def test_render_element(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. -# # Uncomment this one after you get the one above to pass -# # Does it pass right away? -# def test_render_element2(): -# """ -# Tests whether the Element can render two pieces of text -# So it is also testing that the append method works correctly. + It is not testing whether indentation or line feeds are correct. + """ + e = Element("this is some text") + e.append("and this is some more text") -# It is not testing whether indentation or line feeds are correct. -# """ -# e = Element() -# e.append("this is some text") -# e.append("and this is some more text") + # This uses the render_results utility above + file_contents = render_result(e).strip() -# # This uses the render_results utility above -# file_contents = render_result(e).strip() + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents -# # making sure the content got in there. -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") -# # make sure it's in the right order -# assert file_contents.index("this is") < file_contents.index("and this") + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") -# # making sure the opening and closing tags are right. -# assert file_contents.startswith("") -# assert file_contents.endswith("") +# Uncomment this one after you get the one above to pass +# Does it pass right away? +def test_render_element2(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + It is not testing whether indentation or line feeds are correct. + """ + e = Element() + e.append("this is some text") + e.append("and this is some more text") + # This uses the render_results utility above + file_contents = render_result(e).strip() -# # ######## -# # # Step 2 -# # ######## + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents -# # tests for the new tags -# def test_html(): -# e = Html("this is some text") -# e.append("and this is some more text") + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") -# file_contents = render_result(e).strip() + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# print(file_contents) -# assert file_contents.endswith("") -# def test_body(): -# e = Body("this is some text") -# e.append("and this is some more text") +# ######## +# # Step 2 +# ######## -# file_contents = render_result(e).strip() +# tests for the new tags +def test_html(): + e = Html("this is some text") + e.append("and this is some more text") -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents + file_contents = render_result(e).strip() -# assert file_contents.startswith("") -# assert file_contents.endswith("") + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + print(file_contents) + assert file_contents.endswith("") -# def test_p(): -# e = P("this is some text") -# e.append("and this is some more text") +def test_body(): + e = Body("this is some text") + e.append("and this is some more text") -# file_contents = render_result(e).strip() + file_contents = render_result(e).strip() -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents -# assert file_contents.startswith("

            ") -# assert file_contents.endswith("

            ") + assert file_contents.startswith("") + assert file_contents.endswith("") -# def test_sub_element(): -# """ -# tests that you can add another element and still render properly -# """ -# page = Html() -# page.append("some plain text.") -# page.append(P("A simple paragraph of text")) -# page.append("Some more plain text.") - -# file_contents = render_result(page) -# print(file_contents) # so we can see it if the test fails - -# # note: The previous tests should make sure that the tags are getting -# # properly rendered, so we don't need to test that here. -# assert "some plain text" in file_contents -# assert "A simple paragraph of text" in file_contents -# assert "Some more plain text." in file_contents -# assert "some plain text" in file_contents -# # but make sure the embedded element's tags get rendered! -# assert "

            " in file_contents -# assert "

            " in file_contents +def test_p(): + e = P("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("

            ") + assert file_contents.endswith("

            ") + + +def test_sub_element(): + """ + tests that you can add another element and still render properly + """ + page = Html() + page.append("some plain text.") + page.append(P("A simple paragraph of text")) + page.append("Some more plain text.") + + file_contents = render_result(page) + print(file_contents) # so we can see it if the test fails + + # note: The previous tests should make sure that the tags are getting + # properly rendered, so we don't need to test that here. + assert "some plain text" in file_contents + assert "A simple paragraph of text" in file_contents + assert "Some more plain text." in file_contents + assert "some plain text" in file_contents + # but make sure the embedded element's tags get rendered! + assert "

            " in file_contents + assert "

            " in file_contents From 86922c05d64c4ba0e97ee5c17c9fdb20f684c097 Mon Sep 17 00:00:00 2001 From: dac2229 Date: Sat, 9 Mar 2019 00:35:25 -0800 Subject: [PATCH 129/367] up to subclass --- students/daniel_carrasco/session08/circle.py | 86 +++++++++++++++++-- .../daniel_carrasco/session08/test_circle.py | 7 +- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/students/daniel_carrasco/session08/circle.py b/students/daniel_carrasco/session08/circle.py index 00494d6a..7a59bf4b 100644 --- a/students/daniel_carrasco/session08/circle.py +++ b/students/daniel_carrasco/session08/circle.py @@ -1,10 +1,84 @@ -class Circle(): - +import math +class Circle: + pi = math.pi def __init__(self,the_radius): self.radius = the_radius - self.diameter = self.radius*2 + + @property + def diameter(self): + return self.radius*2 + + @diameter.setter + def diameter(self, diameter): + self.radius = diameter/2 + + @property + def area(self): + return self.pi*(self.radius)**2 + + @area.setter + def area(self, diameter): + if input: + print('Attribute Error') # How do I do this correctly + + @classmethod + def from_diameter(cls, diameter): + return Circle(diameter/2) + + def __str__(self): + return f'circle with a radius of {self.radius}' + + def __repr__(self): + return (f'{self.__class__.__name__}(' + f'{self.radius!r})') + + def __add__(self, c2): + print(f'Summing {self} + {c2}') + print(c2.radius) + return Circle(self.radius+c2.radius) + + def __mul__(self, other): + return Circle(self.radius*other) + + def __rmul__(self, other): + return Circle(self.radius*other) + + def __iadd__(self, other): + return Circle(self.radius+other) + def __imul__(self, other): + return Circle(self.radius*other) + + def __lt__(self, other): + if self.radius < other.radius:return True + else: return False + def __le__(self, other): + if self.radius <= other.radius:return True + else: return False + def __eq__(self, other): + if self.radius == other.radius:return True + else: return False + def __ne__(self, other): + if self.radius != other.radius:return True + else: return False + def __gt__(self, other): + if self.radius > other.radius:return True + else: return False + def __ge__(self, other): + if self.radius >= other.radius:return True + else: return False + -c = Circle(4) -print(c.radius) -print(c.diameter) \ No newline at end of file +c1 = Circle(2) +c2 = Circle(2) +a = c1 + c2 +print(a) +print(c1 == c2) +circles =[Circle(6), Circle(7), Circle(8), Circle(4), Circle(0), Circle(2), Circle(3), Circle(5), Circle(9), Circle(1)] +circles.sort() +print(circles) +b = Circle(5) +b+=1 +print(b) +b*=2 +print(b) \ No newline at end of file diff --git a/students/daniel_carrasco/session08/test_circle.py b/students/daniel_carrasco/session08/test_circle.py index e665754d..58f2d666 100644 --- a/students/daniel_carrasco/session08/test_circle.py +++ b/students/daniel_carrasco/session08/test_circle.py @@ -20,8 +20,11 @@ def test_radius(): def test_diameter(): - "check to see if it outputs correct radius" + "check to see if it outputs correct diameter" c = Circle(5) # making sure radius outputs correctly. assert c.diameter == 10 - assert c.diameter == c.radius*2 \ No newline at end of file + assert c.diameter == c.radius*2 + c.diameter = 6 + assert c.radius == 3 + assert c.diameter == 6 From ce291b8eba1c1191e19517591622012d0d7335ef Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sat, 9 Mar 2019 09:01:51 -0800 Subject: [PATCH 130/367] circle updates --- students/jeff_shabani/session08/Circle.py | 99 +++++++++++++++- .../jeff_shabani/session08/test_circle.py | 109 +++++++++++++++--- 2 files changed, 185 insertions(+), 23 deletions(-) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/Circle.py index 02c9a178..ab02d15c 100644 --- a/students/jeff_shabani/session08/Circle.py +++ b/students/jeff_shabani/session08/Circle.py @@ -1,16 +1,103 @@ +#!/usr/bin/env python3 +import math - +""" +Framework for a circular object. +Validation prevents user from entering a +negative radius value. +""" class Circle(object): + instances = [] + def __init__(self, radius): - self.radius = radius + if radius < 0: + raise ValueError('Radius cannot be less than zero') + else: + self.radius = radius + self._radius = radius + Circle.instances.append(self) + + @property + def diameter(self): + return self.radius * 2 + + @diameter.setter + def diameter(self, value): + self.radius = value / 2 + + # make area non-settable + @property + def area(self): + return math.pi * pow(self.radius, 2) + + # method to create a circle with the diameter + @classmethod + def from_diameter(cls, value): + radius = value / 2 + return cls(radius) + + # simple add method + def __add__(self, other): + return self.radius + other.radius + + # augmented assignment add method + def __iadd__(self, other): + return self.radius + other.radius + + # augmented assigment exponential method + def __ipow__(self, other): + return self.radius ** other + + # multiplication method + def __mul__(self, other): + return self.radius * other + + # allow for reversal of arguments + __rmul__ = __mul__ + + # less than comparison + def __lt__(self, other): + return self.radius < other.radius + + # greater than comparison + def __gt__(self, other): + return self.radius > other.radius + + # equality method + def __eq__(self, other): + return self.radius == other.radius + + # non-equality method + def __ne__(self, other): + return self.radius != other.radius def __repr__(self): - return f'The radius is {self.radius}' + return f'Circle with radius of {self.radius}' + + def __str__(self): + return f'Circle with radius of {self.radius}' -if __name__ =='__main__': - c = Circle(5) - print(c) \ No newline at end of file +class Sphere(Circle): + """ + Sublclass of Circle + """ + + # override Circle volume method + def volume(self): + return (4 / 3) * math.pi * (self.radius ** 3) + + # override Circle area method + def area(self): + return 4 * math.pi * (self.radius ** 2) + + def __repr__(self): + return f'Sphere with radius of {self.radius} volume of ' \ + f'{self.volume()} & surface area of {self.area()}' + + def __str__(self): + return f'Sphere with radius of {self.radius} volume of ' \ + f'{self.volume()} & surface area of {self.area()}' diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index ef3f53d5..f10fa0d7 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -1,24 +1,99 @@ #!/usr/bin/env python3 - -import io -import pytest import unittest -from Circle import * +from circle import * + + +class CircleTests(unittest.TestCase): + + def test_init(self): + """test for instantiation""" + c = Circle(5) + self.assertEqual(c.radius, 5) + del c + + def test_diameter_calc(self): + c = Circle(4) + self.assertEqual(c.diameter, c.radius * 2) + del c + + def test_diameter_setter(self): + c = Circle(5) + self.assertEqual(c.diameter, 10) + c.diameter = 24 + self.assertEqual(c.diameter, 24) + self.assertEqual(c.radius, 12) + del c + + def test_area(self): + c = Circle(5) + self.assertEqual(c.area, math.pi * pow(c.radius, 2)) + del c + + def test_from_diameter(self): + c = Circle.from_diameter(6) + self.assertEqual(c.radius, 3) + self.assertEqual(c.diameter, 6) + del c + + def test_print(self): + c = Circle(8) + self.assertEqual(repr(c), 'Circle with radius of 8') + del c + + def test_math(self): + c1 = Circle(2) + c2 = Circle(3) + self.assertEqual(c1 + c2, 5.0) + self.assertEqual(c1 * 5, 10.0) + # this tests argument reversal in mult function + self.assertEqual(5 * c1, 10.0) + del c1, c2 + + def test_compare_circles(self): + c1 = Circle(2) + c2 = Circle(3) + c3 = Circle(3) + self.assertEqual(c1 > c2, False) + self.assertEqual(c1 < c2, True) + self.assertEqual(c1 != c2, True) + self.assertEqual(c3 == c2, True) + self.assertEqual(c1 * c2, 6.0) + self.assertEqual(c1 * 10, 20) + self.assertEqual(c1 * 10 == 10 * c1, True) + del c1, c2, c3 + + def test_extended_assignment(self): + c1 = Circle(12) + c2 = Circle(10) + c2 += c1 + c3 = c1.radius ** 2 + self.assertEqual(c2, 22) + self.assertEqual(c3, 144) + del c1, c2, c3 + + # test for negative radius + @unittest.expectedFailure + def test_negative_radius(self): + c1 = Circle(-1) + self.assertEqual(c1, -1) + del c1 + + def test_sphere_volume(self): + s = Sphere(1) + self.assertEqual(s.volume(), 4.1887902047863905) + del s + def test_sphere_get_from_diameter(self): + s = Sphere.from_diameter(4) + self.assertEqual(s.volume(), 33.510321638291124) + del s -def test_init(): - c = Circle(5) + def test_sphere_printing(self): + s = Sphere(10) + self.assertEqual(repr(s), + 'Sphere with radius of 10 volume of 4188.790204786391 & surface area of 1256.6370614359173') - assert print(c) == 6, 'Not equal' -# c = Circle(8) -# print(c.radius) -# class mailroomTests(unittest.TestCase): -# -# def test_init(self): -# c=Circle(5) -# self.assertEqual(print(c.radius), 5) -# -# if __name__ == '__main__': -# unittest.main() \ No newline at end of file +if __name__ == '__main__': + unittest.main() From 0b269ba66223f588f57ae210ee3d1a0b7840b29d Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sat, 9 Mar 2019 11:05:52 -0800 Subject: [PATCH 131/367] sparse_array updates --- .../jeff_shabani/session08/sparse_array.py | 58 ++++++++++++++----- .../session08/test_sparse_array.py | 15 ++++- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/students/jeff_shabani/session08/sparse_array.py b/students/jeff_shabani/session08/sparse_array.py index 74d48004..51af5697 100644 --- a/students/jeff_shabani/session08/sparse_array.py +++ b/students/jeff_shabani/session08/sparse_array.py @@ -2,30 +2,62 @@ class SparseArray(object): - def __init__(self, sequence, *seq_dict): + def __init__(self, sequence=None): + if sequence is None: + self.sequence = [] self.sequence = sequence - self.seq_dict = dict(seq_dict) - - def dict_convert(self): - #seq_dict = dict() - for k,v in enumerate(self.sequence): - self.seq_dict[k]=v - return self.seq_dict + self.display_list = [i for i in self.sequence if i >0] + self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + def create_dictionary(self): + self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} def __len__(self): return len(self.sequence) + def append(self, val): + if val == 0: + return self.sequence + self.sequence.append(val) + + self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + + + def __delitem__(self, key): + del (self.working_dict[key]) + self.sequence.pop(key) + + def __getitem__(self, item): + if item not in self.working_dict.keys(): + return 0 + else: + return self.working_dict[item] + def __setitem__(self, key, value): self.sequence[key] = value + def __contains__(self, item): + if self.sequence: + return True def __repr__(self): - return f'{self.seq_dict.values()} has a length of {len(self.sequence)}' + return f'{self.sequence} has a length of {len(self.sequence)}' + + +if __name__ == '__main__': + + spa = SparseArray([1, 0, 2, 3]) + print(spa) + print(len(spa)) -spa = SparseArray([1,2,3]) + spa.append(10) + print(spa) -print(len(spa)) + print(spa[2]) + del(spa[4]) + print(spa) -spa[1] = 2 -print(spa) + # spa[5]=10 + # print(spa) + # print(type(spa)) + # print(10 in spa) diff --git a/students/jeff_shabani/session08/test_sparse_array.py b/students/jeff_shabani/session08/test_sparse_array.py index d3fb7311..61c7e1ca 100644 --- a/students/jeff_shabani/session08/test_sparse_array.py +++ b/students/jeff_shabani/session08/test_sparse_array.py @@ -8,7 +8,20 @@ class SparseArrayTest(unittest.TestCase): def test_init(self): spa = SparseArray([1, 2, 3]) - self.assertEqual(repr(spa), '[1, 2, 3]') + self.assertEqual(repr(spa), '{0: 1, 1: 2, 2: 3} has a length of 3') + self.assertIsInstance(spa, SparseArray) + del spa + + def test_length(self): + spa = SparseArray([1,2,3,4]) + self.assertEqual(len(spa), 4) + del spa + + def test_append(self): + spa = SparseArray([1, 2, 3, 4]) + spa[4]=10 + self.assertIn(10, spa) + if __name__ == '__main__': From 0dd1cdbf7d3f93c748c484fb3711659a3b4aede0 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Sat, 9 Mar 2019 17:51:48 -0800 Subject: [PATCH 132/367] circle update --- students/jeff_shabani/session08/{Circle.py => circle.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename students/jeff_shabani/session08/{Circle.py => circle.py} (100%) diff --git a/students/jeff_shabani/session08/Circle.py b/students/jeff_shabani/session08/circle.py similarity index 100% rename from students/jeff_shabani/session08/Circle.py rename to students/jeff_shabani/session08/circle.py From cb01ac72a7a3241a26f157ed0d9289e8b3149fc9 Mon Sep 17 00:00:00 2001 From: admin <23247076+Rockwell70@users.noreply.github.com> Date: Sat, 9 Mar 2019 18:03:35 -0800 Subject: [PATCH 133/367] circle update --- students/jeff_shabani/session08/circle.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/students/jeff_shabani/session08/circle.py b/students/jeff_shabani/session08/circle.py index ab02d15c..0f3dd15c 100644 --- a/students/jeff_shabani/session08/circle.py +++ b/students/jeff_shabani/session08/circle.py @@ -101,3 +101,9 @@ def __repr__(self): def __str__(self): return f'Sphere with radius of {self.radius} volume of ' \ f'{self.volume()} & surface area of {self.area()}' + +if __name__=='__main__': + ins = [Circle(10), Circle(11), Circle(9)] + ins = sorted(ins) + for i in sorted(ins, reverse=True): + print(i) From e8f81dc82d41c534b0ce2a8a695f9cad4e24cd32 Mon Sep 17 00:00:00 2001 From: sdlipp Date: Sat, 9 Mar 2019 18:27:54 -0800 Subject: [PATCH 134/367] Assignment 8 files --- students/ScottL/session08/circle_class.py | 84 ++++++++++++++++++ .../ScottL/session08/test_circle_class.py | 86 +++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 students/ScottL/session08/circle_class.py create mode 100644 students/ScottL/session08/test_circle_class.py diff --git a/students/ScottL/session08/circle_class.py b/students/ScottL/session08/circle_class.py new file mode 100644 index 00000000..5a36b2ce --- /dev/null +++ b/students/ScottL/session08/circle_class.py @@ -0,0 +1,84 @@ + +""" +Homework 8 - Circle Class +Use objects and their associated methods for characterizing circles and spheres. +""" + +import math + + +class Circle: + """Define and quantify properties for circles with a given radius""" + + def __init__(self, radius): + self.radius = radius + + @property + def diameter(self): + """Return the diameter calculated from the radius property.""" + return self.radius * 2 + + @diameter.setter + def diameter(self, value): + self.radius = value / 2 + + @property + def area(self): + """Return the area of a circle calculated from the radius property.""" + return math.pi * self.radius ** 2 + + @classmethod + def from_diameter(cls, diameter): + """Define the object and its radius based an input for the diameter.""" + return cls(diameter / 2) + + def __str__(self): + return f"Circle with a radius of: {self.radius}" + + def __repr__(self): + return f"Circle({self.radius})" + + def __add__(self, other): + return f"Circle({self.radius + other.radius})" + + def __mul__(self, other): + return f"Circle({self.radius * other})" + + __rmul__ = __mul__ + + def __lt__(self, other): + return self.radius < other.radius + + def __gt__(self, other): + return self.radius > other.radius + + def __eq__(self, other): + return self.radius == other.radius + + +class Sphere(Circle): + """Define and calculate member of the sphere class based on the circle class""" + + @property + def volume(self): + """Return the volume of a sphere calculated from the radius property.""" + return 4 / 3 * math.pi * self.radius ** 3 + + @property + def area(self): + """Return the surface area of a sphere calculated from the radius property""" + return 4 * math.pi * self.radius ** 2 + + def __str__(self): + return f"Sphere with a radius of: {self.radius}" + + def __repr__(self): + return f"Sphere({self.radius})" + + def __add__(self, other): + return f"Sphere({self.radius + other.radius})" + + def __mul__(self, other): + return f"Sphere({self.radius * other})" + + __rmul__ = __mul__ diff --git a/students/ScottL/session08/test_circle_class.py b/students/ScottL/session08/test_circle_class.py new file mode 100644 index 00000000..4442c438 --- /dev/null +++ b/students/ScottL/session08/test_circle_class.py @@ -0,0 +1,86 @@ + +import circle_class + + +def test_radius(): + cir1 = circle_class.Circle(5) + cir2 = circle_class.Circle(3.5) + assert isinstance(cir1.radius, int) + assert isinstance(cir2.radius, float) + + +def test_diameter(): + cir1 = circle_class.Circle(5) + cir1.diameter = 20 + assert cir1.radius == 20 / 2 + assert cir1.diameter == 20 + + +def test_area(): + cir1 = circle_class.Circle(10) + assert round(cir1.area, 1) == round(3.1415 * 10 ** 2, 1) + + +def test_alt_constructor(): + cir1 = circle_class.Circle.from_diameter(10) + assert cir1.diameter == 10 + + +def test_string(): + cir1 = circle_class.Circle(4) + assert cir1.__str__() == "Circle with a radius of: 4" + + +def test_repr(): + cir1 = circle_class.Circle(5) + assert cir1.__repr__() == "Circle(5)" + + +def test_add(): + cir1 = circle_class.Circle(3) + cir2 = circle_class.Circle(4) + assert cir1 + cir2 == "Circle(7)" + + +def test_multiply(): + cir1 = circle_class.Circle(4) + assert cir1 * 2 == "Circle(8)" + assert 2 * cir1 == "Circle(8)" + + +def test_less(): + cir1 = circle_class.Circle(1) + cir2 = circle_class.Circle(2) + assert cir1 < cir2 + + +def test_more(): + cir4 = circle_class.Circle(4) + cir3 = circle_class.Circle(3) + assert cir4 > cir3 + + +def test_equal(): + cir1 = circle_class.Circle(1) + cir2 = circle_class.Circle(1) + assert cir1 == cir2 + + +def test_sort(): + list_circ = [circle_class.Circle(i) for i in range(3, 0, -1)] + assert str(sorted(list_circ)) == "[Circle(1), Circle(2), Circle(3)]" + + +def test_sphere(): + sph1 = circle_class.Sphere(3) + sph2 = circle_class.Sphere(4) + assert sph1.radius == 3 + assert round(sph1.volume, 1) == round(4 / 3 * 3.1415 * 3 ** 3, 1) + assert round(sph1.area, 1) == round(4 * 3.1415 * 3 ** 2, 1) + assert sph1.__str__() == "Sphere with a radius of: 3" + assert sph1.__repr__() == "Sphere(3)" + assert sph1 + sph2 == "Sphere(7)" + assert sph1 * 2 == "Sphere(6)" + assert 4 * sph1 == "Sphere(12)" + assert sph1 < sph2 + assert sph2 > sph1 From ea4f660e065e7180153e9f3cd1b83aab5173e157 Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Sat, 9 Mar 2019 20:54:57 -0800 Subject: [PATCH 135/367] updated Circle file --- students/shirin_ak/Session08/Circle.py | 53 ++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/students/shirin_ak/Session08/Circle.py b/students/shirin_ak/Session08/Circle.py index f80044d6..7a540097 100644 --- a/students/shirin_ak/Session08/Circle.py +++ b/students/shirin_ak/Session08/Circle.py @@ -1,32 +1,41 @@ +#------------------- +#!/usr/bin/env python3 +#Session 08 Exercise:Circle class +#Shirin Akther +#------------------------- import math class Circle(): def __init__(self, radius): # STEP 1 The radius is a required parameter self.radius = radius + # STEP 2 Add a 'diameter' property @property def diameter(self): return self.radius*2 + #STEP 3 set up the diameter property @diameter.setter def diameter(self, value): - # self.diameter = value self.radius = value/2 + #STEP 4 Add an area property @property def area(self): return math.pi * (self.radius ** 2) + # STEP 5 Add an “alternate constructor” that #lets the user create a Circle directly with the diameter: @classmethod def from_diameter(cls, diameter): return cls(diameter/2) + #STEP 6 Add __str__ and __repr__ methods to your Circle class. @@ -35,16 +44,20 @@ def __str__(self): def __repr__(self): return "Circle({})".format(self.radius) - + #STEP 7 Add two circles and multiply one by a number def __add__(self, other): - return Circle(self.radius + other.radius) + return self.radius + other.radius def __mul__(self, other): - return Circle(self.radius * other) - + return self.radius * other + + def __rmul__(self, other): + return self.radius * other + + #STEP 8 Add the ability to compare two circles #Once the comparing is done, you should be able to sort a list of circles def __greater__(self, other): @@ -56,9 +69,35 @@ def __less__(self, other): def __equal__(self, other): return self.radius == other.radius - def sort_key(self): - return self.radius + def sort_val(self): + return self.radius + + +#STEP 9 Add a Sphere class as a subclass of Circle class +#and add and change a couple things +class Sphere(Circle): + + """ Sphere class, inherits from Circle class """ + def __str__(self): + return "Sphere with radius: {:.2f}".format(self.radius) + + + def __repr__(self): + + return "Sphere({})".format(self.radius) + + + @property + def area(self): + + """ Returns the area of the sphere """ + return 4 * math.pi * (self.radius ** 2) + @property + def volume(self): + + """ Returns the Volume of the sphere """ + return (4/3) * math.pi * (self.radius ** 3) From b6c24c34d224229e584b0838cf6d42e0f6265f3e Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Sat, 9 Mar 2019 20:56:55 -0800 Subject: [PATCH 136/367] updated two files --- students/shirin_ak/Session08/test_Circle.py | 77 ++++++++++++++++----- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/students/shirin_ak/Session08/test_Circle.py b/students/shirin_ak/Session08/test_Circle.py index 98edc122..9879dc39 100644 --- a/students/shirin_ak/Session08/test_Circle.py +++ b/students/shirin_ak/Session08/test_Circle.py @@ -1,12 +1,13 @@ import pytest - -from Circle import Circle +import math +from Circle import Circle, Sphere def test_radius(): """Test that the radius is the radius""" c = Circle(4) assert c.radius == 4 + def test_diameter(): """ test that diameter is calculated correctly""" @@ -20,30 +21,33 @@ def test_set_diameter(): assert c.diameter == 10 assert c.radius == 5 + def test_area(): """test that area gets calculated properly""" - c = Circle(1) - - assert c.area == 3.141592653589793 + c = Circle(2) + assert c.area == math.pi * (2 ** 2) + def test_constructor(): - """Test that the alternate constructor of from_diameter() works""" - + """Test that the alternate constructor of from_diameter() works""" c = Circle.from_diameter(4) assert c.diameter == 4 assert c.radius == 2 + def test_str(): """Test that a Circle class object prints the string""" c = Circle(4) - s = str(c) - assert s == "Circle with radius: 4.0000" + result = str(c) + assert result == "Circle with radius: 4.0000" + def test_repr(): c = Circle(4) d = repr(c) assert d == 'Circle(4)' + def test_add(): """ Testing that adding two Circle classes together yields a @@ -52,34 +56,75 @@ def test_add(): c1 = Circle(2) c2 = Circle(4) print(c1 + c2) - assert(c1+c2) == Circle(6) + assert(c1.radius+c2.radius) == 6 + def test_mul(): c1 = Circle(4) - assert (c1 * 3) == Circle(12) + assert (c1 * 3) == 12 + + +def test_rmul(): + c1 = Circle(4) + assert 3 * c1 == 12 + def test_less(): """ Test that the Circles can be compared with less than statement""" c1 = Circle(3) c2 = Circle(5) assert c1.radius < c2.radius + - def test_greater(): """ Test that the Circles can be compared with greater than statement""" c1 = Circle(5) c2 = Circle(3) assert c1.radius > c2.radius + def test_equal(): """Test that the Circles can be compared with equal statement""" c1 = Circle(6) c2 = Circle(6) assert c1.radius == c2.radius + + +def test_sort_val(): + """test list of circles is sorted""" + circle1= Circle(10) + circle2 = Circle(5) + circle3 = Circle(2) + circle4 = Circle(7) + circles_list = [circle1.radius, circle2.radius, circle3.radius, circle4.radius] + circles_list.sort() + assert circles_list == [2,5,7,10] + +# Test the Sphere class +def test_sphere_str(): + """ Tests that __str__ is working """ + s = Sphere(4) + sphere1 = str(s) + assert sphere1 == "Sphere with radius: 4.00" -def test_sort_key(): - circles = [Circle(6), Circle(8), Circle(7), Circle(4), Circle(0), Circle(2)] - circles.sort() - assert circles == [Circle(0), Circle(2), Circle(4), Circle(6), Circle(7), Circle(8)] +def test_sphere_repr(): + """ Tests that __repr__ is working """ + s = Sphere(4) + sphere1 = repr(s) + assert sphere1 == 'Sphere(4)' + + +def test_sphere_area(): + """ Tests that the area of the sphere is calculated correctly """ + sphere1 = Sphere(10) + assert sphere1.area == 4 * math.pi * 10 ** 2 + + +def test_sphere_volume(): + """ Tests that the volume of the sphere is calculated correctly """ + sphere1 = Sphere(10) + assert sphere1.volume == (4/3) * math.pi * 10 ** 3 + + From c4fa4e7371e13e82c3dbc389deb47696e22c5d52 Mon Sep 17 00:00:00 2001 From: Mahmood08 Date: Sun, 10 Mar 2019 06:40:31 -0700 Subject: [PATCH 137/367] little change made in test file --- students/shirin_ak/Session08/test_Circle.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/students/shirin_ak/Session08/test_Circle.py b/students/shirin_ak/Session08/test_Circle.py index 9879dc39..da018267 100644 --- a/students/shirin_ak/Session08/test_Circle.py +++ b/students/shirin_ak/Session08/test_Circle.py @@ -56,7 +56,7 @@ def test_add(): c1 = Circle(2) c2 = Circle(4) print(c1 + c2) - assert(c1.radius+c2.radius) == 6 + assert(c1+c2) == 6 def test_mul(): @@ -92,13 +92,13 @@ def test_equal(): def test_sort_val(): """test list of circles is sorted""" - circle1= Circle(10) - circle2 = Circle(5) - circle3 = Circle(2) - circle4 = Circle(7) - circles_list = [circle1.radius, circle2.radius, circle3.radius, circle4.radius] + circle1= 10 + circle2 = 5 + circle3 = 2 + circle4 = 7 + circles_list = [circle1, circle2, circle3, circle4] circles_list.sort() - assert circles_list == [2,5,7,10] + assert circles_list == [circle3, circle2, circle4, circle1] # Test the Sphere class From a0c22f9f9eb48807b7e750f1aaaad352de4983b0 Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Sun, 10 Mar 2019 08:24:07 -0700 Subject: [PATCH 138/367] html_render update --- .../session07/test_html_render.py | 372 +++++++----------- 1 file changed, 146 insertions(+), 226 deletions(-) diff --git a/students/jeff_shabani/session07/test_html_render.py b/students/jeff_shabani/session07/test_html_render.py index a67097a5..5cf0d2fa 100644 --- a/students/jeff_shabani/session07/test_html_render.py +++ b/students/jeff_shabani/session07/test_html_render.py @@ -6,7 +6,6 @@ import io import pytest -import unittest # import * is often bad form, but makes it easier to test everything in a module. from html_render import * @@ -14,253 +13,174 @@ # utility function for testing render methods # needs to be used in multiple tests, so we write it once here. -# def render_result(element, ind=""): -# """ -# calls the element's render method, and returns what got rendered as a -# string -# """ -# # the StringIO object is a "file-like" object -- something that -# # provides the methods of a file, but keeps everything in memory -# # so it can be used to test code that writes to a file, without -# # having to actually write to disk. -# outfile = io.StringIO() -# # this so the tests will work before we tackle indentation -# if ind: -# element.render(outfile, ind) -# else: -# element.render(outfile) -# return outfile.getvalue() +def render_result(element, ind=""): + """ + calls the element's render method, and returns what got rendered as a + string + """ + # the StringIO object is a "file-like" object -- something that + # provides the methods of a file, but keeps everything in memory + # so it can be used to test code that writes to a file, without + # having to actually write to disk. + outfile = io.StringIO() + # this so the tests will work before we tackle indentation + if ind: + element.render(outfile, ind) + else: + element.render(outfile) + return outfile.getvalue() ######## # Step 1 ######## -# -# def test_init(): -# """ -# This only tests that it can be initialized with and without -# some content -- but it's a start -# """ -# e = Element() -# -# e = Element("this is some text") -# -# -# def test_append(): -# """ -# This tests that you can append text -# -# It doesn't test if it works -- -# that will be covered by the render test later -# """ -# e = Element("this is some text") -# e.append("some more text") -# -# -# def test_render_element(): -# """ -# Tests whether the Element can render two pieces of text -# So it is also testing that the append method works correctly. -# -# It is not testing whether indentation or line feeds are correct. -# """ -# e = Element("this is some text") -# e.append("and this is some more text") -# -# # This uses the render_results utility above -# file_contents = render_result(e).strip() -# -# # making sure the content got in there. -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# # make sure it's in the right order -# assert file_contents.index("this is") < file_contents.index("and this") -# -# # making sure the opening and closing tags are right. -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# # # Uncomment this one after you get the one above to pass -# # # Does it pass right away? -# def test_render_element2(): -# """ -# Tests whether the Element can render two pieces of text -# So it is also testing that the append method works correctly. -# -# It is not testing whether indentation or line feeds are correct. -# """ -# e = Element() -# e.append("this is some text") -# e.append("and this is some more text") -# -# # This uses the render_results utility above -# file_contents = render_result(e).strip() -# -# # making sure the content got in there. -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# # make sure it's in the right order -# assert file_contents.index("this is") < file_contents.index("and this") -# -# # making sure the opening and closing tags are right. -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# -# -# # # ######## -# # # # Step 2 -# # # ######## -# -# # tests for the new tags -# def test_html(): -# e = Html("this is some text") -# e.append("and this is some more text") -# -# file_contents = render_result(e).strip() -# -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# print(file_contents) -# assert file_contents.endswith("") -# -# -# def test_body(): -# e = Body("this is some text") -# e.append("and this is some more text") -# -# file_contents = render_result(e).strip() -# -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# -# def test_head(): -# """ Tests that you can add the tag """ -# -# head = Head("this is some text") -# head.append("and this is some more text") -# -# file_contents = render_result(head).strip() -# print(file_contents) -# -# assert "this is some text" in file_contents -# assert "and this is some more text" in file_contents -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# -# def test_p(): -# e = P("this is some text") -# e.append("and this is some more text") -# -# file_contents = render_result(e).strip() -# -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# assert file_contents.startswith("

            ") -# assert file_contents.endswith("

            ") -# -# -# def test_sub_element(): -# """ -# tests that you can add another element and still render properly -# """ -# page = Html() -# page.append("some plain text.") -# page.append(P("A simple paragraph of text")) -# page.append("Some more plain text.") -# -# file_contents = render_result(page) -# print(file_contents) # so we can see it if the test fails -# -# # note: The previous tests should make sure that the tags are getting -# # properly rendered, so we don't need to test that here. -# assert "some plain text" in file_contents -# assert "A simple paragraph of text" in file_contents -# assert "Some more plain text." in file_contents -# assert "some plain text" in file_contents -# # but make sure the embedded element's tags get rendered! -# assert "

            " in file_contents -# assert "

            " in file_contents -# -# ####### -# # Step 3 -# ######## -# -# # Add your tests here! -# -# def test_one_line_tag(): -# """Test proper implementation""" -# olt = OneLineTag("the initial content") -# file_contents = render_result(olt).strip() -# print(file_contents) -# -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# assert "the initial content" in file_contents -# assert "some more content" not in file_contents +def test_init(): + """ + This only tests that it can be initialized with and without + some content -- but it's a start + """ + e = Element() -####### -# Step 5 -######## + e = Element("this is some text") -def test_self_closing_tag(): - sct = SelfClosingTag(width=400) - file_contents = render_result(sct) - print('This is the result:',file_contents) +def test_append(): + """ + This tests that you can append text - assert file_contents.startswith('
            ') - assert f'
            ' in file_contents + It doesn't test if it works -- + that will be covered by the render test later + """ + e = Element("this is some text") + e.append("some more text") -def test_self_closing_tag_2(): - """Test that conent cannot be appended to the self closing tag""" - sct = SelfClosingTag() +def test_render_element(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. - with pytest.raises(NotImplementedError): - sct.append("This should not append") + It is not testing whether indentation or line feeds are correct. + """ + e = Element("this is some text") + e.append("and this is some more text") - file_contents = render_result(sct).strip() - print(file_contents) + # This uses the render_results utility above + file_contents = render_result(e).strip() - assert "This should not append" not in file_contents + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") -def test_class_a(): - ca = A("http://google.com/", "link to google") - file_contents = render_result(ca) - print(file_contents) + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + +# Uncomment this one after you get the one above to pass +# Does it pass right away? +def test_render_element2(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. - assert f'link to google' in file_contents + It is not testing whether indentation or line feeds are correct. + """ + e = Element() + e.append("this is some text") + e.append("and this is some more text") + # This uses the render_results utility above + file_contents = render_result(e).strip() -def test_ul_li(): - """ Tests that you can add unordered lists and list items """ - with pytest.raises(TypeError): - ul = Ul("Should fail") + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents - ul = Ul(style='list-style-type:disc;') - ul.append(Li("List item 1")) - ul.append(Li("List item 2")) + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") - file_contents = render_result(ul).strip() + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + + + +# ######## +# # Step 2 +# ######## + +# tests for the new tags +def test_html(): + e = Html("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents print(file_contents) + assert file_contents.endswith("") + + +def test_body(): + e = Body("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("") + assert file_contents.endswith("") + + +def test_p(): + e = P("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + + assert file_contents.startswith("

            ") + assert file_contents.endswith("

            ") + + +def test_sub_element(): + """ + tests that you can add another element and still render properly + """ + page = Html() + page.append("some plain text.") + page.append(P("A simple paragraph of text")) + page.append("Some more plain text.") + + file_contents = render_result(page) + print(file_contents) # so we can see it if the test fails + + # note: The previous tests should make sure that the tags are getting + # properly rendered, so we don't need to test that here. + assert "some plain text" in file_contents + assert "A simple paragraph of text" in file_contents + assert "Some more plain text." in file_contents + assert "some plain text" in file_contents + # but make sure the embedded element's tags get rendered! + assert "

            " in file_contents + assert "

            " in file_contents + + + + +######## +# Step 3 +######## - assert file_contents.startswith("
              ") - assert "List item 1" in file_contents - assert "List item 2" in file_contents - assert file_contents.count("
            • ") == 2 - assert file_contents.count("
            • ") == 2 +# Add your tests here! # ##################### # # indentation testing @@ -341,4 +261,4 @@ def test_ul_li(): # # by the class attribute: "indent" # assert lines[1].startswith(Element.indent + "thi") # assert lines[2] == "" -# assert file_contents.endswith("") +# assert file_contents.endswith("") \ No newline at end of file From de7871c5c0bc0a0e0520dca5e65414e310404de6 Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Sun, 10 Mar 2019 08:49:06 -0700 Subject: [PATCH 139/367] cirlce tests: added list comparison with reverse and forward sorting --- students/jeff_shabani/session08/test_circle.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/students/jeff_shabani/session08/test_circle.py b/students/jeff_shabani/session08/test_circle.py index f10fa0d7..64528f0b 100644 --- a/students/jeff_shabani/session08/test_circle.py +++ b/students/jeff_shabani/session08/test_circle.py @@ -63,6 +63,15 @@ def test_compare_circles(self): self.assertEqual(c1 * 10 == 10 * c1, True) del c1, c2, c3 + def test_sorting_list_of_instances(self): + instances = [Circle(3), Circle(5), Circle(2), Circle(7)] + reg_sort = sorted(instances, reverse=False) + rev_sort = sorted(instances, reverse=True) + self.assertEqual(repr(reg_sort), + '[Circle with radius of 2, Circle with radius of 3, Circle with radius of 5, Circle with radius of 7]') + self.assertEqual(repr(rev_sort), + '[Circle with radius of 7, Circle with radius of 5, Circle with radius of 3, Circle with radius of 2]') + def test_extended_assignment(self): c1 = Circle(12) c2 = Circle(10) From 24c66c0b4284fc2a527541497f202bfe602648c0 Mon Sep 17 00:00:00 2001 From: Rockwell70 Date: Sun, 10 Mar 2019 09:04:36 -0700 Subject: [PATCH 140/367] sparese_array_update. Adding self callable function. --- .../jeff_shabani/session08/sparse_array.py | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/students/jeff_shabani/session08/sparse_array.py b/students/jeff_shabani/session08/sparse_array.py index f11ffebf..0484ea50 100644 --- a/students/jeff_shabani/session08/sparse_array.py +++ b/students/jeff_shabani/session08/sparse_array.py @@ -2,12 +2,68 @@ class SparseArray(object): - def __init__(self, sequence): + def __init__(self, sequence=None): + if sequence is None: + self.sequence = [] self.sequence = sequence + self.display_list = [i for i in self.sequence if i >0] + iterable = sequence + self.create_working_dict(iterable) + #self.create_working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + + def create_working_dict(self): + self.working_dict = {key: value for key, value in enumerate(self) if value > 0} + + # + # def create_dictionary(self): + # self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + + def __len__(self): + return len(self.sequence) + + def append(self, val): + if val == 0: + return self.sequence + self.sequence.append(val) + + self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + + + def __delitem__(self, key): + del (self.working_dict[key]) + self.sequence.pop(key) + + def __getitem__(self, item): + if item not in self.working_dict.keys(): + return 0 + else: + return self.working_dict[item] + + def __setitem__(self, key, value): + self.sequence[key] = value + + def __contains__(self, item): + if self.sequence: + return True def __repr__(self): - return f'{self.sequence}' + return f'{self.sequence} has a length of {len(self.sequence)}' + + +if __name__ == '__main__': + + spa = SparseArray([1, 0, 2, 3]) + print(spa) + print(len(spa)) + + spa.append(10) + print(spa) -spa = SparseArray([1,2,3]) + print(spa[2]) + del(spa[4]) + print(spa) -print(spa) + # spa[5]=10 + # print(spa) + # print(type(spa)) + # print(10 in spa) From 1b89c7c848fb917b1e7f926e863c1ff0388e0e46 Mon Sep 17 00:00:00 2001 From: Elaine Xu Date: Sun, 10 Mar 2019 10:55:58 -0700 Subject: [PATCH 141/367] session08 hw --- .../elaine_x/session08/circle_exercise_ex.py | 63 ++++++---- .../session08/test_circle_exercise_ex.py | 111 ++++++++++++++++++ 2 files changed, 152 insertions(+), 22 deletions(-) create mode 100644 students/elaine_x/session08/test_circle_exercise_ex.py diff --git a/students/elaine_x/session08/circle_exercise_ex.py b/students/elaine_x/session08/circle_exercise_ex.py index 6b0ae0ea..d58406f7 100644 --- a/students/elaine_x/session08/circle_exercise_ex.py +++ b/students/elaine_x/session08/circle_exercise_ex.py @@ -1,7 +1,7 @@ ''' ########################## #Python 210 -#Session 07 - Circle Exercise +#Session 08 - Circle Exercise #Elaine Xu #Mar 5, 2019 ########################### @@ -40,14 +40,10 @@ def area(self): ############################# # Step 5 add an alternate constructor that create circle directly with the diameter ############################# - -# @classmethod -# def from_diameter(cls, diameter): -# self = cls(self) -# self.diameter = diameter -# self.radius = diameter/2 -# return self.diameter - + @classmethod + def from_diameter(cls, diameter): + radius = diameter/2 + return cls(radius) ############################# # Step 6 add __str__ and __repr__ methods @@ -58,29 +54,52 @@ def __str__(self): def __repr__(self): return "Circle({})".format(self.radius) - ############################# # Step 7 add numerical protocol ############################# def __add__(self, other): - return "Circle({})".format(self.radius + other.radius) + return (self.radius + other.radius) - def __mul__(self, other): - return "Circle({})".format(self.radius * other) + def __mul__(self, val): + try: + return (self.radius * val) + except TypeError: + __rmul__(self, val) + + def __rmul__(self, val): + return (self.radius * val) ############################# # Step 8 add ability to compare two circles ############################# + def __eq__(self, other): + return (self.radius == other.radius) + + def __lt__(self, other): + return (self.radius < other.radius) + + def __iadd__(self, other): + return self.radius + other.radius + + def __imul__(self, val): + return self.radius * val ############################# # Step 9 sphere subclassing ############################# -'''c = Circle(4) -c = Circle.from_diameter(8) -print(c.diameter) -''' -c1 = Circle(2) -c2 = Circle(4) -print(c1+c2) -print(c2 * 3) -#print(3 * c2) \ No newline at end of file +class Sphere(Circle): + def __str__(self): + return "Sphere with radius: " + str(self.radius) + + def __repr__(self): + return "Sphere({})".format(self.radius) + + @property + def volume(self): + return 4/3 * math.pi * self.radius**3 + + @property + def area(self): + raise NotImplementedError + + diff --git a/students/elaine_x/session08/test_circle_exercise_ex.py b/students/elaine_x/session08/test_circle_exercise_ex.py new file mode 100644 index 00000000..7eae8362 --- /dev/null +++ b/students/elaine_x/session08/test_circle_exercise_ex.py @@ -0,0 +1,111 @@ +''' +########################## +#Python 210 +#Session 08 - Circle Exercise +#Elaine Xu +#Mar 5, 2019 +########################### +''' +from circle_exercise_ex import * +import pytest +############################# +#Step 1 +############################# +def test_radius(): + c = Circle(4) + assert c.radius == 4 + +############################# +#Step 2 +############################# +def test_diameter(): + c = Circle(4) + assert c.diameter == 8 + +############################# +#Step 3 +############################# +def test_diameter2(): + c = Circle(4) + c.diameter = 2 + assert c.diameter == 2 + assert c.radius == 1 + +############################# +#Step 4 +############################# +def test_area(): + c = Circle(2) + assert round(c.area, 6) == 12.566371 + + with pytest.raises(AttributeError): + c.area = 12 + +############################# +#Step 5 +############################# +def test_alt_method(): + c = Circle.from_diameter(8) + assert c.diameter == 8 + assert c.radius == 4 + +############################# +#Step 6 +############################# +def test_print(): + c = Circle(4) + assert c.__str__() == "Circle with radius: 4" + assert c.__repr__() == "Circle(4)" + +############################# +#Step 7 +############################# +def test_numeric_protocol(): + c1 = Circle(2) + c2 = Circle(4) + assert c1 + c2 == 6 + assert c2 * 3 == 12 + assert 3 * c2 == 12 + +############################# +#Step 8 +############################# +def test_compare(): + c1 = Circle(2) + c2 = Circle(4) + c3 = Circle(4) + assert (c1 > c2) == False + assert (c1 < c2) == True + assert (c1 == c2) == False + assert (c2 == c3) == True + + #test sorting + circles = [Circle(6), Circle(7), Circle(8), Circle(4), Circle(0), + Circle(2), Circle(3), Circle(5), Circle(9), Circle(1)] + circles.sort() + assert circles == [Circle(0), Circle(1), Circle(2), Circle(3), Circle(4), + Circle(5), Circle(6), Circle(7), Circle(8), Circle(9)] + + #test augmented assignment + assert c1 * 3 == 3 * c1 + c1 += c2 + assert c1 == 6 + c2 *= 2 + assert c2 == 8 + +############################# +#Step 9 +############################# +def test_sphere(): + s = Sphere(4) + assert s.__str__() == "Sphere with radius: 4" + assert s.__repr__() == "Sphere(4)" + assert round(s.volume, 6) == 268.082573 + + with pytest.raises(NotImplementedError): + s.area() + + #test shpere with alternate constructor + s2 = Sphere.from_diameter(8) + assert s2.diameter == 8 + assert s2.radius == 4 \ No newline at end of file From d8b513e591f3a6d30cd73d8915424ce219c8dcca Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 10 Mar 2019 16:32:53 -0700 Subject: [PATCH 142/367] sparse_array updates --- .../session08/test_sparse_array.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session08/test_sparse_array.py b/students/jeff_shabani/session08/test_sparse_array.py index d3fb7311..513bf6fb 100644 --- a/students/jeff_shabani/session08/test_sparse_array.py +++ b/students/jeff_shabani/session08/test_sparse_array.py @@ -8,7 +8,24 @@ class SparseArrayTest(unittest.TestCase): def test_init(self): spa = SparseArray([1, 2, 3]) - self.assertEqual(repr(spa), '[1, 2, 3]') + self.assertEqual(repr(spa), '[1, 2, 3] has a length of 3') + del spa + + def test_get_length(self): + spa = SparseArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + self.assertEqual(len(spa), 10) + del spa + + def test_append(self): + spa = SparseArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + spa.append(11) + self.assertEqual(len(spa), 11) + del spa + + def del_item_from_index(self): + spa = SparseArray([1, 0, 2, 3]) + del(spa[1]) + self.assertEqual(spa.sequence, [1, 2, 3]) if __name__ == '__main__': From 8609a9df32c017130196d8737cc8615fb0767eba Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 10 Mar 2019 16:33:04 -0700 Subject: [PATCH 143/367] sparse_array updates --- .../jeff_shabani/session08/sparse_array.py | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/students/jeff_shabani/session08/sparse_array.py b/students/jeff_shabani/session08/sparse_array.py index 0484ea50..054fc70c 100644 --- a/students/jeff_shabani/session08/sparse_array.py +++ b/students/jeff_shabani/session08/sparse_array.py @@ -1,22 +1,19 @@ #!/usr/bin/env python3 class SparseArray(object): + working_dict = dict() def __init__(self, sequence=None): if sequence is None: self.sequence = [] self.sequence = sequence - self.display_list = [i for i in self.sequence if i >0] - iterable = sequence - self.create_working_dict(iterable) - #self.create_working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + self.display_list = [i for i in self.sequence if i > 0] + self.create_working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} - def create_working_dict(self): - self.working_dict = {key: value for key, value in enumerate(self) if value > 0} - - # - # def create_dictionary(self): - # self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + # @classmethod + def create_working_dict(cls): + working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + return working_dict def __len__(self): return len(self.sequence) @@ -25,12 +22,12 @@ def append(self, val): if val == 0: return self.sequence self.sequence.append(val) - + # self.create_working_dict() self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} - def __delitem__(self, key): - del (self.working_dict[key]) + if key in self.working_dict: + del (self.working_dict[key]) self.sequence.pop(key) def __getitem__(self, item): @@ -40,7 +37,8 @@ def __getitem__(self, item): return self.working_dict[item] def __setitem__(self, key, value): - self.sequence[key] = value + self.working_dict[key] = value + def __contains__(self, item): if self.sequence: @@ -60,10 +58,10 @@ def __repr__(self): print(spa) print(spa[2]) - del(spa[4]) + del(spa[1]) print(spa) - # spa[5]=10 - # print(spa) + spa[4]=10 + print(spa.working_dict) # print(type(spa)) # print(10 in spa) From d32953cbeaa59ffb9dbfcd6b7c34847e6935d94f Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 10 Mar 2019 16:52:58 -0700 Subject: [PATCH 144/367] sparse_array updates --- students/jeff_shabani/session08/test_sparse_array.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session08/test_sparse_array.py b/students/jeff_shabani/session08/test_sparse_array.py index 513bf6fb..cb7ef89c 100644 --- a/students/jeff_shabani/session08/test_sparse_array.py +++ b/students/jeff_shabani/session08/test_sparse_array.py @@ -22,10 +22,18 @@ def test_append(self): self.assertEqual(len(spa), 11) del spa - def del_item_from_index(self): + def test_del_item_from_index(self): spa = SparseArray([1, 0, 2, 3]) del(spa[1]) self.assertEqual(spa.sequence, [1, 2, 3]) + del spa + + def test_slicing(self): + spa = SparseArray([1, 0, 2, 3, 17]) + self.assertEqual(spa[1:4], [0, 2, 3]) + self.assertEqual(spa[::-1], [17, 3, 2, 0, 1]) + del spa + if __name__ == '__main__': From 174f09254b53689d79ecedd373a34c854d47ced3 Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 10 Mar 2019 16:53:09 -0700 Subject: [PATCH 145/367] sparse_array updates --- students/jeff_shabani/session08/sparse_array.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/students/jeff_shabani/session08/sparse_array.py b/students/jeff_shabani/session08/sparse_array.py index 054fc70c..622d259b 100644 --- a/students/jeff_shabani/session08/sparse_array.py +++ b/students/jeff_shabani/session08/sparse_array.py @@ -25,16 +25,22 @@ def append(self, val): # self.create_working_dict() self.working_dict = {key: value for key, value in enumerate(self.sequence) if value > 0} + def __getslice__(self, start, end): + return self.sequence[start:end] + def __delitem__(self, key): if key in self.working_dict: del (self.working_dict[key]) self.sequence.pop(key) + # def __getitem__(self, item): + # if item not in self.working_dict.keys(): + # return 0 + # else: + # return self.working_dict[item] + def __getitem__(self, item): - if item not in self.working_dict.keys(): - return 0 - else: - return self.working_dict[item] + return self.sequence[item] def __setitem__(self, key, value): self.working_dict[key] = value @@ -63,5 +69,7 @@ def __repr__(self): spa[4]=10 print(spa.working_dict) + print(spa[-1:]) + print(reversed(spa)) # print(type(spa)) # print(10 in spa) From 3400b8a10f4ec86d53488fbb83598be3e7c92da3 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 10 Mar 2019 16:57:44 -0700 Subject: [PATCH 146/367] Added doctstrings to test_circle_class.py. Final commit before submitting. --- .../lesson08_exercise/circle_class.py | 104 +++++++++++++++++ .../lesson08_exercise/test_circle_class.py | 107 ++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 students/jeremy_m/lesson08_exercise/test_circle_class.py diff --git a/students/jeremy_m/lesson08_exercise/circle_class.py b/students/jeremy_m/lesson08_exercise/circle_class.py index e69de29b..b0144709 100644 --- a/students/jeremy_m/lesson08_exercise/circle_class.py +++ b/students/jeremy_m/lesson08_exercise/circle_class.py @@ -0,0 +1,104 @@ +import math + + +class Circle(): + def __init__(self, radius): + self.radius = radius + + def __str__(self): + return 'A circle with a radius of {}'.format(self.radius) + + def __repr__(self): + return 'Circle({})'.format(self.radius) + + + # Binary operators defined here + def __add__(self, other): + try: + return self.radius + other.radius + except AttributeError: + return self.radius + other + + def __radd__(self, other): + return self.radius + other + + def __mul__(self, other): + try: + return self.radius * other.radius + except AttributeError: + return self.radius * other + + def __rmul__(self, other): + return self.radius * other + # Binary operators end + + # Comparison operators defined here + def __lt__(self, other): + try: + return self.radius < other.radius + except AttributeError: + return self.radius < other + + def __le__(self, other): + try: + return self.radius <= other.radius + except AttributeError: + return self.radius <= other + + def __eq__(self, other): + try: + return self.radius == other.radius + except AttributeError: + return self.radius == other + + def __ge__(self, other): + try: + return self.radius >= other.radius + except AttributeError: + return self.radius >= other + + def __gt__(self, other): + try: + return self.radius > other.radius + except AttributeError: + return self.radius > other + # Comparison operators end + + @property + def diameter(self): + """ Calculates the diameter based on given radius """ + return self.radius * 2 + + @diameter.setter + def diameter(self, new_value): + """ Sets the diameter based on the radius """ + self.radius = new_value // 2 + + @property + def area(self): + """ Calculates the area of the circle """ + return math.pi * (self.radius ** 2) + + @classmethod + def from_diameter(cls, diameter): + """ Instantiates an instance of a circle from its diameter """ + return cls(diameter // 2) + + + +class Sphere(Circle): + def __str__(self): + return 'A sphere with a radius of {}'.format(self.radius) + + def __repr__(self): + return 'Sphere({})'.format(self.radius) + + @property + def volume(self): + """ Calculates the volume of the sphere """ + return round((4 / 3) * math.pi * (self.radius ** 3), 2) + + @property + def area(self): + """ Calculates the surface area of the sphere """ + return round(4 * math.pi * (self.radius ** 2), 2) \ No newline at end of file diff --git a/students/jeremy_m/lesson08_exercise/test_circle_class.py b/students/jeremy_m/lesson08_exercise/test_circle_class.py new file mode 100644 index 00000000..8f22cc60 --- /dev/null +++ b/students/jeremy_m/lesson08_exercise/test_circle_class.py @@ -0,0 +1,107 @@ +""" Tests for circle_class.py """ + +import pytest +from circle_class import * +import math + + +def test_basic_circle(): + """ Test if a circle can be instantiated and basic parameters are set properly """ + c1 = Circle(10) + assert c1.radius == 10 + assert c1.diameter == 20 + + +def test_set_radius(): + """ Tests setting the radius """ + c1 = Circle(10) + c1.radius = 20 + + assert c1.radius == 20 + + +def test_set_diameter(): + """ + Tests setting the diameter and checks to ensure radius is calculated + accurately. + """ + c1 = Circle(10) + + c1.diameter = 100 + assert c1.radius == 50 + assert c1.diameter == 100 + + +def test_area(): + """ Tests the circle area function """ + c1 = Circle(10) + + asserted_area = math.pi * (10 ** 2) + assert c1.area == asserted_area + + +def test_construct_from_diameter(): + """ Tests instantiating a Circle from its diameter """ + c1 = Circle.from_diameter(50) + + assert c1.radius == 25 + assert c1.diameter == 50 + + +def test_str_and_repr(): + """ Testing Circle's dunder str and repr methods """ + c1 = Circle(10) + + assert c1.__str__() == 'A circle with a radius of 10' + assert c1.__repr__() == 'Circle(10)' + + +def test_add_multiply(): + """ Testing variations of Circle addition and multiplication """ + c1 = Circle(10) + c2 = Circle(20) + + assert c1 + c2 == 30 + assert c1 + 10 == 20 + assert 10 + c1 == 20 + assert c1 * c2 == 200 + assert c1 * 10 == 100 + assert 10 * c1 == 100 + + +def test_comparison(): + """ Tests Circle's comparison operators """ + c1 = Circle(10) + c2 = Circle(20) + + assert c1 < c2 + assert not (c1 > c2) + assert c1 < 30 + assert c1 == 10 + assert c1 > 5 + assert c1 <= c2 + assert c1 <= 15 + assert c1 >= 3 + + +def test_comparison_complex(): + """ Tests Circle comparison in a more complex way """ + c1 = Circle(10) + + assert c1 * 3 == 3 * c1 + + +def test_sphere(): + """ Tests instantiating a sphere and checks its properties for accuracy """ + s1 = Sphere(10) + + assert s1.radius == 10 + assert s1.volume == 4188.79 + assert s1.area == 1256.64 + + +def test_sphere_from_diameter(): + """ Tests creating a sphere from its diameter. """ + s1 = Sphere.from_diameter(30) + assert s1.radius == 15 + assert s1.diameter == 30 From 0005b302a0bdead0f4006c2f5e07c79c8c64ff3d Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 10 Mar 2019 17:00:38 -0700 Subject: [PATCH 147/367] sparse_array updates --- .../jeff_shabani/session08/test_sparse_array.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/students/jeff_shabani/session08/test_sparse_array.py b/students/jeff_shabani/session08/test_sparse_array.py index cb7ef89c..a7f63f37 100644 --- a/students/jeff_shabani/session08/test_sparse_array.py +++ b/students/jeff_shabani/session08/test_sparse_array.py @@ -4,6 +4,7 @@ from sparse_array import * + class SparseArrayTest(unittest.TestCase): def test_init(self): @@ -24,7 +25,7 @@ def test_append(self): def test_del_item_from_index(self): spa = SparseArray([1, 0, 2, 3]) - del(spa[1]) + del (spa[1]) self.assertEqual(spa.sequence, [1, 2, 3]) del spa @@ -34,6 +35,16 @@ def test_slicing(self): self.assertEqual(spa[::-1], [17, 3, 2, 0, 1]) del spa + @unittest.expectedFailure + def test_index_error(self): + spa = SparseArray([1, 0, 2, 3, 17]) + self.assertEqual(spa[8], 12) + del spa + + def test_index_error_two(self): + spa = SparseArray([1, 0, 2, 3, 17]) + with self.assertRaises(IndexError): + return spa[8] if __name__ == '__main__': From 66108ca00da0bbd176c123c6fedeae5983208da8 Mon Sep 17 00:00:00 2001 From: JRockwell70 Date: Sun, 10 Mar 2019 17:01:43 -0700 Subject: [PATCH 148/367] sparse_array updates --- .../jeff_shabani/session08/sparse_array.py | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/students/jeff_shabani/session08/sparse_array.py b/students/jeff_shabani/session08/sparse_array.py index 622d259b..5e4d7cf6 100644 --- a/students/jeff_shabani/session08/sparse_array.py +++ b/students/jeff_shabani/session08/sparse_array.py @@ -33,43 +33,15 @@ def __delitem__(self, key): del (self.working_dict[key]) self.sequence.pop(key) - # def __getitem__(self, item): - # if item not in self.working_dict.keys(): - # return 0 - # else: - # return self.working_dict[item] - def __getitem__(self, item): return self.sequence[item] def __setitem__(self, key, value): self.working_dict[key] = value - def __contains__(self, item): if self.sequence: return True def __repr__(self): return f'{self.sequence} has a length of {len(self.sequence)}' - - -if __name__ == '__main__': - - spa = SparseArray([1, 0, 2, 3]) - print(spa) - print(len(spa)) - - spa.append(10) - print(spa) - - print(spa[2]) - del(spa[1]) - print(spa) - - spa[4]=10 - print(spa.working_dict) - print(spa[-1:]) - print(reversed(spa)) - # print(type(spa)) - # print(10 in spa) From a04c8c95ca994358e7dba0184dce6187f69310bf Mon Sep 17 00:00:00 2001 From: Alex Whitty Date: Sun, 10 Mar 2019 20:11:07 -0700 Subject: [PATCH 149/367] Updating files --- students/alex_whitty/session06/mailroom4.py | 49 ++++++------ .../alex_whitty/session06/test_mailroom.py | 42 ++++++---- students/alex_whitty/session08/circle.py | 71 ++++++++++++++++ students/alex_whitty/session08/test_circle.py | 80 +++++++++++++++++++ 4 files changed, 203 insertions(+), 39 deletions(-) create mode 100644 students/alex_whitty/session08/circle.py create mode 100644 students/alex_whitty/session08/test_circle.py diff --git a/students/alex_whitty/session06/mailroom4.py b/students/alex_whitty/session06/mailroom4.py index 67d1e8a1..970970e4 100644 --- a/students/alex_whitty/session06/mailroom4.py +++ b/students/alex_whitty/session06/mailroom4.py @@ -1,7 +1,5 @@ import sys # imports go at the top of the file - - # Data Structure donor_db = {"William Gates, III": [653772.32, 12.17], "Jeff Bezos": [877.33], @@ -10,26 +8,25 @@ "Elon Musk": [2263.23, 3300.87, 15432.0], } - ''' First Comprehesion''' new_donor_dic = \ - {d: donors for d, donors in donor_db.items()} + {d: donors for d, donors in donor_db.items()} # Input/Output prompt = "\n".join(("Mail Distribution Center!", - "Please choose from below options:", - "1 - Send a Thank You to a single donor", - "2 - Create a Report", - "3 - Send letters to all donors", - "4 - Exit", - ">>> ")) + "Please choose from below options:", + "1 - Send a Thank You to a single donor", + "2 - Create a Report", + "3 - Send letters to all donors", + "4 - Exit", + ">>> ")) # Features ''' Second Comprehension''' dict_comp = {d for d in donor_db.keys()} -def view_donor_names(): +def view_donor_names(): for donor in donor_db.keys(): print(donor) @@ -41,6 +38,7 @@ def write_a_letter(donor, amount): f"The Fundraising Committee" return letter + def write_a_letter_all(donor): letter = f"Dear {donor},\n\nThank you for your kind donation. \n\n" \ f"It will be put to very good use.\n\n" \ @@ -49,14 +47,11 @@ def write_a_letter_all(donor): return letter - def dir_for_letter(): - input("Hit key to save to the current working directory.") def thank_you_letter(): - answer = input("Please enter Full Name.>>>") if answer.lower() == 'list': for donor in donor_db.keys(): @@ -68,7 +63,6 @@ def thank_you_letter(): add_donor(answer) - def letter_to_all_donors(): dir_for_letter() for donor in donor_db.keys(): @@ -76,11 +70,11 @@ def letter_to_all_donors(): letter.write(switch_func_dict.get(1)(donor)) - def get_letter_text(donor): letter_to_all_donors() return f"{donor}, Thank you for your kind donation" + def get_value(text, check_type): while True: try: @@ -90,8 +84,8 @@ def get_value(text, check_type): print("Invalid value. Please try again") continue -def current_donor(donor): +def current_donor(donor): amount = get_value("Please enter donor amount.>>>", float) donor_db[donor].append(float(amount)) dir_for_letter() @@ -100,13 +94,11 @@ def current_donor(donor): print('Thanks, {} for your generous donation.'.format(donor)) - def sort_key(donor_db): return donor_db[:] def add_donor(new_donor): - donor_amount = get_value("What is the donation amount?.>>>", float) donor_db[new_donor] = [float(donor_amount)] print(donor_db) @@ -117,26 +109,35 @@ def add_donor(new_donor): def report(): - summary = [] + headers = ["Donor Name", "Total Given", "Num Gifts", "Average Gift"] print() print("{:20} | {:10} | {:10} | {}".format(headers[0], headers[1], headers[2], headers[3])) print("-" * 80) + summary = create_summary() + for i in summary: + print("{:20} ${:>12,.2f}{:>10} ${:>14,.2f}".format(i[0], i[1], i[2], i[3])) + print("") + + +def create_summary(): + summary = [] for k, v in donor_db.items(): total = (sum(v)) times = (len(v)) avg = (sum(v) / len(v)) summary.append([k, total, times, avg]) + summary.sort(key=lambda d: d[1], reverse=True) - for i in summary: - print("{:20} ${:>12,.2f}{:>10} ${:>14,.2f}".format(i[0], i[1], i[2], i[3])) - print("") + return summary + def exit_program(): print("Good-Bye!") sys.exit() # exit the interactive script + # Processing def main(): while True: @@ -155,7 +156,6 @@ def main(): print("Not a valid option!") - ''' Switch with the above functions "write_a_letter and write_a_letter_all" ''' switch_func_dict = { @@ -166,4 +166,3 @@ def main(): if __name__ == "__main__": # don't forget this block to guard against your code running automatically if this module is imported main() - diff --git a/students/alex_whitty/session06/test_mailroom.py b/students/alex_whitty/session06/test_mailroom.py index 81697cec..cd19ac87 100644 --- a/students/alex_whitty/session06/test_mailroom.py +++ b/students/alex_whitty/session06/test_mailroom.py @@ -1,27 +1,42 @@ #!/usr/bin/env python3 + import unittest import mailroom4 +from unittest import mock -class TestMailroom4(unittest.TestCase): +class TestMailroom4(unittest.TestCase): def test_write_a_letter(self): - donor = 'Paul Allen' - amount = 200 - self.assertEqual(donor, "Paul Allen") - self.assertEqual(amount, 200) - self.assertTrue(mailroom4.write_a_letter(donor, amount), True) + actual = mailroom4.write_a_letter('Paul Allen', 200) + expected = f"Dear Paul Allen,\n\nThank you for your kind donation of $200\n\n" \ + f"It will be put to very good use.\n\n" \ + f"Sincerely,\n" \ + f"The Fundraising Committee" + self.assertEqual(actual, expected) + + @mock.patch('mailroom4.get_value', mock.MagicMock(return_value=200.00)) + @mock.patch('mailroom4.dir_for_letter') + def test_add_donor(self, mocks): + new_donor = 'Pete Rose' + mailroom4.add_donor(new_donor) + with open(f'{new_donor}.txt', 'r') as my_test_file: + actual = my_test_file.read() + expected = f"Dear {new_donor},\n\nThank you for your kind donation of $200.0\n\n" \ + f"It will be put to very good use.\n\n" \ + f"Sincerely,\n" \ + f"The Fundraising Committee" - def test_add_donor(self): - new_donor = 'Pete Rose' - self.assertEqual(new_donor, "Pete Rose") - self.assertNotEqual(mailroom4.add_donor(new_donor), new_donor) + self.assertEqual(actual, expected) - def test_view_donor_names(self): - self.assertEqual(mailroom4.view_donor_names(), - print('\nJeff Bezos\nPaul Allen\nElon Musk\nMark Zuckerberg\nWilliam Gates, III')) + + def test_create_summary(self): + mailroom4.donor_db = {"William Gates, III": [653772.32, 12.17, 15.123], "Jeff Bezos": [877.33, 1000.20]} + actual = mailroom4.create_summary() + expected = [['William Gates, III', 653799.613, 3, 217933.20433333333], ['Jeff Bezos', 1877.5300000000002, 2, 938.7650000000001]] + self.assertEqual(expected, actual) @unittest.expectedFailure def test_letter_to_all_donors(self): @@ -36,7 +51,6 @@ def test_letter_to_all_donors(self): def test_report(self): self.assertEqual(mailroom4.report(), None) - def test_current_donor(self): current_donor = 'Elon Musk' self.assertEqual(current_donor, "Elon Musk") diff --git a/students/alex_whitty/session08/circle.py b/students/alex_whitty/session08/circle.py new file mode 100644 index 00000000..411afe71 --- /dev/null +++ b/students/alex_whitty/session08/circle.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import math + +class Circle(object): + def __init__(self, radius): + self.radius = radius + + @property + def diameter(self): + print("in getter") + return self.radius * 2 + + @diameter.setter + def diameter(self, value): + print("in setter", value) + self.radius = value / 2 + + + @property + def area(self): + return math.pi * self.radius**2 + + @classmethod + def from_diameter(cls, diameter): + """ Initializes class from diameter instead of radius """ + return cls(diameter / 2) + + + def __str__(self): + return "Circle with radius: " + str(self.radius) + + def __repr__(self): + return "Circle({})".format(self.radius) + + def __add__(self, other): + return "Circle({})".format(self.radius + other.radius) + + def __mul__(self, other): + return "Circle({})".format(self.radius * other) + + __rmul__ = __mul__ + + def __lt__(self, other): + return self.radius < other.radius + + def __gt__(self, other): + return self.radius > other.radius + + def __eq__(self, other): + return self.radius == other.radius + + +class Sphere(Circle): + """ Sphere class, inherits from Circle """ + + @property + def area(self): + """ Returns the area of the sphere """ + return 4 * math.pi * self.radius ** 2 + + @property + def volume(self): + """ Returns the Volume of the sphere """ + return (4/3) * math.pi * self.radius ** 3 + + def __str__(self): + return "Sphere with a radius of: " + str(self.radius) + + def __repr__(self): + return "Sphere({})".format(self.radius) diff --git a/students/alex_whitty/session08/test_circle.py b/students/alex_whitty/session08/test_circle.py new file mode 100644 index 00000000..dafb1541 --- /dev/null +++ b/students/alex_whitty/session08/test_circle.py @@ -0,0 +1,80 @@ +from math import pi +from circle import Circle, Sphere + + +def test_radius(): + c = Circle(2) + assert c.radius == 2 + + +def test_diameter(): + c = Circle(3) + assert c.diameter == 6 + + +def test_set_diameter(): + c = Circle(4) + c.diameter = 5 + assert c.diameter == 5 + assert c.radius == 2.5 + + +def test_area(): + c = Circle(6) + assert c.area == pi * 36 + +def test_alt_construct(): + c1 = Circle.from_diameter(10) + assert c1.diameter == 10 + + +def test_from_diameter(): + c = Circle.from_diameter(8) + assert c.diameter == 8 + assert c.radius == 4 + + +def test_string(): + c = Circle(9) + assert str(c) == "Circle with radius: 9" + +def test_string_repr(): + c = Circle(12) + assert repr(c) == "Circle(12)" + + +def test_less(): + c1 = Circle(2) + c2 = Circle(5) + assert (c1 < c2) is True + + +def test_equal(): + c1 = Circle(3) + c2 = Circle(3) + assert (c1 == c2) is True + + +def test_sphere(): + Sphere(4) + + +def test_sphere_repr(): + s = Sphere(12) + assert repr(s) == "Sphere(12)" + + +def test_sphere_volume(): + s = Sphere(4) + assert s.volume == 4 / 3 * pi * 4 ** 3 + + +def test_sphere_area(): + s = Sphere(6) + assert s.area == 4 * pi * 6 ** 2 + + +def test_sphere_diameter(): + s = Sphere.from_diameter(8) + assert s.area == 4 * pi * 4 ** 2 + assert s.volume == 4 / 3 * pi * 4 ** 3 From a80bf0409a0fe7b2682aa7234edbb8b37d06b64f Mon Sep 17 00:00:00 2001 From: dac2229 Date: Sun, 10 Mar 2019 20:28:03 -0700 Subject: [PATCH 150/367] finished circle and circle test --- students/daniel_carrasco/session08/circle.py | 36 +++++----- .../daniel_carrasco/session08/test_circle.py | 65 +++++++++++++++++++ 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/students/daniel_carrasco/session08/circle.py b/students/daniel_carrasco/session08/circle.py index 7a59bf4b..4087ba2b 100644 --- a/students/daniel_carrasco/session08/circle.py +++ b/students/daniel_carrasco/session08/circle.py @@ -1,5 +1,6 @@ import math -class Circle: + +class Circle(object): pi = math.pi def __init__(self,the_radius): self.radius = the_radius @@ -23,10 +24,10 @@ def area(self, diameter): @classmethod def from_diameter(cls, diameter): - return Circle(diameter/2) + return cls(diameter/2) def __str__(self): - return f'circle with a radius of {self.radius}' + return f'Circle with a radius of {self.radius}' def __repr__(self): return (f'{self.__class__.__name__}(' @@ -67,18 +68,21 @@ def __ge__(self, other): if self.radius >= other.radius:return True else: return False +class Sphere(Circle): + + def __str__(self): + return f'Sphere with a radius of {self.radius}' + + def __repr__(self): + return (f'{self.__class__.__name__}(' + f'{self.radius!r})') + @property + def volume(self): + return 4/3*self.pi*self.radius**3 + +a = Circle(2) +b = Circle(4) + +print(b.radius*a.radius) -c1 = Circle(2) -c2 = Circle(2) -a = c1 + c2 -print(a) -print(c1 == c2) -circles =[Circle(6), Circle(7), Circle(8), Circle(4), Circle(0), Circle(2), Circle(3), Circle(5), Circle(9), Circle(1)] -circles.sort() -print(circles) -b = Circle(5) -b+=1 -print(b) -b*=2 -print(b) \ No newline at end of file diff --git a/students/daniel_carrasco/session08/test_circle.py b/students/daniel_carrasco/session08/test_circle.py index 58f2d666..e13dbdc4 100644 --- a/students/daniel_carrasco/session08/test_circle.py +++ b/students/daniel_carrasco/session08/test_circle.py @@ -1,5 +1,6 @@ import io import pytest +import math from circle import * @@ -28,3 +29,67 @@ def test_diameter(): c.diameter = 6 assert c.radius == 3 assert c.diameter == 6 + +def test_from_diameter(): + "test to see if it still calculates using diameter" + t = Circle.from_diameter(5) + assert t.radius == 2.5 + assert t.diameter == 5 + +def test_str_repr(): + "test to see if __str__ and __repr__ methods work" + a = str(Circle(4)) + b = repr(Circle(5)) + c = str(Sphere(3)) + d = repr(Sphere(2)) + assert a == 'Circle with a radius of 4' + assert b == 'Circle(5)' + assert c == 'Sphere with a radius of 3' + assert d == 'Sphere(2)' + +def test_lo(): + "test to see if logical operators work for class" + a = Circle(1) + b = Circle(2) + c = Circle(1) + assert b>a + assert a=a + assert a<=b + assert a!=b + +def test_rmul_mul(): + "test to see if you can multiply the class, and at any order" + a = Circle(2) + b = 3*a + c = a*4 + assert b.radius == 6 + assert c.radius == 8 + +def test_mult_add(): + "test to see if you can multiply and add classes together" + a = Circle(5) + b = Circle(5) + assert a.radius+b.radius == 10 + assert a.radius*b.radius == 25 + +def test_volume(): + "test to see if volume of sphere calculations work" + a = Sphere(2) + b = Sphere.from_diameter(2) + assert a.volume == 4/3*math.pi*2**3 + assert b.volume == 4/3*math.pi*1**3 + +def test_area(): + 'test to see if area method works' + a = Circle(7) + b = Circle.from_diameter(4) + assert a.area == math.pi*7**2 + assert b.area == math.pi*2**2 + + + + + + From 0b3528c88e3562aadb1a6694b8835120da099038 Mon Sep 17 00:00:00 2001 From: dac2229 Date: Sun, 10 Mar 2019 20:29:49 -0700 Subject: [PATCH 151/367] pep8 to files --- students/daniel_carrasco/session08/circle.py | 75 ++++++++++++------- .../daniel_carrasco/session08/test_circle.py | 47 ++++++------ 2 files changed, 70 insertions(+), 52 deletions(-) diff --git a/students/daniel_carrasco/session08/circle.py b/students/daniel_carrasco/session08/circle.py index 4087ba2b..94bdf568 100644 --- a/students/daniel_carrasco/session08/circle.py +++ b/students/daniel_carrasco/session08/circle.py @@ -1,30 +1,32 @@ import math + class Circle(object): pi = math.pi - def __init__(self,the_radius): + + def __init__(self, the_radius): self.radius = the_radius @property def diameter(self): - return self.radius*2 + return self.radius * 2 @diameter.setter def diameter(self, diameter): - self.radius = diameter/2 + self.radius = diameter / 2 @property def area(self): - return self.pi*(self.radius)**2 + return self.pi * (self.radius)**2 @area.setter def area(self, diameter): if input: - print('Attribute Error') # How do I do this correctly + print('Attribute Error') # How do I do this correctly @classmethod def from_diameter(cls, diameter): - return cls(diameter/2) + return cls(diameter / 2) def __str__(self): return f'Circle with a radius of {self.radius}' @@ -36,37 +38,56 @@ def __repr__(self): def __add__(self, c2): print(f'Summing {self} + {c2}') print(c2.radius) - return Circle(self.radius+c2.radius) + return Circle(self.radius + c2.radius) def __mul__(self, other): - return Circle(self.radius*other) + return Circle(self.radius * other) def __rmul__(self, other): - return Circle(self.radius*other) + return Circle(self.radius * other) def __iadd__(self, other): - return Circle(self.radius+other) + return Circle(self.radius + other) + def __imul__(self, other): - return Circle(self.radius*other) + return Circle(self.radius * other) def __lt__(self, other): - if self.radius < other.radius:return True - else: return False + if self.radius < other.radius: + return True + else: + return False + def __le__(self, other): - if self.radius <= other.radius:return True - else: return False + if self.radius <= other.radius: + return True + else: + return False + def __eq__(self, other): - if self.radius == other.radius:return True - else: return False + if self.radius == other.radius: + return True + else: + return False + def __ne__(self, other): - if self.radius != other.radius:return True - else: return False + if self.radius != other.radius: + return True + else: + return False + def __gt__(self, other): - if self.radius > other.radius:return True - else: return False + if self.radius > other.radius: + return True + else: + return False + def __ge__(self, other): - if self.radius >= other.radius:return True - else: return False + if self.radius >= other.radius: + return True + else: + return False + class Sphere(Circle): @@ -76,13 +97,9 @@ def __str__(self): def __repr__(self): return (f'{self.__class__.__name__}(' f'{self.radius!r})') + @property def volume(self): - return 4/3*self.pi*self.radius**3 - -a = Circle(2) -b = Circle(4) - -print(b.radius*a.radius) + return 4 / 3 * self.pi * self.radius**3 diff --git a/students/daniel_carrasco/session08/test_circle.py b/students/daniel_carrasco/session08/test_circle.py index e13dbdc4..ad786d56 100644 --- a/students/daniel_carrasco/session08/test_circle.py +++ b/students/daniel_carrasco/session08/test_circle.py @@ -4,6 +4,7 @@ from circle import * + def test_init(): """ This only tests that it can be initialized with and without @@ -13,29 +14,30 @@ def test_init(): def test_radius(): - "check to see if it outputs correct radius" c = Circle(5) # making sure radius outputs correctly. assert c.radius == 5 -def test_diameter(): +def test_diameter(): "check to see if it outputs correct diameter" c = Circle(5) # making sure radius outputs correctly. assert c.diameter == 10 - assert c.diameter == c.radius*2 + assert c.diameter == c.radius * 2 c.diameter = 6 assert c.radius == 3 assert c.diameter == 6 + def test_from_diameter(): "test to see if it still calculates using diameter" t = Circle.from_diameter(5) assert t.radius == 2.5 assert t.diameter == 5 + def test_str_repr(): "test to see if __str__ and __repr__ methods work" a = str(Circle(4)) @@ -47,49 +49,48 @@ def test_str_repr(): assert c == 'Sphere with a radius of 3' assert d == 'Sphere(2)' + def test_lo(): "test to see if logical operators work for class" a = Circle(1) b = Circle(2) c = Circle(1) - assert b>a - assert a=a - assert a<=b - assert a!=b + assert b > a + assert a < b + assert a == c + assert b >= a + assert a <= b + assert a != b + def test_rmul_mul(): "test to see if you can multiply the class, and at any order" a = Circle(2) - b = 3*a - c = a*4 + b = 3 * a + c = a * 4 assert b.radius == 6 assert c.radius == 8 + def test_mult_add(): "test to see if you can multiply and add classes together" a = Circle(5) b = Circle(5) - assert a.radius+b.radius == 10 - assert a.radius*b.radius == 25 + assert a.radius + b.radius == 10 + assert a.radius * b.radius == 25 + def test_volume(): "test to see if volume of sphere calculations work" a = Sphere(2) b = Sphere.from_diameter(2) - assert a.volume == 4/3*math.pi*2**3 - assert b.volume == 4/3*math.pi*1**3 + assert a.volume == 4 / 3 * math.pi * 2**3 + assert b.volume == 4 / 3 * math.pi * 1**3 + def test_area(): 'test to see if area method works' a = Circle(7) b = Circle.from_diameter(4) - assert a.area == math.pi*7**2 - assert b.area == math.pi*2**2 - - - - - - + assert a.area == math.pi * 7**2 + assert b.area == math.pi * 2**2 From b38bb5f9c1d9fd7dec73a909fd8e0e4933e8f4dc Mon Sep 17 00:00:00 2001 From: Alex Whitty Date: Sun, 10 Mar 2019 20:30:48 -0700 Subject: [PATCH 152/367] Updated test_circle file --- students/alex_whitty/session08/test_circle.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/students/alex_whitty/session08/test_circle.py b/students/alex_whitty/session08/test_circle.py index dafb1541..66584d53 100644 --- a/students/alex_whitty/session08/test_circle.py +++ b/students/alex_whitty/session08/test_circle.py @@ -55,6 +55,11 @@ def test_equal(): assert (c1 == c2) is True +def test_sort(): + list_c = [Circle(i) for i in range(3, 0, -1)] + assert str(sorted(list_c)) == "[Circle(1), Circle(2), Circle(3)]" + + def test_sphere(): Sphere(4) From eb6eafb784b7d25a1f9090fc03df5f7ab579724a Mon Sep 17 00:00:00 2001 From: Elaine Xu Date: Sun, 10 Mar 2019 21:59:41 -0700 Subject: [PATCH 153/367] session08 sparse array --- .../elaine_x/session08/sparse_array_ex.py | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 students/elaine_x/session08/sparse_array_ex.py diff --git a/students/elaine_x/session08/sparse_array_ex.py b/students/elaine_x/session08/sparse_array_ex.py new file mode 100644 index 00000000..df41b199 --- /dev/null +++ b/students/elaine_x/session08/sparse_array_ex.py @@ -0,0 +1,125 @@ +''' +########################## +#Python 210 +#Session 08 - Sparse Array +#Elaine Xu +#Mar 8, 2019 +########################### +''' +#import numpy as np +#import spicy.sparse +''' +https://uwpce-pythoncert.github.io/PythonCertDevel/exercises/sparse_array.html + +Oftentimes, at least in computation programming, we have large arrays of data that hold mostly zeros. +These are referred to as “sparse” as the information in them is widely scattered, or sparse. +Since they are mostly zeros, it can be memory and computationally efficient to store only the value +that are non-zero. +But you want it to look like a regular array in user code. +In the real world, these are usually 2 dimensional arrays. But to keep it a bit simpler, we’ll make +a 1 dimensional sparse array in this class. + +A sparse array class should present to the user the same interface as a regular list. + +Internally, it can store the values in a dict, with the index as the keys, so that only the indexes +with non-zero values will be stored. +It should take a sequence of values as an initializer: +sa = SparseArray([1,2,0,0,0,0,3,0,0,4]) + +you should be able to tell how long it is: +len(my_array) +This will give its “virtual” length – with the zeros + +It should support getting and setting particular elements via indexing: +sa[5] = 12 +sa[3] = 0 # the zero won't get stored! +val = sa[13] # it should get a zero if not set + +It should support deleting an element by index: +del sa[4] + +It should raise an IndexError if you try to access an index beyond the end. +it should have an append() method. +Can you make it support slicing? +How else can you make it like a list? +''' +class SparseArray(): + def __init__(self, array): + #self.array = array + self.array = {} + self.len = len(array) + for i, item in enumerate(array): + if item is not 0: + self.array[i] = item + def __str__(self): + return "Sparse Array({})".format(self.array) + + def __getitem__(self, i): + if isinstance(i, slice): + print(i) + if i.stop > self.len: + raise IndexError + self.slicearray = {} + for ind in range(i.start, i.stop): + if ind in self.array: + self.slicearray[ind] = self.array[ind] + return self.slicearray + else: #simple index integer + if i in self.array: + return self.array[i] + elif i <= self.len: + return 0 + else: + raise IndexError + + def __setitem__(self, i, item): + if item is not 0: + self.array[i] = item + if i > self.len: + self.len = i + + def __delitem__(self, i): + if i in self.array: + del self.array[i] + #return self.array + + def append(self, item): + pass + self.len += 1 + self.array[self.len] = item + +my_array = [1,2,0,0,0,0,3,0,0,4] +sa = SparseArray(my_array) +print("Sparse Array:", sa.array) +print("Array virtual length:", sa.len) + +print("\nTest:") +print("Assign a value to 12:") +sa[5] = 12 +print('sa[5]:', sa[5]) +print(sa) + +print("\nAssign a value to 0:") +sa[3] = 0 # the zero won't get stored! +#print(sa) +print('sa[3]:', sa[3]) +print(sa) + +print("\nGet a value:") +print('sa[10]:', sa[10]) # it should get a zero if not set + +print("\nIt should support deleting an element by index:") +del sa[4] +del sa[1] +print("deleting sa[4], sa[1]") +print(sa) + +print("\nRaise an IndexError if you try to access an index beyond the end") +#print('sa[13]:', sa[13]) + +print("\nTry append() method:") +sa.append(4) +print(sa) + +print("\nSupport slicing") +print('sliced array:', sa[4:6]) \ No newline at end of file From ad09824aa70b28530b51fc5b417a472cc09d79cf Mon Sep 17 00:00:00 2001 From: Elaine Xu Date: Sun, 10 Mar 2019 22:04:28 -0700 Subject: [PATCH 154/367] session08 sparse array --- .../elaine_x/session08/sparse_array_ex.py | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/students/elaine_x/session08/sparse_array_ex.py b/students/elaine_x/session08/sparse_array_ex.py index df41b199..ed7ce7c3 100644 --- a/students/elaine_x/session08/sparse_array_ex.py +++ b/students/elaine_x/session08/sparse_array_ex.py @@ -6,8 +6,6 @@ #Mar 8, 2019 ########################### ''' -#import numpy as np -#import spicy.sparse ''' https://uwpce-pythoncert.github.io/PythonCertDevel/exercises/sparse_array.html @@ -45,12 +43,12 @@ ''' class SparseArray(): def __init__(self, array): - #self.array = array self.array = {} self.len = len(array) for i, item in enumerate(array): if item is not 0: self.array[i] = item + def __str__(self): return "Sparse Array({})".format(self.array) @@ -81,45 +79,47 @@ def __setitem__(self, i, item): def __delitem__(self, i): if i in self.array: del self.array[i] - #return self.array def append(self, item): - pass self.len += 1 self.array[self.len] = item -my_array = [1,2,0,0,0,0,3,0,0,4] -sa = SparseArray(my_array) -print("Sparse Array:", sa.array) -print("Array virtual length:", sa.len) -print("\nTest:") -print("Assign a value to 12:") -sa[5] = 12 -print('sa[5]:', sa[5]) -print(sa) +############################################################# +if __name__ == "__main__": -print("\nAssign a value to 0:") -sa[3] = 0 # the zero won't get stored! -#print(sa) -print('sa[3]:', sa[3]) -print(sa) + my_array = [1,2,0,0,0,0,3,0,0,4] + sa = SparseArray(my_array) + print("Sparse Array:", sa.array) + print("Array virtual length:", sa.len) -print("\nGet a value:") -print('sa[10]:', sa[10]) # it should get a zero if not set + print("\nTest:") + print("Assign a value to 12:") + sa[5] = 12 + print('sa[5]:', sa[5]) + print(sa) -print("\nIt should support deleting an element by index:") -del sa[4] -del sa[1] -print("deleting sa[4], sa[1]") -print(sa) + print("\nAssign a value to 0:") + sa[3] = 0 # the zero won't get stored! + #print(sa) + print('sa[3]:', sa[3]) + print(sa) + + print("\nGet a value:") + print('sa[10]:', sa[10]) # it should get a zero if not set + + print("\nIt should support deleting an element by index:") + del sa[4] + del sa[1] + print("deleting sa[4], sa[1]") + print(sa) -print("\nRaise an IndexError if you try to access an index beyond the end") -#print('sa[13]:', sa[13]) + print("\nRaise an IndexError if you try to access an index beyond the end") + #print('sa[13]:', sa[13]) -print("\nTry append() method:") -sa.append(4) -print(sa) + print("\nTry append() method:") + sa.append(4) + print("appending 4 to the last number:", sa) -print("\nSupport slicing") -print('sliced array:', sa[4:6]) \ No newline at end of file + print("\nSupport slicing") + print('sliced array:', sa[4:6]) \ No newline at end of file From 5cf647ac63d3e2987c6e6ace98c345b23fadea13 Mon Sep 17 00:00:00 2001 From: sdlipp Date: Sun, 10 Mar 2019 23:00:47 -0700 Subject: [PATCH 155/367] Fixing error with __add__ and __mul__ --- students/ScottL/session08/circle_class.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/students/ScottL/session08/circle_class.py b/students/ScottL/session08/circle_class.py index 5a36b2ce..f4f61669 100644 --- a/students/ScottL/session08/circle_class.py +++ b/students/ScottL/session08/circle_class.py @@ -39,10 +39,10 @@ def __repr__(self): return f"Circle({self.radius})" def __add__(self, other): - return f"Circle({self.radius + other.radius})" + return Circle(self.radius + other.radius) def __mul__(self, other): - return f"Circle({self.radius * other})" + return Circle(self.radius * other) __rmul__ = __mul__ @@ -66,7 +66,7 @@ def volume(self): @property def area(self): - """Return the surface area of a sphere calculated from the radius property""" + """Return the surface area of a sphere calculated from the radius property.""" return 4 * math.pi * self.radius ** 2 def __str__(self): @@ -76,9 +76,9 @@ def __repr__(self): return f"Sphere({self.radius})" def __add__(self, other): - return f"Sphere({self.radius + other.radius})" + return Sphere(self.radius + other.radius) def __mul__(self, other): - return f"Sphere({self.radius * other})" + return Sphere(self.radius * other) __rmul__ = __mul__ From 4e164de1526dda53ae55c7c6f3d7a7b3accde7d1 Mon Sep 17 00:00:00 2001 From: sdlipp Date: Sun, 10 Mar 2019 23:01:28 -0700 Subject: [PATCH 156/367] Fixing error with __add__ and __mul__ --- students/ScottL/session08/test_circle_class.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/students/ScottL/session08/test_circle_class.py b/students/ScottL/session08/test_circle_class.py index 4442c438..deafdb72 100644 --- a/students/ScottL/session08/test_circle_class.py +++ b/students/ScottL/session08/test_circle_class.py @@ -39,13 +39,13 @@ def test_repr(): def test_add(): cir1 = circle_class.Circle(3) cir2 = circle_class.Circle(4) - assert cir1 + cir2 == "Circle(7)" + assert cir1 + cir2 == circle_class.Circle(7) def test_multiply(): cir1 = circle_class.Circle(4) - assert cir1 * 2 == "Circle(8)" - assert 2 * cir1 == "Circle(8)" + assert cir1 * 2 == circle_class.Circle(8) + assert 2 * cir1 == circle_class.Circle(8) def test_less(): @@ -79,8 +79,8 @@ def test_sphere(): assert round(sph1.area, 1) == round(4 * 3.1415 * 3 ** 2, 1) assert sph1.__str__() == "Sphere with a radius of: 3" assert sph1.__repr__() == "Sphere(3)" - assert sph1 + sph2 == "Sphere(7)" - assert sph1 * 2 == "Sphere(6)" - assert 4 * sph1 == "Sphere(12)" + assert sph1 + sph2 == circle_class.Sphere(7) + assert sph1 * 2 == circle_class.Sphere(6) + assert 4 * sph1 == circle_class.Sphere(12) assert sph1 < sph2 assert sph2 > sph1 From a043e1d8393d2d1b9649d1007993cf8abb91222c Mon Sep 17 00:00:00 2001 From: woosukjeung <47073569+woosukjeung@users.noreply.github.com> Date: Sun, 10 Mar 2019 23:15:03 -0700 Subject: [PATCH 157/367] Create test --- students/WooseokJ/Lesson 8/test | 1 + 1 file changed, 1 insertion(+) create mode 100644 students/WooseokJ/Lesson 8/test diff --git a/students/WooseokJ/Lesson 8/test b/students/WooseokJ/Lesson 8/test new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/students/WooseokJ/Lesson 8/test @@ -0,0 +1 @@ + From fca7bc18c53d9d7f9d9a57f7284c44bdbdd29bf3 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 11 Mar 2019 07:40:58 -0700 Subject: [PATCH 158/367] Circle update --- students/jeff_shabani/session08/circle.py | 1 + 1 file changed, 1 insertion(+) diff --git a/students/jeff_shabani/session08/circle.py b/students/jeff_shabani/session08/circle.py index f4a1ebd4..4a2e04db 100644 --- a/students/jeff_shabani/session08/circle.py +++ b/students/jeff_shabani/session08/circle.py @@ -101,3 +101,4 @@ def __repr__(self): def __str__(self): return f'Sphere with radius of {self.radius} volume of ' \ f'{self.volume()} & surface area of {self.area()}' + From 78f5ef16aabedd0e078715a5d822e2683daaad09 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 11 Mar 2019 07:42:14 -0700 Subject: [PATCH 159/367] Circle update --- .../office_hours_code/class_inheritence.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 examples/office_hours_code/class_inheritence.py diff --git a/examples/office_hours_code/class_inheritence.py b/examples/office_hours_code/class_inheritence.py new file mode 100644 index 00000000..daef02b3 --- /dev/null +++ b/examples/office_hours_code/class_inheritence.py @@ -0,0 +1,38 @@ +class rectangle: + def __init__(self, width, length): + self.width = width + self.length = length + + def area(self): + return self.width * self.length + + def present_figure(self): + return f'This figure has a width of {self.width}, a length of {self.length} and an area of {self.area()}' + + +class square(rectangle): + # pass + def __init__(self, side): + super().__init__(side, side) + + # def present_square(self): + # return self.present_figure() + + def present_figure(self): + return f'{super().present_figure()}. The figure is a square.' + + +def main(): + # first_rectangle = rectangle(10, 5) + # print(first_rectangle.area()) + # print(first_rectangle.present_figure()) + + # first_square = square(10, 10) + first_square = square(10) + print(first_square.area()) + print(first_square.present_figure()) + # print(first_square.present_square()) + + +if __name__ == '__main__': + main() \ No newline at end of file From 79468e6dc1cdc78f99e221e8099608927b1e8911 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 11 Mar 2019 08:01:21 -0700 Subject: [PATCH 160/367] html_render update --- .../jeff_shabani/session07/html_render.py | 154 ++++++++++-------- 1 file changed, 88 insertions(+), 66 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index 17374899..d1a4bad2 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -5,13 +5,14 @@ """ import functools + # This is the framework for the base class class Element(object): - indent = ' ' * 2 + indent = '' tag = 'html' - def __init__(self, content=None, **attrs): - self.attrs = attrs + def __init__(self, content=None, **kwargs): + self.attrs = kwargs if content: self.content = [content] else: @@ -28,15 +29,15 @@ def _end_tag(self): def append(self, new_content): self.content.append(new_content) - def render(self, file_name, cur_indent=''): + def render(self, file_name, indent='', ind_count=0): # Writes the opening tag file_name.write(f'{self._front_tag()}\n') for content_line in self.content: if hasattr(content_line, 'render'): - content_line.render(file_name) + content_line.render(file_name, indent, ind_count + 1) else: - file_name.write(f'{content_line}\n') + file_name.write(f'{self.indent}{indent}{content_line}\n') file_name.write(f'{self._end_tag()}\n') @@ -46,9 +47,10 @@ class Html(Element): """ tag = 'html' - def render(self, file_name): + def render(self, file_name, indent="", ind_count=0): + self.indent = indent file_name.write(f'\n') - super().render(file_name) + super().render(file_name, indent) class P(Element): @@ -68,20 +70,23 @@ class for p tag """ Step 3: print on one line """ -class OneLineTag(Element): + +class OneLineTag(Element): tag = 'Title' - def render(self, file_name, cur_indent=''): + def render(self, file_name, indent="", ind_count=0): """ Renders elements on a single line. - :param file_name: - :param cur_indent: + :param file_name: Rendered object destination + :param indent: Indentation level + :param ind_count: Number of times indentation is to be applied """ - file_name.write(f'{self._front_tag()} ') + self.indent = indent * ind_count + file_name.write(f'{self.indent}{self._front_tag()[:-1]} ') for k, v in self.attrs.items(): file_name.write(f'{k}="{v}"') - file_name.write(f'{self._front_tag()}') + file_name.write(f'>') file_name.write(f'{self.content[0]}') file_name.write(f'{self._end_tag()}') @@ -90,84 +95,101 @@ def append(self, new_content): class Head(Element): - tag = "head" - """ Step 5: Self closing tag """ + class SelfClosingTag(Element): - tag = 'br' + + def __init__(self, content=None, **kwargs): + + if content: raise TypeError + self.attrs = kwargs def append(self, new_content): raise NotImplementedError - def render(self, file_name): + + def render(self, file_name, indent="", ind_count=0): """ - if conent is entered this tells user that self closing tags + if content is entered this tells user that self closing tags can't have conent and resets the conent to an empty string. """ + self.indent = indent * ind_count + if self.content: raise TypeError - file_name.write(f'{self._front_tag()[:-1]}') + file_name.write(f'{self.indent}{self._front_tag()[:-1]}') for k, v in self.attrs.items(): file_name.write(f'{k.rjust(len(k) + 1)}="{v}" />') + + + """ Step 6 """ -class A(OneLineTag): +class A(OneLineTag): tag = 'a' - def __init__(self, link, content=None, **attrs): - if not (content and link): raise TypeError - - attrs['href'] = link - super().__init__(content, **attrs) - - # def __init__(self, link, content): - # self.link = link - # self.content = content - # #super(Element).__init__() - # - # def render(self, file_name): - # filename.write() - # head = 'a href=' - # tail = 'a' - # outtext = f'<{head}"{self.link}">{self.content}' - # with open(f'{file_name}.html', 'w') as file: - # file.write(outtext) -# -# class Ul(Element): -# """ -# Step 7: Ul class -# """ -# ul = [] -# -# class Li(Element): -# """ -# Step 7: Li class -# """ -# list_element = '' -# - -# -# class Meta(SelfClosingTag): -# """ -# add meta tag -# """ -# -# def __init__(self, content=None, tag = 'meta charset="UTF-8"'): -# super().__init__(content, tag) - -# if __name__ == '__main__': -# -# olt = OneLineTag('this is william') -# olt.render(olt, 'tag') + def __init__(self, link, content=None, **kwargs): + if not (content and link): + raise TypeError + + kwargs['href'] = link + super().__init__(content, **kwargs) + + +class Hr(SelfClosingTag): + + tag = 'hr' + + +#
              is XHTML format +class Br(SelfClosingTag): + tag = 'br' + + def __init__(self, content=None, **kwargs): + """ + __init__ method for Br class. + Checks that no attributes were passed then calls super().__init__ + :param content: Content that is to be added to the instance content and later rendered. + :param kwargs: br elements accept no attributes. Raises TypeError is passed in. + """ + if kwargs: raise TypeError + + super().__init__(content, **kwargs) + + +class Ul(Element): + """ + Step 7: Ul class + """ + tag = 'ul' + + def __init__(self, content=None, **kwargs): + self.content = [] + self.attrs = kwargs + + +class Li(Element): + """ + Step 7: Li class + """ + list_element = '' + + +class Meta(SelfClosingTag): + """ + add meta tag + """ + + tag = 'meta' From 0cf0e7bb7612d60a361d4a042d36cf109c400155 Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 11 Mar 2019 08:09:43 -0700 Subject: [PATCH 161/367] Circle update --- .../jeff_shabani/session07/html_render.py | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/students/jeff_shabani/session07/html_render.py b/students/jeff_shabani/session07/html_render.py index d1a4bad2..31a4a3cf 100644 --- a/students/jeff_shabani/session07/html_render.py +++ b/students/jeff_shabani/session07/html_render.py @@ -76,12 +76,7 @@ class OneLineTag(Element): tag = 'Title' def render(self, file_name, indent="", ind_count=0): - """ - Renders elements on a single line. - :param file_name: Rendered object destination - :param indent: Indentation level - :param ind_count: Number of times indentation is to be applied - """ + self.indent = indent * ind_count file_name.write(f'{self.indent}{self._front_tag()[:-1]} ') for k, v in self.attrs.items(): @@ -123,13 +118,10 @@ def render(self, file_name, indent="", ind_count=0): self.indent = indent * ind_count - if self.content: - raise TypeError file_name.write(f'{self.indent}{self._front_tag()[:-1]}') for k, v in self.attrs.items(): - file_name.write(f'{k.rjust(len(k) + 1)}="{v}" />') - - + file_name.write(f' {k}="{v}"') + file_name.write(f' />\n') """ @@ -158,12 +150,7 @@ class Br(SelfClosingTag): tag = 'br' def __init__(self, content=None, **kwargs): - """ - __init__ method for Br class. - Checks that no attributes were passed then calls super().__init__ - :param content: Content that is to be added to the instance content and later rendered. - :param kwargs: br elements accept no attributes. Raises TypeError is passed in. - """ + if kwargs: raise TypeError super().__init__(content, **kwargs) From 96d72815cc0d971c4ddd51ddf9afa1f6bfb4100c Mon Sep 17 00:00:00 2001 From: Alex Whitty Date: Mon, 11 Mar 2019 08:11:26 -0700 Subject: [PATCH 162/367] Updated circle file --- students/alex_whitty/session08/circle.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/students/alex_whitty/session08/circle.py b/students/alex_whitty/session08/circle.py index 411afe71..1b1e976e 100644 --- a/students/alex_whitty/session08/circle.py +++ b/students/alex_whitty/session08/circle.py @@ -8,12 +8,10 @@ def __init__(self, radius): @property def diameter(self): - print("in getter") return self.radius * 2 @diameter.setter def diameter(self, value): - print("in setter", value) self.radius = value / 2 From 4b1e9eaee666771f26df54b2e497da67fa28bb5c Mon Sep 17 00:00:00 2001 From: Jeff Shabani Date: Mon, 11 Mar 2019 08:15:27 -0700 Subject: [PATCH 163/367] html_render updates --- .../session07/test_html_render.py | 438 ++++++++---------- 1 file changed, 187 insertions(+), 251 deletions(-) diff --git a/students/jeff_shabani/session07/test_html_render.py b/students/jeff_shabani/session07/test_html_render.py index 559d69ed..7934bdb7 100644 --- a/students/jeff_shabani/session07/test_html_render.py +++ b/students/jeff_shabani/session07/test_html_render.py @@ -6,7 +6,6 @@ import io import pytest -import unittest # import * is often bad form, but makes it easier to test everything in a module. from html_render import * @@ -34,233 +33,154 @@ def render_result(element, ind=""): ######## # Step 1 ######## -# -# def test_init(): -# """ -# This only tests that it can be initialized with and without -# some content -- but it's a start -# """ -# e = Element() -# -# e = Element("this is some text") -# -# -# def test_append(): -# """ -# This tests that you can append text -# -# It doesn't test if it works -- -# that will be covered by the render test later -# """ -# e = Element("this is some text") -# e.append("some more text") -# -# -# def test_render_element(): -# """ -# Tests whether the Element can render two pieces of text -# So it is also testing that the append method works correctly. -# -# It is not testing whether indentation or line feeds are correct. -# """ -# e = Element("this is some text") -# e.append("and this is some more text") -# -# # This uses the render_results utility above -# file_contents = render_result(e).strip() -# -# # making sure the content got in there. -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# # make sure it's in the right order -# assert file_contents.index("this is") < file_contents.index("and this") -# -# # making sure the opening and closing tags are right. -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# # # Uncomment this one after you get the one above to pass -# # # Does it pass right away? -# def test_render_element2(): -# """ -# Tests whether the Element can render two pieces of text -# So it is also testing that the append method works correctly. -# -# It is not testing whether indentation or line feeds are correct. -# """ -# e = Element() -# e.append("this is some text") -# e.append("and this is some more text") -# -# # This uses the render_results utility above -# file_contents = render_result(e).strip() -# -# # making sure the content got in there. -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# # make sure it's in the right order -# assert file_contents.index("this is") < file_contents.index("and this") -# -# # making sure the opening and closing tags are right. -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# -# -# # # ######## -# # # # Step 2 -# # # ######## -# -# # tests for the new tags -# def test_html(): -# e = Html("this is some text") -# e.append("and this is some more text") -# -# file_contents = render_result(e).strip() -# -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# print(file_contents) -# assert file_contents.endswith("") -# -# -# def test_body(): -# e = Body("this is some text") -# e.append("and this is some more text") -# -# file_contents = render_result(e).strip() -# -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# -# def test_head(): -# """ Tests that you can add the tag """ -# -# head = Head("this is some text") -# head.append("and this is some more text") -# -# file_contents = render_result(head).strip() -# print(file_contents) -# -# assert "this is some text" in file_contents -# assert "and this is some more text" in file_contents -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# -# -# def test_p(): -# e = P("this is some text") -# e.append("and this is some more text") -# -# file_contents = render_result(e).strip() -# -# assert("this is some text") in file_contents -# assert("and this is some more text") in file_contents -# -# assert file_contents.startswith("

              ") -# assert file_contents.endswith("

              ") -# -# -# def test_sub_element(): -# """ -# tests that you can add another element and still render properly -# """ -# page = Html() -# page.append("some plain text.") -# page.append(P("A simple paragraph of text")) -# page.append("Some more plain text.") -# -# file_contents = render_result(page) -# print(file_contents) # so we can see it if the test fails -# -# # note: The previous tests should make sure that the tags are getting -# # properly rendered, so we don't need to test that here. -# assert "some plain text" in file_contents -# assert "A simple paragraph of text" in file_contents -# assert "Some more plain text." in file_contents -# assert "some plain text" in file_contents -# # but make sure the embedded element's tags get rendered! -# assert "

              " in file_contents -# assert "

              " in file_contents -# -# ####### -# # Step 3 -# ######## -# -# # Add your tests here! -# -# def test_one_line_tag(): -# """Test proper implementation""" -# olt = OneLineTag("the initial content") -# file_contents = render_result(olt).strip() -# print(file_contents) -# -# assert file_contents.startswith("") -# assert file_contents.endswith("") -# assert "the initial content" in file_contents -# assert "some more content" not in file_contents +def test_init(): + """ + This only tests that it can be initialized with and without + some content -- but it's a start + """ + e = Element() + + e = Element("this is some text") -####### -# Step 5 -######## -def test_self_closing_tag(): +def test_append(): + """ + This tests that you can append text + + It doesn't test if it works -- + that will be covered by the render test later + """ + e = Element("this is some text") + e.append("some more text") - sct = SelfClosingTag(width=400) - file_contents = render_result(sct) - print('This is the result:',file_contents) - assert file_contents.startswith('
              ') - assert f'
              ' in file_contents +def test_render_element(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + It is not testing whether indentation or line feeds are correct. + """ + e = Element("this is some text") + e.append("and this is some more text") -def test_self_closing_tag_2(): - """Test that conent cannot be appended to the self closing tag""" - sct = SelfClosingTag() + # This uses the render_results utility above + file_contents = render_result(e).strip() - with pytest.raises(NotImplementedError): - sct.append("This should not append") + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents - file_contents = render_result(sct).strip() - print(file_contents) + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") + + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + +# Uncomment this one after you get the one above to pass +# Does it pass right away? +def test_render_element2(): + """ + Tests whether the Element can render two pieces of text + So it is also testing that the append method works correctly. + + It is not testing whether indentation or line feeds are correct. + """ + e = Element() + e.append("this is some text") + e.append("and this is some more text") + + # This uses the render_results utility above + file_contents = render_result(e).strip() - assert "This should not append" not in file_contents + # making sure the content got in there. + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents + # make sure it's in the right order + assert file_contents.index("this is") < file_contents.index("and this") -def test_class_a(): - ca = A("http://google.com/", "link to google") - file_contents = render_result(ca) + # making sure the opening and closing tags are right. + assert file_contents.startswith("") + assert file_contents.endswith("") + + + +# ######## +# # Step 2 +# ######## + +# tests for the new tags +def test_html(): + e = Html("this is some text") + e.append("and this is some more text") + + file_contents = render_result(e).strip() + + assert("this is some text") in file_contents + assert("and this is some more text") in file_contents print(file_contents) + assert file_contents.endswith("") - assert f'link to google' in file_contents +def test_body(): + e = Body("this is some text") + e.append("and this is some more text") -# def test_ul_li(): -# """ Tests that you can add unordered lists and list items """ -# with pytest.raises(TypeError): -# ul = Ul("Should fail") -# -# ul = Ul(style='list-style-type:disc;') -# ul.append(Li("List item 1")) -# ul.append(Li("List item 2")) -# -# file_contents = render_result(ul).strip() -# print(file_contents) -# -# assert file_contents.startswith("