Loading __init__.py +17 −1 Original line number Diff line number Diff line #!/usr/bin/env python3 No newline at end of file # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. color.py +17 −1 Original line number Diff line number Diff line #!/usr/bin/env python3 # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. import sys import re Loading display.py +131 −3 Original line number Diff line number Diff line #!/usr/bin/env python3 # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. import os import sys import locale import errno import fcntl import time import textwrap import subprocess from struct import unpack, pack from termios import TIOCGWINSZ from utils.color import stringc from utils.color import BColors from utils.parsing import to_text from utils.errors import AMMSMLError from utils.singleton import Singleton from config import constants as C from utils.six import with_metaclass from utils.wrap import wrap_var b_COW_PATHS = ( Loading @@ -22,6 +44,7 @@ b_COW_PATHS = ( b"/opt/local/bin/cowsay", # MacPorts path for cowsay ) class Display(with_metaclass(Singleton, object)): def __init__(self, verbosity: int=0): Loading @@ -34,6 +57,35 @@ class Display(with_metaclass(Singleton, object)): self._warns = {} self._errors = {} self.b_cowsay = None self.noncow = C.AMMSML_COW_SELECTION self.set_cowsay_info() if self.b_cowsay: try: cmd = subprocess.Popen([self.b_cowsay, "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = cmd.communicate() self.cows_available = set([to_text(c) for c in out.split()]) if C.AMMSML_COW_WHITELIST and any(C.AMMSML_COW_WHITELIST): self.cows_available = set(C.AMNMSML_COW_WHITELIST).intersection(self.cows_available) except Exception: # could not execute cowsay for some reason self.b_cowsay = False self._set_column_width() def set_cowsay_info(self): if C.AMMSML_NOCOWS: return if C.AMMSML_COW_PATH: self.b_cowsay = C.AMMSML_COW_PATH else: for b_cow_path in b_COW_PATHS: if os.path.exists(b_cow_path): self.b_cowsay = b_cow_path def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. Loading Loading @@ -158,3 +210,79 @@ class Display(with_metaclass(Singleton, object)): star_len = 3 stars = u"*" * star_len self.display(u"\n%s %s" % (msg, stars), color=color) def error(self, msg, wrap_text=True): if wrap_text: new_msg = "\n[ERROR]: %s" % msg wrapped = textwrap.wrap(new_msg, self.columns) new_msg = "\n".join(wrapped) + "\n" else: new_msg = "ERROR! %s" % msg if new_msg not in self._errors: self.display(new_msg, color=C.COLOR_ERROR, stderr=True) self._errors[new_msg] = 1 @staticmethod def prompt(msg): prompt_string = to_text(msg, encoding=Display._output_encoding()) if sys.version_info >= (3,): # Convert back into text on python3. We do this double conversion # to get rid of characters that are illegal in the user's locale prompt_string = to_text(prompt_string) return input(prompt_string) def do_var_prompt(self, varname, private=True, prompt=None, confirm=False, default=None, unsafe=None): result = None if sys.__stdin__.isatty(): do_prompt = self.prompt if prompt and default is not None: msg = "%s [%s]: " % (prompt, default) elif prompt: msg = "%s: " % prompt else: msg = 'input for %s: ' % varname if confirm: while True: result = do_prompt(msg, private) second = do_prompt("confirm " + msg, private) if result == second: break self.display("***** VALUES ENTERED DO NOT MATCH ****") else: result = do_prompt(msg, private) else: result = None self.warning("Not prompting as we are not in interactive mode") # if result is false and default is not None if not result and default is not None: result = default # handle utf-8 chars result = to_text(result, errors='surrogate_or_strict') if unsafe: result = wrap_var(result) return result @staticmethod def _output_encoding(stderr=False): encoding = locale.getpreferredencoding() # https://bugs.python.org/issue6202 # Python2 hardcodes an obsolete value on Mac. Use MacOSX defaults # instead. if encoding in ('mac-roman',): encoding = 'utf-8' return encoding def _set_column_width(self): if os.isatty(0): tty_size = unpack('HHHH', fcntl.ioctl(0, TIOCGWINSZ, pack('HHHH', 0, 0, 0, 0)))[1] else: tty_size = 0 self.columns = max(79, tty_size - 1) No newline at end of file errors.py +17 −2 Original line number Diff line number Diff line #!/usr/bin/env python3 # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. class AMMSMLError(Exception): Loading @@ -19,4 +35,3 @@ class TemplateParsingError(AMMSMLError): class AMMSMLOptionsError(AMMSMLError): pass parseing_yaml.py +18 −0 Original line number Diff line number Diff line # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. import yaml from utils.parsing import to_text Loading Loading
__init__.py +17 −1 Original line number Diff line number Diff line #!/usr/bin/env python3 No newline at end of file # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>.
color.py +17 −1 Original line number Diff line number Diff line #!/usr/bin/env python3 # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. import sys import re Loading
display.py +131 −3 Original line number Diff line number Diff line #!/usr/bin/env python3 # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. import os import sys import locale import errno import fcntl import time import textwrap import subprocess from struct import unpack, pack from termios import TIOCGWINSZ from utils.color import stringc from utils.color import BColors from utils.parsing import to_text from utils.errors import AMMSMLError from utils.singleton import Singleton from config import constants as C from utils.six import with_metaclass from utils.wrap import wrap_var b_COW_PATHS = ( Loading @@ -22,6 +44,7 @@ b_COW_PATHS = ( b"/opt/local/bin/cowsay", # MacPorts path for cowsay ) class Display(with_metaclass(Singleton, object)): def __init__(self, verbosity: int=0): Loading @@ -34,6 +57,35 @@ class Display(with_metaclass(Singleton, object)): self._warns = {} self._errors = {} self.b_cowsay = None self.noncow = C.AMMSML_COW_SELECTION self.set_cowsay_info() if self.b_cowsay: try: cmd = subprocess.Popen([self.b_cowsay, "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out, err) = cmd.communicate() self.cows_available = set([to_text(c) for c in out.split()]) if C.AMMSML_COW_WHITELIST and any(C.AMMSML_COW_WHITELIST): self.cows_available = set(C.AMNMSML_COW_WHITELIST).intersection(self.cows_available) except Exception: # could not execute cowsay for some reason self.b_cowsay = False self._set_column_width() def set_cowsay_info(self): if C.AMMSML_NOCOWS: return if C.AMMSML_COW_PATH: self.b_cowsay = C.AMMSML_COW_PATH else: for b_cow_path in b_COW_PATHS: if os.path.exists(b_cow_path): self.b_cowsay = b_cow_path def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. Loading Loading @@ -158,3 +210,79 @@ class Display(with_metaclass(Singleton, object)): star_len = 3 stars = u"*" * star_len self.display(u"\n%s %s" % (msg, stars), color=color) def error(self, msg, wrap_text=True): if wrap_text: new_msg = "\n[ERROR]: %s" % msg wrapped = textwrap.wrap(new_msg, self.columns) new_msg = "\n".join(wrapped) + "\n" else: new_msg = "ERROR! %s" % msg if new_msg not in self._errors: self.display(new_msg, color=C.COLOR_ERROR, stderr=True) self._errors[new_msg] = 1 @staticmethod def prompt(msg): prompt_string = to_text(msg, encoding=Display._output_encoding()) if sys.version_info >= (3,): # Convert back into text on python3. We do this double conversion # to get rid of characters that are illegal in the user's locale prompt_string = to_text(prompt_string) return input(prompt_string) def do_var_prompt(self, varname, private=True, prompt=None, confirm=False, default=None, unsafe=None): result = None if sys.__stdin__.isatty(): do_prompt = self.prompt if prompt and default is not None: msg = "%s [%s]: " % (prompt, default) elif prompt: msg = "%s: " % prompt else: msg = 'input for %s: ' % varname if confirm: while True: result = do_prompt(msg, private) second = do_prompt("confirm " + msg, private) if result == second: break self.display("***** VALUES ENTERED DO NOT MATCH ****") else: result = do_prompt(msg, private) else: result = None self.warning("Not prompting as we are not in interactive mode") # if result is false and default is not None if not result and default is not None: result = default # handle utf-8 chars result = to_text(result, errors='surrogate_or_strict') if unsafe: result = wrap_var(result) return result @staticmethod def _output_encoding(stderr=False): encoding = locale.getpreferredencoding() # https://bugs.python.org/issue6202 # Python2 hardcodes an obsolete value on Mac. Use MacOSX defaults # instead. if encoding in ('mac-roman',): encoding = 'utf-8' return encoding def _set_column_width(self): if os.isatty(0): tty_size = unpack('HHHH', fcntl.ioctl(0, TIOCGWINSZ, pack('HHHH', 0, 0, 0, 0)))[1] else: tty_size = 0 self.columns = max(79, tty_size - 1) No newline at end of file
errors.py +17 −2 Original line number Diff line number Diff line #!/usr/bin/env python3 # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. class AMMSMLError(Exception): Loading @@ -19,4 +35,3 @@ class TemplateParsingError(AMMSMLError): class AMMSMLOptionsError(AMMSMLError): pass
parseing_yaml.py +18 −0 Original line number Diff line number Diff line # GNU Lesser General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/lgpl-3.0.txt) # (c) 2019, Christof Schulze <christof.schulze@fau.de> # # This file is part of Ammsml # # Ammsml is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ammsml is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with Ammsml. If not, see <http://www.gnu.org/licenses/>. import yaml from utils.parsing import to_text Loading