Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 207 lines (173 sloc) 5.512 kb
77c581f @ethanpg Added initial Sphinx documentation.
ethanpg authored
1 """
2 The transparencydata module provides API wrappers for the data found on
3 transparencydata.com.
4 """
5
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
6 __author__ = "Jeremy Carbaugh (jcarbaugh@sunlightfoundation.com)"
7 __version__ = "0.1"
8 __copyright__ = "Copyright (c) 2010 Sunlight Labs"
9 __license__ = "BSD"
10
11 import sys
12
13 if sys.version_info[0] == 3:
14 from urllib.parse import urlencode, urljoin
15 from urllib.request import urlopen
16 from urllib.error import HTTPError
17 else:
18 from urllib import urlencode
19 from urlparse import urljoin
20 from urllib2 import HTTPError, urlopen
21
22 try:
23 import json
24 except ImportError:
25 import simplejson as json
26
27 DEFAULT_URL = "http://transparencydata.com/api/1.0/"
28 DEFAULT_PARAMETERS = ('apikey','page','per_page')
29 DEFAULT_HANDLERS = {}
30
31 class TransparencyDataError(Exception):
32 pass
33
dbf56b9 @ethanpg [#779] Adding brisket api.
ethanpg authored
34
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
35 # base client
36 class Client(object):
37
8284cee @ethanpg [#779] Restructured InfluenceExplorer API.
ethanpg authored
38 def __init__(self, key, base_url=DEFAULT_URL):
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
39 self.apikey = key
8284cee @ethanpg [#779] Restructured InfluenceExplorer API.
ethanpg authored
40 self.apiurl = base_url
cfb9a89 Make the existing print/return path an optional "debug" path and enab…
Sam Hart authored
41 self.debug = False
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
42
43 def __call__(self, **kwargs):
44
45 kwargs['apikey'] = self.apikey
46 params = {}
47
48 handlers = {}
49 handlers.update(DEFAULT_HANDLERS)
50 if hasattr(self, 'handlers'):
51 handlers.update(self.handlers)
52
53 for param, value in kwargs.iteritems():
54
55 (name, operator) = param.split('__') if '__' in param else (param, None)
56
57 if name not in self.parameters and name not in DEFAULT_PARAMETERS:
58 raise TransparencyDataError('%s is not a valid parameter' % param)
59
60 if operator == 'in':
61 if isinstance(value, (list, tuple)):
62 value = "|".join(str(v) for v in value)
63 else:
64 operator = None
65
66 elif operator == 'gt':
67 value = ">|%s" % value
68
69 elif operator == 'lt':
70 value = "<|%s" % value
71
72 elif operator == 'between':
73 if not isinstance(value, (list, tuple)):
74 raise TransparencyDataError('%s__%s must be a tuple or list' % (name, operator))
75 start = value[0].strftime("%Y-%m-%d")
76 end = value[1].strftime("%Y-%m-%d")
77 value = "><|%s|%s" % (start, end)
78
79 handler = handlers.get(name, None)
80 if handler:
81 value = handler(name, value, operator)
82
fa1bf18 @aaronsw support unicode parameters
aaronsw authored
83 params[name] = value.encode('utf8')
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
84
85 url = "%s?%s" % (urljoin(self.apiurl, self.endpoint), urlencode(params))
cfb9a89 Make the existing print/return path an optional "debug" path and enab…
Sam Hart authored
86 if self.debug:
87 print url
88 return
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
89
90 try:
91 response = urlopen(url).read().decode()
92 return json.loads(response)
93 except HTTPError, e:
94 raise TransparencyDataError(e.read())
95 except (ValueError, KeyError), e:
96 raise TransparencyDataError('Invalid Response')
97
98 # base types
99 class ContributionsClient(Client):
100 endpoint = 'contributions.json'
101 parameters = (
4a1cadf @ethanpg [#779] Added grants, contracts and earmarks.
ethanpg authored
102 'contributor_state',
103 'recipient_state',
104 'cycle',
105 'for_against',
106 'contributor_industry',
107 'seat',
108 'transaction_namespace',
109 'transaction_type',
110 'contributor_ext_id',
111 'recipient_ext_id',
112 'organization_ext_id',
113 'parent_organization_ext_id',
114 'committee_ext_id',
115 'contributor_type',
116 'recipient_type',
117 'date',
118 'amount',
119 'committee_ft',
120 'contributor_ft',
121 'employer_ft',
122 'organization_ft',
123 'recipient_ft',
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
124 )
125
126 class LobbyingClient(Client):
127 endpoint = 'lobbying.json'
128 parameters = (
4a1cadf @ethanpg [#779] Added grants, contracts and earmarks.
ethanpg authored
129 'lobbyist_is_rep',
130 'industry',
131 'transaction_id',
132 'transaction_type',
133 'filing_type',
134 'year',
135 'issue',
136 'client_ext_id',
137 'lobbyist_ext_id',
138 'candidate_ext_id',
139 'client_ft',
140 'client_parent_ft',
141 'lobbyist_ft',
142 'registrant_ft',
143 'issue_ft',
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
144 )
145
4a1cadf @ethanpg [#779] Added grants, contracts and earmarks.
ethanpg authored
146 class EarmarkClient(Client):
147 endpoint = 'earmarks.json'
148 parameters = (
149 'year',
150 'state',
151 'member_party',
152 'member_state',
153 'bill',
154 'description',
155 'city',
156 'member',
157 'recipient',
158 )
159
160
161 class GrantsClient(Client):
162 endpoint = 'grants.json'
163 parameters = (
164 'assistance_type',
165 'fiscal_year',
166 'recipient_state',
167 'recipient_type',
168 'agency_ft',
169 'recipient_ft',
170 )
171
172
173 class ContractsClient(Client):
174 endpoint = 'contracts.json'
175 parameters = (
176 'agency_id',
177 'contracting_agency_id',
178 'fiscal_year',
179 'place_distrct',
180 'place_state',
181 'requesting_agency_id',
182 'vendor_state',
183 'vendor_zipcode',
184 'vendor_district',
185 'vendor_duns',
186 'vendor_parent_duns',
187 'agency_name',
188 'contracting_agency_name',
189 'requesting_agency_name',
190 'vendor_name',
191 'vendor_city',
192 'obligated_amount',
193 'current_amount',
194 'maximum_amount',
195 )
0dff05d Testing commit to trigger ReadTheDocs update via web hook
Alison Rowland authored
196
4a1cadf @ethanpg [#779] Added grants, contracts and earmarks.
ethanpg authored
197
3215ab4 @jcarbaugh initial commit
jcarbaugh authored
198 # main wrapper
199 class TransparencyData(object):
200
201 def __init__(self, key):
202 self.contributions = ContributionsClient(key)
203 self.lobbying = LobbyingClient(key)
4a1cadf @ethanpg [#779] Added grants, contracts and earmarks.
ethanpg authored
204 self.earmarks = EarmarkClient(key)
205 self.grants = GrantsClient(key)
206 self.contracts = ContractsClient(key)
Something went wrong with that request. Please try again.