Get rid of pithos_sh
authorStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 19 Sep 2012 11:06:12 +0000 (14:06 +0300)
committerStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 19 Sep 2012 11:06:12 +0000 (14:06 +0300)
The old profecy "there will be only one [Pithos Client]" is finally
fullfilled

kamaki/cli/commands/pithos_cli.py
kamaki/cli/commands/pithos_sh_cli.py [deleted file]
kamaki/clients/pithos.py
kamaki/clients/pithos_sh_lib/__init__.py [deleted file]
kamaki/clients/pithos_sh_lib/client.py [deleted file]
kamaki/clients/pithos_sh_lib/hashmap.py [deleted file]
kamaki/clients/pithos_sh_lib/sh.py [deleted file]
kamaki/clients/pithos_sh_lib/transfer.py [deleted file]
kamaki/clients/pithos_sh_lib/util.py [deleted file]

index f6d4c52..0a94ab4 100644 (file)
@@ -39,6 +39,7 @@ from kamaki.clients.pithos import PithosClient, ClientError
 from colors import bold
 from sys import stdout, exit
 import signal
+from time import localtime, strftime
 
 from progress.bar import IncrementalBar
 
@@ -1034,3 +1035,20 @@ class store_sharers(_store_account_command):
                 print_dict(acc, exclude='name', ident=18)
         if not getattr(self.args, 'detail'):
             print
+
+@command()
+class store_versions(_store_container_command):
+    """Get the version list of an object"""
+
+    def main(self, container___path):
+        super(store_versions, self).main(container___path)
+        try:
+            versions = self.client.get_object_versionlist(self.path)
+        except ClientError as err:
+            raise CLIError(err)
+
+        print('%s:%s versions'%(self.container,self.path))
+        for vitem in versions:
+            t = localtime(float(vitem[1]))
+            vid = bold(unicode(vitem[0]))
+            print('\t%s \t(%s)'%(vid, strftime('%d-%m-%Y %H:%M:%S', t)))
\ No newline at end of file
diff --git a/kamaki/cli/commands/pithos_sh_cli.py b/kamaki/cli/commands/pithos_sh_cli.py
deleted file mode 100644 (file)
index 7862e2a..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2011-2012 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.cli import command, CLIError
-from kamaki.cli.utils import print_list, dict2file, list2file
-from .pithos_cli import _store_container_command, _store_account_command
-from colors import bold
-
-from sys import stdout#argv, exit, stdin, stdout
-
-from kamaki.clients.pithos_sh_lib.client import Pithos_Client, Fault
-from kamaki.clients.pithos_sh_lib.transfer import download, cat#,upload
-
-class _pithos_sh_account_command(_store_account_command):
-
-    def update_parser(self, parser):
-        super(_pithos_sh_account_command, self).update_parser(parser)
-
-    def main(self):
-        super(_pithos_sh_account_command, self).main()
-        self.client = Pithos_Client(self.base_url, self.token, self.account)
-
-class _pithos_sh_container_command(_store_container_command):
-
-    def update_parser(self, parser):
-        super(_pithos_sh_container_command, self).update_parser(parser)
-
-    def main(self, container_with_path, path_is_optional=True):
-        super(_pithos_sh_container_command, self).main(container_with_path, path_is_optional)
-        self.client = Pithos_Client(self.base_url, self.token, self.account)
-
-def _build_args(arglist, attrs):
-    args = {}
-    for a in [a for a in attrs if getattr(arglist, a)]:
-        args[a] = getattr(arglist, a)
-    return args
-
-@command()
-class store_versions(_pithos_sh_container_command):
-    """Get the version list of an object"""
-
-    def main(self, container___path):
-        super(store_versions, self).main(container___path)
-        try:
-            data = self.client.retrieve_object_versionlist(self.container, self.path)
-        except Fault as err:
-            raise CLIError(message=unicode(err), status=err.status)
-        from time import localtime, strftime
-        print('%s:%s version ids:'%(self.container,self.path))
-        for vitem in data['versions']:
-            t = localtime(float(vitem[1]))
-            vid = bold(unicode(vitem[0]))
-            print('\t%s \t(%s)'%(vid, strftime('%d-%m-%Y %H:%M:%S', t)))
-
-"""
-@command()
-class store_sharers(_pithos_sh_account_command):
-    ""list accounts who share objects with current account""
-    
-    def update_parser(self, parser):
-        super(store_sharers, self).update_parser(parser)
-        parser.add_argument('-l', action='store_true', dest='detail', default=False,
-            help='show detailed output')
-        parser.add_argument('-n', action='store',  dest='limit', default=10000,
-            help='show limited output')
-        parser.add_argument('--marker', action='store', dest='marker', default=None,
-            help='show output greater then marker')
-        
-    def main(self):
-        super(store_sharers, self).main()
-        attrs = ['limit', 'marker']
-        args = _build_args(self.args, attrs)
-        args['format'] = 'json' if getattr(self.args, 'detail') else 'text'
-    
-        try:    
-            print_list(self.client.list_shared_by_others(**args))
-        except Fault as err:
-            raise CLIError(message=unicode(err), status=err.status, importance=err.status/100)
-"""
\ No newline at end of file
index 988f038..44f8d45 100644 (file)
@@ -571,4 +571,9 @@ class PithosClient(PithosRestAPI):
         path = ''
         success = kwargs.pop('success', (200, 204))
         r = self.get(path, *args, success = success, **kwargs)
