• [SCM]源码管理 perforce python的使用


    一 p4的API支持几乎所有的常用的语言
    1)查看p4 API 主页: http://www.perforce.com/perforce/loadsupp.html#api (包含下载 和 p4script.pdf)

    2)支持几乎所有的语言: 

    Perforce C/C++ API
    Perforce Java API
    Perforce Perl API
    Perforce Ruby API
    Perforce Python API
    Perforce PHP API
    Perforce Objective-C API
    P4COM, a COM Interface to the Perforce C++ API for Windows

    二 p4python

    1)安装(以windows为例)

    下载和安装python2.6;(可以安装activepython)

    下载和安装p4python26;(ftp://ftp.perforce.com/perforce/r09.2/bin.ntx86/p4python26.exe

    2)安装后(C:\Python26\Lib\site-packages)

    文件:P4.py + P4.pyc + P4API.pyd + P4Python-2009.2-py2.6.egg-info。其中P4API.pyd为python对p4的extension模块,里面定义了 P4API.P4Adapter可惜看不到源码,P4.py 里面包含了p4 class的定义,p4class从P4API.P4Adapter继承。

    3)p4.py

    在p4.py中定义了

    • P4
    • P4Exception
    • DepotFile
    • Revision
    • Integration
    • MergeData
    • Spec

    其中主要的p4 class定义如下:

    import P4API

    class P4(P4API.P4Adapter):
        
    """Use this class to communicate with a Perforce server
        
        Instances of P4 will use the environment settings (including P4CONFIG)
        to determine the connection parameters such as P4CLIENT and P4PORT.
        
        This attributes can also be set separately before connecting.
        
        To run any Perforce commands, users of this class first need to run
        the connect() method.
        
        It is good practice to disconnect() after the program is complete.
        
    """
        
    # Constants useful for exception_level
        # RAISE_ALL:     Errors and Warnings are raised as exceptions (default)
        # RAISE_ERROR:   Only Errors are raised as exceptions
        # RAISE_NONE:    No exceptions are raised, instead False is returned
        
        RAISE_ALL 
    = 2
        RAISE_ERROR 
    = 1
        RAISE_NONE 
    = 0
        
        
    def __init__(self, *args, **kwlist): 
            P4API.P4Adapter.
    __init__(self, *args, **kwlist)

        
    def __del__(self):
            
    if self.debug > 3:
                
    print >>sys.stderr, "P4.__del__()"
                
        
    # store the references to the created lambdas as a weakref to allow Python 
        # to clean up the garbage. |The lambda as a closure stores a reference to self
        # which causes a circular reference problem without the weakref
        
        
    def __getattr__(self, name):
            
    if name.startswith("run_"):
                cmd 
    = name[len("run_"):]
                
    return lambda *args: self.run(cmd, *args)
            
    elif name.startswith("delete_"):
                cmd 
    = name[len("delete_"):]
                
    return lambda *args: self.run(cmd, "-d"*args)
            
    elif name.startswith("fetch_"):
                cmd 
    = name[len("fetch_"):]
                
    return lambda *args: self.run(cmd, "-o"*args)[0]
            
    elif name.startswith("save_"):
                cmd 
    = name[len("save_"):]
                
    return lambda *args: self.__save(cmd, *args)
            
    elif name.startswith("parse_"):
                cmd 
    = name[len("parse_"):]
                
    return lambda *args: self.parse_spec(cmd, *args)
            
    elif name.startswith("format_"):
                cmd 
    = name[len("format_"):]
                
    return lambda *args: self.format_spec(cmd, *args)
            
    else:
                
    raise AttributeError, name
        
        
    def __save(self, cmd, *args):
            self.input 
    = args[0]
            
    return self.run(cmd, "-i", args[1:])
        
        
    def __repr__(self):
            state 
    = "disconnected"
            
    if self.connected():
                state 
    = "connected"
                
            
    return "P4 [%s@%s %s] %s" % \
              (self.user, self.client, self.port, state)
        
        
    def identify(cls):
            
    return P4API.identify()
        identify 
    = classmethod(identify)
        
        
    def run(self, *args):
            
    "Generic run method"
            
    return P4API.P4Adapter.run(self, *self.__flatten(args))
            
        
    def run_submit(self, *args):
            
    "Simplified submit - if any arguments is a dict, assume it to be the changeform"
            nargs 
    = list(args)
            form 
    = None
            
    for n, arg in enumerate(nargs):
                
    if isinstance( arg, dict):
                    self.input 
    = arg
                    nargs.pop(n)
                    nargs.append(
    "-i")
                    
    break
            
    return self.run("submit"*nargs)
        
        
    def run_login(self, *args):
            
    "Simple interface to make login easier"
            self.input 
    = self.password
            
    return self.run("login"*args)

        
    def run_password( self, oldpass, newpass ):
            
    "Simple interface to allow setting of the password"
            
    if( oldpass and len(oldpass) > 0 ):
                self.input 
    = [ oldpass, newpass, newpass ]
            
    else:
                self.input 
    = [ newpass, newpass ]
                
            
    return self.run( "password" )

        
    #
        # run_filelog: convert "p4 filelog" responses into objects with useful
        #              methods
        #
        # Requires tagged output to be of any real use. If tagged output it not 
        # enabled then you just get the raw data back
        #
        def run_filelog( self, *args ):
          raw 
    = self.run( 'filelog', args )
          
    if (not self.tagged): 
              
    # untagged mode returns simple strings, which breaks the code below
              return raw
          result 
    = []
          
    for h in raw:
              r 
    = None
              
    if isinstance( h, dict ):
                  df 
    = DepotFile( h[ "depotFile" ] )
                  
    for n, rev in enumerate( h[ "rev" ]):
                      
    # Create a new revision of this file ready for populating
                      r = df.new_revision()
                      
    # Populate the base attributes of each revision
                      r.rev = int( rev )
                      r.change 
    = int( h[ "change" ][ n ] )
                      r.action 
    = h[ "action" ][ n ] 
                      r.type 
    = h[ "type" ][ n ]
                      r.time 
    = datetime.datetime.utcfromtimestamp( int( h[ "time" ][ n ]) )
                      r.user 
    = h[ "user" ][ n ]
                      r.client 
    = h[ "client" ][ n ]
                      r.desc 
    = h[ "desc" ][ n ]
                      
    if "digest" in h:
                        r.digest 
    = h[ "digest" ][ n ]
                      
    if "fileSize" in h:
                        r.fileSize 
    = h[ "fileSize" ][ n ]

                      
    # Now if there are any integration records for this revision,
                      # add them in too
                      
                      
    if (not "how" in h) or (n >= len(h["how"]) or h["how"][n] == None):
                          
    continue
                      
    else:
                          
    for m, how in enumerate( h[ "how" ][ n ] ):
                              file 
    = h[ "file" ][ n ][ m ]
                              srev 
    = string.lstrip(h[ "srev" ][ n ][ m ], '#')
                              erev 
    = string.lstrip(h[ "erev" ][ n ][ m ], '#')
                              
                              
    if srev == "none":
                                  srev 
    = 0
                              
    else:
                                  srev 
    = int( srev )
                            
                              
    if erev == "none":
                                  erev 
    = 0
                              
    else:
                                  erev 
    = int( erev )
                                  
                              r.integration( how, file, srev, erev )
              
    else:
                  r 
    = h
              result.append( df )
          
    return result

        
    def run_print(self, *args):
          raw 
    = self.run('print', args)
          result 
    = [raw.pop(0), ""]
          
          
    for line in raw:
              result[
    -1+= line
          
    return result
        
        
    def run_resolve(self, *args, **kargs):
            myResolver 
    = Resolver()
            
    if "resolver" in kargs: 
                myResolver 
    = kargs["resolver"]
                
            savedResolver 
    = self.resolver
            self.resolver 
    = myResolver
            result 
    = self.run("resolve", args)
            self.resolver 
    = savedResolver
            
            
    return result
        
        
    def __flatten(self, args):
            result 
    = []
            
    if isinstance(args, tuple) or isinstance(args, list):
                
    for i in args:
                    result.extend(self.
    __flatten(i))
            
    else:
                result.append(args)
            
    return tuple(result)

        
    def __enter__( self ):
            
    return self
            
        
    def __exit__( self, exc_type, exc_val, exc_tb ):
            
    if self.connected():
                self.disconnect()
            
    return True
            
        
    def connect( self ):
            P4API.P4Adapter.connect( self )
            
    return self
        
        @contextmanager
        
    def while_tagged( self, t ):
            old 
    = self.tagged
            self.tagged 
    = t
            
    yield
            self.tagged 
    = old
        
        @contextmanager
        
    def at_exception_level( self, e ):
            old 
    = self.exception_level
            self.exception_level 
    = e
            
    yield
            self.exception_level 
    = old
            
        @contextmanager
        
    def saved_context( self , **kargs):
            
    """Saves the context of this p4 object and restores it again at the end of the block"""
        
            saved_context 
    = {}
            
    for attr in self.__members__:
                saved_context[attr] 
    = getattr(self, attr)
        
            
    for (k,v) in kargs.items():
                setattr( self, k, v)
            
            
    yield
            
            
    # now restore the context again. Ignore AttributeError exception
            # Exception is expected because some attributes only have getters, no setters
            
            
    for (k,v) in saved_context.items():
                
    try:
                    setattr( self, k, v )
                
    except AttributeError:
                    
    pass # expected for server_level and p4config_file

    三 实例

    1)p4info.py

    from P4 import P4,P4Exception 

    p4 
    = P4() 
    p4.port 
    = "localhost:1666"
    p4.user 
    = "AAA"
    p4.password 
    = "aaa"
    p4.client 
    = "TestProject_AAA" 

    try
      p4.connect() 
      info 
    = p4.run("info"
      
    for key in info[0]: 
        
    print key, "=", info[0][key]
      p4.disconnect() 
    except P4Exception:
      
    for e in p4.errors: 
        
    print e

    结果:

    2)p4sync.py 

    from P4 import P4, P4Exception

    p4 
    = P4() 
    p4.port 
    = "localhost:1666"
    p4.user 
    = "AAA"
    p4.password 
    = "aaa"
    p4.client 
    = "TestProject_AAA" 

    try:
      p4.connect()
      p4.exception_level 
    = 1 # ignore "File(s) up-to-date"
      files = p4.run_sync()
      
    for file in files:
        
    for key in file.keys():
          
    print key,":",file[key]
        
    print "----------"
    except P4Exception:
      
    for e in p4.errors:
        
    print e
    finally:
      p4.disconnect()

    结果:

    3)p4submit.py

    from P4 import P4

    p4 
    = P4()
    p4.host 
    = "localhost"
    p4.port 
    = "1666"
    p4.user 
    = "AAA"
    p4.password 
    = "aaa"
    p4.client 
    = "TestProject_AAA"

    p4.connect()
    changeSpec 
    = p4.run_change( "-o" )
    change 
    = changeSpec[0]
    change[
    "Description"= "Autosubmitted changelist"

    p4.run_edit(
    "//depot/TestProject/addfile.txt")

    change[
    "Files"= ["//depot/TestProject/addfile.txt"]
    p4.input 
    = change
    p4.run_submit( 
    "-i" )
    p4.disconnect()

    所有的p4 command 都可以使用p4.run_command()或p4.run(command)来调用。

    四 超级详细的帮助文档:

    http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html
     

    完!

  • 相关阅读:
    线程共享全局变量和私有全局变量
    线程退出前操作
    Linux下线程pid和tid
    几种常见的光纤接头(ST,SC,LC,FC)以及PC、APC和UPC的区别
    Javascript对象及数组用法笔记
    Javascript对象及数组用法笔记
    程序员特有的9个坏习惯
    程序员特有的9个坏习惯
    程序人生:真正的效率源自专注
    程序人生:真正的效率源自专注
  • 原文地址:https://www.cnblogs.com/itech/p/2176455.html
Copyright © 2020-2023  润新知