Programming with P4Python
P4Python
provides an object-oriented interface to
Helix Core Server
that is intended to be intuitive for Python programmers. Data is loaded
and returned in Python arrays and dictionaries. Each
P4
object represents a connection to the Helix Core Server.
When instantiated, the P4
instance is set up with
the default environment settings just as the command line client
p4
, that is, using environment variables, the
registry or user preferences (on Windows and macOS) and, if defined, the
P4CONFIG
file. The settings can be checked and changed
before the connection to the server is established with the
P4.connect()
method. After your script connects, it can send
multiple commands to the Helix Core Server with the same P4
instance. After the script is
finished, it should disconnect from the server by calling the
P4.disconnect()
method.
The following example illustrates the basic structure of a P4Python script. The example establishes a connection, issues a command, and tests for errors resulting from the command:
from P4 import P4,P4Exception # Import the module
p4 = P4() # Create the P4 instance
p4.port = "1666"
p4.user = "fred"
p4.client = "fred-ws" # Set some environment variables
try: # Catch exceptions with try/except
p4.connect() # Connect to the Perforce server
info = p4.run( "info" ) # Run "p4 info" (returns a dict)
for key in info[0]: # and display all key-value pairs
print key, "=", info[0][key]
p4.run( "edit", "file.txt" ) # Run "p4 edit file.txt"
p4.disconnect() # Disconnect from the server
except P4Exception:
for e in p4.errors: # Display errors
print e
This example creates a client workspace from a template and syncs it:
from P4 import P4, P4Exception
template = "my-client-template"
client_root = "C:\work\my-root"
p4 = P4()
try:
p4.connect()
# Retrieve client spec as a Python dictionary
client = p4.fetch_client( "-t", template )
client._root = client_root
p4.save_client( client )
p4.run_sync()
except P4Exception:
# If any errors occur, we'll jump in here. Just log them
# and raise the exception up to the higher level
When extending the P4 class, be sure to match the method signatures used in the default class. P4Python uses both variable length arguments (*args) and keyword arguments (**kwargs). Review the P4.py in the source bundle for specifics. Example code:
class MyP4(P4.P4):
def run(self, *args, **kargs):
P4.P4.run(self, *args, **kargs)
Using keyword arguments
All of the attributes that can be set for an active connection can also be provided as keyword arguments. This only works for a single command and you do not need to wrap the command in a with block. More than one keyword argument can be provided if required.
Examples
To disable tagged mode:
p4.run_counter('mycounter', tagged = False)
To provide an OutputHandler:
p4.run_files('//...', handler = MyOutputHandler() )
Submitting a Changelist
This example creates a changelist, modifies it and then submits it:
from P4 import P4
p4 = P4()
p4.connect()
change = p4.fetch_change()
# Files were opened elsewhere and we want to
# submit a subset that we already know about.
myfiles = ['//depot/some/path/file1.c', '//depot/some/path/file1.h']
change._description = "My changelist\nSubmitted from P4Python\n"
change._files = myfiles # This attribute takes a Python list
p4.run_submit( change )
Logging into Helix Core Server ticket-based authentication
On some servers, users might need to log in to Helix Core Server before issuing commands. The following example illustrates login using Helix Core Server tickets:
from P4 import P4
p4 = P4()
p4.user = "bruno"
p4.password = "my_password"
p4.connect()
p4.run_login()
opened = p4.run_opened()
...
Connecting to Helix Core Server over SSL
Scripts written with
P4Python
use any existing P4TRUST
file present in their operating
environment (by default, .p4trust
in the home directory of
the user that runs the script).
If the fingerprint returned by the server fails to match the one
installed in the P4TRUST
file associated with the script’s
run-time environment, your script will (and should!) fail to connect to
the server.
Changing your password
You can use P4Python to change your password, as shown in the following example:
from P4 import P4
p4 = P4()
p4.user = "bruno"
p4.password = "MyOldPassword"
p4.connect()
p4.run_password( "MyOldPassword", MyNewPassword" )
# p4.password is automatically updated with the encoded password
Timestamp conversion
Timestamp information in
P4Python
is normally represented as seconds since Epoch (with the exception of
P4.Revision
). To convert this data to a more useful
format, use the following procedure:
import datetime
...
myDate = datetime.datetime.fromtimestamp(timestamp, datetime.UTC)
Working with comments in specs
As of
P4Python
2012.3, comments in specs are preserved in the
parse_<spectype>()
and
format_<spectype>()
methods. This behavior can
be circumvented by using parse_spec( '<spectype>',
spec )
and format_spec( '<spectype>',
spec )
instead of parse_<spectype>(
spec )
and format_<spectype>(
spec )
. For example:
p4 = P4()
p4.connect()
...
# fetch a client spec in raw format, no formatting:
specform = p4.run( 'client', '-o', tagged=False )[0]
# convert the raw document into a spec
client1 = p4.parse_client( specform )
# comments are preserved in the spec as well
print( client1.comment )
# comments can be updated
client1.comment += "# ... and now for something completely different"
# the comment is prepended to the spec ready to be sent to the user
formatted1 = p4.format_client( client1 )
# or you can strip the comments
client2 = p4.parse_spec( 'client', specform )
formatted2 = p4.format_spec( 'client', specform )