diff --git a/Examples/Session05/__pycache__/arg_test.cpython-27-PYTEST.pyc b/Examples/Session05/__pycache__/arg_test.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..264f9101 Binary files /dev/null and b/Examples/Session05/__pycache__/arg_test.cpython-27-PYTEST.pyc differ diff --git a/Examples/Session05/__pycache__/test_codingbat.cpython-27-PYTEST.pyc b/Examples/Session05/__pycache__/test_codingbat.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..a75522a6 Binary files /dev/null and b/Examples/Session05/__pycache__/test_codingbat.cpython-27-PYTEST.pyc differ diff --git a/Examples/Session05/__pycache__/test_pytest_parameter.cpython-27-PYTEST.pyc b/Examples/Session05/__pycache__/test_pytest_parameter.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..56680621 Binary files /dev/null and b/Examples/Session05/__pycache__/test_pytest_parameter.cpython-27-PYTEST.pyc differ diff --git a/Examples/Session05/__pycache__/test_random_pytest.cpython-27-PYTEST.pyc b/Examples/Session05/__pycache__/test_random_pytest.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..511760de Binary files /dev/null and b/Examples/Session05/__pycache__/test_random_pytest.cpython-27-PYTEST.pyc differ diff --git a/Examples/Session05/__pycache__/test_random_unitest.cpython-27-PYTEST.pyc b/Examples/Session05/__pycache__/test_random_unitest.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..1bf205df Binary files /dev/null and b/Examples/Session05/__pycache__/test_random_unitest.cpython-27-PYTEST.pyc differ diff --git a/Examples/Session05/codingbat.pyc b/Examples/Session05/codingbat.pyc new file mode 100644 index 00000000..70b301cf Binary files /dev/null and b/Examples/Session05/codingbat.pyc differ diff --git a/Students/salim/notes/class_notes.py b/Students/salim/notes/class_notes.py index 32b6b7e0..d134a7dc 100644 --- a/Students/salim/notes/class_notes.py +++ b/Students/salim/notes/class_notes.py @@ -471,6 +471,12 @@ def complex_function(arg1, arg2, kwarg1=u'bannana'): ############################## SESSION03 ############################## +""" +making a python file an executable: + - change the mode of the file to executable: chmod +x myscript.py + - add the path to python at the top with '#!' before +""" + """ git question: - create a pull request for the branch itself @@ -643,3 +649,148 @@ def func(c, list=[]): # this is wrong because it dones't create a function le return list.append(c) +############################## SESSION03 ############################## +""" +you almost never have to loop through sequences using range() +- zip() will zip lists together +- unpack embedded squences using this construct +""" + +a_list = [(1,2), (3,4), (5,6)] + +for i, j in a_list: + print i + print j + +""" +enumerate allows you to get the indix while you are looping through a sequence +""" + +for i, item in enumerate(a_list): + print i + print item + +""" +buidling up a long string: + - one option is to continue to keep += to the string. however, this is + an inefficent process + - a better way is to build a list, then use " ".join(list) + +sorting data: + - when you + +""" + +fruits = ['Apples', 'Pears', 'Grapes'] +numbers = [1, 2, 3] +combine = zip(fruits, numbers) + +def sort_key(item): + return item[1] + +combine.sort(key=sort_key) + +""" +you can build up strings for formatting before you subistiute values in +""" + +s = 'Hello ' + '%d' * 4 +print s % (1,2,3,4) + +""" +dictionaries: + - create a dict with d = {} + - keys don't have to be the same type and values don't have to be the same + type + - keys can be any immutable object (technically "hash" objects): + - number + - string + - tuple + - dictionaries are unordered (due to the way they are built using hasing) + - dictionaries are very effecicent + +dictionary methods + - dict.setdefault() <-- will use this in the homework + - dict.iteritems() <-- will not return a list + +hashing: + - missed this so read the class notes +""" + +""" +Exceptions: + - you can use "finally" at the end of an exception, which will always get + run + - they also have an "else" which will run if there is no exception +""" +# never do this! this doesn't give you information about the exception +try: + do_something() +except: + print "something went wrong." + +""" +reading and writing files: + +text files: + - f +""" + +f = open('secrets.txt') +secret_data = f.read() +f.close() + + + +############################## SESSION04 ############################## + +""" dealing with "ordered" / "sorted" dicts """ + +# option #1 +import collections # package with tools for dealing with dicts +o_dict = collections.OrderedDict() # this will create an ordered dict + +# option #2 +sorted() # built in function that sorts iterables + +""" Advanced argument passing """ + +# keyword arguments +def fun(a, b = True, c = False): + return + +# functional arguments + +def func(x, y, w=0, h=0): # positional arguments are tuples + # keywork arguments are dictionaries + print "%s %s %s %s" % (x, y, x, h) + +a_tuple = (1, 2) +a_dict = {'w':1, 'h': 2} +func(*a_tuple, **a_dict) # you can pass the tuple and dict in directly + +def func(*args, **kwargs): # you can recieve an undefined number of args + print args + print kwargs + +"""mutablility""" + +import copy # for making copies of objects + +copy.deepcopy() # this is how you make a deep copy + + +"""list comprehensions""" +l = [1, 2, 3] +[i * 2 for i in l] +[i * 2 for i in l if i > 1] # you can have an if statement here + +# searching 'in' a sequence is faster with sets because they are hash tables + +"""set comprehension""" + +"""dict comprehensions""" + + +"""testing in python""" + diff --git a/Students/salim/session03/.mailroom.py.swp b/Students/salim/session03/.mailroom.py.swp new file mode 100644 index 00000000..06352d29 Binary files /dev/null and b/Students/salim/session03/.mailroom.py.swp differ diff --git a/Students/salim/session03/list_lab.py b/Students/salim/session03/list_lab.py old mode 100755 new mode 100644 index efc1e803..fe3dbc16 --- a/Students/salim/session03/list_lab.py +++ b/Students/salim/session03/list_lab.py @@ -1,5 +1,6 @@ #!/usr/bin/env python + # print original list a_list = ['Apples', 'Pears', 'Oranges', 'Peaches'] print a_list diff --git a/Students/salim/session04/cp_dict_set_lab.py b/Students/salim/session04/cp_dict_set_lab.py new file mode 100644 index 00000000..81abd531 --- /dev/null +++ b/Students/salim/session04/cp_dict_set_lab.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + + +# #############################Lesson 1############################## + +# create dict +d1 = {'name': 'Chris', 'city': 'Seattle', 'cake': 'Chocolate'} +print d1 + +# delete entry for cake +del d1['cake'] +print d1 + +# add an entry to the dict +d1['fruit'] = 'Mango' +print d1 + +# display the values +d1.values() + +# display the keys +d1.keys() + +# is 'cake' a key in the dict? +'cake' in d1 + +# is 'Mango' a value in the dict? +'Mango' in d1.values() + + +# #############################Lesson 2############################## + +# create list from 0 to 15 +l2 = range(16) + +# create list with hex representation +s2 = [] +for item in l2: + s2.append(hex(item)) + +# zip lists into dict +d2 = dict(zip(l2, s2)) + + +# #############################Lesson 3############################## + +# use d1 to create a new dict with same keys but number of 't's in values +d3 = {} +for key, value in d1.iteritems(): + d3[key] = value.count('t') + + +# #############################Lesson 4############################## + +# make three sets +s2 = set(range(0, 20, 2)) +s3 = set(range(0, 20, 3)) +s4 = set(range(0, 20, 4)) + +# print the sets +print s2 +print s3 +print s4 + +# check sets +s3.issubset(s2) +s4.issubset(s2) + + +# #############################Lesson 4############################## + +a_set = set('Python') +a_set.add('i') + +b_set = frozenset('marathon') + +u_set = a_set.union(b_set) +i_set = a_set.intersection(b_set) + +print u_set +print i_set diff --git a/Students/salim/session04/dict_set_lab.py b/Students/salim/session04/dict_set_lab.py new file mode 100644 index 00000000..81abd531 --- /dev/null +++ b/Students/salim/session04/dict_set_lab.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + + +# #############################Lesson 1############################## + +# create dict +d1 = {'name': 'Chris', 'city': 'Seattle', 'cake': 'Chocolate'} +print d1 + +# delete entry for cake +del d1['cake'] +print d1 + +# add an entry to the dict +d1['fruit'] = 'Mango' +print d1 + +# display the values +d1.values() + +# display the keys +d1.keys() + +# is 'cake' a key in the dict? +'cake' in d1 + +# is 'Mango' a value in the dict? +'Mango' in d1.values() + + +# #############################Lesson 2############################## + +# create list from 0 to 15 +l2 = range(16) + +# create list with hex representation +s2 = [] +for item in l2: + s2.append(hex(item)) + +# zip lists into dict +d2 = dict(zip(l2, s2)) + + +# #############################Lesson 3############################## + +# use d1 to create a new dict with same keys but number of 't's in values +d3 = {} +for key, value in d1.iteritems(): + d3[key] = value.count('t') + + +# #############################Lesson 4############################## + +# make three sets +s2 = set(range(0, 20, 2)) +s3 = set(range(0, 20, 3)) +s4 = set(range(0, 20, 4)) + +# print the sets +print s2 +print s3 +print s4 + +# check sets +s3.issubset(s2) +s4.issubset(s2) + + +# #############################Lesson 4############################## + +a_set = set('Python') +a_set.add('i') + +b_set = frozenset('marathon') + +u_set = a_set.union(b_set) +i_set = a_set.intersection(b_set) + +print u_set +print i_set diff --git a/Students/salim/session04/exception_lab.py b/Students/salim/session04/exception_lab.py new file mode 100644 index 00000000..233e4806 --- /dev/null +++ b/Students/salim/session04/exception_lab.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python + + +def safe_input(): + try: + return raw_input('Type ^c or ^d to raise an error.') + except (KeyboardInterrupt, EOFError): + return None + +if __name__ == '__main__': + safe_input() diff --git a/Students/salim/session04/files_lab.py b/Students/salim/session04/files_lab.py new file mode 100644 index 00000000..35c2d75b --- /dev/null +++ b/Students/salim/session04/files_lab.py @@ -0,0 +1,48 @@ +#!/Library/Frameworks/Python.framework/Versions/2.7/bin/python + + +def read_file_to_list(a_file): + """Return a list of the lines in a file with newlines removed""" + # move file to begining + a_file.seek(0) + + # add lines to list + a_list = [] + for line in a_file: + a_list.append(line.strip()) + + return a_list + + +def parse_languages(a_list): + """Return a list of distinct languages.""" + a_set = set() + + # parse text file + for item in a_list: + # split students and languages + student_lang = item.split(':') + + # split languages + lang = student_lang[1].split(',') + + # add languages to set + for l in lang: + if len(l.strip()) > 0: + a_set.add(l.strip()) + + # convert to list + b_list = [] + for language in a_set: + b_list.append(language) + + # sort list + b_list.sort() + + return b_list + + +path_students = '../../../Examples/Session01/students.txt' +file_students = open(path_students, 'r') +list_students = read_file_to_list(file_students) +list_languages = parse_languages(list_students) diff --git a/Students/salim/session04/kata_14.py b/Students/salim/session04/kata_14.py new file mode 100644 index 00000000..626d58c0 --- /dev/null +++ b/Students/salim/session04/kata_14.py @@ -0,0 +1,143 @@ +#!/Library/Frameworks/Python.framework/Versions/2.7/bin/python + +import string + + +def file_to_list(a_file, start_line=0, end_line=0): + """Read lines of file into a list. Ignore blank and all cap lines.""" + + a_list = [] + + ignore_list = ['I.', 'II.', 'III.', 'IV.', 'V.', 'VI.', 'VII.', 'VIII.', + 'IX.', 'X.', 'XI.', 'XII.'] + + for idx, line in enumerate(a_file, start_line): + + # strip whitespace out of line + line = line.strip() + + # stop reading if reached end_line parameter + if end_line and idx >= end_line: + break + + else: + # check if line starts with text in ignore list + start_with_ignore = False + for word in ignore_list: + if line.startswith(word): + start_with_ignore = True + break + + # only add line to list if it's non-blank and non-uppercase + if line and not line.isupper() and not start_with_ignore: + a_list.append(line) + + return a_list + + +def build_trigram(all_words): + """Return a trigram dictionary.""" + trigram_dict = dict() + for idx, word in enumerate(all_words): + + # only add words to dict if there are three words left + if idx < len(all_words) - 3: + + # build keys and values for dict + key = '{:s} {:s}'.format(word, all_words[idx + 1]) + value = all_words[idx + 2] + + # get or set the current_set for the given key + current_set = trigram_dict.setdefault(key, set([value])) + + # add new value to the current set + current_set.add(value) + + return trigram_dict + + +def get_trigram_output(trigram, start_words, num_of_words): + """Print trigram.""" + trigram_output = start_words.split() + key_string = '{:s} ' * 2 + key_string = key_string.strip() + + for i in range(num_of_words): + # build the key to lookup the set of next words from dictionary + key = key_string.format(*trigram_output[i:i+2]) + + # get the set of next words + try: + return_set = trigram[key] + except KeyError: + break + + # randomly choose and remove a word from the set + next_word = return_set.pop() + + # add the new work to the output list + trigram_output.append(next_word) + + return trigram_output + + +def clean_string(s, lowercase = False, punctuation = False): + s = s.strip() # strip whitespce + + if lowercase: + s = s.lower() # convert to lowercase + + if punctuation: + # create list with all punctuation + delete_characters = list(string.punctuation) + + # exclude some punctuation from being removed + delete_characters.remove('!') + delete_characters.remove('.') + delete_characters.remove('?') + delete_characters.remove(',') + delete_characters.remove("'") + + s = s.translate(None, ''.join(delete_characters)) + + return s + +if __name__ == '__main__': + + path_book = ('/Users/salimhamed/Documents/Documents/School/' + 'Python (2014)/downloads/sherlock.txt') + + # path_book = ('/Users/salimhamed/Documents/Documents/School/' + # 'Python (2014)/downloads/sherlock_small.txt') + + start_line = 0 # starting line of the file + end_line = 0 # ending line of the file + + num_of_words_to_print = 200 + start_words = 'I did' + + # read file to list + f = open(path_book) + f_list = file_to_list(f, start_line, end_line) + + # condense list to a single string + f_string = ' '.join(f_list) + + # strip white space and remove quotes + f_string = clean_string(f_string, lowercase = False, punctuation = False) + + # split single string into list of words + words_list = f_string.split() + + # build a trigram + trigram_dict = build_trigram(words_list) + + # get trigram list + trigram_list = get_trigram_output(trigram_dict, + start_words, + num_of_words_to_print) + + # print trigram list + print_string = ('{:s} ' * len(trigram_list))[:-1] + print 'Trigram of {:d} words:'.format(len(trigram_list)) + print print_string.format(*trigram_list) diff --git a/Students/salim/session04/mailroom2.py b/Students/salim/session04/mailroom2.py new file mode 100755 index 00000000..05169abc --- /dev/null +++ b/Students/salim/session04/mailroom2.py @@ -0,0 +1,161 @@ +#!/Library/Frameworks/Python.framework/Versions/2.7/bin/python + +from textwrap import dedent + + +def create_donation_list(): + """Build inital list of donors.""" + d_list = [['Salim Hamed', [100, 900, 1500]], + ['Iris Marlin', [300]], + ['John Doe', [200, 1904343]], + ['Terry Smith', [850]], + ['Bill Williams', [450, 894]], + ['Richard Sherman', [500, 900, 50000]]] + return d_list + + +def inital_prompt(): + """Display inital prompt and return user response.""" + prompt = dedent(""" + Hello, what would you like to do? + + 1 <- Send a Thank You Letter + 2 <- Create a Donation Report + q <- Quit + + """) + return raw_input(prompt) + + +def thank_you(donor_list): + """Prompt for name and add donation amount to history.""" + + # prompt user for donor name + name_prompt = dedent(""" + Enter donor's name. + ('b' to go back or 'l' for donor list) + """) + response = raw_input(name_prompt) + + # remember if donor is in list + donor_in_list = in_list(response, donor_list) + + # evaluate user responses + if response.lower() == 'b': + return + + elif response.lower() == 'l': + list_doners(donor_list) + + else: + # ask user for donation amount + while True: + amount_prompt = dedent(""" + How much money was donated? + ('b' to go back) + """) + amount = raw_input(amount_prompt) + + # exit function if user wants to go back + if amount.lower() == 'b': + return + + # convert entry to float + try: + amount = float(amount) + except ValueError: + print '\nInvalid Entry! Please Try Again.' + else: + break + + # add donation to history + if donor_in_list: + send_mail(response, amount) + add_existing_donor_to_list(response, amount, donor_list) + return + else: + send_mail(response, amount) + add_new_donor_to_list(response, amount, donor_list) + return + + +def send_mail(name, amount): + """Print thank you letter for donation.""" + email = dedent(""" + Dear {:s}, + + Thank you very much for your generous donation of ${:,.2f}. We + appreciate your thoughtfullness and we will make sure your donation + goes to the right cause. + + Kind Regards, + Donation Team + """) + print email.format(name, amount) + + +def list_doners(d_list): + """Print the current list of donors.""" + for doner in d_list: + print doner[0] + + +def in_list(name, d_list): + """Return True if donor is in donation list.""" + for item in d_list: + if str(item[0]).lower() == name.lower(): + return True + return False + + +def add_existing_donor_to_list(name, amount, donor_list): + """Add donation amount to list of historical dontations.""" + for donor, donations in donor_list: + if donor.lower() == name.lower(): + donations.append(amount) + return donor_list + + +def add_new_donor_to_list(name, amount, donor_list): + """Add new donor and donation amount to list of historical dontations.""" + return donor_list.append([name, [amount]]) + + +def display_report(d_list): + """Print Donation Report.""" + # create report header + header = '\n| {:<30s} | {:>21s} |'.format('Donor Name', 'Total Donation') + border = '=' * 58 + + # print header + print header + print border + + # print lines + for name, donations in d_list: + line = '| {:<30s} | ${:20,.2f} |'.format(name, sum(donations)) + print line + + # print final board below lines + print border + + +if __name__ == '__main__': + # get donation list + donation_list = create_donation_list() + + while True: + # capture user response from inital prompt + response = inital_prompt() + + # exit program if user enters 'q' + if response.lower() == 'q': + break + # send thank you letter + elif response == '1': + thank_you(donation_list) + # create a donation report + elif response == '2': + display_report(donation_list) + else: + print 'Invalid Entry! Please Try Again.' diff --git a/Students/salim/session04/paths_files.py b/Students/salim/session04/paths_files.py new file mode 100644 index 00000000..1297e761 --- /dev/null +++ b/Students/salim/session04/paths_files.py @@ -0,0 +1,31 @@ +#!/usr/local/bin/python + +import pathlib + + +def copy_file(source, destination): + # read cotents of source file + file_to_copy = open(source, 'r').read() + + # open new file and write contents of source file + file_to_write = open(destination, 'w') + file_to_write.write(file_to_copy) + + # close file + file_to_write.close() + + +# find file directory +file_path = pathlib.Path(__file__) +parent_path = file_path.parent + +# print files in directory +for f in parent_path.iterdir(): + print f + +# copy file +source = ("/Users/salimhamed/Documents/Documents/School/Python (2014)/" + "IntroToPython/Students/salim/session04/dict_set_lab.py") +destination = ("/Users/salimhamed/Documents/Documents/School/Python (2014)/" + "IntroToPython/Students/salim/session04/cp_dict_set_lab.py") +copy_file(source, destination) diff --git a/Students/salim/session05/__pycache__/test_count_evens.cpython-27-PYTEST.pyc b/Students/salim/session05/__pycache__/test_count_evens.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..24130a08 Binary files /dev/null and b/Students/salim/session05/__pycache__/test_count_evens.cpython-27-PYTEST.pyc differ diff --git a/Students/salim/session05/__pycache__/test_mailroom.cpython-27-PYTEST.pyc b/Students/salim/session05/__pycache__/test_mailroom.cpython-27-PYTEST.pyc new file mode 100644 index 00000000..7c00ff14 Binary files /dev/null and b/Students/salim/session05/__pycache__/test_mailroom.cpython-27-PYTEST.pyc differ diff --git a/Students/salim/session05/count_evens.py b/Students/salim/session05/count_evens.py new file mode 100644 index 00000000..43599c6c --- /dev/null +++ b/Students/salim/session05/count_evens.py @@ -0,0 +1,6 @@ +#!/usr/local/bin/python + + +def count_evens(a_list): + even_list = [x for x in a_list if x % 2 == 0] + return len(even_list) diff --git a/Students/salim/session05/count_evens.pyc b/Students/salim/session05/count_evens.pyc new file mode 100644 index 00000000..06933e26 Binary files /dev/null and b/Students/salim/session05/count_evens.pyc differ diff --git a/Students/salim/session05/dict_set_comprehensions_lab.py b/Students/salim/session05/dict_set_comprehensions_lab.py new file mode 100644 index 00000000..c004178c --- /dev/null +++ b/Students/salim/session05/dict_set_comprehensions_lab.py @@ -0,0 +1,59 @@ +#!/usr/local/bin/python + + +def print_dict(a_dict): + """Returns the printed version of food_prefs dict.""" + s = ('{name} is from {city}, and he likes {cake} cake, {fruit} fruit, ' + '{salad} salad, and {pasta} pasta.') + print s.format(**a_dict) + + +def build_dict_list_comp(n): + """Return a dict with hexadecimal representation range of numbers.""" + a_list = [[k, '{:x}'.format(k)] for k in range(n)] + return dict(a_list) + + +def build_dict_dict_comp(n): + """Return a dict with hexadecimal representation range of numbers.""" + return {k: '{:x}'.format(k) for k in range(n)} + + +def dict_number_a(a_dict): + """Return a dict with the number of 'a's.""" + return {k: v.count('a') for k, v in a_dict.iteritems()} + + +def create_sets(): + s2 = {i for i in range(21) if i % 2 == 0} + s3 = {i for i in range(21) if i % 3 == 0} + s4 = {i for i in range(21) if i % 4 == 0} + print s2 + print s3 + print s4 + + +def create_sets_better(): + l = [] + for x in range(2, 5): + l.append({i for i in range(21) if i % x == 0}) + return l + + +def print_sets_better(): + l = [] + for x in range(2, 5): + l.append({i for i in range(21) if i % x == 0}) + print str('{}\n' * 3).format(*l) + + +def create_sets_better_comprehension(): + return [{i for i in range(21) if i % x == 0} for x in range(2, 5)] + + +food_prefs = {"name": u"Chris", + u"city": u"Seattle", + u"cake": u"chocolate", + u"fruit": u"mango", + u"salad": u"greek", + u"pasta": u"lasagna"} diff --git a/Students/salim/session05/email/salim.txt b/Students/salim/session05/email/salim.txt new file mode 100644 index 00000000..c18e549e --- /dev/null +++ b/Students/salim/session05/email/salim.txt @@ -0,0 +1,9 @@ + +Dear salim, + +Thank you very much for your generous donation of $100.00. We +appreciate your thoughtfullness and we will make sure your donation +goes to the right cause. + +Kind Regards, +Donation Team diff --git a/Students/salim/session05/keywords_lab.py b/Students/salim/session05/keywords_lab.py new file mode 100644 index 00000000..2fe64c29 --- /dev/null +++ b/Students/salim/session05/keywords_lab.py @@ -0,0 +1,33 @@ +#!/usr/local/bin/python + + +def func(fore_color='White', + back_color='Black', + link_color='Blue', + visited_color='Green'): + """Print colors.""" + s = ('{} ' * 4).strip() + + print s.format(fore_color, back_color, link_color, visited_color) + + +def func_args(**kwargs): + """Print colors.""" + s = '{fore_color}, {back_color}, {link_color}, {visited_color}' + + print s.format(**kwargs) + + +# call the function with various parameters +func((1, 2, 3, 4)) # prints the tuple in the first argument + +func(*(1, 2, 3, 4)) + +args = (1, 2, 3, 4) +func(*args) + +kwargs = {'fore_color':'hey', + 'back_color':'there', + 'link_color':'how', + 'visited_color':'you'} +func_args(**kwargs) diff --git a/Students/salim/session05/mailroom3.py b/Students/salim/session05/mailroom3.py new file mode 100755 index 00000000..419e1d27 --- /dev/null +++ b/Students/salim/session05/mailroom3.py @@ -0,0 +1,150 @@ +#!/usr/local/bin/python + +from textwrap import dedent +import pathlib + + +def create_donation_list(): + """Build inital list of donors.""" + d_list = {'salim hamed': [100, 900, 1500], + 'iris marlin': [300], + 'john doe': [200, 1904343], + 'terry smith': [850], + 'bill williams': [450, 894], + 'richard sherman': [500, 900, 50000]} + return d_list + + +def inital_prompt(): + """Display inital prompt and return user response.""" + prompt = dedent(""" + Hello, what would you like to do? + + 1 <- Send a Thank You Letter + 2 <- Create a Donation Report + q <- Quit + + """) + return raw_input(prompt) + + +def thank_you(donor_list): + """Prompt for name and add donation amount to history.""" + # prompt user for donor name + name_prompt = dedent(""" + Enter donor's name. + ('b' to go back or 'l' for donor list) + """) + response = raw_input(name_prompt) + + # evaluate user responses + if response.lower() == 'b': + return + + elif response.lower() == 'l': + print list_doners(donor_list) + + else: + # ask user for donation amount + while True: + amount_prompt = dedent(""" + How much money was donated? + ('b' to go back) + """) + amount = raw_input(amount_prompt) + + # exit function if user wants to go back + if amount.lower() == 'b': + return + + # convert entry to float + try: + amount = float(amount) + except ValueError: + print '\nInvalid Entry! Please Try Again.' + else: + break + + # send thank you letter + print send_mail(response, amount) + + # add donation to history + donor_list.setdefault(response.lower(), []).append(amount) + return + + +def send_mail(name, amount): + """Print thank you letter for donation.""" + # create email pretext + pretext = dedent(""" + The folowing email has been saved to the "email/" sub directory + ===================================================================== + """) + + # create email + email = dedent(""" + Dear {:s}, + + Thank you very much for your generous donation of ${:,.2f}. We + appreciate your thoughtfullness and we will make sure your donation + goes to the right cause. + + Kind Regards, + Donation Team + """) + + # write email to file + parent_path = pathlib.Path(__file__).parent + email_file = open(str(parent_path) + '/email/' + name + '.txt', 'w') + email_file.write(email.format(name, amount)) + email_file.close() + + return (pretext + email).format(name, amount) + + +def list_doners(d_list): + """Return print read string with the current list of donors.""" + s = ('\n' + '{}\n' * len(d_list))[:-1] + return s.format(*d_list.keys()).title() + + +def display_report(d_list): + """Print Donation Report.""" + l_report = [] + + # create report header and boder + header = '| {:<30s} | {:>21s} |'.format('Donor Name', 'Total Donation') + border = '=' * 58 + + # create report rows + s = '| {:<30s} | ${:20,.2f} |' + rows = [s.format(k.title(), sum(v)) for k, v in d_list.iteritems()] + + # build report list + l_report.append(header) + l_report.append(border) + l_report.extend(rows) + l_report.append(border) + + return ('\n{}' * len(l_report)).format(*l_report) + + +if __name__ == '__main__': + # get donation list + donation_list = create_donation_list() + + while True: + # capture user response from inital prompt + response = inital_prompt() + + # exit program if user enters 'q' + if response.lower() == 'q': + break + # send thank you letter + elif response == '1': + thank_you(donation_list) + # create a donation report + elif response == '2': + print display_report(donation_list) + else: + print 'Invalid Entry! Please Try Again.' diff --git a/Students/salim/session05/mailroom3.pyc b/Students/salim/session05/mailroom3.pyc new file mode 100644 index 00000000..cbacc161 Binary files /dev/null and b/Students/salim/session05/mailroom3.pyc differ diff --git a/Students/salim/session05/test_count_evens.py b/Students/salim/session05/test_count_evens.py new file mode 100644 index 00000000..dd3a9b16 --- /dev/null +++ b/Students/salim/session05/test_count_evens.py @@ -0,0 +1,39 @@ +#!/usr/local/bin/python + +from count_evens import count_evens + + +def test_count_evens_1(): + assert count_evens([2, 1, 2, 3, 4]) == 3 + + +def test_count_evens_2(): + assert count_evens([2, 1, 2, 3, 4]) == 3 + + +def test_count_evens_3(): + assert count_evens([2, 2, 0]) == 3 + + +def test_count_evens_4(): + assert count_evens([1, 3, 5]) == 0 + + +def test_count_evens_5(): + assert count_evens([]) == 0 + + +def test_count_evens_6(): + assert count_evens([11, 9, 0, 1]) == 1 + + +def test_count_evens_7(): + assert count_evens([2, 11, 9, 0]) == 2 + + +def test_count_evens_8(): + assert count_evens([2]) == 1 + + +def test_count_evens_9(): + assert count_evens([2, 5, 12]) == 2 diff --git a/Students/salim/session05/test_mailroom.py b/Students/salim/session05/test_mailroom.py new file mode 100644 index 00000000..b03537c5 --- /dev/null +++ b/Students/salim/session05/test_mailroom.py @@ -0,0 +1,26 @@ +#!/usr/local/bin/python + + +import mailroom3 as mail + + +def test_create_donation_list(): + assert type(mail.create_donation_list()) == dict + + +def test_send_mail(): + assert type(mail.send_mail('Salim Hamed', 100)) == str + assert mail.send_mail('Salim Hamed', 100).count('Salim Hamed') == 1 + assert mail.send_mail('Salim Hamed', 100).count('100') == 1 + + +def test_list_doners(): + assert type(mail.list_doners(mail.create_donation_list())) == str + assert (mail.list_doners(mail.create_donation_list()).count('\n') == + len(mail.create_donation_list())) + assert mail.list_doners(mail.create_donation_list()).count('Salim') == 1 + + +def test_display_report(): + assert type(mail.display_report(mail.create_donation_list())) == str + assert mail.display_report(mail.create_donation_list()).count('Salim') == 1