This is a read-only mirror of pymolwiki.org
Difference between revisions of "Pml2py"
Jump to navigation
Jump to search
(created) |
m (1 revision) |
||
| (6 intermediate revisions by 2 users not shown) | |||
| Line 4: | Line 4: | ||
<source lang="python"> | <source lang="python"> | ||
| + | from __future__ import print_function | ||
| + | |||
import sys | import sys | ||
| − | from pymol import cmd | + | from pymol import cmd, parsing |
def pml2py(filename, out=sys.stdout): | def pml2py(filename, out=sys.stdout): | ||
| Line 16: | Line 18: | ||
pml2py infile [, outfile] | pml2py infile [, outfile] | ||
| − | |||
| − | |||
| − | |||
| − | |||
''' | ''' | ||
def quote(args): | def quote(args): | ||
| + | args = iter(args) | ||
for arg in args: | for arg in args: | ||
if '=' not in arg: | if '=' not in arg: | ||
| − | + | prefix = '' | |
else: | else: | ||
| − | + | prefix, arg = arg.split('=', 1) | |
| − | + | prefix += '=' | |
| + | arg = arg.lstrip() | ||
| + | yield prefix + repr(arg) | ||
| + | |||
| + | class stackiter: | ||
| + | def __init__(self, collection): | ||
| + | self.iterator = iter(collection) | ||
| + | self.stack = [] | ||
| + | def __iter__(self): | ||
| + | return self | ||
| + | def next(self): | ||
| + | if len(self.stack): | ||
| + | return self.stack.pop() | ||
| + | return next(self.iterator) | ||
| + | __next__ = next | ||
| + | def push(self, v): | ||
| + | self.stack.append(v) | ||
| + | |||
| + | basestring = (bytes, unicode) if (bytes is str) else (bytes, str) | ||
if isinstance(out, basestring): | if isinstance(out, basestring): | ||
out = open(out, 'w') | out = open(out, 'w') | ||
| − | print | + | |
| + | print(''' | ||
# automatically converted from "%s" | # automatically converted from "%s" | ||
import pymol | import pymol | ||
from pymol import * | from pymol import * | ||
| − | ''' % (filename) | + | ''' % (filename), file=out) |
| − | handle = | + | |
| + | handle = stackiter(open(filename, 'rU')) | ||
for line in handle: | for line in handle: | ||
while line.endswith('\\\n'): | while line.endswith('\\\n'): | ||
| − | line = line[:-2] + | + | line = line[:-2] + next(handle) |
a = line.split(None, 1) | a = line.split(None, 1) | ||
| + | if len(a) > 1 and a[0] == '_': | ||
| + | line = a[1] | ||
| + | a = line.split(None, 1) | ||
| + | |||
try: | try: | ||
name = a[0] | name = a[0] | ||
| Line 47: | Line 70: | ||
raise | raise | ||
name = cmd.kwhash.shortcut.get(name, name) | name = cmd.kwhash.shortcut.get(name, name) | ||
| − | + | kw = cmd.keyword[name] | |
| − | + | assert kw[4] != parsing.PYTHON | |
| + | func = kw[0] | ||
except: | except: | ||
out.write(line) | out.write(line) | ||
| + | continue | ||
| + | |||
| + | # PyMOL stuff without named python function | ||
| + | if func.__name__ == '<lambda>' or name.startswith('@'): | ||
| + | print('cmd.do(%s)' % (repr(line.strip())), file=out) | ||
continue | continue | ||
| − | if | + | # code blocks |
| − | + | if name == 'python': | |
| + | for line in handle: | ||
| + | if line.split() == ['python', 'end']: | ||
| + | break | ||
| + | out.write(line) | ||
continue | continue | ||
| − | + | if name == 'skip': | |
| − | + | for line in handle: | |
| − | if name == ' | + | if line.split() == ['skip', 'end']: |
| − | + | break | |
continue | continue | ||
| + | # split args | ||
| + | tok = ',' | ||
| + | if kw[4] == parsing.MOVIE: | ||
| + | tok = kw[3] | ||
| + | split_mx = 1 | ||
| + | else: | ||
| + | split_mx = kw[4] - parsing.LITERAL | ||
if len(a) > 1: | if len(a) > 1: | ||
| − | args = [i.strip() for i in a[1] | + | a[1] = parsing.split(a[1], '#', 1)[0] # strip of comment |
| + | if split_mx < 0: | ||
| + | # strip of additional commands | ||
| + | a[1:] = parsing.split(a[1], ';', 1) | ||
| + | if len(a) > 2: | ||
| + | handle.push(a[2]) | ||
| + | if split_mx == 0: | ||
| + | args = [a[1]] | ||
| + | else: | ||
| + | args = [i.strip() for i in parsing.split(a[1], tok, max(0, split_mx))] | ||
else: | else: | ||
args = [] | args = [] | ||
| − | if | + | # old syntax: set property=value |
| − | for | + | if kw[4] == parsing.LEGACY and '=' in args[0]: |
| − | + | args = [i.strip() for i in args[0].split('=', 1)] + args[1:] | |
| − | + | ||
| − | + | # register alias | |
| − | + | if name == 'alias': | |
| + | cmd.alias(*args) | ||
| + | |||
| + | # use 'cmd' module if possible | ||
| + | try: | ||
| + | test = getattr(cmd, func.__name__) | ||
| + | assert func == test | ||
| + | module = 'cmd' | ||
| + | except: | ||
| + | module = func.__module__ | ||
| − | print | + | print('%s.%s(%s)' % (module, func.__name__, ', '.join(quote(args))), file=out) |
cmd.extend('pml2py', pml2py) | cmd.extend('pml2py', pml2py) | ||
# vi:expandtab:smarttab | # vi:expandtab:smarttab | ||
| + | |||
</source> | </source> | ||
| + | |||
| + | [[Category:Script_Library]] | ||
| + | [[Category:System_Scripts]] | ||
Latest revision as of 04:30, 3 March 2020
This script converts a pml script to a python script.
See pymol-users mailing list (Subject: Convert pml script to Pymol Python script, Fri, 8 Apr 2011).
from __future__ import print_function
import sys
from pymol import cmd, parsing
def pml2py(filename, out=sys.stdout):
'''
DESCRIPTION
Convert a pml script to python syntax.
USAGE
pml2py infile [, outfile]
'''
def quote(args):
args = iter(args)
for arg in args:
if '=' not in arg:
prefix = ''
else:
prefix, arg = arg.split('=', 1)
prefix += '='
arg = arg.lstrip()
yield prefix + repr(arg)
class stackiter:
def __init__(self, collection):
self.iterator = iter(collection)
self.stack = []
def __iter__(self):
return self
def next(self):
if len(self.stack):
return self.stack.pop()
return next(self.iterator)
__next__ = next
def push(self, v):
self.stack.append(v)
basestring = (bytes, unicode) if (bytes is str) else (bytes, str)
if isinstance(out, basestring):
out = open(out, 'w')
print('''
# automatically converted from "%s"
import pymol
from pymol import *
''' % (filename), file=out)
handle = stackiter(open(filename, 'rU'))
for line in handle:
while line.endswith('\\\n'):
line = line[:-2] + next(handle)
a = line.split(None, 1)
if len(a) > 1 and a[0] == '_':
line = a[1]
a = line.split(None, 1)
try:
name = a[0]
if name.startswith('/'):
line = line.lstrip()[1:]
raise
name = cmd.kwhash.shortcut.get(name, name)
kw = cmd.keyword[name]
assert kw[4] != parsing.PYTHON
func = kw[0]
except:
out.write(line)
continue
# PyMOL stuff without named python function
if func.__name__ == '<lambda>' or name.startswith('@'):
print('cmd.do(%s)' % (repr(line.strip())), file=out)
continue
# code blocks
if name == 'python':
for line in handle:
if line.split() == ['python', 'end']:
break
out.write(line)
continue
if name == 'skip':
for line in handle:
if line.split() == ['skip', 'end']:
break
continue
# split args
tok = ','
if kw[4] == parsing.MOVIE:
tok = kw[3]
split_mx = 1
else:
split_mx = kw[4] - parsing.LITERAL
if len(a) > 1:
a[1] = parsing.split(a[1], '#', 1)[0] # strip of comment
if split_mx < 0:
# strip of additional commands
a[1:] = parsing.split(a[1], ';', 1)
if len(a) > 2:
handle.push(a[2])
if split_mx == 0:
args = [a[1]]
else:
args = [i.strip() for i in parsing.split(a[1], tok, max(0, split_mx))]
else:
args = []
# old syntax: set property=value
if kw[4] == parsing.LEGACY and '=' in args[0]:
args = [i.strip() for i in args[0].split('=', 1)] + args[1:]
# register alias
if name == 'alias':
cmd.alias(*args)
# use 'cmd' module if possible
try:
test = getattr(cmd, func.__name__)
assert func == test
module = 'cmd'
except:
module = func.__module__
print('%s.%s(%s)' % (module, func.__name__, ', '.join(quote(args))), file=out)
cmd.extend('pml2py', pml2py)
# vi:expandtab:smarttab