diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/webquiz/scripts/webquiz_util.py |
Initial commit
Diffstat (limited to 'macros/latex/contrib/webquiz/scripts/webquiz_util.py')
-rw-r--r-- | macros/latex/contrib/webquiz/scripts/webquiz_util.py | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/macros/latex/contrib/webquiz/scripts/webquiz_util.py b/macros/latex/contrib/webquiz/scripts/webquiz_util.py new file mode 100644 index 0000000000..ea2e6e7b17 --- /dev/null +++ b/macros/latex/contrib/webquiz/scripts/webquiz_util.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +r''' +------------------------------------------------------------------------------ + webquiz_util | utilty functions +------------------------------------------------------------------------------ + Copyright (C) Andrew Mathas, University of Sydney + + Distributed under the terms of the GNU General Public License (GPL) + http://www.gnu.org/licenses/ + + This file is part of the WebQuiz system. + + <Andrew.Mathas@sydney.edu.au> +------------------------------------------------------------------------------ +''' + +import os +import subprocess +import shutil +import stat +import sys +import traceback + +# --------------------------------------------------------------------------------------- +# Return the full path for a file in the webquiz directory +webquiz_file = lambda file: os.path.join(os.path.dirname(os.path.realpath(__file__)), file) + +def shell_command(cmd): + r''' + Short-cut for shell commands + ''' + return subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode('ascii').strip() + +def kpsewhich(search): + r''' + Short-cut to access kpsewhich output. + + usage: kpsewhich('-var-value=TEXMFLOCAL') + ''' + return subprocess.check_output('kpsewhich ' + search, shell=True).decode('ascii').strip() + +# --------------------------------------------------------------------------------------- +class MetaData(dict): + r""" + A dummy class for reading, accessing and storing key-value pairs from + a file. Any internal spaces in the key name are replaced with underscores + and lines without a key-value pair are ignored. + + The key-value pairs are available as both attributes and items + + Usage: MetaData(filename) or MetaData(filename, key-value pairs) + """ + + def __init__(self, filename, **args): + dict.__init__(self) + # add attributes from **args + for key in args: + setattr(self, key, args[key]) + with open(filename, 'r') as meta: + for line in meta: + if '=' in line: + key, val = line.strip().split('=') + if key.strip() != '': + self.__setitem__(key.strip().lower().replace(' ', '_'), + val.strip()) + setattr(self, + key.strip().lower().replace(' ', '_'), + val.strip()) + + +################################################################################# +def webquiz_debug(debugging, *arg): + if debugging: + sys.stderr.write(' '.join('{}'.format(a) for a in arg)+'\n') + + +################################################################################# +def webquiz_error(debugging, msg, err=None): + r''' + Consistent handling of errors in magthquiz: print the message `msg` and + exist with error code `err.errno` if it is available.abs + ''' + print('{dash}WebQuiz error:\n {msg}\n{dash}'.format( + msg=msg, dash='-'*40+'\n') + ) + + if err is not None: + trace = traceback.extract_tb(sys.exc_info()[2]) + filename, lineno, fn, text = trace[-1] + print('File: {}, line number: {}\nError {} in {}: {}'.format( + filename, lineno, err, fn, text)) + + if debugging and err is not None: + raise + + if hasattr(err, 'errno'): + sys.exit(err.errno) + + sys.exit(1) + + +############################################################################### +def copytree(src, dst, symlinks=False, ignore=None): + r''' Recursively copy directory tree, fixing shutil.copytree + from https://stackoverflow.com/questions/1868714 + ''' + if not os.path.exists(dst): + os.makedirs(dst) + shutil.copystat(src, dst) + lst = os.listdir(src) + if ignore: + excl = ignore(src, lst) + lst = [x for x in lst if x not in excl] + for item in lst: + s = os.path.join(src, item) + d = os.path.join(dst, item) + if symlinks and os.path.islink(s): + if os.path.lexists(d): + os.remove(d) + os.symlink(os.readlink(s), d) + try: + st = os.lstat(s) + mode = stat.S_IMODE(st.st_mode) + os.lchmod(d, mode) + except OSError: + pass # lchmod not available + elif os.path.isdir(s): + copytree(s, d, symlinks, ignore) + else: + shutil.copy2(s, d) + +############################################################################### +## shortcuts for running commands +environ = os.environ.copy() + +def run(cmd, shell=False): + r''' + Run commands with output to stdout and errors to stderr + ''' + if shell: + subprocess.call(cmd, env=environ, shell=True) + else: + subprocess.call(cmd.split(), env=environ) + +def quiet_run(cmd, shell=False): + r''' + Run commands with ignoring and sending errors to stderr + ''' + if shell: + subprocess.call(cmd, env=environ, stdout=open(os.devnull, 'wb'), shell=True) + else: + subprocess.call(cmd.split(), env=environ, stdout=open(os.devnull, 'wb')) + +def silent_run(cmd, shell=False): + r''' + Run commands ignoring all output and errors + ''' + if shell: + subprocess.call(cmd, env=environ, stdout=open(os.devnull, 'wb'), stderr=open(os.devnull, 'wb'), shell=True) + else: + subprocess.call(cmd.split(), env=environ, stdout=open(os.devnull, 'wb'), stderr=open(os.devnull, 'wb')) |