Skip to content

Commit c375dad

Browse files
committed
added notes about individual project.
1 parent dd7ee0d commit c375dad

File tree

8 files changed

+132
-24
lines changed

8 files changed

+132
-24
lines changed

materials/source/index.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ Fluent Python
115115

116116
`Fluent Python <http://shop.oreilly.com/product/0636920032519.do>`_, by Luciano Ramalho, is an excellent book about the more advanced features of Python. We highly recommend you get it, and we will be referencing it throughout the class.
117117

118+
Individual_project
119+
------------------
120+
121+
In addition to weekly exercises, you will also complete an :ref:`individual_project`
122+
123+
118124
Week 1: Jan 9 -- Iterators and Generators, Packaging
119125
....................................................
120126

solutions/mailroom_json_save/mailroom/model.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99

1010
# handy utility to make pretty printing easier
1111
from textwrap import dedent
12+
from pathlib import Path
1213

1314
import json_save.json_save_dec as js
1415
import json
1516

17+
from . import data_dir
18+
1619

1720
@js.json_save
1821
class Donor:
@@ -108,31 +111,78 @@ def gen_letter(self):
108111
@js.json_save
109112
class DonorDB:
110113
"""
111-
encapsulation of the entire database of donors and data associated with them.
114+
Encapsulation of the entire database of donors and data associated with them.
112115
"""
116+
# specify a json_save dict as the data structure for the data.
113117
donor_data = js.Dict()
114118

115-
def __init__(self, donors=None):
119+
def __init__(self, donors=None, db_file=None):
116120
"""
117121
Initialize a new donor database
118122
119123
:param donors=None: iterable of Donor objects
124+
125+
:param db_file=None: path to file to store the datbase in.
126+
if None, the data will be stored in the
127+
package data_dir
120128
"""
121129
if donors is None:
122130
self.donor_data = {}
123131
else:
124132
self.donor_data = {d.norm_name: d for d in donors}
125133

134+
if db_file is None:
135+
self.db_file = data_dir / "mailroom_data.json"
136+
else:
137+
self.db_file = Path(db_file)
138+
139+
def mutating(self, method):
140+
"""
141+
Decorator that saves the DB when a change is made
142+
143+
It should be applied to all mutating methods, so the
144+
data will be saved whenever it's been changed.
145+
146+
NOTE: This is not very efficient -- it will re-write
147+
the entire file each time.
148+
"""
149+
def wrapped(*args, **kwargs):
150+
res = method(*args, **kwargs)
151+
self.save()
152+
return res
153+
return wrapped
154+
126155
@classmethod
127156
def load_from_file(cls, filename):
128157
"""
129-
loads a donor database from a json file
158+
loads a donor database from a raw json file
159+
NOTE: This is not a json_save format file!
160+
-- it is a simpler, less flexible format.
130161
"""
131162
with open(filename) as infile:
132163
donors = json.load(infile)
133164
db = cls([Donor(*d) for d in donors])
134165
return db
135166

167+
168+
@classmethod
169+
def load_json_save(cls, filename):
170+
"""
171+
loads a donor database from a json_save format file.
172+
"""
173+
174+
# with open(filename) as infile:
175+
# donors = json.load(infile)
176+
# db = cls([Donor(*d) for d in donors])
177+
# return db
178+
179+
def save(self):
180+
"""
181+
save the data to a json_save file
182+
"""
183+
with open(self.db_file, 'w') as db_file:
184+
self.to_json(db_file)
185+
136186
@property
137187
def donors(self):
138188
"""
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
sample data for testing, etc.
5+
6+
This is a python list of Donor objects, suitable for loading into a
7+
8+
DonorDB instance:
9+
10+
DB = DonorDB(sample_donor_data)
11+
12+
"""
13+
14+
from .model import Donor
15+
16+
17+
def sample_donor_data():
18+
return [Donor("William Gates III", [653772.32, 12.17]),
19+
Donor("Jeff Bezos", [877.33]),
20+
Donor("Paul Allen", [663.23, 43.87, 1.32]),
21+
Donor("Mark Zuckerberg", [1663.23, 4300.87, 10432.0])
22+
]
Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
"""
22
conftest.py
33
4-
This is a file that will automatically be read by pytest to find fixtures, etc.
4+
This is a file that will automatically be read by pytest to
5+
find fixtures, etc.
56
67
It's a good place to put stuff that multiple test files need.
78
"""
9+
from pathlib import Path
810

