in modules/pymol/parser.py [0:0]
def _parse(self, s, secure):
layer = self.layer[self.nest]
self.result = None
# report any uncaught errors...
# WLD: this is problematic if parse is called inside an exception...removed.
# if sys.exc_info()!=(None,None,None):
# traceback.print_exc()
# sys.exc_clear()
def parse_embed():
if s.strip() == layer.embed_sentinel:
etn = layer.embed_type
if etn == 0: # embedded data
colorprinting.parrot(" Embed: read %d lines."%(len(layer.embed_list)))
layer.embed_sentinel=None
elif etn == 1: # python block
colorprinting.parrot("PyMOL>"+s.rstrip())
py_block = ''.join(layer.embed_list)
del layer.embed_list
layer.embed_sentinel=None
self.exec_python(py_block)
elif etn == 2: # skip block
colorprinting.parrot(" Skip: skipped %d lines."%(layer.embed_line))
layer.embed_sentinel=None
else:
etn = layer.embed_type
if etn == 0: # normal embedded data
layer.embed_list.append(s.rstrip()+"\n")
elif etn == 1: # python block
el = layer.embed_line + 1
colorprinting.parrot("%5d:%s"%(el,s.rstrip()))
layer.embed_line = el
layer.embed_list.append(s.rstrip()+"\n")
elif etn == 2:
layer.embed_line = layer.embed_line + 1
p_result = 1
layer.com0 = s
try:
if layer.embed_sentinel is not None:
parse_embed()
return 1
layer.com1 = layer.com0.rstrip() # strips trailing whitespace
if len(layer.com1) > 0:
if str(layer.com1[-1]) == "\\":
# prepend leftovers
if layer.cont != '':
layer.cont = layer.cont + "\n" + layer.com1[:-1]
else:
layer.cont = layer.com1[:-1]
else:
# prepend leftovers
if layer.cont != '':
layer.com1 = layer.cont + "\n" + layer.com1
layer.cont = ''
# this routine splits up the line first based on semicolon
layer.next = parsing.split(layer.com1,';',1) + layer.next[1:]
# layer.com2 now a full non-compound command
layer.com2 = layer.next[0]
layer.input = layer.com2.split(' ',1)
lin = len(layer.input)
if lin:
layer.input[0] = layer.input[0].strip()
com = layer.input[0]
if (com[0:1]=='/'):
# explicit literal python
layer.com2 = layer.com2[1:].strip()
if len(layer.com2)>0:
self.exec_python(layer.com2, secure)
elif lin>1 and layer.input[-1:][0].split(' ',1)[0] in py_delims:
self.exec_python(layer.com2, secure)
else:
# try to find a keyword which matches
if com in self.cmd.kwhash:
amb = self.cmd.kwhash.interpret(com)
if amb == None:
com = self.cmd.kwhash[com]
elif not isinstance(amb, str):
colorprinting.warning('Error: ambiguous command: ')
amb.sort()
amb = parsing.list_to_str_list(amb)
for a in amb:
colorprinting.warning(a)
raise QuietException
com = amb
if com in self.cmd.keyword:
# here is the command and argument handling section
layer.kw = self.cmd.keyword[com]
if layer.kw[4]>=parsing.NO_CHECK:
# stricter, Python-based argument parsing
# remove line breaks (only important for Python expressions)
layer.com2=layer.com2.replace('\n','')
if layer.kw[4]>=parsing.LITERAL: # treat literally
layer.next = []
if not secure:
layer.com2=layer.com1
else:
raise SecurityException('Python expressions disallowed in this file')
if secure and (layer.kw[4]==parsing.SECURE):
layer.next = []
raise SecurityException('Command disallowed in this file')
else:
(layer.args, layer.kw_args) = \
parsing.prepare_call(
layer.kw[0],
parsing.parse_arg(layer.com2,mode=layer.kw[4],_self=self.cmd),
layer.kw[4], _self=self.cmd) # will raise exception on failure
self.result=layer.kw[0](*layer.args, **layer.kw_args)
elif layer.kw[4]==parsing.PYTHON:
# handle python keyword
layer.com2 = layer.com2.strip()
if len(layer.com2)>0:
self.exec_python(layer.com2, secure)
else:
# remove line breaks (only important for Python expressions)
layer.com2=layer.com2.replace('\n','')
# old parsing style, being phased out
if layer.kw[4]==parsing.ABORT:
return None # SCRIPT ABORT EXIT POINT
if layer.kw[4]==parsing.MOVIE: # copy literal single line, no breaks
layer.next = []
if not secure:
layer.input = layer.com1.split(' ',1)
else:
raise SecurityException('Movie commands disallowed in this file')
if len(layer.input)>1:
layer.args = parsing.split(layer.input[1],layer.kw[3])
while 1:
nArg = len(layer.args) - 1
c = 0
while c < nArg:
if ( layer.args[c].count('(')!=
layer.args[c].count(')')):
tmp=layer.args[c+1]
layer.args.remove(tmp)
layer.args[c]=layer.args[c].strip()+\
','+tmp.strip()
nArg = nArg-1
break;
c = c + 1
if c == nArg:
break;
if len(layer.args)==1 and len(layer.args[0])==0:
layer.args = []
else:
layer.args = []
if layer.kw[1]<= len(layer.args) <= layer.kw[2]:
layer.args = [a.strip() for a in layer.args]
if layer.kw[4]<parsing.RUN:
#
# this is where old-style commands are invoked
#
self.result=layer.kw[0](*layer.args)
#
elif (layer.kw[4]==parsing.EMBED):
layer.next = []
if secure or self.nest==0: # only legal on top level and p1m files
l = len(layer.args)
if l>0:
key = layer.args[0]
else:
key = self.get_default_key()
if l>1:
format = layer.args[1]
else:
format = 'pdb'
if l>2:
layer.embed_sentinel = layer.args[2]
else:
layer.embed_sentinel = "embed end"
list = []
layer.embed_dict[key] = ( format, list )
layer.embed_list = list
layer.embed_type = 0 # not a python block
else:
print('Error: embed only legal in special files (e.g. p1m)')
raise None
elif (layer.kw[4]==parsing.SKIP):
layer.next = []
arg = parsing.apply_arg(
parsing.parse_arg(layer.com2,_self=self.cmd),
('sentinel',),
{'sentinel':'skip end'})
print(arg) # ???
if len(layer.args):
if layer.args[0]=='end': # probable 'skip end' to ignore
arg = []
if len(arg):
layer.embed_sentinel = arg[0]
layer.embed_type = 2 # skip block
layer.embed_line = 0
elif (layer.kw[4]==parsing.PYTHON_BLOCK):
layer.next = []
if not secure:
arg = parsing.apply_arg(
parsing.parse_arg(layer.com2,_self=self.cmd),
('sentinel','skip'),
{'sentinel':'python end','skip':0})
layer.embed_sentinel = arg[0]
list = []
layer.embed_list = list
if arg[1]:
layer.embed_type = 2 # skip block
else:
layer.embed_type = 1 # python block
layer.embed_line = 0
else:
print('Error: Python blocks disallowed in this file.')
raise None
else:
print('Error: unknown keyword mode: '+str(layer.kw[4]))
raise QuietException
else:
print('Error: invalid arguments for %s command.' % com)
#
# non-keyword command handling
#
elif len(layer.input[0]):
if layer.input[0][0]=='@':
path = exp_path(layer.com2[1:].strip())
if path[-3:].lower()=='p1m':
nest_securely = 1
else:
nest_securely = secure
if re.search("\.py$|\.pym$",path) != None:
if self.cmd._feedback(fb_module.parser,fb_mask.warnings):
print("Warning: use 'run' instead of '@' with Python files?")
layer.script = open(path,'rU')
self.cmd._pymol.__script__ = path
self.nest=self.nest+1
self.layer[self.nest] = NestLayer()
layer = self.layer[self.nest]
layer.cont=''
layer.sc_path=path
layer.embed_sentinel=None
while 1:
layer.com0 = self.layer[self.nest-1].script.readline()
self.layer[self.nest].lineno += 1
if not layer.com0: break
inp_cmd = layer.com0
tmp_cmd = inp_cmd.strip()
if len(tmp_cmd):
if tmp_cmd[0] not in ['#','_','/']: # suppress comments, internals, python
if layer.embed_sentinel==None:
colorprinting.parrot("PyMOL>"+tmp_cmd)
elif tmp_cmd[0]=='_' and \
tmp_cmd[1:2] in [' ','']: # "_ " remove echo suppression signal
inp_cmd=inp_cmd[2:]
pp_result = self.parse(inp_cmd,nest_securely)
if pp_result==None: # RECURSION
break # abort command gets us out
elif pp_result==0: # QuietException
if self.cmd.get_setting_boolean("stop_on_exceptions"):
p_result = 0 # signal an error occurred
colorprinting.error("PyMOL: stopped on exception.")
break;
self.nest=self.nest-1
layer=self.layer[self.nest]
layer.script.close()
self.cmd._pymol.__script__ = layer.sc_path
else: # nothing found, try literal python
layer.com2 = layer.com2.strip()
if len(layer.com2)>0:
if not secure:
self.exec_python(layer.com2, fallback=True)
elif layer.input[0][0:1]!='#':
colorprinting.error('Error: unrecognized keyword: '+layer.input[0])
if (len(layer.next)>1) and p_result:
# continue parsing if no error or break has occurred
self.nest=self.nest+1
self.layer[self.nest] = NestLayer()
layer=self.layer[self.nest]
layer.com0 = self.layer[self.nest-1].next[1]
self.layer[self.nest-1].next=[]
layer.cont=''
layer.embed_sentinel=None
p_result = self.parse(layer.com0,secure) # RECURSION
self.nest=self.nest-1
layer=self.layer[self.nest]
except (QuietException, CmdException) as e:
if e.args:
colorprinting.error(e)
if self.cmd._feedback(fb_module.parser,fb_mask.blather):
print("Parser: caught " + type(e).__name__)
p_result = 0
except SecurityException as e:
colorprinting.error('Error: %s' % (e,))
p_result = None
except:
exc_type, exc_value, tb = colorprinting.print_exc(
[__file__, SCRIPT_TOPLEVEL])
p_result = 0 # notify caller that an error was encountered
if not p_result and self.cmd._pymol.invocation.options.exit_on_error:
self.cmd.quit(1)
return p_result # 0 = Exception, None = abort, 1 = ok