"""
Interactive shell around the sqmediumlite network interface.
Invoked by the main method of the network front-end module.
"""
import sys, os, time
import sqmedium as sqlite
from sqmedium._shellbase import Shell as baseShell, _fmt_sql_value
class Shell(baseShell):
def __init__ (self, **kwargs):
sqlite.SQLError = sqlite.OperationalError
sqlite.apswversion = self.apswversion
sqlite.sqlitelibversion = self.sqlitelibversion
sqlite.complete = self.complete_statement
sqlite.format_sql_value = _fmt_sql_value
baseShell.__init__ (self, **kwargs)
def _ensure_db(self):
"The database isn't opened until first use. This function ensures it is now open."
if not self._db:
if self.dbfilename is None:
self.dbfilename=""
self._db=sqlite.Connection(self.dbfilename, isolation_level=None)
return self._db
db=property(_ensure_db, baseShell._set_db, None, "The current :class:`Connection`")
def complete_sql(self, line, token, beg, end):
"""Provide some completions for SQL
:param line: The current complete input line
:param token: The word readline is looking for matches
:param beg: Integer offset of token in line
:param end: Integer end of token in line
:return: A list of completions, or an empty list if none
"""
try:
return baseShell.complete_sql(self, line, token, beg, end)
except sqlite.ServerNotUp:
return []
def process_complete_line(self, command):
"""Given some text will call the appropriate method to process
it (eg :meth:`process_sql` or :meth:`process_command`)"""
try:
return baseShell.process_complete_line(self, command)
except sqlite.ServerNotUp as e:
self._db = None
raise
def process_sql(self, sql, bindings=None, internal=False, summary=None):
"""Processes SQL text consisting of one or more statements
:param sql: SQL to execute
:param bindings: bindings for the *sql*
:param internal: If True then this is an internal execution
(eg the .tables or .database command). When executing
internal sql timings are not shown nor is the SQL echoed.
"""
if bindings is None:
bindings = ()
return baseShell.process_sql(self, sql, bindings, internal, summary)
def handle_interrupt(self):
"""Deal with keyboard interrupt (typically Control-C). It
will :meth:`~Connection.interrupt` the database and print"^C" if interactive."""
try:
baseShell.handle_interrupt(self)
except:
self.write(self.stderr, self.colour.error_)
raise
def command_sleep (self, args):
"""sleep MS: sleep so many miliseconds"""
if len (args) != 1: raise self.Error("sleep takes 1 parameter")
time.sleep (.001 * int (args [0]))
def command_start (self, args):
"""start: start back-end for sqmediumlite """
if args: raise self.Error("start takes no parameters")
sqlite.start ()
def command_stop (self, args):
"""stop: stop back-end for sqmediumlite """
if args: raise self.Error("stop takes no parameters")
sqlite.stop ()
def command_status (self, args):
"""status: print status of sqmediumlite back-end"""
if args: raise self.Error("status takes no parameters")
try:
for i in self.db._do ("modstatus").items():
self.write(self.stderr, "%s: %s\n" % i)
except sqlite.ServerNotUp:
self.write(self.stderr, "sqmediumlite back-end process does not exist\n")
def command_restart (self, args):
"""restart: restart back-end for sqmediumlite """
if args: raise self.Error("restart takes no parameters")
if sqlite.status ():
sqlite.stop ()
sqlite.start ()
def command_service (self, args):
"""service install|start|stop|remove: service for sqmediumlite back-end """
sqlite.service (*args)
def command_dir (self, args):
"""dir [PATH]: list database files """
if len (args) > 1: raise self.Error("sleep takes at most 1 parameter")
for i in self.db._do ("moddo", "dir", *args):
self.write(self.stderr, "%s\n" % i)
def sqlitelibversion (self):
try:
return self.db.sqlite_version
except sqlite.ServerNotUp:
return "not available"
def apswversion (self):
try:
versions = self.db.apsw_version, self.db.backend_version
except sqlite.ServerNotUp:
versions = "version not available", sqlite.version
return "%s, sqmediumlite %s" % versions
def complete_statement (self, sql):
try:
return self.db.complete_statement (sql)
except sqlite.ServerNotUp:
return True
def main():
"""
Call this to run the interactive shell. It automatically passes
in sys.argv[1:] and exits Python when done.
"""
try:
s=Shell(args=sys.argv[1:])
if len (sys.argv) <= 2 or sys.argv [-1].startswith ('-'):
s.cmdloop()
except:
v=sys.exc_info()[1]
if getattr(v, "_handle_exception_saw_this", False):
pass
else:
import traceback; traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main ()