Package gavo :: Package user :: Module cli
[frames] | no frames]

Source Code for Module gavo.user.cli

  1  """ 
  2  The main entry point to CLI usage of GAVO code. 
  3  """ 
  4   
  5  #c Copyright 2008-2019, the GAVO project 
  6  #c 
  7  #c This program is free software, covered by the GNU GPL.  See the 
  8  #c COPYING file in the source distribution. 
  9   
 10   
 11  from __future__ import print_function 
 12   
 13  # The idea here is that you expose a CLI functionality by giving, as 
 14  # strings, the module and function to call. 
 15  # 
 16  # We also give a little startup note if we're running on a tty. 
 17  # While we do this, we import api; that should take care of most 
 18  # of the real startup time. 
 19   
 20  import os 
 21  import sys 
 22  import textwrap 
 23  import traceback 
 24   
 25  # this (and its companion in api.py) works around a race condition in 
 26  # Debian stretch's python-cryptography module.  Remove about 2021. 
 27  from cryptography.hazmat.bindings.openssl.binding import Binding #noflake: see above 
 28   
 29  from gavo.user import common 
 30   
 31   
 32  functions = [ 
 33          ("admin", ("user.admin", "main")), 
 34          ("adql", ("protocols.adqlglue", "localquery")), 
 35          ("config", ("base.config", "main")), 
 36          ("drop", ("user.dropping", "dropRD")), 
 37          ("dlrun", ("protocols.dlasync", "main")), 
 38          ("dump", ("rsc.dumping", "main")), 
 39          ("gendoc", ("user.docgen", "main")), 
 40          ("import", ("user.importing", "main")), 
 41          ("info", ("user.info", "main")), 
 42          ("limits", ("user.rdmanipulator", "main")), 
 43          ("mkboost", ("grammars.directgrammar", "main")), 
 44          ("mkrd", ("user.mkrd", "main")), 
 45          ("publish", ("registry.publication", "main")), 
 46          ("purge", ("user.dropping", "dropTable")), 
 47          ("raise", ("user.errhandle", "bailOut")), 
 48          ("serve", ("user.serve", "main")), 
 49          ("start", ("user.mkrd", "start")), 
 50          ("stc", ("stc.cli", "main")), 
 51          ("show", ("user.show", "main")), 
 52          ("test", ("rscdef.regtest", "main")), 
 53          ("taprun", ("protocols.taprunner", "main")), 
 54          ("totesturl", ("rscdef.regtest", "urlToURL")), 
 55          ("validate", ("user.validation", "main")), 
 56          ("upgrade", ("user.upgrade", "main")), 
 57          ("uwsrun", ("protocols.useruws", "main")), 
 58  # init is special cased, but we want it in here for help generation 
 59          ("init", ("initdachs.info", "main")), 
 60  ] 
 61   
 62   
