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
5 changes: 5 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.6.0 / 2017-06-19
==================
* Added: Python 3 compatibility
* Fixed: Non running tests

0.5.2 / 2017-02-02
==================
* Fixed: packaging for Pypi
Expand Down
19 changes: 18 additions & 1 deletion 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.6 - 2.7, with 3.x support coming in the future.
It currently supports Python 2.6 - 3.5.

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 @@ -121,3 +121,20 @@ ox = ox3apiclient.Client(

ox.logon(email, password)
````

# To run these tests. Install nose (pip install nose)
# and run nosetests -sxv tests/ from the root dir

## Tests

Install nose

````bash
pip install nose
````

and run the following command line from the root:

````bash
nosetests -sxv tests/
````
38 changes: 20 additions & 18 deletions ox3apiclient/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# -*- coding: utf-8 -*-

import ConfigParser
import cookielib
from six.moves import configparser as ConfigParser
from six.moves import http_cookiejar as cookielib
import logging
import mimetypes
from pprint import pformat
import random
import json
from urlparse import parse_qs, urlparse
from six.moves.urllib.parse import parse_qs, urlparse

import requests
from requests_oauthlib import OAuth1

__version__ = '0.5.2'
__version__ = '0.6.0'

REQUEST_TOKEN_URL = 'https://sso.openx.com/api/index/initiate'
ACCESS_TOKEN_URL = 'https://sso.openx.com/api/index/token'
Expand Down Expand Up @@ -123,9 +123,9 @@ def log_request(self, response):
self.logger.debug("%s: %s" % (k, v))
self.logger.debug('====={0:=<45}'.format('OX3 api call response body'))
try:
self.logger.debug(pformat(json.loads(response.content)))
self.logger.debug(pformat(json.loads(response.text)))
except ValueError:
self.logger.debug("%s" % response.content)
self.logger.debug("%s" % response.text)
self.logger.debug('====={0:=<45}'.format('OX3 api call finished'))

def request(self, url, method='GET', headers=None, data=None, sign=False,
Expand Down Expand Up @@ -164,8 +164,8 @@ def fetch_request_token(self):
response = self._session.post(url=self.request_token_url, auth=oauth, timeout=self.timeout)
self.log_request(response)
if response.status_code != 200:
raise OAuthException("OAuth token request failed (%s) %s" % (response.status_code, response.content))
credentials = parse_qs(response.content)
raise OAuthException("OAuth token request failed (%s) %s" % (response.status_code, response.text))
credentials = parse_qs(response.text)
self._token = {'key': credentials['oauth_token'][0],
'secret': credentials['oauth_token_secret'][0]}
return self._token
Expand All @@ -192,10 +192,10 @@ def authorize_token(self, email=None, password=None):
response = self._session.post(url=self.authorization_url, data=data, timeout=self.timeout)
self.log_request(response)
if response.status_code != 200:
raise OAuthException("OAuth login failed (%s) %s" % (response.status_code, response.content))
raise OAuthException("OAuth login failed (%s) %s" % (response.status_code, response.text))

# set token verifier
self._token['verifier'] = parse_qs(response.content)['oauth_verifier'][0]
self._token['verifier'] = parse_qs(response.text)['oauth_verifier'][0]

def fetch_access_token(self):
"""Helper method to fetch and set access token.
Expand All @@ -212,8 +212,8 @@ def fetch_access_token(self):
response = self._session.post(url=self.access_token_url, auth=oauth, timeout=self.timeout)
self.log_request(response)
if response.status_code != 200:
raise OAuthException("OAuth token verification failed (%s) %s" % (response.status_code, response.content))
self._token = parse_qs(response.content)['oauth_token'][0]
raise OAuthException("OAuth token verification failed (%s) %s" % (response.status_code, response.text))
self._token = parse_qs(response.text)['oauth_token'][0]
return self._token

def validate_session(self):
Expand Down Expand Up @@ -244,7 +244,7 @@ def validate_session(self):
if self.api_path == API_PATH_V1:
response = self._session.put(url=self._resolve_url('/a/session/validate'), timeout=self.timeout)
self.log_request(response)
return response.content
return response.text

def logon(self, email=None, password=None):
"""Returns self after authentication.
Expand Down Expand Up @@ -276,7 +276,7 @@ def logoff(self):

response = self._session.delete(url=self.access_token_url, auth=oauth, timeout=self.timeout)
if response.status_code != 204:
raise OAuthException("OAuth token deletion failed (%s) %s" % (response.status_code, response.content))
raise OAuthException("OAuth token deletion failed (%s) %s" % (response.status_code, response.text))
else:
raise UnknownAPIFormatError(
'Unrecognized API path: %s' % self.api_path)
Expand Down Expand Up @@ -305,13 +305,13 @@ def _resolve_url(self, url):

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

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

def get(self, url):
"""Issue a GET request to the given URL or API shorthand
Expand Down Expand Up @@ -377,7 +377,7 @@ def upload_creative(self, account_id, file_path):
"""
# Thanks to nosklo for his answer on SO:
# http://stackoverflow.com/a/681182
boundary = '-----------------------------' + str(int(random.random()*1e10))
boundary = '-----------------------------' + str(int(random.random() * 1e10))
parts = []

# Set account ID part.
Expand All @@ -392,7 +392,8 @@ def upload_creative(self, account_id, file_path):
parts.append('Content-Type: %s' % mimetypes.guess_type(file_path)[0] or 'application/octet-stream')
parts.append('')
# TODO: catch errors with opening file.
parts.append(open(file_path, 'r').read())
with open(file_path, 'r') as f:
parts.append(f.read())

parts.append('--' + boundary + '--')
parts.append('')
Expand Down Expand Up @@ -479,6 +480,7 @@ def client_from_file(file_path='.ox3rc', env=None):

return client


# The exposed API has moved to using Client instead of OX3APIClient, but create
# a temporary alias for backwards compatibility.
OX3APIClient = Client
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
'Programming Language :: Python',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Libraries',
Expand Down
4 changes: 0 additions & 4 deletions tests/__init__.py

This file was deleted.

205 changes: 0 additions & 205 deletions tests/client.py

This file was deleted.

Loading