Package: p4cmd
P4CMD 🌴A Python Perforce package that doesn't bring in any other packages to work.
Relies on p4cli installed on the system.p4cmdThep4cmdmodule holds the P4Client class that allows you to interact with the P4 server.To instantiate a new client, you either pass it the root path of you Perforce workspace or if the "P4ROOT" system variable is set, you can use thefrom_envclass functionfromp4cmdimportp4cmdclient=p4cmd.P4Client("~/nisse/projects/raw")If you pass in a path intoP4Clientthat doesn't have a.p4configfile in it, the class will travel up the chain of parent folders to find a.p4configfile. When found,perforce_rootwill be set to this folder.fromp4cmdimportp4cmdimportos# settings system variableos.environ["P4ROOT"]="~/nisse/projects/raw"# now we can use from_envclient=p4cmd.P4Client.from_env()Most of the functions are pretty self explanatory and have docstrings about how they work.There are 2 functions calledfile_to_p4filesandfolder_to_p4filesthat use theP4Fileclass inp4file.p4fileThis module holds theP4Fileclass that allows you to quickly and easily get information about any file on disk or in the depot.UsageSome use case examples to help you on your way.Checking out files or adding new files. You can mix/match local and depot paths. Add a changelist number or description to put the files in that CL. If you add a description of a changelist that doesn't exist, it will be created.fromp4cmdimportp4cmdroot="~/p4/MyGame"files=[r"~/p4/MyGame/Raw/Characters/info_file.json","//MyGame/Main/Templates/morefiles.json"]p4=p4cmd.P4Client(root)p4.add_or_edit_files(files,changelist="My new changelist")Separateedit_filesandadd_filesmethods also exist if you need to use them for some reason.Perforce operations can be quite slow, so if you need to check a bunch of files at once you can use do something like this:fromp4cmdimportp4cmdroot="~/p4/MyGame"folder=r"~/p4/MyGame/Animations"p4=p4cmd.P4Client(root)p4files=p4.folder_to_p4files(folder)files_to_sync=[]forp4fileinp4files:ifp4file.get_checked_out_by()isnotNone:# somebody else other than you checked out the fileprint("depot path:",p4file.get_depot_file_path())print("local path:",p4file.get_local_file_path())print("status:",p4file.get_status())print("Checked out by:",p4file.get_checked_out_by())ifp4file.needs_syncing():files_to_sync.append(p4file.get_local_file_path())p4.sync_files([files_to_sync])depot path: //MyGame/Main/MyGame/run.fbx
local path: ~/p4/MyGame/MyGame/run.fbx
status: UP_TO_DATE
Checked out by: barack.obama@barack.obama-US-BOBAMA-MyGame
depot path: //MyGame/Main/MyGame/dance.json
local path: ~/p4/MyGame/MyGame/dance.json
status: NEED_SYNCfolder_to_p4filesreturns a list of type p4file. A p4file has a bunch of functions to get information about the file and its status. This will get information back about all the files in one go, instead of you having to make a server call for every file on its own.Getting all your pending changelists:fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)all_changelists=p4.get_pending_changelists()[35272, 33160, 32756, 30872, 27277]Getting changelists with shelved files:fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)shelved_changelists=[pair[1]forpairinp4.get_shelved_files()][30872, 30872, 27277]Searching in changelist descriptions:fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)houdini_cls=p4.get_pending_changelists(description_filter="houdini")[35272, 33160]Finding an exact changelist:fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)houdini_anim_cl=p4.get_pending_changelists(description_filter="[houdini tools]",perfect_match_only=True,case_sensitive=True)[33160]Listing all the files in a changelist by changelist number:fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)files=p4.get_files_in_changelist(33160)//MyGame/Animations/a_pose.fbx
//MyGame/Animations/t_pose.fbxList all the files in a changelist by changelist description:fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)files=p4.get_files_in_changelist("[houdini tools]")//MyGame/Animations/a_pose.fbx
//MyGame/Animations/t_pose.fbxSubmit a changelist with the description "Character files", butdon'trevert unchanged files first.fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)p4.submit_changelist("Character files",revert_unchanged_files=False)Sync all the files in a folder, but first set the parallel connections to 2fromp4cmdimportp4cmdroot="~/p4/MyGame"p4=p4cmd.P4Client(root)p4.set_max_parallel_connections(2)p4.sync_folders(["//Content/Basketball/Players/"])