/
phonebook.py
203 lines (140 loc) · 5.36 KB
/
phonebook.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# A mini phonebook Python app based off the coding exercise written
# by Amy Hanlon (HS W '14)
import cPickle
import os
import sys
# extension expected for all phonebooks
EXTENSION = ".pb"
class ArgumentError(Exception): pass
class NoFileError(Exception): pass
class NoEntryError(Exception): pass
class DuplicateError(Exception): pass
def create(phonebook_name):
"""Creates a new phonebook of the given name. (If given name
is not a .pb file, adds '.pb'.)"""
if not phonebook_name.endswith(EXTENSION):
phonebook_name = "%s%s" % (phonebook_name, EXTENSION)
if os.path.exists(filename):
raise DuplicateError("That phonebook already exists!")
else:
with open(filename, "w") as infile:
pass
def add(name, number, phonebook):
"""Adds new entry to specified phonebook."""
phonebook_data = read_phonebook(phonebook)
if phonebook_data.get(name):
raise DuplicateError("This entry already exists. To make changes, "
"use update_number or update_name.")
else:
phonebook_data[name] = number
print "Entry added:", name, number
save(phonebook_data, phonebook)
def update_number(name, number, phonebook):
"""Updates an entry of given name with new number. Exact
name matches only."""
phonebook_data = read_phonebook(phonebook)
if not phonebook_data.get(name):
raise NoEntryError("This entry does not exist! "
"(Names are case-sensitive.)")
else:
print "Previous entry:", name, phonebook_data[name]
phonebook_data[name] = number
print "New entry:", name, phonebook_data[name]
save(phonebook_data, phonebook)
def update_name(old_name, new_name, phonebook):
"""Updates an entry of given name with new name. Exact
name matches only."""
phonebook_data = read_phonebook(phonebook)
if not phonebook_data.get(old_name):
raise NoEntryError("This entry does not exist! "
"(Names are case-sensitive.)")
else:
print "Previous entry:", old_name, phonebook_data[old_name]
number = phonebook_data[old_name]
del phonebook_data[old_name]
phonebook_data[new_name] = number
print "New entry:", new_name, phonebook_data[new_name]
save(phonebook_data, phonebook)
def delete(name, phonebook):
"""Deletes the entry of given name. Exact name matches only."""
phonebook_data = read_phonebook(phonebook)
if not phonebook_data.get(name):
raise NoEntryError("This entry does not exist! "
"(Names are case-sensitive.)")
else:
print "Deleting entry:", name, phonebook_data[name]
del phonebook_data[name]
save(phonebook_data, phonebook)
def lookup(name, phonebook):
"""Given name, returns any matching entries."""
phonebook_data = read_phonebook(phonebook)
match = False
for entry_name in phonebook_data:
if name.lower() in entry_name.lower():
match = True
print entry_name, phonebook_data[entry_name]
if not match:
print "No matches found."
def reverse_lookup(number, phonebook):
"""Given number, returns all matching entries."""
phonebook_data = read_phonebook(phonebook)
match = False
for entry_name, entry_number in phonebook_data.iteritems():
if number in entry_number:
print entry_name, entry_number
match = True
if not match:
print "No matches found."
def display(phonebook):
"""Displays the contents of given phonebook in alphabetical order."""
phonebook_data = read_phonebook(phonebook)
for name in sorted(phonebook_data.keys(), key=str.lower):
print name, phonebook_data[name]
def list_phonebooks(path="."):
"""Lists all phonebooks (i.e. '.pb' files) at the top level of
the given path. If no path is given, assumes the root dir."""
files = os.listdir(path)
for file in files:
if file.endswith(EXTENSION):
print file
def read_phonebook(phonebook):
"""Returns the dictionary of names/numbers contained in the given
phonebook file, or throws an error if the file does not exist."""
try:
with open(phonebook) as infile:
try:
return cPickle.load(infile)
except EOFError:
return {}
except IOError:
print "That phonebook does not exist!"
def save(data, phonebook):
"""Saves the dictionary containing phonebook data to the given
phonebook, using cPickle."""
with open(phonebook, "w") as outfile:
cPickle.dump(data, outfile)
def main():
"""The main function of the program."""
# all of the functions in the program
functions = {"create": create,
"add" : add,
"update_number" : update_number,
"update_name" : update_name,
"delete" : delete,
"lookup" : lookup,
"reverse_lookup" : reverse_lookup,
"display" : display,
"list_phonebooks" : list_phonebooks}
args = sys.argv[:]
script = args.pop(0)
try:
command = args.pop(0)
except IndexError:
raise ArgumentError("Not enough arguments!")
try:
func = functions[command]
except KeyError:
raise ArgumentError("Not a valid command.")
func(*args)
if __name__ == '__main__':
main()