|  |  |  | @ -1,17 +1,20 @@ | 
			
		
	
		
			
				
					|  |  |  |  | # Imports | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | from commonkit import parse_jinja_template, read_file | 
			
		
	
		
			
				
					|  |  |  |  | from commonkit import indent, parse_jinja_template, read_file, split_csv | 
			
		
	
		
			
				
					|  |  |  |  | from jinja2 import TemplateNotFound, TemplateError | 
			
		
	
		
			
				
					|  |  |  |  | import logging | 
			
		
	
		
			
				
					|  |  |  |  | import os | 
			
		
	
		
			
				
					|  |  |  |  | from ...variables import LOGGER_NAME | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | log = logging.getLogger(__name__) | 
			
		
	
		
			
				
					|  |  |  |  | log = logging.getLogger(LOGGER_NAME) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | # Exports | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | __all__ = ( | 
			
		
	
		
			
				
					|  |  |  |  |     "Command", | 
			
		
	
		
			
				
					|  |  |  |  |     "Content", | 
			
		
	
		
			
				
					|  |  |  |  |     "ItemizedCommand", | 
			
		
	
		
			
				
					|  |  |  |  |     "Prompt", | 
			
		
	
		
			
				
					|  |  |  |  |     "Sudo", | 
			
		
	
		
			
				
					|  |  |  |  |     "Template", | 
			
		
	
		
			
				
					|  |  |  |  | ) | 
			
		
	
	
		
			
				
					|  |  |  | @ -118,6 +121,135 @@ class Command(object): | 
			
		
	
		
			
				
					|  |  |  |  |         return self.statement | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class Content(object): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def __init__(self, content_type, caption=None, css=None, heading=None, height=None, image=None, message=None, | 
			
		
	
		
			
				
					|  |  |  |  |                  width=None, **kwargs): | 
			
		
	
		
			
				
					|  |  |  |  |         self.caption = caption | 
			
		
	
		
			
				
					|  |  |  |  |         self.css = css | 
			
		
	
		
			
				
					|  |  |  |  |         self.heading = heading | 
			
		
	
		
			
				
					|  |  |  |  |         self.height = height | 
			
		
	
		
			
				
					|  |  |  |  |         self.image = image | 
			
		
	
		
			
				
					|  |  |  |  |         self.message = message | 
			
		
	
		
			
				
					|  |  |  |  |         self.width = width | 
			
		
	
		
			
				
					|  |  |  |  |         self.name = "content" | 
			
		
	
		
			
				
					|  |  |  |  |         self.type = content_type | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         self.kwargs = kwargs | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def __getattr__(self, item): | 
			
		
	
		
			
				
					|  |  |  |  |         return self.kwargs.get(item) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def __repr__(self): | 
			
		
	
		
			
				
					|  |  |  |  |         return "<%s %s>" % (self.__class__.__name__, self.content_type) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @property | 
			
		
	
		
			
				
					|  |  |  |  |     def is_itemized(self): | 
			
		
	
		
			
				
					|  |  |  |  |         """Always returns ``False``. Content cannot be itemized.""" | 
			
		
	
		
			
				
					|  |  |  |  |         return False | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def get_output(self, output_format): | 
			
		
	
		
			
				
					|  |  |  |  |         if self.content_type == "explain": | 
			
		
	
		
			
				
					|  |  |  |  |             return self._get_message_output(output_format) | 
			
		
	
		
			
				
					|  |  |  |  |         elif self.content_type == "screenshot": | 
			
		
	
		
			
				
					|  |  |  |  |             return self._get_image_output(output_format) | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             log.warning("Invalid content type: %s" % self.content_type) | 
			
		
	
		
			
				
					|  |  |  |  |             return None | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # noinspection PyUnusedLocal | 
			
		
	
		
			
				
					|  |  |  |  |     def get_statement(self, cd=True, include_comment=True, include_register=True, include_stop=True): | 
			
		
	
		
			
				
					|  |  |  |  |         """Override to return only bash output format.""" | 
			
		
	
		
			
				
					|  |  |  |  |         return self.get_output("bash") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def _get_image_output(self, output_format): | 
			
		
	
		
			
				
					|  |  |  |  |         """Get the output of the content when the content type is an image.""" | 
			
		
	
		
			
				
					|  |  |  |  |         a = list() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if output_format == "bash": | 
			
		
	
		
			
				
					|  |  |  |  |             if self.caption: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("# %s" % self.caption) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("# %s" % self.image) | 
			
		
	
		
			
				
					|  |  |  |  |         elif output_format == "html": | 
			
		
	
		
			
				
					|  |  |  |  |             b = list() | 
			
		
	
		
			
				
					|  |  |  |  |             b.append('<img src="%s"' % self.image) | 
			
		
	
		
			
				
					|  |  |  |  |             b.append('alt="%s"' % self.caption or self.comment) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if self.css is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 b.append('class="%s"' % self.css) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if self.height is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 b.append('height="%s"' % self.height) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if self.width is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 b.append('width="%s"' % self.width) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append(" ".join(b) + ">") | 
			
		
	
		
			
				
					|  |  |  |  |         elif output_format == "md": | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("" % (self.caption or self.comment, self.image)) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("") | 
			
		
	
		
			
				
					|  |  |  |  |         elif output_format == "rst": | 
			
		
	
		
			
				
					|  |  |  |  |             a.append(".. figure:: %s" % self.image) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if self.caption is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append(indent(":alt: %s" % self.caption, 8)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if self.height is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append(indent(":height: %s" % self.height, 8)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if self.height is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append(indent(":height: %s" % self.height, 8)) | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             if self.caption: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("%s: %s" % (self.caption, self.image)) | 
			
		
	
		
			
				
					|  |  |  |  |             else: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append(self.image) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return "\n".join(a) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def _get_message_output(self, output_format): | 
			
		
	
		
			
				
					|  |  |  |  |         """Get the output of the content when the content type is a message.""" | 
			
		
	
		
			
				
					|  |  |  |  |         a = list() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if output_format == "bash": | 
			
		
	
		
			
				
					|  |  |  |  |             if self.heading: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("# %s: %s" % (self.heading, self.message)) | 
			
		
	
		
			
				
					|  |  |  |  |             else: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("# %s" % self.message) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("") | 
			
		
	
		
			
				
					|  |  |  |  |         elif output_format == "html": | 
			
		
	
		
			
				
					|  |  |  |  |             if self.heading: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("<h2>%s</h2>" % self.heading) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("<p>%s</p>" % self.message) | 
			
		
	
		
			
				
					|  |  |  |  |         elif output_format == "md": | 
			
		
	
		
			
				
					|  |  |  |  |             if self.heading: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("## %s" % self.heading) | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append(self.message) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("") | 
			
		
	
		
			
				
					|  |  |  |  |         elif output_format == "rst": | 
			
		
	
		
			
				
					|  |  |  |  |             if self.heading: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append(self.heading) | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("=" * len(self.heading)) | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append(self.message) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("") | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             if self.heading: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("***** %s *****" % self.heading) | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append("") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append(self.message) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return "\n".join(a) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class ItemizedCommand(object): | 
			
		
	
		
			
				
					|  |  |  |  |     """An itemized command represents multiple commands of with the same statement but different parameters.""" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -194,6 +326,133 @@ class ItemizedCommand(object): | 
			
		
	
		
			
				
					|  |  |  |  |         return True | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class Prompt(Command): | 
			
		
	
		
			
				
					|  |  |  |  |     """Prompt the user for input.""" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def __init__(self, name, back_title="Input", choices=None, default=None, dialog=False, help_text=None, label=None, | 
			
		
	
		
			
				
					|  |  |  |  |                  **kwargs): | 
			
		
	
		
			
				
					|  |  |  |  |         """Initialize a prompt for user input. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param name: The variable name. | 
			
		
	
		
			
				
					|  |  |  |  |         :type name: str | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param back_title: The back title of the input. Used only when ``dialog`` is enabled. | 
			
		
	
		
			
				
					|  |  |  |  |         :type back_title: str | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param choices: Valid choices for the variable. May be given as a list of strings or a comma separated string. | 
			
		
	
		
			
				
					|  |  |  |  |         :type choices: list[str] | str | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param default: The default value of the variable. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param dialog: Indicates the dialog command should be used. | 
			
		
	
		
			
				
					|  |  |  |  |         :type dialog: bool | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param help_text: Additional text to display. Only use when ``fancy`` is ``True``. | 
			
		
	
		
			
				
					|  |  |  |  |         :type help_text: str | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         :param label: The label of the prompt. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         """ | 
			
		
	
		
			
				
					|  |  |  |  |         self.back_title = back_title | 
			
		
	
		
			
				
					|  |  |  |  |         self.default = default | 
			
		
	
		
			
				
					|  |  |  |  |         self.dialog_enabled = dialog | 
			
		
	
		
			
				
					|  |  |  |  |         self.help_text = help_text | 
			
		
	
		
			
				
					|  |  |  |  |         self.label = label or name.replace("_", " ").title() | 
			
		
	
		
			
				
					|  |  |  |  |         self.variable_name = name | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if type(choices) in (list, tuple): | 
			
		
	
		
			
				
					|  |  |  |  |             self.choices = choices | 
			
		
	
		
			
				
					|  |  |  |  |         elif type(choices) is str: | 
			
		
	
		
			
				
					|  |  |  |  |             self.choices = split_csv(choices, smart=False) | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             self.choices = None | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         kwargs.setdefault("comment", "prompt user for %s input" % name) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         super().__init__(name, **kwargs) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def get_statement(self, cd=True, include_comment=True, include_register=True, include_stop=True): | 
			
		
	
		
			
				
					|  |  |  |  |         """Get the statement using dialog or read.""" | 
			
		
	
		
			
				
					|  |  |  |  |         if self.dialog_enabled: | 
			
		
	
		
			
				
					|  |  |  |  |             return self._get_dialog_statement() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return self._get_read_statement() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def _get_dialog_statement(self): | 
			
		
	
		
			
				
					|  |  |  |  |         """Get the dialog statement.""" | 
			
		
	
		
			
				
					|  |  |  |  |         a = list() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         a.append('dialog --clear --backtitle "%s" --title "%s"' % (self.back_title, self.label)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if self.choices is not None: | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('--menu "%s" 15 40 %s' % (self.help_text or "Select", len(self.choices))) | 
			
		
	
		
			
				
					|  |  |  |  |             count = 1 | 
			
		
	
		
			
				
					|  |  |  |  |             for choice in self.choices: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append('"%s" %s' % (choice, count)) | 
			
		
	
		
			
				
					|  |  |  |  |                 count += 1 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('2>/tmp/input.txt') | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             if self.help_text is not None: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append('--inputbox "%s"' % self.help_text) | 
			
		
	
		
			
				
					|  |  |  |  |             else: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append('--inputbox ""') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('8 60 2>/tmp/input.txt') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         b = list() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         b.append('touch /tmp/input.txt') | 
			
		
	
		
			
				
					|  |  |  |  |         b.append(" ".join(a)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         b.append('%s=$(</tmp/input.txt)' % self.variable_name) | 
			
		
	
		
			
				
					|  |  |  |  |         b.append('clear') | 
			
		
	
		
			
				
					|  |  |  |  |         b.append('rm /tmp/input.txt') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if self.default is not None: | 
			
		
	
		
			
				
					|  |  |  |  |             b.append('if [[ -z "$%s" ]]; then %s="%s"; fi;' % (self.variable_name, self.variable_name, self.default)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # b.append('echo "$%s"' % self.name) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return "\n".join(b) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def _get_read_statement(self): | 
			
		
	
		
			
				
					|  |  |  |  |         """Get the standard read statement.""" | 
			
		
	
		
			
				
					|  |  |  |  |         a = list() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if self.choices is not None: | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('echo "%s "' % self.label) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             options = list() | 
			
		
	
		
			
				
					|  |  |  |  |             for choice in self.choices: | 
			
		
	
		
			
				
					|  |  |  |  |                 options.append('"%s"' % choice) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('options=(%s)' % " ".join(options)) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('select opt in "${options[@]}"') | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('do') | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('    case $opt in') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             for choice in self.choices: | 
			
		
	
		
			
				
					|  |  |  |  |                 a.append('        "%s") %s=$opt; break;;' % (choice, self.variable_name)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             # a.append('        %s) %s=$opt;;' % ("|".join(self.choices), self.name)) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('        *) echo "invalid choice";;') | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('    esac') | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('done') | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             # a.append("read %s" % self.name) | 
			
		
	
		
			
				
					|  |  |  |  |         else: | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('echo -n "%s "' % self.label) | 
			
		
	
		
			
				
					|  |  |  |  |             a.append("read %s" % self.variable_name) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if self.default is not None: | 
			
		
	
		
			
				
					|  |  |  |  |             a.append('if [[ -z "$%s" ]]; then %s="%s"; fi;' % (self.variable_name, self.variable_name, self.default)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # a.append('echo "$%s"' % self.name) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return "\n".join(a) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class Sudo(object): | 
			
		
	
		
			
				
					|  |  |  |  |     """Helper class for defining sudo options.""" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -296,6 +555,9 @@ class Template(object): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # Get the content; e.g. parse the template. | 
			
		
	
		
			
				
					|  |  |  |  |         content = self.get_content() | 
			
		
	
		
			
				
					|  |  |  |  |         if content is None: | 
			
		
	
		
			
				
					|  |  |  |  |             lines.append("# NOT CONTENT AVAILABLE") | 
			
		
	
		
			
				
					|  |  |  |  |             return "\n".join(lines) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         # Templates that are bash scripts will fail to write because of the shebang. | 
			
		
	
		
			
				
					|  |  |  |  |         if content.startswith("#!"): | 
			
		
	
	
		
			
				
					|  |  |  | 
 |