Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added bucket method to upload files from a file object. #145

Merged
merged 1 commit into from
Sep 30, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions gcloud/storage/bucket.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from gcloud.storage import exceptions
from gcloud.storage.acl import BucketACL
from gcloud.storage.acl import DefaultObjectACL
Expand Down Expand Up @@ -233,6 +235,51 @@ def upload_file(self, filename, key=None):
key = self.new_key(key)
return key.set_contents_from_filename(filename)

def upload_file_object(self, fh, key=None):
# TODO: What do we do about overwriting data?
"""Shortcut method to upload a file into this bucket.

Use this method to quickly put a local file in Cloud Storage.

For example::

>>> from gcloud import storage
>>> connection = storage.get_connection(project, email, key_path)
>>> bucket = connection.get_bucket('my-bucket')
>>> bucket.upload_file(open('~/my-file.txt'), 'remote-text-file.txt')
>>> print bucket.get_all_keys()
[<Key: my-bucket, remote-text-file.txt>]

If you don't provide a key value,
we will try to upload the file using the local filename
as the key
(**not** the complete path)::

>>> from gcloud import storage
>>> connection = storage.get_connection(project, email, key_path)
>>> bucket = connection.get_bucket('my-bucket')
>>> bucket.upload_file(open('~/my-file.txt'))
>>> print bucket.get_all_keys()
[<Key: my-bucket, my-file.txt>]

:type fh: file
:param fh: A file handle open for reading.

:type key: string or :class:`gcloud.storage.key.Key`
:param key: The key (either an object or a remote path)
of where to put the file.

If this is blank,
we will try to upload the file
to the root of the bucket
with the same name as on your local file system.
"""
if key:
key = self.new_key(key)
else:
key = self.new_key(os.path.basename(fh.name))
return key.set_contents_from_file(fh)

def has_metadata(self, field=None):
"""Check if metadata is available locally.

Expand Down
45 changes: 44 additions & 1 deletion gcloud/storage/test_bucket.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import io

import unittest2


Expand Down Expand Up @@ -266,6 +268,41 @@ def set_contents_from_filename(self, filename):
bucket.upload_file(FILENAME, KEY)
self.assertEqual(_uploaded, [(bucket, KEY, FILENAME)])

def test_upload_file_object_no_key(self):
from gcloud.test_credentials import _Monkey
from gcloud.storage import bucket as MUT
FILENAME = 'file.txt'
FILEOBJECT = MockFile(FILENAME)
_uploaded = []
class _Key(object):
def __init__(self, bucket, name):
self._bucket = bucket
self._name = name
def set_contents_from_file(self, fh):
_uploaded.append((self._bucket, self._name, fh))
bucket = self._makeOne()
with _Monkey(MUT, Key=_Key):
bucket.upload_file_object(FILEOBJECT)
self.assertEqual(_uploaded, [(bucket, FILENAME, FILEOBJECT)])

def test_upload_file_object_explicit_key(self):
from gcloud.test_credentials import _Monkey
from gcloud.storage import bucket as MUT
FILENAME = 'file.txt'
FILEOBJECT = MockFile(FILENAME)
KEY = 'key'
_uploaded = []
class _Key(object):
def __init__(self, bucket, name):
self._bucket = bucket
self._name = name
def set_contents_from_file(self, fh):
_uploaded.append((self._bucket, self._name, fh))
bucket = self._makeOne()
with _Monkey(MUT, Key=_Key):
bucket.upload_file_object(FILEOBJECT, KEY)
self.assertEqual(_uploaded, [(bucket, KEY, FILEOBJECT)])

def test_has_metdata_none_set(self):
NONESUCH = 'nonesuch'
bucket = self._makeOne()
Expand Down Expand Up @@ -790,4 +827,10 @@ def delete_bucket(self, bucket, force=False):
if not self._delete_ok:
raise NotFoundError('miss', None)
return True



class MockFile(io.StringIO):
name = None
def __init__(self, name, buffer_ = None):
super(MockFile, self).__init__(buffer_)
self.name = name