commit a8326bef39303a8a42897b1b46f94590b0db2a12
Author: Antony Chazapis <chazapis@gmail.com>
Date:   Fri Jul 22 16:03:32 2011 +0300

    Conditional object create/update.

diff --git a/pithos/api/functions.py b/pithos/api/functions.py
index ece0173..9231631 100644
--- a/pithos/api/functions.py
+++ b/pithos/api/functions.py
@@ -189,6 +189,8 @@ def account_meta(request, v_account):
     except NotAllowedError:
         raise Unauthorized('Access denied')
     
+    validate_modification_preconditions(request, meta)
+    
     response = HttpResponse(status=204)
     put_account_headers(response, meta, groups)
     return response
@@ -303,6 +305,8 @@ def container_meta(request, v_account, v_container):
     except NameError:
         raise ItemNotFound('Container does not exist')
     
+    validate_modification_preconditions(request, meta)
+    
     response = HttpResponse(status=204)
     put_container_headers(response, meta, policy)
     return response
@@ -322,6 +326,8 @@ def container_create(request, v_account, v_container):
         ret = 201
     except NotAllowedError:
         raise Unauthorized('Access denied')
+    except ValueError:
+        raise BadRequest('Invalid policy header')
     except NameError:
         ret = 202
     
@@ -519,6 +525,15 @@ def object_meta(request, v_account, v_container, v_object):
     update_sharing_meta(permissions, v_account, v_container, v_object, meta)
     update_public_meta(public, meta)
     
+    # Evaluate conditions.
+    validate_modification_preconditions(request, meta)
+    try:
+        validate_matching_preconditions(request, meta)
+    except NotModified:
+        response = HttpResponse(status=304)
+        response['ETag'] = meta['hash']
+        return response
+    
     response = HttpResponse(status=200)
     put_object_headers(response, meta)
     return response
@@ -652,6 +667,16 @@ def object_write(request, v_account, v_container, v_object):
     if not request.GET.get('format'):
         request.serialization = 'text'
     
+    # Evaluate conditions.
+    if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'):
+        try:
+            meta = backend.get_object_meta(request.user, v_account, v_container, v_object)
+        except NotAllowedError:
+            raise Unauthorized('Access denied')
+        except NameError:
+            meta = {}
+        validate_matching_preconditions(request, meta)
+    
     copy_from = request.META.get('HTTP_X_COPY_FROM')
     move_from = request.META.get('HTTP_X_MOVE_FROM')
     if copy_from or move_from:
@@ -800,6 +825,18 @@ def object_copy(request, v_account, v_container, v_object):
         dest_container, dest_name = split_container_object_string(dest_path)
     except ValueError:
         raise BadRequest('Invalid Destination header')
+    
+    # Evaluate conditions.
+    if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'):
+        src_version = request.META.get('HTTP_X_SOURCE_VERSION')
+        try:
+            meta = backend.get_object_meta(request.user, v_account, v_container, v_object, src_version)
+        except NotAllowedError:
+            raise Unauthorized('Access denied')
+        except (NameError, IndexError):
+            raise ItemNotFound('Container or object does not exist')
+        validate_matching_preconditions(request, meta)
+    
     copy_or_move_object(request, v_account, v_container, v_object, dest_container, dest_name, move=False)
     return HttpResponse(status=201)
 
@@ -818,6 +855,17 @@ def object_move(request, v_account, v_container, v_object):
         dest_container, dest_name = split_container_object_string(dest_path)
     except ValueError:
         raise BadRequest('Invalid Destination header')
+    
+    # Evaluate conditions.
+    if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'):
+        try:
+            meta = backend.get_object_meta(request.user, v_account, v_container, v_object)
+        except NotAllowedError:
+            raise Unauthorized('Access denied')
+        except NameError:
+            raise ItemNotFound('Container or object does not exist')
+        validate_matching_preconditions(request, meta)
+    
     copy_or_move_object(request, v_account, v_container, v_object, dest_container, dest_name, move=True)
     return HttpResponse(status=201)
 
@@ -840,6 +888,11 @@ def object_update(request, v_account, v_container, v_object):
         raise Unauthorized('Access denied')
     except NameError:
         raise ItemNotFound('Object does not exist')
+    
+    # Evaluate conditions.
+    if request.META.get('HTTP_IF_MATCH') or request.META.get('HTTP_IF_NONE_MATCH'):
+        validate_matching_preconditions(request, prev_meta)
+    
     # If replacing, keep previous values of 'Content-Type' and 'hash'.
     replace = True
     if 'update' in request.GET:
