Pml2py: Difference between revisions

From PyMOLWiki
Jump to navigation Jump to search
(parse list arguments)
(use pymol.parsing module)
Line 5: Line 5:
<source lang="python">
<source lang="python">
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 19: Line 19:
TODO
TODO


     comments, aliases
     comments, aliases, multiple commands in one line
     '''
     '''
     def quote(args):
     def quote(args):
Line 30: Line 30:
                 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)


Line 47: Line 41:
''' % (filename)
''' % (filename)


     handle = iter(open(filename))
     handle = iter(open(filename, 'rU'))
     for line in handle:
     for line in handle:
         while line.endswith('\\\n'):
         while line.endswith('\\\n'):
Line 53: Line 47:


         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 57:
                 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 >> out, 'cmd.do(%s)' % (repr(line.strip()))
             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(',')]
             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':
            for line in handle:
                if line.split() == ['python', 'end']:
                    break
                out.write(line)
            continue


         # use 'cmd' module if possible
         # use 'cmd' module if possible

Revision as of 10:29, 20 May 2011

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).

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]

TODO

    comments, aliases, multiple commands in one line
    '''
    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)

    if isinstance(out, basestring):
        out = open(out, 'w')

    print >> out, '''
# automatically converted from "%s"
import pymol
from pymol import *
''' % (filename)

    handle = iter(open(filename, 'rU'))
    for line in handle:
        while line.endswith('\\\n'):
            line = line[:-2] + handle.next()

        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 >> out, 'cmd.do(%s)' % (repr(line.strip()))
            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:
            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:]

        # use 'cmd' module if possible
        try:
            test = getattr(cmd, func.__name__)
            assert func == test
            module = 'cmd'
        except:
            module = func.__module__

        print >> out, '%s.%s(%s)' % (module, func.__name__, ', '.join(quote(args)))

cmd.extend('pml2py', pml2py)

# vi:expandtab:smarttab