Permalink
Browse files

Now supporting Python 2.4, 2.5, 2.6, and 2.7. Tox rocks!

Closes #5.
  • Loading branch information...
1 parent a185f95 commit b7eb66f90eb754d7886b432f58fe7313a630193a @jacobian jacobian committed Aug 16, 2010
@@ -1,8 +1,6 @@
-from __future__ import absolute_import
-
__version__ = '1.1'
-from .backup_schedules import (BackupSchedule, BackupScheduleManager,
+from cloudservers.backup_schedules import (BackupSchedule, BackupScheduleManager,
BACKUP_WEEKLY_DISABLED, BACKUP_WEEKLY_SUNDAY, BACKUP_WEEKLY_MONDAY,
BACKUP_WEEKLY_TUESDAY, BACKUP_WEEKLY_WEDNESDAY,
BACKUP_WEEKLY_THURSDAY, BACKUP_WEEKLY_FRIDAY, BACKUP_WEEKLY_SATURDAY,
@@ -13,13 +11,13 @@
BACKUP_DAILY_H_1400_1600, BACKUP_DAILY_H_1600_1800,
BACKUP_DAILY_H_1800_2000, BACKUP_DAILY_H_2000_2200,
BACKUP_DAILY_H_2200_0000)
-from .client import CloudServersClient
-from .exceptions import (CloudServersException, BadRequest, Unauthorized,
+from cloudservers.client import CloudServersClient
+from cloudservers.exceptions import (CloudServersException, BadRequest, Unauthorized,
Forbidden, NotFound, OverLimit)
-from .flavors import FlavorManager, Flavor
-from .images import ImageManager, Image
-from .ipgroups import IPGroupManager, IPGroup
-from .servers import ServerManager, Server, REBOOT_HARD, REBOOT_SOFT
+from cloudservers.flavors import FlavorManager, Flavor
+from cloudservers.images import ImageManager, Image
+from cloudservers.ipgroups import IPGroupManager, IPGroup
+from cloudservers.servers import ServerManager, Server, REBOOT_HARD, REBOOT_SOFT
class CloudServers(object):
"""
@@ -1,4 +1,4 @@
-from . import base
+from cloudservers import base
BACKUP_WEEKLY_DISABLED = 'DISABLED'
BACKUP_WEEKLY_SUNDAY = 'SUNDAY'
@@ -2,7 +2,14 @@
Base utilities to build API operation managers and objects on top of.
"""
-from .exceptions import NotFound
+from cloudservers.exceptions import NotFound
+
+# Python 2.4 compat
+try:
+ all
+except NameError:
+ def all(iterable):
+ return True not in (not x for x in iterable)
class Manager(object):
"""
@@ -13,7 +13,7 @@
urlparse.parse_qsl = cgi.parse_qsl
import cloudservers
-from . import exceptions
+from cloudservers import exceptions
class CloudServersClient(httplib2.Http):
@@ -39,7 +39,10 @@ def request(self, *args, **kwargs):
kwargs['body'] = json.dumps(kwargs['body'])
resp, body = super(CloudServersClient, self).request(*args, **kwargs)
- body = json.loads(body) if body else None
+ if body:
+ body = json.loads(body)
+ else:
+ body = None
if resp.status in (400, 401, 403, 404, 413, 500):
raise exceptions.from_response(resp, body)
@@ -45,7 +45,12 @@ class OverLimit(CloudServersException):
http_status = 413
message = "Over limit"
-_code_map = dict((c.http_status, c) for c in CloudServersException.__subclasses__())
+# In Python 2.4 Exception is old-style and thus doesn't have a __subclasses__()
+# so we can do this:
+# _code_map = dict((c.http_status, c) for c in CloudServersException.__subclasses__())
+#
+# Instead, we have to hardcode it:
+_code_map = dict((c.http_status, c) for c in [BadRequest, Unauthorized, Forbidden, NotFound, OverLimit])
def from_response(response, body):
"""
@@ -1,4 +1,4 @@
-from . import base
+from cloudservers import base
class Flavor(base.Resource):
"""
@@ -1,4 +1,4 @@
-from . import base
+from cloudservers import base
class Image(base.Resource):
"""
@@ -1,4 +1,4 @@
-from . import base
+from cloudservers import base
class IPGroup(base.Resource):
def __repr__(self):
@@ -1,4 +1,4 @@
-from . import base
+from cloudservers import base
REBOOT_SOFT, REBOOT_HARD = 'SOFT', 'HARD'
View
@@ -6,15 +6,13 @@
behavior differs from the spec.
"""
-from __future__ import absolute_import
-
import httplib2
import urlparse
import urllib
from nose.tools import assert_equal
from cloudservers import CloudServers
from cloudservers.client import CloudServersClient
-from .utils import fail, assert_in, assert_not_in, assert_has_keys
+from utils import fail, assert_in, assert_not_in, assert_has_keys
class FakeServer(CloudServers):
def __init__(self, username=None, password=None):
View
@@ -1,4 +1,3 @@
-from __future__ import with_statement
import mock
import cloudservers
import httplib2
@@ -12,7 +11,9 @@ def test_authenticate_success():
'x-auth-token': '1b751d74-de0c-46ae-84f0-915744b582d1',
})
mock_request = mock.Mock(return_value=(auth_response, None))
- with mock.patch.object(httplib2.Http, "request", mock_request):
+
+ @mock.patch.object(httplib2.Http, "request", mock_request)
+ def test_auth_call():
cs.client.authenticate()
mock_request.assert_called_with(cs.client.AUTH_URL, 'GET',
headers = {
@@ -23,25 +24,39 @@ def test_authenticate_success():
assert_equal(cs.client.management_url, auth_response['x-server-management-url'])
assert_equal(cs.client.auth_token, auth_response['x-auth-token'])
+ test_auth_call()
+
def test_authenticate_failure():
cs = cloudservers.CloudServers("username", "apikey")
auth_response = httplib2.Response({'status': 401})
mock_request = mock.Mock(return_value=(auth_response, None))
- with mock.patch.object(httplib2.Http, "request", mock_request):
+
+ @mock.patch.object(httplib2.Http, "request", mock_request)
+ def test_auth_call():
assert_raises(cloudservers.Unauthorized, cs.client.authenticate)
+ test_auth_call()
+
def test_auth_automatic():
client = cloudservers.CloudServers("username", "apikey").client
client.management_url = ''
mock_request = mock.Mock(return_value=(None, None))
- with mock.patch.object(client, 'request', mock_request):
- with mock.patch.object(client, 'authenticate') as mock_authenticate:
- client.get('/')
- mock_authenticate.assert_called()
- mock_request.assert_called()
-
+
+ @mock.patch.object(client, 'request', mock_request)
+ @mock.patch.object(client, 'authenticate')
+ def test_auth_call(m):
+ client.get('/')
+ m.assert_called()
+ mock_request.assert_called()
+
+ test_auth_call()
+
def test_auth_manual():
cs = cloudservers.CloudServers("username", "password")
- with mock.patch.object(cs.client, 'authenticate') as mocked:
+
+ @mock.patch.object(cs.client, 'authenticate')
+ def test_auth_call(m):
cs.authenticate()
- mocked.assert_called()
+ m.assert_called()
+
+ test_auth_call()
@@ -1,8 +1,7 @@
-from __future__ import absolute_import
from cloudservers.backup_schedules import *
-from .fakeserver import FakeServer
-from .utils import assert_isinstance
+from fakeserver import FakeServer
+from utils import assert_isinstance
cs = FakeServer()
View
@@ -1,12 +1,11 @@
-from __future__ import absolute_import, with_statement
import mock
import cloudservers.base
-from .fakeserver import FakeServer
from cloudservers import Flavor
from cloudservers.exceptions import NotFound
from cloudservers.base import Resource
from nose.tools import assert_equal, assert_not_equal, assert_raises
+from fakeserver import FakeServer
cs = FakeServer()
View
@@ -1,4 +1,3 @@
-from __future__ import with_statement
import mock
import httplib2
from cloudservers.client import CloudServersClient
@@ -16,17 +15,23 @@ def client():
def test_get():
cl = client()
- with mock.patch.object(httplib2.Http, "request", mock_request):
- with mock.patch('time.time', mock.Mock(return_value=1234)):
- resp, body = cl.get("/hi")
- mock_request.assert_called_with("http://example.com/hi?fresh=1234", "GET",
- headers={"X-Auth-Token": "token", "User-Agent": cl.USER_AGENT})
- # Automatic JSON parsing
- assert_equal(body, {"hi":"there"})
+
+ @mock.patch.object(httplib2.Http, "request", mock_request)
+ @mock.patch('time.time', mock.Mock(return_value=1234))
+ def test_get_call():
+ resp, body = cl.get("/hi")
+ mock_request.assert_called_with("http://example.com/hi?fresh=1234", "GET",
+ headers={"X-Auth-Token": "token", "User-Agent": cl.USER_AGENT})
+ # Automatic JSON parsing
+ assert_equal(body, {"hi":"there"})
+
+ test_get_call()
def test_post():
cl = client()
- with mock.patch.object(httplib2.Http, "request", mock_request):
+
+ @mock.patch.object(httplib2.Http, "request", mock_request)
+ def test_post_call():
cl.post("/hi", body=[1, 2, 3])
mock_request.assert_called_with("http://example.com/hi", "POST",
headers = {
@@ -35,3 +40,5 @@ def test_post():
"User-Agent": cl.USER_AGENT},
body = '[1, 2, 3]'
)
+
+ test_post_call()
@@ -1,8 +1,6 @@
-from __future__ import absolute_import
-
from cloudservers import Flavor, NotFound
-from .fakeserver import FakeServer
-from .utils import assert_isinstance
+from fakeserver import FakeServer
+from utils import assert_isinstance
from nose.tools import assert_raises, assert_equal
cs = FakeServer()
@@ -1,8 +1,6 @@
-from __future__ import absolute_import
-
from cloudservers import Image
-from .fakeserver import FakeServer
-from .utils import assert_isinstance
+from fakeserver import FakeServer
+from utils import assert_isinstance
from nose.tools import assert_equal
cs = FakeServer()
@@ -1,8 +1,6 @@
-from __future__ import absolute_import
-
from cloudservers import IPGroup
-from .fakeserver import FakeServer
-from .utils import assert_isinstance
+from fakeserver import FakeServer
+from utils import assert_isinstance
from nose.tools import assert_equal
cs = FakeServer()
@@ -1,9 +1,7 @@
-from __future__ import absolute_import
-
import StringIO
from nose.tools import assert_equal
-from .fakeserver import FakeServer
-from .utils import assert_isinstance
+from fakeserver import FakeServer
+from utils import assert_isinstance
from cloudservers import Server
cs = FakeServer()
View
@@ -1,13 +1,9 @@
-from __future__ import with_statement
-from __future__ import absolute_import
-
import os
import mock
import httplib2
-from contextlib import nested
from nose.tools import assert_raises, assert_equal
from cloudservers.shell import CloudserversShell, CommandError
-from .fakeserver import FakeServer
+from fakeserver import FakeServer
# Patch os.environ to avoid required auth info.
def setup():
@@ -99,8 +95,9 @@ def test_boot_key_auto():
mock_open.return_value = mock.Mock()
mock_open.return_value.read = mock.Mock(return_value='SSHKEY')
- with nested(mock.patch('os.path.exists', mock_exists),
- mock.patch('__builtin__.open', mock_open)):
+ @mock.patch('os.path.exists', mock_exists)
+ @mock.patch('__builtin__.open', mock_open)
+ def test_shell_call():
shell('boot some-server --image 1 --key')
assert_called(
'POST', '/servers',
@@ -111,11 +108,17 @@ def test_boot_key_auto():
]}
}
)
+
+ test_shell_call()
def test_boot_key_auto_no_keys():
mock_exists = mock.Mock(return_value=False)
- with mock.patch('os.path.exists', mock_exists):
+
+ @mock.patch('os.path.exists', mock_exists)
+ def test_shell_call():
assert_raises(CommandError, shell, 'boot some-server --image 1 --key')
+
+ test_shell_call()
def test_boot_key_file():
testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
@@ -239,12 +242,19 @@ def test_delete():
assert_called('DELETE', '/servers/1234')
def test_help():
- with mock.patch.object(_shell.parser, 'print_help') as m:
+ @mock.patch.object(_shell.parser, 'print_help')
+ def test_help(m):
shell('help')
m.assert_called()
- with mock.patch.object(_shell.subcommands['delete'], 'print_help') as m:
+
+ @mock.patch.object(_shell.subcommands['delete'], 'print_help')
+ def test_help_delete(m):
shell('help delete')
m.assert_called()
+
+ test_help()
+ test_help_delete()
+
assert_raises(CommandError, shell, 'help foofoo')
def test_debug():

0 comments on commit b7eb66f

Please sign in to comment.