<html dir="LTR"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Windows-1252" /> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5" /> <title>P4.Net: API Comparisons</title> <xml> </xml> <link rel="stylesheet" type="text/css" href="MSDN.css" /> <style> <!--table {mso-displayed-decimal-separator:"\."; mso-displayed-thousand-separator:"\,";} @page {margin:1.0in .75in 1.0in .75in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-page-orientation:landscape;} .font6 {color:windowtext; font-size:8.0pt; font-weight:400; font-style:normal; text-decoration:none; font-family:"Courier New", monospace; mso-font-charset:0;} .font7 {color:fuchsia; font-size:8.0pt; font-weight:400; font-style:normal; text-decoration:none; font-family:"Courier New", monospace; mso-font-charset:0;} .font8 {color:blue; font-size:8.0pt; font-weight:400; font-style:normal; text-decoration:none; font-family:"Courier New", monospace; mso-font-charset:0;} .font10 {color:#993366; font-size:8.0pt; font-weight:700; font-style:normal; text-decoration:none; font-family:"Courier New", monospace; mso-font-charset:0;} .font11 {color:#993366; font-size:8.0pt; font-weight:700; font-style:normal; text-decoration:none; font-family:"Courier New", monospace; mso-font-charset:0;} tr {mso-height-source:auto;} col {mso-width-source:auto;} br {mso-data-placement:same-cell;} .style0 {mso-number-format:General; text-align:general; vertical-align:bottom; white-space:nowrap; mso-rotate:0; mso-background-source:auto; mso-pattern:auto; color:windowtext; font-size:10.0pt; font-weight:400; font-style:normal; text-decoration:none; font-family:Arial; mso-generic-font-family:auto; mso-font-charset:0; border:none; mso-protection:locked visible; mso-style-name:Normal; mso-style-id:0;} td {mso-style-parent:style0; padding-top:1px; padding-right:1px; padding-left:1px; mso-ignore:padding; color:windowtext; font-size:10.0pt; font-weight:400; font-style:normal; text-decoration:none; font-family:Arial; mso-generic-font-family:auto; mso-font-charset:0; mso-number-format:General; text-align:general; vertical-align:bottom; border:none; mso-background-source:auto; mso-pattern:auto; mso-protection:locked visible; white-space:nowrap; mso-rotate:0;} .xl24 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:.5pt solid windowtext; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl25 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext;} .xl26 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl27 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0;} .xl28 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl29 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext;} .xl30 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl31 {mso-style-parent:style0; color:fuchsia; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:none;} .xl32 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:none; border-right:none; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext;} .xl33 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext;} .xl34 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext;} .xl35 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:none;} .xl36 {mso-style-parent:style0; color:fuchsia; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext;} .xl37 {mso-style-parent:style0; color:fuchsia; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl38 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:none;} .xl39 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:none;} .xl40 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext;} .xl41 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl42 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:none;} .xl43 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext;} .xl44 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext;} .xl45 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:none;} .xl46 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center;} .xl47 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext;} .xl48 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:.5pt solid windowtext; border-right:none; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl49 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl50 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:none; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl51 {mso-style-parent:style0; color:fuchsia; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:none; background:silver; mso-pattern:auto none;} .xl52 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl53 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl54 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl55 {mso-style-parent:style0; color:fuchsia; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:none; background:silver; mso-pattern:auto none;} .xl56 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:none; border-right:none; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl57 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl58 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:none; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl59 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:none; background:silver; mso-pattern:auto none;} .xl60 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:none; background:silver; mso-pattern:auto none;} .xl61 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:none; border-right:.5pt solid windowtext; border-bottom:none; border-left:none; background:silver; mso-pattern:auto none;} .xl62 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; border-top:.5pt solid windowtext; border-right:none; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl63 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:none; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl64 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:none; background:silver; mso-pattern:auto none;} .xl65 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl66 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:none; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl67 {mso-style-parent:style0; color:green; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:none;} .xl68 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl69 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl70 {mso-style-parent:style0; color:#993366; font-size:8.0pt; font-weight:700; font-family:"Courier New", monospace; mso-font-charset:0; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:none; background:silver; mso-pattern:auto none;} .xl71 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; vertical-align:middle; border-top:.5pt solid windowtext; border-right:.5pt solid windowtext; border-bottom:none; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl72 {mso-style-parent:style0; font-size:8.0pt; font-family:"Courier New", monospace; mso-font-charset:0; text-align:center; vertical-align:middle; border-top:none; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext; background:silver; mso-pattern:auto none;} .xl73 {mso-style-parent:style0; text-align:center; vertical-align:middle; border-top:none; border-right:.5pt solid windowtext; border-bottom:.5pt solid windowtext; border-left:.5pt solid windowtext;} --> </style> </head> <body id="bodyID" class="dtBODY"> <div id="nsbanner"> <div id="bannerrow1"> <table class="bannerparthead" cellspacing="0" id="Table1"> <tr id="hdr"> <td class="runninghead">Perforce API for the .Net CLR</td> <td class="product"><img alt="P4.Net" src="p4net.GIF" /></td> </tr> </table> </div> <div id="TitleRow"> <h1 class="dtH1">Comparisons with other Perforce APIs</h1> </div> </div> <div id="nstext"> <H4 class="dtH4">Python Example</H4> <P> The P4Connection class is the main player in P4.Net. This represents a connection to the Perforce server. Every utility that uses P4.Net will have some variation of the following code: </P> <table x:str border=0 cellpadding=0 cellspacing=0 width=817 style='border-collapse: collapse;table-layout:fixed;width:613pt'> <col class=xl46 width=28 style='mso-width-source:userset;mso-width-alt:1024; width:21pt'> <col class=xl29 width=385 style='mso-width-source:userset;mso-width-alt:14080; width:289pt'> <col class=xl30 width=13 style='mso-width-source:userset;mso-width-alt:475; width:10pt'> <col class=xl27 width=391 style='mso-width-source:userset;mso-width-alt:14299; width:293pt'> <tr height=15 style='height:11.25pt'> <td height=15 class=xl24 width=28 style='height:11.25pt;width:21pt'> </td> <td class=xl47 width=385 style='width:289pt'># Standard Python and P4Python</td> <td class=xl26 width=13 style='border-left:none;width:10pt'> </td> <td class=xl67 width=391 style='width:293pt'># IronPython and P4.Net</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl32 style='height:11.25pt'> </td> <td class=xl33> </td> <td class=xl34 style='border-left:none'> </td> <td class=xl35> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl48 style='height:11.25pt;border-top:none'> </td> <td class=xl49 style='border-top:none'> </td> <td class=xl50 style='border-top:none;border-left:none'> </td> <td class=xl51 style='border-top:none'>import<font class="font6"> clr</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt' x:num>1</td> <td class=xl53> </td> <td class=xl54 style='border-left:none'> </td> <td class=xl55>from<font class="font6"> System </font><font class="font7">import</font><font class="font6"> Array, String</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl56 style='height:11.25pt'> </td> <td class=xl57> </td> <td class=xl58 style='border-left:none'> </td> <td class=xl59>clr.AddReferenceToFile('<font class="font8">P4API.dll</font><font class="font6">')</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl36> </td> <td class=xl37 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl36>import<font class="font6"> p4 as P4API</font></td> <td class=xl37 style='border-left:none'> </td> <td class=xl31>import<font class="font6"> P4API</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl36> </td> <td class=xl37 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl48 style='height:11.25pt'> </td> <td class=xl49>p4 = P4API.P4()</td> <td class=xl50 style='border-left:none'> </td> <td class=xl60>p4 = P4API.P4Connection()</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt' x:num>2</td> <td class=xl53>p4.parse_forms()</td> <td class=xl54 style='border-left:none'> </td> <td class=xl61> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl56 style='height:11.25pt'> </td> <td class=xl57>p4.connect()</td> <td class=xl58 style='border-left:none'> </td> <td class=xl59>p4.Connect()</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29>lname = '<font class="font8">P4NetTestingSample</font><font class="font6">'</font></td> <td class=xl30 style='border-left:none'> </td> <td class=xl38>lname = '<font class="font8">P4NetTestingSample</font><font class="font6">'</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl40># build my label</td> <td class=xl41 style='border-left:none'> </td> <td class=xl42># build my label</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl48 style='height:11.25pt'> </td> <td class=xl49>labelForm = p4.fetch_label(lname)</td> <td class=xl50 style='border-left:none'> </td> <td class=xl60>labelForm = p4.Fetch_Form('<font class="font8">label</font><font class="font6">', lname)</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt'> </td> <td class=xl53>labelForm['<font class="font8">Description</font><font class="font6">'] = '</font><font class="font8">Created for P4.Net sample</font><font class="font6">'</font></td> <td class=xl54 style='border-left:none'> </td> <td class=xl61>labelForm['<font class="font8">Description</font><font class="font6">'] = '</font><font class="font8">Created for P4.Net sample</font><font class="font6">'</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt' x:num>3</td> <td class=xl53>view = ['<font class="font8">//guest/shawn_hladky/...</font><font class="font6">']</font></td> <td class=xl54 style='border-left:none'> </td> <td class=xl61>view = Array[String](['<font class="font8">//guest/shawn_hladky/...</font><font class="font6">'])</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt'> </td> <td class=xl53>labelForm['<font class="font8">View</font><font class="font6">'] = view</font></td> <td class=xl54 style='border-left:none'> </td> <td class=xl61>labelForm.ArrayFields['<font class="font8">View</font><font class="font6">'] = view</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl56 style='height:11.25pt'> </td> <td class=xl57>res = p4.save_label(labelForm)</td> <td class=xl58 style='border-left:none'> </td> <td class=xl59>res = p4.Save_Form(labelForm)</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td rowspan=2 height=30 class=xl71 style='border-bottom:.5pt solid black; height:22.5pt' x:num>4</td> <td class=xl69 style='border-left:none'>if<font class="font6"> len(p4.errors) > 0:</font></td> <td class=xl50 style='border-left:none'> </td> <td class=xl70>if<font class="font6"> res.HasErrors():</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl57 style='height:11.25pt;border-left:none'><span style='mso-spacerun:yes'> </span><font class="font11">for</font><font class="font6"> e </font><font class="font11">in</font><font class="font6"> p4.errors: print e</font></td> <td class=xl58 style='border-left:none'> </td> <td class=xl59><span style='mso-spacerun:yes'> </span><font class="font11">for</font><font class="font6"> e </font><font class="font11">in</font><font class="font6"> res.Errors: print e</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl40># My list of changes.<span style='mso-spacerun:yes'> </span>This is totally arbitrary</td> <td class=xl41 style='border-left:none'> </td> <td class=xl42># My list of changes.<span style='mso-spacerun:yes'> </span>This is totally arbitrary</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29>changes=['<font class="font8">5774</font><font class="font6">', '</font><font class="font8">5680</font><font class="font6">', '</font><font class="font8">5636</font><font class="font6">', '</font><font class="font8">5444</font><font class="font6">']</font></td> <td class=xl30 style='border-left:none'> </td> <td class=xl38>changes=['<font class="font8">5774</font><font class="font6">', '</font><font class="font8">5680</font><font class="font6">', '</font><font class="font8">5636</font><font class="font6">', '</font><font class="font8">5444</font><font class="font6">']</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29>sorted_changes = changes.sort()</td> <td class=xl30 style='border-left:none'> </td> <td class=xl38>sorted_changes = changes.sort()</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl40># dictionary: keyed by file, value = revision</td> <td class=xl41 style='border-left:none'> </td> <td class=xl42># dictionary: keyed by file, value = revision</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29>filerevs = {}</td> <td class=xl30 style='border-left:none'> </td> <td class=xl38>filerevs = {}</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl40># spin the description on each file</td> <td class=xl41 style='border-left:none'> </td> <td class=xl42># spin the description on each file</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl62 style='height:11.25pt' x:num>5</td> <td class=xl68>for<font class="font6"> chg </font><font class="font10">in</font><font class="font6"> p4.run_describe('</font><font class="font8">-s</font><font class="font6">', *changes):</font></td> <td class=xl63 style='border-left:none'> </td> <td class=xl64>for<font class="font6"> chg </font><font class="font10">in</font><font class="font6"> p4.Run('</font><font class="font8">describe</font><font class="font6">', '</font><font class="font8">-s</font><font class="font6">', *changes):</font></td> </tr> <tr height=15 style='height:11.25pt'> <td rowspan=2 height=30 class=xl71 style='border-bottom:.5pt solid black; height:22.5pt;border-top:none' x:num>6</td> <td class=xl49 style='border-top:none;border-left:none'><span style='mso-spacerun:yes'> </span>depotFiles = chg['<font class="font8">depotFile</font><font class="font6">']</font></td> <td class=xl50 style='border-top:none;border-left:none'> </td> <td class=xl60 style='border-top:none'><span style='mso-spacerun:yes'> </span>depotFiles = chg.ArrayFields['<font class="font8">depotFile</font><font class="font6">']</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl57 style='height:11.25pt;border-left:none'><span style='mso-spacerun:yes'> </span>revisions<span style='mso-spacerun:yes'> </span>= chg['<font class="font8">rev</font><font class="font6">']</font></td> <td class=xl58 style='border-left:none'> </td> <td class=xl59><span style='mso-spacerun:yes'> </span>revisions<span style='mso-spacerun:yes'> </span>= chg.ArrayFields['<font class="font8">rev</font><font class="font6">']</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl24 style='height:11.25pt;border-top:none'> </td> <td class=xl25 style='border-top:none'><span style='mso-spacerun:yes'> </span><font class="font10">for</font><font class="font6"> i </font><font class="font10">in</font><font class="font6"> range(0, len(depotFiles)):</font></td> <td class=xl26 style='border-top:none;border-left:none'> </td> <td class=xl39 style='border-top:none'><span style='mso-spacerun:yes'> </span><font class="font10">for</font><font class="font6"> i </font><font class="font10">in</font><font class="font6"> range(0, len(depotFiles)):</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29><span style='mso-spacerun:yes'> </span>key,value = depotFiles[i], revisions[i]</td> <td class=xl30 style='border-left:none'> </td> <td class=xl38><span style='mso-spacerun:yes'> </span>key,value = depotFiles[i], revisions[i]</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29><span style='mso-spacerun:yes'> </span>filerevs[key]=value</td> <td class=xl30 style='border-left:none'> </td> <td class=xl38><span style='mso-spacerun:yes'> </span>filerevs[key]=value</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl40># convert the dictionary to a list</td> <td class=xl41 style='border-left:none'> </td> <td class=xl42># convert the dictionary to a list</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29>flist = []</td> <td class=xl41 style='border-left:none'> </td> <td class=xl38>flist = []</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl43>for<font class="font6"> k,v </font><font class="font10">in</font><font class="font6"> filerevs.items():</font></td> <td class=xl30 style='border-left:none'> </td> <td class=xl45>for<font class="font6"> k,v </font><font class="font10">in</font><font class="font6"> filerevs.items():</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29><span style='mso-spacerun:yes'> </span>flist.append("%s#%s" % (k,v))</td> <td class=xl30 style='border-left:none'> </td> <td class=xl38><span style='mso-spacerun:yes'> </span>flist.append("%s#%s" % (k,v))</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl32 style='height:11.25pt'> </td> <td class=xl33> </td> <td class=xl34 style='border-left:none'> </td> <td class=xl35> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl48 style='height:11.25pt;border-top:none'> </td> <td class=xl65 style='border-top:none'># now I want to run in non-parsed mode</td> <td class=xl66 style='border-top:none;border-left:none'> </td> <td class=xl60 style='border-top:none'> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt'> </td> <td class=xl53>p4.disconnect()</td> <td class=xl54 style='border-left:none'> </td> <td class=xl61> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt'> </td> <td class=xl53>p4 = P4API.P4()</td> <td class=xl54 style='border-left:none'> </td> <td class=xl61> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt' x:num>7</td> <td class=xl53>p4.connect()</td> <td class=xl54 style='border-left:none'> </td> <td class=xl61> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl52 style='height:11.25pt'> </td> <td class=xl53> </td> <td class=xl54 style='border-left:none'> </td> <td class=xl61> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl56 style='height:11.25pt'> </td> <td class=xl57>out = p4.run('<font class="font8">labelsync</font><font class="font6">', '</font><font class="font8">-l</font><font class="font6">', lname, *flist)</font></td> <td class=xl58 style='border-left:none'> </td> <td class=xl59>out = p4.RunUnParsed('<font class="font8">labelsync</font><font class="font6">', '</font><font class="font8">-l</font><font class="font6">', lname, *flist)</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl43>for<font class="font6"> s </font><font class="font10">in</font><font class="font6"> out: </font><font class="font10">print</font><font class="font6"> s</font></td> <td class=xl44 style='border-left:none'> </td> <td class=xl45>for<font class="font6"> s </font><font class="font10">in</font><font class="font6"> out: </font><font class="font10">print</font><font class="font6"> s</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl40># delete the label to keep the public depot clean :-)</td> <td class=xl41 style='border-left:none'> </td> <td class=xl42># delete the label to keep the public depot clean :-)</td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29>p4.run('<font class="font8">label</font><font class="font6">', '</font><font class="font8">-d</font><font class="font6">', lname)</font></td> <td class=xl30 style='border-left:none'> </td> <td class=xl38>p4.RunUnParsed('<font class="font8">label</font><font class="font6">', '</font><font class="font8">-d</font><font class="font6">', lname)</font></td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl28 style='height:11.25pt'> </td> <td class=xl29> </td> <td class=xl30 style='border-left:none'> </td> <td class=xl38> </td> </tr> <tr height=15 style='height:11.25pt'> <td height=15 class=xl32 style='height:11.25pt'> </td> <td class=xl33>p4.disconnect()</td> <td class=xl34 style='border-left:none'> </td> <td class=xl35>p4.Disconnect()</td> </tr> <![if supportMisalignedColumns]> <tr height=0 style='display:none'> <td width=28 style='width:21pt'></td> <td width=385 style='width:289pt'></td> <td width=13 style='width:10pt'></td> <td width=391 style='width:293pt'></td> </tr> <![endif]> </table> <H4 class="dtH4">Interpreting Output</H4> <P>Although the arguments to run Perforce commands are similar to the command line interface, the way we interpret the output can be dramatically different. This is where the power of the API comes in. In the example above, the result changes is of type P4Recordset. This is a rich object in P4.Net that provides a parsed version of the command output. At the core of the P4Recordset is the enumerable collection of P4Records. Each P4Record generally represents all the data on one lines output from the command-line. P4Records are dictionary-like objects allowing you to access fields by a key:</P> <pre class="code" language="C#" escaped="true"> // we used the -m1 switch, so we know there is just one record returned. P4Record change = changes[0]; int changeNumber = int(change["change"]); </pre> <P> It can also be accessed using the Fields property: </P> <pre class="code" language="C#" escaped="true"> int changeNumber = int(change.Fields["change"]); </pre> <P> So, how do you know what keys are available? Well, it depends on the command run, the server version, and sometimes the arguments to the command. The RecordsetViewer sample application is a great tool for determining the keys that are returned from a command. In addition to RecordsetViewer, you can use the -Ztag global option of the p4 command line client to see how the output is parsed. At runtime, you can access all of the keys returned from the Fields.Keys property: </P> <pre class="code" language="C#" escaped="true"> foreach (string key in change.Fields.Keys) { Console.WriteLine("{0} : {1}", key, change[key]); } </pre> <P> In addition to the normal parsed output, there may be warnings, errors, and informational messages from the command that are not parsed (i.e. it will be the same English message returned at the command line). Again, the RecordsetViewer sample application can help you identify all the elements returned in a P4Recordset for a particular command. At runtime, we can access those messages as shown below: </P> <pre class="code" language="C#" escaped="true"> foreach (string e in changes.Errors) Console.WriteLine(e); foreach (string e in changes.Warnings) Console.WriteLine(e); foreach (string e in changes.Messages) Console.WriteLine(e); </pre> <P> Not all fields have a single string for a value. Some commands return arrays of strings in a field. To access these values at runtime, you can use the ArrayFields property of the P4Record object. </P> <pre class="code" language="C#" escaped="true"> P4Recordset describes = p4.Run("describe", "-s", "1234"); //One changelist, one record... at least if that changelist exists P4Record describe = describes[0]; Console.WriteLine("Changelist: {0}", describe["Change"]); Console.WriteLine("Files:"); foreach( int i=0; i< describe.ArrayFields["depotFile"].Length; i++) { Console.WriteLine(" {0}#{1}", describe.ArrayFields["depotFile"][i], describe.ArrayFields["rev"][i]); } </pre> <P> In the preceding examples, we only looked at the first record in the recordset. However many commands will return multiple records. We can enumerate them as follows: </P> <pre class="code" language="C#" escaped="true"> // This example enumerates all the files in a folder hierarchy, and prints the ones // that are deleted at the head revision. (Note, theres a more efficient way to do this.) P4Recordset fstats = p4.Run("fstat", "//depot/path/..."); foreach( P4Record stat in fstats) { if (stat["headAction"] == "delete") { Console.WriteLine(stat["depotFile"]); } } </pre> <H4 class="dtH4">Unparsed Output</H4> <P> Not all commands support the parsed output. In that case, all of the output will be simple English statements, just as the command line outputs. Again, this is highly dependant on the version of the Perforce server. You can see the Perforce C++ API release notes for your version to see if the parsed output is supported for a given command (referred to as tagged in the C++ documentation). </P><P> While you can access these messages from the P4Recordset.Messages property, its often easier to use the RunUnParsed method of the P4Connection class, which returns a P4UnParsedRecordset object. This is similar to the P4Recordset object, except there are no Fields and ArrayFields properties, and the default enumerator is the Messages array. </P><P> RunUnParsed can also help ensure forward compatibility with newer server versions. In recent releases, many commands that previously only supported the unparsed output, now support parsed output. If the server was upgraded, code that called Run, would still look at the P4Recordset.Messages. However the output from the upgrades server would now be available only in Fields and ArrayFields. By using RunUnParsed, you are guaranteed to get the raw strings from the server. </P> <P/> <H4 class="dtH4">Forms</H4> <P> Another major object in P4.Net is the P4Form object. Perforce forms are the text files that pop up in an editor when a "form" command is run. They have fields that are specially formatted in the file, and you can view or change these fields by following the formatting standards. You can see this behavior in the command line: <pre class="code" escaped="true" > c:\> p4 user </pre> <P> In P4.Net, you do not have to worry about this special formatting. The fields are read/modified using Fields and ArrayFields properties (P4Form inherits P4Record). The only trick is you need to use the methods Fetch_Form and Save_Form:</P> <pre class="code" language="C#" escaped="true"> // Change the root of the current workspace. P4Connection p4 = new P4Connection(); p4.Connect(); P4Form client = p4.Fetch_Form("client"); client["Root"] = @"c:\p4"; p4.Save_Form(client); p4.Disconnect(); </pre> <P/><P/> <H4 class="dtH4">Submitting Files</H4> <P> In P4.Net, theres no straight-forward way to submit the default pending changelist. This is by design. If the client workspace has opened files in the default changelist before any P4.Net automation runs, those files will "come along for the ride" when you submit the default changelist. If the user has a JobView set, all jobs in that JobView will automatically be fixed when you submit that default changelist. Both of those behaviors are almost never desired, and Ive found many scripts that have those bugs. </P> <P> So, how do you submit files in P4.Net? The key is to create a named pending changelist before opening any files. Then add the switches "-c", and "1234" (1234 is the changelist number) to all commands that are opening files. This is quite simple using the P4PendingChangelist object: </P> <pre class="code" language="C#" escaped="true"> P4Connection p4 = new P4Connection(); p4.Connect(); P4PendingChangelist cl = p4.CreatePendingChangelist("My New Changelist\nVery, Very bad description!\nShame on me!"); p4.Run("edit", "-c", cl.Number.ToString(), "//depot/path/foo.cs", "//depot/path/bar.cs"); // Do something to manipulate the files cl.Submit(); p4.Disconnect(); </pre> <H4 class="dtH4">Connections Revisited.</H4> <P> Finally, lets look at the connection properties. You may be wondering how the P4Connection object knows which Port/Client/User to use. It turns out P4.Net will use the default properties using the same logic as all Perforce clients (see Technote 36 and the P4 User Guide). Of course, any of these can be explicitly overridden on the P4Connection object. However, Ive found using the built-in Perforce configuration system to be much more portable and maintainable than explicitly defining the configuration for each custom tool. </P> <P/><P/> <div id="footer"> <p> </p> </div> </div> </body> </html>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 5830 | Shawn Hladky | P4.Net: reorg to support release branches | ||
#4 | 5824 | Shawn Hladky | P4.Net: Last bits of documentation for 0.9 | ||
#3 | 5815 | Shawn Hladky |
P4.Net: more documentation will build strong-named assemblies now. |
||
#2 | 5812 | Shawn Hladky | P4.Net: More documentation. | ||
#1 | 5798 | Shawn Hladky |
P4.Net... still not ready for beta Added license to all files Added several doc files Misc bugs |