From 95862bbf95715bbe4a79ee4005e7d86381d3113b Mon Sep 17 00:00:00 2001 From: Federico Delgado Date: Tue, 19 Jul 2016 15:13:57 -0700 Subject: [PATCH] API-3187 updates to API Python Client - Dropped support for Python 2.4 and 2.5. - Simplified code dealing with python versions. - General: - formatting - code duplication removal - Setup: - Removed oauth2 - No intervention from user is needed to install requests_oauthlib - Updated contact info. --- History.md | 1 + README.md | 15 ++---- ox3apiclient/__init__.py | 101 ++++++++++++++------------------------- setup.py | 50 +++++++++---------- 4 files changed, 67 insertions(+), 100 deletions(-) diff --git a/History.md b/History.md index 0c31452..06fa7d0 100644 --- a/History.md +++ b/History.md @@ -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 ================== diff --git a/README.md b/README.md index 094821f..7865bb6 100644 --- a/README.md +++ b/README.md @@ -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". @@ -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) @@ -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 diff --git a/ox3apiclient/__init__.py b/ox3apiclient/__init__.py index a2ffb10..6538241 100644 --- a/ox3apiclient/__init__.py +++ b/ox3apiclient/__init__.py @@ -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' @@ -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. @@ -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 @@ -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)) @@ -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.""" @@ -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) @@ -321,13 +299,23 @@ 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 @@ -335,10 +323,7 @@ def get(self, url): 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 @@ -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 @@ -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 @@ -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.""" @@ -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 @@ -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. @@ -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 \ No newline at end of file +OX3APIClient = Client diff --git a/setup.py b/setup.py index 4c95e82..e948d1a 100644 --- a/setup.py +++ b/setup.py @@ -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'])