Perforce API for the .Net CLR P4.Net

Comparisons with other Perforce APIs

Python Example

Let's just dive into a sample, and compare the APIs. In this case, I'll compare P4.Net using IronPython to P4Python using standard Python. Note, I don't mean to suggest that P4.Net/IronPython is superior to P4Python/Standard Python, I just did this to show apples-to-apples comparisons, w/o looking at individual language features.

  # Standard Python and P4Python   # IronPython and P4.Net
       
      import clr
1     from System import Array, String
      clr.AddReferenceToFile('P4API.dll')
       
  import p4 as P4API   import P4API
       
  p4 = P4API.P4()   p4 = P4API.P4Connection()
2 p4.parse_forms()    
  p4.connect()   p4.Connect()
       
  lname = 'P4NetTestingSample'   lname = 'P4NetTestingSample'
       
  # build my label   # build my label
  labelForm = p4.fetch_label(lname)   labelForm = p4.Fetch_Form('label', lname)
  labelForm['Description'] = 'Created for P4.Net sample'   labelForm['Description'] = 'Created for P4.Net sample'
3 view = ['//guest/shawn_hladky/...']   view = Array[String](['//guest/shawn_hladky/...'])
  labelForm['View'] = view   labelForm.ArrayFields['View'] = view
  res = p4.save_label(labelForm)   res = p4.Save_Form(labelForm)
       
4 if len(p4.errors) > 0:   if res.HasErrors():
    for e in p4.errors: print e       for e in res.Errors: print e
       
  # My list of changes. This is totally arbitrary   # My list of changes. This is totally arbitrary
  changes=['5774', '5680', '5636', '5444']   changes=['5774', '5680', '5636', '5444']
       
  sorted_changes = changes.sort()   sorted_changes = changes.sort()
       
  # dictionary: keyed by file, value = revision   # dictionary: keyed by file, value = revision
  filerevs = {}   filerevs = {}
       
  # spin the description on each file   # spin the description on each file
5 for chg in p4.run_describe('-s', *changes):   for chg in p4.Run('describe', '-s', *changes):
6     depotFiles = chg['depotFile']   depotFiles = chg.ArrayFields['depotFile']
    revisions = chg['rev']       revisions  = chg.ArrayFields['rev']
  for i in range(0, len(depotFiles)):   for i in range(0, len(depotFiles)):
          key,value = depotFiles[i], revisions[i]           key,value = depotFiles[i], revisions[i]
  filerevs[key]=value   filerevs[key]=value
       
  # convert the dictionary to a list   # convert the dictionary to a list
  flist = []   flist = []
  for k,v in filerevs.items():   for k,v in filerevs.items():
  flist.append("%s#%s" % (k,v))   flist.append("%s#%s" % (k,v))
       
  # now I want to run in non-parsed mode    
  p4.disconnect()    
  p4 = P4API.P4()    
7 p4.connect()    
       
  out = p4.run('labelsync', '-l', lname, *flist)   out = p4.RunUnParsed('labelsync', '-l', lname, *flist)
       
  for s in out: print s   for s in out: print s
       
  # delete the label to keep the public depot clean :-)   # delete the label to keep the public depot clean :-)
  p4.run('label', '-d', lname)   p4.RunUnParsed('label', '-d', lname)
       
  p4.disconnect()   p4.Disconnect()

Block 1

This is some overhead required for IronPython. It will load the CLR, and P4.Net.

Block 2

This chunk of code is establishing a connection to the Perforce server. There are a couple things unique to P4.Net worth noting here. Classes in P4.Net are more explicitly named. Here the connection class is named P4Connection. Also, while were talking about naming, P4.Net uses the .Net conventions, and all Method names use cammel case.

Also, note that P4.Net does not need the parse_forms() method. P4.Net is designed to be more statically typed than P4Python/P4Ruby/P4Perl. You use different methods to retrieve tagged vs. untagged output. Therefore, P4.Net auto-manages the connection, and will dynamically switch modes in the native C++ API when needed.

Block 3

There's several things going on in this chunk, so let's break it down line-by-line: