Monthly Scripting Column for April

Greetings! This continues a series of bulletins, in which we introduce one of the scripts that will be in a future release.

Tip: don't like the output? Use 'p4 -G' output as input to your Python script, and format the data (or graph it) to your liking.

Today's script

Leverage off other work. We hear this often, and say it in this column a lot, too. The most error-prone programming I encounter is data validation code. That's the stuff that reads input, validates it, etc. Any chance I get to use code that someone else has already created (and tested), I'll take.

To that end, there's a facility available to Python programmers for retrieving that data from a Perforce query without parsing through formatted output. This option, "p4 -G", retrieves Perforce data to be read by a Python program:

      p4 -G clients  | python program.py 
Today's example retrieves that output using the Python library routine, os.popen.

The "-G" option, which went between p4 and clients, sets the output option to a binary format. That format is called "marshal", and is a representation of a Python variable or object.

You can read such output with this routine written in Python, which runs a Perforce command and returns the results of the 'p4' command. The results are easy for the Python programmer to use: an array of 'dict' objects.

import os
import marshal
def runp4cmd(p4cmd):
    """ Return the output from the Perforce command,
    and assume that the user put the '-G' in the options
    to get us marshall output.  We always return an array
    for the results."""

    fd = os.popen(p4cmd, 'r')
    results = []
    while 1:
        try:
            d = marshal.load(fd)
            results.append(d)
        except EOFError:
            break
    fd.close()
    return results         # end of runp4cmd

clientList = runp4cmd('p4 -G clients')
for c in clientList:
    print c['client']

In the following example, there's a reference to the Options field. (We normally think of it as a list of strings, since that's how the client spec is formatted when we run 'p4 client.') The first thing is to burst it into an array, optionList, so that we can search it easily.


import marshal,os, pprint,sys
from readp4marshal import runp4cmd

# Task: determine which client specs have the option 'nocompress'set.
#
# status: tested on Win/2000 using python 2.0
# num of calls to 'p4': 1

clientList = runp4cmd("p4 -G clients")

for c in clientList:
    optionList = c['Options'].split(' ')
    for o in optionList:
        if o == 'compress':
            print "%s: compression of data (default)" % c['client']
        if o == 'nocompress':
            print "%s: *no* compression of data" % c['client']

findnocompress.py

Note: all the programs shown in these columns have been written four times: in Perl, in P4Perl, in Python, and in P4Ruby. Look into the Perforce example database for the other versions.
$Id: //guest/jeff_bowles/scripts/0430python.html#1 $
© 2004 Perforce Corporation, Inc.