-        return r.json
\ No newline at end of file
+        return r.json
+
+    def get_object_versionlist(self, path):
+        self.assert_container()
+        r = self.object_get(path, format='json', version='list')
+        return r.json['versions']
diff --git a/kamaki/clients/pithos_sh_lib/__init__.py b/kamaki/clients/pithos_sh_lib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/kamaki/clients/pithos_sh_lib/client.py b/kamaki/clients/pithos_sh_lib/client.py
deleted file mode 100644 (file)
index efe40a6..0000000
+++ /dev/null
@@ -1,1003 +0,0 @@
-# Copyright 2011-2012 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 httplib import HTTPConnection, HTTPSConnection, HTTP
-from sys import stdin
-from xml.dom import minidom
-from StringIO import StringIO
-from urllib import quote, unquote
-from urlparse import urlparse
-
-import json
-import types
-import socket
-import urllib
-import datetime
-
-ERROR_CODES = {304:'Not Modified',
-               400:'Bad Request',
-               401:'Unauthorized',
-               403:'Forbidden',
-               404:'Not Found',
-               409:'Conflict',
-               411:'Length Required',
-               412:'Precondition Failed',
-               413:'Request Entity Too Large',
-               416:'Range Not Satisfiable',
-               422:'Unprocessable Entity',
-               500:'Internal Server Error',
-               501:'Not Implemented'}
-
-class Fault(Exception):
-    def __init__(self, data='', status=None):
-        if data == '' and status in ERROR_CODES.keys():
-            data = ERROR_CODES[status]
-        Exception.__init__(self, data)
-        self.data = data
-        self.status = status
-
-class Client(object):
-    def __init__(self, url, token, account, verbose=False, debug=False):
-        """`url` can also include a port, e.g '127.0.0.1:8000'."""
-        
-        self.url = url
-        self.account = account
-        self.verbose = verbose or debug
-        self.debug = debug
-        self.token = token
-    
-    def _req(self, method, path, body=None, headers={}, format='text', params={}):
-        p = urlparse(self.url)
-        if p.scheme == 'http':
-            conn = HTTPConnection(p.netloc)
-        elif p.scheme == 'https':
-            conn = HTTPSConnection(p.netloc)
-        else:
-            raise Exception('Unknown URL scheme')
-        
-        full_path = _prepare_path(p.path + path, format, params)
-        
-        kwargs = {}
-        kwargs['headers'] = _prepare_headers(headers)
-        kwargs['headers']['X-Auth-Token'] = self.token
-        if body:
-            kwargs['body'] = body
-            kwargs['headers'].setdefault('content-type', 'application/octet-stream')
-        kwargs['headers'].setdefault('content-length', len(body) if body else 0)
-        
-        #print '#', method, full_path, kwargs
-        #t1 = datetime.datetime.utcnow()
-        conn.request(method, full_path, **kwargs)
-        
-        resp = conn.getresponse()
-        #t2 = datetime.datetime.utcnow()
-        #print 'response time:', str(t2-t1)
-        return _handle_response(resp, self.verbose, self.debug)
-    
-    def _chunked_transfer(self, path, method='PUT', f=stdin, headers=None,
-                          blocksize=1024, params={}):
-        """perfomrs a chunked request"""
-        p = urlparse(self.url)
-        if p.scheme == 'http':
-            conn = HTTPConnection(p.netloc)
-        elif p.scheme == 'https':
-            conn = HTTPSConnection(p.netloc)
-        else:
-            raise Exception('Unknown URL scheme')
-        
-        full_path = _prepare_path(p.path + path, params=params)
-        
-        headers.setdefault('content-type', 'application/octet-stream')
-        
-        conn.putrequest(method, full_path)
-        conn.putheader('x-auth-token', self.token)
-        conn.putheader('transfer-encoding', 'chunked')
-        for k,v in _prepare_headers(headers).items():
-            conn.putheader(k, v)
-        conn.endheaders()
-        
-        # write body
-        data = ''
-        while True:
-            if f.closed:
-                break
-            block = f.read(blocksize)
-            if block == '':
-                break
-            data = '%x\r\n%s\r\n' % (len(block), block)
-            try:
-                conn.send(data)
-            except:
-                #retry
-                conn.send(data)
-        data = '0\r\n\r\n'
-        try:
-            conn.send(data)
-        except:
-            #retry
-            conn.send(data)
-        
-        resp = conn.getresponse()
-        return _handle_response(resp, self.verbose, self.debug)
-    
-    def delete(self, path, format='text', params={}):
-        return self._req('DELETE', path, format=format, params=params)
-    
-    def get(self, path, format='text', headers={}, params={}):
-        return self._req('GET', path, headers=headers, format=format,
-                        params=params)
-    
-    def head(self, path, format='text', params={}):
-         return self._req('HEAD', path, format=format, params=params)
-    
-    def post(self, path, body=None, format='text', headers=None, params={}):
-        return self._req('POST', path, body, headers=headers, format=format,
-                        params=params)
-    
-    def put(self, path, body=None, format='text', headers=None, params={}):
-        return self._req('PUT', path, body, headers=headers, format=format,
-                         params=params)
-    
-    def _list(self, path, format='text', params={}, **headers):
-        status, headers, data = self.get(path, format=format, headers=headers,
-                                         params=params)
-        if format == 'json':
-            data = json.loads(data) if data else ''
-        elif format == 'xml':
-            data = minidom.parseString(data)
-        else:
-            data = data.split('\n')[:-1] if data else ''
-        return data
-    
-    def _get_metadata(self, path, prefix=None, params={}):
-        status, headers, data = self.head(path, params=params)
-        prefixlen = len(prefix) if prefix else 0
-        meta = {}
-        for key, val in headers.items():
-            if prefix and not key.startswith(prefix):
-                continue
-            elif prefix and key.startswith(prefix):
-                key = key[prefixlen:]
-            meta[key] = val
-        return meta
-    
-    def _filter(self, l, d):
-        """
-        filter out from l elements having the metadata values provided
-        """
-        ll = l
-        for elem in l:
-            if type(elem) == types.DictionaryType:
-                for key in d.keys():
-                    k = 'x_object_meta_%s' % key
-                    if k in elem.keys() and elem[k] == d[key]:
-                        ll.remove(elem)
-                        break
-        return ll
-    
-class OOS_Client(Client):
-    """Openstack Object Storage Client"""
-    
-    def _update_metadata(self, path, entity, **meta):
-        """adds new and updates the values of previously set metadata"""
-        ex_meta = self.retrieve_account_metadata(restricted=True)
-        ex_meta.update(meta)
-        headers = {}
-        prefix = 'x-%s-meta-' % entity
-        for k,v in ex_meta.items():
-            k = '%s%s' % (prefix, k)
-            headers[k] = v
-        return self.post(path, headers=headers)
-    
-    def _reset_metadata(self, path, entity, **meta):
-        """
-        overwrites all user defined metadata
-        """
-        headers = {}
-        prefix = 'x-%s-meta-' % entity
-        for k,v in meta.items():
-            k = '%s%s' % (prefix, k)
-            headers[k] = v
-        return self.post(path, headers=headers)
-    
-    def _delete_metadata(self, path, entity, meta=[]):
-        """delete previously set metadata"""
-        ex_meta = self.retrieve_account_metadata(restricted=True)
-        headers = {}
-        prefix = 'x-%s-meta-' % entity
-        for k in ex_meta.keys():
-            if k in meta:
-                headers['%s%s' % (prefix, k)] = ex_meta[k]
-        return self.post(path, headers=headers)
-    
-    # Storage Account Services
-    
-    def list_containers(self, format='text', limit=None,
-                        marker=None, params={}, account=None, **headers):
-        """lists containers"""
-        account = account or self.account
-        path = '/%s' % account
-        params.update({'limit':limit, 'marker':marker})
-        return self._list(path, format, params, **headers)
-    
-    def retrieve_account_metadata(self, restricted=False, account=None, **params):
-        """returns the account metadata"""
-        account = account or self.account
-        path = '/%s' % account
-        prefix = 'x-account-meta-' if restricted else None
-        return self._get_metadata(path, prefix, params)
-    
-    def update_account_metadata(self, account=None, **meta):
-        """updates the account metadata"""
-        account = account or self.account
-        path = '/%s' % account
-        return self._update_metadata(path, 'account', **meta)
-        
-    def delete_account_metadata(self, meta=[], account=None):
-        """deletes the account metadata"""
-        account = account or self.account
-        path = '/%s' % account
-        return self._delete_metadata(path, 'account', meta)
-    
-    def reset_account_metadata(self, account=None, **meta):
-        """resets account metadata"""
-        account = account or self.account
-        path = '/%s' % account
-        return self._reset_metadata(path, 'account', **meta)
-    
-    # Storage Container Services
-    
-    def _filter_trashed(self, l):
-        return self._filter(l, {'trash':'true'})
-    
-    def list_objects(self, container, format='text',
-                     limit=None, marker=None, prefix=None, delimiter=None,
-                     path=None, include_trashed=False, params={}, account=None,
-                     **headers):
-        """returns a list with the container objects"""
-        account = account or self.account
-        params.update({'limit':limit, 'marker':marker, 'prefix':prefix,
-                       'delimiter':delimiter, 'path':path})
-        l = self._list('/%s/%s' % (account, container), format, params,
-                       **headers)
-        #TODO support filter trashed with xml also
-        if format != 'xml' and not include_trashed:
-            l = self._filter_trashed(l)
-        return l
-    
-    def create_container(self, container, account=None, meta={}, **headers):
-        """creates a container"""
-        account = account or self.account
-        if not headers:
-            headers = {}
-        for k,v in meta.items():
-            headers['x-container-meta-%s' %k.strip().upper()] = v.strip()
-        status, header, data = self.put('/%s/%s' % (account, container),
-                                        headers=headers)
-        if status == 202:
-            return False
-        elif status != 201:
-            raise Fault(data, int(status))
-        return True
-    
-    def delete_container(self, container, params={}, account=None):
-        """deletes a container"""
-        account = account or self.account
-        return self.delete('/%s/%s' % (account, container), params=params)
-    
-    def retrieve_container_metadata(self, container, restricted=False,
-                                    account=None, **params):
-        """returns the container metadata"""
-        account = account or self.account
-        prefix = 'x-container-meta-' if restricted else None
-        return self._get_metadata('/%s/%s' % (account, container), prefix,
-                                  params)
-    
-    def update_container_metadata(self, container, account=None, **meta):
-        """unpdates the container metadata"""
-        account = account or self.account
-        return self._update_metadata('/%s/%s' % (account, container),
-                                     'container', **meta)
-        
-    def delete_container_metadata(self, container, meta=[], account=None):
-        """deletes the container metadata"""
-        account = account or self.account
-        path = '/%s/%s' % (account, container)
-        return self._delete_metadata(path, 'container', meta)
-    
-    # Storage Object Services
-    
-    def request_object(self, container, object, format='text', params={},
-                       account=None, **headers):
-        """returns tuple containing the status, headers and data response for an object request"""
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        status, headers, data = self.get(path, format, headers, params)
-        return status, headers, data
-    
-    def retrieve_object(self, container, object, format='text', params={},
-                        account=None, **headers):
-        """returns an object's data"""
-        account = account or self.account
-        t = self.request_object(container, object, format, params, account,
-                                **headers)
-        data = t[2]
-        if format == 'json':
-            data = json.loads(data) if data else ''
-        elif format == 'xml':
-            data = minidom.parseString(data)
-        return data
-    
-    def retrieve_object_hashmap(self, container, object, format='json', params={},
-                        account=None, **headers):
-        """returns the hashmap representing object's data"""
-        if not params:
-            params = {}
-        params.update({'hashmap':None})
-        return self.retrieve_object(container, object, params, format, account, **headers)
-    
-    def create_directory_marker(self, container, object, account=None):
-        """creates a dierectory marker"""
-        account = account or self.account
-        if not object:
-            raise Fault('Directory markers have to be nested in a container')
-        h = {'content_type':'application/directory'}
-        return self.create_zero_length_object(container, object, account=account,
-                                              **h)
-    
-    def create_object(self, container, object, f=stdin, format='text', meta={},
-                      params={}, etag=None, content_type=None, content_encoding=None,
-                      content_disposition=None, account=None, **headers):
-        """creates a zero-length object"""
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        for k, v  in headers.items():
-            if v == None:
-                headers.pop(k)
-        
-        l = ['etag', 'content_encoding', 'content_disposition', 'content_type']
-        l = [elem for elem in l if eval(elem)]
-        for elem in l:
-            headers.update({elem:eval(elem)})
-        headers.setdefault('content-type', 'application/octet-stream')
-        
-        for k,v in meta.items():
-            headers['x-object-meta-%s' %k.strip()] = v.strip()
-        data = f.read() if f else None
-        return self.put(path, data, format, headers=headers, params=params)
-    
-    def create_zero_length_object(self, container, object, meta={}, etag=None,
-                                  content_type=None, content_encoding=None,
-                                  content_disposition=None, account=None,
-                                  **headers):
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'headers', 'account']:
-            args.pop(elem)
-        args.update(headers)
-        return self.create_object(container, account=account, f=None, **args)
-    
-    def update_object(self, container, object, f=stdin,
-                      offset=None, meta={}, params={}, content_length=None,
-                      content_type=None, content_encoding=None,
-                      content_disposition=None,  account=None, **headers):
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        for k, v  in headers.items():
-            if v == None:
-                headers.pop(k)
-        
-        l = ['content_encoding', 'content_disposition', 'content_type',
-             'content_length']
-        l = [elem for elem in l if eval(elem)]
-        for elem in l:
-            headers.update({elem:eval(elem)})
-        
-        if 'content_range' not in headers.keys():
-            if offset != None:
-                headers['content_range'] = 'bytes %s-/*' % offset
-            else:
-                headers['content_range'] = 'bytes */*'
-            
-        for k,v in meta.items():
-            headers['x-object-meta-%s' %k.strip()] = v.strip()
-        data = f.read() if f else None
-        return self.post(path, data, headers=headers, params=params)
-    
-    def update_object_using_chunks(self, container, object, f=stdin,
-                                   blocksize=1024, offset=None, meta={},
-                                   params={}, content_type=None, content_encoding=None,
-                                   content_disposition=None, account=None, **headers):
-        """updates an object (incremental upload)"""
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        headers = headers if not headers else {}
-        l = ['content_type', 'content_encoding', 'content_disposition']
-        l = [elem for elem in l if eval(elem)]
-        for elem in l:
-            headers.update({elem:eval(elem)})
-        
-        if offset != None:
-            headers['content_range'] = 'bytes %s-/*' % offset
-        else:
-            headers['content_range'] = 'bytes */*'
-        
-        for k,v in meta.items():
-            v = v.strip()
-            headers['x-object-meta-%s' %k.strip()] = v
-        return self._chunked_transfer(path, 'POST', f, headers=headers,
-                                      blocksize=blocksize, params=params)
-    
-    def _change_obj_location(self, src_container, src_object, dst_container,
-                             dst_object, remove=False, meta={}, account=None,
-                             content_type=None, delimiter=None, **headers):
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, dst_container, dst_object)
-        headers = {} if not headers else headers
-        params = {}
-        for k, v in meta.items():
-            headers['x-object-meta-%s' % k] = v
-        if remove:
-            headers['x-move-from'] = '/%s/%s' % (src_container, src_object)
-        else:
-            headers['x-copy-from'] = '/%s/%s' % (src_container, src_object)
-        headers['content_length'] = 0
-        if content_type:
-            headers['content_type'] = content_type
-        else:
-            params['ignore_content_type'] = ''
-        if delimiter:
-               params['delimiter'] = delimiter
-        return self.put(path, headers=headers, params=params)
-    
-    def copy_object(self, src_container, src_object, dst_container, dst_object,
-                   meta={}, account=None, content_type=None, delimiter=None, **headers):
-        """copies an object"""
-        account = account or self.account
-        return self._change_obj_location(src_container, src_object,
-                                   dst_container, dst_object, account=account,
-                                   remove=False, meta=meta,
-                                   content_type=content_type, delimiter=delimiter, **headers)
-    
-    def move_object(self, src_container, src_object, dst_container,
-                             dst_object, meta={}, account=None,
-                             content_type=None, **headers):
-        """moves an object"""
-        account = account or self.account
-        return self._change_obj_location(src_container, src_object,
-                                         dst_container, dst_object,
-                                         account=account, remove=True,
-                                         meta=meta, content_type=content_type,
-                                         **headers)
-    
-    def delete_object(self, container, object, params={}, account=None):
-        """deletes an object"""
-        account = account or self.account
-        return self.delete('/%s/%s/%s' % (account, container, object),
-                           params=params)
-    
-    def retrieve_object_metadata(self, container, object, restricted=False,
-                                 version=None, account=None):
-        """
-        set restricted to True to get only user defined metadata
-        """
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        prefix = 'x-object-meta-' if restricted else None
-        params = {'version':version} if version else {}
-        return self._get_metadata(path, prefix, params=params)
-    
-    def update_object_metadata(self, container, object, account=None,
-                               **meta):
-        """
-        updates object's metadata
-        """
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        return self._update_metadata(path, 'object', **meta)
-    
-    def delete_object_metadata(self, container, object, meta=[], account=None):
-        """
-        deletes object's metadata
-        """
-        account = account or self.account
-        path = '/%s/%s' % (account, container, object)
-        return self._delete_metadata(path, 'object', meta)
-    
-class Pithos_Client(OOS_Client):
-    """Pithos Storage Client. Extends OOS_Client"""
-    
-    def _update_metadata(self, path, entity, **meta):
-        """
-        adds new and updates the values of previously set metadata
-        """
-        params = {'update':None}
-        headers = {}
-        prefix = 'x-%s-meta-' % entity
-        for k,v in meta.items():
-            k = '%s%s' % (prefix, k)
-            headers[k] = v
-        return self.post(path, headers=headers, params=params)
-    
-    def _delete_metadata(self, path, entity, meta=[]):
-        """
-        delete previously set metadata
-        """
-        params = {'update':None}
-        headers = {}
-        prefix = 'x-%s-meta-' % entity
-        for m in meta:
-            headers['%s%s' % (prefix, m)] = ''
-        return self.post(path, headers=headers, params=params)
-    
-    # Storage Account Services
-    
-    def list_containers(self, format='text', if_modified_since=None,
-                        if_unmodified_since=None, limit=None, marker=None,
-                        shared=False, until=None, account=None, public=False):
-        """returns a list with the account containers"""
-        account = account or self.account
-        params = {'until':until} if until else {}
-        if shared:
-            params['shared'] = None
-        if public:
-            params['public'] = None
-        headers = {'if-modified-since':if_modified_since,
-                   'if-unmodified-since':if_unmodified_since}
-        return OOS_Client.list_containers(self, account=account, format=format,
-                                          limit=limit, marker=marker,
-                                          params=params, **headers)
-    
-    def retrieve_account_metadata(self, restricted=False, until=None,
-                                  account=None):
-        """returns the account metadata"""
-        account = account or self.account
-        params = {'until':until} if until else {}
-        return OOS_Client.retrieve_account_metadata(self, account=account,
-                                                    restricted=restricted,
-                                                    **params)
-    
-    def set_account_groups(self, account=None, **groups):
-        """create account groups"""
-        account = account or self.account
-        path = '/%s' % account
-        headers = {}
-        for k, v in groups.items():
-            headers['x-account-group-%s' % k] = v
-        params = {'update':None}
-        return self.post(path, headers=headers, params=params)
-    
-    def retrieve_account_groups(self, account=None):
-        """returns the account groups"""
-        account = account or self.account
-        meta = self.retrieve_account_metadata(account=account)
-        prefix = 'x-account-group-'
-        prefixlen = len(prefix)
-        groups = {}
-        for key, val in meta.items():
-            if prefix and not key.startswith(prefix):
-                continue
-            elif prefix and key.startswith(prefix):
-                key = key[prefixlen:]
-            groups[key] = val
-        return groups
-    
-    def unset_account_groups(self, groups=[], account=None):
-        """delete account groups"""
-        account = account or self.account
-        path = '/%s' % account
-        headers = {}
-        for elem in groups:
-            headers['x-account-group-%s' % elem] = ''
-        params = {'update':None}
-        return self.post(path, headers=headers, params=params)
-    
-    def reset_account_groups(self, account=None, **groups):
-        """overrides account groups"""
-        account = account or self.account
-        path = '/%s' % account
-        headers = {}
-        for k, v in groups.items():
-            v = v.strip()
-            headers['x-account-group-%s' % k] = v
-        meta = self.retrieve_account_metadata(restricted=True)
-        prefix = 'x-account-meta-'
-        for k,v in meta.items():
-            k = '%s%s' % (prefix, k)
-            headers[k] = v
-        return self.post(path, headers=headers)
-    
-    # Storage Container Services
-    def create_container(self, container, account=None, meta={}, policies={}):
-        """creates a container"""
-        args = {}
-        for k, v in policies.items():
-            args['X-Container-Policy-%s' % k.capitalize()] = v
-        return OOS_Client.create_container(self, container, account, meta, **args)
-    
-    def list_objects(self, container, format='text',
-                     limit=None, marker=None, prefix=None, delimiter=None,
-                     path=None, shared=False, include_trashed=False, params={},
-                     if_modified_since=None, if_unmodified_since=None, meta='',
-                     until=None, account=None, public=False):
-        """returns a list with the container objects"""
-        account = account or self.account
-        params = {'until':until, 'meta':meta}
-        if shared:
-            params['shared'] = None
-        if public:
-            params['public'] = None
-        args = locals().copy()
-        for elem in ['self', 'container', 'params', 'until', 'meta']:
-            args.pop(elem)
-        return OOS_Client.list_objects(self, container, params=params, **args)
-    
-    def retrieve_container_metadata(self, container, restricted=False,
-                                    until=None, account=None):
-        """returns container's metadata"""
-        account = account or self.account
-        params = {'until':until} if until else {}
-        return OOS_Client.retrieve_container_metadata(self, container,
-                                                      account=account,
-                                                      restricted=restricted,
-                                                      **params)
-    
-    def set_container_policies(self, container, account=None,
-                               **policies):
-        """sets containers policies"""
-        account = account or self.account
-        path = '/%s/%s' % (account, container)
-        headers = {}
-        for key, val in policies.items():
-            headers['x-container-policy-%s' % key] = val
-        return self.post(path, headers=headers)
-    
-    def update_container_data(self, container, f=stdin):
-        """adds blocks of data to the container"""
-        account = self.account
-        path = '/%s/%s' % (account, container)
-        params = {'update': None}
-        headers = {'content_type': 'application/octet-stream'}
-        data = f.read() if f else None
-        headers['content_length'] = len(data)
-        return self.post(path, data, headers=headers, params=params)
-    
-    def delete_container(self, container, until=None, account=None, delimiter=None):
-        """deletes a container or the container history until the date provided"""
-        account = account or self.account
-        params = {'until':until} if until else {}
-        if delimiter:
-               params['delimiter'] = delimiter
-        return OOS_Client.delete_container(self, container, account=account,
-                                           params=params)
-    
-    # Storage Object Services
-    
-    def retrieve_object(self, container, object, params={}, format='text',
-                        range=None, if_range=None,
-                        if_match=None, if_none_match=None,
-                        if_modified_since=None, if_unmodified_since=None,
-                        account=None, **headers):
-        """returns an object"""
-        account = account or self.account
-        headers={}
-        l = ['range', 'if_range', 'if_match', 'if_none_match',
-             'if_modified_since', 'if_unmodified_since']
-        l = [elem for elem in l if eval(elem)]
-        for elem in l:
-            headers.update({elem:eval(elem)})
-        if format != 'text':
-            params['hashmap'] = None
-        return OOS_Client.retrieve_object(self, container, object,
-                                          account=account, format=format,
-                                          params=params, **headers)
-    
-    def retrieve_object_version(self, container, object, version,
-                                format='text', range=None, if_range=None,
-                                if_match=None, if_none_match=None,
-                                if_modified_since=None, if_unmodified_since=None,
-                                account=None):
-        """returns a specific object version"""
-        account = account or self.account
-        args = locals().copy()
-        l = ['self', 'container', 'object']
-        for elem in l:
-            args.pop(elem)
-        params = {'version':version}
-        return self.retrieve_object(container, object, params=params, **args)
-    
-    def retrieve_object_versionlist(self, container, object, range=None,
-                                    if_range=None, if_match=None,
-                                    if_none_match=None, if_modified_since=None,
-                                    if_unmodified_since=None, account=None):
-        """returns the object version list"""
-        account = account or self.account
-        args = locals().copy()
-        l = ['self', 'container', 'object']
-        for elem in l:
-            args.pop(elem)
-        
-        return self.retrieve_object_version(container, object, version='list',
-                                            format='json', **args)
-    
-    def create_zero_length_object(self, container, object,
-                                  meta={}, etag=None, content_type=None,
-                                  content_encoding=None,
-                                  content_disposition=None,
-                                  x_object_manifest=None, x_object_sharing=None,
-                                  x_object_public=None, account=None):
-        """createas a zero length object"""
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'object']:
-            args.pop(elem)
-        return OOS_Client.create_zero_length_object(self, container, object,
-                                                    **args)
-    
-    def create_folder(self, container, name,
-                          meta={}, etag=None, 
-                          content_encoding=None,
-                          content_disposition=None,
-                          x_object_manifest=None, x_object_sharing=None,
-                          x_object_public=None, account=None):
-       args = locals().copy()
-        for elem in ['self', 'container', 'name']:
-            args.pop(elem)
-        args['content_type'] = 'application/directory'
-        return self.create_zero_length_object(container, name, **args)
-    
-    def create_object(self, container, object, f=stdin, format='text',
-                      meta={}, params={}, etag=None, content_type=None,
-                      content_encoding=None, content_disposition=None,
-                      x_object_manifest=None, x_object_sharing=None,
-                      x_object_public=None, account=None):
-        """creates an object"""
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'object']:
-            args.pop(elem)
-        if format != 'text':
-            params.update({'hashmap':None})
-        return OOS_Client.create_object(self, container, object, **args)
-        
-    def create_object_using_chunks(self, container, object,
-                                   f=stdin, blocksize=1024, meta={}, etag=None,
-                                   content_type=None, content_encoding=None,
-                                   content_disposition=None,
-                                   x_object_sharing=None, x_object_manifest=None,
-                                   x_object_public=None, account=None):
-        """creates an object (incremental upload)"""
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        headers = {}
-        l = ['etag', 'content_type', 'content_encoding', 'content_disposition', 
-             'x_object_sharing', 'x_object_manifest', 'x_object_public']
-        l = [elem for elem in l if eval(elem)]
-        for elem in l:
-            headers.update({elem:eval(elem)})
-        headers.setdefault('content-type', 'application/octet-stream')
-        
-        for k,v in meta.items():
-            v = v.strip()
-            headers['x-object-meta-%s' %k.strip()] = v
-        
-        return self._chunked_transfer(path, 'PUT', f, headers=headers,
-                                      blocksize=blocksize)
-    
-    def create_object_by_hashmap(self, container, object, hashmap={},
-                                 meta={}, etag=None, content_encoding=None,
-                                 content_disposition=None, content_type=None,
-                                 x_object_sharing=None, x_object_manifest=None,
-                                 x_object_public = None, account=None):
-        """creates an object by uploading hashes representing data instead of data"""
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'object', 'hashmap']:
-            args.pop(elem)
-            
-        try:
-            data = json.dumps(hashmap)
-        except SyntaxError:
-            raise Fault('Invalid formatting')
-        args['params'] = {'hashmap':None}
-        args['format'] = 'json'
-        
-        return self.create_object(container, object, f=StringIO(data), **args)
-    
-    def create_manifestation(self, container, object, manifest, account=None):
-        """creates a manifestation"""
-        account = account or self.account
-        headers={'x_object_manifest':manifest}
-        return self.create_object(container, object, f=None, account=account,
-                                  **headers)
-    
-    def update_object(self, container, object, f=stdin,
-                      offset=None, meta={}, replace=False, content_length=None,
-                      content_type=None, content_range=None,
-                      content_encoding=None, content_disposition=None,
-                      x_object_bytes=None, x_object_manifest=None,
-                      x_object_sharing=None, x_object_public=None,
-                      x_source_object=None, account=None):
-        """updates an object"""
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'object', 'replace']:
-            args.pop(elem)
-        if not replace:
-            args['params'] = {'update':None}
-        return OOS_Client.update_object(self, container, object, **args)
-    
-    def update_object_using_chunks(self, container, object, f=stdin,
-                                   blocksize=1024, offset=None, meta={},
-                                   replace=False, content_type=None, content_encoding=None,
-                                   content_disposition=None, x_object_bytes=None,
-                                   x_object_manifest=None, x_object_sharing=None,
-                                   x_object_public=None, account=None):
-        """updates an object (incremental upload)"""
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'object', 'replace']:
-            args.pop(elem)
-        if not replace:
-            args['params'] = {'update':None}
-        return OOS_Client.update_object_using_chunks(self, container, object, **args)
-    
-    def update_from_other_source(self, container, object, source,
-                      offset=None, meta={}, content_range=None,
-                      content_encoding=None, content_disposition=None,
-                      x_object_bytes=None, x_object_manifest=None,
-                      x_object_sharing=None, x_object_public=None, account=None):
-        """updates an object"""
-        account = account or self.account
-        args = locals().copy()
-        for elem in ['self', 'container', 'object', 'source']:
-            args.pop(elem)
-        
-        args['x_source_object'] = source
-        return self.update_object(container, object, f=None, **args)
-    
-    def delete_object(self, container, object, until=None, account=None, delimiter=None):
-        """deletes an object or the object history until the date provided"""
-        account = account or self.account
-        params = {'until':until} if until else {}
-        if delimiter:
-               params['delimiter'] = delimiter
-        return OOS_Client.delete_object(self, container, object, params, account)
-    
-    def trash_object(self, container, object):
-        """trashes an object"""
-        account = account or self.account
-        path = '/%s/%s' % (container, object)
-        meta = {'trash':'true'}
-        return self._update_metadata(path, 'object', **meta)
-    
-    def restore_object(self, container, object, account=None):
-        """restores a trashed object"""
-        account = account or self.account
-        return self.delete_object_metadata(container, object, account, ['trash'])
-    
-    def publish_object(self, container, object, account=None):
-        """sets a previously created object publicly accessible"""
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        headers = {}
-        headers['x_object_public'] = True
-        params = {'update':None}
-        return self.post(path, headers=headers, params=params)
-    
-    def unpublish_object(self, container, object, account=None):
-        """unpublish an object"""
-        account = account or self.account
-        path = '/%s/%s/%s' % (account, container, object)
-        headers = {}
-        headers['x_object_public'] = False
-        params = {'update':None}
-        return self.post(path, headers=headers, params=params)
-    
-    def copy_object(self, src_container, src_object, dst_container, dst_object,
-                    meta={}, public=False, version=None, account=None,
-                    content_type=None, delimiter=None):
-        """copies an object"""
-        account = account or self.account
-        headers = {}
-        headers['x_object_public'] = public
-        if version:
-            headers['x_source_version'] = version
-        return OOS_Client.copy_object(self, src_container, src_object,
-                                      dst_container, dst_object, meta=meta,
-                                      account=account, content_type=content_type,
-                                      delimiter=delimiter,
-                                      **headers)
-    
-    def move_object(self, src_container, src_object, dst_container,
-                             dst_object, meta={}, public=False,
-                             account=None, content_type=None, delimiter=None):
-        """moves an object"""
-        headers = {}
-        headers['x_object_public'] = public
-        return OOS_Client.move_object(self, src_container, src_object,
-                                      dst_container, dst_object, meta=meta,
-                                      account=account, content_type=content_type,
-                                      delimiter=delimiter,
-                                      **headers)
-    
-    def list_shared_by_others(self, limit=None, marker=None, format='text'):
-        """lists other accounts that share objects to the user"""
-        l = ['limit', 'marker']
-        params = {}
-        for elem in [elem for elem in l if eval(elem)]:
-            params[elem] = eval(elem)
-        return self._list('', format, params)
-    
-    def share_object(self, container, object, l, read=True):
-        """gives access(read by default) to an object to a user/group list"""
-        action = 'read' if read else 'write'
-        sharing = '%s=%s' % (action, ','.join(l))
-        self.update_object(container, object, f=None, x_object_sharing=sharing)
-
-def _prepare_path(path, format='text', params={}):
-    full_path = '%s?format=%s' % (quote(path), format)
-    
-    for k,v in params.items():
-        value = quote(str(v)) if v else ''
-        full_path = '%s&%s=%s' %(full_path, quote(k), value)
-    return full_path
-
-def _prepare_headers(headers):
-    for k,v in headers.items():
-        headers.pop(k)
-        k = k.replace('_', '-')
-        headers[quote(k)] = quote(v, safe='/=,:@ *"') if type(v) == types.StringType else v
-    return headers
-
-def _handle_response(response, verbose=False, debug=False):
-    headers = response.getheaders()
-    headers = dict((unquote(h), unquote(v)) for h,v in headers)
-    
-    if verbose:
-        print '%d %s' % (response.status, response.reason)
-        for key, val in headers.items():
-            print '%s: %s' % (key.capitalize(), val)
-        print
-    
-    length = response.getheader('content-length', None)
-    data = response.read(length)
-    if debug:
-        print data
-        print
-    
-    if int(response.status) in ERROR_CODES.keys():
-        raise Fault(data, int(response.status))
-    
-    #print '**',  response.status, headers, data, '\n'
-    return response.status, headers, data
diff --git a/kamaki/clients/pithos_sh_lib/hashmap.py b/kamaki/clients/pithos_sh_lib/hashmap.py
deleted file mode 100644 (file)
index d2f96cb..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright 2011-2012 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.
-
-import hashlib
-import os
-
-from binascii import hexlify
-
-from progress.bar import IncrementalBar
-
-def file_read_iterator(fp, size=1024):
-    while True:
-        data = fp.read(size)
-        if not data:
-            break
-        yield data
-
-class HashMap(list):
-    
-    def __init__(self, blocksize, blockhash):
-        super(HashMap, self).__init__()
-        self.blocksize = blocksize
-        self.blockhash = blockhash
-    
-    def _hash_raw(self, v):
-        h = hashlib.new(self.blockhash)
-        h.update(v)
-        return h.digest()
-    
-    def _hash_block(self, v):
-        return self._hash_raw(v.rstrip('\x00'))
-    
-    def hash(self):
-        if len(self) == 0:
-            return self._hash_raw('')
-        if len(self) == 1:
-            return self.__getitem__(0)
-        
-        h = list(self)
-        s = 2
-        while s < len(h):
-            s = s * 2
-        h += [('\x00' * len(h[0]))] * (s - len(h))
-        while len(h) > 1:
-            h = [self._hash_raw(h[x] + h[x + 1]) for x in range(0, len(h), 2)]
-        return h[0]
-    
-    def load(self, fp, with_progress_bar=True):
-        self.size = 0
-        file_size = os.fstat(fp.fileno()).st_size
-        nblocks = 1 + (file_size - 1) // self.blocksize
-        if with_progress_bar:
-            bar = IncrementalBar('Computing', max=nblocks)
-            bar.suffix = '%(percent).1f%% - %(eta)ds'
-            for block in bar.iter(file_read_iterator(fp, self.blocksize)):
-                self.append(self._hash_block(block))
-                self.size += len(block)
-        else:
-            for block in file_read_iterator(fp, self.blocksize):
-                self.append(self._hash_block(block))
-                self.size += len(block)
-
-    def get_hash(self, fp, start, size):
-        fp.seek(start)
-        block = fp.read(size)
-        h = hashlib.new(self.blockhash)
-        h.update(block.strip('\x00'))
-        return h.digest()
-        #r = self._hash_raw(block.strip('\x00'))
-        #return r
-
-
-def merkle(path, blocksize=4194304, blockhash='sha256'):
-    hashes = HashMap(blocksize, blockhash)
-    hashes.load(open(path))
-    return hexlify(hashes.hash())
diff --git a/kamaki/clients/pithos_sh_lib/sh.py b/kamaki/clients/pithos_sh_lib/sh.py
deleted file mode 100755 (executable)
index 1555ed1..0000000
+++ /dev/null
@@ -1,829 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2011-2012 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 getpass import getuser
-from optparse import OptionParser
-from os import environ
-from sys import argv, exit, stdin, stdout
-from datetime import datetime
-
-from kamaki.pithos_sh.client import Pithos_Client, Fault
-from kamaki.pithos_sh.util import get_user, get_auth, get_url
-from kamaki.pithos_sh.transfer import upload, download
-
-import json
-import logging
-import types
-import re
-import time as _time
-import os
-
-_cli_commands = {}
-
-def cli_command(*args):
-    def decorator(cls):
-        cls.commands = args
-        for name in args:
-            _cli_commands[name] = cls
-        return cls
-    return decorator
-
-def class_for_cli_command(name):
-    return _cli_commands[name]
-
-class Command(object):
-    syntax = ''
-    
-    def __init__(self, name, argv):
-        parser = OptionParser('%%prog %s [options] %s' % (name, self.syntax))
-        parser.add_option('--url', dest='url', metavar='URL',
-                          default=get_url(), help='server URL (currently: %s)' % get_url())
-        parser.add_option('--user', dest='user', metavar='USER',
-                          default=get_user(),
-                          help='account USER (currently: %s)' % get_user())
-        parser.add_option('--token', dest='token', metavar='TOKEN',
-                          default=get_auth(),
-                          help='account TOKEN (currently: %s)' % get_auth())
-        parser.add_option('-v', action='store_true', dest='verbose',
-                          default=False, help='verbose output')
-        parser.add_option('-d', action='store_true', dest='debug',
-                          default=False, help='debug output')
-        self.add_options(parser)
-        options, args = parser.parse_args(argv)
-        
-        # Add options to self
-        for opt in parser.option_list:
-            key = opt.dest
-            if key:
-                val = getattr(options, key)
-                setattr(self, key, val)
-        
-        self.client = Pithos_Client(self.url, self.token, self.user, self.verbose,
-                             self.debug)
-        
-        self.parser = parser
-        self.args = args
-    
-    def _build_args(self, attrs):
-        args = {}
-        for a in [a for a in attrs if getattr(self, a)]:
-            args[a] = getattr(self, a)
-        return args
-
-    def add_options(self, parser):
-        pass
-    
-    def execute(self, *args):
-        pass
-
-@cli_command('list', 'ls')
-class List(Command):
-    syntax = '[<container>[/<object>]]'
-    description = 'list containers or objects'
-    
-    def add_options(self, parser):
-        parser.add_option('-l', action='store_true', dest='detail',
-                          default=False, help='show detailed output')
-        parser.add_option('-n', action='store', type='int', dest='limit',
-                          default=10000, help='show limited output')
-        parser.add_option('--marker', action='store', type='str',
-                          dest='marker', default=None,
-                          help='show output greater then marker')
-        parser.add_option('--prefix', action='store', type='str',
-                          dest='prefix', default=None,
-                          help='show output starting with prefix')
-        parser.add_option('--delimiter', action='store', type='str',
-                          dest='delimiter', default=None,
-                          help='show output up to the delimiter')
-        parser.add_option('--path', action='store', type='str',
-                          dest='path', default=None,
-                          help='show output starting with prefix up to /')
-        parser.add_option('--meta', action='store', type='str',
-                          dest='meta', default=None,
-                          help='show output having the specified meta keys')
-        parser.add_option('--if-modified-since', action='store', type='str',
-                          dest='if_modified_since', default=None,
-                          help='show output if modified since then')
-        parser.add_option('--if-unmodified-since', action='store', type='str',
-                          dest='if_unmodified_since', default=None,
-                          help='show output if not modified since then')
-        parser.add_option('--until', action='store', dest='until',
-                          default=None, help='show metadata until that date')
-        parser.add_option('--format', action='store', dest='format',
-                          default='%d/%m/%Y %H:%M:%S', help='format to parse until date (default: %d/%m/%Y %H:%M:%S)')
-        parser.add_option('--shared', action='store_true', dest='shared',
-                          default=False, help='show only shared')
-        parser.add_option('--public', action='store_true', dest='public',
-                          default=False, help='show only public')
-        
-    
-    def execute(self, container=None):
-        if container:
-            self.list_objects(container)
-        else:
-            self.list_containers()
-    
-    def list_containers(self):
-        attrs = ['limit', 'marker', 'if_modified_since',
-                 'if_unmodified_since', 'shared', 'public']
-        args = self._build_args(attrs)
-        args['format'] = 'json' if self.detail else 'text'
-        
-        if getattr(self, 'until'):
-            t = _time.strptime(self.until, self.format)
-            args['until'] = int(_time.mktime(t))
-        
-        l = self.client.list_containers(**args)
-        print_list(l)
-    
-    def list_objects(self, container):
-        #prepate params
-        params = {}
-        attrs = ['limit', 'marker', 'prefix', 'delimiter', 'path',
-                 'meta', 'if_modified_since', 'if_unmodified_since',
-                 'shared', 'public']
-        args = self._build_args(attrs)
-        args['format'] = 'json' if self.detail else 'text'
-        
-        if self.until:
-            t = _time.strptime(self.until, self.format)
-            args['until'] = int(_time.mktime(t))
-        
-        container, sep, object = container.partition('/')
-        if object:
-            return
-        
-        detail = 'json'
-        #if request with meta quering disable trash filtering
-        show_trashed = True if self.meta else False
-        l = self.client.list_objects(container, **args)
-        print_list(l, detail=self.detail)
-
-@cli_command('meta')
-class Meta(Command):
-    syntax = '[<container>[/<object>]]'
-    description = 'get account/container/object metadata'
-    
-    def add_options(self, parser):
-        parser.add_option('-r', action='store_true', dest='restricted',
-                          default=False, help='show only user defined metadata')
-        parser.add_option('--until', action='store', dest='until',
-                          default=None, help='show metadata until that date')
-        parser.add_option('--format', action='store', dest='format',
-                          default='%d/%m/%Y %H:%M:%S', help='format to parse until date (default: %d/%m/%Y %H:%M:%S)')
-        parser.add_option('--version', action='store', dest='version',
-                          default=None, help='show specific version \
-                                  (applies only for objects)')
-    
-    def execute(self, path=''):
-        container, sep, object = path.partition('/')
-        args = {'restricted': self.restricted}
-        if getattr(self, 'until'):
-            t = _time.strptime(self.until, self.format)
-            args['until'] = int(_time.mktime(t))
-        
-        if object:
-            meta = self.client.retrieve_object_metadata(container, object,
-                                                        self.restricted,
-                                                        self.version)
-        elif container:
-            meta = self.client.retrieve_container_metadata(container, **args)
-        else:
-            meta = self.client.retrieve_account_metadata(**args)
-        if meta == None:
-            print 'Entity does not exist'
-        else:
-            print_dict(meta, header=None)
-
-@cli_command('create')
-class CreateContainer(Command):
-    syntax = '<container> [key=val] [...]'
-    description = 'create a container'
-    
-    def add_options(self, parser):
-        parser.add_option('--versioning', action='store', dest='versioning',
-                          default=None, help='set container versioning (auto/none)')
-        parser.add_option('--quota', action='store', dest='quota',
-                          default=None, help='set default container quota')
-    
-    def execute(self, container, *args):
-        meta = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            meta[key] = val
-        policy = {}
-        if getattr(self, 'versioning'):
-            policy['versioning'] = self.versioning
-        if getattr(self, 'quota'):
-            policy['quota'] = self.quota
-        ret = self.client.create_container(container, meta=meta, policies=policy)
-        if not ret:
-            print 'Container already exists'
-
-@cli_command('delete', 'rm')
-class Delete(Command):
-    syntax = '<container>[/<object>]'
-    description = 'delete a container or an object'
-    
-    def add_options(self, parser):
-        parser.add_option('--until', action='store', dest='until',
-                          default=None, help='remove history until that date')
-        parser.add_option('--format', action='store', dest='format',
-                          default='%d/%m/%Y %H:%M:%S', help='format to parse until date (default: %d/%m/%Y %H:%M:%S)')
-        parser.add_option('--delimiter', action='store', type='str',
-                          dest='delimiter', default=None,
-                          help='mass delete objects with path staring with <src object> + delimiter')
-        parser.add_option('-r', action='store_true',
-                          dest='recursive', default=False,
-                          help='mass delimiter objects with delimiter /')
-    
-    def execute(self, path):
-        container, sep, object = path.partition('/')
-        until = None
-        if getattr(self, 'until'):
-            t = _time.strptime(self.until, self.format)
-            until = int(_time.mktime(t))
-        
-        kwargs = {}
-        if self.delimiter:
-            kwargs['delimiter'] = self.delimiter
-        elif self.recursive:
-            kwargs['delimiter'] = '/'
-        
-        if object:
-            self.client.delete_object(container, object, until, **kwargs)
-        else:
-            self.client.delete_container(container, until, **kwargs)
-
-@cli_command('get')
-class GetObject(Command):
-    syntax = '<container>/<object>'
-    description = 'get the data of an object'
-    
-    def add_options(self, parser):
-        parser.add_option('-l', action='store_true', dest='detail',
-                          default=False, help='show detailed output')
-        parser.add_option('--range', action='store', dest='range',
-                          default=None, help='show range of data')
-        parser.add_option('--if-range', action='store', dest='if_range',
-                          default=None, help='show range of data')
-        parser.add_option('--if-match', action='store', dest='if_match',
-                          default=None, help='show output if ETags match')
-        parser.add_option('--if-none-match', action='store',
-                          dest='if_none_match', default=None,
-                          help='show output if ETags don\'t match')
-        parser.add_option('--if-modified-since', action='store', type='str',
-                          dest='if_modified_since', default=None,
-                          help='show output if modified since then')
-        parser.add_option('--if-unmodified-since', action='store', type='str',
-                          dest='if_unmodified_since', default=None,
-                          help='show output if not modified since then')
-        parser.add_option('-o', action='store', type='str',
-                          dest='file', default=None,
-                          help='save output in file')
-        parser.add_option('--version', action='store', type='str',
-                          dest='version', default=None,
-                          help='get the specific \
-                               version')
-        parser.add_option('--versionlist', action='store_true',
-                          dest='versionlist', default=False,
-                          help='get the full object version list')
-        parser.add_option('--hashmap', action='store_true',
-                          dest='hashmap', default=False,
-                          help='get the object hashmap instead')
-    
-    def execute(self, path):
-        attrs = ['if_match', 'if_none_match', 'if_modified_since',
-                 'if_unmodified_since', 'hashmap']
-        args = self._build_args(attrs)
-        args['format'] = 'json' if self.detail else 'text'
-        if self.range:
-            args['range'] = 'bytes=%s' % self.range
-        if getattr(self, 'if_range'):
-            args['if-range'] = 'If-Range:%s' % getattr(self, 'if_range')
-        
-        container, sep, object = path.partition('/')
-        data = None
-        if self.versionlist:
-            if 'detail' in args.keys():
-                args.pop('detail')
-            args.pop('format')
-            self.detail = True
-            data = self.client.retrieve_object_versionlist(container, object, **args)
-        elif self.version:
-            data = self.client.retrieve_object_version(container, object,
-                                                       self.version, **args)
-        elif self.hashmap:
-            if 'detail' in args.keys():
-                args.pop('detail')
-            args.pop('format')
-            self.detail = True
-            data = self.client.retrieve_object_hashmap(container, object, **args)
-        else:
-            data = self.client.retrieve_object(container, object, **args)    
-        
-        f = open(self.file, 'w') if self.file else stdout
-        if self.detail or type(data) == types.DictionaryType:
-            if self.versionlist:
-                print_versions(data, f=f)
-            else:
-                print_dict(data, f=f)
-        else:
-            f.write(data)
-        f.close()
-
-@cli_command('mkdir')
-class PutMarker(Command):
-    syntax = '<container>/<directory marker>'
-    description = 'create a directory marker'
-    
-    def execute(self, path):
-        container, sep, object = path.partition('/')
-        self.client.create_directory_marker(container, object)
-
-@cli_command('put')
-class PutObject(Command):
-    syntax = '<container>/<object> [key=val] [...]'
-    description = 'create/override object'
-    
-    def add_options(self, parser):
-        parser.add_option('--use_hashes', action='store_true', dest='use_hashes',
-                          default=False, help='provide hashmap instead of data')
-        parser.add_option('--chunked', action='store_true', dest='chunked',
-                          default=False, help='set chunked transfer mode')
-        parser.add_option('--etag', action='store', dest='etag',
-                          default=None, help='check written data')
-        parser.add_option('--content-encoding', action='store',
-                          dest='content_encoding', default=None,
-                          help='provide the object MIME content type')
-        parser.add_option('--content-disposition', action='store', type='str',
-                          dest='content_disposition', default=None,
-                          help='provide the presentation style of the object')
-        #parser.add_option('-S', action='store',
-        #                  dest='segment_size', default=False,
-        #                  help='use for large file support')
-        parser.add_option('--manifest', action='store',
-                          dest='x_object_manifest', default=None,
-                          help='provide object parts prefix in <container>/<object> form')
-        parser.add_option('--content-type', action='store',
-                          dest='content_type', default=None,
-                          help='create object with specific content type')
-        parser.add_option('--sharing', action='store',
-                          dest='x_object_sharing', default=None,
-                          help='define sharing object policy')
-        parser.add_option('-f', action='store',
-                          dest='srcpath', default=None,
-                          help='file descriptor to read from (pass - for standard input)')
-        parser.add_option('--public', action='store_true',
-                          dest='x_object_public', default=False,
-                          help='make object publicly accessible')
-    
-    def execute(self, path, *args):
-        if path.find('=') != -1:
-            raise Fault('Missing path argument')
-        
-        #prepare user defined meta
-        meta = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            meta[key] = val
-        
-        attrs = ['etag', 'content_encoding', 'content_disposition',
-                 'content_type', 'x_object_sharing', 'x_object_public']
-        args = self._build_args(attrs)
-        
-        container, sep, object = path.partition('/')
-        
-        f = None
-        if self.srcpath:
-            f = open(self.srcpath) if self.srcpath != '-' else stdin
-        
-        if self.use_hashes and not f:
-            raise Fault('Illegal option combination')
-        
-        if self.chunked:
-            self.client.create_object_using_chunks(container, object, f,
-                                                    meta=meta, **args)
-        elif self.use_hashes:
-            data = f.read()
-            hashmap = json.loads(data)
-            self.client.create_object_by_hashmap(container, object, hashmap,
-                                             meta=meta, **args)
-        elif self.x_object_manifest:
-            self.client.create_manifestation(container, object, self.x_object_manifest)
-        elif not f:
-            self.client.create_zero_length_object(container, object, meta=meta, **args)
-        else:
-            self.client.create_object(container, object, f, meta=meta, **args)
-        if f:
-            f.close()
-
-@cli_command('copy', 'cp')
-class CopyObject(Command):
-    syntax = '<src container>/<src object> [<dst container>/]<dst object> [key=val] [...]'
-    description = 'copy an object to a different location'
-    
-    def add_options(self, parser):
-        parser.add_option('--version', action='store',
-                          dest='version', default=False,
-                          help='copy specific version')
-        parser.add_option('--public', action='store_true',
-                          dest='public', default=False,
-                          help='make object publicly accessible')
-        parser.add_option('--content-type', action='store',
-                          dest='content_type', default=None,
-                          help='change object\'s content type')
-        parser.add_option('--delimiter', action='store', type='str',
-                          dest='delimiter', default=None,
-                          help='mass copy objects with path staring with <src object> + delimiter')
-        parser.add_option('-r', action='store_true',
-                          dest='recursive', default=False,
-                          help='mass copy with delimiter /')
-    
-    def execute(self, src, dst, *args):
-        src_container, sep, src_object = src.partition('/')
-        dst_container, sep, dst_object = dst.partition('/')
-        
-        #prepare user defined meta
-        meta = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            meta[key] = val
-        
-        if not sep:
-            dst_container = src_container
-            dst_object = dst
-        
-        args = {'content_type':self.content_type} if self.content_type else {}
-        if self.delimiter:
-               args['delimiter'] = self.delimiter
-        elif self.recursive:
-               args['delimiter'] = '/'
-        self.client.copy_object(src_container, src_object, dst_container,
-                                dst_object, meta, self.public, self.version,
-                                **args)
-
-@cli_command('set')
-class SetMeta(Command):
-    syntax = '[<container>[/<object>]] key=val [key=val] [...]'
-    description = 'set account/container/object metadata'
-    
-    def execute(self, path, *args):
-        #in case of account fix the args
-        if path.find('=') != -1:
-            args = list(args)
-            args.append(path)
-            args = tuple(args)
-            path = ''
-        meta = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            meta[key.strip()] = val.strip()
-        container, sep, object = path.partition('/')
-        if object:
-            self.client.update_object_metadata(container, object, **meta)
-        elif container:
-            self.client.update_container_metadata(container, **meta)
-        else:
-            self.client.update_account_metadata(**meta)
-
-@cli_command('update')
-class UpdateObject(Command):
-    syntax = '<container>/<object> path [key=val] [...]'
-    description = 'update object metadata/data (default mode: append)'
-    
-    def add_options(self, parser):
-        parser.add_option('-a', action='store_true', dest='append',
-                          default=True, help='append data')
-        parser.add_option('--offset', action='store',
-                          dest='offset',
-                          default=None, help='starting offest to be updated')
-        parser.add_option('--range', action='store', dest='content_range',
-                          default=None, help='range of data to be updated')
-        parser.add_option('--chunked', action='store_true', dest='chunked',
-                          default=False, help='set chunked transfer mode')
-        parser.add_option('--content-encoding', action='store',
-                          dest='content_encoding', default=None,
-                          help='provide the object MIME content type')
-        parser.add_option('--content-disposition', action='store', type='str',
-                          dest='content_disposition', default=None,
-                          help='provide the presentation style of the object')
-        parser.add_option('--manifest', action='store', type='str',
-                          dest='x_object_manifest', default=None,
-                          help='use for large file support')        
-        parser.add_option('--sharing', action='store',
-                          dest='x_object_sharing', default=None,
-                          help='define sharing object policy')
-        parser.add_option('--nosharing', action='store_true',
-                          dest='no_sharing', default=None,
-                          help='clear object sharing policy')
-        parser.add_option('-f', action='store',
-                          dest='srcpath', default=None,
-                          help='file descriptor to read from: pass - for standard input')
-        parser.add_option('--public', action='store_true',
-                          dest='x_object_public', default=False,
-                          help='make object publicly accessible')
-        parser.add_option('--replace', action='store_true',
-                          dest='replace', default=False,
-                          help='override metadata')
-    
-    def execute(self, path, *args):
-        if path.find('=') != -1:
-            raise Fault('Missing path argument')
-        
-        #prepare user defined meta
-        meta = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            meta[key] = val
-        
-        
-        attrs = ['content_encoding', 'content_disposition', 'x_object_sharing',
-                 'x_object_public', 'x_object_manifest', 'replace', 'offset',
-                 'content_range']
-        args = self._build_args(attrs)
-        
-        if self.no_sharing:
-            args['x_object_sharing'] = ''
-        
-        container, sep, object = path.partition('/')
-        
-        f = None
-        if self.srcpath:
-            f = open(self.srcpath) if self.srcpath != '-' else stdin
-        
-        if self.chunked:
-            self.client.update_object_using_chunks(container, object, f,
-                                                    meta=meta, **args)
-        else:
-            self.client.update_object(container, object, f, meta=meta, **args)
-        if f:
-            f.close()
-
-@cli_command('move', 'mv')
-class MoveObject(Command):
-    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
-    description = 'move an object to a different location'
-    
-    def add_options(self, parser):
-        parser.add_option('--public', action='store_true',
-                          dest='public', default=False,
-                          help='make object publicly accessible')
-        parser.add_option('--content-type', action='store',
-                          dest='content_type', default=None,
-                          help='change object\'s content type')
-        parser.add_option('--delimiter', action='store', type='str',
-                          dest='delimiter', default=None,
-                          help='mass move objects with path staring with <src object> + delimiter')
-        parser.add_option('-r', action='store_true',
-                          dest='recursive', default=False,
-                          help='mass move objects with delimiter /')
-    
-    def execute(self, src, dst, *args):
-        src_container, sep, src_object = src.partition('/')
-        dst_container, sep, dst_object = dst.partition('/')
-        if not sep:
-            dst_container = src_container
-            dst_object = dst
-        
-        #prepare user defined meta
-        meta = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            meta[key] = val
-        
-        args = {'content_type':self.content_type} if self.content_type else {}
-        if self.delimiter:
-               args['delimiter'] = self.delimiter
-        elif self.recursive:
-               args['delimiter'] = '/'
-        self.client.move_object(src_container, src_object, dst_container,
-                                dst_object, meta, self.public, **args)
-
-@cli_command('unset')
-class UnsetObject(Command):
-    syntax = '<container>/[<object>] key [key] [...]'
-    description = 'delete metadata info'
-    
-    def execute(self, path, *args):
-        #in case of account fix the args
-        if len(args) == 0:
-            args = list(args)
-            args.append(path)
-            args = tuple(args)
-            path = ''
-        meta = []
-        for key in args:
-            meta.append(key)
-        container, sep, object = path.partition('/')
-        if object:
-            self.client.delete_object_metadata(container, object, meta)
-        elif container:
-            self.client.delete_container_metadata(container, meta)
-        else:
-            self.client.delete_account_metadata(meta)
-
-@cli_command('group')
-class CreateGroup(Command):
-    syntax = 'key=val [key=val] [...]'
-    description = 'create account groups'
-    
-    def execute(self, *args):
-        groups = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            groups[key] = val
-        self.client.set_account_groups(**groups)
-
-@cli_command('ungroup')
-class DeleteGroup(Command):
-    syntax = 'key [key] [...]'
-    description = 'delete account groups'
-    
-    def execute(self, *args):
-        groups = []
-        for arg in args:
-            groups.append(arg)
-        self.client.unset_account_groups(groups)
-
-@cli_command('policy')
-class SetPolicy(Command):
-    syntax = 'container key=val [key=val] [...]'
-    description = 'set container policies'
-    
-    def execute(self, path, *args):
-        if path.find('=') != -1:
-            raise Fault('Missing container argument')
-        
-        container, sep, object = path.partition('/')
-        
-        if object:
-            raise Fault('Only containers have policies')
-        
-        policies = {}
-        for arg in args:
-            key, sep, val = arg.partition('=')
-            policies[key] = val
-        
-        self.client.set_container_policies(container, **policies)
-
-@cli_command('publish')
-class PublishObject(Command):
-    syntax = '<container>/<object>'
-    description = 'publish an object'
-    
-    def execute(self, src):
-        src_container, sep, src_object = src.partition('/')
-        
-        self.client.publish_object(src_container, src_object)
-
-@cli_command('unpublish')
-class UnpublishObject(Command):
-    syntax = '<container>/<object>'
-    description = 'unpublish an object'
-    
-    def execute(self, src):
-        src_container, sep, src_object = src.partition('/')
-        
-        self.client.unpublish_object(src_container, src_object)
-
-@cli_command('sharing')
-class SharingObject(Command):
-    syntax = 'list users sharing objects with the user'
-    description = 'list user accounts sharing objects with the user'
-    
-    def add_options(self, parser):
-        parser.add_option('-l', action='store_true', dest='detail',
-                          default=False, help='show detailed output')
-        parser.add_option('-n', action='store', type='int', dest='limit',
-                          default=10000, help='show limited output')
-        parser.add_option('--marker', action='store', type='str',
-                          dest='marker', default=None,
-                          help='show output greater then marker')
-        
-    
-    def execute(self):
-        attrs = ['limit', 'marker']
-        args = self._build_args(attrs)
-        args['format'] = 'json' if self.detail else 'text'
-        
-        print_list(self.client.list_shared_by_others(**args))
-
-@cli_command('send')
-class Send(Command):
-    syntax = '<file> <container>[/<prefix>]'
-    description = 'upload file to container (using prefix)'
-    
-    def execute(self, file, path):
-        container, sep, prefix = path.partition('/')
-        upload(self.client, file, container, prefix)
-
-@cli_command('receive')
-class Receive(Command):
-    syntax = '<container>/<object> <file>'
-    description = 'download object to file'
-    
-    def execute(self, path, file):
-        container, sep, object = path.partition('/')
-        download(self.client, container, object, file)
-
-def print_usage():
-    cmd = Command('', [])
-    parser = cmd.parser
-    parser.usage = '%prog <command> [options]'
-    parser.print_help()
-    
-    commands = []
-    for cls in set(_cli_commands.values()):
-        name = ', '.join(cls.commands)
-        description = getattr(cls, 'description', '')
-        commands.append('  %s %s' % (name.ljust(12), description))
-    print '\nCommands:\n' + '\n'.join(sorted(commands))
-
-def print_dict(d, header='name', f=stdout, detail=True):
-    header = header if header in d else 'subdir'
-    if header and header in d:
-        f.write('%s\n' %d.pop(header).encode('utf8'))
-    if detail:
-        patterns = ['^x_(account|container|object)_meta_(\w+)$']
-        patterns.append(patterns[0].replace('_', '-'))
-        for key, val in sorted(d.items()):
-            f.write('%s: %s\n' % (key.rjust(30), val))
-
-def print_list(l, verbose=False, f=stdout, detail=True):
-    for elem in l:
-        #if it's empty string continue
-        if not elem:
-            continue
-        if type(elem) == types.DictionaryType:
-            print_dict(elem, f=f, detail=detail)
-        elif type(elem) == types.StringType:
-            if not verbose:
-                elem = elem.split('Traceback')[0]
-            f.write('%s\n' % elem)
-        else:
-            f.write('%s\n' % elem)
-
-def print_versions(data, f=stdout):
-    if 'versions' not in data:
-        f.write('%s\n' %data)
-        return
-    f.write('versions:\n')
-    for id, t in data['versions']:
-        f.write('%s @ %s\n' % (str(id).rjust(30), datetime.fromtimestamp(float(t))))
-
-
-def main():
-    try:
-        name = argv[1]
-        cls = class_for_cli_command(name)
-    except (IndexError, KeyError):
-        print_usage()
-        exit(1)
-    
-    cmd = cls(name, argv[2:])
-    
-    try:
-        cmd.execute(*cmd.args)
-    except TypeError, e:
-        cmd.parser.print_help()
-        exit(1)
-    except Fault, f:
-        status = '%s ' % f.status if f.status else ''
-        print '%s%s' % (status, f.data)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/kamaki/clients/pithos_sh_lib/transfer.py b/kamaki/clients/pithos_sh_lib/transfer.py
deleted file mode 100644 (file)
index dd2d6fb..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 2011-2012 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.
-
-import os
-import types
-import json
-
-from hashmap import HashMap
-from binascii import hexlify, unhexlify
-from cStringIO import StringIO
-from client import Fault
-
-from progress.bar import IncrementalBar
-
-def upload(client, path, container, prefix, name=None, mimetype=None):
-    
-    meta = client.retrieve_container_metadata(container)
-    blocksize = int(meta['x-container-block-size'])
-    blockhash = meta['x-container-block-hash']
-    
-    size = os.path.getsize(path)
-    hashes = HashMap(blocksize, blockhash)
-    hashes.load(open(path))
-    map = {'bytes': size, 'hashes': [hexlify(x) for x in hashes]}
-    
-    objectname = name if name else os.path.split(path)[-1]
-    object = prefix + objectname
-    kwargs = {'mimetype':mimetype} if mimetype else {}
-    v = None
-    try:
-        v = client.create_object_by_hashmap(container, object, map, **kwargs)
-    except Fault, fault:
-        if fault.status != 409:
-            raise
-    else:
-        return v
-    
-    if type(fault.data) == types.StringType:
-        missing = json.loads(fault.data)
-    elif type(fault.data) == types.ListType:
-        missing = fault.data
-    
-    if '' in missing:
-        del missing[missing.index(''):]
-    
-    bar = IncrementalBar('Uploading', max=len(missing))
-    bar.suffix = '%(percent).1f%% - %(eta)ds'
-    with open(path) as fp:
-        for hash in missing:
-            offset = hashes.index(unhexlify(hash)) * blocksize
-            fp.seek(offset)
-            block = fp.read(blocksize)
-            client.update_container_data(container, StringIO(block))
-            bar.next()
-    bar.finish()
-    
-    return client.create_object_by_hashmap(container, object, map, **kwargs)
-
-def download(client, container, object, path):
-    
-    res = client.retrieve_object_hashmap(container, object)
-    blocksize = int(res['block_size'])
-    blockhash = res['block_hash']
-    bytes = res['bytes']
-    map = res['hashes']
-    
-    if os.path.exists(path):
-        h = HashMap(blocksize, blockhash)
-        h.load(open(path))
-        hashes = [hexlify(x) for x in h]
-    else:
-        open(path, 'w').close()     # Create an empty file
-        hashes = []
-    
-    with open(path, 'a+') as fp:
-        if bytes != 0:
-            for i, h in enumerate(map):
-                if i < len(hashes) and h == hashes[i]:
-                    continue
-                start = i * blocksize
-                end = '' if i == len(map) - 1 else ((i + 1) * blocksize) - 1
-                data = client.retrieve_object(container, object, range='bytes=%s-%s' % (start, end))
-                if i != len(map) - 1:
-                    data += (blocksize - len(data)) * '\x00'
-                fp.seek(start)
-                fp.write(data)
-        fp.truncate(bytes)
-
-def cat(client, container, object):
-    res = client.retrieve_object_hashmap(container, object)
-    blocksize = int(res['block_size'])
-    blockhash = res['block_hash']
-    bytes = res['bytes']
-    map = res['hashes']
-    
-    hashes = []
-    for i, h in enumerate(map):
-        if i < len(hashes) and h == hashes[i]:
-            continue
-        start = i * blocksize
-        end = '' if i == len(map) - 1 else ((i + 1) * blocksize) - 1
-        data = client.retrieve_object(container, object, range='bytes=%s-%s' % (start, end))
-        if i != len(map) - 1:
-            data += (blocksize - len(data)) * '\x00'
-        print(unicode(data))
diff --git a/kamaki/clients/pithos_sh_lib/util.py b/kamaki/clients/pithos_sh_lib/util.py
deleted file mode 100644 (file)
index b2198ae..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2011-2012 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.
-
-import os
-
-DEFAULT_URL = 'https://pithos.okeanos.grnet.gr/v1'
-DEFAULT_USER = 'test'
-DEFAULT_TOKEN = '0000'
-
-def get_user():
-    try:
-        return os.environ['PITHOS_USER']
-    except KeyError:
-        return DEFAULT_USER
-
-def get_auth():
-    try:
-        return os.environ['PITHOS_TOKEN']
-    except KeyError:
-        return DEFAULT_TOKEN
-
-def get_url():
-    try:
-        return os.environ['PITHOS_URL'].rstrip('/')
-    except KeyError:
-        return DEFAULT_URL