diff --git a/students/Final/Final.txt b/students/Final/Final.txt
new file mode 100644
index 0000000..e14673b
--- /dev/null
+++ b/students/Final/Final.txt
@@ -0,0 +1 @@
+Final
diff --git a/students/Final/ProductInventory.zip b/students/Final/ProductInventory.zip
new file mode 100644
index 0000000..a67c1a9
Binary files /dev/null and b/students/Final/ProductInventory.zip differ
diff --git a/students/Module04/Trigrams.py b/students/Module04/Trigrams.py
new file mode 100644
index 0000000..4200a3a
--- /dev/null
+++ b/students/Module04/Trigrams.py
@@ -0,0 +1,88 @@
+#----------------------------------------#
+# Title: Trigrams.py
+# Initial File
+# Claire Yoon,2019-02-03,New file
+#----------------------------------------#
+
+"""
+build up the trigrams dict from the list of words
+
+returns a dict with:
+ keys: word pairs
+ values: list of followers
+"""
+
+import sys
+import string
+import random
+# from string import maketrans
+
+def read_in_data(filename):
+ objFile = open(filename, "r")
+ strData = objFile.read()
+ # return text in one line
+ return strData
+
+def make_words(in_data):
+ in_data.replace(" *** START OF THIS PROJECT GUTENBERG EBOOK",'')
+ in_data = in_data.translate({ord(c): " " for c in "\"!@#$%^&*()[]{};:,/<>?\|~-=_+"})
+ words = in_data.split()
+ # print(words)
+ return words
+
+def build_trigram(words):
+
+ trigrams = {}
+ # why -2?: last two words would not have next one.
+ for i in range(len(words) - 2):
+ pair = words[i:i + 2]
+ follower = words[i + 2]
+ val = trigrams.get((pair[0], pair[1]))
+
+ if val is None :
+ val = [follower]
+ else :
+ val.append(follower)
+ trigrams.update({(pair[0], pair[1]): val})
+
+ # build up the dict here!
+ # print(trigrams)
+ return trigrams
+
+def build_text(word_pairs):
+ # returns a number between 0 and len(word_pairs) - 1
+ starting_point = random.randint(0,len(word_pairs) - 1)
+ # get word list of key of starting point
+ start_word = list(word_pairs.keys())[starting_point]
+ new_text = start_word[0] + ' ' + start_word[1]
+ # while the pair has next word
+ while(True):
+ word_list = new_text.split()
+ new_tuple = (word_list[-2] , word_list[-1])
+ # if the tuple is one of the keys of word_pairs:
+ if new_tuple in word_pairs.keys():
+ word_values = word_pairs.get(new_tuple)
+ rand_val = random.randint(0,len(word_values) - 1)
+ join_word = word_values[rand_val]
+ new_text = new_text + ' ' + join_word
+
+ # print(new_text)
+ # else: terminate the function
+ else:
+ break
+ return new_text
+
+if __name__ == "__main__":
+ # get the filename from the command line
+ try:
+ filename = sys.argv[1]
+ except IndexError:
+ print("You must pass in a filename")
+ sys.exit(1)
+
+ in_data = read_in_data(filename)
+ words = make_words(in_data)
+ word_pairs = build_trigram(words)
+ new_text = build_text(word_pairs)
+
+ print(new_text)
\ No newline at end of file
diff --git a/students/Module04/mailroom2.py b/students/Module04/mailroom2.py
new file mode 100644
index 0000000..9c0b111
--- /dev/null
+++ b/students/Module04/mailroom2.py
@@ -0,0 +1,93 @@
+#----------------------------------------#
+# Title: mailroom2.py
+# Initial File
+# Claire Yoon,2019-02-03,New file
+#----------------------------------------#
+
+
+# Convert main donor data structure to be a dict.
+donor_dict = { 'Will Gates': [10000, 20000, 300000],
+ 'Conan Obrien': [20000],
+ 'Mark Zucker' : [30000, 12000],
+ 'Jeff Bezos' : [50000],
+ 'Tom Hardy' : [12000, 40000]
+ }
+
+def thx_single():
+ while(True):
+ temp = []
+ for i in donor_dict.keys():
+ temp.append(i)
+ name = input("Please enter a full name (enter 'list' to see list): ")
+ # If user types 'list'
+ if name.lower() == 'list':
+ print(temp)
+ # If user types other than list - applies the same logic
+ else:
+ amount = float(input("Please enter amount of donation (in numbers): "))
+ if name in temp:
+ donors_amount = donor_dict.get(name)
+ donors_amount.append(amount)
+ history_amount = 0
+ for i in range(len(donors_amount)):
+ history_amount += donors_amount[i]
+ else :
+ donor_dict.update({name : amount})
+ history_amount = amount
+
+ print("\nDear", name, "\n\n I would like to thank you for your donation of $",history_amount,"so far.\n",
+ "Our organization relies on the generosity of donors such as yourself. \n Thank you once again. \n")
+ break
+ return
+
+def create_report():
+ report_lst= []
+
+ for i in donor_dict.keys():
+ report_lst.append([i, sum(donor_dict.get(i)), len(donor_dict.get(i)), sum(donor_dict.get(i))/len(donor_dict.get(i))])
+
+ print()
+ print("<>")
+
+ print("Donor Name | Total Given | Num Gifts | Average Gift\n------------------------------------------------------------")
+ for l in report_lst:
+ print ('{:<20}'.format(l[0]), end='')
+ print ('$','{:<12}'.format(l[1]), end='')
+ print ('{:<11}'.format(l[2]), end='')
+ print ('$','{:<12}'.format(l[3]))
+ print()
+
+def thx_all():
+ for i in donor_dict.keys():
+ # get donor's amount of donation
+ amount = sum(donor_dict.get(i))
+ donor_name = i.split(' ')
+ filename = "thx_letter"
+ # generate file name as : thx_letter_(firstname)_(lastname)
+ for j in range(len(donor_name)):
+ filename += '_'+(donor_name[j])
+ # open a file and write body
+ letter = open(filename, "w")
+ letter_body = str("\nDear "+ str(donor_name[0]) + ' ' + str(donor_name[1]) + ",\n\nI would like to thank you for your donation of $" + str(amount) +" so far.\n" +
+ "Our organization relies on the generosity of donors such as yourself. \n\nThank you once again. \n")
+
+ letter.write(letter_body)
+ letter.close()
+ print("\n All thank-you letters have been created. Please check your current folder. \n ")
+ return
+
+def equit():
+ exit()
+
+
+def main_menu():
+ while(True):
+ # a dict to switch between the user’s selections.
+ menu_dict = {1: thx_single, 2: create_report, 3: thx_all, 4: equit }
+ menu = int(input("Choose an action: \n 1 - Send a Thank You to a single donor \n 2 - Create a Report \n 3 - Send letters to all donors. \n 4 - Quit \n : "))
+ menu_dict.get(menu)()
+
+ return
+
+if __name__ == '__main__':
+ main_menu()
diff --git a/students/Module05/except_excercise.py b/students/Module05/except_excercise.py
new file mode 100644
index 0000000..3d6ee80
--- /dev/null
+++ b/students/Module05/except_excercise.py
@@ -0,0 +1,58 @@
+#----------------------------------------#
+# Title: except_excercise.py
+# Initial File
+# Claire Yoon,2019-02-09,New file
+#----------------------------------------#
+
+#!/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 as e:
+ joke = fun('cheese')
+# 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 Exception as e:
+ more_joke = more_fun(langs[1])
+finally:
+ last_fun()
diff --git a/students/Module05/mailroom3.py b/students/Module05/mailroom3.py
new file mode 100644
index 0000000..abf0b23
--- /dev/null
+++ b/students/Module05/mailroom3.py
@@ -0,0 +1,107 @@
+#----------------------------------------#
+# Title: mailroom3.py
+# Revised mailroom2.py
+# Claire Yoon,2019-02-09,New file
+#----------------------------------------#
+
+
+# Convert main donor data structure to be a dict.
+donor_dict = { 'Will Gates': [10000, 20000, 300000],
+ 'Conan Obrien': [20000],
+ 'Mark Zucker' : [30000, 12000],
+ 'Jeff Bezos' : [50000],
+ 'Tom Hardy' : [12000, 40000]
+ }
+
+name_mapping = {i: i.lower() for i in donor_dict.keys()}
+
+def thx_single():
+ while(True):
+ name = input("Please enter a full name (enter 'list' to see list): ")
+
+ # If user types 'list'
+ if name.lower() == 'list':
+ print([i for i in name_mapping.keys()])
+
+ # If user types other than list - applies the same logic
+ else:
+ amount = float(input("Please enter amount of donation (in numbers): "))
+ if name.lower() in name_mapping.values():
+ for camel, lower in name_mapping.items():
+ if lower == name.lower():
+ name = camel
+ donors_amount = donor_dict.get(name)
+ # append input amount value to donors_amount list
+ donors_amount.append(amount)
+ history_amount = 0
+ for i in range(len(donors_amount)):
+ history_amount += donors_amount[i]
+
+ #for newly added name
+ else :
+ name_toList = name.lower().split(' ')
+ for i in range(len(name_toList)):
+ name_toList[i] = name_toList[i].capitalize()
+ name = " ".join(name_toList)
+ new_amount = {name : [amount]}
+ donor_dict.update(new_amount)
+ print(donor_dict)
+ history_amount = amount
+ name_mapping.update({name: name.lower()})
+
+ print("\nDear", name, ",\n\nOur organization would like to thank you for your donation of $",history_amount,"so far.\n",
+ "Our organization relies on the generosity of donors such as yourself. \n Thank you once again. \n")
+ break
+ return
+
+def create_report():
+ report_lst= []
+
+ #using comprehension
+ [report_lst.append([i, sum(donor_dict.get(i)), len(donor_dict.get(i)), sum(donor_dict.get(i))/len(donor_dict.get(i))]) for i in donor_dict.keys()]
+ print()
+ print("\t\t\t\t<>")
+
+ print("Donor Name | Total Given | Num Gifts | Average Gift\n------------------------------------------------------------")
+ for l in report_lst:
+ print ('{:<20}'.format(l[0]), end='')
+ print ('$','{:<12}'.format(l[1]), end='')
+ print ('{:<11}'.format(l[2]), end='')
+ print ('$','{:<12}'.format(l[3]))
+ print()
+
+def thx_all():
+ for i in donor_dict.keys():
+ # get donor's amount of donation
+ amount = sum(donor_dict.get(i))
+ donor_name = i.split(' ')
+ filename = '_'.join(donor_name) + '_Thx_Letter'
+ # open a file and write body
+ letter = open(filename, "w")
+ letter_body = str("\nDear "+ str(donor_name[0]) + ' ' + str(donor_name[1]) + ",\n\nOur organization would like to thank you for your donation of $" + str(amount) +" so far.\n" +
+ "Our organization relies on the generosity of donors such as yourself. \n\nThank you once again. \n")
+
+ letter.write(letter_body)
+ letter.close()
+ print("\n All thank-you letters have been created. Please check your current folder. \n ")
+ return
+
+def equit():
+ exit()
+
+def main_menu():
+ while(True):
+ # a dict to switch between the user’s selections.
+ menu_dict = {1: thx_single, 2: create_report, 3: thx_all, 4: equit}
+ try:
+ menu = int(input("Choose an action: \n 1 - Send a Thank You to a single donor \n 2 - Create a Report \n 3 - Send letters to all donors. \n 4 - Quit \n : "))
+ menu_dict.get(menu)()
+ except ValueError as e :
+ print("** Warning: Please enter number **")
+ except TypeError as e:
+ print("** Warning: Please enter valid menu (1 - 4) **")
+
+ return
+
+if __name__ == '__main__':
+ main_menu()
\ No newline at end of file
diff --git a/students/Module06/mailroom4.py b/students/Module06/mailroom4.py
new file mode 100644
index 0000000..e8955a9
--- /dev/null
+++ b/students/Module06/mailroom4.py
@@ -0,0 +1,137 @@
+#----------------------------------------#
+# Title: mailroom4.py
+# Revised mailroom3.py
+# Claire Yoon,2019-02-18,New file
+#----------------------------------------#
+
+# Convert main donor data structure to be a dict.
+donor_dict = { 'Will Gates': [10000, 20000, 300000],
+ 'Conan Obrien': [20000],
+ 'Mark Zucker' : [30000, 12000],
+ 'Jeff Bezos' : [50000],
+ 'Tom Hardy' : [12000, 40000]
+ }
+
+name_mapping = {i: i.lower() for i in donor_dict.keys()}
+
+# listing donors
+def print_list():
+ return [i for i in name_mapping.keys()]
+
+# adding or updating donors
+def update_donor(name, amount):
+ new_amount = {name: [amount]}
+ donor_dict.update(new_amount)
+ name_mapping.update({name: name.lower()})
+ return (donor_dict)
+
+# generating thank you text
+def write_thx(name, history_amount):
+ return "\nDear {},\n\nOur organization would like to thank you for your donation of ${} so far.\nOur organization relies on the generosity of donors such as yourself.\n\nThank you once again. \n".format(name, history_amount)
+
+# Unit tests should test the data manipulation logic code: generating thank you text, adding or updating donors, and listing donors.
+def thx_single():
+ while(True):
+ name = input("Please enter a full name (enter 'list' to see list): ")
+ name = name.rstrip().lstrip()
+
+ # If user types 'list'
+ # listing donors
+ if name.lower() == 'list':
+ print(print_list())
+
+ # If user types other than list - applies the same logic
+ else:
+ amount = float(input("Please enter amount of donation (in numbers): "))
+
+ #for existing name
+ if name.lower() in name_mapping.values():
+ for camel, lower in name_mapping.items():
+ if lower == name.lower():
+ name = camel
+ donors_amount = donor_dict.get(name)
+ # append input amount value to donors_amount list
+ donors_amount.append(amount)
+ print("Donor list has been updated: ",donor_dict)
+ history_amount = 0
+ for i in range(len(donors_amount)):
+ history_amount += donors_amount[i]
+
+ #for newly added name
+ else :
+ name_toList = name.lower().split(' ')
+ for i in range(len(name_toList)):
+ name_toList[i] = name_toList[i].capitalize()
+ name = " ".join(name_toList)
+ # adding or updating donors
+ print("Donor list has been updated: ",update_donor(name,amount))
+ history_amount = amount
+ # generating thank you text
+ print(write_thx(name, history_amount))
+ break
+ return
+
+def get_report():
+ #data logic
+ #using comprehension
+ report_lst = []
+ [report_lst.append([i, int(sum(donor_dict.get(i))), len(donor_dict.get(i)),
+ round((sum(donor_dict.get(i)) / len(donor_dict.get(i))), 2)]) for i in donor_dict.keys()]
+ print(report_lst)
+ return report_lst
+
+def print_report(report):
+ print()
+ print("\t\t\t\t<>")
+ # user presentation
+ print("Donor Name | Total Given | Num Gifts | Average Gift\n------------------------------------------------------------")
+ for l in report:
+ print ('{:<20}'.format(l[0]), end='')
+ print ('$','{:<12}'.format(l[1]), end='')
+ print ('{:<11}'.format(l[2]), end='')
+ print ('$','{:<12}'.format(l[3]))
+ print()
+
+def display_report():
+
+ print_report(get_report())
+
+def write_file(key):
+ amount = sum(donor_dict.get(key))
+ donor_name = key.split(' ')
+ filename = '_'.join(donor_name) + '_Thx_Letter'
+ # open a file and write body
+ letter = open(filename, "w")
+ letter_body = letter_text(donor_name[0], donor_name[1], amount)
+ letter.write(letter_body)
+ letter.close()
+
+def letter_text(fname, lname, amount):
+ return "\nDear {} {},\n\nOur organization would like to thank you for your donation of ${} so far.\nOur organization relies on the generosity of donors such as yourself.\n\nThank you once again. \n".format(fname, lname, amount)
+
+
+def thx_all():
+ for key in donor_dict.keys():
+ write_file(key)
+ print("\n All thank-you letters have been created. Please check your current folder. \n ")
+ return
+
+def equit():
+ exit()
+
+def main_menu():
+ while(True):
+ # a dict to switch between the user’s selections.
+ menu_dict = {1: thx_single, 2: display_report, 3: thx_all, 4: equit}
+ try:
+ menu = int(input("Choose an action: \n 1 - Send a Thank You to a single donor \n 2 - Create a Report \n 3 - Send letters to all donors. \n 4 - Quit \n : "))
+ menu_dict.get(menu)()
+ except ValueError as e :
+ print("** Warning: Please enter number **")
+ except TypeError as e:
+ print("** Warning: Please enter valid menu (1 - 4) **")
+
+ return
+
+if __name__ == '__main__':
+ main_menu()
diff --git a/students/Module06/test_mailroom4.py b/students/Module06/test_mailroom4.py
new file mode 100644
index 0000000..bf92c73
--- /dev/null
+++ b/students/Module06/test_mailroom4.py
@@ -0,0 +1,30 @@
+#----------------------------------------#
+# Title: test_mailroom4.py
+# Derived from mailroom4.py
+# Claire Yoon,2019-02-18,New file
+#----------------------------------------#
+
+import os.path
+from mailroom4 import print_list, update_donor, write_thx, get_report, donor_dict, letter_text
+
+def test_write_file():
+ for key in donor_dict.keys():
+ donor_name = key.split(' ')
+ filename = '_'.join(donor_name) + '_Thx_Letter'
+ assert os.path.isfile(filename) == True
+
+def test_letter_text():
+ assert letter_text("Dwight","Schrute",12345) == "\nDear Dwight Schrute,\n\nOur organization would like to thank you for your donation of $12345 so far.\nOur organization relies on the generosity of donors such as yourself.\n\nThank you once again. \n"
+
+def test_print_list():
+ assert print_list() == ['Will Gates', 'Conan Obrien', 'Mark Zucker', 'Jeff Bezos', 'Tom Hardy']
+
+def test_update_donor():
+ assert update_donor('Brad Pitt', 30000) == {'Will Gates': [10000, 20000, 300000], 'Conan Obrien': [20000], 'Mark Zucker': [30000, 12000], 'Jeff Bezos': [50000], 'Tom Hardy': [12000, 40000], 'Brad Pitt': [30000.0]}
+
+def test_write_thx():
+ assert write_thx("Brad Pitt", 30000) == "\nDear Brad Pitt,\n\nOur organization would like to thank you for your donation of $30000 so far.\nOur organization relies on the generosity of donors such as yourself.\n\nThank you once again. \n"
+
+def test_get_report():
+ assert get_report() == [['Will Gates', 330000, 3, 110000.0], ['Conan Obrien', 20000, 1, 20000.0], ['Mark Zucker', 42000, 2, 21000.0], ['Jeff Bezos', 50000, 1, 50000.0], ['Tom Hardy', 52000, 2, 26000.0], ["Brad Pitt", 30000, 1, 30000.0]]
+
diff --git a/students/Module07/html_render.py b/students/Module07/html_render.py
new file mode 100644
index 0000000..a8b7ebe
--- /dev/null
+++ b/students/Module07/html_render.py
@@ -0,0 +1,184 @@
+#!/usr/bin/env python3
+
+"""
+A class-based system for rendering html.
+"""
+
+#----------------------------------------#
+# Title: html_render.py
+# Derived from render.py
+# Claire Yoon,2019-02-23,New file
+#----------------------------------------#
+
+
+# This is the framework for the base class
+class Element(object):
+ tag = "html"
+
+ def __init__(self, content=None, **kwargs):
+ if content is not None:
+ self.contents = [content]
+ else:
+ self.contents = []
+
+ # e = P("A paragraph of text", style="text-align: center", id="intro")
+ if kwargs is not None:
+ self.attributes = {}
+ for k, v in kwargs.items():
+ self.attributes.update( {k : v})
+ else:
+ pass
+
+
+ def append(self, new_content):
+ self.contents.append(new_content)
+
+ def ToString(self):
+ return str(self.content)
+
+ def _open_tag(self):
+ return ("<{}>".format(self.tag))
+ def _close_tag(self):
+ return ("<{} />".format(self.tag))
+
+ def render(self, out_file):
+ # out_file.write("just something as a place holder...")
+ """
+ A paragraph of text
+
"""
+ # out_file.write(self._open_tag())
+ # out_file.write("\n")
+
+ for content in self.contents:
+ # out_file.write("<{}>\n".format(self.tag))
+ open_tag = ["<{}".format(self.tag)]
+
+ if self.attributes is not None:
+ for k, v in self.attributes.items():
+ open_tag.append(' ')
+ open_tag.append(k)
+ open_tag.append('=\"')
+ open_tag.append(v)
+ open_tag.append('"')
+ open_tag.append(">\n")
+ out_file.write("".join(open_tag))
+
+ try:
+ content.render(out_file)
+ except AttributeError:
+ out_file.write(content)
+ out_file.write("\n")
+ out_file.write("{}>\n".format(self.tag))
+ # out_file.write(self._close_tag())
+ # out_file.write("\n")
+
+class Html(Element):
+ tag = 'html'
+
+class Body(Element):
+ tag = 'body'
+
+class P(Element):
+ tag = 'p'
+
+class Head(Element):
+ tag = 'head'
+
+class OneLineTag(Element):
+ # def render(self, out_file):
+ # for content in self.contents:
+ # out_file.write("<{}>".format((self.tag)))
+ # try:
+ # content.render(out_file)
+ # except AttributeError:
+ # out_file.write(content)
+ # out_file.write("{}>\n".format(self.tag))
+ # def render(self, out_file):
+ # out_file.write("<{}>".format(self.tag))
+ # out_file.write(self.contents[0])
+ # out_file.write("{}>\n".format(self.tag))
+
+ # link
+ def render(self, out_file):
+ # out_file.write("<{}>".format(self.tag))
+ # out_file.write(self.contents[0])
+ # # print(self.contents)
+ # print(self.contents[0])
+ # print(self.attributes)
+ # out_file.write("{}>\n".format(self.tag))
+
+ for content in self.contents:
+ open_tag = ["<{}".format(self.tag)]
+
+ if self.attributes is not None:
+ for k, v in self.attributes.items():
+ open_tag.append(' ')
+ open_tag.append(k)
+ open_tag.append('=\"')
+ open_tag.append(v)
+ open_tag.append('"')
+ open_tag.append(">")
+ out_file.write("".join(open_tag))
+
+ try:
+ content.render(out_file)
+ except AttributeError:
+ out_file.write(content)
+ out_file.write("{}>\n".format(self.tag))
+
+
+ def append(self, new_content):
+ raise NotImplementedError
+
+
+class Title(OneLineTag):
+ tag = "title"
+
+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):
+ open_tag = ["<{}".format(self.tag)]
+
+ if self.attributes is not None:
+ for k, v in self.attributes.items():
+ open_tag.append(' ')
+ open_tag.append(k)
+ open_tag.append('=\"')
+ open_tag.append(str(v))
+ open_tag.append('"')
+ open_tag.append(" />\n")
+ outfile.write("".join(open_tag))
+
+ # try:
+ # content.render(out_file)
+ # except TypeError:
+ # out_file.write(content)
+ # outfile.write("\n")
+ # outfile.write("{}>\n".format(self.tag))
+ def append(self, *args):
+ raise TypeError("You can not add content to a SelfClosingTag")
+
+class Hr(SelfClosingTag):
+ tag = "hr"
+
+class Br(SelfClosingTag):
+ tag = "br"
+
+
+# class A(OneLineTag):
+# def __init__(self, link, content):
+# self.link = link
+# self.content = content
+
+class A(OneLineTag):
+ tag = 'a'
+
+ def __init__(self, link, content=None, **kwargs):
+ kwargs['href'] = link
+ # print(kwargs)
+ # print(link)
+ super().__init__(content, **kwargs)
\ No newline at end of file
diff --git a/students/Module07/run_html_render.py b/students/Module07/run_html_render.py
new file mode 100644
index 0000000..f00daef
--- /dev/null
+++ b/students/Module07/run_html_render.py
@@ -0,0 +1,237 @@
+ #!/usr/bin/env python3
+
+#----------------------------------------#
+# Title: run_html_render.py
+# Derived from run_html_render.py
+# Claire Yoon,2019-02-23,New file
+#----------------------------------------#
+
+
+"""
+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.
+
+## 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/Module07/test_html_render.py b/students/Module07/test_html_render.py
new file mode 100644
index 0000000..021e237
--- /dev/null
+++ b/students/Module07/test_html_render.py
@@ -0,0 +1,362 @@
+"""
+test code for html_render.py
+
+This is just a start -- you will need more tests!
+"""
+
+#----------------------------------------#
+# Title: test_html_render.py
+# Derived from test_render.py
+# Claire Yoon,2019-02-23,New file
+#----------------------------------------#
+
+
+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")
+ print(file_contents)
+ # 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.startswith("")
+ 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
+ print(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_title():
+ # Title("Title of the page")
+ e = Title("Title of the page")
+
+ file_contents = render_result(e).strip()
+
+ assert("Title of the page") 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")
+
+
+
+########
+# Step 4
+########
+
+# Add your tests here!
+
+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("") > file_contents.index('id="intro"')
+ print(file_contents[:file_contents.index(">")].count(" "))
+ assert file_contents[:file_contents.index(">")].count(" ") == 3
+
+########
+# Step 5
+########
+
+def test_hr():
+ """a simple horizontal rule with no attributes"""
+ hr = Hr()
+ file_contents = render_result(hr)
+ print(file_contents)
+ 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_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("")
diff --git a/students/Module3/list_lab.py b/students/Module3/list_lab.py
new file mode 100644
index 0000000..8502f83
--- /dev/null
+++ b/students/Module3/list_lab.py
@@ -0,0 +1,81 @@
+#----------------------------------------#
+# Title: list_lab.py
+# Initial File
+# Claire Yoon,2019-01-27,New file
+#----------------------------------------#
+
+#Series 1
+
+lst = ["Apples", "Pears", "Oranges","Peaches"]
+print(lst)
+fruit1 = input("Type another fruit that you want to add: ")
+lst.append(fruit1)
+print(lst)
+numb = input("Type a number that you want to check: ")
+print("You typed",numb, ", and corresponding fruit is",lst[int(numb)-1])
+
+fruit2 = input("Type another fruit that you want to add: ")
+temp = [fruit2]
+lst = temp + lst
+print(lst)
+
+fruit3 = input("Type another fruit that you want to add: ")
+lst.insert(0,fruit3)
+print(lst)
+
+for i in range(len(lst)):
+ if lst[i][:1].lower() == 'p':
+ print(lst[i])
+
+#Series 2
+lst2 = lst
+print(lst2)
+lst2 = lst2[:-1]
+print(lst2)
+
+fruit4 = input("Type a fruit that you want to delete: ")
+temp2 = []
+for i in range(len(lst2)):
+ if fruit4.lower() != lst2[i].lower():
+ temp2.append(lst2[i])
+lst2 = temp2
+print(lst2)
+
+#bonus
+# lst2 = lst2 + lst2
+# temp2 = []
+# for i in range(len(lst2)):
+# if fruit4.lower() != lst2[i].lower():
+# temp2.append(lst2[i])
+# lst2 = temp2
+# print(lst2)
+
+
+#Series 3
+lst3 = lst
+
+newlst = []
+for i in range(len(lst3)):
+ ans = input("Do you like "+lst3[i]+"? :")
+ if ans.lower() == 'yes':
+ newlst.append(lst3[i])
+ elif ans.lower() == 'no':
+ pass
+ else:
+ print('Please use valid answer (yes/no)')
+
+lst3 = newlst
+print(lst3)
+
+
+#Series 4
+lst4 = lst
+
+lst4cp = []
+for i in range(len(lst4)):
+ lst4cp.append(lst4[i][::-1])
+
+lst = lst[:-1]
+print(lst)
+
+print(lst4cp)
diff --git a/students/Module3/mailroom.py b/students/Module3/mailroom.py
new file mode 100644
index 0000000..28066f8
--- /dev/null
+++ b/students/Module3/mailroom.py
@@ -0,0 +1,87 @@
+#----------------------------------------#
+# Title: mailroom.py
+# Initial File
+# Claire Yoon,2019-01-28,New file
+#----------------------------------------#
+
+# data structure for - a list of your donors, a history of the amounts they have donated.
+# populate at first with at least five donors
+# with between 1 and 3 donations each
+
+#prompt - to choose from a menu of 3 actions: “Send a Thank You”, “Create a Report” or “quit”.
+
+donor_list = [('Will Gates', 10000), ('Will Gates', 20000), ('Will Gates', 300000),
+ ('Conan Obrien', 20000),
+ ('Mark Zucker', 30000), ('Mark Zucker', 12000),
+ ('Jeff Bezos', 50000),
+ ('Tom Hardy', 12000), ('Tom Hardy', 40000)]
+
+def main_menu():
+
+ while(True):
+ menu = input("Please choose the number to enter one of the menus. \n 1 - Send a Thank you \n 2 - Create a Report \n 3 - quit \n : ")
+ if menu == '1' :
+ send_Thx()
+ elif menu == '2' :
+ create_Report()
+ elif menu == '3' :
+ break
+ else :
+ print("Please enter a valid menu")
+
+def send_Thx():
+ while(True):
+ temp = []
+ for i in range(len(donor_list)):
+ if donor_list[i][0] not in temp:
+ temp.append(donor_list[i][0])
+ name = input("Please enter a full name (enter 'list' to see list): ")
+ # If user types 'list'
+ if name.lower() == 'list':
+ print(temp)
+ # If user types other than list - applies the same logic
+ else:
+ amount = float(input("Please enter amount of donation (in numbers): "))
+ donor_list.append((name, amount))
+
+ history_amount = 0
+ for i in range(len(donor_list)):
+ if(donor_list[i][0] == name):
+ history_amount += donor_list[i][1]
+
+ print("Dear ", name, "\n\n I would like to thank you for your donation of $",history_amount,"so far.\n",
+ "Our organization relies on the generosity of donors such as yourself. \n Thank you once again. \n")
+
+ break
+ return
+
+def create_Report():
+ temp_lst = []
+ report_lst= []
+
+ for i in range(len(donor_list)):
+ if donor_list[i][0] not in temp_lst:
+ temp_lst.append(donor_list[i][0])
+
+ for i in range(len(temp_lst)):
+ report_lst.append([temp_lst[i], 0.0, 0, 0.0])
+
+ for i in range(len(temp_lst)):
+ for j in range(len(donor_list)):
+ if donor_list[j][0] == temp_lst[i]:
+ name = donor_list[j][0]
+ amount = donor_list[j][1]
+ report_lst[i] = ([name, amount + report_lst[i][1], report_lst[i][2] + 1, (amount + report_lst[i][1])/(report_lst[i][2] + 1)])
+
+
+ print("<>")
+
+ print("Donor Name | Total Given | Num Gifts | Average Gift\n------------------------------------------------------------")
+ for l in report_lst:
+ print ('{:<20}'.format(l[0]), end='')
+ print ('$','{:<12}'.format(l[1]), end='')
+ print ('{:<11}'.format(l[2]), end='')
+ print ('$','{:<12}'.format(l[3]))
+
+if __name__ == '__main__':
+ main_menu()
\ No newline at end of file
diff --git a/students/Module3/slicing_lab.py b/students/Module3/slicing_lab.py
new file mode 100644
index 0000000..66b6e8f
--- /dev/null
+++ b/students/Module3/slicing_lab.py
@@ -0,0 +1,45 @@
+#----------------------------------------#
+# Title: slicing_lab.py
+# Initial File
+# Claire Yoon,2019-01-27,New file
+#----------------------------------------#
+
+# with the first and last items exchanged.
+def exchange_first_last(seq):
+ return seq[-1:] + seq[1:-1]+ seq[:1]
+
+assert exchange_first_last("this is a string") == "ghis is a strint"
+assert exchange_first_last((2, 54, 13, 12, 5, 32)) == (32, 54, 13, 12, 5, 2)
+
+# with every other item removed.
+
+def every_other_removed(seq):
+ return seq[::2]
+
+assert every_other_removed("this is a string") == "ti sasrn"
+assert every_other_removed((2, 54, 13, 12, 5, 32)) == (2, 13, 5)
+
+# with the first 4 and the last 4 items removed, and then every other item in the remaining sequence.
+def remove4_every_other(seq):
+ if(len(seq) <= 8):
+ return print("Length should be bigger than 8")
+ seq = seq[4:-4]
+ return seq[::2]
+
+assert remove4_every_other("this is a string") == " sas"
+assert remove4_every_other((2, 54, 13, 12, 5, 32, 45, 28, 14, 8, 72)) == (5, 45)
+
+# with the elements reversed (just with slicing).
+def reverse(seq):
+ return seq[::-1]
+
+assert reverse("this is a string") == "gnirts a si siht"
+assert reverse((2, 54, 13, 12, 5, 32)) == (32, 5, 12, 13, 54, 2)
+
+# with the last third, then first third, then the middle third in the new order.
+def new_order(seq):
+ l = len(seq)
+ return seq[int(l*(2/3)):] + seq[:int(l*(1/3))] + seq[int(l*(1/3)):int(l*(2/3))]
+
+assert new_order("this is a string") == "stringthis is a "
+assert new_order((2, 54, 13, 12, 5, 32)) == (5, 32, 2, 54, 13, 12)
diff --git a/students/Module3/strformat_lab.py b/students/Module3/strformat_lab.py
new file mode 100644
index 0000000..47f5eb9
--- /dev/null
+++ b/students/Module3/strformat_lab.py
@@ -0,0 +1,52 @@
+#----------------------------------------#
+# Title: strformat_lab.py
+# Initial File
+# Claire Yoon,2019-01-27,New file
+#----------------------------------------#
+
+# Task One
+print('Task One: ')
+tpl = ( 2, 123.4567, 10000, 12345.67)
+print('file_' + '{0:0>3}'.format(tpl[0]) , " : " , "{:.2f}".format(float(tpl[1])) , ', ' , '{:0.2e}'.format(float(tpl[2])), ', ' , '{:3.2e}'.format(float(tpl[3])))
+print('')
+
+#Task Two
+print('Task Two: ')
+print('file_' + '{0:0>3}'.format(tpl[0]) , " : " , "{:.2f}".format(float(tpl[1])) , ', ' , '{:0.2e}'.format(float(tpl[2])), ', ' , '{:3.2e}'.format(float(tpl[3])))
+print('')
+
+# #Task Three
+print('Task Three: ')
+tpl3 = (2,3,5,7,9)
+
+def formatter(in_tuple):
+ num = (len(in_tuple))
+ form_string = "the "+str(num)+" numbers are: "
+ # form_string = 'the ',len(in_tuple),' numbers are:'
+ for i in range(num-1):
+ form_string += "{:d} , "
+ form_string += "{:d}"
+ return form_string.format(*in_tuple)
+
+print(formatter(tpl3))
+print('')
+
+#Task Four
+print('Task Four: ')
+tpl4 = (4, 30, 2017, 2, 27)
+print('{0:0>2}'.format(tpl4[3]),tpl4[4],tpl4[2],'{0:0>2}'.format(tpl4[0]),tpl4[1])
+print('')
+
+#Task Five
+print('Task Five: ')
+lst5 = ['oranges', 1.3, 'lemons', 1.1]
+print(f"The weight of an {lst5[0][:-1]} is {lst5[1]} and the weight of a {lst5[2][:-1]} is {lst5[3]}")
+print(f"The weight of an {lst5[0][:-1].upper()} is {lst5[1]*1.2} and the weight of a {lst5[2][:-1].upper()} is {lst5[3]*1.2}")
+print('')
+
+#Task Six
+print('Task Six: ')
+for line in [['Name', 'Age', 'Cost'], ['Steve Jobs', '62', '$1000.00'],['Diana Hamington', '43', '$115.00'],['John Doe', '24','$200.00']]:
+ print('{:>15} {:>15} {:>15}'.format(*line))
+
+