configurationengine/source/plugins/common/ConeCommandPlugin/commandplugin/commandml.py
changeset 3 e7e0ae78773e
parent 0 2e8eeb919028
child 4 0951727b8815
equal deleted inserted replaced
2:87cfa131b535 3:e7e0ae78773e
    20 fecthed from ConfML to maximize portability and minimize maintenance.
    20 fecthed from ConfML to maximize portability and minimize maintenance.
    21 '''
    21 '''
    22 
    22 
    23 import re
    23 import re
    24 import os
    24 import os
    25 import sys
       
    26 import logging
    25 import logging
    27 import types
    26 import types
       
    27 import pkg_resources
    28 
    28 
    29 import subprocess
    29 import subprocess
    30 import __init__
    30 
    31 
    31 from cone.public import plugin,utils
    32 from cone.public import exceptions,plugin,utils,api, settings
    32 
       
    33 def get_folder_set(folder):
       
    34     """
       
    35     Get a set object containing all files of given folder
       
    36     @param folder: the folder to create set for
       
    37     @return: a python set 
       
    38     """
       
    39     fileset = set()
       
    40     for (root, _, filenames) in os.walk(folder):
       
    41         for filename in filenames:
       
    42             fname = utils.relpath(os.path.join(root,filename), folder)
       
    43             fileset.add(fname)
       
    44     
       
    45     return fileset
    33 
    46 
    34 class CommandImpl(plugin.ImplBase):
    47 class CommandImpl(plugin.ImplBase):
    35     """
    48     """
    36     Plugin implementation class. 
    49     Plugin implementation class. 
    37     """
    50     """
    45         """
    58         """
    46         plugin.ImplBase.__init__(self,ref,configuration)###3
    59         plugin.ImplBase.__init__(self,ref,configuration)###3
    47         self.desc = ""
    60         self.desc = ""
    48         self.logger = logging.getLogger('cone.commandml(%s)' % self.ref)
    61         self.logger = logging.getLogger('cone.commandml(%s)' % self.ref)
    49         self.reader = reader
    62         self.reader = reader
       
    63         for element in self.reader.elements:
       
    64             element.set_logger(self.logger)
    50         
    65         
    51 
    66 
    52     def generate(self, context=None):
    67     def generate(self, context=None):
    53         """
    68         """
    54         Generate the given implementation.
    69         Generate the given implementation.
    55         """
    70         """
    56         self.create_output()        
    71         
       
    72         self.create_output(context)
    57         return 
    73         return 
    58     
    74     
    59     def generate_layers(self,layers):
    75     def generate_layers(self,layers):
    60         """
    76         """
    61         Generate the given Configuration layers.
    77         Generate the given Configuration layers.
    62         """
    78         """
    63         self.logger.info('Generating layers %s' % layers)
    79         self.logger.info('Generating layers %s' % layers)
    64         self.create_output(layers)
    80         self.create_output(layers)
    65         return 
    81         return 
    66     
    82     
    67     def create_output(self, layers=None):
    83     def create_output(self, context, layers=None):
    68         """
    84         """
    69         Function to generate output files.
    85         Function to generate output files.
    70         """
    86         """
    71         
    87         self.context = context
    72         tmpDict = self.__create_helper_variables()
    88         tmpDict = self.__create_helper_variables()
    73         
    89         # Get the contents of output folder before the generation
       
    90         outset_before = get_folder_set(context.output)
    74         for element in self.reader.elements:
    91         for element in self.reader.elements:
    75             #Element can be either command or condition.
    92             #Element can be either command or condition.
    76             element.set_logger(self.logger)
    93             element.set_logger(self.logger)
    77             element.execute(tmpDict)        
    94             element.execute(context, tmpDict)        
       
    95         
       
    96         # Get the contents of output folder after the generation 
       
    97         # and get the new files created by the set difference.
       
    98         # NOTE! this does not recognize files outside output folder!
       
    99         outset_after = get_folder_set(context.output)
       
   100         outset = outset_after - outset_before
       
   101         for outfile in outset:
       
   102             context.add_file(outfile, implementation=self)
    78         return
   103         return
    79 
   104 
    80     def __create_helper_variables(self):
   105     def __create_helper_variables(self):
    81         """
   106         """
    82         Internal function to create dictionary containing most often used ConE "environment" variables.
   107         Internal function to create dictionary containing most often used ConE "environment" variables.
    83         """        
   108         """        
    84         tmp = {}
   109         tmp = {}
    85         tmp["%CONE_OUT%"] = self.output
   110         tmp["%CONE_OUT%"] = os.path.join(self.context.output, self.output).rstrip('\\')
    86         tmp["%CONE_OUT_ABSOLUTE%"] = os.path.abspath(self.output)
   111         tmp["%CONE_OUT_ABSOLUTE%"] = os.path.abspath(os.path.join(self.context.output, self.output)).rstrip('\\')
    87         return tmp    
   112         return tmp    
    88     
   113     
    89     def has_ref(self, refs):
   114     def has_ref(self, refs):
    90         """
   115         """
    91         @returns True if the implementation uses the given ref as input value.
   116         @returns True if the implementation uses the given ref as input value.
    98 class CommandImplReader(plugin.ReaderBase):
   123 class CommandImplReader(plugin.ReaderBase):
    99     """
   124     """
   100     Parses a single commandml file
   125     Parses a single commandml file
   101     """ 
   126     """ 
   102     NAMESPACE = 'http://www.s60.com/xml/commandml/1'
   127     NAMESPACE = 'http://www.s60.com/xml/commandml/1'
       
   128     NAMESPACE_ID = 'commandml'
       
   129     ROOT_ELEMENT_NAME = 'commandml'
   103     FILE_EXTENSIONS = ['commandml']
   130     FILE_EXTENSIONS = ['commandml']
   104     
   131     
   105     def __init__(self):
   132     def __init__(self):
   106         """
   133         """
   107         Constructor
   134         Constructor
   120         reader.from_etree(etree)
   147         reader.from_etree(etree)
   121         impl = CommandImpl(resource_ref, configuration, reader)
   148         impl = CommandImpl(resource_ref, configuration, reader)
   122         if reader.tags:
   149         if reader.tags:
   123             impl.set_tags(reader.tags)
   150             impl.set_tags(reader.tags)
   124         return impl
   151         return impl
   125             
   152     
       
   153     @classmethod
       
   154     def get_schema_data(cls):
       
   155         return pkg_resources.resource_string('commandplugin', 'xsd/commandml.xsd')
       
   156     
   126     def set_default_view(self, dview):
   157     def set_default_view(self, dview):
   127         """
   158         """
   128         Function to set default view that is needed when solving out ConfML reference information
   159         Function to set default view that is needed when solving out ConfML reference information
   129         """        
   160         """        
   130         self.dview = dview
   161         self.dview = dview
   258         self.logger = logger
   289         self.logger = logger
   259         for cmd in self.commands:
   290         for cmd in self.commands:
   260             cmd.set_logger(logger)        
   291             cmd.set_logger(logger)        
   261 
   292 
   262     def add_command(self, command):
   293     def add_command(self, command):
   263         self.command.append(command)
   294         self.commands.append(command)
   264 
   295 
   265     def execute(self, replaceDict=None):
   296     def execute(self, context, replaceDict=None):
   266         if self.__solve_condition(self.condition):
   297         if self._solve_condition(self.condition, context):
   267             #Condition is true -> running command
   298             #Condition is true -> running command
   268             for command in self.commands:                
   299             for command in self.commands:                
   269                 command.execute(replaceDict)
   300                 command.execute(context, replaceDict)
   270         else:
   301         else:
   271             self.logger.info("Ignoring %s because it is evaluated as False." % self.condition)
   302             self.logger.info("Ignoring %s because it is evaluated as False." % self.condition)
   272 
   303 
   273     def __solve_condition(self, condition_str):
   304     def _solve_condition(self, condition_str, context):
   274         """
   305         """
   275         Internal function to handle condition
   306         Internal function to handle condition
   276         """
   307         """
   277         if condition_str != "":
   308         if condition_str != "":
   278             #Expanding ConfML information
   309             #Expanding ConfML information
   279             modstr = utils.expand_delimited_tokens(
   310             modstr = utils.expand_delimited_tokens(
   280                 condition_str,
   311                 condition_str,
   281                 lambda ref, index: repr(self.dview.get_feature(ref).get_value()))
   312                 lambda ref, index: repr(context.configuration.get_default_view().get_feature(ref).get_value()))
   282             return eval(modstr)
   313             return eval(modstr)
   283         else:
   314         else:
   284             #Empty condition is true always.
   315             #Empty condition is true always.
   285             return True
   316             return True
   286 
   317 
   321     
   352     
   322     def set_cwd(self, cwd):
   353     def set_cwd(self, cwd):
   323         self.cwd = cwd
   354         self.cwd = cwd
   324     
   355     
   325     def set_all_envs(self, envs):
   356     def set_all_envs(self, envs):
   326         if envs:
   357         self.envs = envs
   327             self.envs = eval(envs)
       
   328     def set_default_view(self, dview):
   358     def set_default_view(self, dview):
   329         self.dview = dview
   359         self.dview = dview
   330         
   360         
   331     def set_env(self, name, value):
   361     def set_env(self, name, value):
   332         self.envs[name] = value
   362         self.envs[name] = value
   399         """
   429         """
   400         """
   430         """
   401         for filter in self.filters:
   431         for filter in self.filters:
   402             filter.report(self.logger)
   432             filter.report(self.logger)
   403 
   433 
   404     def execute(self, replaceDict=None):
   434     def execute(self, context, replaceDict=None):
       
   435         self.dview = context.configuration.get_default_view()
       
   436         
   405         self.solve_refs()
   437         self.solve_refs()
       
   438         
       
   439         try:
       
   440             if self.envs:   env_dict = eval(self.envs)
       
   441             else:           env_dict = None
       
   442         except Exception, e:
       
   443             raise RuntimeError("Failed to evaluate env dictionary: %s: %s" % (e.__class__.__name__, e))
   406         
   444         
   407         exit_code = 0
   445         exit_code = 0
   408         try:
   446         try:
   409             try:
   447             try:
   410                 if self.cwd is not None:
   448                 if self.cwd is not None:
   413                     cwd = self.cwd
   451                     cwd = self.cwd
   414                 command_str = self.executable + " " + self.__replace_helper_variables(self.get_arguments_string(), replaceDict)
   452                 command_str = self.executable + " " + self.__replace_helper_variables(self.get_arguments_string(), replaceDict)
   415                 self.logger.info("Running command: \"%s\"" % command_str)
   453                 self.logger.info("Running command: \"%s\"" % command_str)
   416                 self.logger.info("with args: shell=%s envs=%s cwd=%s bufsize=%s stdin=%s stdout=%s stderr=%s" \
   454                 self.logger.info("with args: shell=%s envs=%s cwd=%s bufsize=%s stdin=%s stdout=%s stderr=%s" \
   417                                  % (self.shell, self.envs, cwd, self.bufsize, \
   455                                  % (self.shell, self.envs, cwd, self.bufsize, \
   418                                     self.get_pipe("stdin", 'r'),self.get_pipe("stdout"), self.get_pipe("stderr")))                    
   456                                     self.get_pipe("stdin", 'r'),self.get_pipe("stdout"), self.get_pipe("stderr")))
   419                 pid = subprocess.Popen(command_str, shell=self.shell, env=self.envs, cwd=cwd,\
   457                 pid = subprocess.Popen(command_str, shell=self.shell, env=env_dict, cwd=cwd,\
   420                                           bufsize=self.bufsize, stdin = self.get_pipe("stdin", 'r'),\
   458                                           bufsize=self.bufsize, stdin = self.get_pipe("stdin", 'r'),\
   421                                           stdout = self.get_pipe("stdout"), stderr = self.get_pipe("stderr"))
   459                                           stdout = self.get_pipe("stdout"), stderr = self.get_pipe("stderr"))
   422                 #Waiting for process to complete
   460                 #Waiting for process to complete
   423                 retcode = pid.wait()
   461                 retcode = pid.wait()
   424                 #Storing stream information for possible further processing.
   462                 #Storing stream information for possible further processing.
   450         
   488         
   451         self.executable = self.__solve_ref(self.executable)
   489         self.executable = self.__solve_ref(self.executable)
   452         self.shell = self.__solve_ref(self.shell)
   490         self.shell = self.__solve_ref(self.shell)
   453         self.bufsize = self.__solve_ref(self.bufsize)
   491         self.bufsize = self.__solve_ref(self.bufsize)
   454         self.cwd = self.__solve_ref(self.cwd)
   492         self.cwd = self.__solve_ref(self.cwd)
       
   493         self.envs = self.__solve_ref(self.envs)
   455         for argument in self.arguments:
   494         for argument in self.arguments:
   456             self.arguments[self.arguments.index(argument)] = self.__solve_ref(argument) 
   495             self.arguments[self.arguments.index(argument)] = self.__solve_ref(argument) 
   457         for pipe in self.pipes.keys():
   496         for pipe in self.pipes.keys():
   458             self.pipes[pipe] = self.__solve_ref(self.pipes[pipe])
   497             self.pipes[pipe] = self.__solve_ref(self.pipes[pipe])
   459 
   498