-
Notifications
You must be signed in to change notification settings - Fork 0
/
DataSource.py
372 lines (348 loc) · 15 KB
/
DataSource.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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#!/usr/bin/python
# -*- coding: utf-8 -*-
#import cgitb
#cgitb.enable()
import os.path
import sys
import psycopg2
import datetime
from Bill import Bill
from Senator import Senator
from Committee import Committee
from Session import Session
class DataSource:
"""SQL database interface class that contains methods for getting
information from the database while handling SQL connections itself"""
def __init__(self):
# This constructor reads the database password from the secret
# directory and uses that password to open an SQL database connection
# usin psycopg2 as an interface.
USERNAME = 'emeryj'
DB_NAME = 'emeryj'
try:
#f = open('testpassfileworkaround') <--- UNCOMMENT ME FOR TESTS
f = open(os.path.join('/cs257', USERNAME))
PASSWORD = f.read().strip()
f.close()
except:
print "failed to connect to the database directory"
global db_connection
try:
db_connection = psycopg2.connect(user=USERNAME,
database=DB_NAME,
password=PASSWORD)
except:
print "psycopg2 failed to load the directory"
def getBill(self, bill_id):
# Returns a bill object corresponding to the id of the bill it is given
# without any vote information.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT id, session, roll, vote_date, type, question FROM bills WHERE id = (%s);',
(bill_id, ))
bills = []
for row in cursor:
bills.append(Bill(row))
if len(bills)==1:
return bills[0]
else:
return None
except:
db_connection.rollback()
def getBillWithVotes(self, bill_id):
# Returns a bill object corresponding to id of the bill it is given as
# well as returning lists of senator objects corresponding to the
# voters on said bill.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM bills WHERE id = (%s);',
(bill_id, ))
bills = []
for row in cursor:
yea = []
nay = []
present = []
not_voting = []
# Loops through each row of the votes and gets senator objects
# corresponding to all of the ID numbers in the array
for senator in row[6]:
yea.append(self.getSenator(senator))
for senator in row[7]:
nay.append(self.getSenator(senator))
for senator in row[8]:
present.append(self.getSenator(senator))
for senator in row[9]:
not_voting.append(self.getSenator(senator))
bil = list(row)[:6] + list([yea, nay, present, not_voting])
bills.append(Bill(bil))
if len(bills)==1:
return bills[0]
else:
return None
except:
db_connection.rollback()
def getSenator(self, senator_id):
# Returns a Senator object corresponding to id of the bill it is given.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM senators WHERE id = (%s);',
(senator_id,))
senators = []
for row in cursor:
senators.append(Senator(row))
if len(senators)==1:
return senators[0]
else:
print senator_id
return None
except:
db_connection.rollback()
def getSenatorWithCommittees(self, senator_id):
# Returns a Senator object corresponding to the Senator id it was
# passed except with a list of committee objects correspoinding to the
# committees that the senator has been part of.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM senators WHERE id = (%s);',
(senator_id,))
rows = []
for row in cursor:
rows.append(row)
# If only one senator was found, it searches the
# committee_membership_pair table to find all the committees the
# senator is a part of, and builds a committee object for each one.
if len(rows)==1:
cursor.execute('''SELECT * FROM committee_membership_pair
WHERE senator = (%s);''',
(senator_id,))
committees = []
for pair in cursor:
committees.append([self.getCommittee(pair[0]), pair[2]])
subrow = rows[0]
sen_row = [subrow[0], subrow[1], subrow[2], subrow[3], subrow[4],
subrow[5], subrow[6], subrow[7], subrow[8], committees]
return Senator(sen_row)
else:
return None
except:
db_connection.rollback()
def getSenatorList(self):
# Returns a list of Senator objects corresponding to every senator in
# the database.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM senators;')
senators = []
for row in cursor:
senators.append(Senator(row))
return senators
except:
db_connection.rollback()
def getBillList(self):
# Returns a list of Bill objects corresponding to every bill in the
# database.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM bills;')
bills = []
for row in cursor:
bills.append(Bill(row))
return bills
except:
db_connection.rollback()
def getSenatorsInSession(self, session):
# Returns a list of Senator objects corresponding to the members of the
# specified congress.
try:
cursor = db_connection.cursor()
cursor.execute('''SELECT senators FROM sessions
WHERE number = (%s);''', (session, ))
senators = []
for row in cursor:
for ident in row[0]:
senators.append(self.getSenator(ident))
return senators
except:
db_connection.rollback()
def getVotesBySenator(self, senator_id, number):
# Returns a double list of containing the last number (or all votes in
# the database number =0) reverse chronological votes that the senator
# has participated in. The first value in the tuple is bill object
# correspoinding to the bill in question and the second value is a
# string representing the senators vote.
try:
cursor = db_connection.cursor()
cursor.execute('''SELECT number,senators
FROM sessions
ORDER BY number DESC;''')
# Determines what congress the senator belongs and stores the ID of
# that congress in a list.
member_congresses = []
for row in cursor:
list_senators = row[1]
for ident in list_senators:
if ident == int(senator_id):
member_congresses.append(row[0])
if len(member_congresses) == 0:
return []
# Loops through the bills in the congress, then loops through the
# votes in the congress looking for places where the particular
# senator appears on the voting roll.
bills_voted = []
for session in member_congresses:
cursor.execute('''SELECT id, yea_votes, nay_votes, present, not_voting FROM bills
where session = (%s)
ORDER BY vote_date DESC;''',
(session,))
for row in cursor:
# Stops the search if the requisite number of bills has been
# found.
if (number != 0)&(len(bills_voted) >= number):
break
# Loops through each list of votes and searches for the senator
# in the vote rolls, if the senator is found then a bill object
# is constructed and added to the running list.
for ident in row[1]:
if ident == int(senator_id):
bills_voted.append([self.getBill(row[0]),"yea"])
for ident in row[2]:
if ident == int(senator_id):
bills_voted.append([self.getBill(row[0]),"nay"])
for ident in row[3]:
if ident == int(senator_id):
bills_voted.append([self.getBill(row[0]),"present"])
for ident in row[4]:
if ident == int(senator_id):
bills_voted.append([self.getBill(row[0]),"not_voting"])
return bills_voted
except:
db_connection.rollback()
def getBillsInCongress(self, congress, number):
# Returns a list of the id numbers for the last number bills in
# congress in reverse chronological. Specifying more bills than are in
# the congress returns all available bills, and specifying zero bills
# returns all bills.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT bills FROM sessions WHERE number = (%s);',
(congress,))
bills = []
for row in cursor:
for bill_id in row[0]:
bills.append(self.getBill(bill_id))
if (number != 0)&(len(bills) >= number):
break
return bills
except:
db_connection.rollback()
def getSenatorsInState(self, state_name):
# Returns a list that corresponds to the id number for each senator in
# a given state with the name for each state given as a string.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM senators WHERE state = (%s);',
(state_name,))
senators = []
for row in cursor:
senators.append(Senator(row))
return senators
except:
db_connection.rollback()
def getCommittee(self, committee_id):
# Returns a Committee object corresponding to the ID number it gets
# with a populated list of senator objects corresponding to its members.
try:
cursor = db_connection.cursor()
cursor.execute('''SELECT id, name, super_committee, session
FROM committees WHERE id = (%s);''',
(committee_id,))
committees = []
for row in cursor:
committees.append(Committee(row))
if len(committees) == 1:
return committees[0]
else:
return None
except:
db_connection.rollback()
def getCommitteeWithMembers(self, committee_id):
# Returns a Committee object corresponding to the ID number it gets
# with a populated list of senator objects corresponding to its members
# as well as populating the 'associated' field in committes with a list
# of tuples that contain the id and name of the super committee or sub
# committee.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM committees WHERE id = (%s);',
(committee_id,))
committees = []
for row in cursor:
# Grabs the senators in the nested array stored in the
# database and builds a senator object out of them.
members = []
if row[4] != None:
for member in row[4]:
senator = self.getSenator(int(member[0]))
members.append([senator,member[1]])
args = [row[0], row[1], row[2], row[3], members]
# Searches the database for all the committees that have this
# committee listed in the 'super_committee' category and adds a
# tuple of it's id and name to the end of the row for the
# constructor.
subcursor = db_connection.cursor()
# If the current commmittee is a sub committee or super committee
# and either gets the super committee or all of the committees
# associated with this one.
if args[0] == args[2]:
subcursor.execute('''SELECT id,name FROM committees
WHERE super_committee = (%s);''',
(args[2],))
else:
subcursor.execute('''SELECT id,name FROM committees
WHERE id = (%s);''',
(args[2],))
associated_committees = []
for subrow in subcursor:
if args[0] != subrow[0]:
associated_committees.append([subrow[0],subrow[1]])
args.append(associated_committees)
committees.append(Committee(args))
if len(committees) == 1:
return committees[0]
else:
return None
except:
db_connection.rollback()
def getCommitteesBySession(self, congress):
# Returns a list of committee objects correspoinding to the committees
# in a given congressional session.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT * FROM committees WHERE session = (%s);',
(congress,))
committees = []
for row in cursor:
committees.append(Committee(row))
return committees
except:
db_connection.rollback()
def getSessionObject(self, congress):
# Returns a session object containing the rows of the table and lists
# of senator objects and bill objects corresponding to the session.
try:
cursor = db_connection.cursor()
cursor.execute('SELECT number, start_date, end_date FROM sessions WHERE number = (%s);',
(congress,))
congresses = []
for row in cursor:
args = [row[0],row[1],row[2]]
args.append(self.getSenatorsInSession(congress))
args.append(self.getBillsInCongress(congress,0))
args.append(self.getCommitteesBySession(congress))
congresses.append(Session(args))
if len(congresses) == 1:
return congresses[0]
else:
return None
except:
db_connection.rollback()