configurationengine/source/plugins/common/ConeContentPlugin/contentplugin/contentml.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
child 5 d2c80f5cab53
equal deleted inserted replaced
2:87cfa131b535 3:e7e0ae78773e
    21 import re
    21 import re
    22 import os
    22 import os
    23 import sys
    23 import sys
    24 import logging
    24 import logging
    25 import shutil
    25 import shutil
       
    26 import pkg_resources
    26             
    27             
    27 import __init__
    28 import __init__
    28 
    29 
    29 from cone.public import exceptions,plugin,utils,api,container
    30 from cone.public import exceptions,plugin,utils,api,container
    30 from contentplugin import contentmlparser
    31 from contentplugin import contentmlparser
    44         """
    45         """
    45         plugin.ImplBase.__init__(self,ref,configuration)
    46         plugin.ImplBase.__init__(self,ref,configuration)
    46         self.desc = ""
    47         self.desc = ""
    47         self.logger = logging.getLogger('cone.content(%s)' % self.ref)
    48         self.logger = logging.getLogger('cone.content(%s)' % self.ref)
    48         self.errors = False
    49         self.errors = False
       
    50         self.context = plugin.GenerationContext(configuration=configuration)
       
    51 
    49 
    52 
    50     def list_output_files(self):
    53     def list_output_files(self):
    51         """
    54         """
    52         Return a list of output files as an array. 
    55         Return a list of output files as an array. 
    53         """
    56         """
    74                 copylist = []
    77                 copylist = []
    75                 if print_info:
    78                 if print_info:
    76                     self.logger.info('Content copy items from %s to %s' % (input.dir,os.path.join(self.output,output.dir)))
    79                     self.logger.info('Content copy items from %s to %s' % (input.dir,os.path.join(self.output,output.dir)))
    77                 
    80                 
    78                 if input.__class__.__name__ == "ContentInput":
    81                 if input.__class__.__name__ == "ContentInput":
    79                     copylist = self.create_copy_list(content=self.configuration.layered_content(),
    82                     copylist = self.create_copy_list(content=self.configuration.layered_content(empty_folders=True),
    80                                                      input=input.dir,
    83                                                      input=input.dir,
    81                                                      output=os.path.join(self.output,output.dir),
    84                                                      output=os.path.join(self.output,output.dir),
    82                                                      include_pattern=input.get_include_pattern(),
    85                                                      include_pattern=input.get_include_pattern(),
    83                                                      exclude_pattern=input.get_exclude_pattern(),
    86                                                      exclude_pattern=input.get_exclude_pattern(),
    84                                                      files=input.get_filelist(),
    87                                                      files=input.get_filelist(),
    89                     if input.dir != None:
    92                     if input.dir != None:
    90                         fulldir = os.path.abspath(os.path.join(self.configuration.get_project().get_storage().get_path(),input.dir))
    93                         fulldir = os.path.abspath(os.path.join(self.configuration.get_project().get_storage().get_path(),input.dir))
    91                     else:
    94                     else:
    92                         fulldir = self.configuration.get_project().get_storage().get_path()
    95                         fulldir = self.configuration.get_project().get_storage().get_path()
    93                     
    96                     
    94                     data = container.DataContainer()                     
    97                     data = container.DataContainer()
    95                     for root, dirs, files in os.walk(fulldir):
    98                     for root, dirs, files in os.walk(fulldir):
    96                         for f in files:                            
    99                         for f in files:
    97                             filepath = utils.resourceref.norm(os.path.join(root, f))
   100                             filepath = utils.resourceref.norm(os.path.join(root, f))
    98                             key = utils.resourceref.replace_dir(filepath,fulldir,"")
   101                             key = utils.resourceref.replace_dir(filepath,fulldir,"")
    99                             data.add_value(key,filepath)
   102                             data.add_value(key,filepath)
   100                             #data.add_value(filepath,filepath)
   103                         
       
   104                         # If the root contains no directories and no files, it is
       
   105                         # an empty directory and needs to be added
       
   106                         if not dirs and not files:
       
   107                             filepath = utils.resourceref.norm(root)
       
   108                             key = utils.resourceref.replace_dir(filepath,fulldir,"")
       
   109                             data.add_value(key,filepath)
       
   110                     
   101                     copylist = self.create_copy_list(content=data,
   111                     copylist = self.create_copy_list(content=data,
   102                                                      input=input.dir,
   112                                                      input=input.dir,
   103                                                      output=os.path.join(self.output,output.dir),
   113                                                      output=os.path.join(self.output,output.dir),
   104                                                      include_pattern=input.get_include_pattern(),
   114                                                      include_pattern=input.get_include_pattern(),
   105                                                      exclude_pattern=input.get_exclude_pattern(),
   115                                                      exclude_pattern=input.get_exclude_pattern(),
   109                                                      external=True)
   119                                                      external=True)
   110                 else:
   120                 else:
   111                     logging.getLogger('cone.content').warning("Unknown input %s" % (input.__class__.__name__))
   121                     logging.getLogger('cone.content').warning("Unknown input %s" % (input.__class__.__name__))
   112                 
   122                 
   113                 fullcopylist += copylist
   123                 fullcopylist += copylist
   114                  
   124         
       
   125         # Sort to make automated testing easier (list always in same order)
       
   126         fullcopylist.sort()
       
   127         
   115         return fullcopylist
   128         return fullcopylist
   116 
   129 
   117     def generate(self, context=None):
   130     def generate(self, context=None):
   118         """
   131         """
   119         Generate the given implementation.
   132         Generate the given implementation.
   120         """
   133         """
       
   134         #assert context, "No Context given for generation!"
       
   135         self.context = context
   121         self.logger.info('Generating')
   136         self.logger.info('Generating')
   122         self.create_output()
   137         self.create_output()
   123         return 
   138         return 
   124 
   139 
   125     def create_output(self,layers=None):
   140     def create_output(self,layers=None):
   126         """
   141         """
   127         Create the output directory from the content folder files
   142         Create the output directory from the content folder files
   128         """
   143         """
   129         if not self.errors:
   144         if not self.errors:
   130             datacontainer = self.configuration.layered_content(layers)
       
   131             #root = self.configuration.get_root()
       
   132             copylist = self.get_full_copy_list(True)
   145             copylist = self.get_full_copy_list(True)
   133             for copy_item in copylist:
   146             for copy_item in copylist:
   134                 sourceref = copy_item[0]
   147                 source_path = copy_item[0]
   135                 targetfile = copy_item[1]
   148                 target_path = copy_item[1]
   136                 external = copy_item[2]                                
   149                 external = copy_item[2]
   137                 
   150                 
   138                 self.logger.info('Copy from %s to %s' % (sourceref,targetfile))                   
   151                 self.logger.info('Copy from %s to %s' % (source_path,target_path))
   139                 if not os.path.exists(os.path.dirname(targetfile)):
   152                 
   140                     os.makedirs(os.path.dirname(targetfile))
   153                 # Open file resource if the source is a file
   141                 if not external:
   154                 file_res = None
   142                     outfile = open(targetfile,"wb")
   155                 if not external and not self.configuration.get_storage().is_folder(source_path):
   143                     res = self.configuration.get_storage().open_resource(sourceref,"rb")
   156                     file_res = self.configuration.get_storage().open_resource(source_path, "rb")
   144                     outfile.write(res.read())
   157                 elif external and os.path.isfile(source_path):
       
   158                     file_res = open(source_path, 'rb')
       
   159                 
       
   160                 # Copy file or create empty directory
       
   161                 if file_res:
       
   162                     try:        self._copy_file(file_res, target_path)
       
   163                     finally:    file_res.close()
   145                 else:
   164                 else:
   146                     shutil.copyfile(sourceref,targetfile)
   165                     path = os.path.join(self.context.output, target_path)
       
   166                     if not os.path.exists(path): os.makedirs(path)
   147             return 
   167             return 
   148         else:
   168         else:
   149             self.logger.error('Plugin had errors! Bailing out!')                   
   169             self.logger.error('Plugin had errors! Bailing out!')
   150             
   170     
       
   171     def _copy_file(self, source_file, target_file_path):
       
   172         outfile = self.context.create_file(target_file_path, implementation=self)
       
   173         try:
       
   174             # Copy data in chunks of max 2 MB to avoid
       
   175             # memory errors with very large files
       
   176             while True:
       
   177                 data = source_file.read(2 * 1024 * 1024)
       
   178                 if data:    outfile.write(data)
       
   179                 else:       break
       
   180         finally:
       
   181             outfile.close()
   151 
   182 
   152     def create_copy_list(self, **kwargs):
   183     def create_copy_list(self, **kwargs):
   153         """
   184         """
   154         Return a list copy list where each element is a (from,to) tuple 
   185         Return a list copy list where each element is a (from, to, is_external) tuple 
   155         """
   186         """
   156         datacontainer = kwargs.get('content',None)
   187         datacontainer = kwargs.get('content',None)
   157         input_dir     = kwargs.get('input','')
   188         input_dir     = kwargs.get('input','')
   158         output_dir    = kwargs.get('output','')
   189         output_dir    = kwargs.get('output','')
   159         output_file   = kwargs.get('output_file','')        
   190         output_file   = kwargs.get('output_file','')        
   167         """ 
   198         """ 
   168         First get only the files list from content files.
   199         First get only the files list from content files.
   169         Then apply the possible filters. 
   200         Then apply the possible filters. 
   170         """
   201         """
   171         if input_dir == None:
   202         if input_dir == None:
   172            self.logger.warning("Input dir is none!")
   203             self.logger.warning("Input dir is none!")
   173 
   204 
   174         
   205         
   175         if files != []:
   206         if files != []:
   176             for f in files:
   207             for f in files:
   177                 if f in contentfiles:
   208                 if f in contentfiles:
   197             contentfiles = utils.resourceref.neg_filter_resources(contentfiles,filter_regexp)
   228             contentfiles = utils.resourceref.neg_filter_resources(contentfiles,filter_regexp)
   198         for outfile in contentfiles:
   229         for outfile in contentfiles:
   199             sourcefile = ""
   230             sourcefile = ""
   200             targetfile = ""
   231             targetfile = ""
   201             
   232             
   202             if input_dir != None and outfile.startswith(input_dir):
   233             # For the startswith() check, make sure that input dir has a trailing slash
       
   234             if input_dir and input_dir[-1] != '/':  input_dir_check = input_dir + '/'
       
   235             else:                                   input_dir_check = input_dir
       
   236             
       
   237             if input_dir != None and (input_dir == outfile or outfile.startswith(input_dir_check)):
   203                 sourcefile = datacontainer.get_value(outfile)
   238                 sourcefile = datacontainer.get_value(outfile)
   204                 if flatten:
   239                 if flatten:
   205                     targetfile = utils.resourceref.join_refs([output_dir, os.path.basename(outfile)])
   240                     targetfile = utils.resourceref.join_refs([output_dir, os.path.basename(outfile)])
   206                     targetfile = utils.resourceref.norm(targetfile)
   241                     targetfile = utils.resourceref.norm(targetfile)
   207                 else:
   242                 else:
   218                     targetfile = utils.resourceref.replace_dir(sourcefile,fulldir,output_dir)
   253                     targetfile = utils.resourceref.replace_dir(sourcefile,fulldir,output_dir)
   219                 
   254                 
   220             if output_file:
   255             if output_file:
   221                 #Renaming output if defined
   256                 #Renaming output if defined
   222                 targetfile = targetfile.replace(os.path.basename(targetfile), output_file)
   257                 targetfile = targetfile.replace(os.path.basename(targetfile), output_file)
   223                     
   258                 
   224             if sourcefile and targetfile:                
   259             if sourcefile and targetfile:
   225                 copylist.append((sourcefile,targetfile, external))
   260                 copylist.append((sourcefile,targetfile,external))
   226         return copylist
   261         return copylist
   227 
   262     
       
   263     def uses_layer(self, layer):
       
   264         layered_content = layer.layered_content().list_keys()
       
   265         for f in self.get_full_copy_list():
       
   266             for file in layered_content:
       
   267                 if utils.resourceref.norm(os.path.join(utils.resourceref.get_path(layer.get_path()), 'content', file)) == f[0]:
       
   268                     return True
       
   269         return False
       
   270     
       
   271     def uses_layers(self, layers, context):
       
   272         # Use the base implementation to check with refs first
       
   273         if super(ContentImpl, self).uses_layers(layers, context):
       
   274             return True
       
   275         
       
   276         # Then check if any of the files in the copy list come from the layers
       
   277         copy_list = self.get_full_copy_list()
       
   278         for layer in layers:
       
   279             layered_content = layer.layered_content().list_keys()
       
   280             for f in copy_list:
       
   281                 for file in layered_content:
       
   282                     if utils.resourceref.norm(os.path.join(utils.resourceref.get_path(layer.get_path()), 'content', file)) == f[0]:
       
   283                         return True
       
   284         return False
       
   285     
       
   286     
   228 class ContentImplReaderBase(object):
   287 class ContentImplReaderBase(object):
   229     FILE_EXTENSIONS = ['content', 'contentml']
   288     FILE_EXTENSIONS = ['content', 'contentml']
   230     
   289     
   231     @classmethod
   290     @classmethod
   232     def read_impl(cls, resource_ref, configuration, etree):
   291     def read_impl(cls, resource_ref, configuration, etree):
   249             
   308             
   250         return impl
   309         return impl
   251 
   310 
   252 class ContentImplReader1(ContentImplReaderBase, plugin.ReaderBase):
   311 class ContentImplReader1(ContentImplReaderBase, plugin.ReaderBase):
   253     NAMESPACE = 'http://www.s60.com/xml/content/1'
   312     NAMESPACE = 'http://www.s60.com/xml/content/1'
       
   313     NAMESPACE_ID = 'contentml1'
       
   314     ROOT_ELEMENT_NAME = 'content'
   254     parser_class = contentmlparser.Content1Parser
   315     parser_class = contentmlparser.Content1Parser
       
   316     
       
   317     @classmethod
       
   318     def get_schema_data(cls):
       
   319         return pkg_resources.resource_string('contentplugin', 'xsd/contentml.xsd')
   255 
   320 
   256 class ContentImplReader2(ContentImplReaderBase, plugin.ReaderBase):
   321 class ContentImplReader2(ContentImplReaderBase, plugin.ReaderBase):
   257     NAMESPACE = 'http://www.s60.com/xml/content/2'
   322     NAMESPACE = 'http://www.s60.com/xml/content/2'
       
   323     NAMESPACE_ID = 'contentml2'
       
   324     ROOT_ELEMENT_NAME = 'content'
   258     parser_class = contentmlparser.Content2Parser
   325     parser_class = contentmlparser.Content2Parser
       
   326     
       
   327     @classmethod
       
   328     def get_schema_data(cls):
       
   329         return pkg_resources.resource_string('contentplugin', 'xsd/contentml2.xsd')