web/ldt_utils/ldt/fileimport.py
changeset 4 7c994c98d1df
parent 3 651f67b66c51
equal deleted inserted replaced
3:651f67b66c51 4:7c994c98d1df
       
     1 import tempfile
       
     2 import os.path
       
     3 import shutil
       
     4 from django.core.exceptions import ObjectDoesNotExist
       
     5 from ldt.utils import zipfileext
       
     6 from django.conf import settings
       
     7 from models import Content
       
     8 import xml.dom.minidom
       
     9 import xml.dom.ext #@UnresolvedImport
       
    10 import xml.xpath #@UnresolvedImport
       
    11 import fnmatch
       
    12 import uuid
       
    13 import urllib
       
    14 
       
    15 class FileImportError(Exception):
       
    16     def __init__(self, value):
       
    17         self.value = value
       
    18     def __str__(self):
       
    19         return repr(self.value)
       
    20 
       
    21 
       
    22 def Property(func):
       
    23     return property(**func()) 
       
    24 
       
    25 class IriInfo(object):
       
    26 
       
    27     
       
    28     def __init__(self, id, order, titledesc, basepath="", videopath=settings.STREAM_URL, decoupage_blacklist = settings.DECOUPAGE_BLACKLIST, flatten = True):
       
    29         self.id = id
       
    30         self.basepath = basepath
       
    31         self.order = order
       
    32         self.src = ""
       
    33         self.annotations = None
       
    34         self.videopath = videopath
       
    35         self.videourl = ""
       
    36         self.title = None
       
    37         self.desc = None
       
    38         self.duration = None
       
    39         self.created = False
       
    40         self.content = None
       
    41         self.decoupage_blacklist = decoupage_blacklist
       
    42         if self.decoupage_blacklist is None:
       
    43             self.decoupage_blacklist = ()
       
    44         self.flatten = flatten
       
    45         
       
    46         
       
    47     
       
    48     def processIri(self):
       
    49         # for just import a file ldt and get the title for every media
       
    50         if 'http' in self.src:
       
    51             url = urllib.urlopen(self.src)
       
    52             doc = xml.dom.minidom.parse(url)
       
    53             doc = Ft.Xml.Domlette.ConvertDocument(doc)             
       
    54             con = xml.xpath.Context.Context(doc, 1, 1, None)
       
    55             #open .iri and get the title
       
    56             res = xml.xpath.Evaluate("/iri/head/meta[@name='title']/@content", context=con)
       
    57             self.title = res[0].value
       
    58             
       
    59         #for import a zip, get title and copy file .iri in the media directory
       
    60         else:
       
    61             path = os.path.join(self.basepath, self.src)
       
    62             doc = xml.dom.minidom.parse(path)
       
    63             
       
    64             con = xml.xpath.Context.Context(doc, 1, 1, None)
       
    65             
       
    66             res = xml.xpath.Evaluate("/iri/head/meta[@name='title']/@content", context=con)
       
    67             self.title = res[0].value
       
    68             
       
    69         res = xml.xpath.Evaluate("/iri/body/ensembles",context=con)
       
    70         ensemblesnode = res[0]
       
    71 
       
    72         ensembleids = []
       
    73 
       
    74         for node in ensemblesnode.childNodes:
       
    75             if node.nodeType == xml.dom.Node.ELEMENT_NODE and node.tagName == "ensemble":
       
    76                 id = node.getAttributeNS("id",None)
       
    77                 if id not in ensembleids:
       
    78                     ensembleids.append(id)
       
    79 
       
    80         if self.annotations is not None:
       
    81             newEnsemble = None
       
    82             for cnode in self.annotations.childNodes:
       
    83                 if cnode.nodeType == xml.dom.Node.ELEMENT_NODE and cnode.tagName == "decoupage":
       
    84                     if newEnsemble is None:
       
    85                         newensemble = doc.createElement('ensemble')
       
    86                         ensembleid = self.id+"_"+str(uuid.uuid1())
       
    87                         newensemble.setAttributeNS(None,'id',ensembleid)
       
    88             
       
    89                         newensemble.setAttributeNS(None,'title', self.annotations.getAttribute('title'))
       
    90                         newensemble.setAttributeNS(None,'author', self.annotations.getAttribute('author'))
       
    91                         newensemble.setAttributeNS(None,'date', self.annotations.getAttribute('date'))
       
    92                         newensemble.setAttributeNS(None,'abstract', self.annotations.getAttribute('abstract'))
       
    93                         ensemblesnode.appendChild(newensemble)
       
    94                         ensembleids.append(ensembleid)
       
    95                     newDecoupageNode = cnode.cloneNode(True)
       
    96                     newensemble.appendChild(newDecoupageNode)
       
    97                 elif cnode.nodeType == xml.dom.Node.ELEMENT_NODE and cnode.tagName == "ensemble":
       
    98                     ensembleid = cnode.getAttribute(u"id")
       
    99                     cloneNode = cnode.cloneNode(True)
       
   100                     if ensembleid in ensembleids:
       
   101                         ensembleid = self.id+"_"+str(uuid.uuid1())
       
   102                         cloneNode.setAttribute(u"id", ensembleid)
       
   103                     ensembleids.append(ensembleid)
       
   104                     ensemblesnode.appendChild(cloneNode)
       
   105 
       
   106         res = xml.xpath.Evaluate("/iri/body/medias/media[@id='video']/video", context=con)
       
   107         if self.flatten:
       
   108             src_video = res[0].getAttribute('src')
       
   109             self.videourl = os.path.basename(src_video)
       
   110             res[0].setAttributeNS(None,'src', self.videourl)
       
   111         self.duration = res[0].getAttributeNS(None, 'dur')
       
   112             
       
   113         f = open(path, "w")
       
   114         try:
       
   115             xml.dom.ext.Print(doc, stream=f)
       
   116         finally:
       
   117             f.close()
       
   118         
       
   119         
       
   120         destPath = os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "media"), "ldt"), self.id);
       
   121         if not os.path.exists(destPath):
       
   122             os.makedirs(destPath)
       
   123         shutil.move(os.path.join(self.basepath, self.src), os.path.join(destPath, os.path.basename(self.src)))
       
   124         self.src = self.id + u"/" + os.path.basename(self.src)
       
   125 
       
   126 
       
   127 
       
   128     def saveContent(self):
       
   129         #if 'http' in self.src:
       
   130         #    url = self.src
       
   131         #else:
       
   132         #    url = self.id + u"/" + os.path.basename(self.src)
       
   133         content, self.created = Content.objects.get_or_create(iri_id=self.id, defaults = {'iriurl': self.src, 'title':self.title, 'description':self.desc, 'videopath': self.videopath})
       
   134         if not self.created:
       
   135             content.iriurl = self.src
       
   136             content.title = self.title
       
   137             content.description = self.desc
       
   138             content.save()
       
   139 
       
   140         content.iriurl = self.src
       
   141         content.videopath = self.videopath.rstrip("/") + "/"
       
   142 
       
   143         content.iri = self.id + u"/" + os.path.basename(self.src)
       
   144         content.title = self.title
       
   145         content.description = self.desc
       
   146         content.duration = int(self.duration)
       
   147         content.save()
       
   148 
       
   149         self.content = content
       
   150             
       
   151     def process(self):
       
   152         self.processIri()
       
   153         self.saveContent()
       
   154         
       
   155 class BaseFileImport(object):
       
   156 
       
   157     def __init__(self, filepath, videopath):
       
   158         self.__filepath = filepath
       
   159         self.__tempdir = ""
       
   160         self.__videopath = videopath
       
   161         self.__author = None
       
   162 
       
   163         
       
   164     def filepath(): #@NoSelf
       
   165         doc = """Docstring""" #@UnusedVariable
       
   166        
       
   167         def fget(self):
       
   168             return self.__filepath
       
   169            
       
   170         def fset(self, value):
       
   171             self.__filepath = value
       
   172            
       
   173         def fdel(self):
       
   174             del self.__filepath
       
   175            
       
   176         return locals()
       
   177        
       
   178     filepath = property(**filepath())
       
   179     
       
   180     def videopath(): #@NoSelf
       
   181         doc = """Docstring""" #@UnusedVariable
       
   182        
       
   183         def fget(self):
       
   184             return self.__videopath
       
   185            
       
   186         def fset(self, value):
       
   187             self.__videopath = value
       
   188            
       
   189         def fdel(self):
       
   190             del self.__videopath
       
   191            
       
   192         return locals()
       
   193        
       
   194     videopath = property(**videopath())
       
   195 
       
   196     def author(): #@NoSelf
       
   197         doc = """Docstring""" #@UnusedVariable
       
   198        
       
   199         def fget(self):
       
   200             return self.__author
       
   201            
       
   202         def fset(self, value):
       
   203             self.__author = value
       
   204            
       
   205         def fdel(self):
       
   206             del self.__author
       
   207            
       
   208         return locals()
       
   209 
       
   210     author = property(**author())
       
   211     
       
   212        
       
   213 class FileImport(BaseFileImport):
       
   214 
       
   215     def __init__(self, filepath, videopath, flatten):
       
   216         BaseFileImport.__init__(self, filepath, videopath)
       
   217         self.__checkExistingMedia = False
       
   218         self.__flatten = flatten
       
   219         
       
   220     def checkExistingMedia(): #@NoSelf
       
   221         doc = """Docstring""" #@UnusedVariable
       
   222        
       
   223         def fget(self):
       
   224             return self.__checkExistingMedia
       
   225            
       
   226         def fset(self, value):
       
   227             self.__checkExistingMedia = value
       
   228            
       
   229         def fdel(self):
       
   230             del self.__checkExistingMedia
       
   231            
       
   232         return locals()
       
   233 
       
   234     checkExistingMedia = property(**checkExistingMedia())    
       
   235 
       
   236     def flatten(): #@NoSelf
       
   237         doc = """Docstring""" #@UnusedVariable
       
   238        
       
   239         def fget(self):
       
   240             return self.__flatten
       
   241            
       
   242         def fset(self, value):
       
   243             self.__flatten = value
       
   244            
       
   245         def fdel(self):
       
   246             del self.__flatten
       
   247            
       
   248         return locals()
       
   249     flatten = property(**flatten())
       
   250 
       
   251     def processLdt(self, ldtpath=None):
       
   252         
       
   253         # list iri
       
   254         # see if there is some comments
       
   255         # inject comment in iri
       
   256         # copy iri in folder
       
   257         # create or update content
       
   258         contents = {}
       
   259         if ldtpath:
       
   260             doc = xml.dom.minidom.parse(ldtpath)
       
   261         else:
       
   262             doc = xml.dom.minidom.parse(self.filepath)
       
   263         
       
   264         con = xml.xpath.Context.Context(doc, 1, 1, None)
       
   265         
       
   266         #get author from file ldt
       
   267         result = xml.xpath.Evaluate("/iri/project", context=con)
       
   268         for pnode in result:
       
   269             author = pnode.getAttributeNS("user",None)
       
   270             if author:
       
   271                 self.author = unicode(author)
       
   272                 break 
       
   273 
       
   274         result = xml.xpath.Evaluate("/iri/medias/media", context=con)
       
   275         
       
   276         for i, medianode in  enumerate(result):
       
   277         # get iri file's id from file ldt
       
   278             id = medianode.attributes['id'].value
       
   279             if self.checkExistingMedia:
       
   280                 try:
       
   281                     Content.objects.get(iri_id=id)
       
   282                     do_pass = True
       
   283                 except ObjectDoesNotExist: #Content.DoesNotExist
       
   284                     do_pass = False
       
   285             else:
       
   286                     do_pass = False
       
   287             if not do_pass:
       
   288                 if not (contents.has_key(id)):
       
   289                     # Create instance iriInfo(id, order, titledesc, basepath="", videopath=settings.STREAM_URL)
       
   290                     if ldtpath:
       
   291                         contents[id] = IriInfo(id, i, "", os.path.dirname(ldtpath), flatten=self.flatten)
       
   292                     else: 
       
   293                         contents[id] = IriInfo(id, i, "", flatten=self.flatten)
       
   294                     # Get iri file's url from ldt. This url can be relative path or absolute path.
       
   295                 contents[id].src = medianode.attributes['src'].value
       
   296                 if medianode.attributes['video'].value !="":
       
   297                     contents[id].videopath = medianode.attributes['video'].value
       
   298                 elif self.videopath !="" or self.videopath:
       
   299                     contents[id].videopath = self.videopath
       
   300                 else:
       
   301                     contents[id].videopath =settings.STREAM_URL
       
   302                     
       
   303                 
       
   304         #get annotation of file ldt
       
   305         result = xml.xpath.Evaluate("/iri/annotations/content", context=con)
       
   306         
       
   307         for contentnode in result:
       
   308             id = contentnode.attributes['id'].value
       
   309             # pocketfilms.utils.log.debug("ID : " + str(id))
       
   310             if contents.has_key(id):
       
   311                 if self.author:
       
   312                     contentnode.setAttributeNS(None,"author", unicode(self.author))
       
   313                 contents[id].annotations = contentnode
       
   314         
       
   315         #go throught values
       
   316         for iriinfo in contents.values():
       
   317             
       
   318             iriinfo.process()
       
   319             
       
   320             # if yes update
       
   321             # if no create
       
   322             # move iri file to the proper place
       
   323             #return list of iriInfo
       
   324         
       
   325     def processFile(self):
       
   326         if self.filepath.name.endswith(".ldt"):
       
   327             self.processLdt()
       
   328         elif self.filepath.name.endswith(".zip"):
       
   329             self.processZip()
       
   330         else:
       
   331             raise FileImportError("Bad file type")
       
   332 
       
   333 
       
   334     def processZip(self):
       
   335     # """ extraire .zip, pass to method processLdt"""
       
   336         # create temp directory
       
   337         self.__tempdir = tempfile.mkdtemp()
       
   338         openfiles = []
       
   339         flvfiles = []
       
   340         processedids = []
       
   341         
       
   342         try:
       
   343             zipfile = zipfileext.ZipFileExt(self.filepath)
       
   344             zipfile.unzip_into_dir(self.__tempdir)
       
   345             #load ldt
       
   346             foldersToProcess = [self.__tempdir]
       
   347             while len(foldersToProcess):
       
   348                 # pocketfilms.utils.log.debug("folder stack length : "+ str(len(foldersToProcess)))
       
   349                 currentFolder = foldersToProcess.pop()
       
   350                 for entry in os.listdir(currentFolder):
       
   351                     if entry in settings.ZIP_BLACKLIST:
       
   352                         continue
       
   353                     entryPath = os.path.join(currentFolder, entry)
       
   354                     if(os.path.isdir(entryPath)):
       
   355                         # pocketfilms.utils.log.debug("Push folder : " + entryPath)
       
   356                         foldersToProcess.append(entryPath)
       
   357                     elif fnmatch.fnmatch(entry, "*.ldt"):
       
   358                         # pocketfilms.utils.log.debug("Process file : " + entryPath)
       
   359                         ldtid = self.processLdt(entryPath)
       
   360                         processedids.append(ldtid)
       
   361                     elif fnmatch.fnmatch(entry, "*.flv"):
       
   362                         flvfiles.append(entryPath)
       
   363              
       
   364             if settings.CONTENT_ROOT and os.path.exists(settings.CONTENT_ROOT): 
       
   365                 for entry in flvfiles:
       
   366                     shutil.copy(entry, settings.CONTENT_ROOT)
       
   367                     
       
   368         finally:
       
   369             for f in openfiles:
       
   370                 f.close()
       
   371             shutil.rmtree(self.__tempdir)
       
   372         # delete directory
       
   373         return processedids
       
   374         
       
   375     # def processFileLdt(self):
       
   376         # processedids = []
       
   377         # ldtid = self.processLdt(self.filepath)
       
   378         # processedids.append(ldtid)
       
   379         # return processedids