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. |
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 |