Skip to content

Commit 941a2c7

Browse files
committed
Merge pull request #224 from tseaver/pr_99-gsalgado-master
Rebase PR #99 and fix up
2 parents 2db8ce0 + dcaae75 commit 941a2c7

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

gcloud/storage/bucket.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,28 @@ def delete_keys(self, keys):
191191
for key in keys:
192192
self.delete_key(key)
193193

194-
def copy_key(self): # pragma NO COVER
195-
raise NotImplementedError
194+
def copy_key(self, key, destination_bucket, new_name=None):
195+
"""Copy the given key to the given bucket, optionally with a new name.
196+
197+
:type key: string or :class:`gcloud.storage.key.Key`
198+
:param key: The key to be copied.
199+
200+
:type destination_bucket: :class:`gcloud.storage.bucket.Bucket`
201+
:param destination_bucket: The bucket into which the key should be
202+
copied.
203+
204+
:type new_name: string
205+
:param new_name: (optional) the new name for the copied file.
206+
207+
:rtype: :class:`gcloud.storage.key.Key`
208+
:returns: The new Key.
209+
"""
210+
if new_name is None:
211+
new_name = key.name
212+
new_key = destination_bucket.new_key(new_name)
213+
api_path = key.path + '/copyTo' + new_key.path
214+
self.connection.api_request(method='POST', path=api_path)
215+
return new_key
196216

197217
def upload_file(self, filename, key=None):
198218
"""Shortcut method to upload a file into this bucket.

gcloud/storage/key.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ def exists(self):
133133

134134
return self.bucket.get_key(self.name) is not None
135135

136+
def rename(self, new_name):
137+
"""Renames this key.
138+
139+
Effectively, copies key to the same bucket with a new name, then
140+
deletes the key.
141+
142+
:type new_name: string
143+
:param new_name: The new name for this key.
144+
145+
:rtype: :class:`Key`
146+
:returns: The newly-copied key.
147+
"""
148+
new_key = self.bucket.copy_key(self, self.bucket, new_name)
149+
self.bucket.delete_key(self)
150+
return new_key
151+
136152
def delete(self):
137153
"""Deletes a key from Cloud Storage.
138154

gcloud/storage/test_bucket.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,50 @@ def test_delete_keys_miss(self):
247247
self.assertEqual(kw[1]['method'], 'DELETE')
248248
self.assertEqual(kw[1]['path'], '/b/%s/o/%s' % (NAME, NONESUCH))
249249

250+
def test_copy_keys_wo_name(self):
251+
SOURCE = 'source'
252+
DEST = 'dest'
253+
KEY = 'key'
254+
255+
class _Key(object):
256+
name = KEY
257+
path = '/b/%s/o/%s' % (SOURCE, KEY)
258+
259+
connection = _Connection({})
260+
source = self._makeOne(connection, SOURCE)
261+
dest = self._makeOne(connection, DEST)
262+
key = _Key()
263+
new_key = source.copy_key(key, dest)
264+
self.assertTrue(new_key.bucket is dest)
265+
self.assertEqual(new_key.name, KEY)
266+
kw, = connection._requested
267+
COPY_PATH = '/b/%s/o/%s/copyTo/b/%s/o/%s' % (SOURCE, KEY, DEST, KEY)
268+
self.assertEqual(kw['method'], 'POST')
269+
self.assertEqual(kw['path'], COPY_PATH)
270+
271+
def test_copy_keys_w_name(self):
272+
SOURCE = 'source'
273+
DEST = 'dest'
274+
KEY = 'key'
275+
NEW_NAME = 'new_name'
276+
277+
class _Key(object):
278+
name = KEY
279+
path = '/b/%s/o/%s' % (SOURCE, KEY)
280+
281+
connection = _Connection({})
282+
source = self._makeOne(connection, SOURCE)
283+
dest = self._makeOne(connection, DEST)
284+
key = _Key()
285+
new_key = source.copy_key(key, dest, NEW_NAME)
286+
self.assertTrue(new_key.bucket is dest)
287+
self.assertEqual(new_key.name, NEW_NAME)
288+
kw, = connection._requested
289+
COPY_PATH = (
290+
'/b/%s/o/%s/copyTo/b/%s/o/%s' % (SOURCE, KEY, DEST, NEW_NAME))
291+
self.assertEqual(kw['method'], 'POST')
292+
self.assertEqual(kw['path'], COPY_PATH)
293+
250294
def test_upload_file_default_key(self):
251295
from gcloud.test_credentials import _Monkey
252296
from gcloud.storage import bucket as MUT

gcloud/storage/test_key.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ def test_exists_hit(self):
9595
bucket._keys[KEY] = 1
9696
self.assertTrue(key.exists())
9797

98+
def test_rename(self):
99+
KEY = 'key'
100+
NEW_NAME = 'new-name'
101+
connection = _Connection()
102+
bucket = _Bucket(connection)
103+
key = self._makeOne(bucket, KEY)
104+
bucket._keys[KEY] = 1
105+
orig_key_path = key.path
106+
new_key = key.rename(NEW_NAME)
107+
self.assertEqual(key.name, KEY)
108+
self.assertEqual(new_key.name, NEW_NAME)
109+
self.assertFalse(KEY in bucket._keys)
110+
self.assertTrue(KEY in bucket._deleted)
111+
self.assertTrue(NEW_NAME in bucket._keys)
112+
98113
def test_delete(self):
99114
KEY = 'key'
100115
connection = _Connection()
@@ -584,9 +599,15 @@ class _Bucket(object):
584599
def __init__(self, connection):
585600
self.connection = connection
586601
self._keys = {}
602+
self._deleted = []
587603

588604
def get_key(self, key):
589605
return self._keys.get(key) # XXX s.b. 'key.name'?
590606

607+
def copy_key(self, key, destination_bucket, new_name):
608+
destination_bucket._keys[new_name] = self._keys[key.name]
609+
return key.from_dict({'name': new_name}, bucket=destination_bucket)
610+
591611
def delete_key(self, key):
592612
del self._keys[key.name] # XXX s.b. 'key'?
613+
self._deleted.append(key.name)

0 commit comments

Comments
 (0)