commit ebb54b0b36148140dad067e00ee8f77900086e89
Author: Antony Chazapis <chazapis@gmail.com>
Date:   Thu Nov 24 12:01:47 2011 +0200

    Merge public app into api.
    
    Fixes $1678

diff --git a/README.upgrade b/README.upgrade
index 3f6f39b..4ab21fe 100644
--- a/README.upgrade
+++ b/README.upgrade
@@ -14,8 +14,8 @@ UPGRADE
 
 0.7.10 -> 0.7.11
 ----------------
+* Add 'south', remove 'pithos.public' in INSTALLED_APPS in settings.py
 * Install python-django-south
-* Add 'south' in INSTALLED_APPS in settings.py
 * Setup south:
     python manage.py syncdb
     python manage.py migrate im 0001 --fake
diff --git a/pithos/api/public.py b/pithos/api/public.py
new file mode 100644
index 0000000..86191df
--- /dev/null
+++ b/pithos/api/public.py
@@ -0,0 +1,152 @@
+# Copyright 2011 GRNET S.A. All rights reserved.
+# 
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+# 
+#   1. Redistributions of source code must retain the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer.
+# 
+#   2. Redistributions in binary form must reproduce the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer in the documentation and/or other materials
+#      provided with the distribution.
+# 
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# 
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+import logging
+
+from django.http import HttpResponse
+
+from pithos.api.faults import (Fault, BadRequest, ItemNotFound)
+from pithos.api.util import (put_object_headers, update_manifest_meta,
+    validate_modification_preconditions, validate_matching_preconditions,
+    object_data_response, api_method)
+from pithos.api.short_url import decode_url
+
+
+logger = logging.getLogger(__name__)
+
+
+def public_demux(request, v_public):
+    if request.method == 'HEAD':
+        return public_meta(request, v_public)
+    elif request.method == 'GET':
+        return public_read(request, v_public)
+    else:
+        return method_not_allowed(request)
+
+@api_method('HEAD', user_required=False)
+def public_meta(request, v_public):
+    # Normal Response Codes: 204
+    # Error Response Codes: serviceUnavailable (503),
+    #                       itemNotFound (404),
+    #                       badRequest (400)
+    
+    try:
+        v_account, v_container, v_object = request.backend.get_public(request.user_uniq,
+                                                    decode_url(v_public))
+        meta = request.backend.get_object_meta(request.user_uniq, v_account,
+                                                    v_container, v_object)
+        public = request.backend.get_object_public(request.user_uniq, v_account,
+                                                    v_container, v_object)
+    except:
+        raise ItemNotFound('Object does not exist')
+    
+    if not public:
+        raise ItemNotFound('Object does not exist')
+    update_manifest_meta(request, v_account, meta)
+    
+    response = HttpResponse(status=200)
+    put_object_headers(response, meta, True)
+    return response
+
+@api_method('GET', user_required=False)
+def public_read(request, v_public):
+    # Normal Response Codes: 200, 206
+    # Error Response Codes: serviceUnavailable (503),
+    #                       rangeNotSatisfiable (416),
+    #                       preconditionFailed (412),
+    #                       itemNotFound (404),
+    #                       badRequest (400),
+    #                       notModified (304)
+    
+    print '***', v_public
+    try:
+        v_account, v_container, v_object = request.backend.get_public(request.user_uniq,
+                                                    decode_url(v_public))
+        meta = request.backend.get_object_meta(request.user_uniq, v_account,
+                                                    v_container, v_object)
+        public = request.backend.get_object_public(request.user_uniq, v_account,
+                                                    v_container, v_object)
+    except:
+        raise ItemNotFound('Object does not exist')
+    
+    if not public:
+        raise ItemNotFound('Object does not exist')
+    update_manifest_meta(request, v_account, meta)
+    
+    # Evaluate conditions.
+    validate_modification_preconditions(request, meta)
+    try:
+        validate_matching_preconditions(request, meta)
+    except NotModified:
+        response = HttpResponse(status=304)
+        response['ETag'] = meta['ETag']
+        return response
+    
+    sizes = []
+    hashmaps = []
+    if 'X-Object-Manifest' in meta:
+        try:
+            src_container, src_name = split_container_object_string('/' + meta['X-Object-Manifest'])
+            objects = request.backend.list_objects(request.user_uniq, v_account,
+                                src_container, prefix=src_name, virtual=False)
+        except:
+            raise ItemNotFound('Object does not exist')
+        
+        try:
+            for x in objects:
+                s, h = request.backend.get_object_hashmap(request.user_uniq,
+                                        v_account, src_container, x[0], x[1])
+                sizes.append(s)
+                hashmaps.append(h)
+        except:
+            raise ItemNotFound('Object does not exist')
+    else:
+        try:
+            s, h = request.backend.get_object_hashmap(request.user_uniq, v_account,
+                                                        v_container, v_object)
+            sizes.append(s)
+            hashmaps.append(h)
+        except:
+            raise ItemNotFound('Object does not exist')
+    
+    if 'Content-Disposition' not in meta:
+        name = v_object.rstrip('/').split('/')[-1]
+        if not name:
+            name = v_public
+        meta['Content-Disposition'] = 'attachment; filename=%s' % (name,)
+    
+    return object_data_response(request, sizes, hashmaps, meta, True)
+
+@api_method(user_required=False)
+def method_not_allowed(request, **v_args):
+    raise ItemNotFound('Object does not exist')
diff --git a/pithos/public/__init__.py b/pithos/public/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/pithos/public/functions.py b/pithos/public/functions.py
deleted file mode 100644
index fc14068..0000000
--- a/pithos/public/functions.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-import logging
-
-from django.http import HttpResponse
-
-from pithos.api.faults import (Fault, BadRequest, ItemNotFound)
-from pithos.api.util import (put_object_headers, update_manifest_meta,
-    validate_modification_preconditions, validate_matching_preconditions,
-    object_data_response, api_method)
-from pithos.api.short_url import decode_url
-
-
-logger = logging.getLogger(__name__)
-
-
-def public_demux(request, v_public):
-    if request.method == 'HEAD':
-        return public_meta(request, v_public)
-    elif request.method == 'GET':
-        return public_read(request, v_public)
-    else:
-        return method_not_allowed(request)
-
-@api_method('HEAD', user_required=False)
-def public_meta(request, v_public):
-    # Normal Response Codes: 204
-    # Error Response Codes: serviceUnavailable (503),
-    #                       itemNotFound (404),
-    #                       badRequest (400)
-    
-    try:
-        v_account, v_container, v_object = request.backend.get_public(request.user_uniq,
-                                                    decode_url(v_public))
-        meta = request.backend.get_object_meta(request.user_uniq, v_account,
-                                                    v_container, v_object)
-        public = request.backend.get_object_public(request.user_uniq, v_account,
-                                                    v_container, v_object)
-    except:
-        raise ItemNotFound('Object does not exist')
-    
-    if not public:
-        raise ItemNotFound('Object does not exist')
-    update_manifest_meta(request, v_account, meta)
-    
-    response = HttpResponse(status=200)
-    put_object_headers(response, meta, True)
-    return response
-
-@api_method('GET', user_required=False)
-def public_read(request, v_public):
-    # Normal Response Codes: 200, 206
-    # Error Response Codes: serviceUnavailable (503),
-    #                       rangeNotSatisfiable (416),
-    #                       preconditionFailed (412),
-    #                       itemNotFound (404),
-    #                       badRequest (400),
-    #                       notModified (304)
-    
-    try:
-        v_account, v_container, v_object = request.backend.get_public(request.user_uniq,
-                                                    decode_url(v_public))
-        meta = request.backend.get_object_meta(request.user_uniq, v_account,
-                                                    v_container, v_object)
-        public = request.backend.get_object_public(request.user_uniq, v_account,
-                                                    v_container, v_object)
-    except:
-        raise ItemNotFound('Object does not exist')
-    
-    if not public:
-        raise ItemNotFound('Object does not exist')
-    update_manifest_meta(request, v_account, meta)
-    
-    # Evaluate conditions.
-    validate_modification_preconditions(request, meta)
-    try:
-        validate_matching_preconditions(request, meta)
-    except NotModified:
-        response = HttpResponse(status=304)
-        response['ETag'] = meta['ETag']
-        return response
-    
-    sizes = []
-    hashmaps = []
-    if 'X-Object-Manifest' in meta:
-        try:
-            src_container, src_name = split_container_object_string('/' + meta['X-Object-Manifest'])
-            objects = request.backend.list_objects(request.user_uniq, v_account,
-                                src_container, prefix=src_name, virtual=False)
-        except:
-            raise ItemNotFound('Object does not exist')
-        
-        try:
-            for x in objects:
-                s, h = request.backend.get_object_hashmap(request.user_uniq,
-                                        v_account, src_container, x[0], x[1])
-                sizes.append(s)
-                hashmaps.append(h)
-        except:
-            raise ItemNotFound('Object does not exist')
-    else:
-        try:
-            s, h = request.backend.get_object_hashmap(request.user_uniq, v_account,
-                                                        v_container, v_object)
-            sizes.append(s)
-            hashmaps.append(h)
-        except:
-            raise ItemNotFound('Object does not exist')
-    
-    if 'Content-Disposition' not in meta:
-        name = v_object.rstrip('/').split('/')[-1]
-        if not name:
-            name = v_public
-        meta['Content-Disposition'] = 'attachment; filename=%s' % (name,)
-    
-    return object_data_response(request, sizes, hashmaps, meta, True)
-
-@api_method(user_required=False)
-def method_not_allowed(request, **v_args):
-    raise ItemNotFound('Object does not exist')
diff --git a/pithos/public/models.py b/pithos/public/models.py
deleted file mode 100644
index 71a8362..0000000
--- a/pithos/public/models.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.db import models
-
-# Create your models here.
diff --git a/pithos/public/urls.py b/pithos/public/urls.py
deleted file mode 100644
index 613ed3e..0000000
--- a/pithos/public/urls.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django.conf.urls.defaults import *
-
-urlpatterns = patterns('pithos.public.functions',
-    (r'^$', 'method_not_allowed'),
-    (r'^(?P<v_public>.+?)/?$', 'public_demux')
-)
diff --git a/pithos/public/views.py b/pithos/public/views.py
deleted file mode 100644
index 60f00ef..0000000
--- a/pithos/public/views.py
+++ /dev/null
@@ -1 +0,0 @@
-# Create your views here.
diff --git a/pithos/settings.py.dist b/pithos/settings.py.dist
index 1c791de..61855f2 100644
--- a/pithos/settings.py.dist
+++ b/pithos/settings.py.dist
@@ -153,7 +153,6 @@ INSTALLED_APPS = (
 #    'django.contrib.admindocs',
     'pithos.im',
     'pithos.api',
-    'pithos.public',
     'pithos.ui',
     'south'
 )
diff --git a/pithos/urls.py b/pithos/urls.py
index dea4a01..17cc94b 100644
--- a/pithos/urls.py
+++ b/pithos/urls.py
@@ -37,7 +37,7 @@ from django.conf.urls.defaults import include, patterns
 urlpatterns = patterns('',
     (r'^v1(?:$|/)', include('pithos.api.urls')),
     (r'^v1\.0(?:$|/)', include('pithos.api.urls')),
-    (r'^public(?:$|/)', include('pithos.public.urls')),
+    (r'^public/(?P<v_public>.+?)/?$', 'pithos.api.public.public_demux'),
     (r'^im/', include('pithos.im.urls')),
     (r'^ui', include('pithos.ui.urls'))
 )
