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() |
This is some overhead required for IronPython. It will load the CLR, and P4.Net.
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.
There's several things going on in this chunk, so let's break it down line-by-line: