--- a/.hgignore Mon Nov 12 15:03:36 2012 +0100
+++ b/.hgignore Mon Nov 12 16:17:22 2012 +0100
@@ -33,3 +33,6 @@
syntax: regexp
^virtualenv/sync/project-boot\.py$
relre:^.metadata
+
+syntax: regexp
+^web/\.htusers$
\ No newline at end of file
--- a/.hgtags Mon Nov 12 15:03:36 2012 +0100
+++ b/.hgtags Mon Nov 12 16:17:22 2012 +0100
@@ -112,3 +112,13 @@
36d8d68fda811a9020dfcb4794ad42403ab7806b V01.26
3eae57bb42b3d5c8daf3e94331f9ef30cf444693 V01.26
2151b47c58c3291f82a2e190c474e7f616266742 V01.27
+ba611074ecb2c86907386b1c76c87f38e35aa6f0 V01.28
+ba611074ecb2c86907386b1c76c87f38e35aa6f0 V01.28
+be9868b4b13dbbf18bb82c5cad5008e5a540f43b V01.28
+be9868b4b13dbbf18bb82c5cad5008e5a540f43b V01.28
+ba43c842648c3d997157fae50693af90680e9875 V01.28
+ba43c842648c3d997157fae50693af90680e9875 V01.28
+7be50692abb4ad436eb668f20732dd79449c199f V01.28
+7be50692abb4ad436eb668f20732dd79449c199f V01.28
+e20fa653364745615a79f887eb6b77dfd58b171d V01.28
+d42fbe878062cf9765b8f968c5aad2161c479cd5 V01.29
--- a/src/ldt/README Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/README Mon Nov 12 16:17:22 2012 +0100
@@ -5,7 +5,6 @@
The ldt platform, is a django module allowing the annotation, indexation, consultation of temporal content (audio, video)
-
trick:
compile messages for js
python ../../../web/ldtplatform/manage.py makemessages -a -d djangojs
@@ -62,3 +61,16 @@
swfobject.js
ZeroClipboard
tiny_mce
+
+
+==============
+Unit Test
+==============
+
+In a terminal :
+ python manage.py test %test_api%
+Will launch all the tests of the api
+
+For example :
+ python manage.py test ldt_utils
+Will launch all the test defined in /ldt_utils/tests
\ No newline at end of file
--- a/src/ldt/ldt/__init__.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/__init__.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,4 +1,4 @@
-VERSION = (1, 27, 0, "final", 0)
+VERSION = (1, 29, 0, "final", 0)
def get_version():
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/authentication.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,58 @@
+from django.conf import settings
+from django.middleware.csrf import _sanitize_token, constant_time_compare
+from django.utils.http import same_origin
+from tastypie.authentication import Authentication
+
+# imported from tastypie's next version 0.9.12
+class SessionAuthentication(Authentication):
+ """
+ An authentication mechanism that piggy-backs on Django sessions.
+
+ This is useful when the API is talking to Javascript on the same site.
+ Relies on the user being logged in through the standard Django login
+ setup.
+
+ Requires a valid CSRF token.
+ """
+ def is_authenticated(self, request, **kwargs):
+ """
+ Checks to make sure the user is logged in & has a Django session.
+ """
+ # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
+ # We can't just use what's there, since the return values will be
+ # wrong.
+ # We also can't risk accessing ``request.POST``, which will break with
+ # the serialized bodies.
+ if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
+ return request.user.is_authenticated()
+
+ if getattr(request, '_dont_enforce_csrf_checks', False):
+ return request.user.is_authenticated()
+
+ csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))
+
+ if request.is_secure():
+ referer = request.META.get('HTTP_REFERER')
+
+ if referer is None:
+ return False
+
+ good_referer = 'https://%s/' % request.get_host()
+
+ if not same_origin(referer, good_referer):
+ return False
+
+ request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
+
+ if not constant_time_compare(request_csrf_token, csrf_token):
+ return False
+
+ return request.user.is_authenticated()
+
+ def get_identifier(self, request):
+ """
+ Provides a unique string identifier for the requestor.
+
+ This implementation returns the user's username.
+ """
+ return request.user.username
\ No newline at end of file
--- a/src/ldt/ldt/api/ldt/resources/__init__.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/api/ldt/resources/__init__.py Mon Nov 12 16:17:22 2012 +0100
@@ -2,5 +2,6 @@
from content import ContentResource
from project import ProjectResource
from segment import SegmentResource
+from user import UserResource
-__all__ = ["AnnotationResource", "ContentResource", "ProjectResource", "SegmentResource"]
+__all__ = ["AnnotationResource", "ContentResource", "ProjectResource", "SegmentResource", "UserResource"]
--- a/src/ldt/ldt/api/ldt/resources/annotation.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/api/ldt/resources/annotation.py Mon Nov 12 16:17:22 2012 +0100
@@ -10,17 +10,17 @@
class AnnotationObject(object):
- # For the moment, these attributes are useless. We just need to define AnnotationObject
- id = ""
- project = ""
- type = ""
- type_title = ""
- media = ""
- begin = ""
- end = ""
- content = {"title":"", "description":""}
- tags = []
- meta = {"creator":"","created":""}
+ def __init__(self, id="", project = "", type = "", type_title = "", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}):
+ self.id = id
+ self.project = project
+ self.type = type
+ self.type_title = type_title
+ self.media = media
+ self.begin = begin
+ self.end = end
+ self.content = content
+ self.tags = tags
+ self.meta = meta
class AnnotationResource(Resource):
# For the moment, these attributes are useless. We just prepare relations to AnnotationObject
@@ -36,23 +36,24 @@
meta = fields.DictField(attribute = 'meta')
class Meta:
- allowed_methods = ['put']
+ allowed_methods = ['post']
resource_name = 'annotations'
object_class = AnnotationObject
authorization = Authorization()
# always_return_data = True because we want the api returns the data with the updated ids
always_return_data = True
+ include_resource_uri = False
def obj_delete_list(self, request=None, **kwargs):
return True
def obj_create(self, bundle, request=None, **kwargs):
- """
- """
- logging.debug("ICI 0-1 bundle.data = " + repr(bundle.data))
+ #logging.debug("ICI 0-1 bundle.data = " + repr(bundle.data))
+ # Here the a has the datas for only one annotation. Tastypie's post allows only one resource addition
+ a = bundle.data
project_id = ""
- if bundle.data.has_key('project') :
- project_id = bundle.data["project"]
+ if a.has_key('project') :
+ project_id = a["project"]
if project_id and project_id != "" :
try:
project = Project.objects.get(ldt_id=project_id)
@@ -60,18 +61,17 @@
raise NotFound("Project not found. project_id = " + project_id)
else :
# If the project's is not defined, we get or create the content's front project.
- iri_id = bundle.data["media"]
+ iri_id = a["media"]
try:
content = Content.objects.get(iri_id=iri_id)
except Content.DoesNotExist:
raise NotFound("Content not found. iri_id = " + iri_id)
project = content.get_or_create_front_project()
- bundle.data["project"] = project.ldt_id
+ a[u"project"] = project.ldt_id
adder = LdtAnnotation(project)
unprotect_models() # Allows anonymous user to modify models in this request only
- # Here the bundle.data has the datas for only one annotation. The others api's functions parse the "objects" from the request's json.
- a = bundle.data
+
dur = str(a['end'] - a['begin'])
begin = str(a['begin'])
# We test if the annotation has audio node
@@ -95,16 +95,19 @@
add_annotation_to_stat(content, a['begin'], a['end'])
# We update the ids
- bundle.data['type'] = type_id
- bundle.data['id'] = new_id
- if not bundle.data['content'].has_key('audio') :
- bundle.data['content']['audio'] = {'src':audio_src, 'href':audio_href}
- # We reinject the datas in the bundle's response
- bundle = self.full_hydrate(bundle)
+ a['type'] = type_id
+ a['id'] = new_id
+ if not a['content'].has_key('audio') :
+ a['content']['audio'] = {'src':audio_src, 'href':audio_href}
# We save the added annotation and reprotect the contents and projects
adder.save()
protect_models()
+ # We update the AnnotationObject for the returned datas to be correct.
+ bundle.obj = AnnotationObject(id = a["id"], project = a["project"], type = a["type"], type_title = a["type_title"], media = a["media"], begin = a["begin"], end = a["end"], content = a['content'], tags = a['tags'], meta = a['meta'])
return bundle
+
+ def get_resource_uri(self, bundle_or_obj):
+ return ''
\ No newline at end of file
--- a/src/ldt/ldt/api/ldt/resources/content.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/api/ldt/resources/content.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,18 +1,56 @@
from django.conf.urls.defaults import url
-from ldt.ldt_utils.models import Content
-from tastypie.resources import ModelResource
+from ldt.ldt_utils.models import Content, Segment
+from tastypie.resources import Bundle, ModelResource
+from ldt.indexation import get_results_list
+from itertools import groupby
class ContentResource(ModelResource):
class Meta:
allowed_methods = ['get']
resource_name = 'contents'
- queryset = Content.objects.all()
+ queryset = Content.safe_objects.all()
excludes = ['media_obj']
def override_urls(self):
# WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated
return [
- url(r"^(?P<resource_name>%s)/(?P<iri_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
+ url(r"^(?P<resource_name>%s)/recommended/$" % self._meta.resource_name, self.wrap_view('get_recommended'), name="api_contents_recommended"),
+ url(r"^(?P<resource_name>%s)/(?P<iri_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_contents_dispatch_detail"),
]
+ def get_resource_uri(self, bundle_or_obj):
+ kwargs = {
+ 'resource_name': self._meta.resource_name,
+ 'api_name': self._meta.api_name
+ }
+ if isinstance(bundle_or_obj, Bundle):
+ kwargs['iri_id'] = bundle_or_obj.obj.iri_id
+ else:
+ kwargs['iri_id'] = bundle_or_obj.iri_id
+ return self._build_reverse_url("api_dispatch_detail", kwargs=kwargs)
+
+ def get_recommended(self, request, **kwargs):
+ self.method_check(request, allowed=['get'])
+
+ keywords = request.GET.get('keywords','')
+ keywords_search = " OR ".join(keywords.split(','))
+ field = request.GET.get('field','all')
+
+ result_list = get_results_list(field, keywords_search)
+ score_dict = dict([(k,sum([e.score for e in i])) for k,i in groupby(result_list, lambda e: e.iri_id)])
+
+ res = [self.full_dehydrate(self.build_bundle(obj=c, request=request)) for c in Content.safe_objects.filter(iri_id__in = score_dict.keys())]
+
+ def add_score(b,s):
+ b.data['score'] = s
+ return b
+
+ object_list = {
+ 'objects': sorted([add_score(b, score_dict.get(b.data['iri_id'],0)) for b in res], key=lambda b: b.data['score'], reverse=True),
+ }
+
+ self.log_throttled_access(request)
+
+ return self.create_response(request, object_list)
+
\ No newline at end of file
--- a/src/ldt/ldt/api/ldt/resources/project.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/api/ldt/resources/project.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,15 +1,26 @@
from django.conf.urls.defaults import url
from ldt.ldt_utils.models import Project
+from ldt.api.ldt.authentication import SessionAuthentication
+from ldt.api.ldt.serializers.cinelabserializer import CinelabSerializer
+from ldt.api.ldt.resources import ContentResource
+from ldt.api.ldt.resources.user import UserResource
from tastypie.authorization import Authorization
-from tastypie.resources import ModelResource
-
+from tastypie.resources import Bundle, ModelResource
+from tastypie import fields
+from ldt.security import protect_models, unprotect_models
class ProjectResource(ModelResource):
+ contents = fields.ManyToManyField(ContentResource, 'contents')
+ owner = fields.ForeignKey(UserResource, 'owner')
class Meta:
- allowed_methods = ['get', 'put']
- authorization= Authorization() # BE CAREFUL WITH THAT, it's unsecure
+ allowed_methods = ['get', 'post']
+ authorization = Authorization() # BE CAREFUL WITH THAT, it's unsecure
+ authentication = SessionAuthentication()
resource_name = 'projects'
- queryset = Project.objects.all()
+ queryset = Project.safe_objects.all()
+ serializer = CinelabSerializer()
+ # In the future version :
+ # detail_uri_name = 'ldt_id'
# # WARNING : this project API will only accepts and returns json format, no matter format get parameter.
# def determine_format(self, request):
@@ -20,4 +31,21 @@
return [
url(r"^(?P<resource_name>%s)/(?P<ldt_id>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
+
+ def get_resource_uri(self, bundle_or_obj):
+ kwargs = {
+ 'resource_name': self._meta.resource_name,
+ 'api_name': self._meta.api_name
+ }
+ if isinstance(bundle_or_obj, Bundle):
+ kwargs['ldt_id'] = bundle_or_obj.obj.ldt_id
+ else:
+ kwargs['ldt_id'] = bundle_or_obj.ldt_id
+ return self._build_reverse_url("api_dispatch_detail", kwargs=kwargs)
+
+ # TEMPORARY (used before authentication/authorization, because saving a project modifies a Content (via ContentStat))
+ def save_m2m(self, bundle):
+ unprotect_models()
+ super(ProjectResource, self).save_m2m(bundle)
+ protect_models()
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/resources/user.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,26 @@
+from django.contrib.auth.models import User
+from django.conf.urls.defaults import url
+from tastypie.resources import Bundle, ModelResource
+
+class UserResource(ModelResource):
+ class Meta:
+ allowed_methods = ['get']
+ queryset = User.objects.all()
+ resource_name = 'users'
+
+ def override_urls(self):
+ # WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated
+ return [
+ url(r"^(?P<resource_name>%s)/(?P<username>[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
+ ]
+
+ def get_resource_uri(self, bundle_or_obj):
+ kwargs = {
+ 'resource_name': self._meta.resource_name,
+ 'api_name': self._meta.api_name
+ }
+ if isinstance(bundle_or_obj, Bundle):
+ kwargs['username'] = bundle_or_obj.obj.username
+ else:
+ kwargs['username'] = bundle_or_obj.username
+ return self._build_reverse_url("api_dispatch_detail", kwargs=kwargs)
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/serializers/__init__.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,1 @@
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/serializers/cinelabserializer.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,292 @@
+from django.conf import settings
+from django.core.serializers import json
+from django.core.urlresolvers import reverse
+from django.utils import simplejson
+from ldt.ldt_utils.models import Content, Project
+from ldt.ldt_utils.projectserializer import ProjectJsonSerializer
+from ldt.ldt_utils.utils import generate_uuid
+from tastypie.serializers import Serializer
+from tastypie.exceptions import NotFound
+import math
+import lxml.etree
+import logging
+
+
+class CinelabSerializer(Serializer):
+ # Thanks to the this serializer, the api will be able to serialize and deserialize a project in cinelab json format
+ # See http://liris.cnrs.fr/advene/cinelab/ for more information
+ formats = ['json', 'jsonp', 'xml', 'yaml', 'html', 'plist', 'cinelab']
+ content_types = {
+ 'cinelab': 'application/cinelab',
+ 'json': 'application/json',
+ 'jsonp': 'text/javascript',
+ 'xml': 'application/xml',
+ 'yaml': 'text/yaml',
+ 'html': 'text/html',
+ 'plist': 'application/x-plist',
+ }
+ json_indent = 2
+
+ def to_cinelab(self, data, options=None):
+ """
+ Given some Python data, produces Cinelab/JSON output.
+ N.B. : for the moment, this serializer works with api_dispatch_detail only.
+ It does not work with api_dispatch_list. Only from_cinelab deals with api_dispatch_list's multiple objects like {"objects":[...]}
+ """
+ options = options or {}
+ if hasattr(data, 'obj') :
+ if isinstance(data.obj, Project) :
+ ps = ProjectJsonSerializer(data.obj)
+ data = ps.serialize_to_cinelab()
+ return simplejson.dumps(data, cls=json.DjangoJSONEncoder, sort_keys=True, indent=self.json_indent)
+ raise NotFound("Project not found")
+
+
+ def from_cinelab(self, content):
+ """
+ This function takes cinelab/json and transform it into a regular REST API json project data.
+ All fields are (* required at rebuilt json) :
+ "changed_by": "admin",
+ "created_by": "admin",
+ "creation_date": "2012-02-11T01:18:48.028534",
+ "description": "",
+ "image": "/pf/static/media/thumbnails/contents/content_default_icon.png",
+ "ldt*": "<iri><project>...<medias>...<annotations>...<displays>...<edits>...</iri>",
+ "ldt_id*": "594dc612-544e-11e1-96e5-00145ea49a02",
+ "modification_date": "2012-02-11T01:19:40.203322",
+ "state": 2,
+ "title*": "front project : test DailyMotion"
+ "contents*": ["IRI_ID_1","IRI_ID_2"]
+ "owner*": "user_id"
+ """
+ logging.debug("FROM cinelab content = " + content)
+
+ cinelab = simplejson.loads(content)
+ meta = cinelab["meta"]
+ ldt_id = generate_uuid()
+ # default state = (1, 'edition') OR (2, 'published')
+ state = 2
+ contents = [reverse("api_dispatch_detail", kwargs={"api_name":"1.0", "resource_name":"contents", "iri_id":c["id"]}) for c in cinelab["medias"]]
+ owner_uri = reverse("api_dispatch_detail", kwargs={"api_name":"1.0", "resource_name":"users", "username":meta["dc:creator"]})
+
+ ldt = lxml.etree.tostring(self.cinelab_to_ldt(cinelab), pretty_print=True)
+
+ s = {"description": meta["dc:description"], "ldt_id": ldt_id, "title": meta["dc:title"],
+ "created_by": meta["dc:creator"], "changed_by": meta["dc:contributor"], "created_by": meta["dc:creator"], "changed_by": meta["dc:contributor"],
+ "contents": contents, "owner": owner_uri, "state":state, "ldt":ldt}
+
+ #s = '{"description": "", "ldt": "<iri><project/><medias/><annotations/><displays/><edits/></iri>", "000ldt_id": "gen_by_tc","title": "aaa GEN BY TC"}'
+ #s = '{"description": "", "ldt": "<iri><project/><medias/><annotations/><displays/><edits/></iri>", "title": "aaaGEN BY TC"}'
+ #return simplejson.loads(simplejson.dumps(s))
+ return s
+
+
+ def cinelab_to_ldt(self, cinelab, ldt_id=None):
+ # Start xml
+ meta = cinelab["meta"]
+ annotation_types = cinelab["annotation-types"]
+ annotations = cinelab["annotations"]
+ # If the ldt_id is not set, we get in the cinelab meta
+ if not ldt_id:
+ ldt_id = meta["id"]
+
+ # Before creating the xml, we build a dict for tag {"id":"label"}
+ # Careful : works with python >= 2.7
+ tag_dict = {t["id"]:t["meta"]["dc:title"] for t in cinelab["tags"]}
+ # We'll also build a annotation-type to media/ensemble dict to simplify the views node building
+ at_media_dict = {}
+ # We'll also build a dict from annotation id to media/ensemble/decoupage dict to simplify the edits/mashup node building
+ annot_ids_dict = {}
+ # We'll also build a dict from media id to media url dict to simplify the edits/mashup node building
+ media_url_dict = {}
+
+ # create a dom
+ iri = lxml.etree.Element('iri')
+
+ # Node project
+ projectNode = lxml.etree.SubElement(iri, 'project')
+ projectNode.set('abstract', meta["dc:description"])
+ projectNode.set('title', meta["dc:title"])
+ projectNode.set('user', meta["dc:creator"])
+ projectNode.set('id', ldt_id)
+
+ # Node medias and node annotations
+ mediasNode = lxml.etree.SubElement(iri, 'medias')
+ annotationsNode = lxml.etree.SubElement(iri, 'annotations')
+ for c in cinelab["medias"]:
+ # We add the content to the medias node
+ content = Content.objects.get(iri_id=c["id"])
+ iri_id = content.iri_id
+ mediaNode = lxml.etree.SubElement(mediasNode, 'media')
+ mediaNode.set('id', iri_id)
+ mediaNode.set('src', content.iri_url())
+ if content.videopath != None :
+ mediaNode.set('video', content.videopath)
+ media_url_dict[iri_id] = {'url':content.videopath + content.src, 'pos':None}
+ else:
+ mediaNode.set('video', settings.STREAM_URL)
+ media_url_dict[iri_id] = {'url':settings.STREAM_URL + content.src, 'pos':None}
+ mediaNode.set('pict', "")
+ mediaNode.set('extra', "")
+ # We add the annotations
+ contentNode = lxml.etree.SubElement(annotationsNode, 'content')
+ contentNode.set('id', iri_id)
+ # we search the cinelab lists if they represent a content's list of annotation-type
+ for l in cinelab["lists"]:
+ if l["meta"].has_key("id-ref"):
+ if l["meta"]["id-ref"]==iri_id:
+ # We build the ensemble node
+ ensembleNode = lxml.etree.SubElement(contentNode, 'ensemble')
+ ensembleNode.set('id', l["id"])
+ ensembleNode.set('idProject', ldt_id)
+ ensembleNode.set('title', l["meta"]["dc:title"])
+ ensembleNode.set('author', l["meta"]["dc:creator"])
+ ensembleNode.set('abstract', l["meta"]["dc:description"])
+ # We build the decoupage node, equivalent to an annotation-type
+ for at_ref in l["items"]:
+ at_id = at_ref["id-ref"]
+ # We get the annotation-type datas
+ for at in annotation_types:
+ if at["id"]==at_id:
+ at_media_dict[at_id] = (iri_id, l["id"])
+ decoupageNode = lxml.etree.SubElement(ensembleNode, 'decoupage')
+ decoupageNode.set('id', at_id)
+ decoupageNode.set('author', at["dc:creator"])
+ titleDec = lxml.etree.SubElement(decoupageNode, 'title')
+ titleDec.text = at["dc:title"]
+ abstractDec = lxml.etree.SubElement(decoupageNode, 'abstract')
+ abstractDec.text = at["dc:description"]
+ elementsNode = lxml.etree.SubElement(decoupageNode, 'elements')
+ # We get all the annotations for this media and this annotation-type
+ for a in annotations:
+ if a["media"]==iri_id and a["meta"]["id-ref"]==at_id:
+ annot_ids_dict[a["id"]] = (iri_id, l["id"], at_id, a["begin"], a["end"], a["color"])
+ elementNode = lxml.etree.SubElement(elementsNode, 'element')
+ elementNode.set('id', a["id"])
+ elementNode.set('begin', str(a["begin"]))
+ elementNode.set('dur', str(a["end"]-a["begin"]))
+ elementNode.set('author', a["meta"]["dc:creator"])
+ elementNode.set('date', a["meta"]["dc:modified"])
+ elementNode.set('color', a["color"])
+ elementNode.set('src', "")
+ titleElm = lxml.etree.SubElement(elementNode, 'title')
+ titleElm.text = a["content"]["title"]
+ abstractElm = lxml.etree.SubElement(elementNode, 'abstract')
+ abstractElm.text = a["content"]["description"]
+ # Audio node, if the dict has the audio key
+ audioElm = lxml.etree.SubElement(elementNode, 'audio')
+ audioElm.set('source', "")
+ if a["content"].has_key("audio"):
+ audioElm.set('source', a["content"]["audio"]["src"])
+ audioElm.text = a["content"]["audio"]["href"]
+ # The tags dict has been set before, we just get the labels
+ tagsNode = lxml.etree.SubElement(elementNode, 'tags')
+ if a["tags"]:
+ for t in a["tags"]:
+ if tag_dict.has_key(t["id-ref"]):
+ tagNode = lxml.etree.SubElement(tagsNode, 'tag')
+ tagNode.text = tag_dict[t["id-ref"]]
+ # Last element's node
+ lxml.etree.SubElement(elementNode, 'meta')
+
+ # Now all medias and annotation-types and annotations are the xml
+ # We can set the views/displays node
+ displaysNode = lxml.etree.SubElement(iri, 'displays')
+ id_sel = None
+ i = 1
+ for v in cinelab["views"]:
+ if "stat" not in v["id"] and v.has_key("annotation_types"):
+ displayNode = lxml.etree.SubElement(displaysNode, 'display')
+ displayNode.set('id', v["id"])
+ displayNode.set('title', "View " + str(i))
+ i += 1
+ displayNode.set('tc', "0")
+ displayNode.set('zoom', "0")
+ displayNode.set('scroll', "0")
+ audioDis = lxml.etree.SubElement(displayNode, 'audio')
+ audioDis.set('source', "")
+ last_iri_id = ""
+ last_content_node = None
+ for at_id in v["annotation_types"]:
+ iri_id, ens_id = at_media_dict[at_id]
+ if iri_id != last_iri_id:
+ last_iri_id = iri_id
+ last_content_node = lxml.etree.SubElement(displayNode, 'content')
+ last_content_node.set('id', iri_id)
+ if last_content_node is not None:
+ decoupageNode = lxml.etree.SubElement(last_content_node, 'decoupage')
+ decoupageNode.set('idens', ens_id)
+ decoupageNode.set('id', at_id)
+ decoupageNode.set('tagsSelect', "")
+ if not id_sel:
+ id_sel = iri_id
+ if not id_sel:
+ id_sel = ""
+ displayNode.set('idsel', id_sel)
+
+ # Now we build the edit node
+ editsNode = lxml.etree.SubElement(iri, 'edits')
+ i = 0
+ for l in cinelab["lists"]:
+ if l["meta"].has_key("listtype"):
+ if l["meta"]["listtype"]=="mashup":
+ editingNode = lxml.etree.SubElement(editsNode, 'editing')
+ editingNode.set('id', str(i))
+ i += 1
+ editingNode.set('tags', "")
+ titleEd = lxml.etree.SubElement(editingNode, 'title')
+ titleEd.text = l["meta"]["dc:title"]
+ abstractEd = lxml.etree.SubElement(editingNode, 'abstract')
+ abstractEd.text = l["meta"]["dc:description"]
+ editNode = lxml.etree.SubElement(editingNode, 'edit')
+ editNode.set('id', "edit1")
+ editNode.set('tags', "")
+ # We build the 4 nodes (2 are used in reality : edit list and media list
+ eListNode = lxml.etree.SubElement(editNode, 'eList')
+ lxml.etree.SubElement(editNode, 'caption')
+ lxml.etree.SubElement(editNode, 'audio')
+ mListNode = lxml.etree.SubElement(editNode, 'mList')
+ media_pos = 0
+ edit_fulltime = 0
+ for a_id in l["items"]:
+ # the key is the annotation's id
+ iri_id, ens_id, at_id, begin, end, color = annot_ids_dict[a_id]
+ # We check the media's position in media list. If it was not set, we create the mList node
+ if media_url_dict[iri_id]["pos"] is None:
+ media_url_dict[iri_id]["pos"] = media_pos
+ mNode = lxml.etree.SubElement(mListNode, 'm')
+ mNode.set('ref', iri_id)
+ mNode.set('id', str(media_pos))
+ media_pos += 1
+ mNode.set('t', "v")
+ mNode.set('c', color)
+ contentEd = lxml.etree.SubElement(mNode, 'content')
+ contentEd.text = media_url_dict[iri_id]["url"]
+ # We add the annotation/instruction to the eList
+ instNode = lxml.etree.SubElement(eListNode, 'inst')
+ instNode.set('ref', iri_id + "|;|" + ens_id + "|;|" + at_id + "|;||;||;|" + a_id)
+ b = int(math.floor(begin/1000))
+ instNode.set('begin', str(b))
+ e = int(math.floor(end/1000))
+ instNode.set('end', str(e))
+ instNode.set('m', str(media_url_dict[iri_id]["pos"]))
+ instNode.set('v', "100")
+ instNode.set('eBegin', str(edit_fulltime))
+ edit_fulltime = edit_fulltime + e - b
+ instNode.set('eEnd', str(edit_fulltime))
+ instNode.set('trId', "0")
+ instNode.set('trIc', "0")
+ instNode.set('trOd', "0")
+ instNode.set('trOc', "0")
+ # The second empty edit
+ edit2Node = lxml.etree.SubElement(editingNode, 'edit')
+ edit2Node.set('id', "edit2")
+ edit2Node.set('tags', "")
+ lxml.etree.SubElement(edit2Node, 'eList')
+ lxml.etree.SubElement(edit2Node, 'caption')
+ lxml.etree.SubElement(edit2Node, 'audio')
+ lxml.etree.SubElement(edit2Node, 'mList')
+
+ # This is the end
+ return iri
+
\ No newline at end of file
--- a/src/ldt/ldt/api/ldt/urls.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/api/ldt/urls.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,5 +1,5 @@
from django.conf.urls.defaults import patterns, include
-from ldt.api.ldt.resources import ProjectResource, ContentResource, SegmentResource, AnnotationResource
+from ldt.api.ldt.resources import ProjectResource, ContentResource, SegmentResource, AnnotationResource, UserResource
from tastypie.api import Api
v1_api = Api(api_name='1.0')
@@ -7,6 +7,7 @@
v1_api.register(ContentResource())
v1_api.register(SegmentResource())
v1_api.register(AnnotationResource())
+v1_api.register(UserResource())
urlpatterns = patterns('',
(r'', include(v1_api.urls)),
--- a/src/ldt/ldt/ldt_utils/contentindexer.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/contentindexer.py Mon Nov 12 16:17:22 2012 +0100
@@ -8,7 +8,8 @@
import logging
import lxml.etree #@UnresolvedImport
import tagging.utils
-import urllib #@UnresolvedImport
+from ldt.utils.url import request_with_auth
+from StringIO import StringIO
logger = logging.getLogger(__name__)
@@ -129,8 +130,8 @@
def index_content(self, content):
url = content.iri_url()
- filepath = urllib.urlopen(url)
- doc = lxml.etree.parse(filepath) #@UndefinedVariable
+ _, file_content = request_with_auth(url)
+ doc = lxml.etree.parse(StringIO(file_content)) #@UndefinedVariable
Segment.objects.filter(iri_id=content.iri_id).delete() #@UndefinedVariable
--- a/src/ldt/ldt/ldt_utils/fileimport.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/fileimport.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,11 +1,13 @@
+from StringIO import StringIO
from copy import deepcopy #@UnresolvedImport
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db import transaction
from ldt.utils import zipfileext
+from ldt.utils.url import request_with_auth
from models import Content, Media
import fnmatch
-import lxml.etree
+import lxml.etree #@UnresolvedImport
import mimetypes #@UnresolvedImport
import os.path
import shutil #@UnresolvedImport
@@ -25,8 +27,8 @@
class IriInfo(object):
- def __init__(self, id, order, titledesc, basepath="", videopath=settings.STREAM_URL, decoupage_blacklist=settings.DECOUPAGE_BLACKLIST, flatten=True):
- self.id = id
+ def __init__(self, iri_id, order, titledesc, basepath="", videopath=settings.STREAM_URL, decoupage_blacklist=settings.DECOUPAGE_BLACKLIST, flatten=True):
+ self.id = iri_id
self.basepath = basepath
self.order = order
self.src = ""
@@ -48,14 +50,15 @@
def process_iri(self):
# for just import a file ldt and get the title for every media
if 'http' in self.src:
- #url = urllib.urlopen(self.src)
path = self.src
- #doc = xml.dom.minidom.parse(url)
#for import a zip, get title and copy file .iri in the media directory
else:
path = os.path.join(self.basepath, self.src)
- #doc = xml.dom.minidom.parse(path)
-
+
+ if 'http' in path:
+ _,content = request_with_auth(path)
+ path = StringIO(content)
+
doc = lxml.etree.parse(path) #@UndefinedVariable
@@ -78,9 +81,9 @@
#if node.nodeType == xml.dom.Node.ELEMENT_NODE and node.tagName == "ensemble":
if node.tag == "ensemble":
#id = node.getAttributeNS(None,u"id")
- id = node.attrib["id"]
- if id not in ensembleids:
- ensembleids.append(id)
+ ens_id = node.attrib["id"]
+ if ens_id not in ensembleids:
+ ensembleids.append(ens_id)
if self.annotations is not None:
newEnsemble = None
@@ -304,43 +307,41 @@
for i, medianode in enumerate(result):
# get iri file's id from file ldt
- #id = medianode.attributes['id'].value
- id = medianode.attrib['id']
+ iri_id = medianode.attrib['id']
if self.check_existing_media:
try:
- Content.objects.get(iri_id=id)
+ Content.objects.get(iri_id=iri_id)
do_pass = True
except ObjectDoesNotExist: #Content.DoesNotExist
do_pass = False
else:
do_pass = False
if not do_pass:
- if not (contents.has_key(id)):
+ if not (contents.has_key(iri_id)):
# Create instance iriInfo(id, order, titledesc, basepath="", videopath=settings.STREAM_URL)
if ldtpath:
- contents[id] = IriInfo(id, i, "", os.path.dirname(ldtpath), flatten=self.flatten)
+ contents[iri_id] = IriInfo(iri_id, i, "", os.path.dirname(ldtpath), flatten=self.flatten)
else:
- contents[id] = IriInfo(id, i, "", flatten=self.flatten)
+ contents[iri_id] = IriInfo(iri_id, i, "", flatten=self.flatten)
# Get iri file's url from ldt. This url can be relative path or absolute path.
- #contents[id].src = medianode.attributes['src'].value
- contents[id].src = medianode.attrib['src']
+ contents[iri_id].src = medianode.attrib['src']
if medianode.attrib['video'] != "":
- contents[id].videopath = medianode.attrib['video']
+ contents[iri_id].videopath = medianode.attrib['video']
elif self.videopath != "" or self.videopath:
- contents[id].videopath = self.videopath
+ contents[iri_id].videopath = self.videopath
else:
- contents[id].videopath = settings.STREAM_URL
+ contents[iri_id].videopath = settings.STREAM_URL
#get annotation of file ldt
result = doc.xpath("/iri/annotations/content")
for contentnode in result:
- id = contentnode.attrib['id']
- if contents.has_key(id):
+ content_id = contentnode.attrib['id']
+ if contents.has_key(content_id):
if self.author:
contentnode.set("author", unicode(self.author))
- contents[id].annotations = contentnode
+ contents[content_id].annotations = contentnode
#go throught values
for iriinfo in contents.values():
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/fixtures/base_data.json Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,36 @@
+[
+ {
+ "pk": 6,
+ "model": "text.annotation",
+ "fields": {
+ "update_date": "2010-11-16 17:30:50",
+ "description": "texte de description",
+ "title": "titre de l'annotation",
+ "color": "#DDDDDD",
+ "text": "texte selectionne lors de la creation de l'annotation",
+ "creator": "wakimd",
+ "uri": "",
+ "creation_date": "2010-11-16 17:01:41",
+ "contributor": "oaubert",
+ "tags_field": "tag3,tag1,",
+ "external_id": "z2c1d1fa-629d-4520-a3d2-955b4f2582c0"
+ }
+ },
+ {
+ "pk": 7,
+ "model": "text.annotation",
+ "fields": {
+ "update_date": "2010-11-16 17:30:50",
+ "description": "texte de description",
+ "title": "titre de l'annotation",
+ "color": "#DDDDDD",
+ "text": "texte selectionne lors de la creation de l'annotation",
+ "creator": "wakimd",
+ "uri": "http://www.leezam.com/pub/epub/123456!/OPS/chapter2.xhtml#pos=56,168",
+ "creation_date": "2010-11-16 17:01:41",
+ "contributor": "oaubert",
+ "tags_field": "tag3,tag1,",
+ "external_id": "mypersonnalid2"
+ }
+ }
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/fixtures/user_data.json Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,67 @@
+[
+ {
+ "pk": 2,
+ "model": "auth.user",
+ "fields": {
+ "username": "admin",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": true,
+ "is_staff": false,
+ "last_login": "2010-12-12 00:04:07",
+ "groups": [], "user_permissions": [],
+ "password": "",
+ "email": "admin@example.com",
+ "date_joined": "2010-12-12 00:04:07"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "oauth_provider.resource",
+ "fields": {
+ "url": "/api/1.0/text/delete/",
+ "name": "delete",
+ "is_readonly": true
+ }
+ },
+ {
+ "pk": 2,
+ "model": "oauth_provider.resource",
+ "fields": {
+ "url": "/api/1.0/text/create/",
+ "name": "create",
+ "is_readonly": true
+ }
+ },
+ {
+ "pk": 3,
+ "model": "oauth_provider.resource",
+ "fields": {
+ "url": "/api/1.0/text/update/",
+ "name": "update",
+ "is_readonly": true
+ }
+ },
+ {
+ "pk": 4,
+ "model": "oauth_provider.resource",
+ "fields": {
+ "url": "",
+ "name": "all",
+ "is_readonly": true
+ }
+ },
+ {
+ "pk": 1,
+ "model": "oauth_provider.consumer",
+ "fields": {
+ "status": 1,
+ "name": "example.com",
+ "secret": "kd94hf93k423kf44",
+ "user": 2,
+ "key": "dpf43f3p2l4k3l03",
+ "description": ""
+ }
+ }
+]
\ No newline at end of file
--- a/src/ldt/ldt/ldt_utils/models.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py Mon Nov 12 16:17:22 2012 +0100
@@ -8,13 +8,14 @@
get_current_user)
from ldt.security.manager import SafeManager
from ldt.security.models import SafeModel
+from ldt.utils import url as url_utils
from sorl.thumbnail import ImageField
from tagging.models import Tag
from utils import (create_ldt, copy_ldt, create_empty_iri, update_iri,
generate_uuid)
from ldt.utils import generate_hash
import datetime
-import lxml.etree
+import lxml.etree #@UnresolvedImport
import mimetypes
import os.path
import re
@@ -54,7 +55,6 @@
description = models.TextField(null=True, blank=True, verbose_name=_('description'))
title = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('title'))
src = models.CharField(max_length=1024, verbose_name=_('media.src'))
- #TODO: use a fixed length char field
src_hash = models.CharField(max_length=128, unique=True, verbose_name=_('media.src_hash'), blank=True)
mimetype_field = models.CharField(max_length=512, null=True, blank=True, verbose_name=_('media.mimetype'))
@@ -178,10 +178,10 @@
iri_file_path = self.iri_file_path()
thumbnail = os.path.join(settings.MEDIA_ROOT, unicode(self.image))
if os.path.exists(iri_file_path):
- dir = os.path.dirname(iri_file_path)
- temp = os.path.join(os.path.join(os.path.dirname(dir), "temp"), self.iri_id)
+ iri_dir = os.path.dirname(iri_file_path)
+ temp = os.path.join(os.path.join(os.path.dirname(iri_dir), "temp"), self.iri_id)
try:
- move(dir, temp)
+ move(iri_dir, temp)
except Exception, e:
raise e
if os.path.exists(thumbnail):
@@ -197,8 +197,8 @@
#del .iri, and .png from temp directory
def commit(self):
iri_file_path=self.iri_file_path()
- dir = os.path.dirname(iri_file_path)
- temp = os.path.join(os.path.join(os.path.dirname(dir), "temp"), self.iri_id)
+ iri_dir = os.path.dirname(iri_file_path)
+ temp = os.path.join(os.path.join(os.path.dirname(iri_dir), "temp"), self.iri_id)
thumbnail = os.path.join(settings.MEDIA_ROOT, unicode(self.image))
temp_thumbnail = os.path.join(os.path.dirname(thumbnail), "temp")
if os.path.exists(temp):
@@ -211,12 +211,12 @@
#move .iri, and .png to there original directory
def rollback(self):
iri_file_path=self.iri_file_path()
- dir = os.path.dirname(iri_file_path)
- temp = os.path.join(os.path.join(os.path.dirname(dir), "temp"), self.iri_id)
+ iri_dir = os.path.dirname(iri_file_path)
+ temp = os.path.join(os.path.join(os.path.dirname(iri_dir), "temp"), self.iri_id)
thumbnail = os.path.join(settings.MEDIA_ROOT, unicode(self.image))
temp_thumbnail = os.path.join(os.path.dirname(thumbnail), "temp")
if os.path.exists(temp):
- move(temp, dir)
+ move(temp, iri_dir)
os.rmdir(os.path.dirname(temp))
if os.path.exists(temp_thumbnail):
move(os.path.join(temp_thumbnail, os.path.basename(thumbnail)), os.path.dirname(thumbnail))
@@ -260,12 +260,12 @@
try:
iri_file_path = self.iri_file_path()
if not os.path.exists(iri_file_path):
- dir = os.path.dirname(iri_file_path)
- if not os.path.exists(dir):
- os.makedirs(dir)
+ iri_dir = os.path.dirname(iri_file_path)
+ if not os.path.exists(iri_dir):
+ os.makedirs(iri_dir)
created = True
- file = open(iri_file_path, "w")
- create_empty_iri(file, self, "IRI")
+ iri_file = open(iri_file_path, "w")
+ create_empty_iri(iri_file, self, "IRI")
else:
created = False
update_iri(iri_file_path, self, "IRI")
@@ -301,10 +301,13 @@
return str(self.id) + ": " + self.iri_id
def iri_url(self, web_url=settings.WEB_URL):
- if 'http' in self.iriurl or 'https' in self.iriurl:
+ if url_utils.is_absolute(self.iriurl):
return self.iriurl
else:
- return unicode(web_url) + unicode(settings.MEDIA_URL) + u"ldt/" + unicode(self.iriurl)
+ res_url = unicode(settings.MEDIA_URL) + u"ldt/" + unicode(self.iriurl)
+ if not url_utils.is_absolute(res_url):
+ res_url = unicode(web_url) + res_url
+ return res_url
def iri_file_path(self):
return os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "ldt"), self.iri_id), os.path.basename(self.iriurl))
--- a/src/ldt/ldt/ldt_utils/projectserializer.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/projectserializer.py Mon Nov 12 16:17:22 2012 +0100
@@ -16,7 +16,7 @@
"""
Serialize a project object to a cinelab compatible array
"""
-class ProjectSerializer:
+class ProjectJsonSerializer:
def __init__(self, project, from_contents=True, from_display=True, first_cutting=None, only_one_cutting=False):
self.project = project
--- a/src/ldt/ldt/ldt_utils/searchutils.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/searchutils.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,4 +1,3 @@
-from django.conf import settings
from ldt.indexation import SimpleSearch
from ldt.ldt_utils.models import Content, Project
from ldt.ldt_utils.utils import LdtUtils
--- a/src/ldt/ldt/ldt_utils/templates/front/front_base.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_base.html Mon Nov 12 16:17:22 2012 +0100
@@ -78,7 +78,7 @@
<!-- FOOTER COMMUN -->
<ul id="footer">
<li>{% blocktrans %}{{WEB_VERSION}} | {{ VERSION }}{% endblocktrans %}</li>
- <li>©2011 IRI</li>
+ <li>©2012 IRI</li>
<li>
<a target="_blank" href="http://www.iri.centrepompidou.fr" title="{% trans 'link IRI'%}">{% trans "about" %}</a>
</li>
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_group.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_group.html Mon Nov 12 16:17:22 2012 +0100
@@ -1,12 +1,11 @@
-{% extends "ldt/ldt_raw_base.html" %}
+{% extends "ldt/ldt_utils/workspace_base.html" %}
+{% load i18n %}
-{% load i18n %}
{% load adminmedia %}
{% load thumbnail %}
{% block js_import %}
{{ block.super }}
- <script type="text/javascript" src="{{LDT_MEDIA_PREFIX}}js/jquery.nyroModal.min.js"></script>
<script type="text/javascript" src="{% url ldt.jsi18n packages='ldt' %}" ></script>
<script type="text/javascript" src="{{LDT_MEDIA_PREFIX}}js/projectscontents.js" ></script>
<script type="text/javascript" src="{{LDT_MEDIA_PREFIX}}js/tiny_mce/tiny_mce.js"></script>
@@ -25,28 +24,8 @@
{% block js_declaration %}
{{ block.super }}
<script type="text/javascript">
-
- tinyMCE.init({
- plugins : '-example',
- mode : "textareas",
- theme : "advanced",
- language : "{{ LANGUAGE_CODE }}",
- theme_advanced_buttons1 : "bold,italic,underline,separator,justifyleft,justifycenter,justifyfull,undo,redo,link,unlink",
- theme_advanced_buttons2 : "",
- theme_advanced_buttons3 : "",
- theme_advanced_toolbar_location : "top",
- theme_advanced_toolbar_align : "left",
- width: "250",
- height: "150",
- entity_encoding : "raw"
- });
$(document).ready(function() {
- $("#close_button").click(function (e) {
- e.preventDefault();
- parent.$.nmTop().close();
- });
-
$("#ldt_submit_delete").click(function(e){
$(this).addClass("e-clicked");
});
@@ -63,16 +42,13 @@
$( this ).find("button[type=submit]").removeClass("e-clicked");
});
-
var search_url = "{% url ldt.ldt_utils.views.workspace.share_filter filter='__FILTER__' use_groups='false' %}";
- resize_modal_window($("#add_group"));
-
});
</script>
{% endblock %}
-{% block body %}
+{% block content %}
<div id="add_group" class="span-18 last">
<div class="projectscontentstitle span-18 last">{% if group_id %}{% trans "Update a group" %}{% else %}{% trans "Create a group" %}{% endif %}</div>
@@ -96,9 +72,9 @@
{% include "ldt/ldt_utils/partial/permissions.html" %}
{% include "ldt/ldt_utils/partial/picture.html"%}
-
+
<div id="submitcontent-buttons" class="span-12 last">
- <button type="button" id="close_button" value="close">{% trans "close_cancel" %}</button>
+ <button class="button" id="close_button" type="submit" value="close" name="submit_button">{% trans "close_cancel" %}</button>
{% if group_id %}
<button class="button" style="float:right; margin-left:4px" id="ldt_submit_update" type="submit" value="update" name="submit_button">{% trans "update_group" %}</button>
{% if is_owner_group %}
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html Mon Nov 12 16:17:22 2012 +0100
@@ -54,22 +54,19 @@
},
widgets: [
{
- {% if external_url %}
- type: "AutoPlayer",
- video: "{{ external_url }}",
- {% else %}
- type: "JwpPlayer",
- streamer: function(_url) {
- var _matches = _url.match(/^[^\/]+\/\/[^\/]+\/[^\/]+\//);
- if (_matches) {
- return _matches[0];
- } else {
- return _url;
- }
- },
- live: true,
- provider: "rtmp",
- {% endif %}
+ type: "AutoPlayer",
+ {% if external_url %}
+ video: "{{ external_url }}",
+ {% else %}
+ streamer: function(_url) {
+ var _matches = _url.match(/^[^\/]+\/\/[^\/]+\/[^\/]+\//);
+ if (_matches) {
+ return _matches[0];
+ } else {
+ return _url;
+ }
+ },
+ {% endif %}
height: '{{ player_height }}',
autostart: true
} {% if polemic == 'all' or polemic == 'tweet' %},
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html Mon Nov 12 16:17:22 2012 +0100
@@ -90,7 +90,7 @@
<div id="iframe_div_premode" class="embedPersonnalisation">
<input type="radio" id="mode_1" name="embed_mode" value="mode1" checked onClick="mode1()" > {% trans 'Basic configuration' %} </input><br>
<input type="radio" id="mode_2" name="embed_mode" value="mode2" onClick="mode2()"> {% trans 'Polemic configuration' %} </input><br>
- <input type="radio" id="mode_3" name="embed_mode" value="mode3" onClick="mode3()"> {% trans 'Polemic configuration with sparkline and tagcloud' %} </input><br>
+ <input type="radio" id="mode_3" name="embed_mode" value="mode3" onClick="mode3()"> {% trans 'Polemic configuration with tagcloud, annotationsList and Social widgets' %} </input><br>
<br>
</div>
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/groups.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/groups.html Mon Nov 12 16:17:22 2012 +0100
@@ -19,7 +19,6 @@
function init_events(base_node) {
init_events_projects(base_node, "{% url ldt.ldt_utils.views.workspace.popup_embed %}", project_filter_url, publish_project_url, unpublish_project_url)
- init_events_groups(base_node, "{% url ldt.ldt_utils.views.workspace.popup_embed %}", groups_filter_url);
}
var global_csrf_token = "{{ csrf_token }}";
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html Mon Nov 12 16:17:22 2012 +0100
@@ -34,11 +34,10 @@
},
widgets: [
{
+ type: "AutoPlayer",
{% if external_url %}
- type: "AutoPlayer",
video: "{{ external_url }}",
{% else %}
- type: "JwpPlayer",
streamer: function(_url) {
var _matches = _url.match(/^[^\/]+\/\/[^\/]+\/[^\/]+\//);
if (_matches) {
@@ -47,8 +46,6 @@
return _url;
}
},
- live: true,
- provider: "rtmp",
{% endif %}
height: 300,
autostart: true
@@ -90,7 +87,6 @@
},{
type: "CreateAnnotation",
api_endpoint_template: "{{WEB_URL}}{% url api_dispatch_list resource_name='annotations' api_name='1.0' %}",
- api_method: "PUT",
after_send_timeout: 8000,
show_mic_record: {% if show_mic_record %}true{% else %}false{% endif %},
close_after_send: false,
--- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/permissions.html Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/permissions.html Mon Nov 12 16:17:22 2012 +0100
@@ -121,8 +121,10 @@
<div id="permissioncontainer" class="append-bottom clear" {% if media_form and media_form.media_public.value %}style="display: none;"{% endif %}>
<div id="elemslistcontainer" clas="span-9">
+ {% if media_form %}
<div id="content_public">{{ content_form.is_public }}<label>{% trans "publish the title on the front" %}</label></div>
<br />
+ {% endif %}
<div id="elemslistheader">
{% trans "User and group list" %}<br />
<div class="searchfield span-4">
@@ -147,7 +149,9 @@
<a href="#" id="selectelems"><img src="{{LDT_MEDIA_PREFIX}}img/to-right.gif" title="{% trans "select users" %}"></a><br />
<a href="#" id="removeelems"><img src="{{LDT_MEDIA_PREFIX}}img/to-left.gif" title="{% trans "remove users" %}"></a>
</div>
+ {% if media_form %}
<br /> <br />
+ {% endif %}
<div id="selectedlistcontainer" class="span-9 last">
<div id="selectedlistheader" >
{% trans "Members list" %}
--- a/src/ldt/ldt/ldt_utils/tests.py Mon Nov 12 15:03:36 2012 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-"""
-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.conf import settings
-from django.test import TestCase
-from ldt.ldt_utils.models import User
-from models import Project, Content
-from utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
-import lxml.etree
-import tempfile
-import unittest
-import uuid
-
-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
-"""}
-
-class UtilsTest(unittest.TestCase):
- def setUp(self):
- self.user = User()
- self.user.username = "toto"
- self.LU = LdtUtils()
-
- self.project = Project(title="titleproj1", owner=self.user)
- self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
- self.project.id = "11"
- self.project.ldt_id = str(uuid.uuid1())
- self.project.description = "proj1description"
- self.project.save()
-
- self.projectcopy = Project(title="the2ndproject")
- self.projectcopy.id = "22"
-
- def tearDown(self):
- self.project.delete()
- self.projectcopy.delete()
- #self.cont1.delete()
- #self.cont2.delete()
-
- def test_generate_ldt(self):
- self.cont1 = Content(iriurl="id1/iriurl1")
- self.cont1.iri_id = "id1"
- self.cont1.save()
-
- self.cont2 = Content(iriurl="id2/iriurl2")
- self.cont2.iri_id = "id2"
- self.cont2.save()
-
- self.project.contents.add(self.cont1, self.cont2)
-
- f = tempfile.TemporaryFile(mode='r+')
- doc = self.LU.generate_ldt(Content.objects.all())
- doc.write(f, pretty_print=True)
- f.seek(0)
- ldoc = lxml.etree.parse(f)
- self.assertEqual(ldoc.xpath("/iri/displays/display/content")[10].get("id"), self.cont2.iri_id)
- self.assertEqual(ldoc.xpath("/iri/medias/media")[9].get("id"), self.cont1.iri_id)
- f.close()
-
- def test_generate_init(self):
- self.cont3 = Content(iriurl="id3/iriurl1")
- self.cont3.iri_id = "id3"
- self.cont3.save()
-
- self.cont4 = Content(iriurl="id4/iriurl2")
- self.cont4.iri_id = "id4"
- self.cont4.save()
-
- self.project.contents.add(self.cont3, self.cont4)
- ldoc = self.LU.generate_init(['all', 'foo'], 'ldt.ldt_utils.views.search_ldt')
- self.assertEqual(ldoc.xpath("/iri/files/init")[0].tag, "init")
- self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library")
-
- def test_create_ldt(self):
- self.cont5 = Content(iriurl="id5/iriurl1")
- self.cont5.iri_id = "id5"
- self.cont5.save()
-
- self.cont6 = Content(iriurl="id6/iriurl2")
- self.cont6.iri_id = "id6"
- self.cont6.save()
-
- self.project.contents.add(self.cont5, self.cont6)
- self.project.ldt = ""
- create_ldt(self.project, self.user)
- ldt = lxml.etree.fromstring(self.project.ldt_encoded)
- self.assertEqual(ldt.xpath("/iri")[0].tag, "iri")
- self.assertEqual(ldt.xpath("/iri/project")[0].get("title"), self.project.title)
- self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.iri_url())
- self.assertEqual(ldt.xpath("/iri/medias/media")[1].get("id"), self.cont6.iri_id)
-
- def test_copy_ldt(self):
- self.cont7 = Content(iriurl="id7/iriurl1")
- self.cont7.iri_id = "id7"
- self.cont7.save()
-
- self.cont8 = Content(iriurl="id8/iriurl2")
- self.cont8.iri_id = "id8"
- self.cont8.save()
-
- self.project.contents.add(self.cont7, self.cont8)
- copy_ldt(self.project, self.projectcopy, self.user)
- ldt1 = lxml.etree.fromstring(self.project.ldt_encoded)
- ldt2 = lxml.etree.fromstring(self.projectcopy.ldt_encoded)
- self.assertTrue(ldt1.xpath("/iri/project")[0].get("id") != ldt2.xpath("/iri/project")[0].get("id"))
- self.assertEqual(ldt1.xpath("/iri/medias/media")[0].get("id"), ldt2.xpath("/iri/medias/media")[0].get("id"))
- self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble")[0].get("title"), ldt2.xpath("/iri/annotations/content/ensemble")[0].get("title"))
- self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"), ldt2.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"))
- self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text, ldt2.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text.strip("\n\t"))
-
- def test_create_empty_iri(self):
- self.cont9 = Content(iriurl="id9/iriurl1")
- self.cont9.iri_id = "id9"
- self.cont9.save()
-
- self.cont10 = Content(iriurl="id10/iriurl2")
- self.cont10.iri_id = "id10"
- self.cont10.save()
-
- self.project.contents.add(self.cont9, self.cont10)
- tmp = tempfile.TemporaryFile(mode='r+')
- create_empty_iri(tmp, self.cont9, "admin")
- tmp.seek(0)
- ldoc = lxml.etree.parse(tmp)
- self.assertEqual(ldoc.xpath("/iri/head/meta")[0].get("content"), self.cont9.iri_id)
- self.assertEqual(ldoc.xpath("/iri/body/medias/media/video")[0].get("id"), self.cont9.iri_id)
- tmp.close()
-
- def test_add_annotation(self):
-
- self.cont11 = Content(iriurl="id11/iriurl1")
- self.cont11.iri_id = "id11"
- self.cont11.save()
-
- self.project.contents.add(self.cont11)
- self.project.ldt = ""
- create_ldt(self.project, self.user)
-
- self.LA = LdtAnnotation(self.project)
-
- self.LA.add("id11", "cutting", "title", "text", ["tag1", "tag2"], "800",
- "10000", "jdoe", "2011-09-10T09:12:58")
- self.LA.save()
- ldt = lxml.etree.fromstring(self.project.ldt)
- ann = ldt.xpath('/iri/annotations/content[@id="id11"]/ensemble/decoupage/elements/element')[0]
- title = ann.xpath('title')[0].text
- abstract = ann.xpath('abstract')[0].text
-
- self.assertEqual(ann.get("author"), "jdoe")
- self.assertEqual(title, "title")
- self.assertEqual(abstract, "text")
-
-
-class ViewsTest(unittest.TestCase):
- def setUp(self):
- self.project = Project()
- self.project.id = "121"
- self.project.save()
- self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
-
- self.cont1 = Content(iriurl="/laurentcantet_entrelesmurs/iriurl1")
- self.cont1.iri_id = 'laurentcantet_entrelesmurs'
- self.cont1.save()
-
- self.cont2 = Content(iriurl="/content_notinldt/iriurl2")
- self.cont2.iri_id = 'content_notinldt'
- self.cont2.save()
-
- self.project.contents.add(self.cont1, self.cont2)
-
- def tearDown(self):
- self.project.delete()
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/tests/__init__.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,4 @@
+from content_tests import *
+from ldt_tests import *
+from media_tests import *
+from project_tests import *
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/tests/content_tests.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,75 @@
+"""
+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 ldt.test.testcases import OAuthWebTestCase, TestCase
+from django.conf import settings
+from django.test import TestCase
+from ldt.ldt_utils.models import User, Project, Content, Media
+from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.test.client import Client
+import lxml.etree
+import tempfile
+import unittest
+import uuid
+import logging
+
+class ContentTest(TestCase):
+
+ fixtures = ['base_data.json', 'user_data.json']
+
+ def setUp(self):
+ self.client = Client()
+ User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
+
+ client = self.client.login(username='blop', password='blop')
+
+ self.user = User()
+ self.user.username = 'blop'
+
+ #test the creation of a content without media
+ def test_create_content_v1(self):
+ self.cont12 = Content(iriurl="id12/iriurl12", duration = 100)
+ self.cont12.iri_id = "id112"
+ self.cont12.save()
+
+ self.assertEqual(Content.objects.get(iri_id=self.cont12.iri_id), self.cont12)
+
+ #test the creation of a content with a media
+ def test_create_content_v2(self):
+ self.media13 = Media()
+ self.cont13 = Content(iriurl="id13/iriurl13", duration = 100, media_obj = self.media13)
+ self.cont13 = Content(iriurl="id13/iriurl13", duration = 100)
+ self.cont13.iri_id = "id113"
+ self.cont13.save()
+
+ self.assertEqual(Content.objects.get(iri_id=self.cont13.iri_id), self.cont13)
+
+ #test the deletion of a content without media
+ def test_del_content_v1(self):
+ self.cont14 = Content(iriurl="id14/iriurl14", duration = 100)
+ self.cont14.iri_id = "id114"
+ self.cont14.save()
+
+ self.cont14.delete()
+ self.cont14.commit()
+
+ with self.assertRaises(Content.DoesNotExist):
+ Content.objects.get(iri_id=self.cont14.iri_id)
+
+ #test the deletion of a content with media
+ def test_del_content_v2(self):
+ self.media15 = Media()
+ self.cont15 = Content(iriurl="id15/iriurl15", duration = 100, media_obj = self.media15)
+ self.cont15.iri_id = "id115"
+ self.cont15.save()
+
+ self.cont15.delete()
+ self.cont15.commit()
+
+ with self.assertRaises(Content.DoesNotExist):
+ Content.objects.get(iri_id=self.cont15.iri_id)
+
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/tests/ldt_tests.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,165 @@
+"""
+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 ldt.test.testcases import OAuthWebTestCase, TestCase
+from django.conf import settings
+from django.test import TestCase
+from ldt.ldt_utils.models import User, Project, Content, Media
+from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.test.client import Client
+import lxml.etree
+import tempfile
+import unittest
+import uuid
+import logging
+
+class UtilsTest(TestCase):
+
+ fixtures = ['base_data.json', 'user_data.json']
+
+ def setUp(self):
+ self.client = Client()
+ User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
+
+ client = self.client.login(username='blop', password='blop')
+
+ self.user = User()
+ self.user.username = 'blop'
+
+ self.LU = LdtUtils()
+ self.project = Project(title="titleproj1", owner=self.user)
+ self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+ self.project.id = "11321"
+ self.project.ldt_id = str(uuid.uuid1())
+ self.project.description = "proj1description"
+ self.project.save()
+
+ self.projectcopy = Project(title="the2ndproject")
+ self.projectcopy.id = "21"
+
+ def tearDown(self):
+ self.project.delete()
+ self.projectcopy.delete()
+
+ def test_generate_ldt(self):
+ self.cont1 = Content(iriurl="cont1_id/iriurl1", duration=123)
+ self.cont1.iri_id = "cont1_id"
+ self.cont1.save()
+
+ self.cont2 = Content(iriurl="cont2_id/iriurl2", duration=100)
+ self.cont2.iri_id = "cont2_id"
+ self.cont2.save()
+
+ self.project.contents.add(self.cont1, self.cont2)
+
+ f = tempfile.TemporaryFile(mode='r+')
+ doc = self.LU.generate_ldt(Content.objects.all())
+ doc.write(f, pretty_print=True)
+ f.seek(0)
+ ldoc = lxml.etree.parse(f)
+ self.assertEqual(ldoc.xpath("/iri/displays/display/content")[0].get("id"), self.cont1.iri_id)
+ self.assertEqual(ldoc.xpath("/iri/medias/media")[0].get("id"), self.cont1.iri_id)
+
+ self.assertEqual(ldoc.xpath("/iri/displays/display/content")[1].get("id"), self.cont2.iri_id)
+ self.assertEqual(ldoc.xpath("/iri/medias/media")[1].get("id"), self.cont2.iri_id)
+ f.close()
+
+ """
+ def test_generate_init(self):
+ self.cont3 = Content(iriurl="id3/iriurl3", duration=111)
+ self.cont3.iri_id = "id3"
+ self.cont3.save()
+
+ self.cont4 = Content(iriurl="id4/iriurl4", duration=111)
+ self.cont4.iri_id = "id4"
+ self.cont4.save()
+
+ self.project.contents.add(self.cont3, self.cont4)
+ ldoc = self.LU.generate_init([], 'ldt.ldt_utils.views.search_ldt')
+ self.assertEqual(ldoc.xpath("/iri/files/init")[0].tag, "init")
+ self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library")
+ """
+
+ def test_create_ldt(self):
+ self.cont5 = Content(iriurl="id5/iriurl5", duration=111)
+ self.cont5.iri_id = "id5"
+ self.cont5.save()
+
+ self.cont6 = Content(iriurl="id6/iriurl6", duration=111)
+ self.cont6.iri_id = "id6"
+ self.cont6.save()
+
+ self.project.contents.add(self.cont5, self.cont6)
+ self.project.ldt = ""
+ create_ldt(self.project, self.user)
+ ldt = lxml.etree.fromstring(self.project.ldt_encoded)
+ self.assertEqual(ldt.xpath("/iri")[0].tag, "iri")
+ self.assertEqual(ldt.xpath("/iri/project")[0].get("title"), self.project.title)
+ self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.iri_url())
+ self.assertEqual(ldt.xpath("/iri/medias/media")[1].get("id"), self.cont6.iri_id)
+
+ def test_copy_ldt(self):
+ self.cont7 = Content(iriurl="id7/iriurl7", duration=111)
+ self.cont7.iri_id = "id7"
+ self.cont7.save()
+
+ self.cont8 = Content(iriurl="id8/iriurl8", duration=111)
+ self.cont8.iri_id = "id8"
+ self.cont8.save()
+
+ self.project.contents.add(self.cont7, self.cont8)
+ copy_ldt(self.project, self.projectcopy, self.user)
+ ldt1 = lxml.etree.fromstring(self.project.ldt_encoded)
+ ldt2 = lxml.etree.fromstring(self.projectcopy.ldt_encoded)
+ self.assertTrue(ldt1.xpath("/iri/project")[0].get("id") != ldt2.xpath("/iri/project")[0].get("id"))
+ self.assertEqual(ldt1.xpath("/iri/medias/media")[0].get("id"), ldt2.xpath("/iri/medias/media")[0].get("id"))
+ self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble")[0].get("title"), ldt2.xpath("/iri/annotations/content/ensemble")[0].get("title"))
+ self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"), ldt2.xpath("/iri/annotations/content/ensemble/decoupage")[0].get("id"))
+ self.assertEqual(ldt1.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text, ldt2.xpath("/iri/annotations/content/ensemble/decoupage/title")[1].text.strip("\n\t"))
+
+ def test_create_empty_iri(self):
+ self.cont9 = Content(iriurl="id9/iriurl9", duration=111)
+ self.cont9.iri_id = "id9"
+ self.cont9.save()
+
+ self.cont10 = Content(iriurl="id10/iriurl10", duration=111)
+ self.cont10.iri_id = "id10"
+ self.cont10.save()
+
+ self.project.contents.add(self.cont9, self.cont10)
+ tmp = tempfile.TemporaryFile(mode='r+')
+ create_empty_iri(tmp, self.cont9, "admin")
+ tmp.seek(0)
+ ldoc = lxml.etree.parse(tmp)
+ self.assertEqual(ldoc.xpath("/iri/head/meta")[0].get("content"), self.cont9.iri_id)
+ self.assertEqual(ldoc.xpath("/iri/body/medias/media/video")[0].get("id"), self.cont9.iri_id)
+ tmp.close()
+
+ def test_add_annotation(self):
+
+ self.cont11 = Content(iriurl="id11/iriurl11", duration=111)
+ self.cont11.iri_id = "id11"
+ self.cont11.save()
+
+ self.project.contents.add(self.cont11)
+ self.project.ldt = ""
+ create_ldt(self.project, self.user)
+
+ self.LA = LdtAnnotation(self.project)
+
+ self.LA.add("id11", "cutting_id", "cutting_title", "title", "text", ["tag1", "tag2"], "800",
+ "10000", "jdoe", "2011-09-10T09:12:58")
+ self.LA.save()
+ ldt = lxml.etree.fromstring(self.project.ldt)
+ ann = ldt.xpath('/iri/annotations/content[@id="id11"]/ensemble/decoupage/elements/element')[0]
+ title = ann.xpath('title')[0].text
+ abstract = ann.xpath('abstract')[0].text
+
+ self.assertEqual(ann.get("author"), "jdoe")
+ self.assertEqual(title, "title")
+ self.assertEqual(abstract, "text")
+
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/tests/media_tests.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,50 @@
+"""
+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 ldt.test.testcases import OAuthWebTestCase, TestCase
+from django.conf import settings
+from django.test import TestCase
+from ldt.ldt_utils.models import User, Project, Content, Media
+from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.test.client import Client
+from django.core.exceptions import ObjectDoesNotExist
+import lxml.etree
+import tempfile
+import unittest
+import uuid
+import logging
+
+class MediaTest(TestCase):
+
+ fixtures = ['base_data.json', 'user_data.json']
+
+ def setUp(self):
+ self.client = Client()
+ User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
+
+ client = self.client.login(username='blop', password='blop')
+
+ self.user = User()
+ self.user.username = 'blop'
+
+ def test_create_media(self):
+ self.media1, created = Media.objects.get_or_create(src = "http://www.youtube.com/watch?v=O2G-PEtyKSY")
+ self.media1.id = 1
+ self.media1.save()
+
+ self.assertEqual(Media.objects.get(id=self.media1.id), self.media1)
+
+ def test_del_media(self):
+ self.media2 = Media()
+ self.media2.id = 2
+ self.media2.save()
+
+ self.media2.delete()
+
+ with self.assertRaises(Media.DoesNotExist):
+ Media.objects.get(id=self.media2.id)
+
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/tests/project_tests.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,55 @@
+"""
+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 ldt.test.testcases import OAuthWebTestCase, TestCase
+from django.conf import settings
+from django.test import TestCase
+from ldt.ldt_utils.models import User, Project, Content, Media
+from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.test.client import Client
+import lxml.etree
+import tempfile
+import unittest
+import uuid
+import logging
+
+class ProjectTest(TestCase):
+
+ fixtures = ['base_data.json', 'user_data.json']
+
+ def setUp(self):
+ self.client = Client()
+ User.objects.create_superuser('blop', 'blop@blop.com', 'blop')
+
+ client = self.client.login(username='blop', password='blop')
+
+ self.user = User()
+ self.user.username = 'blop'
+
+ def test_create_project(self):
+ self.project2 = Project(title="titleproj2", owner=self.user)
+ self.project2.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a212" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+ self.project2.ldt_id = str(uuid.uuid1())
+ self.project2.description = "proj2description"
+ self.project2.save()
+
+ self.assertEqual(Project.objects.get(ldt_id=self.project2.ldt_id), self.project2)
+
+ #test deletion of project without annotation
+ def test_del_project_v1(self):
+ self.project3 = Project(title="titleproj3", owner=self.user)
+ self.project3.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a333" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+ self.project3.id = "333"
+ self.project3.ldt_id = str(uuid.uuid1())
+ self.project3.description = "proj3description"
+ self.project3.save()
+
+ self.project3.delete()
+
+ with self.assertRaises(Project.DoesNotExist):
+ Project.objects.get(ldt_id=self.project3.ldt_id)
+
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/tests/view_tests.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,38 @@
+"""
+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 ldt.test.testcases import OAuthWebTestCase, TestCase
+from django.conf import settings
+from django.test import TestCase
+from ldt.ldt_utils.models import User, Project, Content, Media
+from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt
+from ldt.test.client import Client
+import lxml.etree
+import tempfile
+import unittest
+import uuid
+import logging
+
+class ViewsTest(unittest.TestCase):
+ def setUp(self):
+ self.project = Project()
+ self.project.id = "121"
+ self.project.save()
+ self.project.ldt = '<iri ldtversion="1.0.3" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/"><project id="af3b99e4-b695-11df-bfde-00145ea4a2be" user="admin" title="CA:reponse a TC" abstract=""/> <medias> <media extra="" id="laurentcantet_entrelesmurs" pict="" src="http://amateur.iri.centrepompidou.fr//atelier/static/media/ldt/laurentcantet_entrelesmurs/laurentcantet_entrelesmurs.iri" video="rtmp://media.iri.centrepompidou.fr/ddc_player/video/regardssignes/"/> </medias> <annotations> <content id="laurentcantet_entrelesmurs"> <ensemble id="ens_perso" idProject="fe0d5d4c-2201-11df-8a24-00145ea4a2be" title="Decoupages personnels" author="perso" abstract=""> <decoupage id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" author="perso"> <title>CA: prof et admin</title> <abstract/> <elements> <element id="s_442AAB3A-42DA-F9BF-75E7-D2A0663FD5FF" begin="985690" dur="373222" author="" date="2010/09/02" color="16711680" src=""> <title/> <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> <decoupage id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" author="perso"> <title>TC: prof et admin</title> <abstract/> <elements> <element id="s_880D9D4B-8BC0-BA43-5ECA-04EBA9FC9E59" begin="2426894" dur="141478" author="" date="2010/02/25" color="10053375" src=""> <title>Conseil de classe</title> <abstract/> <audio source=""/> <tags> <tag>Argumentation</tag> </tags> </element> <element id="s_D568A57C-7110-DED2-3165-04EC54387060" begin="5052858" dur="124407" author="" date="2010/02/25" color="10053375" src=""> <title>conseil de classe</title> <abstract>Reprise de la figure precedente</abstract> <audio source="undefined"/> <tags/> </element> </elements> </decoupage> </ensemble> </content> </annotations> <displays> <display id="0" title="Init view" idsel="laurentcantet_entrelesmurs" tc="2426424" zoom="0" scroll="0" infoBAB=""> <audio source=""/> <content id="laurentcantet_entrelesmurs"> <decoupage idens="en_2" id="de_PPP" tagsSelect=""/> <decoupage idens="laurentcantet_entrelesmurs" id="c_14A2E638-1936-97DC-E303-2DBA6A82A8B3" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EEEF5C29-86E1-4AAE-E068-04EB5B00E492" tagsSelect=""/> <decoupage idens="ens_perso" id="c_EFC3FFE7-0204-A086-EBEC-D2A03A0E56CB" tagsSelect=""/> </content> </display> </displays> <edits> <editing id="0" tags=""> <title>Bout a bout 1</title> <abstract/> <edit id="edit1" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> <edit id="edit2" tags=""> <eList/> <caption/> <audio/> <mList/> </edit> </editing> </edits> </iri>'
+
+ self.cont1 = Content(iriurl="/laurentcantet_entrelesmurs/iriurl1")
+ self.cont1.iri_id = 'laurentcantet_entrelesmurs'
+ self.cont1.save()
+
+ self.cont2 = Content(iriurl="/content_notinldt/iriurl2")
+ self.cont2.iri_id = 'content_notinldt'
+ self.cont2.save()
+
+ self.project.contents.add(self.cont1, self.cont2)
+
+ def tearDown(self):
+ self.project.delete()
--- a/src/ldt/ldt/ldt_utils/urls.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/urls.py Mon Nov 12 16:17:22 2012 +0100
@@ -9,7 +9,7 @@
url(r'^searchInit/(?P<field>.*)/(?P<query>.*)$', 'views.lignesdetemps.search_init'),
url(r'^searchForm/$', 'views.workspace.search_form'),
url(r'^published/$', 'views.workspace.published_project'),
- url(r'^groups/$', 'views.workspace.groups'),
+ url(r'^groups/$', 'views.workspace.groups', name="groups-view"),
url(r'^get_group_projects/$', 'views.group.get_group_projects'),
url(r'^search/$', 'views.workspace.search_index'),
url(r'^search/(?P<field>.*)/(?P<query>.*)$', 'views.lignesdetemps.search_index_get'),
--- a/src/ldt/ldt/ldt_utils/utils.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/utils.py Mon Nov 12 16:17:22 2012 +0100
@@ -4,9 +4,9 @@
from StringIO import StringIO
import datetime
import django.core.urlresolvers
-import lxml.etree
-import urllib
+import lxml.etree #@UnresolvedImport
import uuid
+from ldt.utils.url import request_with_auth
__BOOLEAN_DICT = {
'false':False,
@@ -25,12 +25,12 @@
node_list = [element_node.text]
return reduce(lambda t, s: t + s, node_list , "")
-def boolean_convert(bool):
- if bool is None:
+def boolean_convert(bool_val):
+ if bool_val is None:
return False
- if bool is True or bool is False:
- return bool
- key = str(bool).lower()
+ if bool_val is True or bool_val is False:
+ return bool_val
+ key = str(bool_val).lower()
return __BOOLEAN_DICT.get(key, False)
def generate_uuid():
@@ -102,7 +102,8 @@
for content in contentList:
contentd = lxml.etree.SubElement(display, "content")
contentd.set(u"id", content.iri_id)
- filepath = urllib.urlopen(content.iri_url())
+ __, content = request_with_auth(content.iri_url())
+ filepath = StringIO(content)
udoc = lxml.etree.parse(filepath)
res = udoc.xpath("/iri/body/ensembles/ensemble/decoupage")
@@ -357,8 +358,8 @@
url = content.iri_url()
else:
url = content.iriurl
- file = urllib.urlopen(url)
- doc = lxml.etree.parse(file)
+ __, content = request_with_auth(url)
+ doc = lxml.etree.parse(StringIO(content))
res = doc.xpath("/iri/body/ensembles/ensemble/decoupage")
#node decoupage
@@ -441,7 +442,7 @@
new_project.save()
return new_project
-def create_empty_iri(file, content, username):
+def create_empty_iri(iri_file, content, username):
iri = lxml.etree.Element('iri')
doc = lxml.etree.ElementTree(iri)
@@ -492,7 +493,7 @@
lxml.etree.SubElement(body, 'display')
- doc.write(file, pretty_print=True)
+ doc.write(iri_file, pretty_print=True)
def update_iri(filepath, content, username):
--- a/src/ldt/ldt/ldt_utils/views/content.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/content.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,37 +1,158 @@
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
+from django.core.files import File
from django.core.urlresolvers import reverse
+from django.db import transaction
from django.forms.models import model_to_dict
-from django.core.files import File
-from django.db import transaction
from django.forms.util import ErrorList
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.utils.translation import ugettext as _, ungettext
+from guardian.shortcuts import remove_perm
from ldt.ldt_utils.forms import ContentForm, MediaForm
-from guardian.shortcuts import remove_perm
from ldt.ldt_utils.models import Content, Media, Project
-from ldt.security.utils import assign_perm_to_obj, add_change_attr, get_userlist, get_userlist_model
from ldt.security.cache import cached_assign
+from ldt.security.utils import (assign_perm_to_obj, add_change_attr, get_userlist,
+ get_userlist_model)
from ldt.user.forms import PictureForm
from tagging.models import Tag, TaggedItem
+import datetime
import ldt.utils.path as ldt_utils_path
import logging
+import math
import mimetypes
import os
-import urllib2
-import subprocess
import re
-import datetime
-import math
import requests
-import urlparse
+import subprocess
+import sys
import tempfile
+import traceback
+import urllib2
+import urlparse
+#from django.core.files.temp import NamedTemporaryFile
+def media_management(request, media_input_type, cleaned_data, content_form, media_form, form_status):
+ if media_input_type == "none":
+ media = None
+ elif media_input_type == "link":
+ media = content_form.cleaned_data["media_obj"]
+ created = False
+ elif media_input_type == "create":
+ del cleaned_data["media_file"]
+ if not cleaned_data['videopath']:
+ cleaned_data['videopath'] = settings.STREAM_URL
+ # if the source is already http:// or rtmp:// we don't have to add STREAM_URL
+ if cleaned_data['src'].startswith("rtmp://") or cleaned_data['src'].startswith("http://"):
+ cleaned_data['videopath'] = ''
+
+ media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
+
+ elif media_input_type == "url" or media_input_type == "upload" :
+ # copy file
+ #complet src
+ destination_file = None
+ source_file = None
+ try:
+ if media_input_type == "url":
+ url = cleaned_data["external_src_url"]
+ source_file = urllib2.urlopen(url)
+ source_filename = source_file.info().get('Content-Disposition', None)
+ if not source_filename:
+ source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1]
+ elif media_input_type == "upload":
+ #source_file = request.FILES['media-media_file']
+ # At this point the file has already be uploaded thanks to the upload view, and original file name is sent through a post var
+ source_filename = request.POST["media-local_file_name"]
+
+ source_filename = ldt_utils_path.sanitize_filename(source_filename)
+ destination_filepath = os.path.join(settings.STREAM_PATH, source_filename)
+ base_source_filename = source_filename
+ extension = base_source_filename.split(".")[-1]
+ if extension == base_source_filename:
+ extension = ""
+ base_basename_filename = base_source_filename
+ else:
+ base_basename_filename = base_source_filename[:-1 * (len(extension) + 1)]
+ i = 0
+
+ while os.path.exists(destination_filepath):
+ base_source_filename = "%s.%d.%s" % (base_basename_filename, i, extension)
+ destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename)
+ i += 1
+
+ if media_input_type == "url":
+ # we upload the file if we are in url case
+ destination_file = open(destination_filepath, "wb")
+ chunck = source_file.read(2048)
+ while chunck:
+ destination_file.write(chunck)
+ chunck = source_file.read(2048)
+
+ elif media_input_type == "upload":
+ # The media file has been uploaded in the session temp folder
+ # so we just have to move to the regular folder and rename it.
+ if os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)):
+ os.rename(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename), os.path.join(settings.STREAM_PATH, base_source_filename))
+
+
+ src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/")
+ if len(src_prefix) > 0:
+ cleaned_data["src"] = src_prefix + "/" + base_source_filename
+ else:
+ cleaned_data["src"] = base_source_filename
+
+
+ except Exception as inst:
+ logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable
+ form_status = "error"
+ #set error for form
+ if media_input_type == "url":
+ errors = media_form._errors.setdefault("external_src_url", ErrorList())
+ errors.append(_("Problem when downloading file from url : ") + url)
+ elif media_input_type == "upload":
+ errors = media_form._errors.setdefault("media_file", ErrorList())
+ errors.append(_("Problem when uploading file : ") + str(inst))
+ finally:
+ if media_input_type == "url":
+ if destination_file:
+ destination_file.close()
+ if source_file:
+ source_file.close()
+
+
+ if form_status != "error":
+ del cleaned_data["media_file"]
+ if not cleaned_data['videopath']:
+ cleaned_data['videopath'] = settings.STREAM_URL
+ mimetype = cleaned_data.get('mimetype_field', None)
+ if not mimetype:
+ mimetype = mimetypes.guess_type(cleaned_data['src'])
+ cleaned_data['mimetype_field'] = mimetype
+ media, created = Media.safe_objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
+ cached_assign('view_media', request.user, media)
+ else:
+ media = None
+
+
+ if media and not created:
+ for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title', 'front_project'):
+ setattr(media, attribute, cleaned_data.get(attribute))
+ mimetype = cleaned_data.get('mimetype_field', None)
+ if not mimetype:
+ mimetype = mimetypes.guess_type(media.src)
+ media.mimetype_field = mimetype
+ cached_assign('view_media', request.user, media)
+ cached_assign('change_media', request.user, media)
+ media.save()
+
+ return media, form_status
+
+
@transaction.commit_manually
-def write_content_base(request, iri_id=None):
+def write_content_base(request, iri_id=None):
if iri_id:
instance_content = Content.safe_objects.get(iri_id=iri_id) #@UndefinedVariable
instance_media = instance_content.media_obj
@@ -46,10 +167,8 @@
form_status = 'none'
errors_transaction = []
- # catch error from creating content, project, media
- try:
- if request.method == "POST":
-
+ if request.method == "POST":
+ try:
if instance_content is not None:
content_instance_val = model_to_dict(instance_content, exclude=ContentForm.Meta.exclude)
else:
@@ -82,11 +201,11 @@
if request.user.is_staff:
content_form.fields['front_project'].queryset = Project.objects.filter(contents__in=[instance_content])
-
media_valid = media_form.is_valid()
content_valid = content_form.is_valid()
picture_valid = picture_form.is_valid()
+
if 'image' in request.POST.keys():
image_link = request.POST.get('url_image')
if picture_valid and image_link!='' :
@@ -98,8 +217,8 @@
img_temp.flush()
picture_form.cleaned_data["image"]=File(img_temp)
except Exception as inst:
- logging.debug("couldn't download video thumbnail from image_link : "+str(image_link))
- logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid) + "picture : valid :" +str(picture_valid)+" loulou") #@UndefinedVariable
+ logging.debug("couldn't download video thumbnail from image_link : " + str(image_link))
+ logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid) + "picture : valid :" +str(picture_valid)) #@UndefinedVariable
if media_valid and content_valid and picture_valid:
@@ -110,117 +229,13 @@
media_input_type = content_form.cleaned_data["media_input_type"]
- if media_input_type == "none":
- media = None
- elif media_input_type == "link":
- media = content_form.cleaned_data["media_obj"]
- created = False
- elif media_input_type == "create":
- del cleaned_data["media_file"]
- if not cleaned_data['videopath']:
- cleaned_data['videopath'] = settings.STREAM_URL
- # if the source is already http:// or rtmp:// we don't have to add STREAM_URL
- if cleaned_data['src'].startswith("rtmp://") or cleaned_data['src'].startswith("http://"):
- cleaned_data['videopath'] = ''
- media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
- elif media_input_type == "url" or media_input_type == "upload" :
- # copy file
- #complet src
- destination_file = None
- source_file = None
- try:
- if media_input_type == "url":
- url = cleaned_data["external_src_url"]
- source_file = urllib2.urlopen(url)
- source_filename = source_file.info().get('Content-Disposition', None)
- if not source_filename:
- source_filename = urlparse.urlparse(url).path.rstrip("/").split('/')[-1]
- elif media_input_type == "upload":
- #source_file = request.FILES['media-media_file']
- # At this point the file has already be uploaded thanks to the upload view, and original file name is sent through a post var
- source_filename = request.POST["media-local_file_name"]
-
- source_filename = ldt_utils_path.sanitize_filename(source_filename)
- destination_filepath = os.path.join(settings.STREAM_PATH, source_filename)
- base_source_filename = source_filename
- extension = base_source_filename.split(".")[-1]
- if extension == base_source_filename:
- extension = ""
- base_basename_filename = base_source_filename
- else:
- base_basename_filename = base_source_filename[:-1 * (len(extension) + 1)]
- i = 0
-
- while os.path.exists(destination_filepath):
- base_source_filename = "%s.%d.%s" % (base_basename_filename, i, extension)
- destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename)
- i += 1
-
- if media_input_type == "url":
- # we upload the file if we are in url case
- destination_file = open(destination_filepath, "wb")
- chunck = source_file.read(2048)
- while chunck:
- destination_file.write(chunck)
- chunck = source_file.read(2048)
-
- elif media_input_type == "upload":
- # The media file has been uploaded in the session temp folder
- # so we just have to move to the regular folder and rename it.
- if os.path.exists(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename)):
- os.rename(os.path.join(settings.STREAM_PATH, "tmp/" + request.COOKIES[settings.SESSION_COOKIE_NAME] + "/", source_filename), os.path.join(settings.STREAM_PATH, base_source_filename))
-
-
- src_prefix = settings.STREAM_SRC_PREFIX.rstrip("/")
- if len(src_prefix) > 0:
- cleaned_data["src"] = src_prefix + "/" + base_source_filename
- else:
- cleaned_data["src"] = base_source_filename
-
-
- except Exception as inst:
- logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable
- form_status = "error"
- #set error for form
- if media_input_type == "url":
- errors = media_form._errors.setdefault("external_src_url", ErrorList())
- errors.append(_("Problem when downloading file from url : ") + url)
- elif media_input_type == "upload":
- errors = media_form._errors.setdefault("media_file", ErrorList())
- errors.append(_("Problem when uploading file : ") + str(inst))
- finally:
- if media_input_type == "url":
- if destination_file:
- destination_file.close()
- if source_file:
- source_file.close()
-
-
- if form_status != "error":
- #try:
- del cleaned_data["media_file"]
- if not cleaned_data['videopath']:
- cleaned_data['videopath'] = settings.STREAM_URL
- mimetype = cleaned_data.get('mimetype_field', None)
- if not mimetype:
- mimetype = mimetypes.guess_type(cleaned_data['src'])
- cleaned_data['mimetype_field'] = mimetype
- media, created = Media.safe_objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data) #@UndefinedVariable
- cached_assign('view_media', request.user, media)
- else:
- media = None
-
-
- if media and not created:
- for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title', 'front_project'):
- setattr(media, attribute, cleaned_data.get(attribute))
- mimetype = cleaned_data.get('mimetype_field', None)
- if not mimetype:
- mimetype = mimetypes.guess_type(media.src)
- media.mimetype_field = mimetype
- cached_assign('view_media', request.user, media)
- cached_assign('change_media', request.user, media)
- media.save()
+
+
+
+ media, form_status = media_management(request, media_input_type, cleaned_data, content_form, media_form, form_status)
+
+
+
if form_status != "error":
content_defaults = {}
@@ -229,9 +244,9 @@
for key in ["media_input_type", "groups", "is_public", "read_list", "write_list", "share" ]:
del content_defaults[key]
-
+
content, created = Content.safe_objects.get_or_create(iri_id=content_form.cleaned_data['iri_id'], defaults=content_defaults) #@UndefinedVariable
-
+
if not created and not request.user.has_perm('ldt_utils.change_content', content):
raise AttributeError("%s is not allowed to change content %s" % (request.user, content))
@@ -245,9 +260,9 @@
cached_assign('view_media', everyone, media)
else:
remove_perm('ldt_utils.view_media', everyone, media)
+ assign_perm_to_obj(content, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
if media:
assign_perm_to_obj(media, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
- assign_perm_to_obj(content, content_form.cleaned_data['read_list'], content_form.cleaned_data['write_list'], request.user)
if content_form.cleaned_data['is_public']:
cached_assign('view_content', everyone, content)
else:
@@ -259,7 +274,7 @@
if request.user.is_staff and content_defaults.has_key('front_project'):
content.front_project = content_defaults['front_project']
-
+
content.save()
picture_form.model = content
picture_form.save()
@@ -269,40 +284,42 @@
picture_form = PictureForm()
else:
form_status = 'error'
+ except Exception, e:
+ transaction.rollback()
+ __, value, traceback = sys.exc_info()
+ return False, False, False, False, False, errors_transaction, e, traceback
+
+ else:
+ form_status = 'empty'
+ initial_c = { 'media_input_type':"link"}
+ initial_m = {}
+ if instance_media:
+ initial_m['media_public'] = instance_media.is_public
else:
- form_status = 'empty'
- initial_c = { 'media_input_type':"link"}
- initial_m = {}
- if instance_media:
- initial_m['media_public'] = instance_media.is_public
- else:
- initial_m['media_public'] = True
- if instance_content:
- initial_c['is_public'] = instance_content.is_public
- else:
- initial_c['is_public'] = True
- content_form = ContentForm(prefix="content", instance=instance_content, initial=initial_c)
- media_form = MediaForm(prefix="media", instance=instance_media, initial=initial_m)
- picture_form = PictureForm()
-
- if instance_content is not None:
- content_form.media_input_type = "link"
-
- if request.user.is_staff:
- content_form.fields['front_project'].queryset = Project.objects.filter(contents__in=[instance_content])
- except:
+ initial_m['media_public'] = True
+ if instance_content:
+ initial_c['is_public'] = instance_content.is_public
+ else:
+ initial_c['is_public'] = True
+ content_form = ContentForm(prefix="content", instance=instance_content, initial=initial_c)
+ media_form = MediaForm(prefix="media", instance=instance_media, initial=initial_m)
+ picture_form = PictureForm()
+
+ if instance_content is not None:
+ content_form.media_input_type = "link"
+
+ if request.user.is_staff:
+ content_form.fields['front_project'].queryset = Project.objects.filter(contents__in=[instance_content])
+
+ try:
+ transaction.commit()
+ except Exception, e:
transaction.rollback()
- errors_transaction.append(_("Content creation failure"))
- return False, False, False, False, False, errors_transaction
- else:
- #Try to make sure the commit succeeded or not.
- try:
- transaction.commit()
- except:
- transaction.rollback()
- errors_transaction.append(_("Commit of the content creation failed"))
- return False, False, False, False, False, errors_transaction
- return content_form, media_form, picture_form, form_status, current_front_project, errors_transaction
+ errors_transaction.append(e)
+ type, value, traceback = sys.exc_info()
+ return False, False, False, False, False, errors_transaction, e, traceback
+
+ return content_form, media_form, picture_form, form_status, current_front_project, errors_transaction, "", ""
@login_required
def write_content(request, iri_id=None):
@@ -353,7 +370,7 @@
elif submit_action=="close":
return redirect("root-view")
else:
- content_form, media_form, picture_form, form_status, current_front_project, errors_transaction = write_content_base(request, iri_id)
+ content_form, media_form, picture_form, form_status, current_front_project, errors_transaction, e, traceback = write_content_base(request, iri_id)
if iri_id:
content_temp = Content.objects.get(iri_id=iri_id)
media_temp = content_temp.media_obj
@@ -366,7 +383,8 @@
if (deleted == False) or (content_form == False and media_form == False and picture_form == False and form_status == False and current_front_project == False):
message=_("An error occurred - Please try again or contact webmaster")
title = _("Error")
- return render_to_response('ldt/ldt_utils/error_confirm.html', {'errors':errors_transaction, 'message':message, 'title': title}, context_instance=RequestContext(request))
+ logging.error(e)
+ raise e, None, traceback
if iri_id:
create_content_action = reverse('ldt.ldt_utils.views.content.write_content', kwargs={'iri_id':iri_id})
@@ -396,7 +414,6 @@
def prepare_delete_content(request, iri_id=None):
errors = []
titles = []
- delete = False
message={}
if not iri_id:
iri_id = request.REQUEST.get("iri_id", None)
@@ -434,10 +451,11 @@
content.delete()
if project is not None:
Project.safe_objects.get(ldt_id= project.ldt_id).delete()
- except:
+ except Exception, e:
content.rollback()
transaction.rollback()
errors_transaction.append(_("Content deletion failure"))
+ errors_transaction.append(e)
return False, errors_transaction
else:
try:
@@ -445,9 +463,10 @@
content.commit()
return True, errors_transaction
except:
+ content.rollback()
transaction.rollback()
- content.rollback()
errors_transaction.append(_("Commit of the content deletion failed"))
+ errors_transaction.append(e)
return False, errors_transaction
def upload(request):
--- a/src/ldt/ldt/ldt_utils/views/group.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/group.py Mon Nov 12 16:17:22 2012 +0100
@@ -2,13 +2,14 @@
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group
from django.http import HttpResponseServerError
-from django.shortcuts import render_to_response, get_object_or_404
+from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
from ldt.ldt_utils.forms import GroupAddForm
from guardian.shortcuts import remove_perm, get_objects_for_group, get_objects_for_user
from ldt.security.utils import add_change_attr, get_userlist, get_userlist_group
from ldt.security.cache import get_cached_checker, cached_assign
from ldt.user.forms import PictureForm
+import logging
@login_required
@@ -41,37 +42,43 @@
if request.method == 'POST':
form = GroupAddForm(request.POST)
picture_form = PictureForm(None, request.POST, request.FILES)
-
- if form.is_valid():
- name = form.cleaned_data['name']
- members_list = form.cleaned_data['read_list']
- admin_list = form.cleaned_data['write_list']
-
- group = Group.objects.create(name=name)
- group.save()
- group.profile.description = form.cleaned_data['description']
- group.profile.save()
-
- picture_form.model = group
- if picture_form.is_valid():
- picture_form.save()
-
- cached_assign('is_owner_group', request.user, group)
- cached_assign('change_group', request.user, group)
- request.user.groups.add(group)
-
- for elem in members_list:
- if hasattr(elem, 'username'):
- elem.groups.add(group)
- if elem in admin_list:
- cached_assign('change_group', elem, group)
- form_status = 'saved'
- else:
- group.delete()
-
+ submit_action = request.REQUEST.get("submit_button", False)
+
+ if submit_action == 'close':
+ return redirect("groups-view")
+ else:
+ if form.is_valid():
+ name = form.cleaned_data['name']
+ members_list = form.cleaned_data['read_list']
+ admin_list = form.cleaned_data['write_list']
+
+ group = Group.objects.create(name=name)
+ group.save()
+ group.profile.description = form.cleaned_data['description']
+ group.profile.save()
+
+ picture_form.model = group
+ if picture_form.is_valid():
+ picture_form.save()
+
+ cached_assign('is_owner_group', request.user, group)
+ cached_assign('change_group', request.user, group)
+ request.user.groups.add(group)
+
+ for elem in members_list:
+ if hasattr(elem, 'username'):
+ elem.groups.add(group)
+ if elem in admin_list:
+ cached_assign('change_group', elem, group)
+ form_status = 'saved'
+ else:
+ group.delete()
else:
form = GroupAddForm()
picture_form = PictureForm()
+
+ if form_status == 'saved':
+ return redirect("groups-view")
return render_to_response("ldt/ldt_utils/create_group.html", {'group_edition': True, 'form' : form, 'form_status' : form_status,
'elem_list' : get_userlist(request.user), 'profile_picture_form': picture_form}, context_instance=RequestContext(request))
@@ -97,6 +104,8 @@
if is_owner_group:
group.delete()
form_status = 'deleted'
+ elif submit_action == 'close':
+ return redirect("groups-view")
else:
if form.is_valid() and picture_form.is_valid():
name = form.cleaned_data['name']
@@ -130,12 +139,11 @@
form = GroupAddForm(initial={'name':unicode(group.name)})
picture_form = PictureForm()
- if form_status != 'deleted':
+ if form_status == 'deleted' or form_status == 'saved':
+ return redirect("groups-view")
+ else:
member_list, admin_list = get_userlist_group(group, request.user)
profile_image = group.profile
- else:
- member_list = admin_list = []
- profile_image = ''
return render_to_response("ldt/ldt_utils/create_group.html", {'group_id' : group_id, 'form' : form, 'form_status' : form_status, 'group_edition': True,
'elem_list' : get_userlist(request.user), 'member_list': member_list, 'admin_list': admin_list,
--- a/src/ldt/ldt/ldt_utils/views/json.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/json.py Mon Nov 12 16:17:22 2012 +0100
@@ -5,9 +5,8 @@
from django.utils import simplejson
from django.utils.html import escape
from django.utils.translation import ugettext as _
-from ldt.indexation import get_results_with_context
from ldt.ldt_utils.models import Project
-from ldt.ldt_utils.projectserializer import ProjectSerializer
+from ldt.ldt_utils.projectserializer import ProjectJsonSerializer
from ldt.ldt_utils.searchutils import search_generate_ldt
from datetime import datetime
import ldt.auth as ldt_auth
@@ -63,7 +62,7 @@
escape_bool = {'true': True, 'false': False, "0": False, "1": True}.get(escape_str.lower())
- ps = ProjectSerializer(project, serialize_contents, first_cutting=first_cutting)
+ ps = ProjectJsonSerializer(project, serialize_contents, first_cutting=first_cutting)
project_dict = ps.serialize_to_cinelab()
json_str = simplejson.dumps(project_dict, ensure_ascii=False, indent=indent)
@@ -104,7 +103,7 @@
now = datetime.now()
project.modification_date = project.creation_date = now
#return HttpResponse(lxml.etree.tostring(project_xml, pretty_print=True), mimetype="text/xml;charset=utf-8")
- ps = ProjectSerializer(project, from_contents=False)
+ ps = ProjectJsonSerializer(project, from_contents=False)
mashup_dict = ps.serialize_to_cinelab()
# Now we build the mashup with the good segments (the ones between in and out)
if results:
@@ -133,8 +132,8 @@
cur_in = float(res["start_ts"])
cur_out = cur_in + float(res["duration"])
if tc_in<=cur_in and cur_out<=tc_out:
- #filtered_results.append(res)
- mashup_list["items"].append(res["element_id"])
+ #filtered_results.append(res)
+ mashup_list["items"].append(res["element_id"])
mashup_dict["lists"].append(mashup_list)
#mashup_dict["escape_bool"] = escape_bool
--- a/src/ldt/ldt/ldt_utils/views/rdf.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/rdf.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,7 +1,7 @@
from django.http import HttpResponse, HttpResponseForbidden
from django.utils.translation import ugettext as _
from ldt.ldt_utils.models import Project
-from ldt.ldt_utils.projectserializer import ProjectSerializer
+from ldt.ldt_utils.projectserializer import ProjectJsonSerializer
import ldt.auth as ldt_auth
import logging
import lxml.etree
@@ -25,7 +25,7 @@
resp['Cache-Control'] = 'no-cache, must-revalidate'
resp['Pragma'] = 'no-cache'
- ps = ProjectSerializer(project, from_contents=False, from_display=True)
+ ps = ProjectJsonSerializer(project, from_contents=False, from_display=True)
annotations = ps.get_annotations(first_cutting=True)
rdf_ns = u"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
--- a/src/ldt/ldt/ldt_utils/views/workspace.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/workspace.py Mon Nov 12 16:17:22 2012 +0100
@@ -13,7 +13,7 @@
from ldt.ldt_utils.forms import SearchForm
from ldt.ldt_utils.models import Content, Project, Segment
from ldt.ldt_utils.utils import boolean_convert
-from ldt.ldt_utils.projectserializer import ProjectSerializer
+from ldt.ldt_utils.projectserializer import ProjectJsonSerializer
from ldt.ldt_utils.views.content import get_contents_page, get_content_tags
from ldt.ldt_utils.views.project import get_projects_page, get_published_projects_page
from ldt.security.utils import add_change_attr, get_userlist
@@ -23,7 +23,6 @@
import django.core.urlresolvers
import ldt.auth as ldt_auth
from django.utils.safestring import mark_safe
-import logging
@@ -40,13 +39,6 @@
is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1);
- # Resolve a URL
- #project_api_view, project_api_args, project_api_kwargs = resolve('/api/ldt/projects/c8448f21-272d-11e1-876b-c8bcc896c290.json')
- #match = resolve('/api/ldt/projects/c8448f21-272d-11e1-876b-c8bcc896c290.json')
-
- # Print the URL pattern that matches the URL
- #print match.url_name
-
# render list
return render_to_response("ldt/ldt_utils/workspace.html",
{'contents': content_list, 'nb_ct_pages': nb_ct_pages, 'content_nb': content_nb, 'current_content_page':float(num_page),
@@ -107,6 +99,7 @@
embed_rendered = dict((typestr,
(lambda s:escape(render_to_string("ldt/ldt_utils/partial/embed_%s.html" % (s), rend_dict, context_instance=RequestContext(request))))(typestr))
for typestr in ('seo_body', 'seo_meta', 'links'))
+
rend_dict['embed_rendered'] = embed_rendered
return render_to_response("ldt/ldt_utils/embed_popup.html", rend_dict, context_instance=RequestContext(request))
@@ -206,7 +199,7 @@
WEB_URL=settings.WEB_URL
LDT_MEDIA_PREFIX=settings.LDT_MEDIA_PREFIX
LANGUAGE_CODE=settings.LANGUAGE_CODE
- ps = ProjectSerializer(project, from_contents=True, from_display=True)
+ ps = ProjectJsonSerializer(project, from_contents=True, from_display=True)
annotations = ps.get_annotations(first_cutting=True)
rend_dict = {'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode,
'external_url': external_url,
@@ -296,19 +289,21 @@
valid_segments = []
for s in all_related_segments:
- segment = [seg for seg in all_segments if seg.element_id == s['element_id'] and seg.project_id == s['project_id'] and seg.iri_id == s['iri_id'] and seg.cutting_id == s['cutting_id'] and seg.ensemble_id == s['ensemble_id'] ][0]
-
- segment.score = s['score']
- segment.indexation_id = s['indexation_id']
- segment.context = s['context']
- segment.context_tags = s['tags']
- segment.highlighted = s['highlighted']
-
- if not s['project_id']:
- segment.project_id = '_'
- valid_segments.append(segment)
- elif s['project_id'] in viewable_projects_id:
- valid_segments.append(segment)
+ array_of_segs = [seg for seg in all_segments if seg.element_id == s['element_id'] and seg.project_id == s['project_id'] and seg.iri_id == s['iri_id'] and seg.cutting_id == s['cutting_id'] and seg.ensemble_id == s['ensemble_id'] ]
+ if len(array_of_segs)>0:
+ segment = array_of_segs[0]
+
+ segment.score = s['score']
+ segment.indexation_id = s['indexation_id']
+ segment.context = s['context']
+ segment.context_tags = s['tags']
+ segment.highlighted = s['highlighted']
+
+ if not s['project_id']:
+ segment.project_id = '_'
+ valid_segments.append(segment)
+ elif s['project_id'] in viewable_projects_id:
+ valid_segments.append(segment)
# If all segments found belong to unpublished projects or projects
# the current user is not allowed to see
Binary file src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo has changed
--- a/src/ldt/ldt/locale/fr/LC_MESSAGES/django.po Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/locale/fr/LC_MESSAGES/django.po Mon Nov 12 16:17:22 2012 +0100
@@ -7,7 +7,7 @@
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-11-12 14:54+0100\n"
+"POT-Creation-Date: 2012-11-12 16:10+0100\n"
"PO-Revision-Date: 2010-03-09 15:52+0100\n"
"Last-Translator: Yves-Marie Haussonne <ymh.work@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -37,7 +37,7 @@
msgid "all"
msgstr "tous"
-#: .\ldt_utils\forms.py:33 .\ldt_utils\models.py:55
+#: .\ldt_utils\forms.py:33 .\ldt_utils\models.py:56
#: .\ldt_utils\templates\ldt\ldt_utils\content_list.html.py:69
msgid "title"
msgstr "titre"
@@ -98,51 +98,51 @@
msgid "content.duration"
msgstr "Durée"
-#: .\ldt_utils\models.py:44
+#: .\ldt_utils\models.py:45
msgid "media.external_id"
msgstr "id externe"
-#: .\ldt_utils\models.py:45
+#: .\ldt_utils\models.py:46
msgid "media.external_permalink"
msgstr "permalien externe"
-#: .\ldt_utils\models.py:46
+#: .\ldt_utils\models.py:47
msgid "media.external_publication_url"
msgstr "url de publication externe"
-#: .\ldt_utils\models.py:47
+#: .\ldt_utils\models.py:48
msgid "media.external_src_url"
msgstr "url source"
-#: .\ldt_utils\models.py:48
+#: .\ldt_utils\models.py:49
msgid "media.creation_date"
msgstr "Date de création"
-#: .\ldt_utils\models.py:49
+#: .\ldt_utils\models.py:50
msgid "media.media_creation_date"
msgstr "Date de création du média"
-#: .\ldt_utils\models.py:50
+#: .\ldt_utils\models.py:51
msgid "media.update_date"
msgstr "Date de maj"
-#: .\ldt_utils\models.py:51
+#: .\ldt_utils\models.py:52
msgid "media.videopath"
msgstr "videopath"
-#: .\ldt_utils\models.py:52
+#: .\ldt_utils\models.py:53
msgid "media.duration"
msgstr "Durée du contenu (ms)"
-#: .\ldt_utils\models.py:53
+#: .\ldt_utils\models.py:54
msgid "media.creator"
msgstr "Créateur"
-#: .\ldt_utils\models.py:54
+#: .\ldt_utils\models.py:55
msgid "description"
msgstr "description"
-#: .\ldt_utils\models.py:56
+#: .\ldt_utils\models.py:57
msgid "media.src"
msgstr "Sources"
@@ -182,35 +182,35 @@
msgid "content.authors"
msgstr "Auteurs"
-#: .\ldt_utils\models.py:523
+#: .\ldt_utils\models.py:526
msgid "content_stat.content"
msgstr "statistiques d'annotation"
-#: .\ldt_utils\models.py:524
+#: .\ldt_utils\models.py:527
msgid "content_stat.annotations_volume"
msgstr "Volume d'annotations"
-#: .\ldt_utils\models.py:525
+#: .\ldt_utils\models.py:528
msgid "content_stat.polemics_volume"
msgstr "Volume d'annotations"
-#: .\ldt_utils\models.py:526
+#: .\ldt_utils\models.py:529
msgid "content.nb_annotation"
msgstr "nombre d'annotations"
-#: .\ldt_utils\models.py:527
+#: .\ldt_utils\models.py:530
msgid "content.last_annotated"
msgstr "annoté pour la dernière foiss"
-#: .\ldt_utils\models.py:582
+#: .\ldt_utils\models.py:585
msgid "created by"
msgstr "créé par"
-#: .\ldt_utils\models.py:583
+#: .\ldt_utils\models.py:586
msgid "changed by"
msgstr "modifié par"
-#: .\ldt_utils\utils.py:203 .\ldt_utils\utils.py:386
+#: .\ldt_utils\utils.py:204 .\ldt_utils\utils.py:387
msgid "Personal cutting"
msgstr "Découpages personnels"
@@ -408,13 +408,13 @@
msgstr "Toutes les annotations sur le média"
#: .\ldt_utils\templates\front\front_search_results.html.py:6
-#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:101
-#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:113
+#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:100
+#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:112
#: .\ldt_utils\templates\ldt\ldt_utils\ldt_list.html.py:80
#: .\ldt_utils\templates\ldt\ldt_utils\published_projects.html.py:70
#: .\ldt_utils\templates\ldt\ldt_utils\workspace_base.html.py:56
#: .\ldt_utils\templates\ldt\ldt_utils\workspace_base.html.py:71
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:129
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:131
#: .\templates\ldt\ldt_base.html.py:127
msgid "search"
msgstr "Recherche"
@@ -557,7 +557,7 @@
msgstr "Le fichier média est en cours de traitement. Veuillez patienter."
#: .\ldt_utils\templates\ldt\ldt_utils\create_content.html.py:145
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:101
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:77
#: .\ldt_utils\templates\ldt\ldt_utils\create_ldt.html.py:145
#: .\ldt_utils\templates\ldt\ldt_utils\error_confirm.html.py:37
#: .\ldt_utils\templates\ldt\ldt_utils\error_confirm_popup.html.py:53
@@ -574,36 +574,36 @@
msgid "write"
msgstr "Enregistrer"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:57
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:36
msgid "Do you really want to delete this group ?"
msgstr "Voulez-vous quitter ce groupe ?"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:78
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:54
msgid "Update a group"
msgstr "Mettre à jour votre groupe"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:78
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:54
msgid "Create a group"
msgstr "Créer un groupe"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:85
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:61
#: .\user\templates\ldt\user\change_profile.html.py:62
msgid "Name"
msgstr "Nom"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:91
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:67
msgid "Description"
msgstr "Description"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:103
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:79
msgid "update_group"
msgstr "Mettre à jour le groupe"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:105
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:81
msgid "delete_group"
msgstr "Effacer le groupe"
-#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:108
+#: .\ldt_utils\templates\ldt\ldt_utils\create_group.html.py:84
msgid "create_group"
msgstr "Créer un nouveau groupe"
@@ -716,8 +716,8 @@
msgstr "Configuration avec widget polemic"
#: .\ldt_utils\templates\ldt\ldt_utils\embed_popup.html.py:93
-msgid "Polemic configuration with sparkline and tagcloud"
-msgstr "Configuration avec widget polemic, sparkline et tagcloud"
+msgid "Polemic configuration with tagcloud, annotationsList and Social widgets"
+msgstr "Configuration avec widget polemic, annotationsList, social et tagcloud"
#: .\ldt_utils\templates\ldt\ldt_utils\embed_popup.html.py:100
msgid "Create your own configuration"
@@ -820,7 +820,7 @@
msgstr "Partager par email"
#: .\ldt_utils\templates\ldt\ldt_utils\embed_popup.html.py:195
-msgid " Displays information relative to a single segment/annotation while it is being played"
+msgid "Displays information relative to a single segment/annotation while it is being played"
msgstr "Affiche les informations relatives à une annotation au moment où celle-ci est jouée"
#: .\ldt_utils\templates\ldt\ldt_utils\embed_popup.html.py:198
@@ -854,20 +854,20 @@
msgid "close_error"
msgstr "Fermer"
-#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:68
+#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:67
msgid "Do you want to leave this group ?"
msgstr "Voulez-vous quitter ce groupe ?"
-#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:93
+#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:92
#: .\templates\ldt\ldt_base.html.py:115
msgid "My groups"
msgstr "Groupes"
-#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:95
+#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:94
msgid "Create group"
msgstr "Créer un nouveau groupe"
-#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:111
+#: .\ldt_utils\templates\ldt\ldt_utils\groups.html.py:110
msgid "The group's projects"
msgstr "projets du groupe"
@@ -962,12 +962,12 @@
#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:52
#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:79
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:174
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:178
msgid "share.eye"
msgstr "Cet utilisateur ou ce groupe a le droit de voir cet élement"
#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:60
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:172
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:176
msgid "share.pencil"
msgstr "cet utilisateur ou ce groupe a le droit de modifier cet élement"
@@ -979,41 +979,41 @@
msgid "publish for everyone"
msgstr "publier pour tout le monde"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:124
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:125
msgid "publish the title on the front"
msgstr "publier le titre sur le front"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:127
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:129
msgid "User and group list"
msgstr "Liste des groupes et des utilisateurs"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:142
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:144
msgid "select all displayed elements"
msgstr "ajouter tous les élements affichés"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:147
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:149
msgid "select users"
msgstr "choisir des utilisateurs"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:148
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:150
msgid "remove users"
msgstr "enlever des utilisateurs"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:153
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:157
msgid "Members list"
msgstr "liste des membres"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:163
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:167
#: .\ldt_utils\templates\ldt\ldt_utils\partial\sharewith.html.py:7
msgid "user"
msgstr "utilisateur"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:165
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:169
#: .\ldt_utils\templates\ldt\ldt_utils\partial\sharewith.html.py:9
msgid "group"
msgstr "groupe"
-#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:185
+#: .\ldt_utils\templates\ldt\ldt_utils\partial\permissions.html.py:189
msgid "remove all"
msgstr "tout enlever"
@@ -1063,71 +1063,63 @@
msgid "Project published"
msgstr "Projet publié"
-#: .\ldt_utils\views\content.py:187
+#: .\ldt_utils\views\content.py:114
msgid "Problem when downloading file from url : "
msgstr "Problème lors du téléchargement du fichier : "
-#: .\ldt_utils\views\content.py:190
+#: .\ldt_utils\views\content.py:117
msgid "Problem when uploading file : "
msgstr "Problème lors de l'upload du fichier : "
-#: .\ldt_utils\views\content.py:295
-msgid "Content creation failure"
-msgstr "Echec lors de la creation du contenu"
-
-#: .\ldt_utils\views\content.py:303
-msgid "Commit of the content creation failed"
-msgstr "Echec lors du commit de la creation du contenu"
-
-#: .\ldt_utils\views\content.py:317
+#: .\ldt_utils\views\content.py:334
#, python-format
msgid "There is %(count)d error when deleting content"
msgid_plural "There are %(count)d errors when deleting content"
msgstr[0] "Il y a %(count)d erreur lors de l'effacement du contenu"
msgstr[1] "Il y a %(count)d erreurs lors de l'effacement du contenu"
-#: .\ldt_utils\views\content.py:318
+#: .\ldt_utils\views\content.py:335
msgid "title error deleting content"
msgstr "Erreur lors de l'effacement du contenu"
-#: .\ldt_utils\views\content.py:323
+#: .\ldt_utils\views\content.py:340
#, python-format
msgid "Confirm delete content %(titles)s"
msgstr "Veuillez confirmer l'effacement du contenu %(titles)s"
-#: .\ldt_utils\views\content.py:324
+#: .\ldt_utils\views\content.py:341
msgid "confirm delete content"
msgstr "Confirmation effacement contenu"
-#: .\ldt_utils\views\content.py:335
+#: .\ldt_utils\views\content.py:352
#, python-format
msgid "Please unpublish the front project %(title)s"
msgstr "Veuillez dépublier le projet : %(title)s"
-#: .\ldt_utils\views\content.py:336
+#: .\ldt_utils\views\content.py:353
msgid "The front project is published"
msgstr "Projet publié"
-#: .\ldt_utils\views\content.py:337 .\ldt_utils\views\content.py:340
+#: .\ldt_utils\views\content.py:354 .\ldt_utils\views\content.py:357
#: .\ldt_utils\views\project.py:137
msgid "confirm reset"
msgstr "Confirmer la réinitialisation"
-#: .\ldt_utils\views\content.py:339 .\ldt_utils\views\project.py:136
+#: .\ldt_utils\views\content.py:356 .\ldt_utils\views\project.py:136
#, python-format
msgid "please confirm reseting project %(title)s"
msgstr "Veuillez confirmer la réinitialisation du projet %(title)s"
-#: .\ldt_utils\views\content.py:367
+#: .\ldt_utils\views\content.py:384
msgid "An error occurred - Please try again or contact webmaster"
msgstr ""
"Une erreur est apparue - Merci de réessayer ou de contacter le webmaster"
-#: .\ldt_utils\views\content.py:368
+#: .\ldt_utils\views\content.py:385
msgid "Error"
msgstr "Erreur"
-#: .\ldt_utils\views\content.py:411
+#: .\ldt_utils\views\content.py:428
#, python-format
msgid ""
"Content '%(title)s' is referenced by this project : %(project_titles)s. "
@@ -1142,7 +1134,7 @@
"Le contenu '%(title)s' est référencé par les projets suivants : '%"
"(project_titles)s'.Veuillez les effacer préalablement."
-#: .\ldt_utils\views\content.py:414
+#: .\ldt_utils\views\content.py:431
#, python-format
msgid ""
"The project '%(project_title)s' pointing on the content '%(title)s' has "
@@ -1152,16 +1144,16 @@
"Le projet '%(project_title)s' référençant le contenu '%(title)s' comporte "
"plusieurs annotations. Voulez vous quand même supprimer le contenu ?"
-#: .\ldt_utils\views\content.py:440
+#: .\ldt_utils\views\content.py:457
msgid "Content deletion failure"
msgstr "Echec lors de la suppression du contenu"
-#: .\ldt_utils\views\content.py:450
+#: .\ldt_utils\views\content.py:468
msgid "Commit of the content deletion failed"
msgstr "Echec lors du commit de la suppression du contenu"
-#: .\ldt_utils\views\json.py:40 .\ldt_utils\views\rdf.py:15
-#: .\ldt_utils\views\workspace.py:205
+#: .\ldt_utils\views\json.py:39 .\ldt_utils\views\rdf.py:15
+#: .\ldt_utils\views\workspace.py:198
msgid "You can not access this project"
msgstr "vous n'avez pas l'autorisation d'accéder à ce projet"
@@ -1197,12 +1189,12 @@
msgid "confirm deletion"
msgstr "Confirmation d'effacement"
-#: .\ldt_utils\views\workspace.py:123
+#: .\ldt_utils\views\workspace.py:116
msgid ""
"The content does not exists or you are not allowed to access this content"
msgstr "Ce contenu n'existe pas, ou vous n'êtes pas autorisé a y acceder"
-#: .\ldt_utils\views\workspace.py:127
+#: .\ldt_utils\views\workspace.py:120
msgid "Parameters project_id or content_id must be given in the url"
msgstr "Les paramètres project_id et content_id doivent être passés dans l'URL"
@@ -1854,6 +1846,12 @@
"Nous vous avons envoyé par courriel les instructions pour activer le compte "
"à l'adresse que vous avez indiquée. Vous devriez le recevoir rapidement."
+#~ msgid "Content creation failure"
+#~ msgstr "Echec lors de la creation du contenu"
+
+#~ msgid "Commit of the content creation failed"
+#~ msgstr "Echec lors du commit de la creation du contenu"
+
#~ msgid "Error 500"
#~ msgstr "Erreur 500"
--- a/src/ldt/ldt/settings.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/settings.py Mon Nov 12 16:17:22 2012 +0100
@@ -54,6 +54,7 @@
WEB_URL = getattr(settings, 'WEB_URL', '')
+WEB_AUTH = getattr(settings, 'WEB_AUTH', [])
BASE_URL = getattr(settings, 'BASE_URL', '')
STATIC_URL = getattr(settings, 'STATIC_URL', '')
MEDIA_URL = getattr(settings, 'MEDIA_URL', '')
@@ -71,6 +72,8 @@
LOG_LEVEL = getattr(settings, 'LOG_LEVEL', logging.INFO)
EMPTY_MEDIA_EXTERNALID = getattr(settings, 'EMPTY_MEDIA_EXTERNALID', None)
+ADMIN_MEDIA_PREFIX = getattr(settings, 'ADMIN_MEDIA_PREFIX', None)
+
TEST_WEBSERVER_ADDRPORT = getattr(settings, 'TEST_WEBSERVER_ADDRPORT', '127.0.0.1:8000')
ACCOUNT_ACTIVATION_DAYS = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', 7)
@@ -106,3 +109,4 @@
'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
},
}
+
--- a/src/ldt/ldt/static/ldt/js/embed_popup.js Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/static/ldt/js/embed_popup.js Mon Nov 12 16:17:22 2012 +0100
@@ -210,15 +210,15 @@
var player_height_val=$j('#player_height').val();
widget_code='\
widgets: [\n\
- {\n';
+ {\n\
+ type: "AutoPlayer",\n';
+
if (external_url!='None'){
widget_code+='\
- type: "AutoPlayer",\n\
video: "'+external_url+'",\n';
}
else{
widget_code+='\
- type: "JwpPlayer",\n\
streamer: function(_url) {\n\
var _matches = _url.match(/^[^\\/]+\\/\\/[^\\/]+\\/[^\\/]+\\//);\n\
if (_matches) {\n\
@@ -226,9 +226,7 @@
} else {\n\
return _url;\n\
}\n\
- },\n\
- live: true,\n\
- provider: "rtmp",\n';
+ },\n';
}
widget_code+='\
--- a/src/ldt/ldt/static/ldt/js/projectscontents.js Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/static/ldt/js/projectscontents.js Mon Nov 12 16:17:22 2012 +0100
@@ -332,35 +332,6 @@
$('.create_group',base_node).each(function(i){
$(this).attr("target","_iri");
});
-
- $('.create_group',base_node).nyroModal({
- filters: ['iriIframe'],
- sizes: {
- minW: '750',
- minH: '750'
- },
- showCloseButton: true,
- closeOnEscape:false,
- closeOnClick:false,
- callbacks: {
- afterShowCont: function(nm) {
- var iframe = nm.store.iframe;
- iframe.load(function(){
- var form_status = $(this).contents().find("#project_form_status").val();
- if(form_status === 'saved' || form_status === 'deleted' ) {
- $.nmTop().close();
- }
-
- });
- nm.store.iframe.width(740);
- nm.store.iframe.height(740);
- },
- afterClose: function(nm) {
- searchCallback($("#searchprojectsinput"), $("#groupslistcontainer"), groupfilterurl, 0);
- }
- }
- });
-
$('.create_group',base_node).each(function(i, e) {
nm = $(e).data('nmObj');
--- a/src/ldt/ldt/static/ldt/metadataplayer/AutoPlayer.js Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/static/ldt/metadataplayer/AutoPlayer.js Mon Nov 12 16:17:22 2012 +0100
@@ -18,6 +18,14 @@
_opts = {},
_types = [
{
+ regexp: /^rtmp:\/\//,
+ type: "JwpPlayer"
+ },
+ {
+ regexp: /\.(mp4|m4v)$/,
+ type: "AdaptivePlayer"
+ },
+ {
regexp: /\.(ogg|ogv|webm)$/,
type: "PopcornPlayer"
},
@@ -33,11 +41,13 @@
regexp: /^(https?:\/\/)?(www\.)?dailymotion\.com/,
type: "DailymotionPlayer"
}
- ];
+ ],
+ _rtmprgx = /^rtmp:\/\//;
for (var i = 0; i < _types.length; i++) {
if (_types[i].regexp.test(this.video)) {
- _opts.type = _types[i].type
+ _opts.type = _types[i].type;
+ break;
}
}
@@ -45,12 +55,21 @@
_opts.type = this.default_type
}
+ if (_opts.type === "AdaptivePlayer") {
+ var _canPlayType = document.createElement('video').canPlayType("video/mp4");
+ _opts.type = (_canPlayType == "maybe" || _canPlayType == "probably") ? "PopcornPlayer" : "JwpPlayer";
+ }
+
+ if (_rtmprgx.test(this.video)) {
+ _opts.provider = "rtmp";
+ _opts.live = true;
+ }
+
for (var i = 0; i < _props.length; i++) {
if (typeof this[_props[i]] !== "undefined") {
_opts[_props[i]] = this[_props[i]];
}
}
-
this.insertSubwidget(this.$, _opts);
--- a/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/static/ldt/metadataplayer/CreateAnnotation.js Mon Nov 12 16:17:22 2012 +0100
@@ -43,7 +43,7 @@
annotation_type: "Contributions",
api_serializer: "ldt_annotate",
api_endpoint_template: "",
- api_method: "PUT",
+ api_method: "POST",
after_send_timeout: 0,
close_after_send: false,
}
--- a/src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js Mon Nov 12 16:17:22 2012 +0100
@@ -235,33 +235,30 @@
/* TODO: Separate Project-specific data from Source */
/* model.js is where data is stored in a standard form, whatever the serializer */
+
IriSP.Model = (function (ns) {
+
+ function pad(n, x, b) {
+ b = b || 10;
+ var s = (x).toString(b);
+ while (s.length < n) {
+ s = "0" + s;
+ }
+ return s;
+ }
+
+ function rand16(n) {
+ return pad(n, Math.floor(Math.random()*Math.pow(16,n)), 16);
+ }
+
+ var uidbase = rand16(8) + "-" + rand16(4) + "-", uidincrement = Math.floor(Math.random()*0x10000);
var Model = {
_SOURCE_STATUS_EMPTY : 0,
_SOURCE_STATUS_WAITING : 1,
_SOURCE_STATUS_READY : 2,
- _ID_AUTO_INCREMENT : 0,
- _ID_BASE : (function(_d) {
- function pad(n){return n<10 ? '0'+n : n}
- function fillrand(n) {
- var _res = ''
- for (var i=0; i<n; i++) {
- _res += Math.floor(16*Math.random()).toString(16);
- }
- return _res;
- }
- return _d.getUTCFullYear() + '-'
- + pad(_d.getUTCMonth()+1) + '-'
- + pad(_d.getUTCDate()) + '-'
- + fillrand(16);
- })(new Date()),
getUID : function() {
- var _n = (++this._ID_AUTO_INCREMENT).toString();
- while (_n.length < 4) {
- _n = '0' + _n
- }
- return "autoid-" + this._ID_BASE + '-' + _n;
+ return uidbase + pad(4, (++uidincrement % 0x10000), 16) + "-" + rand16(4) + "-" + rand16(6) + rand16(6);
},
regexpFromTextOrArray : function(_textOrArray, _testOnly, _iexact) {
var _testOnly = _testOnly || false,
@@ -309,13 +306,12 @@
return _res;
},
dateToIso : function(d) {
- function pad(n){return n<10 ? '0'+n : n}
return d.getUTCFullYear()+'-'
- + pad(d.getUTCMonth()+1)+'-'
- + pad(d.getUTCDate())+'T'
- + pad(d.getUTCHours())+':'
- + pad(d.getUTCMinutes())+':'
- + pad(d.getUTCSeconds())+'Z'
+ + pad(2, d.getUTCMonth()+1)+'-'
+ + pad(2, d.getUTCDate())+'T'
+ + pad(2, d.getUTCHours())+':'
+ + pad(2, d.getUTCMinutes())+':'
+ + pad(2, d.getUTCSeconds())+'Z'
}
}
@@ -580,19 +576,12 @@
}
Model.Time.prototype.toString = function() {
- function pad(_n) {
- var _res = _n.toString();
- while (_res.length < 2) {
- _res = '0' + _res;
- }
- return _res;
- }
var _hms = this.getHMS(),
_res = '';
if (_hms.hours) {
- _res += pad(_hms.hours) + ':'
+ _res += _hms.hours + ':'
}
- _res += pad(_hms.minutes) + ':' + pad(_hms.seconds);
+ _res += pad(2, _hms.minutes) + ':' + pad(2, _hms.seconds);
return _res;
}
@@ -853,11 +842,17 @@
Model.Annotation.prototype = new Model.Element();
Model.Annotation.prototype.setBegin = function(_beginMs) {
- this.begin.setMilliseconds(_beginMs);
+ this.begin.setMilliseconds(Math.max(0,_beginMs));
+ this.trigger("change-begin");
}
-Model.Annotation.prototype.setEnd = function(_beginMs) {
- this.end.setMilliseconds(_beginMs);
+Model.Annotation.prototype.setEnd = function(_endMs) {
+ this.end.setMilliseconds(Math.min(_endMs));
+ this.trigger("change-end");
+}
+
+Model.Annotation.prototype.setDuration = function(_durMs) {
+ this.setEnd(_durMs + this.begin.milliseconds);
}
Model.Annotation.prototype.setMedia = function(_idRef) {
@@ -1284,6 +1279,9 @@
noCss: true,
requires: [ "swfObject" ]
},
+ AdaptivePlayer: {
+ noCss: true
+ },
AutoPlayer: {
noCss: true
},
@@ -1728,14 +1726,42 @@
}
}
},
+ deserializeAnnotation : function(_anndata, _source) {
+ var _ann = new IriSP.Model.Annotation(_anndata.id, _source);
+ _ann.description = _anndata.content.description || "";
+ _ann.title = _anndata.content.title || "";
+ _ann.creator = _anndata.meta.creator || "";
+ _ann.created = new Date(_anndata.meta.created);
+ _ann.setMedia(_anndata.media, _source);
+ var _anntype = _source.getElement(_anndata.type);
+ if (!_anntype) {
+ _anntype = new IriSP.Model.AnnotationType(_anndata.type, _source);
+ _anntype.title = _anndata.type_title;
+ _source.getAnnotationTypes().push(_anntype);
+ }
+ _ann.setAnnotationType(_anntype.id);
+ var _tagIds = IriSP._(_anndata.tags).map(function(_title) {
+ var _tags = _source.getTags(true).searchByTitle(_title, true);
+ if (_tags.length) {
+ var _tag = _tags[0];
+ }
+ else {
+ _tag = new IriSP.Model.Tag(_title.replace(/\W/g,'_'),_source);
+ _tag.title = _title;
+ _source.getTags().push(_tag);
+ }
+ return _tag.id;
+ });
+ _ann.setTags(_tagIds);
+ _ann.setBegin(_anndata.begin);
+ _ann.setEnd(_anndata.end);
+ if (typeof _anndata.content.audio !== "undefined" && _anndata.content.audio.href) {
+ _ann.audio = _anndata.content.audio;
+ }
+ _source.getAnnotations().push(_ann);
+ },
serialize : function(_source) {
- var _this = this
- _res = {
- "objects": _source.getAnnotations().map(function(_annotation) {
- return _this.serializeAnnotation(_annotation, _source);
- })
- };
- return JSON.stringify(_res);
+ return JSON.stringify(this.serializeAnnotation(_source.getAnnotations()[0], _source));
},
deSerialize : function(_data, _source) {
if (typeof _data == "string") {
@@ -1745,39 +1771,6 @@
_source.addList('tag', new IriSP.Model.List(_source.directory));
_source.addList('annotationType', new IriSP.Model.List(_source.directory));
_source.addList('annotation', new IriSP.Model.List(_source.directory));
- IriSP._(_data.objects).each(function(_anndata) {
- var _ann = new IriSP.Model.Annotation(_anndata.id, _source);
- _ann.description = _anndata.content.description || "";
- _ann.title = _anndata.content.title || "";
- _ann.creator = _anndata.meta.creator || "";
- _ann.created = new Date(_anndata.meta.created);
- _ann.setMedia(_anndata.media, _source);
- var _anntype = _source.getElement(_anndata.type);
- if (!_anntype) {
- _anntype = new IriSP.Model.AnnotationType(_anndata.type, _source);
- _anntype.title = _anndata.type_title;
- _source.getAnnotationTypes().push(_anntype);
- }
- _ann.setAnnotationType(_anntype.id);
- var _tagIds = IriSP._(_anndata.tags).map(function(_title) {
- var _tags = _source.getTags(true).searchByTitle(_title, true);
- if (_tags.length) {
- var _tag = _tags[0];
- }
- else {
- _tag = new IriSP.Model.Tag(_title.replace(/\W/g,'_'),_source);
- _tag.title = _title;
- _source.getTags().push(_tag);
- }
- return _tag.id;
- });
- _ann.setTags(_tagIds);
- _ann.setBegin(_anndata.begin);
- _ann.setEnd(_anndata.end);
- if (typeof _anndata.content.audio !== "undefined" && _anndata.content.audio.href) {
- _ann.audio = _anndata.content.audio;
- }
- _source.getAnnotations().push(_ann);
- });
+ this.deserializeAnnotation(_data, _source);
}
}
\ No newline at end of file
--- a/src/ldt/ldt/static/ldt/metadataplayer/Sparkline.js Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/static/ldt/metadataplayer/Sparkline.js Mon Nov 12 16:17:22 2012 +0100
@@ -18,15 +18,22 @@
_duration = this.source.getDuration(),
_max = 0,
_list = this.getWidgetAnnotations();
-
for (var _i = 0; _i < this.slice_count; _i++) {
- var _begin = new IriSP.Model.Time(_i*_duration/this.slice_count),
- _end = new IriSP.Model.Time((_i+1)*_duration/this.slice_count),
- _annotations = _list.filter(function(_annotation) {
- return _annotation.begin >= _begin && _annotation.end < _end;
- }).length;
- _max = Math.max(_max, _annotations);
- _slices.push(_annotations);
+ var _begin = (_i*_duration/this.slice_count),
+ _end = ((_i+1)*_duration/this.slice_count),
+ _volume = 0;
+ _list.forEach(function(_annotation) {
+ if (_annotation.begin < _end && _annotation.end >= _begin) {
+ var _d = _annotation.getDuration().milliseconds;
+ if (!_d) {
+ _volume += 1;
+ } else {
+ _volume += (Math.min(_annotation.end, _end) - Math.max(_annotation.begin, _begin)) / _d;
+ }
+ }
+ });
+ _max = Math.max(_max, _volume);
+ _slices.push(_volume);
}
if (!_max) {
return;
--- a/src/ldt/ldt/utils/context_processors.py Mon Nov 12 15:03:36 2012 +0100
+++ b/src/ldt/ldt/utils/context_processors.py Mon Nov 12 16:17:22 2012 +0100
@@ -1,4 +1,4 @@
-from django.conf import settings
+from ldt import settings
import ldt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/utils/url.py Mon Nov 12 16:17:22 2012 +0100
@@ -0,0 +1,21 @@
+from ldt import settings
+import httplib2
+import re
+import urlparse
+
+def request_with_auth(url, method='GET'):
+ h = httplib2.Http()
+ web_auth = settings.WEB_AUTH if settings.WEB_AUTH else []
+ for entry in web_auth:
+ if not isinstance(entry, dict):
+ continue
+ regex = entry.get('REGEX', None)
+ if regex and re.search(regex, url, re.IGNORECASE):
+ h.add_credentials(entry.get('NAME', ''), entry.get('PASSWORD', ''), entry.get('DOMAIN', ''))
+ break
+
+ return h.request(url, method)
+
+
+def is_absolute(url):
+ return bool(urlparse.urlparse(url).scheme)
\ No newline at end of file
--- a/virtualenv/res/lib/lib_create_env.py Mon Nov 12 15:03:36 2012 +0100
+++ b/virtualenv/res/lib/lib_create_env.py Mon Nov 12 16:17:22 2012 +0100
@@ -44,10 +44,11 @@
'WSGIREF' : {'setup':'wsgiref', 'url':'http://pypi.python.org/packages/source/w/wsgiref/wsgiref-0.1.2.zip', 'local': 'wsgiref-0.1.2.zip', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
# dependencies for Tastypie : mimeparse>=0.1.3, python-dateutil>=2.1, lxml, PyYAML (not necessary but we never know), python-digest
'MIMEPARSE' : {'setup':'mimeparse', 'url':'http://pypi.python.org/packages/source/m/mimeparse/mimeparse-0.1.3.tar.gz', 'local': 'mimeparse-0.1.3.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
+ 'SIX' : {'setup':'six', 'url':'http://pypi.python.org/packages/source/s/six/six-1.2.0.tar.gz', 'local': 'six-1.2.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
'PYTHON-DATEUTIL' : {'setup':'python-dateutil', 'url':'http://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.1.tar.gz', 'local': 'python-dateutil-2.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
'PYYAML' : {'setup':'pyyaml', 'url':'http://pypi.python.org/packages/source/P/PyYAML/PyYAML-3.10.tar.gz', 'local': 'PyYAML-3.10.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
'PYTHON-DIGEST' : {'setup':'python-digest', 'url':'http://pypi.python.org/packages/source/p/python-digest/python-digest-1.7.tar.gz', 'local': 'python-digest-1.7.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
- 'DJANGO-TASTYPIE' : {'setup':'django-tastypie', 'url':'http://pypi.python.org/packages/source/d/django-tastypie/django-tastypie-0.9.11.tar.gz', 'local': 'django-tastypie-0.9.11.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
+ 'DJANGO-TASTYPIE' : {'setup':'django-tastypie', 'url':'django-tastypie-0.9.11-modified.tar.gz', 'local': 'django-tastypie-0.9.11-modified.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}},
}
if system_str == 'Windows':
Binary file virtualenv/res/src/django-tastypie-0.9.11-modified.tar.gz has changed
Binary file virtualenv/res/src/django-tastypie-0.9.11.tar.gz has changed
Binary file virtualenv/res/src/six-1.2.0.tar.gz has changed
--- a/virtualenv/web/res/res_create_env.py Mon Nov 12 15:03:36 2012 +0100
+++ b/virtualenv/web/res/res_create_env.py Mon Nov 12 16:17:22 2012 +0100
@@ -30,6 +30,7 @@
'PYELASTICSEARCH',
'WHOOSH',
'MIMEPARSE',
+ 'SIX',
'PYTHON-DATEUTIL',
'PYYAML',
'PYTHON-DIGEST',
--- a/web/ldtplatform/config.py.tmpl Mon Nov 12 15:03:36 2012 +0100
+++ b/web/ldtplatform/config.py.tmpl Mon Nov 12 16:17:22 2012 +0100
@@ -7,6 +7,7 @@
BASE_DIR = '%(base_dir)s'
BASE_URL = '%(base_url)s'
WEB_URL = '%(web_url)s'
+WEB_AUTH = [] # example [{'REGEX': 'localhost/~ymh/platform', 'NAME': 'ymh', 'PASSWORD': 'ymh'}]
STATIC_URL = BASE_URL + 'static/site/'