commit c608d6e929575f771ee4752ef47c2bb12bd5636d
Author: Stavros Sachtouris <saxtouri@admin.grnet.gr>
Date:   Tue Mar 12 18:35:29 2013 +0200

    Finetest Storage.get_acount_info

diff --git a/kamaki/clients/storage.py b/kamaki/clients/storage.py
deleted file mode 100644
index 341a5fe..0000000
--- a/kamaki/clients/storage.py
+++ /dev/null
@@ -1,329 +0,0 @@
-#a Copyright 2011 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from kamaki.clients import Client, ClientError
-from kamaki.clients.utils import filter_in, filter_out, path4url
-
-
-class StorageClient(Client):
-    """OpenStack Object Storage API 1.0 client"""
-
-    def __init__(self, base_url, token, account=None, container=None):
-        super(StorageClient, self).__init__(base_url, token)
-        self.account = account
-        self.container = container
-
-    def _assert_account(self):
-        if not self.account:
-            raise ClientError("No account provided")
-
-    def _assert_container(self):
-        self._assert_account()
-        if not self.container:
-            raise ClientError("No container provided")
-
-    def get_account_info(self):
-        """
-        :returns: (dict)
-        """
-        self._assert_account()
-        path = path4url(self.account)
-        r = self.head(path, success=(204, 401))
-        if r.status_code == 401:
-            raise ClientError("No authorization", status=401)
-        reply = r.headers
-        return reply
-
-    def replace_account_meta(self, metapairs):
-        """
-        :param metapais: (dict) key:val metadata pairs
-        """
-        self._assert_account()
-        path = path4url(self.account)
-        for key, val in metapairs.items():
-            self.set_header('X-Account-Meta-' + key, val)
-        r = self.post(path, success=202)
-        r.release()
-
-    def del_account_meta(self, metakey):
-        """
-        :param metakey: (str) metadatum key
-        """
-        headers = self.get_account_info()
-        self.headers = filter_out(
-            headers,
-            'X-Account-Meta-' + metakey,
-            exactMatch=True)
-        if len(self.headers) == len(headers):
-            raise ClientError('X-Account-Meta-%s not found' % metakey, 404)
-        path = path4url(self.account)
-        r = self.post(path, success=202)
-        r.release()
-
-    def create_container(self, container):
-        """
-        :param container: (str)
-
-        :raises ClientError: 202 Container already exists
-        """
-        self._assert_account()
-        path = path4url(self.account, container)
-        r = self.put(path, success=(201, 202))
-        r.release()
-        if r.status_code == 202:
-            raise ClientError("Container already exists", r.status_code)
-
-    def get_container_info(self, container):
-        """
-        :param container: (str)
-
-        :returns: (dict)
-
-        :raises ClientError: 404 Container does not exist
-        """
-        self._assert_account()
-        path = path4url(self.account, container)
-        r = self.head(path, success=(204, 404))
-        if r.status_code == 404:
-            raise ClientError("Container does not exist", r.status_code)
-        reply = r.headers
-        return reply
-
-    def delete_container(self, container):
-        """
-        :param container: (str)
-
-        :raises ClientError: 404 Container does not exist
-        :raises ClientError: 409 Container not empty
-        """
-        self._assert_account()
-        path = path4url(self.account, container)
-        r = self.delete(path, success=(204, 404, 409))
-        if r.status_code == 404:
-            raise ClientError("Container does not exist", r.status_code)
-        elif r.status_code == 409:
-            raise ClientError("Container is not empty", r.status_code)
-
-    def list_containers(self):
-        """
-        :returns: (dict)
-        """
-        self._assert_account()
-        self.set_param('format', 'json')
-        path = path4url(self.account)
-        r = self.get(path, success=(200, 204))
-        reply = r.json
-        return reply
-
-    def upload_object(self, obj, f, size=None):
-        """ A simple (naive) implementation.
-
-        :param obj: (str)
-
-        :param f: an open for reading file descriptor
-
-        :param size: (int) number of bytes to upload
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container, obj)
-        data = f.read(size) if size is not None else f.read()
-        r = self.put(path, data=data, success=201)
-        r.release()
-
-    def create_object(
-            self, obj,
-            content_type='application/octet-stream', content_length=0):
-        """
-        :param obj: (str) directory-object name
-        :param content_type: (str) explicitly set content_type
-        :param content_length: (int) explicitly set content length
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container, obj)
-        self.set_header('Content-Type', content_type)
-        self.set_header('Content-length', str(content_length))
-        r = self.put(path, success=201)
-        r.release()
-
-    def create_directory(self, obj):
-        """
-        :param obj: (str) directory-object name
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container, obj)
-        self.set_header('Content-Type', 'application/directory')
-        self.set_header('Content-length', '0')
-        r = self.put(path, success=201)
-        r.release()
-
-    def get_object_info(self, obj):
-        """
-        :param obj: (str)
-
-        :returns: (dict)
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container, obj)
-        r = self.head(path, success=200)
-        reply = r.headers
-        return reply
-
-    def get_object_meta(self, obj):
-        """
-        :param obj: (str)
-
-        :returns: (dict)
-        """
-        r = filter_in(self.get_object_info(obj), 'X-Object-Meta-')
-        reply = {}
-        for (key, val) in r.items():
-            metakey = key.split('-')[-1]
-            reply[metakey] = val
-        return reply
-
-    def del_object_meta(self, obj, metakey):
-        """
-        :param obj: (str)
-
-        :param metakey: (str) the metadatum key
-        """
-        self._assert_container()
-        self.set_header('X-Object-Meta-' + metakey, '')
-        path = path4url(self.account, self.container, obj)
-        r = self.post(path, success=202)
-        r.release()
-
-    def replace_object_meta(self, metapairs):
-        """
-        :param metapairs: (dict) key:val metadata
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container)
-        for key, val in metapairs.items():
-            self.set_header('X-Object-Meta-' + key, val)
-        r = self.post(path, success=202)
-        r.release()
-
-    def copy_object(
-            self, src_container, src_object, dst_container,
-            dst_object=False):
-        """Copy an objects from src_contaier:src_object to
-            dst_container[:dst_object]
-
-        :param src_container: (str)
-
-        :param src_object: (str)
-
-        :param dst_container: (str)
-
-        :param dst_object: (str)
-        """
-        self._assert_account()
-        dst_object = dst_object or src_object
-        dst_path = path4url(self.account, dst_container, dst_object)
-        self.set_header('X-Copy-From', path4url(src_container, src_object))
-        self.set_header('Content-Length', 0)
-        r = self.put(dst_path, success=201)
-        r.release()
-
-    def move_object(
-            self, src_container, src_object, dst_container,
-            dst_object=False):
-        """Move an objects from src_contaier:src_object to
-            dst_container[:dst_object]
-
-        :param src_container: (str)
-
-        :param src_object: (str)
-
-        :param dst_container: (str)
-
-        :param dst_object: (str)
-        """
-        self._assert_account()
-        dst_object = dst_object or src_object
-        dst_path = path4url(self.account, dst_container, dst_object)
-        self.set_header('X-Move-From', path4url(src_container, src_object))
-        self.set_header('Content-Length', 0)
-        r = self.put(dst_path, success=201)
-        r.release()
-
-    def delete_object(self, obj):
-        """
-        :param obj: (str)
-
-        :raises ClientError: 404 Object not found
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container, obj)
-        r = self.delete(path, success=(204, 404))
-        if r.status_code == 404:
-            raise ClientError("Object %s not found" % obj, r.status_code)
-
-    def list_objects(self):
-        """
-        :returns: (dict)
-
-        :raises ClientError: 404 Invalid account
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container)
-        self.set_param('format', 'json')
-        r = self.get(path, success=(200, 204, 304, 404), )
-        if r.status_code == 404:
-            raise ClientError(
-                "Invalid account (%s) for that container" % self.account,
-                r.status_code)
-        elif r.status_code == 304:
-            return []
-        return r.json
-
-    def list_objects_in_path(self, path_prefix):
-        """
-        :param path_prefix: (str)
-
-        :raises ClientError: 404 Invalid account
-
-        :returns: (dict)
-        """
-        self._assert_container()
-        path = path4url(self.account, self.container)
-        self.set_param('format', 'json')
-        self.set_param('path', path_prefix)
-        r = self.get(path, success=(200, 204, 404))
-        if r.status_code == 404:
-            raise ClientError(
-                "Invalid account (%s) for that container" % self.account,
-                r.status_code)
-        reply = r.json
-        return reply
diff --git a/kamaki/clients/test.py b/kamaki/clients/test.py
index d5ea71a..b19c486 100644
--- a/kamaki/clients/test.py
+++ b/kamaki/clients/test.py
@@ -38,6 +38,7 @@ from inspect import getmembers, isclass
 from kamaki.clients.astakos.test import Astakos
 from kamaki.clients.cyclades.test import Cyclades
 from kamaki.clients.image.test import Image
+from kamaki.clients.storage.test import Storage
 from kamaki.clients.pithos.test import Pithos
 
 
diff --git a/setup.py b/setup.py
index e099d59..c1b7ca8 100755
--- a/setup.py
+++ b/setup.py
@@ -65,6 +65,7 @@ setup(
         'kamaki.clients',
         'kamaki.clients.livetest',
         'kamaki.clients.image',
+        'kamaki.clients.storage',
         'kamaki.clients.pithos',
         'kamaki.clients.astakos',
         'kamaki.clients.cyclades',
