Package jazzparser :: Package shell :: Module shell
[hide private]
[frames] | no frames]

Source Code for Module jazzparser.shell.shell

  1  """Jazz Parser interactive shell for examining the output of the parser. 
  2   
  3  """ 
  4  """ 
  5  ============================== License ======================================== 
  6   Copyright (C) 2008, 2010-12 University of Edinburgh, Mark Granroth-Wilding 
  7    
  8   This file is part of The Jazz Parser. 
  9    
 10   The Jazz Parser is free software: you can redistribute it and/or modify 
 11   it under the terms of the GNU General Public License as published by 
 12   the Free Software Foundation, either version 3 of the License, or 
 13   (at your option) any later version. 
 14    
 15   The Jazz Parser is distributed in the hope that it will be useful, 
 16   but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18   GNU General Public License for more details. 
 19    
 20   You should have received a copy of the GNU General Public License 
 21   along with The Jazz Parser.  If not, see <http://www.gnu.org/licenses/>. 
 22   
 23  ============================ End license ====================================== 
 24   
 25  """ 
 26  __author__ = "Mark Granroth-Wilding <mark.granroth-wilding@ed.ac.uk>"  
 27   
 28  import sys, traceback, logging, readline, os 
 29  from jazzparser import settings 
 30  from jazzparser.formalisms.loader import get_default_formalism 
 31  from . import tools 
 32  from . import gstools 
 33   
 34  # Get the logger from the logging system 
 35  logger = logging.getLogger("main_logger") 
 36   
 37  CORE_TOOLS = [  
 38      tools.HelpTool(), 
 39      tools.DerivationTraceTool(), 
 40      tools.DerivationTraceExplorerTool(), 
 41      tools.AtomsOnlyTool(), 
 42      tools.ResultListTool(), 
 43      tools.RuleApplicationTool(), 
 44      tools.LogLevelTool(), 
 45      tools.PythonTool(), 
 46      tools.SaveStateTool(), 
 47      tools.TonalSpaceCoordinatesTool(), 
 48      tools.LoadResultsTool(), 
 49      gstools.LoadGoldStandardTool(), 
 50      gstools.MarkCorrectTool(), 
 51  ] 
