This is a read-only mirror of pymolwiki.org

Difference between revisions of "Pml2py"

From PyMOL Wiki
Jump to navigation Jump to search
(parse list arguments)
m (1 revision)
 
(5 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]
 
TODO
 
 
    comments, aliases
 
 
     '''
 
     '''
 
     def quote(args):
 
     def quote(args):
Line 30: Line 28:
 
                 prefix += '='
 
                 prefix += '='
 
                 arg = arg.lstrip()
 
                 arg = arg.lstrip()
            if arg.startswith('['):
 
                while not arg.endswith(']'):
 
                    arg += ',' + args.next()
 
            elif arg.startswith('('):
 
                while not arg.endswith(')'):
 
                    arg += ',' + args.next()
 
 
             yield prefix + repr(arg)
 
             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 >> out, '''
+
     print('''
 
# automatically converted from "%s"
 
# automatically converted from "%s"
 
import pymol
 
import pymol
 
from pymol import *
 
from pymol import *
''' % (filename)
+
''' % (filename), file=out)
  
     handle = iter(open(filename))
+
     handle = stackiter(open(filename, 'rU'))
 
     for line in handle:
 
     for line in handle:
 
         while line.endswith('\\\n'):
 
         while line.endswith('\\\n'):
             line = line[:-2] + handle.next()
+
             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 59: Line 70:
 
                 raise
 
                 raise
 
             name = cmd.kwhash.shortcut.get(name, name)
 
             name = cmd.kwhash.shortcut.get(name, name)
             func = cmd.keyword[name][0]
+
             kw = cmd.keyword[name]
             assert func.__name__ != 'python_help'
+
            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 func.__name__ == '<lambda>':
+
        # code blocks
             print >> out, 'cmd.do(%s)' % (repr(line.strip()))
+
         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
 
             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].split(',')]
+
             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 = []
  
 
         # old syntax: set property=value
 
         # old syntax: set property=value
         if name in ['set', 'set_color'] and '=' in args[0]:
+
         if kw[4] == parsing.LEGACY and '=' in args[0]:
 
             args = [i.strip() for i in args[0].split('=', 1)] + args[1:]
 
             args = [i.strip() for i in args[0].split('=', 1)] + args[1:]
  
         if name == 'python':
+
        # register alias
             for line in handle:
+
         if name == 'alias':
                if line.split() == ['python', 'end']:
+
             cmd.alias(*args)
                    break
 
                out.write(line)
 
            continue
 
  
 
         # use 'cmd' module if possible
 
         # use 'cmd' module if possible
Line 93: Line 132:
 
             module = func.__module__
 
             module = func.__module__
  
         print >> out, '%s.%s(%s)' % (module, func.__name__, ', '.join(quote(args)))
+
         print('%s.%s(%s)' % (module, func.__name__, ', '.join(quote(args))), file=out)
  
 
cmd.extend('pml2py', pml2py)
 
cmd.extend('pml2py', pml2py)

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