Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 3215ab49da03d60d984f1377e5b6e47c002ee973 @jcarbaugh jcarbaugh committed Apr 6, 2010
Showing with 169 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +30 −0 LICENSE
  3. +1 −0 MANIFEST.in
  4. 0 README.rst
  5. +24 −0 setup.py
  6. +112 −0 transparencydata.py
2 .gitignore
@@ -0,0 +1,2 @@
+*.pyc
+ignored.py
30 LICENSE
@@ -0,0 +1,30 @@
+BSD-style license
+=================
+
+Copyright (c) 2010, Sunlight Labs
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of Sunlight Labs nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 MANIFEST.in
@@ -0,0 +1 @@
+include LICENSE *.rst *.py
0 README.rst
No changes.
24 setup.py
@@ -0,0 +1,24 @@
+from distutils.core import setup
+from transparencydata import __version__
+
+long_description = open('README.rst').read()
+
+setup(name="python-transparencydata",
+ version=__version__,
+ py_modules=["transparencydata"],
+ description="Library for interacting with the Sunlight Labs Transparency Data API",
+ author="Jeremy Carbaugh",
+ author_email = "jcarbaugh@sunlightfoundation.com",
+ license='BSD',
+ url="http://github.com/sunlightlabs/python-transparencydata/",
+ long_description=long_description,
+ platforms=["any"],
+ classifiers=["Development Status :: 4 - Beta",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: BSD License",
+ "Natural Language :: English",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
+ )
112 transparencydata.py
@@ -0,0 +1,112 @@
+__author__ = "Jeremy Carbaugh (jcarbaugh@sunlightfoundation.com)"
+__version__ = "0.1"
+__copyright__ = "Copyright (c) 2010 Sunlight Labs"
+__license__ = "BSD"
+
+import sys
+
+if sys.version_info[0] == 3:
+ from urllib.parse import urlencode, urljoin
+ from urllib.request import urlopen
+ from urllib.error import HTTPError
+else:
+ from urllib import urlencode
+ from urlparse import urljoin
+ from urllib2 import HTTPError, urlopen
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+DEFAULT_URL = "http://transparencydata.com/api/1.0/"
+DEFAULT_PARAMETERS = ('apikey','page','per_page')
+DEFAULT_HANDLERS = {}
+
+class TransparencyDataError(Exception):
+ pass
+
+# base client
+class Client(object):
+
+ def __init__(self, key):
+ self.apikey = key
+ self.apiurl = DEFAULT_URL
+
+ def __call__(self, **kwargs):
+
+ kwargs['apikey'] = self.apikey
+ params = {}
+
+ handlers = {}
+ handlers.update(DEFAULT_HANDLERS)
+ if hasattr(self, 'handlers'):
+ handlers.update(self.handlers)
+
+ for param, value in kwargs.iteritems():
+
+ (name, operator) = param.split('__') if '__' in param else (param, None)
+
+ if name not in self.parameters and name not in DEFAULT_PARAMETERS:
+ raise TransparencyDataError('%s is not a valid parameter' % param)
+
+ if operator == 'in':
+ if isinstance(value, (list, tuple)):
+ value = "|".join(str(v) for v in value)
+ else:
+ operator = None
+
+ elif operator == 'gt':
+ value = ">|%s" % value
+
+ elif operator == 'lt':
+ value = "<|%s" % value
+
+ elif operator == 'between':
+ if not isinstance(value, (list, tuple)):
+ raise TransparencyDataError('%s__%s must be a tuple or list' % (name, operator))
+ start = value[0].strftime("%Y-%m-%d")
+ end = value[1].strftime("%Y-%m-%d")
+ value = "><|%s|%s" % (start, end)
+
+ handler = handlers.get(name, None)
+ if handler:
+ value = handler(name, value, operator)
+
+ params[name] = value
+
+ url = "%s?%s" % (urljoin(self.apiurl, self.endpoint), urlencode(params))
+ print url
@jamesturk
jamesturk added a line comment Jul 2, 2010

:(

@jcarbaugh
jcarbaugh added a line comment Jul 2, 2010

print isn't used enough!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ return
+
+ try:
+ response = urlopen(url).read().decode()
+ return json.loads(response)
+ except HTTPError, e:
+ raise TransparencyDataError(e.read())
+ except (ValueError, KeyError), e:
+ raise TransparencyDataError('Invalid Response')
+
+# base types
+class ContributionsClient(Client):
+ endpoint = 'contributions.json'
+ parameters = (
+ 'amount','contributor_ft','contributor_state','cycle',
+ 'date','employer_ft','recipient_ft','recipient_state',
+ 'seat','transaction_namespace','contributor_industry',
+ )
+
+class LobbyingClient(Client):
+ endpoint = 'lobbying.json'
+ parameters = (
+ 'amount','client_ft','client_parent_ft','filing_type',
+ 'lobbyist_ft','registrant_ft','transaction_id',
+ 'transaction_type','year'
+ )
+
+# main wrapper
+class TransparencyData(object):
+
+ def __init__(self, key):
+ self.contributions = ContributionsClient(key)
+ self.lobbying = LobbyingClient(key)

0 comments on commit 3215ab4

Please sign in to comment.