diff --git a/pandora/backend/__init__.py b/pandora/api/__init__.py similarity index 100% rename from pandora/backend/__init__.py rename to pandora/api/__init__.py diff --git a/pandora/backend/admin.py b/pandora/api/admin.py similarity index 100% rename from pandora/backend/admin.py rename to pandora/api/admin.py diff --git a/pandora/backend/forms.py b/pandora/api/forms.py similarity index 100% rename from pandora/backend/forms.py rename to pandora/api/forms.py diff --git a/pandora/backend/management/__init__.py b/pandora/api/management/__init__.py similarity index 100% rename from pandora/backend/management/__init__.py rename to pandora/api/management/__init__.py diff --git a/pandora/backend/management/commands/__init__.py b/pandora/api/management/commands/__init__.py similarity index 100% rename from pandora/backend/management/commands/__init__.py rename to pandora/api/management/commands/__init__.py diff --git a/pandora/backend/migrations/0001_initial.py b/pandora/api/migrations/0001_initial.py similarity index 100% rename from pandora/backend/migrations/0001_initial.py rename to pandora/api/migrations/0001_initial.py diff --git a/pandora/backend/migrations/0002_poster.py b/pandora/api/migrations/0002_poster.py similarity index 100% rename from pandora/backend/migrations/0002_poster.py rename to pandora/api/migrations/0002_poster.py diff --git a/pandora/backend/migrations/0003_archive.py b/pandora/api/migrations/0003_archive.py similarity index 100% rename from pandora/backend/migrations/0003_archive.py rename to pandora/api/migrations/0003_archive.py diff --git a/pandora/backend/migrations/0004_add_dialog.py b/pandora/api/migrations/0004_add_dialog.py similarity index 100% rename from pandora/backend/migrations/0004_add_dialog.py rename to pandora/api/migrations/0004_add_dialog.py diff --git a/pandora/backend/migrations/0005_dialog_sort.py b/pandora/api/migrations/0005_dialog_sort.py similarity index 100% rename from pandora/backend/migrations/0005_dialog_sort.py rename to pandora/api/migrations/0005_dialog_sort.py diff --git a/pandora/backend/migrations/0006_poster.py b/pandora/api/migrations/0006_poster.py similarity index 100% rename from pandora/backend/migrations/0006_poster.py rename to pandora/api/migrations/0006_poster.py diff --git a/pandora/backend/migrations/0007_poster_url.py b/pandora/api/migrations/0007_poster_url.py similarity index 100% rename from pandora/backend/migrations/0007_poster_url.py rename to pandora/api/migrations/0007_poster_url.py diff --git a/pandora/backend/migrations/0008_stream.py b/pandora/api/migrations/0008_stream.py similarity index 100% rename from pandora/backend/migrations/0008_stream.py rename to pandora/api/migrations/0008_stream.py diff --git a/pandora/backend/migrations/0009_stream_info.py b/pandora/api/migrations/0009_stream_info.py similarity index 100% rename from pandora/backend/migrations/0009_stream_info.py rename to pandora/api/migrations/0009_stream_info.py diff --git a/pandora/backend/migrations/0010_add_posterurl.py b/pandora/api/migrations/0010_add_posterurl.py similarity index 100% rename from pandora/backend/migrations/0010_add_posterurl.py rename to pandora/api/migrations/0010_add_posterurl.py diff --git a/pandora/backend/migrations/0011_rename_movie.py b/pandora/api/migrations/0011_rename_movie.py similarity index 100% rename from pandora/backend/migrations/0011_rename_movie.py rename to pandora/api/migrations/0011_rename_movie.py diff --git a/pandora/backend/migrations/0012_auto__del_field_itemfind_all__del_field_itemfind_trivia__del_field_ite.py b/pandora/api/migrations/0012_auto__del_field_itemfind_all__del_field_itemfind_trivia__del_field_ite.py similarity index 100% rename from pandora/backend/migrations/0012_auto__del_field_itemfind_all__del_field_itemfind_trivia__del_field_ite.py rename to pandora/api/migrations/0012_auto__del_field_itemfind_all__del_field_itemfind_trivia__del_field_ite.py diff --git a/pandora/backend/migrations/0013_auto.py b/pandora/api/migrations/0013_auto.py similarity index 100% rename from pandora/backend/migrations/0013_auto.py rename to pandora/api/migrations/0013_auto.py diff --git a/pandora/backend/migrations/__init__.py b/pandora/api/migrations/__init__.py similarity index 100% rename from pandora/backend/migrations/__init__.py rename to pandora/api/migrations/__init__.py diff --git a/pandora/api/models.py b/pandora/api/models.py new file mode 100644 index 0000000..dc3eab4 --- /dev/null +++ b/pandora/api/models.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from item.models import * + diff --git a/pandora/api/urls.py b/pandora/api/urls.py new file mode 100644 index 0000000..fb0b40c --- /dev/null +++ b/pandora/api/urls.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from django.conf.urls.defaults import * + + +urlpatterns = patterns("api.views", + (r'^$', 'api'), +) + diff --git a/pandora/api/views.py b/pandora/api/views.py new file mode 100644 index 0000000..e4f1d53 --- /dev/null +++ b/pandora/api/views.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +from __future__ import division +import os.path +import re +from datetime import datetime +from urllib2 import unquote +import mimetypes + +from django import forms +from django.core.paginator import Paginator +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from django.db.models import Q, Avg, Count, Sum +from django.http import HttpResponse, Http404 +from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect +from django.template import RequestContext +from django.conf import settings + +try: + import simplejson as json +except ImportError: + from django.utils import simplejson as json + +from oxdjango.decorators import login_required_json +from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response +from oxdjango.http import HttpFileResponse +import ox + +import models +import utils +import tasks + +from user.models import getUserJSON +from user.views import api_login, api_logout, api_register, api_contact, api_recover, api_preferences, api_findUser + +from archive.views import api_update, api_upload, api_editFile + +from archive.models import File +from archive import extract + +from item.views import * + +def api(request): + if request.META['REQUEST_METHOD'] == "OPTIONS": + response = HttpResponse('') + response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}}) + response['Access-Control-Allow-Origin'] = '*' + return response + if not 'action' in request.POST: + return apidoc(request) + function = request.POST['action'] + #FIXME: possible to do this in f + #data = json.loads(request.POST['data']) + + f = globals().get('api_'+function, None) + if f: + response = f(request) + else: + response = render_to_json_response(json_response(status=400, + text='Unknown function %s' % function)) + response['Access-Control-Allow-Origin'] = '*' + return response + +def api_api(request): + ''' + returns list of all known api action + return {'status': {'code': int, 'text': string}, + 'data': {actions: ['api', 'hello', ...]}} + ''' + actions = globals().keys() + actions = map(lambda a: a[4:], filter(lambda a: a.startswith('api_'), actions)) + actions.sort() + return render_to_json_response(json_response({'actions': actions})) + +def api_hello(request): + ''' + return {'status': {'code': int, 'text': string}, + 'data': {user: object}} + ''' + #data = json.loads(request.POST['data']) + response = json_response({}) + if request.user.is_authenticated(): + response['data']['user'] = getUserJSON(request.user) + else: + response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'preferences': {}} + return render_to_json_response(response) + +def api_error(request): + ''' + trows 503 error + ''' + success = error_is_success + return render_to_json_response({}) + +def apidoc(request): + ''' + this is used for online documentation at http://127.0.0.1:8000/api/ + ''' + import sys + def trim(docstring): + if not docstring: + return '' + # Convert tabs to spaces (following the normal Python rules) + # and split into a list of lines: + lines = docstring.expandtabs().splitlines() + # Determine minimum indentation (first line doesn't count): + indent = sys.maxint + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + # Remove indentation (first line is special): + trimmed = [lines[0].strip()] + if indent < sys.maxint: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + # Strip off trailing and leading blank lines: + while trimmed and not trimmed[-1]: + trimmed.pop() + while trimmed and not trimmed[0]: + trimmed.pop(0) + # Return a single string: + return '\n'.join(trimmed) + + functions = filter(lambda x: x.startswith('api_'), globals().keys()) + api = [] + for f in sorted(functions): + api.append({ + 'name': f[4:], + 'doc': trim(globals()[f].__doc__).replace('\n', '
\n') + }) + context = RequestContext(request, {'api': api, + 'sitename': settings.SITENAME,}) + return render_to_response('api.html', context) + + + +''' + ajax html snapshots + http://code.google.com/web/ajaxcrawling/docs/html-snapshot.html +''' +def html_snapshot(request): + fragment = unquote(request.GET['_escaped_fragment_']) + url = request.build_absolute_uri('/ra') + url = 'http://'+settings.URL + response = HttpResponse('sorry, server side rendering for %s!#%s not yet implemented'%(url, fragment)) + return response diff --git a/pandora/app/views.py b/pandora/app/views.py index 5cd2e0b..f527340 100644 --- a/pandora/app/views.py +++ b/pandora/app/views.py @@ -8,7 +8,7 @@ from oxdjango.shortcuts import json_response, render_to_json_response, get_objec import models -from backend.views import html_snapshot +from api.views import html_snapshot def intro(request): context = RequestContext(request, {'settings':settings}) diff --git a/pandora/archive/models.py b/pandora/archive/models.py index 6386b06..3bb8de3 100644 --- a/pandora/archive/models.py +++ b/pandora/archive/models.py @@ -22,8 +22,8 @@ from ox.normalize import canonicalTitle, canonicalName from firefogg import Firefogg import chardet -from backend import utils -from pandora.backend.models import Item +from item import utils +from item.models import Item import extract @@ -143,7 +143,7 @@ class File(models.Model): #upload and data handling video = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, '%s.webm'%settings.VIDEO_PROFILE)) - data = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, 'data.raw')) + data = models.FileField(null=True, blank=True, upload_to=lambda f, x: file_path(f, 'data.bin')) def contents(self): if self.data != None: diff --git a/pandora/archive/views.py b/pandora/archive/views.py index 8bb2374..28a0398 100644 --- a/pandora/archive/views.py +++ b/pandora/archive/views.py @@ -29,9 +29,9 @@ import ox import models -from backend.utils import oxid, parse_path -import backend.models -import backend.tasks +from item.utils import oxid, parse_path +import item.models +import item.tasks @login_required_json def api_removeVolume(request): @@ -114,7 +114,7 @@ def api_update(request): else: if not item: item_info = parse_path(folder) - item = backend.models.getItem(item_info) + item = item.models.getItem(item_info) file_object = models.File() file_object.oshash = oshash file_object.name = name @@ -223,7 +223,7 @@ def firefogg_upload(request): elif form.cleaned_data['done']: f.available = True f.save() - backend.tasks.updateStreams.delay(f.item.itemId) + item.tasks.updateStreams.delay(f.item.itemId) response['result'] = 1 response['done'] = 1 return render_to_json_response(response) diff --git a/pandora/item/__init__.py b/pandora/item/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pandora/backend/load.py b/pandora/item/load.py similarity index 100% rename from pandora/backend/load.py rename to pandora/item/load.py diff --git a/pandora/backend/managers.py b/pandora/item/managers.py similarity index 100% rename from pandora/backend/managers.py rename to pandora/item/managers.py diff --git a/pandora/backend/models.py b/pandora/item/models.py similarity index 100% rename from pandora/backend/models.py rename to pandora/item/models.py diff --git a/pandora/backend/tasks.py b/pandora/item/tasks.py similarity index 100% rename from pandora/backend/tasks.py rename to pandora/item/tasks.py diff --git a/pandora/item/tests.py b/pandora/item/tests.py new file mode 100644 index 0000000..2247054 --- /dev/null +++ b/pandora/item/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/pandora/backend/urls.py b/pandora/item/urls.py similarity index 89% rename from pandora/backend/urls.py rename to pandora/item/urls.py index c4c188d..78dc1b7 100644 --- a/pandora/backend/urls.py +++ b/pandora/item/urls.py @@ -4,7 +4,7 @@ from django.conf.urls.defaults import * -urlpatterns = patterns("backend.views", +urlpatterns = patterns("item.views", (r'^(?P.*)/frame/(?P\d+)/(?P[0-9\.,]+).jpg$', 'frame'), (r'^(?P.*)/(?P.*.webm)$', 'video'), (r'^(?P.*)/(?P.*.mp4)$', 'video'), @@ -12,6 +12,5 @@ urlpatterns = patterns("backend.views", (r'^(?P.*)/poster\.(?Plarge)\.jpg$', 'poster'), (r'^(?P.*)/poster\.jpg$', 'poster'), (r'^(?P.*)/timelines/(?P.+)\.(?P\d+)\.(?P\d+)\.png$', 'timeline'), - (r'^api/$', 'api'), ) diff --git a/pandora/backend/utils.py b/pandora/item/utils.py similarity index 100% rename from pandora/backend/utils.py rename to pandora/item/utils.py diff --git a/pandora/backend/views.py b/pandora/item/views.py similarity index 81% rename from pandora/backend/views.py rename to pandora/item/views.py index 43c14ed..6dc469c 100644 --- a/pandora/backend/views.py +++ b/pandora/item/views.py @@ -32,66 +32,10 @@ import utils import tasks from user.models import getUserJSON -from user.views import api_login, api_logout, api_register, api_contact, api_recover, api_preferences, api_findUser - -from archive.views import api_update, api_upload, api_editFile from archive.models import File from archive import extract - -def api(request): - if request.META['REQUEST_METHOD'] == "OPTIONS": - response = HttpResponse('') - response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}}) - response['Access-Control-Allow-Origin'] = '*' - return response - if not 'action' in request.POST: - return apidoc(request) - function = request.POST['action'] - #FIXME: possible to do this in f - #data = json.loads(request.POST['data']) - - f = globals().get('api_'+function, None) - if f: - response = f(request) - else: - response = render_to_json_response(json_response(status=400, - text='Unknown function %s' % function)) - response['Access-Control-Allow-Origin'] = '*' - return response - -def api_api(request): - ''' - returns list of all known api action - return {'status': {'code': int, 'text': string}, - 'data': {actions: ['api', 'hello', ...]}} - ''' - actions = globals().keys() - actions = map(lambda a: a[4:], filter(lambda a: a.startswith('api_'), actions)) - actions.sort() - return render_to_json_response(json_response({'actions': actions})) - -def api_hello(request): - ''' - return {'status': {'code': int, 'text': string}, - 'data': {user: object}} - ''' - #data = json.loads(request.POST['data']) - response = json_response({}) - if request.user.is_authenticated(): - response['data']['user'] = getUserJSON(request.user) - else: - response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'preferences': {}} - return render_to_json_response(response) - -def api_error(request): - ''' - trows 503 error - ''' - success = error_is_success - return render_to_json_response({}) - def _order_query(qs, sort, prefix='sort__'): order_by = [] if len(sort) == 1: @@ -489,46 +433,6 @@ def api_getImdbId(request): response = json_response(status=404, text='not found') return render_to_json_response(response) -def apidoc(request): - ''' - this is used for online documentation at http://127.0.0.1:8000/api/ - ''' - import sys - def trim(docstring): - if not docstring: - return '' - # Convert tabs to spaces (following the normal Python rules) - # and split into a list of lines: - lines = docstring.expandtabs().splitlines() - # Determine minimum indentation (first line doesn't count): - indent = sys.maxint - for line in lines[1:]: - stripped = line.lstrip() - if stripped: - indent = min(indent, len(line) - len(stripped)) - # Remove indentation (first line is special): - trimmed = [lines[0].strip()] - if indent < sys.maxint: - for line in lines[1:]: - trimmed.append(line[indent:].rstrip()) - # Strip off trailing and leading blank lines: - while trimmed and not trimmed[-1]: - trimmed.pop() - while trimmed and not trimmed[0]: - trimmed.pop(0) - # Return a single string: - return '\n'.join(trimmed) - - functions = filter(lambda x: x.startswith('api_'), globals().keys()) - api = [] - for f in sorted(functions): - api.append({ - 'name': f[4:], - 'doc': trim(globals()[f].__doc__).replace('\n', '
\n') - }) - context = RequestContext(request, {'api': api, - 'sitename': settings.SITENAME,}) - return render_to_response('api.html', context) ''' media delivery @@ -577,14 +481,3 @@ def video(request, id, profile): content_type = path.endswith('.mp4') and 'video/mp4' or 'video/webm' return HttpFileResponse(path, content_type=content_type) - -''' - ajax html snapshots - http://code.google.com/web/ajaxcrawling/docs/html-snapshot.html -''' -def html_snapshot(request): - fragment = unquote(request.GET['_escaped_fragment_']) - url = request.build_absolute_uri('/ra') - url = 'http://'+settings.URL - response = HttpResponse('sorry, server side rendering for %s!#%s not yet implemented'%(url, fragment)) - return response diff --git a/pandora/settings.py b/pandora/settings.py index 7a3feb6..5a08561 100644 --- a/pandora/settings.py +++ b/pandora/settings.py @@ -117,7 +117,8 @@ INSTALLED_APPS = ( 'djcelery', 'app', - 'backend', + 'api', + 'item', 'archive', 'user', 'torrent', diff --git a/pandora/urls.py b/pandora/urls.py index 2065b75..b2a3975 100644 --- a/pandora/urls.py +++ b/pandora/urls.py @@ -24,7 +24,8 @@ urlpatterns = patterns('', (r'^file/(?P.*)$', 'archive.views.lookup_file'), (r'^r/(?P.*)$', 'user.views.recover'), - (r'', include('backend.urls')), + (r'^api/$', include('api.urls')), + (r'', include('item.urls')), # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: