support part-num in python swiftClient
Change-Id: Ib3b076581eb0440da1071ea2cb53a90315f55775
This commit is contained in:
parent
fa9718deee
commit
e006c8f38e
|
@ -18,3 +18,4 @@ coverage.xml
|
|||
doc/build
|
||||
doc/source/api/
|
||||
.idea
|
||||
test/
|
||||
|
|
|
@ -159,6 +159,14 @@ def stat_object(conn, options, container, obj):
|
|||
query_string = None
|
||||
if options.get('version_id') is not None:
|
||||
query_string = 'version-id=%s' % options['version_id']
|
||||
if options.get('part_number') is not None:
|
||||
query_string = 'part-number=%s' % options['part_number']
|
||||
elif (options.get('version_id') is not None and options.get('part_number')
|
||||
is not None):
|
||||
query_string = 'version-id=%s&part-number=%s' % (
|
||||
options['version_id'], options['part_number']
|
||||
)
|
||||
|
||||
headers = conn.head_object(container, obj, headers=req_headers,
|
||||
query_string=query_string)
|
||||
items = []
|
||||
|
|
|
@ -1228,6 +1228,14 @@ class SwiftService:
|
|||
if options.get('version_id') is not None:
|
||||
get_args['query_string'] = (
|
||||
'version-id=%s' % options['version_id'])
|
||||
if options.get('part_number') is not None:
|
||||
get_args['query_string'] = (
|
||||
'part-number=%s' % options['part_number'])
|
||||
elif options.get('version_id') is not None and \
|
||||
options.get('part_number') is not None:
|
||||
get_args['query_string'] = (
|
||||
'version-id=%s&part-number=%s' % (
|
||||
options['version_id'], options['part_number']))
|
||||
if options['skip_identical']:
|
||||
# Assume the file is a large object; if we're wrong, the query
|
||||
# string is ignored and the If-None-Match header will trigger
|
||||
|
|
|
@ -236,6 +236,7 @@ st_download_options = '''[--all] [--marker <marker>] [--prefix <prefix>]
|
|||
[--container-threads <threads>] [--no-download]
|
||||
[--skip-identical] [--remove-prefix]
|
||||
[--version-id <version_id>]
|
||||
[--part-number <part_number>]
|
||||
[--header <header:value>] [--no-shuffle]
|
||||
[<container> [<object>] [...]]
|
||||
'''
|
||||
|
@ -282,6 +283,8 @@ Optional arguments:
|
|||
sides.
|
||||
--version-id <version-id>
|
||||
Download specific version of a versioned object.
|
||||
--part-number <part-number>
|
||||
Download a specific part of a static large object.
|
||||
--ignore-checksum Turn off checksum validation for downloads.
|
||||
--no-shuffle By default, when downloading a complete account or
|
||||
container, download order is randomised in order to
|
||||
|
@ -346,6 +349,9 @@ def st_download(parser, args, output_manager, return_parser=False):
|
|||
parser.add_argument(
|
||||
'--version-id', action='store', default=None,
|
||||
help='Download a specific version of a versioned object')
|
||||
parser.add_argument(
|
||||
'--part-number', action='store', default=None,
|
||||
help='Download a specific version of a versioned object')
|
||||
parser.add_argument(
|
||||
'--ignore-checksum', action='store_false', dest='checksum',
|
||||
default=True, help='Turn off checksum validation for downloads.')
|
||||
|
@ -375,12 +381,19 @@ def st_download(parser, args, output_manager, return_parser=False):
|
|||
|
||||
if options['out_file'] and len(args) != 2:
|
||||
exit('-o option only allowed for single file downloads')
|
||||
elif options['out_file'] and options['part_number'] and len(args) != 4:
|
||||
exit('--part-number only allowed for single file downloads')
|
||||
|
||||
if not options['prefix']:
|
||||
options['remove_prefix'] = False
|
||||
|
||||
if options['out_directory'] and len(args) == 2:
|
||||
exit('Please use -o option for single file downloads and renames')
|
||||
if options['out_directory'] and len(args) == 4 and options['part_number']:
|
||||
exit('Please use -o option for single file downloads and renames')
|
||||
|
||||
if options['part_number'] and len(args) < 4:
|
||||
exit('--part-number option only allowed for object downloads')
|
||||
|
||||
if (not args and not options['yes_all']) or (args and options['yes_all']):
|
||||
output_manager.error('Usage: %s download %s\n%s', BASENAME,
|
||||
|
@ -677,6 +690,7 @@ def st_list(parser, args, output_manager, return_parser=False):
|
|||
|
||||
st_stat_options = '''[--lh] [--header <header:value>]
|
||||
[--version-id <version_id>]
|
||||
[--part-number <part_number>]
|
||||
[<container> [<object>]]
|
||||
'''
|
||||
|
||||
|
@ -692,6 +706,8 @@ Optional arguments:
|
|||
ls -lh.
|
||||
--version-id <version-id>
|
||||
Report stat of specific version of a versioned object.
|
||||
--part-number <part-number>
|
||||
Report a specific part of a static large object.
|
||||
-H, --header <header:value>
|
||||
Adds a custom request header to use for stat.
|
||||
'''.strip('\n')
|
||||
|
@ -704,6 +720,9 @@ def st_stat(parser, args, output_manager, return_parser=False):
|
|||
parser.add_argument(
|
||||
'--version-id', action='store', default=None,
|
||||
help='Report stat of a specific version of a versioned object')
|
||||
parser.add_argument(
|
||||
'--part-number', action='store', default=None,
|
||||
help='Report a specific part of a static large object')
|
||||
parser.add_argument(
|
||||
'-H', '--header', action='append', dest='header',
|
||||
default=[],
|
||||
|
@ -717,6 +736,8 @@ def st_stat(parser, args, output_manager, return_parser=False):
|
|||
args = args[1:]
|
||||
if options['version_id'] and len(args) < 2:
|
||||
exit('--version-id option only allowed for object stats')
|
||||
if options['part_number'] and len(args) < 2:
|
||||
exit('--part-number option only allowed for object stats')
|
||||
|
||||
with SwiftService(options=options) as swift:
|
||||
try:
|
||||
|
@ -756,7 +777,11 @@ def st_stat(parser, args, output_manager, return_parser=False):
|
|||
items, headers, output_manager
|
||||
)
|
||||
else:
|
||||
<<<<<<< PATCH SET (62c272 support part-num in python swiftClient)
|
||||
raise (stat_result["error"])
|
||||
=======
|
||||
raise stat_result["error"]
|
||||
>>>>>>> BASE (fa9718 Merge "Add transaction id to errors")
|
||||
else:
|
||||
output_manager.error(
|
||||
'Usage: %s stat %s\n%s', BASENAME,
|
||||
|
@ -866,7 +891,11 @@ def st_post(parser, args, output_manager, return_parser=False):
|
|||
else:
|
||||
result = swift.post(container=container)
|
||||
if not result["success"]:
|
||||
<<<<<<< PATCH SET (62c272 support part-num in python swiftClient)
|
||||
raise (result["error"])
|
||||
=======
|
||||
raise result["error"]
|
||||
>>>>>>> BASE (fa9718 Merge "Add transaction id to errors")
|
||||
|
||||
except SwiftError as e:
|
||||
output_manager.error_with_txn_id(e)
|
||||
|
@ -1518,7 +1547,8 @@ def st_tempurl(parser, args, thread_manager, return_parser=False):
|
|||
thread_manager.print_msg(url)
|
||||
|
||||
|
||||
st_bash_completion_help = '''Retrieve command specific flags used by bash_completion.
|
||||
st_bash_completion_help = '''Retrieve command specific flags used by
|
||||
bash_completion.
|
||||
|
||||
Optional positional arguments:
|
||||
<command> Swift client command to filter the flags by.
|
||||
|
|
|
@ -313,6 +313,30 @@ class TestShell(unittest.TestCase):
|
|||
query_string='version-id=1')],
|
||||
connection.return_value.head_object.mock_calls)
|
||||
|
||||
@mock.patch('swiftclient.service.Connection')
|
||||
def test_stat_part_number(self, connection):
|
||||
argv = ["", "stat", "--part-number", "3"]
|
||||
with self.assertRaises(SystemExit) as caught:
|
||||
swiftclient.shell.main(argv)
|
||||
self.assertEqual(str(caught.exception),
|
||||
"--part-number option only allowed for "
|
||||
"object stats")
|
||||
|
||||
argv = ["", "stat", "--part-number", "8", "container"]
|
||||
with self.assertRaises(SystemExit) as caught:
|
||||
swiftclient.shell.main(argv)
|
||||
self.assertEqual(str(caught.exception),
|
||||
"--part-number option only allowed for "
|
||||
"object stats")
|
||||
|
||||
argv = ["", "stat", "--part-number", "20", "container", "object"]
|
||||
connection.return_value.head_object.return_value = {}
|
||||
with CaptureOutput():
|
||||
swiftclient.shell.main(argv)
|
||||
self.assertEqual([mock.call('container', 'object', headers={},
|
||||
query_string='part-number=20')],
|
||||
connection.return_value.head_object.mock_calls)
|
||||
|
||||
@mock.patch('swiftclient.service.Connection')
|
||||
def test_stat_object(self, connection):
|
||||
return_headers = {
|
||||
|
@ -699,6 +723,39 @@ class TestShell(unittest.TestCase):
|
|||
response_dict={})],
|
||||
connection.return_value.get_object.mock_calls)
|
||||
|
||||
@mock.patch('swiftclient.service.Connection')
|
||||
def test_download_part_number(self, connection):
|
||||
argv = ["", "download", "--part-number", "3"]
|
||||
with self.assertRaises(SystemExit) as caught:
|
||||
swiftclient.shell.main(argv)
|
||||
self.assertEqual(str(caught.exception),
|
||||
"--part-number option only allowed for "
|
||||
"object downloads")
|
||||
|
||||
argv = ["", "download", "--part-number", "12", "container"]
|
||||
with self.assertRaises(SystemExit) as caught:
|
||||
swiftclient.shell.main(argv)
|
||||
self.assertEqual(str(caught.exception),
|
||||
"--part-number option only allowed for "
|
||||
"object downloads")
|
||||
|
||||
argv = ["", "download", " --part-number", "7", "container", "object"]
|
||||
connection.return_value.head_object.return_value = {}
|
||||
connection.return_value.get_object.return_value = {}, ''
|
||||
connection.return_value.attempts = 0
|
||||
with CaptureOutput():
|
||||
swiftclient.shell.main(argv)
|
||||
self.assertEqual([mock.call(' --part-number', '7',
|
||||
headers={}, response_dict={},
|
||||
resp_chunk_size=65536),
|
||||
mock.call(' --part-number', 'container',
|
||||
headers={}, response_dict={},
|
||||
resp_chunk_size=65536),
|
||||
mock.call(' --part-number', 'object',
|
||||
headers={}, response_dict={},
|
||||
resp_chunk_size=65536)],
|
||||
connection.return_value.get_object.mock_calls)
|
||||
|
||||
@mock.patch('swiftclient.service.makedirs')
|
||||
@mock.patch('swiftclient.service.Connection')
|
||||
def test_download(self, connection, makedirs):
|
||||
|
|
Loading…
Reference in New Issue