summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/webquiz/scripts/webquiz_util.py
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /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.py161
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'))