From 0d505050abdd66dc8f3a3a5e3148e51bb591e81b Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:22:13 -0800
Subject: [PATCH 01/23] Submit Assignments
---
list_lab.py | 81 ++++++++++++++++++++++++++++++++++++++++++++
mailroom.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++
slicing_lab.py | 45 +++++++++++++++++++++++++
strformat_lab.py | 52 +++++++++++++++++++++++++++++
4 files changed, 265 insertions(+)
create mode 100644 list_lab.py
create mode 100644 mailroom.py
create mode 100644 slicing_lab.py
create mode 100644 strformat_lab.py
diff --git a/list_lab.py b/list_lab.py
new file mode 100644
index 0000000..77be920
--- /dev/null
+++ b/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)
\ No newline at end of file
diff --git a/mailroom.py b/mailroom.py
new file mode 100644
index 0000000..28066f8
--- /dev/null
+++ b/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/slicing_lab.py b/slicing_lab.py
new file mode 100644
index 0000000..66b6e8f
--- /dev/null
+++ b/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/strformat_lab.py b/strformat_lab.py
new file mode 100644
index 0000000..47f5eb9
--- /dev/null
+++ b/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))
+
+
From ff8e38b5a475b1a546b8678754d0ffb43d9ad52c Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:24:45 -0800
Subject: [PATCH 02/23] Rename list_lab.py to students/Module3/list_lab.py
---
list_lab.py => students/Module3/list_lab.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename list_lab.py => students/Module3/list_lab.py (99%)
diff --git a/list_lab.py b/students/Module3/list_lab.py
similarity index 99%
rename from list_lab.py
rename to students/Module3/list_lab.py
index 77be920..8502f83 100644
--- a/list_lab.py
+++ b/students/Module3/list_lab.py
@@ -78,4 +78,4 @@
lst = lst[:-1]
print(lst)
-print(lst4cp)
\ No newline at end of file
+print(lst4cp)
From 6d6d64dcc837f1aa10ef555b5698c0295db15bf2 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:25:19 -0800
Subject: [PATCH 03/23] Rename mailroom.py to students/module3/mailroom.py
---
mailroom.py => students/module3/mailroom.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename mailroom.py => students/module3/mailroom.py (99%)
diff --git a/mailroom.py b/students/module3/mailroom.py
similarity index 99%
rename from mailroom.py
rename to students/module3/mailroom.py
index 28066f8..11958fb 100644
--- a/mailroom.py
+++ b/students/module3/mailroom.py
@@ -84,4 +84,4 @@ def create_Report():
print ('$','{:<12}'.format(l[3]))
if __name__ == '__main__':
- main_menu()
\ No newline at end of file
+ main_menu()
From 0958580a617868cdeb22684100323e54b1edb1de Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:26:16 -0800
Subject: [PATCH 04/23] Delete mailroom.py
---
students/module3/mailroom.py | 87 ------------------------------------
1 file changed, 87 deletions(-)
delete mode 100644 students/module3/mailroom.py
diff --git a/students/module3/mailroom.py b/students/module3/mailroom.py
deleted file mode 100644
index 11958fb..0000000
--- a/students/module3/mailroom.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#----------------------------------------#
-# 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()
From 9e09000db9f26cee14f8ffd96af8f72966922f8b Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:26:46 -0800
Subject: [PATCH 05/23] Add files via upload
---
students/Module3/mailroom.py | 87 +++++++++++++++++++++++++++++++
students/Module3/slicing_lab.py | 45 ++++++++++++++++
students/Module3/strformat_lab.py | 52 ++++++++++++++++++
3 files changed, 184 insertions(+)
create mode 100644 students/Module3/mailroom.py
create mode 100644 students/Module3/slicing_lab.py
create mode 100644 students/Module3/strformat_lab.py
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))
+
+
From 0f3af3f3940b94a7e3108bccaa96a56bee725d2a Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:27:10 -0800
Subject: [PATCH 06/23] Delete slicing_lab.py
---
slicing_lab.py | 45 ---------------------------------------------
1 file changed, 45 deletions(-)
delete mode 100644 slicing_lab.py
diff --git a/slicing_lab.py b/slicing_lab.py
deleted file mode 100644
index 66b6e8f..0000000
--- a/slicing_lab.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#----------------------------------------#
-# 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)
From 338314e4117531adb8f8f436e57d0cb09497ab95 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 29 Jan 2019 16:27:20 -0800
Subject: [PATCH 07/23] Delete strformat_lab.py
---
strformat_lab.py | 52 ------------------------------------------------
1 file changed, 52 deletions(-)
delete mode 100644 strformat_lab.py
diff --git a/strformat_lab.py b/strformat_lab.py
deleted file mode 100644
index 47f5eb9..0000000
--- a/strformat_lab.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#----------------------------------------#
-# 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))
-
-
From 314f84e673eb0dd324dc1c43a9c3d47d60bed70b Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 5 Feb 2019 17:19:12 -0800
Subject: [PATCH 08/23] Create mailroom2.py
---
students/Module04/mailroom2.py | 93 ++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
create mode 100644 students/Module04/mailroom2.py
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()
From 89a4d88d6f481480c7f3339d31e07d7aeaa62788 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 5 Feb 2019 17:19:31 -0800
Subject: [PATCH 09/23] Add files via upload
---
students/Module04/Trigrams.py | 90 +++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
create mode 100644 students/Module04/Trigrams.py
diff --git a/students/Module04/Trigrams.py b/students/Module04/Trigrams.py
new file mode 100644
index 0000000..86c0ce5
--- /dev/null
+++ b/students/Module04/Trigrams.py
@@ -0,0 +1,90 @@
+#----------------------------------------#
+# 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):
+ # translation = {'\"': ' ', '!': ' ', ',': ' ', '-': ' '}
+ # translated_words = in_data.translate(translation)
+ words = in_data.split()
+ # translator = str.maketrans('', '', string.punctuation)
+ # in_data = in_data.translate(translator)
+ # 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
From 96a056bcccdb23e7ca9bc124e96d21144df5ab77 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 5 Feb 2019 17:33:57 -0800
Subject: [PATCH 10/23] Delete Trigrams.py
---
students/Module04/Trigrams.py | 90 -----------------------------------
1 file changed, 90 deletions(-)
delete mode 100644 students/Module04/Trigrams.py
diff --git a/students/Module04/Trigrams.py b/students/Module04/Trigrams.py
deleted file mode 100644
index 86c0ce5..0000000
--- a/students/Module04/Trigrams.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#----------------------------------------#
-# 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):
- # translation = {'\"': ' ', '!': ' ', ',': ' ', '-': ' '}
- # translated_words = in_data.translate(translation)
- words = in_data.split()
- # translator = str.maketrans('', '', string.punctuation)
- # in_data = in_data.translate(translator)
- # 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
From e51340adfa8accfe7b7fc782e07262c593479039 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 5 Feb 2019 17:34:12 -0800
Subject: [PATCH 11/23] Add files via upload
---
students/Module04/Trigrams.py | 88 +++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 students/Module04/Trigrams.py
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
From cf3510daf2b583f3fbf43d4155e3773ac053c73f Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Mon, 11 Feb 2019 23:20:25 -0800
Subject: [PATCH 12/23] Create Module05
---
Module05 | 1 +
1 file changed, 1 insertion(+)
create mode 100644 Module05
diff --git a/Module05 b/Module05
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Module05
@@ -0,0 +1 @@
+
From fd407bb6ab7d70cf044f75b74164ee6637e523af Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Mon, 11 Feb 2019 23:20:47 -0800
Subject: [PATCH 13/23] Delete Module05
---
Module05 | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 Module05
diff --git a/Module05 b/Module05
deleted file mode 100644
index 8b13789..0000000
--- a/Module05
+++ /dev/null
@@ -1 +0,0 @@
-
From 486232fa47ba347b1e69f652402097a0078f14fb Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Mon, 11 Feb 2019 23:22:42 -0800
Subject: [PATCH 14/23] Create except_excercise.py
---
students/Module05/except_excercise.py | 58 +++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 students/Module05/except_excercise.py
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()
From ba4253cfd22ba7e80c16ac9b6c8580ec4d67d797 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Mon, 11 Feb 2019 23:23:02 -0800
Subject: [PATCH 15/23] Add files via upload
---
students/Module05/mailroom3.py | 107 +++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
create mode 100644 students/Module05/mailroom3.py
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
From 432b7bc403280d61e990098981e3638e5ddf80c4 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Mon, 18 Feb 2019 22:32:20 -0800
Subject: [PATCH 16/23] Create mailroom4.py
---
students/Module06/mailroom4.py | 137 +++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
create mode 100644 students/Module06/mailroom4.py
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()
From 8f305e1b0b72730392644170d61ee82ed04c2ab5 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Mon, 18 Feb 2019 22:32:43 -0800
Subject: [PATCH 17/23] Add files via upload
---
students/Module06/test_mailroom4.py | 30 +++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 students/Module06/test_mailroom4.py
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]]
+
From 49817cbb8162d2b34ced8db516aff2458f53982b Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 26 Feb 2019 17:01:54 -0800
Subject: [PATCH 18/23] Create test_html_render.py
---
students/Module07/test_html_render.py | 362 ++++++++++++++++++++++++++
1 file changed, 362 insertions(+)
create mode 100644 students/Module07/test_html_render.py
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("")
From 492ad2ffa73249f328da7f29d7c72bc7187a5aeb Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Tue, 26 Feb 2019 17:02:26 -0800
Subject: [PATCH 19/23] Add files via upload
---
students/Module07/html_render.py | 184 +++++++++++++++++++++
students/Module07/run_html_render.py | 237 +++++++++++++++++++++++++++
2 files changed, 421 insertions(+)
create mode 100644 students/Module07/html_render.py
create mode 100644 students/Module07/run_html_render.py
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")
From 8744c181e3ec7a106f294df23662abc5c07c8a98 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Sun, 17 Mar 2019 17:59:01 -0700
Subject: [PATCH 20/23] Create Final
---
students/Final | 1 +
1 file changed, 1 insertion(+)
create mode 100644 students/Final
diff --git a/students/Final b/students/Final
new file mode 100644
index 0000000..e14673b
--- /dev/null
+++ b/students/Final
@@ -0,0 +1 @@
+Final
From c63696cafb342f127005032f92d47d30e996ede0 Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Sun, 17 Mar 2019 17:59:21 -0700
Subject: [PATCH 21/23] Delete Final
---
students/Final | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 students/Final
diff --git a/students/Final b/students/Final
deleted file mode 100644
index e14673b..0000000
--- a/students/Final
+++ /dev/null
@@ -1 +0,0 @@
-Final
From e4fe52dd76709a98dc9608f291b478ea975f29bd Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Sun, 17 Mar 2019 17:59:37 -0700
Subject: [PATCH 22/23] Create Final.txt
---
students/Final/Final.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 students/Final/Final.txt
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
From 22431d3e19380d06141068d12eef32ce5a6a75bc Mon Sep 17 00:00:00 2001
From: sunjeuny <46549613+sunjeuny@users.noreply.github.com>
Date: Sun, 17 Mar 2019 18:00:24 -0700
Subject: [PATCH 23/23] Add files via upload
---
students/Final/ProductInventory.zip | Bin 0 -> 1952054 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 students/Final/ProductInventory.zip
diff --git a/students/Final/ProductInventory.zip b/students/Final/ProductInventory.zip
new file mode 100644
index 0000000000000000000000000000000000000000..a67c1a912c3009c92a1e15abb306a3ede299495a
GIT binary patch
literal 1952054
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