commit 58dae3324427d45565bc86bc8c453483268f0155 Author: Ryan McGrath Date: Thu Oct 29 04:07:17 2009 -0400 Initial commit - packaging may or may not work, as it's 4AM and I'm not sure I can bother spending too much more time on this. Use it for what it's worth. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6fdab59 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2009 Ryan McGrath + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..fb376a8 --- /dev/null +++ b/README.markdown @@ -0,0 +1,38 @@ +Pythentic Jobs +========================================================================================= +Pythentic Jobs is a small (pure Python) wrapper around the Authentic Jobs (http://www.authenticjobs.com) +API. I got bored one night, wanted something I could knock out quickly, so... here it is. + +Requirements +----------------------------------------------------------------------------------------------------- +Pythentic Jobs requires simpleJSON, because nobody should ever have to willingly see or deal with +XML ever again. Yeah, I'm opinionated like that, deal with it. + +> http://pypi.python.org/pypi/simplejson + + +Example Use +----------------------------------------------------------------------------------------------------- +> from pythentic_jobs import pythentic +> +> # Simply call Pythentic, and pass in your API key. +> jobs = pythentic("fajsnfjasdnf...") +> jobs.getLocations() + + +Pythentic 3k +----------------------------------------------------------------------------------------------------- +There's a script included that's built for Python 3. It's not guaranteed to work, as I don't actively +maintain it; it's simply there to provide a base to work on. Feel free to contribute back patches on +this if you so desire. + +Questions, Comments, etc? +----------------------------------------------------------------------------------------------------- +Pythentic Jobs should be simple enough that you would hopefully have no questions, but if you do, +feel free to hit me up at the following: + +GitHub: (Where you're probably reading this) +Twitter: ( http://twitter.com/ryanmcgrath ) +Email: (ryan [at] venodesigns dot net) + +Twython is released under an MIT License - see the LICENSE file for more information. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pythentic_jobs.py b/pythentic_jobs.py new file mode 100644 index 0000000..e5bb137 --- /dev/null +++ b/pythentic_jobs.py @@ -0,0 +1,126 @@ +#!/usr/bin/python + +"""Pythentic Jobs - A small pure Python wrapper for the Authentic Jobs API (http://www.authenticjobs.com/)""" + +import urllib2 + +from urlparse import urlparse +from urllib2 import HTTPError + +__author__ = "Ryan McGrath " +__version__ = "1.0" + +try: + import simplejson +except ImportError: + try: + import json as simplejson + except ImportError: + try: + from django.utils import simplejson + except: + raise Exception("pythentic_jobs requires the simplejson library (or Python 2.6) to work. http://www.undefined.org/python/") + +class PythenticJobsError(Exception): + def __init__(self, msg): + self.msg = msg + def __str__(self): + return repr(self.msg) + +class pythentic: + def __init__(self, api_key): + """ __init__() + + Instantiates an instance of Pythentic. Takes parameters for authentication and such (see below). + + Parameters: + api_key: Your API key that authenticates you for requests against Authentic Jobs. + """ + self.base_url = "http://www.authenticjobs.com/api/?api_key=%s&format=json" % api_key + + def checkResponse(self, resp): + """ checkResponse(self, resp) + + Takes the returned JSON result from Authentic Jobs and checks it for odd errors, returning the response + if everything checks out alright. There's only a few we actually have to check against; we dodge the others + by virtue of using a library. + + Parameters: + resp: A JSON object returned from Authentic Jobs. + """ + if resp["stat"] == "ok": + return resp + elif resp["stat"] == "fail": + if resp["code"] == 0: + raise PythenticJobsError("The Authentic Jobs API is currently undergoing maintenance. Try again in a bit!") + elif resp["code"] == 2: + raise PythenticJobsError("It would seem that your API key is disabled. Have you been doing something you shouldn't have? ;)") + else: + raise PythenticJobsError("There's something wrong with your API key; it can't be recognized. Check it, and try again.") + else: + raise PythenticJobsError("Something went terribly wrong. Check all your calls and try again!") + + def getCompanies(self): + """ getCompanies(self) + + Returns a list of companies that are currently advertising positions. + + Parameters: + None + """ + companies = simplejson.load(urllib2.urlopen(self.base_url + "&method=aj.jobs.getCompanies")) + return self.checkResponse(companies) + + def getLocations(self): + """ getLocations(self) + + Returns a list of locations for companies that are currently advertising positions. + + Parameters: + None + """ + locations = simplejson.load(urllib2.urlopen(self.base_url + "&method=aj.jobs.getLocations")) + return self.checkResponse(locations) + + def search(self, **kwargs): + """ search(self, **kwargs) + + Returns a list of current positions, filtered by optional parameters. The response is split into multiple pages, if necessary. + + Note: Pass all parameters as string arguments. + + Parameters: + category: The id of a job category to limit to. See getJobCategories(). + type: The id of a job type to limit to. See getJobTypes(). + sort: Accepted values are: date-posted-desc (the default) and date-posted-asc. + company: Free-text matching against company names. Suggested values are the ids from getCompanies(). + location: Free-text matching against company location names. Suggested values are the ids from getLocations(). + keywords: Keywords to look for in the title or description of the job posting. Separate multiple keywords with commas. Multiple keywords will be treated as an OR. + page: The page of listings to return. Defaults to 1. + perpage: The number of listings per page. The default value is 10. The maximum value is 100. + """ + search_url = self.base_url + "&method=aj.jobs.search" + "&".join(["%s=%s" %(key, value) for (key, value) in kwargs.iteritems()]) + results = simplejson.load(urllib2.urlopen(search_url)) + return self.checkResponse(results) + + def getJobTypes(self): + """ getJobTypes(self) + + Returns a list of available job types. + + Parameters: + None + """ + retlist = simplejson.load(urllib2.urlopen(self.base_url + "&method=aj.types.getList")) + return self.checkResponse(retlist) + + def getJobCategories(self): + """ getJobCategories(self) + + Returns a list of current job categories. + + Parameters: + None + """ + retlist = simplejson.load(urllib2.urlopen(self.base_url + "&method=aj.categories.getList")) + return self.checkResponse(retlist) diff --git a/pythentic_jobs3k.py b/pythentic_jobs3k.py new file mode 100644 index 0000000..6089c42 --- /dev/null +++ b/pythentic_jobs3k.py @@ -0,0 +1,126 @@ +#!/usr/bin/python + +"""Pythentic Jobs - A small pure Python wrapper for the Authentic Jobs API (http://www.authenticjobs.com/)""" + +import urllib.request, urllib.error, urllib.parse + +from urllib.parse import urlparse +from urllib.error import HTTPError + +__author__ = "Ryan McGrath " +__version__ = "1.0" + +try: + import simplejson +except ImportError: + try: + import json as simplejson + except ImportError: + try: + from django.utils import simplejson + except: + raise Exception("pythentic_jobs requires the simplejson library (or Python 2.6) to work. http://www.undefined.org/python/") + +class PythenticJobsError(Exception): + def __init__(self, msg): + self.msg = msg + def __str__(self): + return repr(self.msg) + +class pythentic: + def __init__(self, api_key): + """ __init__() + + Instantiates an instance of Pythentic. Takes parameters for authentication and such (see below). + + Parameters: + api_key: Your API key that authenticates you for requests against Authentic Jobs. + """ + self.base_url = "http://www.authenticjobs.com/api/?api_key=%s&format=json" % api_key + + def checkResponse(self, resp): + """ checkResponse(self, resp) + + Takes the returned JSON result from Authentic Jobs and checks it for odd errors, returning the response + if everything checks out alright. There's only a few we actually have to check against; we dodge the others + by virtue of using a library. + + Parameters: + resp: A JSON object returned from Authentic Jobs. + """ + if resp["stat"] == "ok": + return resp + elif resp["stat"] == "fail": + if resp["code"] == 0: + raise PythenticJobsError("The Authentic Jobs API is currently undergoing maintenance. Try again in a bit!") + elif resp["code"] == 2: + raise PythenticJobsError("It would seem that your API key is disabled. Have you been doing something you shouldn't have? ;)") + else: + raise PythenticJobsError("There's something wrong with your API key; it can't be recognized. Check it, and try again.") + else: + raise PythenticJobsError("Something went terribly wrong. Check all your calls and try again!") + + def getCompanies(self): + """ getCompanies(self) + + Returns a list of companies that are currently advertising positions. + + Parameters: + None + """ + companies = simplejson.load(urllib.request.urlopen(self.base_url + "&method=aj.jobs.getCompanies")) + return self.checkResponse(companies) + + def getLocations(self): + """ getLocations(self) + + Returns a list of locations for companies that are currently advertising positions. + + Parameters: + None + """ + locations = simplejson.load(urllib.request.urlopen(self.base_url + "&method=aj.jobs.getLocations")) + return self.checkResponse(locations) + + def search(self, **kwargs): + """ search(self, **kwargs) + + Returns a list of current positions, filtered by optional parameters. The response is split into multiple pages, if necessary. + + Note: Pass all parameters as string arguments. + + Parameters: + category: The id of a job category to limit to. See getJobCategories(). + type: The id of a job type to limit to. See getJobTypes(). + sort: Accepted values are: date-posted-desc (the default) and date-posted-asc. + company: Free-text matching against company names. Suggested values are the ids from getCompanies(). + location: Free-text matching against company location names. Suggested values are the ids from getLocations(). + keywords: Keywords to look for in the title or description of the job posting. Separate multiple keywords with commas. Multiple keywords will be treated as an OR. + page: The page of listings to return. Defaults to 1. + perpage: The number of listings per page. The default value is 10. The maximum value is 100. + """ + search_url = self.base_url + "&method=aj.jobs.search" + "&".join(["%s=%s" %(key, value) for (key, value) in kwargs.items()]) + results = simplejson.load(urllib.request.urlopen(search_url)) + return self.checkResponse(results) + + def getJobTypes(self): + """ getJobTypes(self) + + Returns a list of available job types. + + Parameters: + None + """ + retlist = simplejson.load(urllib.request.urlopen(self.base_url + "&method=aj.types.getList")) + return self.checkResponse(retlist) + + def getJobCategories(self): + """ getJobCategories(self) + + Returns a list of current job categories. + + Parameters: + None + """ + retlist = simplejson.load(urllib.request.urlopen(self.base_url + "&method=aj.categories.getList")) + return self.checkResponse(retlist) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a3159da --- /dev/null +++ b/setup.py @@ -0,0 +1,47 @@ +#!/usr/bin/python + +import sys, os + +__author__ = 'Ryan McGrath ' +__version__ = '1.0' + +# For the love of god, use Pip to install this. + +# Distutils version +METADATA = dict( + name = "pythentic_jobs", + version = __version__, + py_modules = ['pythentic_jobs'], + author='Ryan McGrath', + author_email='ryan@venodesigns.net', + description='A small (pure Python) wrapper around the Authentic Jobs (http://www.authenticjobs.com) API.', + long_description= open("README.markdown").read(), + license='MIT License', + url='http://github.com/ryanmcgrath/pythentic_jobs/tree/master', + keywords='jobs careers api', +) + +# Setuptools version +SETUPTOOLS_METADATA = dict( + install_requires = ['setuptools', 'simplejson'], + include_package_data = True, + classifiers = [ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: Internet', + ] +) + +def Main(): + try: + import setuptools + METADATA.update(SETUPTOOLS_METADATA) + setuptools.setup(**METADATA) + except ImportError: + import distutils.core + distutils.core.setup(**METADATA) + +if __name__ == '__main__': + Main()