From: Joar Wandborg Date: Mon, 5 Sep 2011 20:06:47 +0000 (+0200) Subject: Feature #571 - Closing storage objects - Removed closing(), renamed X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=c2b862d1349b5ecc6d787000edb209525b719751;p=mediagoblin.git Feature #571 - Closing storage objects - Removed closing(), renamed StorageObjectWrapper, added with-support to CloudFilesStorageWrapper * Removed custom `closing()` method * Removed usage of `closing()` in process_media/__init__.py * Renamed StorageObjectWrapper -> CloudFilesStorageObject wrapper In my first version of the StorageOjbectWrapper it was located inside the CloudFilesStorage object, things have changed since then but there has been no renaming, thank you Elrond for the good point. * CloudFilesStorageObjectWrapper now supports context manager methods such as `__enter__()` and `__exit__()` (and `close()`) --- diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py index db913f5f..2b9eed6e 100644 --- a/mediagoblin/process_media/__init__.py +++ b/mediagoblin/process_media/__init__.py @@ -16,7 +16,6 @@ import Image -from contextlib import contextmanager from celery.task import Task from celery import registry @@ -36,14 +35,6 @@ def create_pub_filepath(entry, filename): filename]) -@contextmanager -def closing(callback): - try: - yield callback - finally: - pass - - ################################ # Media processing initial steps ################################ @@ -66,7 +57,7 @@ class ProcessMedia(Task): except BaseProcessingFail, exc: mark_entry_failed(entry[u'_id'], exc) return - + entry['state'] = u'processed' entry.save() @@ -144,7 +135,7 @@ def process_image(entry): thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg') thumb_file = mgg.public_store.get_file(thumb_filepath, 'w') - with closing(thumb_file): + with thumb_file: thumb.save(thumb_file, "JPEG", quality=90) # If the size of the original file exceeds the specified size of a `medium` @@ -162,7 +153,7 @@ def process_image(entry): medium_filepath = create_pub_filepath(entry, 'medium.jpg') medium_file = mgg.public_store.get_file(medium_filepath, 'w') - with closing(medium_file): + with medium_file: medium.save(medium_file, "JPEG", quality=90) medium_processed = True @@ -172,8 +163,8 @@ def process_image(entry): with queued_file: original_filepath = create_pub_filepath(entry, queued_filepath[-1]) - - with closing(mgg.public_store.get_file(original_filepath, 'wb')) as original_file: + + with mgg.public_store.get_file(original_filepath, 'wb') as original_file: original_file.write(queued_file.read()) mgg.queue_store.delete_file(queued_filepath) diff --git a/mediagoblin/storage.py b/mediagoblin/storage.py index e3df72be..b376ead0 100644 --- a/mediagoblin/storage.py +++ b/mediagoblin/storage.py @@ -291,7 +291,7 @@ class CloudFilesStorage(StorageInterface): if mimetype: obj.content_type = mimetype[0] - return StorageObjectWrapper(obj, *args, **kwargs) + return CloudFilesStorageObjectWrapper(obj, *args, **kwargs) def delete_file(self, filepath): # TODO: Also delete unused directories if empty (safely, with @@ -305,7 +305,7 @@ class CloudFilesStorage(StorageInterface): self._resolve_filepath(filepath)]) -class StorageObjectWrapper(): +class CloudFilesStorageObjectWrapper(): """ Wrapper for python-cloudfiles's cloudfiles.storage_object.Object used to circumvent the mystic `medium.jpg` corruption issue, where @@ -322,11 +322,38 @@ class StorageObjectWrapper(): return self.storage_object.read(*args, **kwargs) def write(self, data, *args, **kwargs): + """ + write data to the cloudfiles storage object + + The original motivation for this wrapper is to ensure + that buffered writing to a cloudfiles storage object does not overwrite + any preexisting data. + + Currently this method does not support any write modes except "append". + However if we should need it it would be easy implement. + """ if self.storage_object.size and type(data) == str: data = self.read() + data self.storage_object.write(data, *args, **kwargs) + def close(self): + pass + + def __enter__(self): + """ + Context Manager API implementation + http://docs.python.org/library/stdtypes.html#context-manager-types + """ + return self + + def __exit__(self, *args): + """ + Context Manger API implementation + see self.__enter__() + """ + self.close() + # ------------ # MountStorage