Add API versioning support, including tests

This commit is contained in:
sneakypete81 2013-04-15 21:32:54 +01:00
parent 677a7cf3bd
commit afde3b2231
3 changed files with 81 additions and 10 deletions

View file

@ -4,14 +4,24 @@ import api_photo
import api_tag
import api_album
LATEST_API_VERSION = 2
class OpenPhoto(OpenPhotoHttp):
""" Client library for OpenPhoto """
"""
Python client library for the specified OpenPhoto host.
OAuth tokens (consumer*, token*) can optionally be specified.
All requests will include the api_version path, if specified.
This should be used to ensure that your application will continue to work
even if the OpenPhoto API is updated to a new revision.
"""
def __init__(self, host,
consumer_key='', consumer_secret='',
token='', token_secret=''):
token='', token_secret='',
api_version=None):
OpenPhotoHttp.__init__(self, host,
consumer_key, consumer_secret,
token, token_secret)
token, token_secret, api_version)
self.photos = api_photo.ApiPhotos(self)
self.photo = api_photo.ApiPhoto(self)

View file

@ -19,12 +19,13 @@ DUPLICATE_RESPONSE = {"code": 409,
class OpenPhotoHttp:
""" Base class to handle HTTP requests to an OpenPhoto server """
def __init__(self, host, consumer_key='', consumer_secret='',
token='', token_secret=''):
token='', token_secret='', api_version=None):
self._host = host
self._consumer_key = consumer_key
self._consumer_secret = consumer_secret
self._token = token
self._token_secret = token_secret
self._api_version = api_version
self._logger = logging.getLogger("openphoto")
@ -37,11 +38,18 @@ class OpenPhotoHttp:
"""
Performs an HTTP GET from the specified endpoint (API path),
passing parameters if given.
The api_version is prepended to the endpoint,
if it was specified when the OpenPhoto object was created.
Returns the decoded JSON dictionary, and raises exceptions if an
error code is received.
Returns the raw response if process_response=False
"""
params = self._process_params(params)
if not endpoint.startswith("/"):
endpoint = "/" + endpoint
if self._api_version is not None:
endpoint = "/v%d%s" % (self._api_version, endpoint)
url = urlparse.urlunparse(('http', self._host, endpoint, '',
urllib.urlencode(params), ''))
if self._consumer_key:
@ -72,11 +80,18 @@ class OpenPhotoHttp:
"""
Performs an HTTP POST to the specified endpoint (API path),
passing parameters if given.
The api_version is prepended to the endpoint,
if it was specified when the OpenPhoto object was created.
Returns the decoded JSON dictionary, and raises exceptions if an
error code is received.
Returns the raw response if process_response=False
"""
params = self._process_params(params)
if not endpoint.startswith("/"):
endpoint = "/" + endpoint
if self._api_version is not None:
endpoint = "/v%d%s" % (self._api_version, endpoint)
url = urlparse.urlunparse(('http', self._host, endpoint, '', '', ''))
if not self._consumer_key:

46
tests/test_framework.py Normal file
View file

@ -0,0 +1,46 @@
import unittest
import logging
import openphoto
import test_base
class TestFramework(test_base.TestBase):
def setUp(self):
"""Override the default setUp, since we don't need a populated database"""
logging.info("\nRunning %s..." % self.id())
def create_client_from_base(self, api_version):
return openphoto.OpenPhoto(self.client._host,
self.client._consumer_key,
self.client._consumer_secret,
self.client._token,
self.client._token_secret,
api_version=api_version)
def test_api_version_zero(self):
# API v0 has a special hello world message
client = self.create_client_from_base(api_version=0)
result = client.get("hello.json")
self.assertEqual(result['message'], "Hello, world! This is version zero of the API!")
self.assertEqual(result['result']['__route__'], "/v0/hello.json")
def test_specified_api_version(self):
# For all API versions >0, we get a generic hello world message
for api_version in range(1, openphoto.LATEST_API_VERSION + 1):
client = self.create_client_from_base(api_version=api_version)
result = client.get("hello.json")
self.assertEqual(result['message'], "Hello, world!")
self.assertEqual(result['result']['__route__'], "/v%d/hello.json" % api_version)
def test_unspecified_api_version(self):
# If the API version is unspecified, we get a generic hello world message
client = self.create_client_from_base(api_version=None)
result = client.get("hello.json")
self.assertEqual(result['message'], "Hello, world!")
self.assertEqual(result['result']['__route__'], "/hello.json")
def test_future_api_version(self):
# If the API version is unsupported, we should get an error
# (it's a ValueError, since the returned 404 HTML page is not valid JSON)
client = self.create_client_from_base(api_version=openphoto.LATEST_API_VERSION + 1)
with self.assertRaises(ValueError):
client.get("hello.json")