[
  {
    "path": ".gitignore",
    "content": "*.pyc"
  },
  {
    "path": "README.md",
    "content": "# indeed-python\n\nA client library for using the Indeed Jobsearch API\n\n## Installation\n\nInstall from PyPi using [pip](http://www.pip-installer.org/en/latest/), a\npackage manager for Python.\n\n    $ pip install indeed\n\nDon't have pip installed? Try installing it, by running this from the command\nline:\n\n    $ curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python\n\n## API Credentials\n\nThe Indeed API needs to be called with your Indeed publisher number. You must pass this\nto the `IndeedClient` constructor.\n\n```python\nfrom indeed import IndeedClient\n\nclient = IndeedClient(publisher = YOUR_PUBLISHER_NUMBER)\n```\n\nIf you do not have a publisher number, you can receive one by heading to the\n[Indeed Publisher Portal](https://ads.indeed.com/jobroll/xmlfeed).\n\n\n## Performing a Job Search\n\n```python\nfrom indeed import IndeedClient\n\nclient = IndeedClient('YOUR_PUBLISHER_NUMBER')\n\nparams = {\n    'q' : \"python\",\n    'l' : \"austin\",\n    'userip' : \"1.2.3.4\",\n    'useragent' : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2)\"\n}\n\nsearch_response = client.search(**params)\n```\n\n## Retrieving Job Details\n\n```python\nfrom indeed import IndeedClient\n\nclient = IndeedClient('YOUR_PUBLISHER_NUMBER')\n\njob_response = client.jobs(jobkeys = (\"5898e9d8f5c0593f\", \"c2c41f024581eae5\"))\n```\n\n## API Paramaters\n\n### Job Search\n\n**q** - \nQuery. By default terms are ANDed. To see what is possible, use our [advanced search](http://www.indeed.com/advanced_search) page to perform a search and then check the url for the q value.\n\n**l** - \nLocation. Use a postal code or a \"city, state/province/region\" combination.\n\n**userip** - \nThe IP number of the end-user to whom the job results will be displayed. *This field is required*.\n\n**useragent** - \nThe User-Agent (browser) of the end-user to whom the job results will be displayed. This can be obtained from the \"User-Agent\" HTTP request header from the end-user. *This field is required*.\n\n**format** - \nFormat. Which output format of the API you wish to use. The options are \"xml\" and \"json.\". Default is \"json\". The `IndeedClient` requests and parses a json repsonse by default. If you with to use the xml format, requests will be performed with the **raw** parameter set to `True`, see **raw**.\n\n**raw** - \nA boolean. Receive the raw json/xml response from the Indeed API. Use in addition with *format* to specify which response format you would like. Default is `False`\n\n**sort** - \nSort by relevance or date. Default is relevance.\n\n**radius** - \nDistance from search location (\"as the crow flies\"). Default is 25.\n\n**start** - \nStart results at this result number, beginning with 0. Default is 0.\n\n**limit** - \nMaximum number of results returned per query. Default is 10, Maximum is 25\n\n**fromage** - \nNumber of days back to search.\n\n**highlight** - \nSetting this value to 1 will bold terms in the snippet that are also present in q. Default is 0.\n\n**filter** - \nFilter duplicate results. 0 turns off duplicate job filtering. Default is 1.\n\n**latlong** - \nIf latlong=1, returns latitude and longitude information for each job result. Default is 0.\n\n**co** - \nSearch within country specified. Default is *us*.\n\n\n### Job Details\n\n**jobkeys** - \nJob keys. A list of job keys specifying the jobs to look up. *This parameter is required*.\n\n**format** - \nFormat. Which output format of the API you wish to use. The options are \"xml\" and \"json.\". Default is \"json\". The `IndeedClient` requests and parses a json repsonse by default. If you with to use the xml format, requests will be performed with the **raw** parameter set to `True`, see **raw**.\n\n**raw** - \nA boolean. Receive the raw json/xml response from the Indeed API. Use in addition with *format* to specify which response format you would like. Default is `False`\n"
  },
  {
    "path": "indeed/__init__.py",
    "content": "import requests\n\nDEFAULT_FORMAT = \"json\"\nAPI_ROOT = \"http://api.indeed.com/ads\"\nAPI_SEARCH = {'end_point': \"%s/apisearch\" % API_ROOT, 'required_fields': ['userip', 'useragent', ['q', 'l']]}\nAPI_JOBS = {'end_point': \"%s/apigetjobs\" % API_ROOT, 'required_fields': ['jobkeys']}\n\nclass IndeedClientException(Exception):\n    pass\n\nclass IndeedClient:\n    def __init__(self, publisher, version = \"2\"):\n        self.publisher = publisher\n        self.version = version\n\n    def search(self, **args):\n        return self.__process_request(API_SEARCH.get('end_point'), self.__valid_args(API_SEARCH.get('required_fields'), args))\n\n    def jobs(self, **args):\n        valid_args = self.__valid_args(API_JOBS.get('required_fields'), args)\n        valid_args['jobkeys'] = \",\".join(valid_args['jobkeys'])\n        return self.__process_request(API_JOBS.get('end_point'), valid_args)\n\n    def __process_request(self, endpoint, args):\n        format = args.get('format', DEFAULT_FORMAT)\n        raw = True if format == 'xml' else args.get('raw', False)\n        args.update({'v': self.version, 'publisher': self.publisher, 'format': format})\n        r = requests.get(endpoint, params = args)\n        return r.json() if not raw else r.content\n\n    def __valid_args(self, required_fields, args):\n        for field in required_fields:\n            if type(field) is list:\n                validation_list = [args.get(f) != None for f in field]\n                if not (True in validation_list):\n                    raise IndeedClientException(\"You must provide one of the following %s\" % \",\".join(field))\n            elif not args.get(field):\n                raise IndeedClientException(\"The field %s is required\" % field)\n        return args\n\n\n"
  },
  {
    "path": "setup.py",
    "content": "from distutils.core import setup\n\nsetup(\n    name = 'indeed',\n    version = '0.0.4',\n    description = 'Indeed Job Search Python Api Client',\n    author = 'Indeed Labs',\n    author_email = 'labs-team@indeed.com',\n    packages = ['indeed'],\n    install_requires=['requests==2.0.0'],\n    url = \"https://github.com/indeedlabs/indeed-python\",\n)\n"
  },
  {
    "path": "tests/test_jobs.py",
    "content": "from nose.tools import *\nimport json\nfrom xml.dom.minidom import parseString\nfrom indeed import IndeedClient, IndeedClientException\n\nclass TestJobs:\n\n    def setup(self):\n        self.client = IndeedClient(\"YOUR_PUBLISHER_NUMBER\")\n        self.params = {\n            'jobkeys' : (\"5898e9d8f5c0593f\", \"c2c41f024581eae5\"),\n        }\n\n    def teardown(self):\n        self.client = None\n        self.params = None\n\n    @with_setup(setup, teardown)\n    def test_jobs(self):\n        jobs_response = self.client.jobs(**self.params)\n        assert type(jobs_response) is dict\n\n    @with_setup(setup, teardown)\n    @raises(IndeedClientException)\n    def test_missing_jobkeys(self):\n        del self.params['jobkeys']\n        jobs_response = self.client.jobs(**self.params)\n\n    @with_setup(setup, teardown)\n    def test_raw_json(self):\n        self.params['raw'] = True\n        jobs_response = self.client.jobs(**self.params)\n        assert isinstance(jobs_response, basestring)\n        assert type(json.loads(jobs_response)) is dict\n\n    @with_setup(setup, teardown)\n    def test_raw_xml_with_paramter(self):\n        self.params['format'] = \"xml\"\n        self.params['raw'] = True\n        jobs_response = self.client.jobs(**self.params)\n        assert isinstance(jobs_response, basestring)\n        assert parseString(jobs_response)\n\n    @with_setup(setup, teardown)\n    def test_raw_xml_without_paramter(self):\n        self.params['format'] = \"xml\"\n        jobs_response = self.client.jobs(**self.params)\n        assert isinstance(jobs_response, basestring)\n        assert parseString(jobs_response)"
  },
  {
    "path": "tests/test_search.py",
    "content": "from nose.tools import *\nimport json\nfrom xml.dom.minidom import parseString\nfrom indeed import IndeedClient, IndeedClientException\n\nclass TestSearch:\n\n    def setup(self):\n        self.client = IndeedClient(\"YOUR_PUBLISHER_NUMBER\")\n        self.params = {\n            'q' : \"python\",\n            'l' : \"austin\",\n            'userip' : \"1.2.3.4\",\n            'useragent' : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2)\",\n        }\n\n    def teardown(self):\n        self.client = None\n        self.params = None\n\n    @with_setup(setup, teardown)\n    def test_search(self):\n        search_response = self.client.search(**self.params)\n        assert type(search_response) is dict\n\n    @with_setup(setup, teardown)\n    def test_missing_one_required(self):\n        del self.params['l']\n        search_response = self.client.search(**self.params)\n        assert type(search_response) is dict\n\n    @with_setup(setup, teardown)\n    @raises(IndeedClientException)\n    def test_missing_both_required(self):\n        del self.params['q']\n        del self.params['l']\n        search_response = self.client.search(**self.params)\n\n    @with_setup(setup, teardown)\n    @raises(IndeedClientException)\n    def test_missing_userip(self):\n        del self.params['userip']\n        search_response = self.client.search(**self.params)\n\n    @with_setup(setup, teardown)\n    @raises(IndeedClientException)\n    def test_missing_useragent(self):\n        del self.params['useragent']\n        search_response = self.client.search(**self.params)\n\n    @with_setup(setup, teardown)\n    def test_raw_json(self):\n        self.params['raw'] = True\n        search_response = self.client.search(**self.params)\n        assert isinstance(search_response, basestring)\n        assert type(json.loads(search_response)) is dict\n\n    @with_setup(setup, teardown)\n    def test_raw_xml_with_paramter(self):\n        self.params['format'] = \"xml\"\n        self.params['raw'] = True\n        search_response = self.client.search(**self.params)\n        assert isinstance(search_response, basestring)\n        assert parseString(search_response)\n\n    @with_setup(setup, teardown)\n    def test_raw_xml_without_paramter(self):\n        self.params['format'] = \"xml\"\n        search_response = self.client.search(**self.params)\n        assert isinstance(search_response, basestring)\n        assert parseString(search_response)\n"
  }
]