63 -def _enablePDB():
64 # This can't be a callback to the --enable-pdb option since it needs 65 # errhandle, and we only want to import this after the command line 66 # is parsed 67 import pdb 68 def enterPdb(type, value, tb): 69 traceback.print_exception(type, value, tb) 70 pdb.pm()
71 sys.excepthook = enterPdb 72 from gavo.base import events 73 events.PDB_ENABLED = True 74 75
76 -def _enableDebug(*args):
77 from gavo import base 78 base.DEBUG = True
79 80
81 -def _printVersion(*args):
82 from gavo import base 83 from gavo.user import upgrade 84 print("Software (%s) Schema (%s/%s)"%( 85 base.getVersion(), 86 upgrade.CURRENT_SCHEMAVERSION, 87 upgrade.getDBSchemaVersion())) 88 sys.exit(0)
89 90
91 -def _parseCLArgs():
92 """parses the command line and returns instructions on how to go on. 93 94 As a side effect, sys.argv is manipulated such that the program 95 called thinks it was execd in the first place. 96 """ 97 from optparse import OptionParser 98 sels = [n for n,x in functions] 99 sels.sort() 100 parser = OptionParser(usage="%prog {<global option>} <func>" 101 " {<func option>} {<func argument>}\n"+ 102 textwrap.fill("<func> is a unique prefix into {%s}"%(", ".join(sels)), 103 initial_indent='', subsequent_indent=' '), 104 description="Try %prog <func> --help for function-specific help") 105 parser.disable_interspersed_args() 106 parser.add_option("--traceback", help="print a traceback on all errors.", 107 action="store_true", dest="alwaysTracebacks") 108 parser.add_option("--hints", help="if there are hints on an error, display" 109 " them", action="store_true", dest="showHints") 110 parser.add_option("--enable-pdb", help="run pdb on all errors.", 111 action="store_true", dest="enablePDB") 112 parser.add_option("--disable-spew", help='Ignored.', 113 action="store_true", dest="disableSpew") 114 parser.add_option("--profile-to", metavar="PROFILEPATH", 115 help="enable profiling and write a profile to PROFILEPATH", 116 action="store", dest="profilePath", default=None) 117 parser.add_option("--suppress-log", help="Do not log exceptions and such" 118 " to the dachs-specific log files", action="store_true", 119 dest="suppressLog") 120 parser.add_option("--debug", help="Produce debug info as appropirate.", 121 action="callback", callback=_enableDebug) 122 parser.add_option("--version", help="Write software version to stdout" 123 " and exit", action="callback", callback=_printVersion) 124 parser.add_option("-U", "--ui", help="use UI to show what is going on;" 125 " try --ui=help to see available interfaces.", 126 dest="uiName", action="store", type="str", default="module-dependent", 127 metavar="UI") 128 129 opts, args = parser.parse_args() 130 if len(args)<1: 131 parser.print_help(file=sys.stderr) 132 sys.exit(2) 133 134 module, funcName = common.getMatchingFunction(args[0], functions, parser) 135 parser.destroy() 136 args[0] = "dachs "+args[0] 137 sys.argv = args 138 return opts, module, funcName
139 140
141 -def main():
142 143 # we want to preserve group-writability in all our operations; hence 144 # this prominent place for overriding a user decision... 145 os.umask(002) 146 147 if len(sys.argv)>1 and sys.argv[1]=="init": 148 # Special case: initial setup, no api working yet 149 del sys.argv[1] 150 from gavo.user import initdachs 151 sys.exit(initdachs.main()) 152 153 opts, module, funcName = _parseCLArgs() 154 from gavo import base 155 from gavo import utils 156 from gavo.user import errhandle 157 from gavo.user import plainui 158 from gavo.user import useless 159 160 interfaces = { 161 "deluge": useless.DelugeUI, 162 "null": useless.NullUI, 163 "stingy": plainui.StingyPlainUI, 164 "semistingy": plainui.SemiStingyPlainUI, 165 "plain": plainui.PlainUI, 166 } 167 168 if not (opts.suppressLog or os.environ.get("GAVO_LOG")=="no"): 169 from gavo.user import logui 170 logui.LoggingUI(base.ui) 171 172 if opts.uiName=="module-dependent": 173 opts.uiName = {"registry.publication": "semistingy", 174 "user.dropping": "stingy", 175 "user.serve": "null", 176 "user.validation": "null", 177 }.get(module, "plain") 178 if opts.uiName not in interfaces: 179 raise base.ReportableError("UI %s does not exist. Choose one of" 180 " %s"%(opts.uiName, ", ".join(interfaces))) 181 interfaces[opts.uiName](base.ui) 182 183 if opts.enablePDB: 184 _enablePDB() 185 funcToRun = utils.loadInternalObject(module, funcName) 186 187 if opts.profilePath: 188 import cProfile 189 cProfile.runctx("funcToRun()", globals(), locals(), opts.profilePath) 190 return 191 192 try: 193 funcToRun() 194 except Exception: 195 if opts.alwaysTracebacks: 196 traceback.print_exc() 197 sys.exit(errhandle.raiseAndCatch(opts))
198 199 200 if __name__=="__main__": 201 main() 202