Programming with P4Python
P4Python provides an object-oriented interface to Perforce 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 Perforce 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 OS X) 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 Perforce 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()
# Convert client spec into 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
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 Perforce using ticket-based authentication
On some servers, users might need to log in to Perforce before issuing commands. The following example illustrates login using Perforce 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 Perforce 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.utcfromtimestamp( int( timestampValue ) )
Working with comments in specs
As of P4Python 2012.3, comments in specs are preserved in the
parse_
and
<spectype>
()format_
methods. This behavior can be circumvented by using
<spectype>
()parse_spec( '
and
<spectype>
',
spec
)format_spec( '
instead of
<spectype>
',
spec
)parse_
and
<spectype>
(
spec
)format_
. For example:
<spectype>
(
spec
)
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 )