forked from opensecrets/python-crpapi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcrpapi.py
More file actions
142 lines (115 loc) · 4.35 KB
/
Copy pathcrpapi.py
File metadata and controls
142 lines (115 loc) · 4.35 KB
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
"""
Python library for interacting with the CRP API.
The CRP API (http://www.opensecrets.org/action/api_doc.php) provides campaign
finance and other data from the Center for Responsive Politics.
See README.rst for methods and usage
"""
__author__ = "James Turk (jturk@sunlightfoundation.com)"
__version__ = "0.1.0"
__copyright__ = "Copyright (c) 2009 Sunlight Labs"
__license__ = "BSD"
import urllib
try:
import requests
except Exception as e:
print(e)
# Timeout in seconds to wait for a response from the API, as (connect, read).
# Must not be None: requests.get() without a timeout blocks forever, wedging a
# uWSGI worker on a slow/down opensecrets.org until the 120s harakiri — the
# cause of the 2026-07-27 justfacts outage. Mirrors elections/nimsp.py TIMEOUT.
# Callers catch CRPApiError and degrade (page renders without finance data),
# so failing fast is safe.
TIMEOUT = (3.05, 10)
class CRPApiError(Exception):
""" Exception for CRP API errors """
# results #
class CRPApiObject(object):
def __init__(self, d):
self.__dict__ = d
# namespaces #
class CRP(object):
apikey = None
@staticmethod
def _apicall(func, params):
if CRP.apikey is None:
raise CRPApiError('Missing CRP apikey')
url = 'http://www.opensecrets.org/api/' \
'?method=%s&output=json&apikey=%s&%s' % \
(func, CRP.apikey, urllib.parse.urlencode(params))
try:
headers = {'User-Agent': 'Votesmart.org'}
response = requests.get(url, headers=headers, timeout=TIMEOUT)
response.raise_for_status()
return response.json()['response']
except requests.RequestException as e:
# Covers Timeout, ConnectionError and HTTPError (all subclasses).
# The previous handler called e.read(), which is urllib2 API and
# does not exist on requests exceptions.
raise CRPApiError(str(e))
except (ValueError, KeyError):
raise CRPApiError('Invalid Response')
class getLegislators(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('getLegislators', kwargs)['legislator']
return results
class memPFDprofile(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('memPFDprofile', kwargs)['member_profile']
return results
class candSummary(object):
@staticmethod
def get(**kwargs):
result = CRP._apicall('candSummary', kwargs)['summary']
return result['@attributes']
class candContrib(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('candContrib', kwargs)['contributors']['contributor']
return results
class candIndustry(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('candIndustry', kwargs)['industries']['industry']
return results
class candSector(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('candSector', kwargs)['sectors']['sector']
return results
class candIndByInd(object):
@staticmethod
def get(**kwargs):
result = CRP._apicall('CandIndByInd', kwargs)['candIndus']
return result['@attributes']
class getOrgs(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('getOrgs', kwargs)['organization']
return results
class orgSummary(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('orgSummary', kwargs)['organization']
return results
class congCmteIndus(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('congCmteIndus', kwargs)['committee']['member']
return results
class presCandContrib(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('prescandContrib', kwargs)
return results
class presCandIndustry(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('prescandIndustry', kwargs)
return results
class presCandSector(object):
@staticmethod
def get(**kwargs):
results = CRP._apicall('prescandSector', kwargs)
return results