Class P4
Description
Main interface to the Python client API.
This module provides an object-oriented interface to the Perforce version management system. Data is returned in Python arrays and dictionaries (hashes) and input can also be supplied in these formats.
Each P4
object represents a connection to the
Perforce server, and multiple commands may be executed (serially) over a
single connection (which of itself can result in substantially improved
performance if executing long sequences of Perforce commands).
-
Instantiate your
P4
object. -
Specify your Perforce client environment:
-
client
-
host
-
password
-
port
-
user
-
-
Set any options to control output or error handling:
-
exception_level
-
-
Connect to the Perforce service.
The Perforce protocol is not designed to support multiple concurrent queries over the same connection. Multithreaded applications that use the C++ API or derived APIs (including P4Python) should ensure that a separate connection is used for each thread, or that only one thread may use a shared connection at a time.
-
Run your Perforce commands.
-
Disconnect from the Perforce service.
Instance Attributes
p4.api_level -> int
Contains the API compatibility level desired. This is useful when
writing scripts using Perforce commands that do not yet support tagged
output. In these cases, upgrading to a later server that supports
tagged output for the commands in question can break your script.
Using this method allows you to lock your script to the output format
of an older Perforce release and facilitate seamless upgrades. Must be
called before calling P4.connect()
.
from P4 import P4
p4 = P4()
p4.api_level = 67 # Lock to 2010.1 format
p4.connect()
...
p4.disconnect
For the API integer levels that correspond to each Perforce release, see:
p4.charset -> string
Contains the character set to use when connect to a Unicode enabled
server. Do not use when working with non-Unicode-enabled servers. By
default, the character set is the value of the
P4CHARSET
environment variable. If the character set is
invalid, this method raises a P4Exception
.
from P4 import P4
p4 = P4()
p4.client = "www"
p4.charset = "iso8859-1"
p4.connect()
p4.run_sync()
p4.disconnect()
p4.client -> string
Contains the name of your client workspace. By default, this is the
value of the P4CLIENT
taken from any
P4CONFIG
file present, or from the environment
according to the normal Perforce conventions.
p4.cwd -> string
Contains the current working directly. Can be called prior to
executing any Perforce command. Sometimes necessary if your script
executes a chdir()
as part of its processing.
from P4 import P4
p4 = P4()
p4.cwd = "/home/bruno"
p4.disable_tmp_cleanup -> string
Invoke this prior to connecting if you need to use multiple
P4
connections in parallel in a multi-threaded
Python application.
from P4 import P4
p4 = P4()
p4.disable_tmp_cleanup()
p4.connect()
...
p4.disconnect()
p4.encoding -> string
When decoding strings from a non-Unicode server, strings are assumed
to be encoded in UTF8. To use another encoding, set
p4.encoding
to a legal Python encoding, or
raw
to receive Python bytes instead of a Unicode
string. Available only when compiled with Python 3.
p4.errors -> list (read-only)
Returns an array containing the error messages received during execution of the last command.
from P4 import P4, P4Exceptionp4 = P4()
try:
p4.connect()
p4.exception_level = 1
# ignore "File(s) up-to-date"s
files = p4.run_sync()
except P4Exception:
for e in p4.errors:
print e
finally:
p4.disconnect()
p4.exception_level -> int
Configures the events which give rise to exceptions. The following three levels are supported:
-
0
: disables all exception handling and makes the interface completely procedural; you are responsible for checking thep4.errors
andp4.warnings
arrays. -
1
: causes exceptions to be raised only when errors are encountered. -
2
: causes exceptions to be raised for both errors and warnings. This is the default.
For example:
from P4 import P4
p4 = P4()
p4.exception_level = 1
p4.connect() # P4Exception on failure
p4.run_sync() # File(s) up-to-date is a warning - no exception raised
p4.disconnect()
p4.handler -> handler
Set the output handler to a subclass of
P4.OutputHandler
.
p4.host -> string
Contains the name of the current host. It defaults to the value of
P4HOST
taken from any P4CONFIG
file
present, or from the environment as per the usual Perforce convention.
Must be called before connecting to the Perforce server.
from P4 import P4
p4 = P4()
p4.host = "workstation123.perforce.com"
p4.connect()
...
p4.disconnect()
p4.ignore_file -> string
Contains the path of the ignore file. It defaults to the value of
P4IGNORE
. Set P4.ignore_file
prior to calling P4.is_ignored()
.
from P4 import P4
p4 = P4()
p4.connect()
p4.ignore_file = "/home/bruno/workspace/.ignore"
p4.disconnect()
p4.input -> string | dict | list
Contains input for the next command.
Set this attribute prior to running a command that requires input from
the user. When the command requests input, the specified data is
supplied to the command. Typically, commands of the form p4
cmd
-i are invoked using the
P4.save_
methods, which retrieve the value from <spectype>
()p4.input
internally; there is no need to set p4.input
when
using the
P4.save_
shortcuts.
<spectype>
()
You may pass a string, a hash, or (for commands that take multiple inputs from the user) an array of strings or hashes. If you pass an array, note that the first element of the array will be popped each time Perforce asks the user for input.
For example, the following code supplies a description for the default changelist and then submits it to the depot:
from P4 import P4
p4 = P4()
p4.connect()
change = p4.run_change( "-o" )[0]
change[ "Description" ] = "Autosubmitted changelist"
p4.input = change
p4.run_submit( "-i" )
p4.disconnect()
p4.iterate_<spectype>( arguments ) -> P4.Spec
The
iterate_
methods are shortcut methods that allow you to quickly iterate through
clients, labels, branches, etc. Valid
<spectype>
()<spectypes>
are clients
,
labels
, branches
,
changes
, streams
,
jobs
, users
,
groups
, depots
and
servers
. Valid arguments are any arguments that
would be valid for the corresponding
run_
command.
<spectype>
()
For example:
for client in p4.iterate_clients():
# do something with the client spec
is equivalent to:
for c in p4.run_clients():
client = p4.fetch_client( c['client'] )
p4.maxlocktime -> int
Limit the amount of time (in milliseconds) spent during data scans to prevent the server from locking tables for too long. Commands that take longer than the limit will be aborted. The limit remains in force until you disable it by setting it to zero. See p4 help maxlocktime for information on the commands that support this limit.
p4.maxresults -> int
Limit the number of results Perforce permits for subsequent commands. Commands that produce more than this number of results will be aborted. The limit remains in force until you disable it by setting it to zero. See p4 help maxresults for information on the commands that support this limit.
p4.maxscanrows -> int
Limit the number of database records Perforce scans for subsequent commands. Commands that attempt to scan more than this number of records will be aborted. The limit remains in force until you disable it by setting it to zero. See p4 help maxscanrows for information on the commands that support this limit.
p4.messages -> list (read-only)
Returns a list of P4.Message
objects, one for
each message (info, warning or error) sent by the server.
p4.p4config_file -> string (read-only)
Contains the name of the current P4CONFIG
file, if any.
This attribute cannot be set.
p4.password -> string
Contains your Perforce password or login ticket. If not used, takes
the value of P4PASSWD
from any P4CONFIG
file in effect, or from the environment according to the normal
Perforce conventions.
This password is also used if you later call
p4.run_login()
to log in using the 2003.2 and
later ticket system. After running
p4.run_login()
, the attribute contains the
ticket the allocated by the server.
from P4 import P4
p4 = P4()
p4.password = "mypass"
p4.connect()
p4.run_login()
p4.port -> string
Contains the host and port of the Perforce server to which you want to
connect. It defaults to the value of P4PORT
in any
P4CONFIG
file in effect, and then to the value of
P4PORT
taken from the environment.
from P4 import P4
p4 = P4()
p4.port = "localhost:1666"
p4.connect()
...
p4.prog -> string
Contains the name of the program, as reported to Perforce system
administrators running p4 monitor show -e. The
default is unnamed p4-python script
.
from P4 import P4
p4 = P4()
p4.prog = "sync-script"
puts( p4.prog )
p4.connect
...
p4.progress -> progress
Set the progress indicator to a subclass of
P4.Progress
.
p4.server_case_insensitive -> boolean
Detects whether or not the server is case-sensitive.
p4.server_level -> int (read-only)
Returns the current Perforce server level. Each iteration of the Perforce server is given a level number. As part of the initial communication this value is passed between the client application and the Perforce server. This value is used to determine the communication that the Perforce server will understand. All subsequent requests can therefore be tailored to meet the requirements of this server level.
This attribute is 0 before the first command is run, and is set automatically after the first communication with the server.
For the API integer levels that correspond to each Perforce release, see:
p4.server_unicode -> boolean
Detects whether or not the server is in Unicode mode.
p4.streams -> int
If 1 or True, p4.streams
enables support for
streams. By default, streams support is enabled at 2011.1 or higher
(api_level
>= 70). Raises a
P4Exception
if you attempt to enable streams on
a pre-2011.1 server. You can enable or disable support for streams
both before and after connecting to the server.
from P4 import P4
p4 = P4()
p4.streams = False
print p4.streams
p4.tagged -> int
If 1 or True, p4.tagged
enables tagged output. By
default, tagged output is on.
from P4 import P4
p4 = P4()
p4.tagged = False
print p4.tagged
p4.ticket_file -> string
Contains the location of the P4TICKETS
file.
p4.track -> boolean
If set to 1 or True, p4.track
indicates that server
performance tracking is enabled for this connection. By default,
performance tracking is disabled.
p4.track_output -> list (read-only)
If performance tracking is enabled with
p4.track
,
returns an array containing the performance data received during
execution of the last command.
from P4 import P4
p4 = P4()
p4.track = 1
p4.run_info()
print p4.track_output
p4.user -> string
Contains the Perforce username. It defaults to the value of
P4USER
taken from any P4CONFIG
file
present, or from the environment as per the usual Perforce convention.
from P4 import P4
p4 = P4()
p4.user = "bruno"
p4.connect()
...
p4.disconnect()
p4.version -> string
Contains the version of the program, as reported to Perforce system administrators in the server log.
from P4 import P4
p4 = P4()
p4.version = "123"
puts( p4.version )
p4.connect()
...
p4.disconnect()
p4.warnings -> list (read-only)
Contains the array of warnings that arose during execution of the last command.
from P4 import P4, P4Exception
p4 = P4()
try:
p4.connect()
p4.exception_level = 2 # File(s) up-to-date is a warning
files = p4.run_sync()
except P4Exception, ex:
for w in p4.warnings:
print w
finally:
p4.disconnect()
Class Methods
P4.P4()
Construct a new P4
object. For example:
from P4 import P4
P4.P4()
P4.identify()
Return the version of P4Python that you are using.
python -c "from P4 import P4; print P4.identify()"
The read-only string attributes PATCHLEVEL
and
OS
are also available to test an installation of
P4Python without having to parse the output of
P4.identify()
.
If applicable, P4.identify()
also reports the
version of the OpenSSL library used for building the underlying
Perforce C++ API with which P4Python was built.
Instance Methods
p4.at_exception_level()
In the context of a with
statement, temporarily set
the exception level for a block. For example:
from P4 import P4
p4 = P4()
p4.connect()
with p4.at_exception_level( P4.RAISE_ERRORS ):
# no exceptions for warnings
p4.run_sync( "//depot/main/..." )
# exceptions back to normal...
p4.connect()
Initializes the Perforce client and connects to the server.
If the connection is successfully established, returns
None
. If the connection fails and
P4.exception_level
is 0, returns False, otherwise
raises a P4Exception
. If already connected,
prints a message.
from P4 import P4
p4 = P4()
p4.connect()
...
p4.disconnect()
P4.connect()
returns a context management
object that is usable with a with
statement within
a block; after the block is finished, the connection is automatically
disconnected:
import P4
p4 = P4.P4()
with p4.connect():
# block in context of connection
...
# p4 is disconnected outside the block
...
p4.connected() -> boolean
Returns true
if connected to the Perforce server
and the connection is alive, otherwise false
.
from P4 import P4
p4 = P4()
print p4.connected()
p4.connect()
print p4.connected()
p4.delete_<spectype>( [ options ], name) -> list
The
delete_
methods are shortcut methods that allow you to delete the definitions
of clients, labels, branches, etc. These methods are equivalent to:
<spectype>
()
p4.run( "<spectype>
", '-d', [options], "spec name
" )
The following code uses P4.delete_client()
to
delete client workspaces that have not been accessed in more than 365
days:
from P4 import P4, P4Exception
from datetime import datetime, timedelta
now = datetime.now()
p4 = P4()
try:
p4.connect()
for client in p4.run_clients():
atime = datetime.utcfromtimestamp( int( client[ "Access" ] ) )
# If the client has not been accessed for a year, delete it
if ( atime + timedelta( 365 ) ) < now :
p4.delete_client( '-f', client[ "client" ] )
except P4Exception:
for e in p4.errors:
print e
finally:
p4.disconnect()
p4.disconnect()
Disconnect from the Perforce server. Call this method before exiting your script.
from P4 import P4
p4 = P4()
p4.connect()
...
p4.disconnect()
p4.env( var )
Get the value of a Perforce environment variable, taking into account
P4CONFIG
files and (on Windows or OS X) the registry or
user preferences.
from P4 import P4
p4 = P4()
print p4.env( "P4PORT" )
p4.fetch_<spectype>() -> P4.Spec
The fetch_
methods are shortcuts for running <spectype>
()p4.run(
"
.
For example:
<spectype>
", "-o" ).pop( 0 )
label = p4.fetch_label( "labelname
" )
change = p4.fetch_change( changeno
)
clientspec = p4.fetch_client( "clientname
" )
are equivalent to:
label = p4.run( "label", "-o", "labelname
" )[0]
change = p4.run( "change", "-o", changeno
)[0]
clientspec = p4.run( "client", "-o", "clientname
" )[0]
p4.format_spec( "<spectype>", dict ) -> string
Converts the fields in the dict containing the elements of a Perforce form (spec) into the string representation familiar to users. The first argument is the type of spec to format: for example, client, branch, label, and so on. The second argument is the hash to parse.
There are shortcuts available for this method. You can use
p4.format_
instead of <spectype>
( dict
)p4.format_spec(
"
, where
<spectype>
", dict)<spectype>
is the name of a
Perforce spec, such as client, label, etc.
p4.format_<spectype>( dict ) -> string
The
format_
methods are shortcut methods that allow you to quickly fetch the
definitions of clients, labels, branches, etc. They're equivalent to:
<spectype>
()
p4.format_spec( "<spectype>
", dict )
p4.is_ignored( "<path>" ) -> boolean
Returns true
if the
<path>
is ignored via the
P4IGNORE
feature. The
<path>
can be a local relative or
absolute path.
from P4 import P4
p4 = P4()
p4.connect()
if ( p4.is_ignored( "/home/bruno/workspace/file.txt" ):
print "Ignored."
else:
print "Not ignored."
p4.disconnect()
p4.parse_spec( "<spectype>", string ) -> P4.Spec
Parses a Perforce form (spec) in text form into a Python dict using
the spec definition obtained from the server. The first argument is
the type of spec to parse: client
,
branch
, label
, and so on. The
second argument is the string buffer to parse.
There are shortcuts available for this method. You can use:
p4.parse_<spectype>
( buf )
instead of:
p4.parse_spec( "<spectype>
", buf )
where <spectype>
is one of
client
, branch
,
label
, and so on.
p4.parse_<spectype>( string ) -> P4.Spec
This is equivalent to:
p4.parse_spec( "<spectype>
", string )
For example, parse_job( myJob )
converts the String
representation of a job spec into a Spec object.
To parse a spec, P4
needs to have the spec
available. When not connected to the Perforce server,
P4
assumes the default format for the spec,
which is hardcoded. This assumption can fail for jobs if the server's
jobspec has been modified. In this case, your script can load a job
from the server first with the command p4.fetch_job( 'somename'
)
, and P4
will cache and use the spec
format in subsequent p4.parse_job()
calls.
p4.run( "<cmd>", [arg, ...] )
Base interface to all the run methods in this API. Runs the specified
Perforce command with the arguments supplied. Arguments may be in any
form as long as they can be converted to strings by
str()
.
The p4.run()
method returns a list of results
whether the command succeeds or fails; the list may, however, be
empty. Whether the elements of the array are strings or dictionaries
depends on:
-
server support for tagged output for the command, and
-
whether tagged output was disabled by calling
p4.tagged = False
.
In the event of errors or warnings, and depending on the exception
level in force at the time, p4.run()
raises a
P4Exception
. If the current exception level is
below the threshold for the error/warning,
p4.run()
returns the output as normal and the
caller must explicitly review p4.errors
and
p4.warnings
to check for errors or warnings.
from P4 import P4
p4 = P4()
p4.connect()
spec = p4.run( "client", "-o" )[0]
p4.disconnect()
Shortcuts are available for p4.run()
. For
example:
p4.run_command
( args
)
is equivalent to:
p4.run( "command
", args
)
There are also some shortcuts for common commands such as editing Perforce forms and submitting. For example, this:
from P4 import P4
p4 = P4()
p4.connect()
clientspec = p4.run_client( "-o" ).pop( 0 )
clientspec[ "Description" ] = "Build client"
p4.input = clientspec
p4.run_client( "-i" )
p4.disconnect()
...may be shortened to:
from P4 import P4
p4 = P4()
p4.connect()
clientspec = p4.fetch_client()
clientspec[ "Description" ] = "Build client"
p4.save_client( clientspec )
p4.disconnect()
The following are equivalent:
Shortcut |
Equivalent to |
---|---|
|
|
|
|
|
|
As the commands associated with
p4.fetch_
typically return only one item, these methods do not return an array,
but instead return the first result element.
<spectype>
()
For convenience in submitting changelists, changes returned by
p4.fetch_change()
can be passed to
p4.run_submit()
. For example:
from P4 import P4
p4 = P4()
p4.connect()
spec = p4.fetch_change()
spec[ "Description" ] = "Automated change"
p4.run_submit( spec )
p4.disconnect()
p4.run_<cmd>()
Shorthand for:
p4.run( "<cmd>
", arguments... )
p4.run_filelog( <fileSpec> ) -> list
Runs a p4 filelog on the
fileSpec
provided and returns an array of
P4.DepotFile
results (when executed in tagged
mode), or an array of strings when executed in nontagged mode. By
default, the raw output of p4 filelog is tagged;
this method restructures the output into a more user-friendly (and
object-oriented) form.
For example:
from P4 import P4, P4Exception
p4 = P4()
try:
p4.connect()
for r in p4.run_filelog( "index.html" )[0].revisions:
for i in r.integrations:
# Do something
except P4Exception:
for e in p4.errors:
print e
finally:
p4.disconnect()
p4.run_login( <arg>... ) -> list
Runs p4 login using a password or ticket set by the user.
p4.run_password( oldpass, newpass ) -> list
A thin wrapper to make it easy to change your password. This method is (literally) equivalent to the following:
p4.input( [ oldpass, newpass, newpass ] )
p4.run( "password" )
For example:
from P4 import P4, P4Exception
p4 = P4()
p4.password = "myoldpass"
try:
p4.connect()
p4.run_password( "myoldpass", "mynewpass" )
except P4Exception:
for e in p4.errors:
print e
finally:
p4.disconnect()
p4.run_resolve( [<resolver>], [arg...] ) -> list
Run a p4 resolve command. Interactive resolves
require the <resolver>
parameter to be an
object of a class derived from P4.Resolver
. In
these cases, the P4.Resolver.resolve()
method is called to handle the resolve. For example:
p4.run_resolve ( resolver=MyResolver() )
To perform an automated merge that skips whenever conflicts are detected:
class MyResolver( P4.Resolver ):
def resolve( self, mergeData ):
if not mergeData.merge_hint == "e":
return mergeData.merge_hint
else:
return "s" # skip the resolve, there is a conflict
In non-interactive resolves, no P4.Resolver
object is required. For example:
p4.run_resolve ( "-at" )
p4.run_submit( [ hash ], [ arg... ] ) -> list
Submit a changelist to the server. To submit a changelist, set the fields of the changelist as required and supply any flags:
change = p4.fetch_change()
change._description = "Some description"
p4.run_submit( "-r", change )
You can also submit a changelist by supplying the arguments as you would on the command line:
p4.run_submit( "-d", "Some description", "somedir/..." )
p4.run_tickets( ) -> list
p4.run_tickets()
returns an array of lists of
the form (p4port
, user
,
ticket
) based on the contents of the local tickets
file.
p4.save_<spectype>()>
The save_
methods are shortcut methods that allow you to quickly update the
definitions of clients, labels, branches, etc. They are equivalent to:
<spectype>
()
p4.input = dictOrString
p4.run( "<spectype>
", "-i" )
For example:
from P4 import P4, P4Exception
p4 = P4()
try:
p4.connect()
client = p4.fetch_client()
client[ "Owner" ] = p4.user
p4.save_client( client )
except P4Exception:
for e in p4.errors:
print e
finally:
p4.disconnect()
p4.set_env( var, value )
On Windows or OS X, set a variable in the registry or user preferences. To unset a variable, pass an empty string as the second argument. On other platforms, an exception is raised.
p4.set_env = ( "P4CLIENT", "my_workspace" )
p4.set_env = ( "P4CLIENT", "" )
p4.temp_client( "<prefix>", "<template>" )
Creates a temporary client, using the prefix
<prefix>
and based upon a client
template named <template>
, then
switches P4.client
to the new client, and provides
a temporary root directory. The prefix makes is easy to exclude the
workspace from the spec depot.
This is intended to be used with a with
statement
within a block; after the block is finished, the temp client is
automatically deleted and the temporary root is removed.
For example:
from P4 import P4
p4 = P4()
p4.connect()
with p4.temp_client( "temp", "my_template" ) as t:
p4.run_sync()
p4.run_edit( "foo" )
p4.run_submit( "-dcomment" )
p4.while_tagged( boolean )
In the context of a with
statement, enable or
disable tagged behavior for the duration of a block. For example:
from P4 import P4
p4 = P4()
p4.connect()
with p4.while_tagged( False ):
# tagged output disabled for this block
print p4.run_info()
# tagged output back to normal
...