From 073cd56218e7ad68f965c00888d053632d7c1986 Mon Sep 17 00:00:00 2001 From: YUZAWA Takahiko <yuzawataka@intellilink.co.jp> Date: Thu, 2 May 2013 00:15:11 +0900 Subject: [PATCH] Add end_marker and path query parameters Fix Bug 1175057 Change-Id: I1bf65fa7c4d99ddb03dd183fe3862df93455f501 --- swiftclient/client.py | 42 ++++++++++++++++++-------- tests/test_swiftclient.py | 62 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 13 deletions(-) diff --git a/swiftclient/client.py b/swiftclient/client.py index f934876b..d052cc4c 100644 --- a/swiftclient/client.py +++ b/swiftclient/client.py @@ -331,7 +331,7 @@ def get_auth(auth_url, user, key, **kwargs): def get_account(url, token, marker=None, limit=None, prefix=None, - http_conn=None, full_listing=False): + end_marker=None, http_conn=None, full_listing=False): """ Get a listing of containers for the account. @@ -340,6 +340,7 @@ def get_account(url, token, marker=None, limit=None, prefix=None, :param marker: marker query :param limit: limit query :param prefix: prefix query + :param end_marker: end_marker query :param http_conn: HTTP connection object (If None, it will create the conn object) :param full_listing: if True, return a full listing, else returns a max @@ -351,12 +352,14 @@ def get_account(url, token, marker=None, limit=None, prefix=None, if not http_conn: http_conn = http_connection(url) if full_listing: - rv = get_account(url, token, marker, limit, prefix, http_conn) + rv = get_account(url, token, marker, limit, prefix, + end_marker, http_conn) listing = rv[1] while listing: marker = listing[-1]['name'] listing = \ - get_account(url, token, marker, limit, prefix, http_conn)[1] + get_account(url, token, marker, limit, prefix, + end_marker, http_conn)[1] if listing: rv[1].extend(listing) return rv @@ -368,6 +371,8 @@ def get_account(url, token, marker=None, limit=None, prefix=None, qs += '&limit=%d' % limit if prefix: qs += '&prefix=%s' % quote(prefix) + if end_marker: + qs += '&end_marker=%s' % quote(end_marker) full_path = '%s?%s' % (parsed.path, qs) headers = {'X-Auth-Token': token} method = 'GET' @@ -458,7 +463,8 @@ def post_account(url, token, headers, http_conn=None): def get_container(url, token, container, marker=None, limit=None, - prefix=None, delimiter=None, http_conn=None, + prefix=None, delimiter=None, end_marker=None, + path=None, http_conn=None, full_listing=False): """ Get a listing of objects for the container. @@ -469,7 +475,9 @@ def get_container(url, token, container, marker=None, limit=None, :param marker: marker query :param limit: limit query :param prefix: prefix query - :param delimeter: string to delimit the queries on + :param delimiter: string to delimit the queries on + :param end_marker: marker query + :param path: path query (equivalent: "delimiter=/" and "prefix=path/") :param http_conn: HTTP connection object (If None, it will create the conn object) :param full_listing: if True, return a full listing, else returns a max @@ -482,7 +490,7 @@ def get_container(url, token, container, marker=None, limit=None, http_conn = http_connection(url) if full_listing: rv = get_container(url, token, container, marker, limit, prefix, - delimiter, http_conn) + delimiter, end_marker, path, http_conn) listing = rv[1] while listing: if not delimiter: @@ -490,12 +498,13 @@ def get_container(url, token, container, marker=None, limit=None, else: marker = listing[-1].get('name', listing[-1].get('subdir')) listing = get_container(url, token, container, marker, limit, - prefix, delimiter, http_conn)[1] + prefix, delimiter, end_marker, path, + http_conn)[1] if listing: rv[1].extend(listing) return rv parsed, conn = http_conn - path = '%s/%s' % (parsed.path, quote(container)) + cont_path = '%s/%s' % (parsed.path, quote(container)) qs = 'format=json' if marker: qs += '&marker=%s' % quote(marker) @@ -505,9 +514,13 @@ def get_container(url, token, container, marker=None, limit=None, qs += '&prefix=%s' % quote(prefix) if delimiter: qs += '&delimiter=%s' % quote(delimiter) + if end_marker: + qs += '&end_marker=%s' % quote(end_marker) + if path: + qs += '&path=%s' % quote(path) headers = {'X-Auth-Token': token} method = 'GET' - conn.request(method, '%s?%s' % (path, qs), '', headers) + conn.request(method, '%s?%s' % (cont_path, qs), '', headers) resp = conn.getresponse() body = resp.read() http_log(('%s?%s' % (url, qs), method,), {'headers': headers}, resp, body) @@ -515,7 +528,7 @@ def get_container(url, token, container, marker=None, limit=None, if resp.status < 200 or resp.status >= 300: raise ClientException('Container GET failed', http_scheme=parsed.scheme, http_host=conn.host, - http_port=conn.port, http_path=path, + http_port=conn.port, http_path=cont_path, http_query=qs, http_status=resp.status, http_reason=resp.reason, http_response_content=body) @@ -1052,13 +1065,14 @@ class Connection(object): return self._retry(None, head_account) def get_account(self, marker=None, limit=None, prefix=None, - full_listing=False): + end_marker=None, full_listing=False): """Wrapper for :func:`get_account`""" # TODO(unknown): With full_listing=True this will restart the entire # listing with each retry. Need to make a better version that just # retries where it left off. return self._retry(None, get_account, marker=marker, limit=limit, - prefix=prefix, full_listing=full_listing) + prefix=prefix, end_marker=end_marker, + full_listing=full_listing) def post_account(self, headers): """Wrapper for :func:`post_account`""" @@ -1069,13 +1083,15 @@ class Connection(object): return self._retry(None, head_container, container) def get_container(self, container, marker=None, limit=None, prefix=None, - delimiter=None, full_listing=False): + delimiter=None, end_marker=None, path=None, + full_listing=False): """Wrapper for :func:`get_container`""" # TODO(unknown): With full_listing=True this will restart the entire # listing with each retry. Need to make a better version that just # retries where it left off. return self._retry(None, get_container, container, marker=marker, limit=limit, prefix=prefix, delimiter=delimiter, + end_marker=end_marker, path=path, full_listing=full_listing) def put_container(self, container, headers=None): diff --git a/tests/test_swiftclient.py b/tests/test_swiftclient.py index ea1a444b..aa0e1590 100644 --- a/tests/test_swiftclient.py +++ b/tests/test_swiftclient.py @@ -354,6 +354,30 @@ class TestGetAccount(MockHttpTest): value = c.get_account('http://www.test.com', 'asdf')[1] self.assertEquals(value, []) + def test_param_marker(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&marker=marker") + c.get_account('http://www.test.com', 'asdf', marker='marker') + + def test_param_limit(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&limit=10") + c.get_account('http://www.test.com', 'asdf', limit=10) + + def test_param_prefix(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&prefix=asdf/") + c.get_account('http://www.test.com', 'asdf', prefix='asdf/') + + def test_param_end_marker(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&end_marker=end_marker") + c.get_account('http://www.test.com', 'asdf', end_marker='end_marker') + class TestHeadAccount(MockHttpTest): @@ -384,6 +408,44 @@ class TestGetContainer(MockHttpTest): value = c.get_container('http://www.test.com', 'asdf', 'asdf')[1] self.assertEquals(value, []) + def test_param_marker(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&marker=marker") + c.get_container('http://www.test.com', 'asdf', 'asdf', marker='marker') + + def test_param_limit(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&limit=10") + c.get_container('http://www.test.com', 'asdf', 'asdf', limit=10) + + def test_param_prefix(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&prefix=asdf/") + c.get_container('http://www.test.com', 'asdf', 'asdf', prefix='asdf/') + + def test_param_delimiter(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&delimiter=/") + c.get_container('http://www.test.com', 'asdf', 'asdf', delimiter='/') + + def test_param_end_marker(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&end_marker=end_marker") + c.get_container('http://www.test.com', 'asdf', 'asdf', + end_marker='end_marker') + + def test_param_path(self): + c.http_connection = self.fake_http_connection( + 204, + query_string="format=json&path=asdf") + c.get_container('http://www.test.com', 'asdf', 'asdf', + path='asdf') + class TestHeadContainer(MockHttpTest):