Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions History.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Replaced: urllib2 with requests package
* Replaced: oauth2 with requests_oauthlib package
* Added: optional timeout parameter
* Removed: support for Python 2.4/2.5

0.4.0 / 2013-07-23
==================
Expand Down
15 changes: 5 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
A small class to help connect to the OpenX Enterprise API. As of version 0.5.0 it uses
[requests_oauthlib](https://github.com/requests/requests-oauthlib) instead of oauth2.

It currently supports Python 2.4 - 2.7, with 3.x support coming in the future.
It currently supports Python 2.6 - 2.7, with 3.x support coming in the future.

As of version 0.4.0, ox3apiclient supports API v2. If your instance is v2,
set the api_path option to "/ox/4.0".
Expand Down Expand Up @@ -33,7 +33,7 @@ order = {
'status': 'Active',
'name': 'OX3APIClient Object Creation Test',
'account_uid': accounts['objects'][0]['account_uid'],
'start_date': '2015-06-01 00:00:00'}
'start_date': '2016-06-01 00:00:00'}

new_order = ox.post('/order', data=order)

Expand All @@ -50,17 +50,12 @@ ox3apiclient is currently unavailable at [PyPi](http://pypi.python.org/pypi) so
````
$ git clone https://github.com/openx/OX3-Python-API-Client.git
````
Install requests and requests_oauthlib from [PyPi](http://pypi.python.org/pypi) with [pip](http://www.pip-installer.org/en/latest/index.html)
````
$ pip install requests requests_oauthlib
````

Note that Python 2.4 and 2.5 support requires simplejson. You will need
simplejson 2.1.0 specifically for Python 2.4. You can install this version with:
Install the downloaded library:
````
$ pip install simplejson==2.1.0
python setup.py install
````

this will install the current dependencies.

## Authentication

Expand Down
101 changes: 36 additions & 65 deletions ox3apiclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,12 @@
import mimetypes
from pprint import pformat
import random

# json module is not supported in versions of Python < 2.6 so try to load the
# simplejson module instead. Note that as of simplejson v2.1.1, Python 2.4
# support was dropped. You will need to look for v2.1.0 specifically for
# Python 2.4 support.
import sys
major_py_version = sys.version_info[0]
minor_py_version = sys.version_info[1]
if major_py_version == 2 and minor_py_version < 6:
import simplejson as json
else:
import json
import json
from urlparse import parse_qs, urlparse

import requests
from requests_oauthlib import OAuth1

# parse_qs is in the urlparse module as of 2.6, but in cgi in earlier versions.
if major_py_version == 2 and minor_py_version > 5:
from urlparse import parse_qs
else:
from cgi import parse_qs

from urlparse import urlparse

__version__ = '0.5.0'

REQUEST_TOKEN_URL = 'https://sso.openx.com/api/index/initiate'
Expand Down Expand Up @@ -62,20 +44,19 @@ class Client(object):

"""


def __init__(self, domain, realm, consumer_key, consumer_secret,
callback_url='oob',
scheme='http',
request_token_url=REQUEST_TOKEN_URL,
access_token_url=ACCESS_TOKEN_URL,
authorization_url=AUTHORIZATION_URL,
api_path=API_PATH_V1,
email=None,
password=None,
http_proxy=None,
https_proxy=None,
headers=None,
timeout=None):
callback_url='oob',
scheme='http',
request_token_url=REQUEST_TOKEN_URL,
access_token_url=ACCESS_TOKEN_URL,
authorization_url=AUTHORIZATION_URL,
api_path=API_PATH_V1,
email=None,
password=None,
http_proxy=None,
https_proxy=None,
headers=None,
timeout=None):
"""

domain -- Your UI domain. The API is accessed off this domain.
Expand All @@ -97,7 +78,7 @@ def __init__(self, domain, realm, consumer_key, consumer_secret,
self.consumer_key = consumer_key
self.consumer_secret = consumer_secret
self.callback_url = callback_url
self.scheme=scheme
self.scheme = scheme
self.request_token_url = request_token_url
self.access_token_url = access_token_url
self.authorization_url = authorization_url
Expand Down Expand Up @@ -129,7 +110,6 @@ def __init__(self, domain, realm, consumer_key, consumer_secret,

self.logger = logging.getLogger(__name__)


def log_request(self, response):
self.logger.debug('====={0:=<45}'.format('OX3 api call started'))
self.logger.debug("%s %s" % (response.request.method, response.request.url))
Expand All @@ -144,11 +124,10 @@ def log_request(self, response):
self.logger.debug('====={0:=<45}'.format('OX3 api call response body'))
try:
self.logger.debug(pformat(json.loads(response.content)))
except:
except ValueError:
self.logger.debug("%s" % response.content)
self.logger.debug('====={0:=<45}'.format('OX3 api call finished'))


def request(self, url, method='GET', headers=None, data=None, sign=False,
send_json=False):
"""Helper method to make a (optionally OAuth signed) HTTP request."""
Expand Down Expand Up @@ -264,7 +243,6 @@ def validate_session(self):
rest={})
self._session.cookies.set_cookie(cookie)


# v2 doesn't need this extra step, just the cookie:
if self.api_path == API_PATH_V1:
response = self._session.put(url=self._resolve_url('/a/session/validate'), timeout=self.timeout)
Expand Down Expand Up @@ -321,24 +299,31 @@ def _resolve_url(self, url):

# If there is no scheme specified we create a fully qualified URL.
if not parse_res[0]:
url ='%s://%s%s%s' % (self.scheme, self.domain, self.api_path,
parse_res[2])
url = '%s://%s%s%s' % (self.scheme, self.domain, self.api_path,
parse_res[2])
if parse_res[4]:
url = url + '?' + parse_res[4]

return url

def _response_value(self, response):
""" Utility method. Returns decoded json. If the response content cannot be decoded, then
the content is returned.

"""
try:
return response.json()
except ValueError:
return response.content

def get(self, url):
"""Issue a GET request to the given URL or API shorthand

"""
response = self._session.get(self._resolve_url(url), timeout=self.timeout)
self.log_request(response)
response.raise_for_status()
try:
return response.json()
except:
return response.content
return self._response_value(response)

def options(self, url):
"""Send a request with HTTP method OPTIONS to the given
Expand All @@ -350,10 +335,7 @@ def options(self, url):
response = self._session.options(self._resolve_url(url), timeout=self.timeout)
self.log_request(response)
response.raise_for_status()
try:
return response.json()
except:
return response.content
return self._response_value(response)

def put(self, url, data=None):
"""Issue a PUT request to url (either a full URL or API
Expand All @@ -366,10 +348,7 @@ def put(self, url, data=None):
response = self._session.put(self._resolve_url(url), data=data, timeout=self.timeout)
self.log_request(response)
response.raise_for_status()
try:
return response.json()
except:
return response.content
return self._response_value(response)

def post(self, url, data=None):
"""Issue a POST request to url (either a full URL or API
Expand All @@ -382,10 +361,7 @@ def post(self, url, data=None):
response = self._session.post(self._resolve_url(url), data=data, timeout=self.timeout)
self.log_request(response)
response.raise_for_status()
try:
return response.json()
except:
return response.content
return self._response_value(response)

def delete(self, url):
"""Issue a DELETE request to the URL or API shorthand."""
Expand All @@ -395,10 +371,7 @@ def delete(self, url):
# Catch no content responses from some delete actions.
if response.status_code == 204:
return []
try:
return response.json()
except:
return response.content
return self._response_value(response)

def upload_creative(self, account_id, file_path):
"""Upload a media creative to the account with ID
Expand Down Expand Up @@ -441,10 +414,8 @@ def upload_creative(self, account_id, file_path):
response = self._session.get(url, headers=headers, data=body, timeout=self.timeout)
self.log_request(response)
response.raise_for_status()
try:
return response.json()
except:
return response.content
return self._response_value(response)


def client_from_file(file_path='.ox3rc', env=None):
"""Return an instance of ox3apiclient.Client with data from file_path.
Expand Down Expand Up @@ -513,4 +484,4 @@ def client_from_file(file_path='.ox3rc', env=None):

# The exposed API has moved to using Client instead of OX3APIClient, but create
# a temporary alias for backwards compatibility.
OX3APIClient = Client
OX3APIClient = Client
50 changes: 25 additions & 25 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from distutils.core import setup
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
from os.path import dirname, join
import re

file_path = join(dirname(__file__), 'ox3apiclient', '__init__.py')
version = re.search("__version__\s*=\s*['\"](.+)['\"]",
open(file_path, 'r').read()).groups()[0]
open(file_path, 'r').read()).groups()[0]

setup(name='ox3apiclient',
version=version,
author='Tony Edwards',
author_email='tnydwrds@gmail.com',
url='https://github.com/tnydwrds/OX3-Python-API-Client',
description='Client to connect to OpenX Enterprise API.',
long_description='Client to connect to OpenX Enterprise API.',
packages=['ox3apiclient'],
install_requires=['oauth2'],
classifiers=[
'Environment :: Console',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2.4',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules'])
version=version,
author='OpenX API Team',
author_email='api@openx.com',
url='https://github.com/openx/OX3-Python-API-Client',
description='Client to connect to OpenX Enterprise API.',
long_description='Client to connect to OpenX Enterprise API.',
packages=['ox3apiclient'],
install_requires=['requests_oauthlib'],
classifiers=[
'Environment :: Console',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules'])