52 53 -def interactive_shell(results,options,tagger,parser,formalism,env,seq_id=None,input_data=None):
54 """ 55 Use an interactive shell to display and give detailed access to 56 the given results, produced by the parser. 57 58 """ 59 tool_sources = formalism.shell_tools + \ 60 parser.shell_tools + \ 61 tagger.shell_tools 62 # Get commands for the input type 63 if input_data is not None: 64 # Add all tools for this data type 65 tool_sources.extend(input_data.SHELL_TOOLS) 66 67 state = ShellState(results, options, tagger, parser, formalism, env, 68 seq_id=seq_id, input_data=input_data) 69 # Pass over to the shell function to run the actual shell 70 shell(state, tools=tool_sources)
71
72 -def restore_shell(name, tools=[]):
73 """ 74 Restores an interactive shell session from a saved state. Such a state 75 is stored using the 'save' command from a shell session (e.g. after 76 parsing). 77 78 """ 79 state = ShellState.load(name) 80 81 tool_sources = [] 82 # Load tools for the formalism, parser and tagger if they're available 83 if state.formalism is not None: 84 tool_sources.extend(state.formalism.shell_tools) 85 if state.parser is not None: 86 tool_sources.extend(state.parser.shell_tools) 87 if state.tagger is not None: 88 tool_sources.extend(state.tagger.shell_tools) 89 if state.input_data is not None: 90 tool_sources.extend(state.input_data.SHELL_TOOLS) 91 92 print "Restoring shell state from saved session '%s'\n" % name 93 # Pass over to the main shell function 94 shell(state, tools=tool_sources+tools)
95
96 -def empty_shell(tools=[]):
97 """ 98 Starts up the interactive shell with no shell state. 99 100 """ 101 state = ShellState() 102 103 tool_sources = [] 104 # Load tools for the formalism, parser and tagger if they're available 105 if state.formalism is not None: 106 tool_sources.extend(state.formalism.shell_tools) 107 108 # Pass over to the main shell function 109 shell(state, tools=tool_sources+tools)
110
111 -def shell(state, tools=[]):
112 """ 113 Starts up the shell with a given L{ShellState}. This is called by 114 L{interactive_shell}, as used by the parser, and also by L{restore_shell}. 115 116 """ 117 # Load the shell history if possible 118 try: 119 readline.read_history_file(settings.SHELL_HISTORY_FILE) 120 except IOError: 121 # No history file found. No problem 122 pass 123 124 # We should have received a list of tools and we add to this the standard ones 125 tool_sources = CORE_TOOLS + tools 126 # Build the list of available commands 127 tools = {} 128 all_tools = [] 129 for tool in tool_sources: 130 for cmd in tool.commands: 131 if cmd in tools: 132 raise ShellError, "The command '%s' provided by '%s' is already "\ 133 "provided by '%s'" % (cmd, tools[cmd].name, tool.name) 134 tools[cmd] = tool 135 all_tools.append(tool) 136 state.tools = tools 137 state.all_tools = all_tools 138 139 # Display the shell intro 140 print "<<<< Jazz Parser interactive shell >>>>" 141 print "Type 'help' for command list" 142 143 input = "" 144 while input != "quit": 145 sys.stdout.flush() 146 try: 147 input = raw_input(">> ") 148 except EOFError: 149 print 150 break 151 152 if input: 153 try: 154 # Pull out the command 155 input = input.rstrip("\n").strip() 156 command = input.split()[0] 157 # A special command 158 if command == "q" or command == "quit": 159 break 160 161 # Get the args and try finding a tool for this command 162 tokens = input.split()[1:] 163 if command not in tools: 164 raise ShellError, "Unknown command: %s. Use 'help' for a list of available commands." % command 165 else: 166 tool = tools[command] 167 168 # Look for args that are actually options 169 args = [] 170 options = [] 171 for token in tokens: 172 if "=" in token: 173 # This must be an option 174 opt,__,val = token.partition("=") 175 if len(opt) == 0 or len(val) == 0: 176 raise ShellError, "Options must be given in "\ 177 "the form OPT=VALUE. Could not parse %s"\ 178 % token 179 options.append(token) 180 else: 181 # Otherwise, we just treat it as an arg 182 args.append(token) 183 184 tool.process_option_list(options) 185 tool.run(args, state) 186 187 except ShellError, msg: 188 # We raised an error because something in the input was bad 189 print msg 190 except: 191 # Any other error: just output it and go on 192 traceback.print_exc(file=sys.stderr) 193 # Write the history out to a file 194 readline.write_history_file(settings.SHELL_HISTORY_FILE) 195 print "Bye!"
196
197 -class ShellState(object):
198 """ 199 Class to wrap up the various bits of state that need to be stored 200 in the shell and that may be manipulated by tools. 201 """
202 - def __init__(self, results=[], options=None, tagger=None, parser=None, 203 formalism=None, env=None, seq_id=None, input_data=None):
204 self.results = results 205 self.options = options 206 self.parser = parser 207 self.env = env 208 self.seq_id = seq_id 209 self.input_data = input_data 210 self.tagger = tagger 211 self.data = {} 212 213 if formalism is None: 214 # Use the default formalism 215 self.formalism = get_default_formalism() 216 else: 217 self.formalism = formalism 218 219 self.tools = {} 220 self.all_tools = []
221
222 - def get_data(self, name, help_msg=""):
223 """ 224 Get previously loaded data, or raise a ShellError saying it's not 225 been loaded. 226 227 """ 228 if name in self.data: 229 return self.data[name] 230 else: 231 # Data hasn't been loaded 232 # Display an error and any additional help info given by requester 233 raise ShellError, "Data set '%s' has not been loaded. %s" % \ 234 (name, help_msg)
235
236 - def save(self, name):
237 """ 238 Pickles the shell state and stores it to a file. 239 240 """ 241 import cPickle as pickle 242 243 filename = os.path.join(settings.SHELL_STATE_DIR, "%s.shst" % name) 244 outfile = open(filename, "wb") 245 # Only include certain bits of the state: not everything is picklable 246 data = { 247 'results' : self.results, 248 'options' : self.options, 249 'tools' : self.tools, 250 'all_tools' : self.all_tools, 251 'seq_id' : self.seq_id, 252 'input_data' : self.input_data, 253 'data' : self.data, 254 'formalism' : self.formalism, 255 } 256 try: 257 # Pickle the object 258 pickle.dump(data, outfile, protocol=-1) 259 finally: 260 outfile.close()
261 262 @staticmethod
263 - def load(name):
264 """ 265 Loads a pickled state representation. 266 267 """ 268 import cPickle as pickle 269 270 filename = os.path.join(settings.SHELL_STATE_DIR, "%s.shst" % name) 271 # Check this state has been saved 272 if not os.path.exists(filename): 273 raise ShellRestoreError, "saved shell state '%s' does not exist" % \ 274 name 275 infile = open(filename, "rb") 276 277 try: 278 # Unpickle the data 279 data = pickle.load(infile) 280 finally: 281 infile.close() 282 283 # Create a shell state from this data 284 return ShellState( 285 results = data['results'], 286 options = data['options'], 287 formalism = data['formalism'], 288 seq_id = data['seq_id'], 289 input_data = data['input_data'])
290 291 @staticmethod
292 - def list():
293 """ 294 List the names of stored shell sessions. 295 296 """ 297 files = os.listdir(settings.SHELL_STATE_DIR) 298 files = [filename.rpartition(".") for filename in files] 299 # Only include files with the right extension 300 names = [name for (name,__,ext) in files if ext == "shst"] 301 return names
302 303 @staticmethod
304 - def remove(name):
305 """ 306 Remove the named saved session. 307 308 """ 309 filename = os.path.join(settings.SHELL_STATE_DIR, "%s.shst" % name) 310 if not os.path.exists(filename): 311 raise ValueError, "couldn't not delete shell state '%s': it "\ 312 "doesn't exist" % name 313 os.remove(filename)
314
315 -class ShellError(Exception):
316 pass
317
318 -class ShellRestoreError(Exception):
319 pass
320