Search code examples
pythonstreamperforcep4python

Perforce P4Python create new stream without vim opening


I am trying to create and populate streams from a parent using P4Python. using the .run command I can send the terminal command, but I cannot surpress vim opening, which prevents the script from populating the stream. Ultimately the script is going to be triggered by another application and the goal is to automate the creation of streams if certain criteria is met. All this works fine, except for the unattended stream creation. Does any of you have any experience with this?

#!/usr/bin/python3
import sys
import P4



p4 = P4.P4()

p4.user = 'user'
p4.password = 'password'
p4.port = 'ssl:localhost:1666'
p4.connect()

stream_name = sys.argv[1]
parent_stream = sys.argv[2]

p4.run(
       "stream",
       "-t",
       "development",
       "-P",
       parent_stream,
       stream_name
    )

p4.run(
    "populate",
    "-S",
    stream_name,
    "-r",
    "-d",
    f"Initial population of stream '{stream_name}'"
)

p4.disconnect()

I tried to replace the stream creation part with the below code, the problem however is that the script seems to hang and I have to manually abort the execution. Once it is done, the populated stream somehow shows up in the depot

import subprocess

def run_p4_stream():
    
    command = [ "stream",
       "-t",
       "development",
       "-P",
       parent_stream,
       stream_name]

    with open('/dev/null', 'w') as devnull:
        subprocess.call(command, stdout=devnull, stderr=subprocess.STDOUT)


run_p4_stream()

Solution

  • From the CLI, you'd use p4 <spec> -o | p4 <spec> -i to create a form of type <spec> without invoking an editor (the -o flag sends the spec to stdout, the -i flag reads it from stdin, and you can potentially modify the form in between with sed/awk/etc). You can also set P4EDITOR to a program other than vim (e.g. you could set it to something that'll no-op instead of opening a UI, or maybe edit the spec on disk and save the modifications before exiting), but that's probably more hassle than using -o/-i.

    In P4Python the handy equivalent is fetch_<spec> and save_<spec>:

    import sys
    import P4
    
    p4 = P4.P4()
    
    stream_name, parent_stream = sys.argv[1:]
    
    # p4.user = 'user'
    # p4.password = 'password'
    # p4.port = 'ssl:localhost:1666'
    
    with p4.connect() as p4:
        p4.save_stream(p4.fetch_stream(
            "-P", parent_stream,
            "-t", "development",
            stream_name
        ))
        p4.run_populate("-r", "-S", stream_name)
    

    p4.fetch_stream returns the new stream spec as a dict, which you can change before passing it to p4.save_stream (if you want to e.g. set a description or change the options).