911
import pytest
10-
from mailroom import model, data_dir
12+
from mailroom.model import DonorDB
13+
from mailroom.sample_data import sample_donor_data
14+
15+
test_output_path = Path(__file__).parent / "output"
16+
17+
# make sure the output path exists
18+
test_output_path.mkdir(exist_ok=True)
1119

1220

1321
@pytest.fixture
1422
def sample_db():
15-
"""
16-
creates a clean sample database for the tests to use
17-
"""
18-
return model.DonorDB.load_from_file(data_dir / "sample_data.json")
23+
"""a clean DonorDB for tests"""
24+
return DonorDB(sample_donor_data(),
25+
db_file=test_output_path / "db1.json_save")
26+
27+
28+
@pytest.fixture
29+
def sample_db2():
30+
"""so we can have two separate ones if needed"""
31+
return DonorDB(sample_donor_data(),
32+
db_file=test_output_path / "db2.json_save")

solutions/mailroom_json_save/mailroom/test/test_json_save.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@
44
Test code for saving data to/from json with json_save
55
"""
66

7-
import pytest
87

9-
from mailroom import data_dir
10-
from mailroom.model import Donor, DonorDB
8+
import pytest
119

10+
from json_save import json_save_dec as js
1211

13-
@pytest.fixture()
14-
def sample_db():
15-
return DonorDB.load_from_file(data_dir / "sample_data.json")
12+
from mailroom.model import Donor, DonorDB
1613

1714

1815
def test_one_donor():
@@ -42,17 +39,34 @@ def test_donor_db(sample_db):
4239
db2 = DonorDB.from_json_dict(dbd)
4340

4441
# See if it's the same:
45-
jeff_bezos = db2.find_donor('jeff bezos')
46-
jeff_bezos.add_donation(2000)
42+
assert db2 == sample_db
43+
4744

48-
print(jeff_bezos)
45+
def test_donor_db_not_equal(sample_db, sample_db2):
46+
"""
47+
makes sure that two DBs aren't equal if you change something.
48+
49+
__eq__ is provided by json_save
50+
"""
51+
# They should be equal initially
4952

50-
print(db2.donor_data.keys())
53+
assert sample_db == sample_db2
54+
55+
# now make a change in one
56+
jeff_bezos = sample_db2.find_donor('jeff bezos')
57+
jeff_bezos.add_donation(2000)
58+
59+
assert sample_db != sample_db2
5160

52-
assert db2 == sample_db
5361

54-
print(db2)
62+
def test_save(sample_db):
63+
# save out the DB
64+
sample_db.save()
5565

56-
assert False
66+
# Make a new one from the file
67+
with open(sample_db.db_file) as js_file:
68+
DB = js.from_json(js_file)
5769

70+
# are they the same?
71+
assert sample_db == DB
5872

solutions/mailroom_json_save/mailroom/test/test_model.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
import os
2828
import pytest
29-
from mailroom import model, data_dir
29+
from mailroom import model
30+
3031

3132

3233
def test_empty_db():

solutions/mailroom_json_save/test_donor_db.json

Whitespace-only changes.

solutions/metaprogramming/json_save/json_save/json_save_dec.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66

77
import json
8+
from pathlib import Path
89

910
from .json_save_meta import *
1011

@@ -139,7 +140,7 @@ def from_json(_json):
139140
Factory function that re-creates a JsonSaveable object
140141
from a json string or file
141142
"""
142-
if isinstance(_json, str):
143+
if isinstance(_json, (str, Path)):
143144
return from_json_dict(json.loads(_json))
144145
else: # assume a file-like object
145146
return from_json_dict(json.load(_json))

0 commit comments

Comments
 (0)