diff --git a/pandora/annotaion/models.py b/pandora/annotaion/models.py
index fa0af1ed8..bf62525b8 100644
--- a/pandora/annotaion/models.py
+++ b/pandora/annotaion/models.py
@@ -2,49 +2,32 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
-from datetime import datetime
-import os.path
-import math
-import random
-import re
-import subprocess
-import unicodedata
-from glob import glob
-
from django.db import models
-from django.db.models import Q
from django.contrib.auth.models import User
-from django.core.files.base import ContentFile
-from django.conf import settings
-
-from ox.django import fields
-import ox
-from ox.utils import json
-from ox import stripTags
-from ox.normalize import canonicalTitle, canonicalName
import utils
class Layer(models.Model):
+
class Meta:
ordering = ('position', )
name = models.CharField(null=True, max_length=255, unique=True)
title = models.CharField(null=True, max_length=255)
- #text, string, string from list(fixme), event, place, person
+ #text, string, string from list(fixme), event, place, person
type = models.CharField(null=True, max_length=255)
position = models.IntegerField(default=0)
- overlapping = models.BooleanField(default=True)
- enabled = models.BooleanField(default=True)
+ overlapping = models.BooleanField(default=True)
+ enabled = models.BooleanField(default=True)
- enabled = models.BooleanField(default=True)
- public = models.BooleanField(default=True) #false=users only see there own bins
- subtitle = models.BooleanField(default=True) #bis can be displayed as subtitle, only one bin
+ enabled = models.BooleanField(default=True)
+ public = models.BooleanField(default=True) #false=users only see there own bins
+ subtitle = models.BooleanField(default=True) #bis can be displayed as subtitle, only one bin
- find = models.BooleanField(default=True)
- #words / item duration(wpm), total words, cuts per minute, cuts, number of annotations, number of annotations/duration
+ find = models.BooleanField(default=True)
+ #words / item duration(wpm), total words, cuts per minute, cuts, number of annotations, number of annotations/duration
sort = models.CharField(null=True, max_length=255)
def properties(self):
@@ -61,7 +44,9 @@ class Layer(models.Model):
def __unicode__(self):
return self.title
+
class Annotation(models.Model):
+
#FIXME: here having a item,start index would be good
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@@ -77,9 +62,9 @@ class Annotation(models.Model):
def editable(self, user):
if user.is_authenticated():
- if obj.user == user.id or user.has_perm('0x.admin'):
+ if self.user == user or user.has_perm('0x.admin'):
return True
- if user.groups.filter(id__in=obj.groups.all()).count() > 0:
+ if user.groups.filter(id__in=self.groups.all()).count() > 0:
return True
return False
@@ -102,4 +87,3 @@ class Annotation(models.Model):
def __unicode__(self):
return "%s/%s-%s" %(self.item, self.start, self.stop)
-
diff --git a/pandora/annotaion/tests.py b/pandora/annotaion/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/annotaion/tests.py
+++ b/pandora/annotaion/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/annotaion/utils.py b/pandora/annotaion/utils.py
index 133d874e4..79ace73df 100644
--- a/pandora/annotaion/utils.py
+++ b/pandora/annotaion/utils.py
@@ -1,19 +1,22 @@
# -*- coding: utf-8 -*-
# ci:si:et:sw=4:sts=4:ts=4
+import re
+import ox
+
def html_parser(text, nofollow=True):
text = text.replace('', '__i__').replace('', '__/i__')
text = text.replace('', '__b__').replace('', '__/b__')
#truns links into wiki links, make sure to only take http links
text = re.sub('(.*?)', '[\\1 \\2]', text)
- text = escape(text)
+ text = ox.escape(text)
text = text.replace('__i__', '').replace('__/i__', '')
text = text.replace('__b__', '').replace('__/b__', '')
if nofollow:
nofollow_rel = ' rel="nofollow"'
else:
nofollow_rel = ''
-
+
links = re.compile('(\[(http.*?) (.*?)\])').findall(text)
for t, link, txt in links:
link = link.replace('http', '__LINK__').replace('.', '__DOT__')
@@ -24,8 +27,8 @@ def html_parser(text, nofollow=True):
link = link.replace('http', '__LINK__').replace('.', '__DOT__')
ll = '%s' % (link, nofollow_rel, link)
text = text.replace(t, ll)
-
- text = urlize(text, nofollow=nofollow)
+
+ text = ox.urlize(text, nofollow=nofollow)
#inpage links
text = re.sub('\[(/.+?) (.+?)\]', '\\2', text)
@@ -33,4 +36,3 @@ def html_parser(text, nofollow=True):
text = text.replace('__LINK__', 'http').replace('__DOT__', '.')
text = text.replace("\n", '
')
return text
-
diff --git a/pandora/annotaion/views.py b/pandora/annotaion/views.py
index ac7e1228a..1f2c4770e 100644
--- a/pandora/annotaion/views.py
+++ b/pandora/annotaion/views.py
@@ -1,27 +1,10 @@
# -*- 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
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
-import ox
import models
from api.actions import actions
@@ -48,6 +31,7 @@ def findAnnotation(request):
return render_to_json_response(response)
actions.register(findAnnotation)
+
@login_required_json
def addAnnotation(request):
'''
@@ -67,18 +51,18 @@ def addAnnotation(request):
data = json.loads(request.POST['data'])
for key in ('item', 'layer', 'start', 'end', 'value'):
if key not in data:
- return render_to_json_response(json_response(status=400, text='invalid data'))
+ return render_to_json_response(json_response(status=400,
+ text='invalid data'))
item = get_object_or_404_json(models.Item, itemId=data['item'])
layer = get_object_or_404_json(models.Layer, layerId=data['layer'])
-
+
annotation = models.Annotation(
item=item,
layer=layer,
user=request.user,
start=float(data['start']), end=float(data['end']),
- value=data['value']
- )
+ value=data['value'])
annotation.save()
response = json_response()
response['data']['annotation'] = annotation.json()
@@ -88,6 +72,7 @@ def addAnnotation(request):
return render_to_json_response(response)
actions.register(addAnnotation)
+
@login_required_json
def removeAnnotation(request):
'''
@@ -103,6 +88,7 @@ def removeAnnotation(request):
return render_to_json_response(response)
actions.register(removeAnnotation)
+
@login_required_json
def editAnnotation(request):
'''
@@ -129,4 +115,3 @@ def editAnnotation(request):
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(editAnnotation)
-
diff --git a/pandora/api/actions.py b/pandora/api/actions.py
index 6f5ad5280..4fca44c5b 100644
--- a/pandora/api/actions.py
+++ b/pandora/api/actions.py
@@ -18,7 +18,7 @@ def autodiscover():
import_module('%s.views'%app)
except:
if module_has_submodule(mod, 'views'):
- raise
+ raise
def trim(docstring):
@@ -46,8 +46,11 @@ def trim(docstring):
# Return a single string:
return '\n'.join(trimmed)
+
class ApiActions(dict):
+
def __init__(self):
+
def api(request):
'''
returns list of all known api action
@@ -56,7 +59,8 @@ class ApiActions(dict):
'''
actions = self.keys()
actions.sort()
- return render_to_json_response(json_response({'actions': actions}))
+ response = json_response({'actions': actions})
+ return render_to_json_response(response)
self['api'] = api
def apidoc(request):
diff --git a/pandora/api/views.py b/pandora/api/views.py
index 028ff1b9a..4f0c6c766 100644
--- a/pandora/api/views.py
+++ b/pandora/api/views.py
@@ -1,54 +1,32 @@
# -*- 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.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
-from ox.utils import json
-from ox.django.decorators import login_required_json
-from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
-import ox
-
-import models
+from ox.django.shortcuts import render_to_json_response, json_response
from pandora.user.models import get_user_json
-from pandora.archive.models import File
-from pandora.archive import extract
-
-
from actions import actions
+
def api(request):
if request.META['REQUEST_METHOD'] == "OPTIONS":
- response = HttpResponse('')
- response = render_to_json_response({'status': {'code': 200, 'text': 'use POST'}})
+ response = render_to_json_response({'status': {'code': 200,
+ 'text': 'use POST'}})
response['Access-Control-Allow-Origin'] = '*'
return response
if not 'action' in request.POST:
methods = actions.keys()
api = []
for f in sorted(methods):
- api.append({
- 'name': f,
- 'doc': actions.doc(f).replace('\n', '
\n')
- })
+ api.append({'name': f,
+ 'doc': actions.doc(f).replace('\n', '
\n')})
context = RequestContext(request, {'api': api,
- 'sitename': settings.SITENAME,})
+ 'sitename': settings.SITENAME})
return render_to_response('api.html', context)
function = request.POST['action']
#FIXME: possible to do this in f
@@ -63,6 +41,7 @@ def api(request):
response['Access-Control-Allow-Origin'] = '*'
return response
+
def hello(request):
'''
return {'status': {'code': int, 'text': string},
@@ -73,15 +52,17 @@ def hello(request):
if request.user.is_authenticated():
response['data']['user'] = get_user_json(request.user)
else:
- response['data']['user'] = {'name': 'Guest', 'group': 'guest', 'preferences': {}}
+ response['data']['user'] = {'name': 'Guest',
+ 'group': 'guest',
+ 'preferences': {}}
return render_to_json_response(response)
actions.register(hello)
+
def error(request):
'''
- this action is used to test api error codes, it should return a 503 error
+ this action is used to test api error codes, it should return a 503 error
'''
success = error_is_success
return render_to_json_response({})
actions.register(error)
-
diff --git a/pandora/app/admin.py b/pandora/app/admin.py
index 428d4a3db..90cbd79f8 100644
--- a/pandora/app/admin.py
+++ b/pandora/app/admin.py
@@ -5,6 +5,7 @@ from django.contrib import admin
import models
+
class PageAdmin(admin.ModelAdmin):
search_fields = ['name', 'body']
@@ -15,4 +16,3 @@ class SiteSettingsAdmin(admin.ModelAdmin):
search_fields = ['key', 'value']
admin.site.register(models.SiteSettings, SiteSettingsAdmin)
-
diff --git a/pandora/app/models.py b/pandora/app/models.py
index b57bfd1a7..16bc42893 100644
--- a/pandora/app/models.py
+++ b/pandora/app/models.py
@@ -2,6 +2,7 @@
# vi:si:et:sw=4:sts=4:ts=4
from django.db import models
+
class Page(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@@ -11,10 +12,10 @@ class Page(models.Model):
def __unicode__(self):
return self.name
+
class SiteSettings(models.Model):
key = models.CharField(max_length=1024, unique=True)
value = models.TextField(blank=True)
def __unicode__(self):
return self.key
-
diff --git a/pandora/app/tests.py b/pandora/app/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/app/tests.py
+++ b/pandora/app/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/app/views.py b/pandora/app/views.py
index 82965bdba..c2e0b90ca 100644
--- a/pandora/app/views.py
+++ b/pandora/app/views.py
@@ -1,31 +1,32 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
-from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
+from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from ox.django.shortcuts import json_response, render_to_json_response, get_object_or_404_json
+from ox.utils import json
import models
-from item.models import siteJson
-
from api.actions import actions
+
def intro(request):
- context = RequestContext(request, {'settings':settings})
+ context = RequestContext(request, {'settings': settings})
return render_to_response('intro.html', context)
+
def index(request):
- context = RequestContext(request, {'settings':settings})
- if request.GET.get('_escaped_fragment_', None):
- return html_snapshot(request)
+ context = RequestContext(request, {'settings': settings})
return render_to_response('index.html', context)
+
def timeline(request):
- context = RequestContext(request, {'settings':settings})
+ context = RequestContext(request, {'settings': settings})
return render_to_response('timeline.html', context)
+
def getPage(request):
data = json.loads(request.POST['data'])
name = data['page']
@@ -34,6 +35,7 @@ def getPage(request):
return render_to_json_response(response)
actions.register(getPage)
+
def site_json(request):
'''
return render_to_json_response(siteJson())
@@ -41,6 +43,7 @@ def site_json(request):
siteSettings = {}
for s in models.SiteSettings.objects.all():
siteSettings[s.key] = s.value
- context = RequestContext(request, {'settings':settings, 'siteSettings': siteSettings})
- return render_to_response('site.json', context, mimetype="application/javascript")
-
+ context = RequestContext(request, {'settings': settings,
+ 'siteSettings': siteSettings})
+ return render_to_response('site.json', context,
+ mimetype="application/javascript")
diff --git a/pandora/archive/admin.py b/pandora/archive/admin.py
index 48c82a1c0..a8057b7b7 100644
--- a/pandora/archive/admin.py
+++ b/pandora/archive/admin.py
@@ -6,6 +6,7 @@ from django.contrib import admin
from forms import FileAdminForm, InstanceAdminForm
import models
+
class FileAdmin(admin.ModelAdmin):
search_fields = ['name', 'video_codec']
list_display = ['available', 'is_main', '__unicode__', 'itemId']
@@ -18,9 +19,9 @@ class FileAdmin(admin.ModelAdmin):
admin.site.register(models.File, FileAdmin)
+
class InstanceAdmin(admin.ModelAdmin):
search_fields = ['name', 'folder', 'volume__name']
form = InstanceAdminForm
admin.site.register(models.Instance, InstanceAdmin)
-
diff --git a/pandora/archive/extract.py b/pandora/archive/extract.py
index 95a641287..87241eaaa 100644
--- a/pandora/archive/extract.py
+++ b/pandora/archive/extract.py
@@ -3,33 +3,31 @@
from __future__ import division, with_statement
import os
-from os.path import abspath, join, dirname, exists
+from os.path import exists
import fractions
import subprocess
-import sys
-import shutil
import tempfile
import time
-import re
import math
from glob import glob
import numpy as np
import Image
-import ox
-from ox.utils import json
img_extension='jpg'
FFMPEG2THEORA = 'ffmpeg2theora'
+
class AspectRatio(fractions.Fraction):
+
def __new__(cls, numerator, denominator=None):
if not denominator:
ratio = map(int, numerator.split(':'))
- if len(ratio) == 1: ratio.append(1)
+ if len(ratio) == 1:
+ ratio.append(1)
numerator = ratio[0]
denominator = ratio[1]
#if its close enough to the common aspect ratios rather use that
@@ -45,6 +43,7 @@ class AspectRatio(fractions.Fraction):
def ratio(self):
return "%d:%d" % (self.numerator, self.denominator)
+
def stream(video, target, profile, info):
if not os.path.exists(target):
fdir = os.path.dirname(target)
@@ -118,8 +117,8 @@ def stream(video, target, profile, info):
bpp = 0.17
fps = AspectRatio(info['video'][0]['framerate'])
- width = int(dar * height)
- width += width % 2
+ width = int(dar * height)
+ width += width % 2
bitrate = height*width*fps*bpp/1000
aspect = dar.ratio
@@ -184,7 +183,7 @@ def stream(video, target, profile, info):
'-me_range', '16',
'-g', '250', #FIXME: should this be related to fps?
'-keyint_min', '25', #FIXME: should this be related to fps?
- '-sc_threshold','40',
+ '-sc_threshold', '40',
'-i_qfactor', '0.71',
'-qmin', '10', '-qmax', '51',
'-qdiff', '4'
@@ -200,19 +199,20 @@ def stream(video, target, profile, info):
if format == 'mp4':
cmd += ["%s.mp4"%target]
else:
- cmd += ['-f','webm', target]
+ cmd += ['-f', 'webm', target]
print cmd
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
p.communicate()
if format == 'mp4':
- cmd = ['qt-faststart', "%s.mp4"%target, target]
+ cmd = ['qt-faststart', "%s.mp4"%target, target]
print cmd
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
p.communicate()
os.unlink("%s.mp4"%target)
return True
+
def run_command(cmd, timeout=10):
#print cmd
p = subprocess.Popen(cmd, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
@@ -226,6 +226,7 @@ def run_command(cmd, timeout=10):
killedpid, stat = os.waitpid(p.pid, os.WNOHANG)
return p.returncode
+
def frame(videoFile, frame, position, width=128, redo=False):
'''
params:
@@ -243,6 +244,7 @@ def frame(videoFile, frame, position, width=128, redo=False):
cmd = ['oxframe', '-i', videoFile, '-o', frame, '-p', str(position), '-x', str(width)]
run_command(cmd)
+
def resize_image(image_source, image_output, width=None, size=None):
if exists(image_source):
source = Image.open(image_source).convert('RGB')
@@ -257,7 +259,7 @@ def resize_image(image_source, image_output, width=None, size=None):
height = size
width = int(height * (float(source_width) / source_height))
width = width - width % 2
-
+
else:
height = int(width / (float(source_width) / source_height))
height = height - height % 2
@@ -269,12 +271,13 @@ def resize_image(image_source, image_output, width=None, size=None):
output = source.resize((width, height), resize_method)
output.save(image_output)
+
def timeline(video, prefix):
cmd = ['oxtimeline', '-i', video, '-o', prefix]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.wait()
-#stats based on timeline images
+
def average_color(prefix):
height = 64
width = 1500
@@ -294,10 +297,12 @@ def average_color(prefix):
color += p
return list(map(float, color))
+
def get_distance(rgb0, rgb1):
dst = math.sqrt(pow(rgb0[0] - rgb1[0], 2) + pow(rgb0[0] - rgb1[0], 2) + pow(rgb0[0] - rgb1[0], 2))
return dst / math.sqrt(3 * pow(255, 2))
+
def cuts(prefix):
cuts = []
fps = 25
@@ -324,6 +329,7 @@ def cuts(prefix):
cuts.append(frame / fps)
return cuts
+
def divide(num, by):
# >>> divide(100, 3)
# [33, 33, 34]
@@ -334,9 +340,10 @@ def divide(num, by):
arr.append(div + (i > by - 1 - mod))
return arr
+
def timeline_strip(item, cuts, info, prefix):
_debug = False
- duration = info['duration']
+ duration = info['duration']
video_height = info['video'][0]['height']
video_width = info['video'][0]['width']
video_ratio = video_width / video_height
@@ -392,6 +399,7 @@ def timeline_strip(item, cuts, info, prefix):
print 'writing', timeline_file
timeline_image.save(timeline_file)
+
def chop(video, start, end):
t = end - start
tmp = tempfile.mkdtemp()
@@ -401,7 +409,7 @@ def chop(video, start, end):
'-y',
'-i', video,
'-ss', '%.3f'%start,
- '-t','%.3f'%t,
+ '-t', '%.3f'%t,
'-vcodec', 'copy',
'-acodec', 'copy',
'-f', 'webm',
diff --git a/pandora/archive/forms.py b/pandora/archive/forms.py
index 59758ad5f..291d77c51 100644
--- a/pandora/archive/forms.py
+++ b/pandora/archive/forms.py
@@ -1,4 +1,4 @@
-from ajax_filtered_fields.forms import AjaxManyToManyField, ForeignKeyByLetter
+from ajax_filtered_fields.forms import ForeignKeyByLetter
from django.conf import settings
from django import forms
@@ -10,6 +10,8 @@ ajax_filtered_js = (
settings.STATIC_URL + 'js/jquery/jquery.js',
settings.STATIC_URL + 'js/ajax_filtered_fields.js',
)
+
+
class FileAdminForm(forms.ModelForm):
item = ForeignKeyByLetter(models.Item, field_name='itemId')
@@ -28,4 +30,3 @@ class InstanceAdminForm(forms.ModelForm):
class Media:
js = ajax_filtered_js
-
diff --git a/pandora/archive/models.py b/pandora/archive/models.py
index eb9a788a2..cd5793a08 100644
--- a/pandora/archive/models.py
+++ b/pandora/archive/models.py
@@ -1,31 +1,23 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
-from datetime import datetime
+
import os.path
-import random
import re
import time
from django.db import models
-from django.db.models import Q
from django.contrib.auth.models import User
-from django.core.files.base import ContentFile
-from django.utils import simplejson as json
from django.conf import settings
from ox.django import fields
import ox
-from ox import stripTags
-from ox.normalize import canonicalTitle, canonicalName
-from firefogg import Firefogg
+from ox.normalize import canonicalTitle
import chardet
from item import utils
from item.models import Item
-import extract
-
class File(models.Model):
created = models.DateTimeField(auto_now_add=True)
@@ -37,7 +29,7 @@ class File(models.Model):
item = models.ForeignKey(Item, related_name='files')
name = models.CharField(max_length=2048, default="") # canoncial path/file
- sort_name = models.CharField(max_length=2048, default="") # sort path/file name
+ sort_name = models.CharField(max_length=2048, default="") # sort name
part = models.CharField(default="", max_length=255)
version = models.CharField(default="", max_length=255) # sort path/file name
@@ -146,13 +138,14 @@ class File(models.Model):
return None
def srt(self):
+
def _detectEncoding(fp):
- bomDict={ # bytepattern : name
- (0x00, 0x00, 0xFE, 0xFF) : "utf_32_be",
- (0xFF, 0xFE, 0x00, 0x00) : "utf_32_le",
- (0xFE, 0xFF, None, None) : "utf_16_be",
- (0xFF, 0xFE, None, None) : "utf_16_le",
- (0xEF, 0xBB, 0xBF, None) : "utf_8",
+ bomDict={ # bytepattern : name
+ (0x00, 0x00, 0xFE, 0xFF): "utf_32_be",
+ (0xFF, 0xFE, 0x00, 0x00): "utf_32_le",
+ (0xFE, 0xFF, None, None): "utf_16_be",
+ (0xFF, 0xFE, None, None): "utf_16_le",
+ (0xEF, 0xBB, 0xBF, None): "utf_8",
}
# go to beginning of file and get the first 4 bytes
@@ -162,15 +155,15 @@ class File(models.Model):
# try bom detection using 4 bytes, 3 bytes, or 2 bytes
bomDetection = bomDict.get((byte1, byte2, byte3, byte4))
- if not bomDetection :
+ if not bomDetection:
bomDetection = bomDict.get((byte1, byte2, byte3, None))
- if not bomDetection :
+ if not bomDetection:
bomDetection = bomDict.get((byte1, byte2, None, None))
## if BOM detected, we're done :-)
fp.seek(oldFP)
- if bomDetection :
- return bomDetection
+ if bomDetection:
+ return bomDetection
encoding = 'latin-1'
#more character detecting magick using http://chardet.feedparser.org/
@@ -221,7 +214,9 @@ class File(models.Model):
return True
return False
+
class Volume(models.Model):
+
class Meta:
unique_together = ("user", "name")
@@ -234,7 +229,9 @@ class Volume(models.Model):
def __unicode__(self):
return u"%s's %s"% (self.user, self.name)
+
class Instance(models.Model):
+
class Meta:
unique_together = ("name", "folder", "volume")
@@ -258,12 +255,15 @@ class Instance(models.Model):
def itemId(self):
return File.objects.get(oshash=self.oshash).itemId
+
def frame_path(frame, name):
ext = os.path.splitext(name)[-1]
name = "%s%s" % (frame.position, ext)
return frame.file.path(name)
+
class Frame(models.Model):
+
class Meta:
unique_together = ("file", "position")
created = models.DateTimeField(auto_now_add=True)
@@ -282,5 +282,3 @@ class Frame(models.Model):
def __unicode__(self):
return u'%s at %s' % (self.file, self.position)
-
-
diff --git a/pandora/archive/tasks.py b/pandora/archive/tasks.py
index c6a9f6e16..f96c9764e 100644
--- a/pandora/archive/tasks.py
+++ b/pandora/archive/tasks.py
@@ -1,17 +1,15 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
-from datetime import timedelta
import os
-import re
-from celery.decorators import task, periodic_task
+from celery.decorators import task
-from item.utils import oxid, parse_path
+from item.utils import parse_path
from item.models import get_item
-import item.tasks
import models
+
@task(ignore_resulsts=True, queue='default')
def update_files(user, volume, files):
user = models.User.objects.get(username=user)
@@ -33,9 +31,9 @@ def update_files(user, volume, files):
same_folder = models.Instance.objects.filter(folder=folder, volume=volume)
if same_folder.count() > 0:
- item = same_folder[0].file.item
+ i = same_folder[0].file.item
else:
- item = None
+ i = None
path = os.path.join(folder, name)
@@ -48,7 +46,7 @@ def update_files(user, volume, files):
setattr(instance, key, f[key])
updated=True
if updated:
- instance.save()
+ instance.save()
else:
#look if oshash is known
file_objects = models.File.objects.filter(oshash=oshash)
@@ -56,13 +54,13 @@ def update_files(user, volume, files):
file_object = file_objects[0]
#new oshash, add to database
else:
- if not item:
+ if not i:
item_info = parse_path(folder)
- item = get_item(item_info)
+ i = get_item(item_info)
file_object = models.File()
file_object.oshash = oshash
file_object.name = name
- file_object.item = item
+ file_object.item = i
file_object.save()
instance = models.Instance()
instance.volume = volume
@@ -74,4 +72,3 @@ def update_files(user, volume, files):
#remove deleted files
#FIXME: can this have any bad consequences? i.e. on the selction of used item files.
models.Instance.objects.filter(volume=volume).exclude(file__oshash__in=all_files).delete()
-
diff --git a/pandora/archive/tests.py b/pandora/archive/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/archive/tests.py
+++ b/pandora/archive/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/archive/views.py b/pandora/archive/views.py
index cc7dd12bf..3f2cf5ed2 100644
--- a/pandora/archive/views.py
+++ b/pandora/archive/views.py
@@ -2,29 +2,18 @@
# 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.shortcuts import get_object_or_404, redirect
from django.conf import settings
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
from ox.django.views import task_status
-import ox
-from item.utils import oxid, parse_path
+from item.utils import parse_path
from item.models import get_item
import item.tasks
from api.actions import actions
@@ -47,6 +36,7 @@ def removeVolume(request):
return render_to_json_response(response)
actions.register(removeVolume)
+
@login_required_json
def update(request):
'''
@@ -111,12 +101,14 @@ def update(request):
return render_to_json_response(response)
actions.register(update)
+
@login_required_json
def encodingProfile(request):
response = json_response({'profile': settings.VIDEO_PROFILE})
return render_to_json_response(response)
actions.register(encodingProfile)
+
@login_required_json
def upload(request):
'''
@@ -157,11 +149,13 @@ def upload(request):
return render_to_json_response(response)
actions.register(upload)
+
class VideoChunkForm(forms.Form):
chunk = forms.FileField()
chunkId = forms.IntegerField(required=False)
done = forms.IntegerField(required=False)
+
@login_required_json
def firefogg_upload(request):
profile = request.GET['profile']
@@ -189,7 +183,7 @@ def firefogg_upload(request):
#FIXME: this fails badly if rabbitmq goes down
try:
t = item.tasks.update_streams.delay((f.item.itemId))
- data['resultUrl'] = t.task_id
+ response['resultUrl'] = t.task_id
except:
pass
response['result'] = 1
@@ -213,6 +207,7 @@ def firefogg_upload(request):
response = json_response(status=400, text='this request requires POST')
return render_to_json_response(response)
+
@login_required_json
def taskStatus(request):
#FIXME: should check if user has permissions to get status
@@ -223,6 +218,7 @@ def taskStatus(request):
return render_to_json_response(response)
actions.register(taskStatus)
+
@login_required_json
def editFile(request):
'''
@@ -257,6 +253,7 @@ def editFile(request):
return render_to_json_response(response)
actions.register(editFile)
+
def lookup_file(request, oshash):
f = get_object_or_404(models.File, oshash=oshash)
return redirect(f.item.get_absolute_url())
@@ -270,34 +267,34 @@ def fileInfo(request):
'data': {imdbId:string }}
'''
if 'data' in request.POST:
- oshash = json.loads(request.POST['data'])
- elif 'oshash' in request.GET:
- oshash = request.GET['oshash']
+ oshash = json.loads(request.POST['data'])
+ elif 'oshash' in request.GET:
+ oshash = request.GET['oshash']
f = models.ItemFile.objects.get(oshash=oshash)
response = {'data': f.json()}
return render_to_json_response(response)
actions.register(fileInfo)
def subtitles(request):
- '''
- param data
- oshash string
- language string
- subtitle string
- return
- if no language is provided:
- {data: {languages: array}}
- if language is set:
- {data: {subtitle: string}}
- if subtitle is set:
- saves subtitle for given language
- '''
+ '''
+ param data
+ oshash string
+ language string
+ subtitle string
+ return
+ if no language is provided:
+ {data: {languages: array}}
+ if language is set:
+ {data: {subtitle: string}}
+ if subtitle is set:
+ saves subtitle for given language
+ '''
if 'data' in request.POST:
- data = json.loads(request.POST['data'])
- oshash = data['oshash']
- language = data.get('language', None)
- srt = data.get('subtitle', None)
- if srt:
+ data = json.loads(request.POST['data'])
+ oshash = data['oshash']
+ language = data.get('language', None)
+ srt = data.get('subtitle', None)
+ if srt:
user = request.user
sub = models.Subtitles.objects.get_or_create(user, oshash, language)
sub.srt = srt
@@ -307,8 +304,8 @@ def subtitles(request):
if language:
q = models.Subtitles.objects.filter(item_file__oshash=oshash, language=language)
if q.count() > 0:
- response['data']['subtitle'] = q[0].srt
- return render_to_json_response(response)
+ response['data']['subtitle'] = q[0].srt
+ return render_to_json_response(response)
l = models.Subtitles.objects.filter(item_file__oshash=oshash).values('language')
response['data']['languages'] = [f['language'] for f in l]
return render_to_json_response(response)
diff --git a/pandora/date/admin.py b/pandora/date/admin.py
index b1141f0a0..a02f41859 100644
--- a/pandora/date/admin.py
+++ b/pandora/date/admin.py
@@ -9,4 +9,3 @@ import models
class DateAdmin(admin.ModelAdmin):
search_fields = ['name']
admin.site.register(models.Date, DateAdmin)
-
diff --git a/pandora/date/managers.py b/pandora/date/managers.py
index 9a7e4e99f..78333b5c2 100644
--- a/pandora/date/managers.py
+++ b/pandora/date/managers.py
@@ -1,15 +1,11 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
-import re
-from ox.utils import json
-from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Manager
-
-import models
+
class DateManager(Manager):
+
def get_query_set(self):
return super(DateManager, self).get_query_set()
diff --git a/pandora/date/models.py b/pandora/date/models.py
index ac44ed098..fc4057d8c 100644
--- a/pandora/date/models.py
+++ b/pandora/date/models.py
@@ -3,13 +3,12 @@
from __future__ import division, with_statement
from django.db import models
-from django.db.models import Q
-from django.conf import settings
from ox.django import fields
import managers
+
class Date(models.Model):
'''
Dates are dates in time that can be once or recurring,
@@ -41,4 +40,3 @@ class Date(models.Model):
self.name_sort = self.name
self.name_find = self.name + '||'.join(self.aliases)
super(Date, self).save(*args, **kwargs)
-
diff --git a/pandora/date/tests.py b/pandora/date/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/date/tests.py
+++ b/pandora/date/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/date/views.py b/pandora/date/views.py
index 348f56c6f..7c68ac178 100644
--- a/pandora/date/views.py
+++ b/pandora/date/views.py
@@ -1,32 +1,15 @@
# -*- 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
from ox.utils import json
-
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
-import ox
import models
from api.actions import actions
+
@login_required_json
def addDate(request):
data = json.loads(request.POST['data'])
@@ -39,6 +22,7 @@ def addDate(request):
return render_to_json_response(response)
actions.register(addDate)
+
@login_required_json
def editDate(request):
'''
@@ -69,17 +53,19 @@ def editDate(request):
return render_to_json_response(response)
actions.register(editDate)
+
@login_required_json
def removeDate(request):
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(removeDate)
+
def findDate(request):
'''
param data
{'query': query, 'sort': array, 'range': array}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
sort: array of key, operator dics
@@ -102,7 +88,7 @@ def findDate(request):
Positions
param data
{'query': query, 'ids': []}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
ids: ids of dates for which positions are required
@@ -111,8 +97,7 @@ Positions
response = json_response(status=200, text='ok')
response['data']['places'] = []
#FIXME: add coordinates to limit search
- for p in Dates.objects.find(data['query']):
+ for p in models.Date.objects.find(data['query']):
response['data']['dates'].append(p.json())
return render_to_json_response(response)
actions.register(findDate)
-
diff --git a/pandora/item/admin.py b/pandora/item/admin.py
index 09daa8f31..0561b70af 100644
--- a/pandora/item/admin.py
+++ b/pandora/item/admin.py
@@ -5,6 +5,7 @@ from django.contrib import admin
import models
+
class ItemAdmin(admin.ModelAdmin):
search_fields = ['itemId', 'data', 'external_data']
list_display = ['available', 'itemId', '__unicode__']
@@ -12,8 +13,7 @@ class ItemAdmin(admin.ModelAdmin):
admin.site.register(models.Item, ItemAdmin)
+
class PropertyAdmin(admin.ModelAdmin):
search_fields = ['name', 'title']
admin.site.register(models.Property, PropertyAdmin)
-
-
diff --git a/pandora/item/forms.py b/pandora/item/forms.py
index dc56ffea5..664b728bb 100644
--- a/pandora/item/forms.py
+++ b/pandora/item/forms.py
@@ -1,8 +1,5 @@
from ajax_filtered_fields.forms import AjaxManyToManyField, ForeignKeyByLetter
from django.conf import settings
-from django import forms
-
-import models
ajax_filtered_js = (
settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js",
diff --git a/pandora/item/managers.py b/pandora/item/managers.py
index 167bc2513..06f0d3ba2 100644
--- a/pandora/item/managers.py
+++ b/pandora/item/managers.py
@@ -1,14 +1,9 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
-import re
from datetime import datetime
-from urllib2 import unquote
-from ox.utils import json
-from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Manager
-
+
import models
@@ -21,6 +16,7 @@ def keyType(key):
return "float"
return "string"
+
def parseCondition(condition):
'''
condition: {
@@ -33,13 +29,15 @@ def parseCondition(condition):
operator: "!="
}
...
- '''
+ '''
k = condition.get('key', 'all')
k = {'id': 'itemId'}.get(k, k)
- if not k: k = 'all'
+ if not k:
+ k = 'all'
v = condition['value']
op = condition.get('operator', None)
- if not op: op = '~'
+ if not op:
+ op = '~'
if op.startswith('!'):
op = op[1:]
exclude = True
@@ -66,16 +64,17 @@ def parseCondition(condition):
k = str(k)
if exclude:
if in_find and not k.startswith('itemId'):
- q = ~Q(**{'find__key':k, value_key:v})
+ q = ~Q(**{'find__key': k, value_key: v})
else:
- q = ~Q(**{k:v})
+ q = ~Q(**{k: v})
else:
if in_find and not k.startswith('itemId'):
- q = Q(**{'find__key':k, value_key:v})
+ q = Q(**{'find__key': k, value_key: v})
else:
- q = Q(**{k:v})
+ q = Q(**{k: v})
return q
else: #number or date
+
def parseDate(d):
while len(d) < 3:
d.append(1)
@@ -90,11 +89,11 @@ def parseCondition(condition):
if exclude: #!1960-1970
k1 = 'value__lt'
k2 = 'value__gte'
- return Q(**{'find__key': k, k1:v1})|Q(**{'find__key': k, k2:v2})
+ return Q(**{'find__key': k, k1: v1})|Q(**{'find__key': k, k2: v2})
else: #1960-1970
k1 = 'value__gte'
k2 = 'value__lt'
- return Q(**{'find__key': k, k1:v1})&Q(**{'find__key': k, k2:v2})
+ return Q(**{'find__key': k, k1: v1})&Q(**{'find__key': k, k2: v2})
else:
if keyType(k) == "date":
v = parseDate(v.split('.'))
@@ -113,9 +112,10 @@ def parseCondition(condition):
vk = str(vk)
if exclude: #!1960
- return ~Q(**{'find__key': k, vk:v})
+ return ~Q(**{'find__key': k, vk: v})
else: #1960
- return Q(**{'find__key': k, vk:v})
+ return Q(**{'find__key': k, vk: v})
+
def parseConditions(conditions, operator):
'''
@@ -135,16 +135,18 @@ def parseConditions(conditions, operator):
}
],
operator: "&"
- '''
+ '''
conn = []
for condition in conditions:
if 'conditions' in condition:
q = parseConditions(condition['conditions'],
condition.get('operator', '&'))
- if q: conn.append(q)
+ if q:
+ conn.append(q)
pass
else:
- if condition.get('value', '') != '' or condition.get('operator', '') == '=':
+ if condition.get('value', '') != '' or \
+ condition.get('operator', '') == '=':
conn.append(parseCondition(condition))
if conn:
q = conn[0]
@@ -156,7 +158,9 @@ def parseConditions(conditions, operator):
return q
return None
+
class ItemManager(Manager):
+
def get_query_set(self):
return super(ItemManager, self).get_query_set()
@@ -165,13 +169,14 @@ class ItemManager(Manager):
l = l.split(":")
only_public = True
if not user.is_anonymous():
- if len(l) == 1: l = [request.user.username] + l
- if request.user.username == l[0]:
+ if len(l) == 1:
+ l = [user.username] + l
+ if user.username == l[0]:
only_public = False
if len(l) == 2:
lqs = models.List.objects.filter(name=l[1], user__username=l[0])
if only_public:
- lqs = qls.filter(public=True)
+ lqs = lqs.filter(public=True)
if lqs.count() == 1:
qs = qs.filter(listitem__list__id=lqs[0].id)
return qs
@@ -196,7 +201,7 @@ class ItemManager(Manager):
],
operator: "&"
}
- '''
+ '''
#join query with operator
qs = self.get_query_set()
@@ -212,4 +217,3 @@ class ItemManager(Manager):
l = data.get('list', 'all')
qs = self.filter_list(qs, l, user)
return qs
-
diff --git a/pandora/item/models.py b/pandora/item/models.py
index 1f8cad830..6dda19510 100644
--- a/pandora/item/models.py
+++ b/pandora/item/models.py
@@ -4,26 +4,18 @@ from __future__ import division, with_statement
from datetime import datetime
import os.path
-import math
-import random
-import re
import subprocess
-import unicodedata
from glob import glob
from django.db import models
-from django.db.models import Q
-from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.utils import simplejson as json
from django.conf import settings
-from ox.django import fields
import ox
-from ox import stripTags
+from ox.django import fields
+from ox.normalize import canonicalTitle
import ox.web.imdb
-from ox.normalize import canonicalTitle, canonicalName
-from firefogg import Firefogg
import managers
import utils
@@ -31,23 +23,23 @@ import tasks
from archive import extract
from annotaion.models import Annotation, Layer
-from person.models import get_name_sort, Person
+from person.models import get_name_sort
def siteJson():
- r = {}
- r['findKeys'] = [{"id": "all", "title": "All"}]
- for p in Property.objects.all():
- if p.find:
- title = p.title
- if not title:
- title = p.name.capitalize()
- f = {"id": p.name, "title": title}
- f['autocomplete'] = p.autocomplete
- r['findKeys'].append(f)
-
- r['groups'] = [p.name for p in Property.objects.filter(group=True)]
- r['layers'] = [l.json() for l in Layer.objects.all()]
+ r = {}
+ r['findKeys'] = [{"id": "all", "title": "All"}]
+ for p in Property.objects.all():
+ if p.find:
+ title = p.title
+ if not title:
+ title = p.name.capitalize()
+ f = {"id": p.name, "title": title}
+ f['autocomplete'] = p.autocomplete
+ r['findKeys'].append(f)
+
+ r['groups'] = [p.name for p in Property.objects.filter(group=True)]
+ r['layers'] = [l.json() for l in Layer.objects.all()]
r['itemViews'] = [
{"id": "info", "title": "Info"},
@@ -81,28 +73,28 @@ def siteJson():
{"id": "public", "title": "Public Lists"},
{"id": "featured", "title": "Featured Lists"}
]
- r['sortKeys'] = []
- for p in Property.objects.exclude(sort=''):
- title = p.title
- if not title:
- title = p.name.capitalize()
+ r['sortKeys'] = []
+ for p in Property.objects.exclude(sort=''):
+ title = p.title
+ if not title:
+ title = p.name.capitalize()
- f = {
- "id": p.name,
- "title": title,
- "operator": p.operator,
- "align": p.align,
- "width": p.width,
- }
- if not p.removable:
- f['removable'] = False
- r['sortKeys'].append(f)
- r['sortKeys'].append([{"id": "id", "title": "ID", "operator": "", "align": "left", "width": 90}])
+ f = {
+ "id": p.name,
+ "title": title,
+ "operator": p.operator,
+ "align": p.align,
+ "width": p.width,
+ }
+ if not p.removable:
+ f['removable'] = False
+ r['sortKeys'].append(f)
+ r['sortKeys'].append([{"id": "id", "title": "ID", "operator": "", "align": "left", "width": 90}])
- r['totals'] = [{"id": "items"}]
- for p in Property.objects.filter(totals=True):
- f = {'id': p.name, 'admin': p.admin}
- r['totals'].append(f)
+ r['totals'] = [{"id": "items"}]
+ for p in Property.objects.filter(totals=True):
+ f = {'id': p.name, 'admin': p.admin}
+ r['totals'].append(f)
#FIXME: defaults should also be populated from properties
r["user"] = {
@@ -127,7 +119,8 @@ def siteJson():
},
"username": ""
}
- return r
+ return r
+
def get_item(info):
'''
@@ -176,28 +169,30 @@ def get_item(info):
item.save()
return item
+
class Property(models.Model):
+
class Meta:
ordering = ('position', )
verbose_name_plural = "Properties"
-
+
name = models.CharField(null=True, max_length=255, unique=True)
title = models.CharField(null=True, max_length=255, blank=True)
- #text, string, string from list(fixme), event, place, person
+ #text, string, string from list(fixme), event, place, person
type = models.CharField(null=True, max_length=255)
array = models.BooleanField(default=False)
position = models.IntegerField(default=0)
width = models.IntegerField(default=180)
align = models.CharField(null=True, max_length=255, default='left')
operator = models.CharField(null=True, max_length=5, default='', blank=True)
- default = models.BooleanField('Enabled by default', default=False)
- removable = models.BooleanField(default=True)
+ default = models.BooleanField('Enabled by default', default=False)
+ removable = models.BooleanField(default=True)
- #sort values: title, string, integer, float, date
+ #sort values: title, string, integer, float, date
sort = models.CharField(null=True, max_length=255, blank=True)
- find = models.BooleanField(default=False)
- autocomplete = models.BooleanField(default=False)
- group = models.BooleanField(default=False)
+ find = models.BooleanField(default=False)
+ autocomplete = models.BooleanField(default=False)
+ group = models.BooleanField(default=False)
totals = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
@@ -207,19 +202,20 @@ class Property(models.Model):
return self.title
return self.name
- def json(self):
- j = {}
- for key in ('type', 'sort', 'title', 'array', 'totals', 'admin'):
- value = getattr(self, key)
- if value:
- j[key] = value
- return j
+ def json(self):
+ j = {}
+ for key in ('type', 'sort', 'title', 'array', 'totals', 'admin'):
+ value = getattr(self, key)
+ if value:
+ j[key] = value
+ return j
def save(self, *args, **kwargs):
if not self.title:
self.title = self.name.capitalize()
super(Property, self).save(*args, **kwargs)
-
+
+
class Item(models.Model):
person_keys = ('director', 'writer', 'producer', 'editor', 'cinematographer', 'actor', 'character')
facet_keys = person_keys + ('country', 'language', 'genre', 'keyword')
@@ -228,7 +224,7 @@ class Item(models.Model):
published = models.DateTimeField(default=datetime.now, editable=False)
#only items that have data from files are available,
- #this is indicated by setting available to True
+ #this is indicated by setting available to True
available = models.BooleanField(default=False, db_index=True)
itemId = models.CharField(max_length=128, unique=True, blank=True)
oxdbId = models.CharField(max_length=42, unique=True, blank=True)
@@ -258,9 +254,9 @@ class Item(models.Model):
def edit(self, data):
#FIXME: how to map the keys to the right place to write them to?
- for key in data:
- if key != 'id':
- setattr(self.data, key, data[key])
+ for key in data:
+ if key != 'id':
+ setattr(self.data, key, data[key])
self.oxdb.save()
self.save()
@@ -339,11 +335,11 @@ class Item(models.Model):
#FIXME: this should not be used
_public_fields = {
'itemId': 'id',
- 'title': 'title',
- 'year': 'year',
+ 'title': 'title',
+ 'year': 'year',
- 'runtime': 'runtime',
- 'release_date': 'release_date',
+ 'runtime': 'runtime',
+ 'release_date': 'release_date',
'countries': 'country',
'directors': 'director',
@@ -402,7 +398,7 @@ class Item(models.Model):
s = self.streams.all()[0]
if s.video and s.info:
stream['duration'] = s.info['duration']
- if 'video' in s.info and s.info['video']:
+ if 'video' in s.info and s.info['video']:
stream['aspectRatio'] = s.info['video'][0]['width'] / s.info['video'][0]['height']
if settings.XSENDFILE or settings.XACCELREDIRECT:
stream['baseUrl'] = '/%s' % self.itemId
@@ -414,7 +410,7 @@ class Item(models.Model):
def get_layers(self):
layers = {}
layers['cuts'] = self.data.get('cuts', {})
-
+
layers['subtitles'] = {}
#FIXME: subtitles should be stored in Annotation
qs = self.files.filter(is_subtitle=True, is_main=True, available=True)
@@ -468,7 +464,9 @@ class Item(models.Model):
'''
Search related functions
'''
+
def update_find(self):
+
def save(key, value):
f, created = ItemFind.objects.get_or_create(item=self, key=key)
if value not in ('', '||'):
@@ -478,7 +476,7 @@ class Item(models.Model):
f.delete()
save('title', '\n'.join([self.get('title'), self.get('original_title', '')]))
-
+
#FIXME: filter us/int title
#f.title += ' '.join([t.title for t in self.alternative_titles()])
@@ -537,17 +535,17 @@ class Item(models.Model):
for key in ('keywords', 'genres', 'cast', 'summary', 'trivia', 'connections'):
setattr(s, key, len(self.get(key, '')))
-
+
s.itemId = self.itemId.replace('0x', 'xx')
s.rating = self.get('rating', -1)
s.votes = self.get('votes', -1)
# data from related subtitles
s.scenes = 0 #FIXME
- s.dialog = 0 #FIXME
- s.words = 0 #FIXME
- s.wpm = 0 #FIXME
- s.risk = 0 #FIXME
+ s.dialog = 0 #FIXME
+ s.words = 0 #FIXME
+ s.wpm = 0 #FIXME
+ s.risk = 0 #FIXME
# data from related files
videos = self.main_videos()
if len(videos) > 0:
@@ -574,7 +572,7 @@ class Item(models.Model):
s.color = int(sum(self.data.get('color', [])))
s.saturation = 0 #FIXME
s.brightness = 0 #FIXME
-
+
s.cuts = len(self.data.get('cuts', []))
if s.duration:
s.cutsperminute = s.cuts / (s.duration/60)
@@ -585,13 +583,13 @@ class Item(models.Model):
if not getattr(s, key):
setattr(s, key, u'zzzzzzzzzzzzzzzzzzzzzzzzz')
if not s.year:
- s.year_desc = '';
- s.year = '9999';
+ s.year_desc = ''
+ s.year = '9999'
#FIXME: also deal with number based rows like genre, keywords etc
s.save()
def update_facets(self):
- #FIXME: what to do with Unkown Director, Year, Country etc.
+ #FIXME: what to do with Unkown Director, Year, Country etc.
for key in self.facet_keys:
if key == 'actor':
current_values = [i[0] for i in self.get('actor', [])]
@@ -616,7 +614,7 @@ class Item(models.Model):
f, created = Facet.objects.get_or_create(key='year', value=year, value_sort=year, item=self)
else:
Facet.objects.filter(item=self, key='year').delete()
-
+
def path(self, name=''):
h = self.itemId
return os.path.join('items', h[:2], h[2:4], h[4:6], h[6:], name)
@@ -624,6 +622,7 @@ class Item(models.Model):
'''
Video related functions
'''
+
def frame(self, position, width=128):
stream = self.streams.filter(profile=settings.VIDEO_PROFILE+'.webm')[0]
path = os.path.join(settings.MEDIA_ROOT, self.path(), 'frames', "%d"%width, "%s.jpg"%position)
@@ -647,14 +646,14 @@ class Item(models.Model):
first.width == v.width and first.height == v.height:
return True
return False
- videos = filter(check, videos)
+ videos = filter(check, videos)
return videos
def update_streams(self):
files = {}
for f in self.main_videos():
files[utils.sort_title(f.name)] = f.video.path
-
+
#FIXME: how to detect if something changed?
if files:
stream, created = Stream.objects.get_or_create(item=self, profile='%s.webm' % settings.VIDEO_PROFILE)
@@ -693,6 +692,7 @@ class Item(models.Model):
'''
Poster related functions
'''
+
def update_poster_urls(self):
_current = {}
for s in settings.POSTER_SERVICES:
@@ -781,12 +781,14 @@ class Item(models.Model):
p.wait()
return posters.keys()
+
class ItemFind(models.Model):
"""
used to find items,
item.update_find populates this table
its used in manager.ItemManager
"""
+
class Meta:
unique_together = ("item", "key")
@@ -794,8 +796,9 @@ class ItemFind(models.Model):
key = models.CharField(max_length=200, db_index=True)
value = models.TextField(blank=True)
-#FIXME: make sort based on site.json
+
class ItemSort(models.Model):
+ #FIXME: make sort based on site.json
"""
used to sort items, all sort values are in here
"""
@@ -872,6 +875,7 @@ class ItemSort(models.Model):
return tuple(fields)
fields = classmethod(fields)
+
class Facet(models.Model):
item = models.ForeignKey('Item', related_name='facets')
key = models.CharField(max_length=200, db_index=True)
@@ -883,7 +887,9 @@ class Facet(models.Model):
self.value_sort = self.value
super(Facet, self).save(*args, **kwargs)
+
class Stream(models.Model):
+
class Meta:
unique_together = ("item", "profile")
@@ -899,7 +905,7 @@ class Stream(models.Model):
def path(self):
return self.item.path(self.profile)
-
+
def extract_derivatives(self):
if settings.VIDEO_H264:
profile = self.profile.replace('.webm', '.mp4')
@@ -945,7 +951,9 @@ class Stream(models.Model):
self.info = ox.avinfo(self.video.path)
super(Stream, self).save(*args, **kwargs)
+
class PosterUrl(models.Model):
+
class Meta:
unique_together = ("item", "service", "url")
ordering = ('-height', )
@@ -958,4 +966,3 @@ class PosterUrl(models.Model):
def __unicode__(self):
return u'%s %s %dx%d' % (unicode(self.item), self.service, self.width, self.height)
-
diff --git a/pandora/item/tasks.py b/pandora/item/tasks.py
index 2a90a681b..f1d12091f 100644
--- a/pandora/item/tasks.py
+++ b/pandora/item/tasks.py
@@ -11,16 +11,19 @@ import models
def cronjob(**kwargs):
print "do some cleanup stuff once a day"
+
@task(ignore_resulsts=True, queue='default')
def update_poster(itemId):
item = models.Item.objects.get(itemId=itemId)
item.make_poster(True)
+
@task(ignore_resulsts=True, queue='default')
def update_imdb(itemId):
item = models.Item.objects.get(itemId=itemId)
item.update_imdb()
+
@task(queue="encoding")
def update_streams(itemId):
'''
diff --git a/pandora/item/tests.py b/pandora/item/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/item/tests.py
+++ b/pandora/item/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/item/urls.py b/pandora/item/urls.py
index fee31d54a..458d29e0c 100644
--- a/pandora/item/urls.py
+++ b/pandora/item/urls.py
@@ -13,4 +13,3 @@ urlpatterns = patterns("item.views",
(r'^(?P[A-Z0-9].*)/poster\.jpg$', 'poster'),
(r'^(?P[A-Z0-9].*)/timelines/(?P.+)\.(?P\d+)\.(?P\d+)\.png$', 'timeline'),
)
-
diff --git a/pandora/item/utils.py b/pandora/item/utils.py
index 017baa1c1..d6d130505 100644
--- a/pandora/item/utils.py
+++ b/pandora/item/utils.py
@@ -2,17 +2,15 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
#
-import errno
from decimal import Decimal
import os
-import sys
import re
import hashlib
import unicodedata
import ox
import ox.iso
-from ox.normalize import normalizeName, normalizeTitle, canonicalTitle
+from ox.normalize import normalizeName, normalizeTitle
def parse_decimal(string):
@@ -22,11 +20,13 @@ def parse_decimal(string):
d = string.split('/')
return Decimal(d[0]) / Decimal(d[1])
+
def plural_key(term):
return {
'country': 'countries',
}.get(term, term + 's')
+
def oxid(title, directors, year='', seriesTitle='', episodeTitle='', season=0, episode=0):
director = ', '.join(directors)
oxid_value = u"\n".join([title, director, year])
@@ -38,6 +38,7 @@ def oxid(title, directors, year='', seriesTitle='', episodeTitle='', season=0, e
oxid += hashlib.sha1(oxid_value.encode('utf-8')).hexdigest()[:20]
return u"0x" + oxid
+
def oxdb_id(title, directors=[], year='', season='', episode='', episode_title='', episode_directors=[], episode_year=''):
# new id function, will replace oxid()
def get_hash(string):
@@ -51,11 +52,13 @@ def oxdb_id(title, directors=[], year='', season='', episode='', episode_title='
get_hash('\n'.join([str(episode), episode_director, episode_title, str(episode_year)]))[:8]
return u'0x' + oxdb_id
+
def oxdb_directors(director):
director = os.path.basename(os.path.dirname(director))
if director.endswith('_'):
director = "%s." % director[:-1]
directors = [normalizeName(d) for d in director.split('; ')]
+
def cleanup(director):
director = director.strip()
director = director.replace('Series', '')
@@ -65,6 +68,7 @@ def oxdb_directors(director):
directors = filter(None, [cleanup(d) for d in directors])
return directors
+
def oxdb_title(_title, searchTitle = False):
'''
normalize filename to get item title
@@ -83,7 +87,7 @@ def oxdb_title(_title, searchTitle = False):
else:
stitle = _title.split('.')[-2]
if stitle.startswith('Episode '):
- stitle = ''
+ stitle = ''
if searchTitle:
title = '"%s" %s' % (title, stitle)
else:
@@ -98,9 +102,11 @@ def oxdb_title(_title, searchTitle = False):
title = normalizeTitle(title)
return title
+
def oxdb_year(data):
return ox.findRe(data, '\.(\d{4})\.')
+
def oxdb_series_title(path):
seriesTitle = u''
if path.startswith('Series'):
@@ -111,6 +117,7 @@ def oxdb_series_title(path):
seriesTitle = t.split(" (S")[0]
return seriesTitle
+
def oxdb_episode_title(path):
episodeTitle = u''
ep = re.compile('.Episode \d+?\.(.*?)\.[a-zA-Z]').findall(path)
@@ -118,6 +125,7 @@ def oxdb_episode_title(path):
episodeTitle = ep[0]
return episodeTitle
+
def oxdb_season_episode(path):
season = 0
episode = 0
@@ -137,6 +145,7 @@ def oxdb_season_episode(path):
episode = int(se[0][1])
return (season, episode)
+
def oxdb_part(path):
part = 1
path = path.lower()
@@ -149,6 +158,7 @@ def oxdb_part(path):
part = p[0]
return part
+
def parse_path(path):
'''
expects path in the form
@@ -178,6 +188,7 @@ def parse_path(path):
episode_year='')
return r
+
def sort_title(title):
#title
title = re.sub(u'[\'!¿¡,\.;\-"\:\*\[\]]', '', title)
@@ -185,9 +196,8 @@ def sort_title(title):
#title = title.replace(u'Æ', 'Ae')
if isinstance(title, str):
title = unicode(title)
- title = unicodedata.normalize('NFKD',title)
+ title = unicodedata.normalize('NFKD', title)
#pad numbered titles
title = re.sub('(\d+)', lambda x: '%010d' % int(x.group(0)), title)
return title.strip()
-
diff --git a/pandora/item/views.py b/pandora/item/views.py
index 33882587d..40def7d30 100644
--- a/pandora/item/views.py
+++ b/pandora/item/views.py
@@ -2,19 +2,10 @@
# 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.db.models import 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.shortcuts import get_object_or_404, redirect
from django.conf import settings
from ox.utils import json
@@ -28,13 +19,13 @@ import models
import utils
import tasks
-from user.models import get_user_json
from archive.models import File
from archive import extract
from api.actions import actions
+
def _order_query(qs, sort, prefix='sort__'):
order_by = []
if len(sort) == 1:
@@ -44,7 +35,8 @@ def _order_query(qs, sort, prefix='sort__'):
sort.append({'operator': '+', 'key': 'director'})
for e in sort:
operator = e['operator']
- if operator != '-': operator = ''
+ if operator != '-':
+ operator = ''
key = {'id': 'itemId'}.get(e['key'], e['key'])
#FIXME: this should be a property of models.ItemSort!!!
if operator=='-' and key in ('title', 'director', 'writer', 'producer', 'editor', 'cinematographer', 'language', 'country', 'year'):
@@ -82,7 +74,7 @@ def find(request):
'sort': array,
'range': array
}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
sort: array of key, operator dics
@@ -111,7 +103,7 @@ Groups
'group': string,
'range': array
}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
range: result range, array [from, to]
@@ -134,7 +126,7 @@ Positions
'query': query,
'ids': []
}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
ids: ids of items for which positions are required
@@ -143,7 +135,7 @@ Positions
if settings.JSON_DEBUG:
print json.dumps(data, indent=2)
query = _parse_query(data, request.user)
-
+
response = json_response({})
if 'group' in query:
if 'sort' in query:
@@ -183,7 +175,7 @@ Positions
elif 'ids' in query:
#FIXME: this does not scale for larger results
qs = _order_query(query['qs'], query['sort'])
-
+
response['data']['positions'] = {}
ids = [j['itemId'] for j in qs.values('itemId')]
response['data']['positions'] = _get_positions(ids, query['ids'])
@@ -371,7 +363,8 @@ def getImdbId(request):
}
}
'''
- imdbId = ox.web.imdb.guess(search_title, r['director'], timeout=-1)
+ data = json.loads(request.POST['data'])
+ imdbId = ox.web.imdb.getImdbId(data['title'], data['director'], timeout=-1)
if imdbId:
response = json_response({'imdbId': imdbId})
else:
@@ -406,7 +399,8 @@ def poster(request, id, size=None):
else:
poster_path = item.poster.path
else:
- if not size: size='large'
+ if not size:
+ size='large'
return redirect('http://0xdb.org/%s/poster.%s.jpg' % (item.itemId, size))
poster_path = os.path.join(settings.STATIC_ROOT, 'png/posterDark.48.png')
return HttpFileResponse(poster_path, content_type='image/jpeg')
diff --git a/pandora/itemlist/models.py b/pandora/itemlist/models.py
index e116efb6f..0320c5785 100644
--- a/pandora/itemlist/models.py
+++ b/pandora/itemlist/models.py
@@ -2,29 +2,12 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
-from datetime import datetime
-import os.path
-import math
-import random
-import re
-import subprocess
-import unicodedata
-from glob import glob
-
from django.db import models
-from django.db.models import Q
from django.contrib.auth.models import User
-from django.core.files.base import ContentFile
-from django.utils import simplejson as json
-from django.conf import settings
-
-from ox.django import fields
-import ox
-from ox import stripTags
-from ox.normalize import canonicalTitle, canonicalName
class List(models.Model):
+
class Meta:
unique_together = ("user", "name")
@@ -33,7 +16,8 @@ class List(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=255)
public = models.BooleanField(default=False)
- items = models.ManyToManyField('item.Item', related_name='lists', through='ListItem')
+ items = models.ManyToManyField('item.Item', related_name='lists',
+ through='ListItem')
def add(self, item):
q = self.items.filter(id=item.id)
@@ -55,6 +39,7 @@ class List(models.Model):
return True
return False
+
class ListItem(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@@ -63,4 +48,3 @@ class ListItem(models.Model):
def __unicode__(self):
return u'%s in %s' % (self.item, self.list)
-
diff --git a/pandora/itemlist/tests.py b/pandora/itemlist/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/itemlist/tests.py
+++ b/pandora/itemlist/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/itemlist/views.py b/pandora/itemlist/views.py
index b2d534ef7..84f03ee2c 100644
--- a/pandora/itemlist/views.py
+++ b/pandora/itemlist/views.py
@@ -1,28 +1,12 @@
# -*- 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
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
-import ox
+import models
from api.actions import actions
@@ -48,12 +32,13 @@ def addListItem(request):
response = json_response(status=403, text='not allowed')
elif 'query' in data:
response = json_response(status=501, text='not implemented')
-
+
else:
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(addListItem)
+
@login_required_json
def removeListItem(request):
'''
@@ -76,12 +61,13 @@ def removeListItem(request):
response = json_response(status=403, text='not allowed')
elif 'query' in data:
response = json_response(status=501, text='not implemented')
-
+
else:
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(removeListItem)
+
@login_required_json
def addList(request):
'''
@@ -97,12 +83,11 @@ def addList(request):
response = json_response(status=200, text='created')
else:
response = json_response(status=200, text='list already exists')
- response['data']['errors'] = {
- 'name': 'List already exists'
- }
+ response['data']['errors'] = {'name': 'List already exists'}
return render_to_json_response(response)
actions.register(addList)
+
@login_required_json
def editList(request):
'''
@@ -124,6 +109,8 @@ def editList(request):
return render_to_json_response(response)
actions.register(editList)
+
+@login_required_json
def removeList(request):
'''
param data
@@ -139,4 +126,3 @@ def removeList(request):
response = json_response(status=403, text='not allowed')
return render_to_json_response(response)
actions.register(removeList)
-
diff --git a/pandora/person/models.py b/pandora/person/models.py
index fa37de2d1..41f78303e 100644
--- a/pandora/person/models.py
+++ b/pandora/person/models.py
@@ -2,26 +2,12 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division, with_statement
-from datetime import datetime
-import os.path
-import math
-import random
-import re
-import subprocess
import unicodedata
-from glob import glob
from django.db import models
-from django.db.models import Q
-from django.contrib.auth.models import User
-from django.core.files.base import ContentFile
-from django.utils import simplejson as json
-from django.conf import settings
from ox.django import fields
import ox
-from ox import stripTags
-from ox.normalize import canonicalTitle, canonicalName
def get_name_sort(name):
@@ -29,6 +15,7 @@ def get_name_sort(name):
name_sort = unicodedata.normalize('NFKD', person.name_sort)
return name_sort
+
class Person(models.Model):
name = models.CharField(max_length=200)
name_sort = models.CharField(max_length=200)
@@ -67,4 +54,3 @@ class Person(models.Model):
def json(self):
return self.name
-
diff --git a/pandora/person/tests.py b/pandora/person/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/person/tests.py
+++ b/pandora/person/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/place/admin.py b/pandora/place/admin.py
index 8044bab14..f7196a9ec 100644
--- a/pandora/place/admin.py
+++ b/pandora/place/admin.py
@@ -9,5 +9,3 @@ import models
class PlaceAdmin(admin.ModelAdmin):
search_fields = ['name']
admin.site.register(models.Place, PlaceAdmin)
-
-
diff --git a/pandora/place/managers.py b/pandora/place/managers.py
index 2e2765371..bef67bb77 100644
--- a/pandora/place/managers.py
+++ b/pandora/place/managers.py
@@ -1,28 +1,23 @@
# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
-import re
-
-from ox.utils import json
-from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q, Manager
-
-import models
+
class PlaceManager(Manager):
+
def get_query_set(self):
return super(PlaceManager, self).get_query_set()
def find(self, q='', f="globe", sw_lat=-180.0, sw_lng=-180.0, ne_lat=180.0, ne_lng=180.0):
qs = self.get_query_set()
qs = qs.filter(Q(
- Q(Q(sw_lat__gt=sw_lat)|Q(sw_lat__lt=ne_lat)|Q(sw_lng__gt=sw_lng)|Q(sw_lng__lt=ne_lng)) &
+ Q(Q(sw_lat__gt=sw_lat)|Q(sw_lat__lt=ne_lat)|Q(sw_lng__gt=sw_lng)|Q(sw_lng__lt=ne_lng)) &
Q(Q(sw_lat__gt=sw_lat)|Q(sw_lat__lt=ne_lat)|Q(sw_lng__lt=ne_lng)|Q(ne_lng__gt=ne_lng)) &
Q(Q(ne_lat__gt=sw_lat)|Q(ne_lat__lt=ne_lat)|Q(sw_lng__gt=sw_lng)|Q(sw_lng__lt=ne_lng)) &
Q(Q(ne_lat__gt=sw_lat)|Q(ne_lat__lt=ne_lat)|Q(ne_lng__gt=sw_lng)|Q(ne_lng__lt=ne_lng))
))
if q:
- qs = qs.filter(name_find__icontains, q)
+ qs = qs.filter(name_find__icontains=q)
return qs
'''
#only return locations that have layers of videos visible to current user
diff --git a/pandora/place/models.py b/pandora/place/models.py
index fa7f80166..c0780502f 100644
--- a/pandora/place/models.py
+++ b/pandora/place/models.py
@@ -3,13 +3,13 @@
from __future__ import division, with_statement
from django.db import models
-from django.db.models import Q
-from django.conf import settings
+import ox
from ox.django import fields
import managers
+
class Place(models.Model):
'''
Places are named locations, they should have geographical information attached to them.
@@ -60,7 +60,6 @@ class Place(models.Model):
self.lng_center = ox.location.center(self.lng_sw, self.lng_ne)
#update area
- self.area = location.area(self.lat_sw, self.lng_sw, self.lat_ne, self.lng_ne)
+ self.area = ox.location.area(self.lat_sw, self.lng_sw, self.lat_ne, self.lng_ne)
super(Place, self).save(*args, **kwargs)
-
diff --git a/pandora/place/tests.py b/pandora/place/tests.py
index 2247054b3..927cadf00 100644
--- a/pandora/place/tests.py
+++ b/pandora/place/tests.py
@@ -7,7 +7,9 @@ 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.
@@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
-
diff --git a/pandora/place/views.py b/pandora/place/views.py
index 433b613c4..32a25d40b 100644
--- a/pandora/place/views.py
+++ b/pandora/place/views.py
@@ -1,37 +1,19 @@
# -*- 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
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
-import ox
import models
from api.actions import actions
-'''
-fixme, require admin
-'''
+
@login_required_json
def addPlace(request):
+ #FIXME: require admin
'''
param data
{
@@ -56,6 +38,7 @@ def addPlace(request):
return render_to_json_response(response)
actions.register(addPlace)
+
@login_required_json
def editPlace(request):
'''
@@ -86,17 +69,19 @@ def editPlace(request):
return render_to_json_response(response)
actions.register(editPlace)
+
@login_required_json
def removePlace(request):
response = json_response(status=501, text='not implemented')
return render_to_json_response(response)
actions.register(removePlace)
+
def findPlace(request):
'''
param data
{'query': query, 'sort': array, 'range': array, 'area': array}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
sort: array of key, operator dics
@@ -120,7 +105,7 @@ def findPlace(request):
Positions
param data
{'query': query, 'ids': []}
-
+
query: query object, more on query syntax at
https://wiki.0x2620.org/wiki/pandora/QuerySyntax
ids: ids of places for which positions are required
@@ -129,8 +114,7 @@ Positions
response = json_response(status=200, text='ok')
response['data']['places'] = []
#FIXME: add coordinates to limit search
- for p in Places.objects.find(data['query']):
+ for p in models.Place.objects.find(data['query']):
response['data']['places'].append(p.json())
return render_to_json_response(response)
actions.register(findPlace)
-
diff --git a/pandora/text/models.py b/pandora/text/models.py
index 6eacc624d..e4ff094cc 100644
--- a/pandora/text/models.py
+++ b/pandora/text/models.py
@@ -5,11 +5,6 @@ from datetime import datetime
from django.db import models
from django.contrib.auth.models import User
-from django.conf import settings
-
-import ox
-from ox.django import fields
-from ox.utils import json
class News(models.Model):
@@ -29,6 +24,7 @@ class News(models.Model):
def get_absolute_url(self):
return '/text/%s' % self.slug
+
class Text(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
@@ -46,6 +42,7 @@ class Text(models.Model):
def get_absolute_url(self):
return '/text/%s' % self.slug
+
class Image(models.Model):
image = models.ImageField(upload_to='text/image')
caption = models.CharField(max_length=255, default="")
@@ -53,10 +50,10 @@ class Image(models.Model):
def get_absolute_url(self):
return self.image.url
+
class Attachment(models.Model):
file = models.FileField(upload_to='text/attachment')
caption = models.CharField(max_length=255, default="")
def get_absolute_url(self):
return self.file.url
-
diff --git a/pandora/text/views.py b/pandora/text/views.py
index b86393fb5..ff894f921 100644
--- a/pandora/text/views.py
+++ b/pandora/text/views.py
@@ -2,23 +2,15 @@
# vi:si:et:sw=4:sts=4:ts=4
from __future__ import division
-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
from ox.utils import json
from ox.django.decorators import login_required_json
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
-from ox.django.http import HttpFileResponse
-import ox
import models
from api.actions import actions
+
def getNews(request):
'''
param data
@@ -33,6 +25,23 @@ def getNews(request):
return render_to_json_response(response)
actions.register(getNews)
+
+@login_required_json
+def editNews(request):
+ '''
+ param data
+ string id
+
+ return page
+ '''
+ response = json_response({})
+ itemId = json.loads(request.POST['data'])
+ item = get_object_or_404_json(models.Text, pk=itemId)
+ response['data']['page'] = item.html()
+ return render_to_json_response(response)
+actions.register(editNews)
+
+
def findNews(request):
'''
'''
@@ -40,6 +49,7 @@ def findNews(request):
return render_to_json_response(response)
actions.register(findNews)
+
def getText(request):
'''
param data
@@ -54,10 +64,26 @@ def getText(request):
return render_to_json_response(response)
actions.register(getText)
+
+@login_required_json
+def editText(request):
+ '''
+ param data
+ string id
+
+ return page
+ '''
+ response = json_response({})
+ itemId = json.loads(request.POST['data'])
+ item = get_object_or_404_json(models.Text, pk=itemId)
+ response['data']['page'] = item.html()
+ return render_to_json_response(response)
+actions.register(editText)
+
+
def findText(request):
'''
'''
response = json_response({})
return render_to_json_response(response)
actions.register(findText)
-
diff --git a/pandora/torrent/transmission.py b/pandora/torrent/transmission.py
index 75bed7e16..af5b339ec 100644
--- a/pandora/torrent/transmission.py
+++ b/pandora/torrent/transmission.py
@@ -10,12 +10,14 @@ from django.conf import settings
import ox.torrent
import transmissionrpc
+
def connect():
return transmissionrpc.Client(settings.TRANSMISSON_HOST,
port=settings.TRANSMISSON_PORT,
user=settings.TRANSMISSON_USER,
password=settings.TRANSMISSON_PASSWORD)
+
def remove(info_hash):
if settings.DEBUG:
print 'remove', info_hash
@@ -24,10 +26,11 @@ def remove(info_hash):
tc = connect()
tc.remove(info_hash.lower())
except:
- if DEBUG:
+ if settings.DEBUG:
import traceback
traceback.print_exc()
-
+
+
def add(torrent_file):
download_dir = os.path.dirname(torrent_file)
with open(torrent_file) as f:
@@ -42,6 +45,7 @@ def add(torrent_file):
import traceback
traceback.print_exc()
+
def is_seeding(info_hash):
info_hash = info_hash.lower()
try:
@@ -56,6 +60,7 @@ def is_seeding(info_hash):
return True
return False
+
def start_daemon():
try:
tc = connect()
@@ -71,4 +76,3 @@ def start_daemon():
'-w', settings.MEDIA_ROOT,
])
time.sleep(1)
-
diff --git a/pandora/user/models.py b/pandora/user/models.py
index 7a3d58e2a..a4e5744b1 100644
--- a/pandora/user/models.py
+++ b/pandora/user/models.py
@@ -5,24 +5,25 @@ from datetime import datetime
from django.contrib.auth.models import User
from django.db import models
-from django.db.models import signals
-from django.dispatch import dispatcher
from django.conf import settings
from ox.utils import json
+
class UserProfile(models.Model):
reset_token = models.TextField(blank=True, null=True, unique=True)
user = models.ForeignKey(User, unique=True)
-
+
files_updated = models.DateTimeField(default=datetime.now)
newsletter = models.BooleanField(default=True)
+
def user_post_save(sender, instance, **kwargs):
profile, new = UserProfile.objects.get_or_create(user=instance)
models.signals.post_save.connect(user_post_save, sender=User)
-
+
+
class Preference(models.Model):
user = models.ForeignKey(User, related_name='preferences')
created = models.DateTimeField(auto_now_add=True)
@@ -33,18 +34,20 @@ class Preference(models.Model):
def __unicode__(self):
return u"%s/%s=%s" % (self.user, self.key, self.value)
+
def get_user_json(user):
- json = {}
+ result = {}
for key in ('username', ):
- json[key] = getattr(user, key)
- json['group'] = 'user'
+ result[key] = getattr(user, key)
+ result['group'] = 'user'
if user.is_staff:
- json['group'] = 'admin'
+ result['group'] = 'admin'
elif user.has_perm('0x.vip'): #FIXME: permissions
- json['group'] = 'vip'
- json['preferences'] = get_preferences(user)
- json['ui'] = get_ui(user)
- return json
+ result['group'] = 'vip'
+ result['preferences'] = get_preferences(user)
+ result['ui'] = get_ui(user)
+ return result
+
def get_ui(user):
with open(os.path.join(settings.PROJECT_ROOT, 'templates', 'site.json')) as f:
@@ -70,6 +73,7 @@ def get_ui(user):
}
'''
+
def get_preferences(user):
prefs = {}
for p in Preference.objects.filter(user=user):
@@ -77,6 +81,7 @@ def get_preferences(user):
prefs['email'] = user.email
return prefs
+
def get_preference(user, key, value=None):
if key in ('email', ):
value = getattr(user, key)
@@ -86,6 +91,7 @@ def get_preference(user, key, value=None):
value = json.loads(q[0].value)
return value
+
def set_preference(user, key, value):
if key in ('email', ):
setattr(user, key, value)
diff --git a/pandora/user/views.py b/pandora/user/views.py
index dbb9df38e..bf48ca6c8 100644
--- a/pandora/user/views.py
+++ b/pandora/user/views.py
@@ -7,8 +7,7 @@ random.seed()
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
-from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
-from django.template import RequestContext, loader, Context
+from django.template import RequestContext, loader
from django.utils import simplejson as json
from django.conf import settings
from django.core.mail import send_mail, BadHeaderError
@@ -26,13 +25,14 @@ class LoginForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
+
def api_login(request):
'''
param data {
username: 'username',
password: 'password'
}
-
+
return {
status: {'code': 200, 'text': 'ok'}
data: {
@@ -81,11 +81,12 @@ def api_login(request):
return render_to_json_response(response)
actions.register(api_login, 'login')
+
def api_logout(request):
'''
param data {
}
-
+
return {
status: {'code': int, 'text': string}
data: {
@@ -105,11 +106,13 @@ def api_logout(request):
return render_to_json_response(response)
actions.register(api_logout, 'logout')
+
class RegisterForm(forms.Form):
username = forms.TextInput()
password = forms.TextInput()
email = forms.TextInput()
+
def register(request):
'''
param data {
@@ -117,7 +120,7 @@ def register(request):
password: 'password',
email: 'emailaddress'
}
-
+
return {
status: {'code': int, 'text': string}
data: {
@@ -172,13 +175,14 @@ def register(request):
return render_to_json_response(response)
actions.register(register)
+
def resetPassword(request):
'''
param data {
token: reset token
password: new password
}
-
+
return {
status: {'code': int, 'text': string}
data: {
@@ -226,13 +230,14 @@ def resetPassword(request):
return render_to_json_response(response)
actions.register(resetPassword)
+
def requestToken(request):
'''
param data {
username: username,
email: email
}
-
+
return {
status: {'code': int, 'text': string}
data: {
@@ -291,13 +296,14 @@ def requestToken(request):
return render_to_json_response(response)
actions.register(requestToken)
+
def findUser(request):
'''
param data {
key: "username",
value: "foo", operator: "="
}
-
+
return {
'status': {'code': int, 'text': string}
'data': {
@@ -315,18 +321,20 @@ def findUser(request):
return render_to_json_response(response)
actions.register(findUser)
+
class ContactForm(forms.Form):
email = forms.EmailField()
subject = forms.TextInput()
message = forms.TextInput()
+
def contact(request):
'''
param data {
'email': string,
'message': string
}
-
+
return {
'status': {'code': int, 'text': string}
}
@@ -353,6 +361,7 @@ def contact(request):
return render_to_json_response(response)
actions.register(contact)
+
@login_required_json
def preferences(request):
'''
@@ -391,4 +400,3 @@ def preferences(request):
models.set_preference(request.user, key, data[key])
return render_to_json_response(response)
actions.register(preferences)
-