PageRenderTime 72ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_2_0/Tutorial/Tutorial.htm

#
HTML | 2996 lines | 2969 code | 26 blank | 1 comment | 0 complexity | 1623e1b5d96dc0645c03a305c88dde4e MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. <html xmlns="http://www.w3.org/1999/xhtml">
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
  4. <title>IronPython Tutorial</title>
  5. <!--link rel="stylesheet" type="text/css" href="../Doc/IronPython.css"-->
  6. <style type="text/css">
  7. p.AntiVerify { display : none; }
  8. p.Code-Background { color : gray; }
  9. p.Code-Highlighted { color : gray; }
  10. p.CodeSample { color:blue; }
  11. p.DOSCommand { color:green; }
  12. p.ExceptionExample { color:green; }
  13. p.ExceptionOutput {display : none; }
  14. p.HiddenCode { display : none; }
  15. p.HiddenOutput {display : none; }
  16. p.LooseVerify { display : none; }
  17. p.Stepnonumbering { text-indent: 2em; }
  18. p.TypedExample { color : green; }
  19. p.UserCode { color:green; }
  20. </style>
  21. </head>
  22. <body lang="EN-US">
  23. <div class="Section1">
  24. <p class="Title1">IronPython Tutorial</p>
  25. <p class="Title2">A tour of Python on .NET</p>
  26. <p class="Title2">&nbsp;</p>
  27. <hr />
  28. <p class="CopyrightText">Information in this document is subject to change without
  29. notice. The example companies, organizations, products, people, and events depicted
  30. herein are fictitious. No association with any real company, organization, product,
  31. person or event is intended or should be inferred. Complying with all applicable
  32. copyright laws is the responsibility of the user. Without limiting the rights
  33. under copyright, no part of this document may be reproduced, stored in or introduced
  34. into a retrieval system, or transmitted in any form or by any means (electronic,
  35. mechanical, photocopying, recording, or otherwise), or for any purpose, without
  36. the express written permission of Microsoft Corporation.</p>
  37. <p class="CopyrightText">&nbsp;</p>
  38. <p class="CopyrightText">Microsoft may have patents, patent applications, trademarked,
  39. copyrights, or other intellectual property rights covering subject matter in
  40. this document. Except as expressly provided in any written license agreement
  41. from Microsoft, the furnishing of this document does not give you any license
  42. to these patents, trademarks, copyrights, or other intellectual property.</p>
  43. <p class="CopyrightText">&nbsp;</p>
  44. <p class="CopyrightText">Š Microsoft Corporation. All rights reserved.</p>
  45. <p class="CopyrightText">&nbsp;</p>
  46. <p class="CopyrightText">Microsoft, MS-DOS, MS, Windows, Windows NT, MSDN, Active
  47. Directory, BizTalk, SQL Server, SharePoint, Outlook, PowerPoint, FrontPage,
  48. Visual Basic, Visual C++, Visual J++, Visual InterDev, Visual SourceSafe, Visual
  49. C#, Visual J#,&nbsp; and Visual Studio are either registered trademarks or trademarks
  50. of Microsoft Corporation in the U.S.A. and/or other countries.</p>
  51. <p class="CopyrightText">&nbsp;</p>
  52. <p class="CopyrightText">Other product and company names herein may be the trademarks of their respective owners.</p>
  53. <hr />
  54. <p class="ContentsHeading">Contents</p>
  55. <p class="Toc1"><a href="#Intro">Introduction</a></p>
  56. <p class="Toc1">Tutorial 1: <a href="#T1">Basic IronPython</a></p>
  57. <p class="Toc2">Exercise 1: <a href="#T1.1">The IronPython interactive console</a></p>
  58. <p class="Toc3">Task 1: <a href="#T1.1.1">IronPython console</a></p>
  59. <p class="Toc3">Task 2: <a href="#T1.1.2">Built-in modules and interactive exploration</a></p>
  60. <p class="Toc3">Task 3: <a href="#T1.1.3">External Python modules</a></p>
  61. <p class="Toc2">Exercise 2: <a href="#T1.2">Using the standard .NET libraries from IronPython</a></p>
  62. <p class="Toc3">Task 1: <a href="#T1.2.1">Basic .NET library use</a></p>
  63. <p class="Toc3">Task 2: <a href="#T1.2.2">Working with .NET classes</a></p>
  64. <p class="Toc3">Task 3: <a href="#T1.2.3">Generics</a></p>
  65. <p class="Toc2">Exercise 3: <a href="#T1.3">Loading .NET libraries</a></p>
  66. <p class="Toc3">Task 1: <a href="#T1.3.1">Using System.Xml - AddReference</a></p>
  67. <p class="Toc3">Task 2: <a href="#T1.3.2">Mapack - Loading the .NET libraries - AddReferenceToFile</a></p>
  68. <p class="Toc2">Exercise 4: <a href="#T1.4">Obtaining and Using Python Standard Library</a></p>
  69. <p class="Toc3">Task 1: <a href="#T1.4.1">Configuring IronPython to use the Python standard library</a></p>
  70. <p class="Toc1">Tutorial 2: <a href="#T2">Advanced IronPython</a></p>
  71. <p class="Toc2">Exercise 1: <a href="#T2.1">Events and Delegates</a></p>
  72. <p class="Toc3">Task 1: <a href="#T2.1.1">File System Watcher</a></p>
  73. <p class="Toc3">Task 2: <a href="#T2.1.2">Improving the event handler</a></p>
  74. <p class="Toc3">Task 3: <a href="#T2.1.3">Defining events in Python</a></p>
  75. <p class="Toc2">Exercise 2: <a href="#T2.2">Windows Forms</a></p>
  76. <p class="Toc3">Task 1: <a href="#T2.2.1">Simple Windows Forms application</a></p>
  77. <p class="Toc2">Exercise 3: <a href="#T2.3">Windows Presentation Foundation (Avalon)</a></p>
  78. <p class="Toc3">Task 1: <a href="#T2.3.1">Simple Avalon Application</a></p>
  79. <p class="Toc3">Task 2: <a href="#T2.3.2">Avalon calculator</a></p>
  80. <p class="Toc1">Tutorial 3: <a href="#T3">IronPython and COM interoperability</a></p>
  81. <p class="Toc2">Exercise 1: <a href="#T3.1">Merlin the Wizard</a></p>
  82. <p class="Toc3">Task 1: <a href="#T3.1.1">Creating COM interop assemblies</a></p>
  83. <p class="Toc3">Task 2: <a href="#T3.1.2">Using COM objects from IronPython</a></p>
  84. <p class="Toc2">Exercise 2: <a href="#T3.2">Use Word for Spell Checking</a></p>
  85. <p class="Toc3">Task 1: <a href="#T3.2.1">Accessing Word and Checking
  86. Spelling</a></p>
  87. <p class="Toc3">Task 2: <a href="#T3.2.2">Use Windows Form Dialog to Correct
  88. Spelling</a></p>
  89. <p class="Toc1">Tutorial 4: <a href="#T4">Debugging IronPython program</a></p>
  90. <p class="Toc2">Exercise 1: <a href="#T4.1">Debugging IronPython programs</a></p>
  91. <p class="Toc3">Task 1: <a href="#T4.1.1">Debugging IronPython programs using Microsoft CLR Debugger</a></p>
  92. <p class="Toc1">Tutorial 5: <a href="#T5">Extending IronPython</a></p>
  93. <p class="Toc2">Exercise 1: <a href="#T5.1">Extending using C#</a></p>
  94. <p class="Toc3">Task 1: <a href="#T5.1.1">Implementing simple class - constructor and ToString</a></p>
  95. <p class="Toc3">Task 2: <a href="#T5.1.2">Making the object enumerable</a></p>
  96. <p class="Toc3">Task 3: <a href="#T5.1.3">Adding custom operator</a></p>
  97. <p class="Toc3">Task 4: <a href="#T5.1.4">Adding delegate</a></p>
  98. <p class="Toc2">Exercise 2: <a href="#T5.2">Extending using Visual Basic.NET</a></p>
  99. <p class="Toc3">Task 1: <a href="#T5.2.1">Implementing simple class - constructor and ToString</a></p>
  100. <p class="Toc3">Task 2: <a href="#T5.2.2">Making the object enumerable</a></p>
  101. <p class="Toc3">Task 3: <a href="#T5.2.3">Adding custom operator</a></p>
  102. <p class="Toc3">Task 4: <a href="#T5.2.4">Adding delegate</a></p>
  103. <p class="Toc1">Tutorial 6: <a href="#T7">Using Visual Studio to Edit .py
  104. Files and Debug Them</a></p>
  105. <p class="Toc2">Exercise 1: <a href="#T6.1">Setting up Visual Studio for
  106. IronPython Debugging</a></p>
  107. <p class="Toc3">Task 1: <a href="#T6.1.1">Setting up Visual Studio for
  108. IronPython Debugging</a></p>
  109. </div>
  110. <div class="Section2">
  111. <h1><a name="Intro">Introduction</a></h1>
  112. <p class="Normal">IronPython is the .NET implementation of the Python programming language
  113. (<a href="http://www.python.org">www.python.org</a>).&nbsp; It's a dynamically typed language with support
  114. for many programming paradigms such as object-oriented programming, and also allows
  115. you to seamlessly use .NET code.</p>
  116. <p class="Normal">&nbsp;</p>
  117. <p class="Normal">The goal of this tutorial is to quickly
  118. familiarize you with the IronPython console, and to show you how to make use of the extensive .NET libraries available.&nbsp;
  119. This tutorial also shows you how to get started in more specialized areas
  120. such as interoperating with COM, extending IronPython with C#, and embedding
  121. IronPython.&nbsp; This tutorial is NOT meant to be an introduction to Python
  122. itself, and if you're looking for that, we recommend you start with the
  123. tutorial at <a href="http://docs.python.org/tut/tut.html">www.python.org</a>
  124. or the often recommended book <i>Learning Python</i> by Mark Lutz and David
  125. Ascher. For an introduction to both the Python language as well as the unique
  126. capabilities of IronPython, we recommend <i>IronPython in Action</i> by
  127. Michael Foord<br><br>
  128. Some of the exercises in this tutorial require prerequisites.&nbsp; The prerequisites to successfully complete the whole tutorial are:</p>
  129. <ul type="disc">
  130. <li class="Normal">Microsoft .NET Framework Version 3.5
  131. <ul type="circle">
  132. <li class="Normal">Required to run IronPython on Windows Vista.</li>
  133. <li class="Normal">Microsoft .NET Framework Version 3.0 SP1 or higher needed for Windows operating systems released prior to Windows Vista</li>
  134. <li class="Normal">Download from
  135. <a href="http://www.microsoft.com/downloads/details.aspx?familyid=333325FD-AE52-4E35-B531-508D977D32A6&displaylang=en ">
  136. here</a>.</li>
  137. </ul>
  138. </li>
  139. </ul>
  140. <ul>
  141. <li class="Normal">Visual Studio 2005 or 2008<ul type="circle">
  142. <li class="Normal">Required for &quot;Setting up Visual Studio for IronPython Debugging&quot; tutorials.</li>
  143. </ul>
  144. </li>
  145. </ul>
  146. <ul>
  147. <li class="Normal">Microsoft Word<ul type="circle">
  148. <li class="Normal">Required for &quot;Use Word for Spell Checking&quot; and &quot;Merlin the Wizard&quot; tutorials.</li>
  149. </ul>
  150. </li>
  151. </ul>
  152. <ul>
  153. <li class="Normal"><a name="Mapack">Mapack</a> (example assembly found
  154. on the internet)<ul>
  155. <li>Required for the &quot;Basic IronPython&quot; tutorial, exercise &quot;Loading .NET
  156. Libraries&quot;.</li>
  157. <li>Download Mapack from
  158. <a href="http://www.lutzroeder.com/dotnet/">here</a> (direct link
  159. to the Mapack.zip download is
  160. <a href="http://www.lutzroeder.com/dotnet/Download.aspx?File=Mapack">
  161. here</a>).</li>
  162. <li>Extract Mapack.dll from the zip file directly into the Tutorial
  163. directory.</li>
  164. </ul>
  165. </li>
  166. </ul>
  167. <p class="Normal">&nbsp;</p>
  168. <p class="Body">Visual Studio 2005 or 2008 can be used in place of the Microsoft .NET
  169. Framework Version 2.0 and the .NET Framework 2.0 Software Development Kit (SDK).
  170. Since Visual Studio installs both the .NET Framework 2.0 and the .NET Framework
  171. SDK, there is no need to install those explicitly if you have Visual Studio
  172. 2005 available. Visual Studio 2008 also installs .NET Framework 3.5. </p>
  173. <p class="Body">This tutorial also assumes that you will launch the
  174. IronPython console (c:\ironpython\ipy.exe) from the tutorial directory.&nbsp;
  175. When the tutorials direct you to start the IronPython console from the tutorial directory,
  176. you should change to the tutorial directory (&gt;cd c:\ironpython\tutorial)
  177. and launch the console with the tutorial as your working directory (&gt;..\ipy.exe). If you
  178. install IronPython via the MSI installer, it will install to c:\Program Files\IronPython 2.0
  179. by default. In this scenario, you can still run the tutorial, but several tutorials require
  180. write access to the tutorial directory, which will require administrator access if IronPython
  181. is installed under Program Files.</p>
  182. <p class="Body">&nbsp;</p>
  183. <h1><a name="T1">Tutorial 1: Basic IronPython</a></h1>
  184. <p class="Body">The emphasis of this tutorial is on the basic interaction with
  185. the IronPython interpreter and using the interactive environment to explore
  186. the .NET libraries.</p>
  187. <p class="Body">Estimated time to complete this tutorial: <b>30 minutes</b></p>
  188. <p class="Body">The objective of this tutorial is to launch the IronPython interpreter,
  189. explore the environment of the interactive console and use IronPython to interact
  190. with .NET libraries.</p>
  191. <p class="Body">The exercises in this tutorial are:</p>
  192. <ul>
  193. <li>
  194. <p class="ExerciseList"><a href="#T1.1">The IronPython interactive console</a></p>
  195. </li>
  196. <li>
  197. <p class="ExerciseList"><a href="#T1.2">Using the standard .NET libraries
  198. from IronPython</a></p>
  199. </li>
  200. <li>
  201. <p class="ExerciseList"><a href="#T1.3">Loading additional .NET libraries</a></p>
  202. </li>
  203. </ul>
  204. <h2><a name="T1.1">Exercise 1: The IronPython interactive console</a></h2>
  205. <p class="Body">In this exercise, you will start the IronPython interactive
  206. interpreter and perform simple tasks to become acquainted with the IronPython
  207. environment.</p>
  208. <p class="Normal">If you are familiar with using the Python interactive console,
  209. the import statement and exploring the Python interactive environment using
  210. dir() function and __doc__ attribute, you can <a href="#T1.2">skip this exercise</a>.</p>
  211. <h3><a name="T1.1.1">Task 1: IronPython console</a></h3>
  212. <ol>
  213. <li>
  214. <p class="Step">Start the IronPython console from the tutorial directory
  215. by changing to the tutorial directory (&gt;cd c:\ironpython\tutorial) and
  216. launching the console c:\ironpython\ipy.exe executable (&gt;..\ipy.exe).&nbsp;
  217. This is how you should always launch the console for the tutorials, but
  218. from now on, we'll just direct you to &quot;start the IronPython console from
  219. the tutorial directory&quot;.</p>
  220. </li>
  221. </ol>
  222. <p class="Code-Highlighted">IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053<br />
  223. Copyright (c) Microsoft Corporation. All rights reserved.</p>
  224. <p class="Code-Highlighted">&gt;&gt;&gt; _</p>
  225. <ol start="2">
  226. <li>
  227. <p class="Step">Execute simple statements listed below.&nbsp; After each statement IronPython prints the result, if any, and awaits more input.&nbsp;
  228. (The input line starting with &quot;for&quot; requires an extra return or enter
  229. key press because the interpreter prompts for more statements in the
  230. 'for' loop.)</p>
  231. </li>
  232. </ol>
  233. <p class="TypedExample">2+2</p>
  234. <p class="TypedExample">print &quot;Hello World!&quot;</p>
  235. <p class="TypedExample">for i in range(3): print i</p>
  236. <p class="TypedExample">x = 10</p>
  237. <p class="TypedExample">print x</p>
  238. <p class="Stepnonumbering">&nbsp;</p>
  239. <p class="Stepnonumbering">After this step, the console window will contain
  240. the following text:</p>
  241. <p class="Code-Highlighted">&gt;&gt;&gt; 2+2</p>
  242. <p class="Code-Background">4</p>
  243. <p class="Code-Highlighted">&gt;&gt;&gt; print &quot;Hello World!&quot;</p>
  244. <p class="Code-Background">Hello World!</p>
  245. <p class="Code-Highlighted">&gt;&gt;&gt; for i in range(3): print i</p>
  246. <p class="Code-Highlighted">...</p>
  247. <p class="Code-Background">0<br />
  248. 1<br />
  249. 2</p>
  250. <p class="Code-Highlighted">&gt;&gt;&gt; x = 10<br />
  251. &gt;&gt;&gt; print x</p>
  252. <p class="Code-Background"></p>
  253. <p class="Code-Background">10</p>
  254. <p class="Code-Highlighted">&gt;&gt;&gt; </p>
  255. <ol start="3">
  256. <li>
  257. <p class="Step">IronPython console supports multi-line statements, often
  258. used by function definitions.&nbsp; IronPython prompts for additional lines of
  259. multi-line statements using:</p>
  260. </li>
  261. </ol>
  262. <p class="Code-Highlighted">...</p>
  263. <p class="Code-Background"></p>
  264. <p class="Stepnonumbering">Unlike C# or Java, where blocks of code are grouped by curly brackets "{...}",
  265. blocks of code in Python are grouped based on their level of indentation.&nbsp; Every new block of code
  266. must be indented one more level than the previous block of code.&nbsp; Blocks of code are used for
  267. function and class definitions as well as 'if' statements and loops. </p>
  268. <p class="Stepnonumbering">Define the &quot;add&quot; function (note, you
  269. need to enter spaces before the 'return' statement):</p>
  270. <p class="TypedExample">def add(a, b):<br>
  271. &nbsp;&nbsp;&nbsp; return a + b</p>
  272. <p class="Stepnonumbering">To complete the function definition, press Enter
  273. once more at this point</p>
  274. <p class="TypedExample">add(3, 2)</p>
  275. <p class="TypedExample">add(&quot;Iron&quot;, &quot;Python&quot;)</p>
  276. <p class="Stepnonumbering">After this step, the console contents will be:</p>
  277. <p class="Code-Highlighted">&gt;&gt;&gt; def add(a, b):<br />
  278. ...&nbsp;&nbsp;&nbsp;&nbsp; return a + b<br />
  279. ...<br />
  280. &gt;&gt;&gt; add(3, 2)</p>
  281. <p class="Code-Background">5</p>
  282. <p class="Code-Highlighted">&gt;&gt;&gt; add(&quot;Iron&quot;, &quot;Python&quot;)</p>
  283. <p class="Code-Background">&#39;IronPython&#39;</p>
  284. <p class="Code-Highlighted">&gt;&gt;&gt; </p>
  285. <p class="Step">&nbsp;</p>
  286. <ol start="4">
  287. <li>
  288. <p class="Step">To exit the IronPython interactive console, type Ctrl+Z and Enter (alternatively,
  289. press F6 followed by Enter).</p>
  290. </li>
  291. </ol>
  292. <p class="TypedExample">^Z</p>
  293. <h3><a name="T1.1.2">Task 2: Built-in modules and interactive exploration</a></h3>
  294. <ol>
  295. <li>
  296. <p class="Step">Start the IronPython console from the tutorial directory
  297. (see <a href="#Intro">Introduction</a> for details).</p>
  298. </li>
  299. <li>
  300. <p class="Step">Using the built-in dir() function, list the contents of
  301. the IronPython environment:</p>
  302. </li>
  303. </ol>
  304. <p class="TypedExample">dir()</p>
  305. <p class="Stepnonumbering">The output in the console window will be:</p>
  306. <p class="Code-Highlighted">&gt;&gt;&gt; dir()</p>
  307. <p class="Code-Background">['__builtins__', '__doc__', '__name__']<br />
  308. </p>
  309. <ol start="3">
  310. <li>
  311. <p class="Step">IronPython comes with several built-in modules, the most
  312. frequently used one being &quot;sys&quot;.&nbsp; Import &quot;sys&quot; module using the &quot;import&quot;
  313. statement:</p>
  314. </li>
  315. </ol>
  316. <p class="TypedExample">import sys</p>
  317. <ol start="4">
  318. <li>
  319. <p class="Step">The Python import statement is similar to the &quot;using&quot; statement
  320. of C# or &quot;Imports&quot; statement of Visual Basic. The important difference is
  321. that the C# and VB statements bring the names from the imported namespace
  322. into the global namespace to be accessed directly. Python’s import doesn’t
  323. do that. To access the names or attributes in an imported module, prefix
  324. the
  325. names with the module's name:</p>
  326. </li>
  327. </ol>
  328. <p class="UserExample">sys.version</p>
  329. <ol start="5">
  330. <li>
  331. <p class="Step">Use the dir() function to explore the environment:</p>
  332. </li>
  333. </ol>
  334. <p class="TypedExample">dir()</p>
  335. <p class="Stepnonumbering" style="margin-left: 0.5in">The environment (global namespace) has changed, now
  336. it contains the &quot;sys&quot; module:</p>
  337. <p class="Code-Highlighted">&gt;&gt;&gt; dir()</p>
  338. <p class="Code-Background">['__builtins__', '__doc__', '__name__', 'sys']</p>
  339. <ol start="6">
  340. <li>
  341. <p class="Step">Use the dir() function to explore the contents of the &quot;sys&quot;
  342. module:</p>
  343. </li>
  344. </ol>
  345. <p class="TypedExample">dir(sys)</p>
  346. <p class="HiddenOutput">['__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit', 'hexversion', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdefaultencoding', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions', 'winver']</p>
  347. <ol start="7">
  348. <li>
  349. <p class="Step">Print the values of some of the &quot;sys&quot; module attributes:</p>
  350. </li>
  351. </ol>
  352. <p class="TypedExample">sys.path</p>
  353. <p class="LooseVerify">['.', '%MERLIN_ROOT%\\Test\\IronPythonTutorial', '%MERLIN_ROOT%\\Test', '%MERLIN_ROOT%\\Languages\\IronPython\\Tutorial', '%MERLIN_ROOT%\\Languages\\IronPython\\Tests', '%MERLIN_ROOT%\\Bin\\Debug\\Lib']</p>
  354. <p class="TypedExample">sys.executable</p>
  355. <p class="LooseVerify">'%MERLIN_ROOT%\\Bin\\Debug\\ipy.exe'</p>
  356. <h3><a name="T1.1.3">Task 3: External Python modules</a></h3>
  357. <p class="Normal">This task uses the module &quot;first.py&quot; located in the Tutorial
  358. folder.</p>
  359. <ol>
  360. <li>
  361. <p class="Step">Import the &quot;first.py&quot; module located in the Tutorial
  362. (because you launched ipy.exe from the Tutorial directory, &quot;first&quot; will
  363. be found on your sys.path):</p>
  364. </li>
  365. </ol>
  366. <p class="TypedExample">import first</p>
  367. <p class="Code-Background"></p>
  368. <ol start="2">
  369. <li>
  370. <p class="Step">Explore the module &quot;first&quot; using dir() function:</p>
  371. </li>
  372. </ol>
  373. <p class="TypedExample">dir(first)</p>
  374. <p class="Code-Highlighted">&gt;&gt;&gt; dir(first)</p>
  375. <p class="Code-Background">['__builtins__', '__file__', '__name__', 'add', 'factorial', 'hi']</p>
  376. <ol start="3">
  377. <li>
  378. <p class="Step">Print the documentation for the &quot;add&quot; and &quot;factorial&quot; functions,
  379. using __doc__ attribute:</p>
  380. </li>
  381. </ol>
  382. <p class="TypedExample">first.add.__doc__</p>
  383. <p class="TypedExample">first.factorial.__doc__</p>
  384. <p class="Stepnonumbering">&nbsp;</p>
  385. <p class="Stepnonumbering">The __doc__ attribute will be later used also for
  386. exploring .NET methods and their parameter types.</p>
  387. <p class="Code-Highlighted">&gt;&gt;&gt; first.add.__doc__</p>
  388. <p class="Code-Background">&#39;add(a, b) -&gt; returns a + b&#39;</p>
  389. <p class="Code-Highlighted">&gt;&gt;&gt; first.factorial.__doc__</p>
  390. <p class="Code-Background">&#39;factorial(n) -&gt; returns factorial of n&#39;</p>
  391. <ol start="4">
  392. <li>
  393. <p class="Step">Call the methods in the &quot;first&quot; module and print the contents
  394. of the &quot;hi&quot; attribute</p>
  395. </li>
  396. </ol>
  397. <p class="TypedExample">first.add(1,2)</p>
  398. <p class="TypedExample">first.factorial(5)</p>
  399. <p class="TypedExample">first.hi</p>
  400. <p class="Stepnonumbering">The expected output is:</p>
  401. <p class="Code-Highlighted">&gt;&gt;&gt; first.add(1,2)</p>
  402. <p class="Code-Background">3</p>
  403. <p class="Code-Highlighted">&gt;&gt;&gt; first.factorial(5)</p>
  404. <p class="Code-Background">120</p>
  405. <p class="Code-Highlighted">&gt;&gt;&gt; first.hi</p>
  406. <p class="Code-Background">&#39;Hello from IronPython!&#39;</p>
  407. <ol start="5">
  408. <li>
  409. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
  410. by Enter)</p>
  411. </li>
  412. </ol>
  413. <h2><a name="T1.2">Exercise 2: Using the standard .NET libraries from IronPython</a></h2>
  414. <p class="Body">The power of IronPython lies within the ability to seamlessly
  415. access the wealth of .NET libraries. This exercise will demonstrate how the
  416. .NET libraries can be used from IronPython.</p>
  417. <p class="Body">In this exercise, you will use the standard .NET libraries from
  418. IronPython. </p>
  419. <h3><a name="T1.2.1">Task 1: Basic .NET library use</a></h3>
  420. <ol>
  421. <li>
  422. <p class="Step">Start the IronPython console from the tutorial directory
  423. (see <a href="#Intro">Introduction</a> for details).</p>
  424. </li>
  425. <li>
  426. <p class="Step">Using the &quot;import&quot; statement, import the .NET System namespace:</p>
  427. </li>
  428. </ol>
  429. <p class="TypedExample">import System</p>
  430. <p class="Code-Background"></p>
  431. <ol start="3">
  432. <li>
  433. <p class="Step">Explore the System.Environment class and access some of
  434. its properties:</p>
  435. </li>
  436. </ol>
  437. <p class="TypedExample">dir(System.Environment)</p>
  438. <p class="UserCode">System.Environment.OSVersion</p>
  439. <p class="TypedExample">System.Environment.CommandLine</p>
  440. <p class="Stepnonumbering">The expected output of these commands is as follows
  441. (with some ellipsis for convenience):</p>
  442. <p class="Code-Highlighted">&gt;&gt;&gt; dir(System.Environment)</p>
  443. <p class="HiddenOutput">['CommandLine', 'CurrentDirectory', 'Equals', 'Exit', 'ExitCode', 'ExpandEnvironmentVariables', 'FailFast', 'GetCommandLineArgs', 'GetEnvironmentVariable', 'GetEnvironmentVariables', 'GetFolderPath', 'GetHashCode', 'GetLogicalDrives', 'GetType', 'HasShutdownStarted', 'MachineName', 'MemberwiseClone', 'NewLine', 'OSVersion', 'ProcessorCount', 'ReferenceEquals', 'SetEnvironmentVariable', 'SpecialFolder', 'StackTrace', 'SystemDirectory', 'TickCount', 'ToString', 'UserDomainName', 'UserInteractive', 'UserName', 'Version', 'WorkingSet', '__all__', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
  444. <p class="Code-Highlighted">&gt;&gt;&gt; System.Environment.OSVersion</p>
  445. <p class="Code-Highlighted">&lt;System.OperatingSystem object at 0x000000000000002B [Microsoft Windows NT 6.0.6000.0]</p>
  446. <p class="Code-Highlighted">&gt;&gt;&gt; System.Environment.CommandLine</p>
  447. <p class="Code-Highlighted">&#39;C:\\IronPython\\ipy.exe&#39;
  448. <p class="LooseVerify">'"%MERLIN_ROOT%\\Bin\\Debug\\ipy.exe"'
  449. </p>
  450. <ol start="4">
  451. <li>
  452. <p class="Step">The import statement can be used also to import contents of
  453. a class or module into the global namespace.&nbsp; Use the &quot;from ... import ...&quot;
  454. flavor of the import statement to do that and explore the contents of the
  455. global namespace using dir().</p>
  456. </li>
  457. </ol>
  458. <p class="TypedExample">from System.Math import *</p>
  459. <p class="UserCode">dir()</p>
  460. <p class="HiddenCode">set1 = set(dir())
  461. set2 = set(dir(object))
  462. list(set1-set2)
  463. </p>
  464. <p class="HiddenOutput">
  465. ['Tan','Sqrt','Acos','Sin','Abs','Round','Pow','Floor','Exp','Log','Atan2','IEEERemainder','Atan','__builtins__','Asin','System','E','Cosh','__name__', 'Ceiling','DivRem','BigMul','Cos','Truncate','Min','Tanh','Log10','Sign','Max','Sinh','PI']</p>
  466. <p class="Stepnonumbering">Now you can call Math methods without having to specify
  467. the namespace and class name prefix:</p>
  468. <p class="TypedExample">Sin(PI/2)</p>
  469. <p class="Stepnonumbering">The expected output is:</p>
  470. <p class="Code-Highlighted">&gt;&gt;&gt; from System.Math import *</p>
  471. <p class="Code-Highlighted">&gt;&gt;&gt; dir()</p>
  472. <p class="Code-Highlighted">[&#39;Abs&#39;, &#39;Acos&#39;, &#39;Asin&#39;, &#39;Atan&#39;, &#39;Atan2&#39;, &#39;BigMul&#39;, &#39;Ceiling&#39;, &#39;Cos&#39;, &#39;Cosh&#39;, &#39;DivRem&#39;, &#39;E&#39;, &#39;Equals&#39;, &#39;Exp&#39;, &#39;Floor&#39;, &#39;GetHashCode&#39;, &#39;GetType&#39;, &#39;IEEERemainder&#39;, &#39;Log&#39;, &#39;Log10&#39;, &#39;Max&#39;, &#39;Min&#39;, &#39;PI&#39;, &#39;Pow&#39;, &#39;Round&#39;, &#39;Sign&#39;, &#39;Sin&#39;, &#39;Sinh&#39;, &#39;Sqrt&#39;, &#39;System&#39;, &#39;Tan&#39;, &#39;Tanh&#39;, &#39;ToString&#39;, &#39;Truncate&#39;, &#39;__builtins__&#39;, &#39;__doc__&#39;, &#39;__name__&#39;]</p>
  473. <p class="Code-Highlighted">&gt;&gt;&gt; Sin(PI/2)</p>
  474. <p class="Code-Background">1.0</p>
  475. <h3><a name="T1.2.2">Task 2: Working with .NET classes</a></h3>
  476. <ol>
  477. <li>
  478. <p class="Step">Import the contents of the &quot;System.Collections&quot; namespace
  479. into the global namespace:</p>
  480. </li>
  481. </ol>
  482. <p class="TypedExample">from System.Collections import *</p>
  483. <p class="Code-Background"></p>
  484. <ol start="2">
  485. <li>
  486. <p class="Step">Create instance of the Hashtable class and explore the instance
  487. using dir():</p>
  488. </li>
  489. </ol>
  490. <p class="TypedExample">h = Hashtable()</p>
  491. <p class="Code-Background"></p>
  492. <p class="UserCode">dir(h)</p>
  493. <p class="HiddenCode">set1 = set(dir(h))
  494. set2 = set(dir(object))
  495. list(set1-set2)</p>
  496. <p class="HiddenOutput">
  497. ['Clone','ContainsValue','SyncRoot','hcp','__setitem__','__contains__','KeyEquals','IsSynchronized','GetEnumerator','GetHash','Contains','Item','Values','ContainsKey','Remove','OnDeserialization','__iter__','Add','Synchronized','EqualityComparer','__len__','comparer','Keys','Clear','IsReadOnly','CopyTo','IsFixedSize','__add__','GetObjectData','Count','__getitem__']</p>
  498. <ol start="3">
  499. <li>
  500. <p class="Step">Insert&nbsp;a few elements into the hash table:</p>
  501. </li>
  502. </ol>
  503. <p class="TypedExample">h[&quot;a&quot;] = &quot;IronPython&quot;</p>
  504. <p class="Code-Background"></p>
  505. <p class="TypedExample">h[&quot;b&quot;] = &quot;Tutorial&quot;</p>
  506. <p class="Code-Background"></p>
  507. <p class="Stepnonumbering">&nbsp;</p>
  508. <p class="Stepnonumbering">IronPython supports the C# - style syntax for accessing
  509. the hash table elements.&nbsp; The same syntax applies to any index-able object (Arrays,
  510. Array lists etc):</p>
  511. <p class="TypedExample">h[&quot;a&quot;]</p>
  512. <p class="Stepnonumbering" style="page-break-after:avoid">&nbsp;</p>
  513. <p class="Stepnonumbering" style="page-break-after:avoid">The output of this
  514. step will be:</p>
  515. <p class="Code-Background" style="page-break-after:avoid">&gt;&gt;&gt; h[&quot;a&quot;] = &quot;IronPython&quot;<br />
  516. &gt;&gt;&gt; h[&quot;b&quot;] = &quot;Tutorial&quot;</p>
  517. <p class="Code-Highlighted" style="page-break-after:avoid">&gt;&gt;&gt; h[&quot;a&quot;]</p>
  518. <p class="Code-Background">&#39;IronPython&#39;</p>
  519. <ol start="4">
  520. <li>
  521. <p class="Step">Enumerate the contents of the hash table using the &quot;for
  522. ... in ...&quot; statement. The hash table elements are instances of &quot;DictionaryEntry&quot;
  523. class. Print the &quot;Key&quot; and &quot;Value&quot; properties of each entry:</p>
  524. </li>
  525. </ol>
  526. <p class="TypedExample">for e in h: print e.Key, &quot;:&quot;, e.Value</p>
  527. <p class="Stepnonumbering">&nbsp;</p>
  528. <p class="Stepnonumbering">The expected output in the console is (the input
  529. line starting with &quot;for&quot; requires an extra return or enter key press because
  530. the interpreter prompts for more statements in the 'for' loop.):</p>
  531. <p class="Code-Highlighted">&gt;&gt;&gt; for e in h: print e.Key, &quot;:&quot;, e.Value<br>
  532. ...</p>
  533. <p class="Code-Background">a : IronPython<br />
  534. b : Tutorial</p>
  535. <ol start="5">
  536. <li>
  537. <p class="Step">You can initialize the collection classes by passing in
  538. the Python built-in list or tuple data types as arguments.&nbsp; You can
  539. create a Python list by specifying the list of elements in square brackets: [1,2,3].&nbsp;
  540. You create tuples by specifying elements in the parentheses: (1,2,3).</p>
  541. </li>
  542. </ol>
  543. <p class="TypedExample">l = ArrayList([1,2,3])</p>
  544. <p class="Code-Background"></p>
  545. <p class="TypedExample">for i in l: print i</p>
  546. <p class="TypedExample">s = Stack((1,2,3))</p>
  547. <p class="TypedExample">while s.Count: s.Pop()</p>
  548. <p class="Stepnonumbering">&nbsp;</p>
  549. <p class="Stepnonumbering">The expected output is:</p>
  550. <p class="Code-Highlighted">&gt;&gt;&gt; l = ArrayList([1,2,3])<br />
  551. &gt;&gt;&gt; for i in l: print i<br>
  552. ...</p>
  553. <p class="Code-Background">1<br />
  554. 2<br />
  555. 3</p>
  556. <p class="Code-Background"></p>
  557. <p class="Code-Highlighted">&gt;&gt;&gt; s = Stack((1,2,3))<br />
  558. &gt;&gt;&gt; while s.Count: s.Pop()<br>...</p>
  559. <p class="Code-Background">3<br />
  560. 2<br />
  561. 1</p>
  562. <h3><a name="T1.2.3">Task 3: Generics</a></h3>
  563. <ol>
  564. <li>
  565. <p class="Step">Import the Generic collections from the System.Collections.Generic
  566. namespace:</p>
  567. </li>
  568. </ol>
  569. <p class="TypedExample">from System.Collections.Generic import *</p>
  570. <p class="Code-Background"></p>
  571. <ol start="2">
  572. <li>
  573. <p class="Step">To instantiate a generic class, the generic type arguments
  574. must be specified.&nbsp; IronPython uses the following syntax to specify the type
  575. arguments: generic_type[type_argument, ...].&nbsp; Create an instance of generic
  576. list of string:</p>
  577. </li>
  578. </ol>
  579. <p class="TypedExample">l = List[str]()</p>
  580. <p class="Code-Background"></p>
  581. <ol start="3">
  582. <li>
  583. <p class="Step">Add string values into the list. Since we created a list of
  584. string, adding strings is possible:</p>
  585. </li>
  586. </ol>
  587. <p class="TypedExample">l.Add(&quot;Hello&quot;)</p>
  588. <p class="Code-Background"></p>
  589. <p class="TypedExample">l.Add(&quot;Hi&quot;)</p>
  590. <p class="Code-Background"></p>
  591. <ol start="4">
  592. <li>
  593. <p class="Step">Try adding objects of types other than string:</p>
  594. </li>
  595. </ol>
  596. <p class="ExceptionExample">l.Add(3)</p>
  597. <p class="Code-Background"></p>
  598. <p class="ExceptionExample">l.Add(2.5)</p>
  599. <p class="Code-Background"></p>
  600. <p class="ExceptionExample">l.Add([1,2,3])</p>
  601. <p class="Code-Background"></p>
  602. <p class="Stepnonumbering">&nbsp;</p>
  603. <p class="Stepnonumbering">Obviously, adding non-strings will fail with type
  604. error:</p>
  605. <p class="Code-Highlighted">&gt;&gt;&gt; l.Add(3)</p>
  606. <p class="Code-Highlighted">Traceback (most recent call last):<br>
  607. File , line unknown, in Initialize##40
  608. <br>
  609. TypeError: expected str, got int
  610. <br></p>
  611. <ol start="5">
  612. <li>
  613. <p class="Step">Enumerate the generic collection:</p>
  614. </li>
  615. </ol>
  616. <p class="TypedExample">for i in l: print i</p>
  617. <p class="Stepnonumbering">The output will be:</p>
  618. <p class="Code-Highlighted">&gt;&gt;&gt; for i in l: print i<br>...</p>
  619. <p class="Code-Background">Hello<br />
  620. Hi</p>
  621. <p class="ExceptionOutput">TypeError: expected str, got int
  622. TypeError: expected str, got float
  623. TypeError: expected str, got list</p>
  624. <ol start="6">
  625. <li>
  626. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
  627. by Enter)</p>
  628. </li>
  629. </ol>
  630. <h2><a name="T1.3">Exercise 3: Loading .NET libraries</a></h2>
  631. <p class="Body">IronPython can directly import only some of the .NET libraries
  632. - the most commonly used ones.&nbsp; To use additional .NET libraries, they must be
  633. explicitly referenced.&nbsp; IronPython maintains a list of all referenced
  634. assemblies (see clr.References in Task 1).&nbsp; To add a reference to a .NET assembly, use the functions
  635. available in the built-in &quot;clr&quot; module:</p>
  636. <ul>
  637. <li>
  638. <p class="Body"><b>clr.AddReference</b> adds a reference to the .NET assembly
  639. either by passing the .NET assembly object directly, or specifying the file
  640. name or the assembly name (full or partial). This function is provided primarily
  641. for the interactive exploration. We recommend using the following functions
  642. in the code modules, since they provide more control over which assembly
  643. is being loaded.</p>
  644. </li>
  645. <li>
  646. <p class="Body"><b>clr.AddReferenceToFile</b> adds reference to the assembly
  647. specified by its file name. This function will load the assembly from the
  648. file regardless of the assembly version. As a result, it doesn&#39;t guarantee
  649. that the correct assembly version is being loaded. To guarantee that correct
  650. assembly version is being loaded, use clr.AddReferenceByName. Moreover,
  651. AddReferenceToFile requires that the assembly be located in a
  652. directory listed in sys.path.</p>
  653. </li>
  654. <li>
  655. <p class="Body"><b>clr.AddReferenceToFileAndPath</b> provides similar
  656. functionality to AddReferenceToFile. The difference is that it accepts
  657. absolute path and before loading the assembly, AddReferenceToFileAndPath
  658. adds the file path into sys.path.</p>
  659. </li>
  660. <li>
  661. <p class="Body"><b>clr.AddReferenceByName</b> adds reference to the assembly
  662. specified by its full assembly name, for example: &#39;System.Xml, Version=2.0.0.0,
  663. Culture=neutral, PublicKeyToken=b77a5c561934e089&#39;.</p>
  664. </li>
  665. <li>
  666. <p class="Body"><b>clr.AddReferenceByPartialName</b> adds reference to the
  667. assembly by specifying a partial assembly name. This function cannot guarantee
  668. that the correct version of the assembly is being loaded. Use clr.AddReferenceByName
  669. to add reference to specific version of the assembly.</p>
  670. </li>
  671. </ul>
  672. <h3><a name="T1.3.1">Task 1: Using System.Xml - AddReference</a></h3>
  673. <ol>
  674. <li>
  675. <p class="Step">Start the IronPython console from the tutorial directory
  676. (see <a href="#Intro">Introduction</a> for details).</p>
  677. </li>
  678. <li>
  679. <p class="Step">To import System.Xml, the reference to the assembly containing
  680. the Xml components must be first added to IronPython.&nbsp; Add reference to System.Xml
  681. using the following code&nbsp; (you can enter &quot;clr.References&quot; before
  682. and after the call to clr.AddReference to see it change if you want):</p>
  683. </li>
  684. </ol>
  685. <p class="TypedExample">import clr</p>
  686. <p class="Code-Background"></p>
  687. <p class="TypedExample">clr.AddReference(&quot;System.Xml&quot;)</p>
  688. <p class="Code-Background"></p>
  689. <p class="TypedExample">from System.Xml import *</p>
  690. <p class="Code-Background"></p>
  691. <p class="TypedExample">dir()</p>
  692. <p class="HiddenOutput">['ConformanceLevel', 'EntityHandling', 'Formatting', 'IHasXmlNode', 'IXmlLineInfo', 'IXmlNamespaceResolver', 'NameTable', 'NewLineHandling', 'ReadState', 'Schema', 'Serialization', 'ValidationType', 'WhitespaceHandling', 'WriteState', 'XPath', 'XmlAttribute', 'XmlAttributeCollection', 'XmlCDataSection', 'XmlCharacterData', 'XmlComment', 'XmlConvert', 'XmlDateTimeSerializationMode', 'XmlDeclaration', 'XmlDocument', 'XmlDocumentFragment', 'XmlDocumentType', 'XmlElement', 'XmlEntity', 'XmlEntityReference', 'XmlException', 'XmlImplementation', 'XmlLinkedNode', 'XmlNameTable', 'XmlNamedNodeMap', 'XmlNamespaceManager', 'XmlNamespaceScope', 'XmlNode', 'XmlNodeChangedAction', 'XmlNodeChangedEventArgs', 'XmlNodeChangedEventHandler', 'XmlNodeList', 'XmlNodeOrder', 'XmlNodeReader', 'XmlNodeType', 'XmlNotation', 'XmlOutputMethod', 'XmlParserContext', 'XmlProcessingInstruction', 'XmlQualifiedName', 'XmlReader', 'XmlReaderSettings', 'XmlResolver', 'XmlSecureResolver', 'XmlSignificantWhitespace', 'XmlSpace', 'XmlText', 'XmlTextReader', 'XmlTextWriter', 'XmlTokenizedType', 'XmlUrlResolver', 'XmlValidatingReader', 'XmlWhitespace', 'XmlWriter', 'XmlWriterSettings', 'Xsl', '__builtins__', '__doc__', '__name__', 'clr']</p>
  693. <ol start="3">
  694. <li>
  695. <p class="Step">Note that the clr.AddReference function accepts either System.Reflection.Assembly object or string
  696. as a parameter. The string parameter can
  697. be a full assembly name, a partial assembly name, or a file name. For more control
  698. over the assembly references, use the appropriate functions described
  699. above. </p>
  700. <p class="Step">For example, consider the following alternatives for the statement clr.AddReference(&quot;System.Xml&quot;) above:</p>
  701. </li>
  702. </ol>
  703. <p class="TypedExample">clr.AddReferenceByName(&#39;System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&#39;)</p>
  704. <p class="Code-Background"></p>
  705. <p class="TypedExample">clr.AddReferenceByPartialName(&quot;System.Xml&quot;)</p>
  706. <p class="Code-Background"></p>
  707. <ol start="4">
  708. <li>
  709. <p class="Step">Load the XML file &quot;load.xml&quot; into the XmlDocument. The
  710. xml file contains sample savegame data from the IronPython sample &quot;Puzzle&quot; .
  711. For direct viewing, the load.xml file is located in the Tutorial folder</p>
  712. </li>
  713. </ol>
  714. <p class="TypedExample">d = XmlDocument()</p>
  715. <p class="Code-Background"></p>
  716. <p class="TypedExample">d.Load(&quot;load.xml&quot;)</p>
  717. <p class="Code-Background"></p>
  718. <ol start="5">
  719. <li>
  720. <p class="Step">We can now query the document. Query for all the saved games using the query below:</p>
  721. </li>
  722. </ol>
  723. <p class="TypedExample">n = d.SelectNodes(&quot;//Puzzle/SavedGames/Game/@caption&quot;)</p>
  724. <p class="TypedExample">for e in n: print e.Value</p>
  725. <p class="Stepnonumbering">&nbsp;</p>
  726. <p class="Stepnonumbering">The output in the console window will be:</p>
  727. <p class="Code-Highlighted">&gt;&gt;&gt; n = d.SelectNodes(&quot;//Puzzle/SavedGames/Game/@caption&quot;)<br />
  728. &gt;&gt;&gt; for e in n: print e.Value<br>...</p>
  729. <p class="Code-Background">
  730. Seattle (default game)<br />
  731. New York<br />
  732. World<br />
  733. North America<br />
  734. </p>
  735. <ol start="6">
  736. <li>
  737. <p class="Step">(Optional) Import the &quot;xmlutil.py&quot; module located in the
  738. Tutorial directory and use the function provided in the module to walk the
  739. contents of the Xml document:</p>
  740. </li>
  741. </ol>
  742. <p class="TypedExample">import xmlutil</p>
  743. <p class="TypedExample">for e in xmlutil.Walk(d): print e.Name, e.Value</p>
  744. <p class="HiddenOutput">#document None
  745. #comment *************************************************************************
  746. *
  747. * Copyright (c) Microsoft Corporation.&nbsp;
  748. *
  749. * This source code is subject to terms and conditions of the Microsoft Public License. A&nbsp;
  750. * copy of the license can be found in the License.html file at the root of this distribution. If&nbsp;
  751. * you cannot locate the Microsoft Public License, please send an email to&nbsp;
  752. * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound&nbsp;
  753. * by the terms of the Microsoft Public License.
  754. *
  755. * You must not remove this notice, or any other, from this software.
  756. *
  757. *
  758. * ***************************************************************************&nbsp;
  759. Puzzle None
  760. SavedGames None
  761. Game None
  762. caption Seattle (default game)
  763. type a
  764. y 714
  765. x 327
  766. level 11
  767. dimension 3
  768. Game None
  769. caption New York
  770. type r
  771. y 1538
  772. x 1205
  773. level 12
  774. dimension 3
  775. Game None
  776. caption World
  777. type h
  778. y 0
  779. x 0
  780. level 2
  781. dimension 4
  782. Game None
  783. caption North America
  784. type a
  785. x 2
  786. y 5
  787. level 4
  788. dimension 3
  789. TopLeftPreviewTile None
  790. x -3
  791. y -3
  792. dimension 3
  793. level 5
  794. Cache None
  795. allow true</p>
  796. <p class="Stepnonumbering">The Walk function is a generator (a Python function
  797. that contains a &quot;yield&quot; statement). As the Walk function executes, it returns
  798. (yields) the XML nodes one by one to the caller who iterates over the generator.
  799. The source for the Walk function is:</p>
  800. <p class="CodeSample">def Walk(xml):</br>
  801. &nbsp;&nbsp;&nbsp; yield xml</br><br>
  802. &nbsp;&nbsp;&nbsp; if hasattr(xml, &quot;Attributes&quot;):<br />
  803. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attrs = xml.Attributes<br />
  804. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if attrs:<br />
  805. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for attr in attrs:</br>
  806. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  807. yield attr</br><br>
  808. &nbsp;&nbsp;&nbsp; for child in xml:<br />
  809. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for c in Walk(child):</br>
  810. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  811. yield c</p>
  812. <ol start="7">
  813. <li>
  814. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
  815. by Enter)</p>
  816. </li>
  817. </ol>
  818. <h3><a name="T1.3.2">Task 2: Mapack - Loading the .NET libraries - AddReferenceToFile</a></h3>
  819. <p class="Normal">This task requires the Mapack.dll library for linear algebra computations.&nbsp;
  820. The library is not part of the IronPython distribution. See <a href="#Mapack">prerequisites</a>
  821. for download details.</p>
  822. <ol>
  823. <li>
  824. <p class="Step">Start the IronPython console from the tutorial directory
  825. (see <a href="#Intro">Introduction</a> for details).</p>
  826. </li>
  827. <li>
  828. <p class="Step">Use the clr.AddReferenceToFile function to load the Matrix
  829. library &quot;Mapack.dll&quot;:</p>
  830. </li>
  831. </ol>
  832. <p class="TypedExample">import clr</p>
  833. <p class="Code-Background"></p>
  834. <p class="TypedExample">clr.AddReferenceToFile(&quot;Mapack.dll&quot;)</p>
  835. <p class="Code-Background"></p>
  836. <p class="TypedExample">from Mapack import *</p>
  837. <p class="Code-Background"></p>
  838. <p class="TypedExample">dir()</p>
  839. <p class="Stepnonumbering">The expected output will be:</p>
  840. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  841. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;Mapack.dll&quot;)<br />
  842. &gt;&gt;&gt; from Mapack import *<br />
  843. &gt;&gt;&gt; dir()</p>
  844. <p class="Code-Background">['CholeskyDecomposition', 'EigenvalueDecomposition', 'LuDecomposition', 'Matrix', 'QrDecomposition', 'SingularValueDecomposition', '__builtins__', '__doc__', '__name__', 'clr']</p>
  845. <ol start="3">
  846. <li>
  847. <p class="Step">Create instance of Matrix class:</p>
  848. </li>
  849. </ol>
  850. <p class="ExceptionExample">m = Matrix()</p>
  851. <p class="Code-Background"></p>
  852. <p class="Stepnonumbering">Oops, bad arguments for the constructor.&nbsp; In the next
  853. step you&#39;ll learn the way to discover the constructors available.</p>
  854. <p class="Code-Highlighted">Traceback (most recent call last):
  855. <br>
  856. File , line unknown, in Initialize##30
  857. <br>
  858. TypeError: Matrix() takes at least 1 argument (0 given)</p>
  859. <ol start="4">
  860. <li>
  861. <p class="Step">Using the __doc__ attribute, find out information about
  862. Matrix constructors:</p>
  863. </li>
  864. </ol>
  865. <p class="TypedExample">print Matrix.__new__.__doc__</p>
  866. <p class="Code-Highlighted">&gt;&gt;&gt; print Matrix.__new__.__doc__</p>
  867. <p class="Code-Background">__new__(cls, int rows, int columns)<br />
  868. __new__(cls, int rows, int columns, float value)<br />
  869. __new__(cls, Array[Array[float]] value)
  870. </p>
  871. <ol start="5">
  872. <li>
  873. <p class="Step">Create instances of the Matrix class using the correct constructors
  874. and set some matrix elements manually.&nbsp; IronPython supports custom indexing
  875. on .NET classes. </p>
  876. </li>
  877. </ol>
  878. <p class="TypedExample">m = Matrix(2, 2, 1.2)</p>
  879. <p class="Code-Background"></p>
  880. <p class="TypedExample">n = Matrix(2,1)</p>
  881. <p class="Code-Background"></p>
  882. <p class="TypedExample">n[0,0] = 4</p>
  883. <p class="Code-Background"></p>
  884. <p class="TypedExample">print m</p>
  885. <p class="TypedExample">print n</p>
  886. <p class="Code-Highlighted">&gt;&gt;&gt; m = Matrix(2, 2, 1.2)<br />
  887. &gt;&gt;&gt; n = Matrix(2,1)<br />
  888. &gt;&gt;&gt; n[0,0] = 4<br />
  889. &gt;&gt;&gt; print m</p>
  890. <p class="Code-Background">1.2 0 <br />
  891. 0 1.2&nbsp;
  892. </p>
  893. <p class="Code-Highlighted">&gt;&gt;&gt; print n</p>
  894. <p class="Code-Background">4 <br />
  895. 0&nbsp;
  896. </p>
  897. <ol start="6">
  898. <li>
  899. <p class="Step">(Optional) IronPython also supports overloaded operators.&nbsp; Matrix does overload operators +, - (binary and unary) and *.&nbsp; You can see
  900. Python representation of the operators (__add__, __mul__, __sub__, ...)
  901. using dir():</p>
  902. </li>
  903. </ol>
  904. <p class="UserCode">dir(m)</p>
  905. <p class="HiddenCode">set1 = set(dir(m))
  906. set2 = set(dir(object))
  907. list(set1-set2)</p>
  908. <p class="HiddenOutput">
  909. ['Submatrix','Symmetric','Clone','__sub__','Columns','Trace','__ne__','InfinityNorm','Rows','__setitem__','Multiply','__neg__','Diagonal','Random','Subtract','Item','Square','FrobeniusNorm','Solve','__rmul__','Negate','Add','Inverse','__radd__','__rsub__','__mul__','Determinant','__add__','__eq__','__getitem__','Norm1','Transpose']</p>
  910. <ol start="7">
  911. <li>
  912. <p class="Step">Make simple calculations with the matrices:</p>
  913. </li>
  914. </ol>
  915. <p class="TypedExample">m * n</p>
  916. <p class="TypedExample">n.Transpose() * m</p>
  917. <p class="TypedExample">m * 3</p>
  918. <p class="TypedExample">n + -n</p>
  919. <p class="Stepnonumbering">The expected output of this step is:</p>
  920. <p class="Code-Highlighted">&gt;&gt;&gt; m * n</p>
  921. <p class="LooseVerify">Mapack.Matrix</p>
  922. <p class="Code-Highlighted">&gt;&gt;&gt; n.Transpose() * m</p>
  923. <p class="LooseVerify">Mapack.Matrix</p>
  924. <p class="Code-Highlighted">&gt;&gt;&gt; m * 3</p>
  925. <p class="LooseVerify">Mapack.Matrix</p>
  926. <p class="Code-Highlighted">&gt;&gt;&gt; n + -n</p>
  927. <p class="LooseVerify">Mapack.Matrix</p>
  928. <p class="ExceptionOutput">TypeError: Matrix() takes at least 1 argument (0 given)</p>
  929. <ol start="8">
  930. <li>
  931. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
  932. by Enter)</p>
  933. </li>
  934. </ol>
  935. <h2><a name="T1.4">Exercise 4: Obtaining and Using Python Standard Library</a></h2>
  936. <p class="Body">In this exercise, you will obtain Python and point
  937. IronPython at the Python standard library. If you installed IronPython from the MSI installer,
  938. the Python standard library is installed by default and you can skip this exercise.</p>
  939. <h3><a name="T1.4.1">Task 1: Configuring IronPython to use the Python standard library</a></h3>
  940. <ol>
  941. <li>
  942. <p class="Step">Download the latest Python installer from
  943. <a href="http://www.python.org/download/">http://www.python.org/download/</a>
  944. and install Python.&nbsp; The rest of this exercise will assume you used
  945. defaults (and installed to c:\python25, for example).</p>
  946. </li>
  947. <li>
  948. <p class="Step">Create a file named &quot;site.py&quot; and place it into your
  949. IronPython &quot;Lib&quot; directory.&nbsp; There might be one there
  950. already, so you can just edit it.&nbsp; The &quot;site.py&quot; file is executed every time
  951. you run IronPython.&nbsp; To tell IronPython where the Python standard library
  952. is, you can add the &quot;lib&quot; directory of Python to IronPython's path.&nbsp; To
  953. do so, put the following code into IronPython's &quot;site.py&quot; file (replace
  954. c:\python25\lib with your actual path to the Python lib directory):</p>
  955. </li>
  956. </ol>
  957. <p class="TypedExample">import sys</p>
  958. <p class="TypedExample">sys.path.append(r&quot;c:\python25\lib&quot;)</p>
  959. <ol start="3">
  960. <li>
  961. <p class="Step">Start the IronPython console from the tutorial directory
  962. (see <a href="#Intro">Introduction</a> for details).</p>
  963. </li>
  964. <li>
  965. <p class="Step">Now you can use the Python standard library from
  966. IronPython, for example to get the current working directory (output
  967. uses assumed location of your IronPython installation):</p>
  968. </li>
  969. </ol>
  970. <p class="TypedExample">import os</p>
  971. <p class="Code-Background"></p>
  972. <p class="TypedExample">os.getcwd()</p>
  973. <p class="Code-Highlighted">'C:\\ironpython\\Tutorial'</p>
  974. <p class="LooseVerify">
  975. '%MERLIN_ROOT%\\Test\\IronPythonTutorial'</p>
  976. <p class="LabSummary">Tutorial Summary</p>
  977. <p class="Body">In this tutorial you performed the following exercises.</p>
  978. <ul>
  979. <li>
  980. <p class="Body"><a href="#T1.1">The IronPython interactive console</a></p>
  981. </li>
  982. <li>
  983. <p class="Body"><a href="#T1.2">Using the standard .NET libraries from IronPython</a></p>
  984. </li>
  985. <li>
  986. <p class="Body"><a href="#T1.3">Loading .NET libraries</a></p>
  987. </li>
  988. <li>
  989. <p class="Body"><a href="#T1.4">Obtaining and Using Python Standard
  990. Library</a></p>
  991. </li>
  992. </ul>
  993. <p class="Body">In this tutorial, you became acquainted with IronPython interactive
  994. console, including the dynamic exploratory way of development using the dir() function
  995. and __doc__ attribute to explore the environment.&nbsp; You learned to load and import
  996. .NET libraries from IronPython (using the import statement), create instances
  997. of .NET classes (including generic classes), call methods, enumerate .NET collections,
  998. and even use overloaded operators on .NET objects.&nbsp; Finally, you
  999. learned how to access standard Python libraries.</p>
  1000. <p class="Body">&nbsp;</p>
  1001. <h1><a name="T2">Tutorial 2: Advanced IronPython</a></h1>
  1002. <p class="Body">The large part of the beauty of IronPython lies within the dynamic-style
  1003. development -- modifying the live application by adding functioning elements
  1004. to it.&nbsp; With Windows applications, this often requires delegates and event handling
  1005. (i.e., adding a button to an existing form and adding functionality to the button
  1006. to handle the user pressing the button).</p>
  1007. <p class="Body">This tutorial will focus on creating delegates, handling
  1008. events in IronPython, and creating Windows applications using Windows Forms and
  1009. the new Windows Presentation Foundation (formerly known as Avalon).</p>
  1010. <p class="Body">Estimated time to complete this tutorial: <b>25 minutes</b></p>
  1011. <p class="Body">The objective of this tutorial is to learn how to create delegates
  1012. and handle events using IronPython, and to use that knowledge to build working Windows
  1013. applications using Windows Forms and Windows Presentation Foundation.</p>
  1014. <ul>
  1015. <li>
  1016. <p class="ExerciseList"><a href="#T2.1">Events and Delegates</a></p>
  1017. </li>
  1018. <li>
  1019. <p class="ExerciseList"><a href="#T2.2">Windows Forms</a></p>
  1020. </li>
  1021. <li>
  1022. <p class="ExerciseList"><a href="#T2.3">Windows Presentation Foundation
  1023. (Avalon)</a></p>
  1024. </li>
  1025. </ul>
  1026. <h2><a name="T2.1">Exercise 1: Events and Delegates</a></h2>
  1027. <p class="Body">In this exercise, you will create a simple event handler and
  1028. learn how to explore event handler use. The event handler we&#39;ll use in this
  1029. exercise is the FileSystemWatcher - a component that raises events on file system
  1030. changes.</p>
  1031. <h3><a name="T2.1.1">Task 1: File System Watcher</a></h3>
  1032. <ol>
  1033. <li>
  1034. <p class="Step">Start the IronPython console from the tutorial directory
  1035. (see <a href="#Intro">Introduction</a> for details).</p>
  1036. </li>
  1037. <li>
  1038. <p class="Step">Import the contents of System.IO into the global namespace:</p>
  1039. </li>
  1040. </ol>
  1041. <p class="TypedExample">from System.IO import *</p>
  1042. <p class="Code-Background"></p>
  1043. <ol start="3">
  1044. <li>
  1045. <p class="Step">Create instance of the FileSystemWatcher class and set Path
  1046. property to watch over the current directory:</p>
  1047. </li>
  1048. </ol>
  1049. <p class="TypedExample">w = FileSystemWatcher()</p>
  1050. <p class="Code-Background"></p>
  1051. <p class="UserCode">dir(w)</p>
  1052. <p class="HiddenCode">set1 = set(dir(w))
  1053. set2 = set(dir(object))
  1054. list(set1-set2)</p>
  1055. <p class="HiddenOutput">
  1056. ['GetLifetimeService', 'EndInit', 'IncludeSubdirectories', 'Filter', 'WaitForChanged', 'Disposed', 'OnChanged', 'DesignMode', 'InitializeLifetimeService', 'NotifyFilter', 'GetService', 'Path', 'Created', 'EnableRaisingEvents', 'InternalBufferSize', 'SynchronizingObject', 'OnError', 'Site', 'BeginInit', 'Deleted', 'Error', 'Dispose', '__enter__', 'CanRaiseEvents', 'Events', 'Changed', '__exit__', 'Container', 'OnRenamed', 'Renamed', 'CreateObjRef', 'OnCreated', 'OnDeleted']</p>
  1057. <p class="TypedExample">w.Path = &quot;.&quot;</p>
  1058. <p class="Code-Background"></p>
  1059. <ol start="4">
  1060. <li>
  1061. <p class="Step" style="page-break-after:avoid">Create the function to handle
  1062. the events.&nbsp; Because we don&#39;t know yet what arguments the delegate will have,
  1063. let&#39;s accept any number of arguments (the *arg notation):</p>
  1064. </li>
  1065. </ol>
  1066. <p class="TypedExample">def handle(*args): print args</p>
  1067. <p class="Code-Background"></p>
  1068. <ol start="5">
  1069. <li>
  1070. <p class="Step">Register the event handler for the &#39;Changed&#39;, &#39;Created&#39;,
  1071. and &#39;Deleted&#39; events:</p>
  1072. </li>
  1073. </ol>
  1074. <p class="TypedExample">w.Changed += handle</p>
  1075. <p class="Code-Background"></p>
  1076. <p class="TypedExample">w.Created += handle</p>
  1077. <p class="Code-Background"></p>
  1078. <p class="TypedExample">w.Deleted += handle</p>
  1079. <p class="Code-Background"></p>
  1080. <ol start="6">
  1081. <li>
  1082. <p class="Step">Enable the watcher to raise events:</p>
  1083. </li>
  1084. </ol>
  1085. <p class="TypedExample">w.EnableRaisingEvents = True</p>
  1086. <ol start="7">
  1087. <li>
  1088. <p class="Step">Open the Tutorial folder and create a file.&nbsp; An easy way
  1089. to create the file is to right-click with the mouse and select &quot;New\Text
  1090. Document&quot;. The file watcher will raise the &quot;Created&quot; event.</p>
  1091. </li>
  1092. </ol>
  1093. <p class="Stepnonumbering">You can then open the file in Notepad, type in any
  1094. text, and save the file.&nbsp; This raises the &quot;Changed&quot; event.&nbsp;
  1095. Then finish by deleting
  1096. the file to see the &quot;Deleted&quot; event get raised.</p>
  1097. <p class="Stepnonumbering">At the end of this step, the output in the command
  1098. window will be similar to the following:</p>
  1099. <p class="Code-Highlighted">(System.IO.FileSystemWatcher, &lt;System.IO.FileSystemEventArgs object at 0x03CE0BB8&gt;)<br />
  1100. (System.IO.FileSystemWatcher, &lt;System.IO.FileSystemEventArgs object at 0x039B3B4D&gt;)<br />
  1101. (System.IO.FileSystemWatcher, &lt;System.IO.FileSystemEventArgs object at 0x039B3B4D&gt;)<br />
  1102. (System.IO.FileSystemWatcher, &lt;System.IO.FileSystemEventArgs object at 0x014EF022&gt;)</p>
  1103. <ol start="8">
  1104. <li>
  1105. <p class="Step">In the next task, we will create an improved event handler.&nbsp; For now, remove the current event handler from the file watcher events:</p>
  1106. </li>
  1107. </ol>
  1108. <p class="TypedExample">w.Changed -= handle</p>
  1109. <p class="Code-Background"></p>
  1110. <p class="TypedExample">w.Created -= handle</p>
  1111. <p class="Code-Background"></p>
  1112. <p class="TypedExample">w.Deleted -= handle</p>
  1113. <p class="Code-Background">
  1114. </p>
  1115. <ol start="9">
  1116. <li>
  1117. <p class="Step">(Optional) You can try step 7 again to see that the events,
  1118. while they are still being raised, are not being handled by the Python &quot;handler&quot;
  1119. function.</p>
  1120. </li>
  1121. </ol>
  1122. <h3><a name="T2.1.2">Task 2: Improving the event handler</a></h3>
  1123. <ol>
  1124. <li>
  1125. <p class="Step">In the previous task, step 7 we can see that the types of
  1126. the parameters passed to all three events were the same:</p>
  1127. </li>
  1128. </ol>
  1129. <p class="Stepnonumbering">FileSystemWatcher - the instance of the object that
  1130. raised the event</p>
  1131. <p class="Stepnonumbering">FileSystemEventArgs - the information about the event
  1132. raised</p>
  1133. <p class="Stepnonumbering">Use dir() to explore the event arguments class to
  1134. find what information the event contains:</p>
  1135. <p class="TypedExample">from System.IO import *</p>
  1136. <p class="Code-Background"></p>
  1137. <p class="TypedExample">w = FileSystemWatcher()</p>
  1138. <p class="Code-Background"></p>
  1139. <p class="TypedExample">w.Path = &quot;.&quot;</p>
  1140. <p class="Code-Background"></p>
  1141. <p class="UserCode">dir(FileSystemEventArgs)</p>
  1142. <p class="HiddenCode">set1 = set(dir(FileSystemEventArgs))
  1143. set2 = set(dir(object))
  1144. list(set1-set2)</p>
  1145. <p class="Stepnonumbering" style="page-break-after:avoid">The output in the
  1146. console window will be:</p>
  1147. <p class="Code-Highlighted" style="page-break-after:avoid">&gt;&gt;&gt; dir(FileSystemEventArgs)</p>
  1148. <p class="Code-Highlighted">['ChangeType', 'Empty', 'Equals', 'FullPath', 'GetHashCode', 'GetType', 'MemberwiseClone', 'Name', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
  1149. <p class="HiddenOutput">
  1150. ['FullPath', 'Name', 'Empty', 'ChangeType']</p>
  1151. <ol start="2">
  1152. <li>
  1153. <p class="Step">Now with more knowledge of the event argument properties,
  1154. we can create a better event handler that will print ChangeType and FullPath
  1155. properties of the event argument object:</p>
  1156. </li>
  1157. </ol>
  1158. <p class="TypedExample">def handle(w, a): print a.ChangeType, a.FullPath</p>
  1159. <ol start="3">
  1160. <li>
  1161. <p class="Step">Register the new event handler for the &#39;Changed&#39;, &#39;Created&#39;
  1162. and &#39;Deleted&#39; events:</p>
  1163. </li>
  1164. </ol>
  1165. <p class="TypedExample">w.Changed += handle</p>
  1166. <p class="Code-Background"></p>
  1167. <p class="TypedExample">w.Created += handle</p>
  1168. <p class="Code-Background"></p>
  1169. <p class="TypedExample">w.Deleted += handle</p>
  1170. <p class="Code-Background">
  1171. </p>
  1172. <ol start="4">
  1173. <li>
  1174. <p class="Step">Make sure the raising of the events is enabled:</p>
  1175. </li>
  1176. </ol>
  1177. <p class="TypedExample">w.EnableRaisingEvents = True</p>
  1178. <ol start="5">
  1179. <li>
  1180. <p class="Step">Open the Tutorial folder again and create a new file (&quot;Created&quot;
  1181. event), edit the file in Notepad and save it (&quot;Changed&quot; event) and finish
  1182. by deleting the file (&quot;Deleted&quot; event).</p>
  1183. </li>
  1184. </ol>
  1185. <p class="Stepnonumbering">At the end of this step, the output in the command
  1186. window will be similar to the following:</p>
  1187. <p class="Code-Highlighted">Created .\New Text Document.txt<br />
  1188. Changed .\New Text Document.txt<br />
  1189. Changed .\New Text Document.txt<br />
  1190. Deleted .\New Text Document.txt</p>
  1191. <ol start="6">
  1192. <li>
  1193. <p class="Step">Remove the event handler from the file watcher events:</p>
  1194. </li>
  1195. </ol>
  1196. <p class="TypedExample">w.Changed -= handle</p>
  1197. <p class="Code-Background"></p>
  1198. <p class="TypedExample">w.Created -= handle</p>
  1199. <p class="Code-Background"></p>
  1200. <p class="TypedExample">w.Deleted -= handle</p>
  1201. <p class="Code-Background"></p>
  1202. <ol start="7">
  1203. <li>
  1204. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6, followed
  1205. by Enter).</p>
  1206. </li>
  1207. </ol>
  1208. <h3><a name="T2.1.3">Task 3: Defining events in Python</a></h3>
  1209. <ol>
  1210. <li>
  1211. <p class="Step">Finally let's look at how we can get event handler syntax from Python code:</p>
  1212. </li>
  1213. </ol>
  1214. <p class="Stepnonumbering">pyevent - a module providing Python event support</p>
  1215. <p class="Stepnonumbering">make_event - a function that returns an event tuple containing both the callable object and the object
  1216. that allows connecting and unconnecting to the event.</p>
  1217. <br/>
  1218. <p class="Stepnonumbering" style="page-break-after:avoid">To create an event:</p>
  1219. <br/>
  1220. <p class="TypedExample">import pyevent</p>
  1221. <p class="TypedExample">hook,caller = pyevent.make_event()</p>
  1222. <br/>
  1223. <p class="Stepnonumbering">This has returned back to us two objects. The first object allows a user to hook a
  1224. function up to the event. The second object allows the owner of the event to cause the event to be raised.
  1225. This allows for the separation of these abilities just like .NET.&nbsp; Now let's take this and put it into a class and
  1226. see how it gets used.</p>
  1227. <ol start="2">
  1228. <li>
  1229. <p class="Step">We'll define a class that has an event for</p>
  1230. </li>
  1231. </ol>
  1232. <p class="TypedExample">class MyClass(object):<br>
  1233. &nbsp;&nbsp;&nbsp;&nbsp;OnNewInstance,_NewInstance= pyevent.make_event()<br>
  1234. &nbsp;&nbsp;&nbsp;&nbsp;def __new__(cls):<br>
  1235. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = object.__new__(object)<br>
  1236. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyClass._NewInstance(res)<br>
  1237. </p>
  1238. <p class="Code-Background"></p>
  1239. <p class="Code-Background"></p>
  1240. <p class="Code-Background"></p>
  1241. <p class="TypedExample">def NewInst(x): print 'new inst: ', x </p>
  1242. <p class="Code-Background"></p>
  1243. <p class="TypedExample">MyClass.OnNewInstance += NewInst</p>
  1244. <p class="Code-Background"></p>
  1245. <p class="TypedExample">a = MyClass()</p>
  1246. <p class="LooseVerify">new inst</p>
  1247. <ol start="3">
  1248. <li>
  1249. <p class="Step">Just like with CLR events you can also remove event handlers:</p>
  1250. </li>
  1251. </ol>
  1252. <p class="TypedExample">MyClass.OnNewInstance -= NewInst</p>
  1253. <p class="Code-Background"></p>
  1254. <h2><a name="T2.2">Exercise 2: Windows Forms</a></h2>
  1255. <p class="Body">To interactively develop Windows applications, IronPython must
  1256. be initialized for that purpose.&nbsp; By default, the Python console executes on one thread only.&nbsp; While this thread awaits text input in the console window, the Windows application
  1257. being dynamically created from the console is not able to process Windows messages.&nbsp;
  1258. Therefore, the application does not repaint itself or handle input to the UI.</p>
  1259. <p class="Body">We provide a .py file to initialize IronPython for Windows Forms
  1260. development, see tasks below.</p>
  1261. <p class="Body">In this exercise, you will create simple Windows Forms applications
  1262. dynamically from the IronPython interactive console.</p>
  1263. <h3><a name="T2.2.1">Task 1: Simple Windows Forms application</a></h3>
  1264. <ol>
  1265. <li>
  1266. <p class="Step">Start the IronPython console from the tutorial directory
  1267. (see <a href="#Intro">Introduction</a> for details).</p>
  1268. </li>
  1269. <li>
  1270. <p class="Step">Initialize Windows Forms by loading the winforms module/script:</p>
  1271. </li>
  1272. </ol>
  1273. <p class="TypedExample">import winforms</p>
  1274. <p class="Code-Background"></p>
  1275. <p class="Stepnonumbering">Python modules get automatically initialized
  1276. (executed) upon import so the Windows Forms initialization code has executed
  1277. as part of the import statement.</p>
  1278. <ol start="3">
  1279. <li>
  1280. <p class="Step">Import the contents of the System.Windows.Forms and System.Drawing
  1281. namespaces into the global namespace: </p>
  1282. </li>
  1283. </ol>
  1284. <p class="TypedExample">from System.Windows.Forms import *</p>
  1285. <p class="Code-Background"></p>
  1286. <p class="TypedExample">from System.Drawing import *</p>
  1287. <p class="Code-Background"></p>
  1288. <ol start="4">
  1289. <li>
  1290. <p class="Step">Create an instance of the Form class and display it:</p>
  1291. </li>
  1292. </ol>
  1293. <p class="TypedExample">f = Form()</p>
  1294. <p class="Code-Background"></p>
  1295. <p class="TypedExample">f.Show()</p>
  1296. <p class="Code-Background"></p>
  1297. <p class="Stepnonumbering">You may need to alt-tab or look for the running
  1298. application since it may not have popped to the top level on your desktop.</p>
  1299. <ol start="5">
  1300. <li>
  1301. <p class="Step">Now set the form Text property:</p>
  1302. </li>
  1303. </ol>
  1304. <p class="TypedExample">f.Text = &quot;My First Interactive Application&quot;</p>
  1305. <p class="Code-Background"></p>
  1306. <ol start="6">
  1307. <li>
  1308. <p class="Step">To bring the application alive, let&#39;s focus on the Click
  1309. event of the form. Create an event handler for the Click event and click
  1310. on the form to receive the event. Then remove the event handler</p>
  1311. </li>
  1312. </ol>
  1313. <p class="TypedExample">def click(*args): print args</p>
  1314. <p class="Code-Background"></p>
  1315. <p class="TypedExample">f.Click += click</p>
  1316. <p class="Code-Background"></p>
  1317. <p class="Stepnonumbering">Click on the form to receive the event..</p>
  1318. <p class="Stepnonumbering">The output will be similar to:</p>
  1319. <p class="Code-Highlighted">&gt;&gt;&gt; (System.Windows.Forms.Form, Text: My First Interactive
  1320. Application, &lt;System.Windows.Forms.MouseEventArgs object at 0x02324551&gt;)</p>
  1321. <p class="Stepnonumbering">Now remove the click handler because we're going
  1322. to further develop it.</p>
  1323. <p class="TypedExample">f.Click -= click</p>
  1324. <p class="Code-Background"></p>
  1325. <ol start="7">
  1326. <li>
  1327. <p class="Step">Use dir() function to explore the MouseEventArgs</p>
  1328. </li>
  1329. </ol>
  1330. <p class="UserCode">dir(MouseEventArgs)</p>
  1331. <p class="HiddenCode">set1 = set(dir(MouseEventArgs))
  1332. set2 = set(dir(object))
  1333. list(set1-set2)</p>
  1334. <p class="HiddenOutput">
  1335. ['Location', 'Y', 'X', 'Button', 'Clicks', 'Empty', 'Delta']</p>
  1336. <ol start="8">
  1337. <li>
  1338. <p class="Step" style="page-break-after:avoid">Knowing the contents of the
  1339. MouseEventArgs, create an improved event handler for the Click event:</p>
  1340. </li>
  1341. </ol>
  1342. <p class="TypedExample" style="page-break-after:avoid">def click(f, a):<br>
  1343. &nbsp;&nbsp;&nbsp; l = Label(Text = &quot;Hello&quot;)<br>
  1344. &nbsp;&nbsp;&nbsp; l.Location = a.Location<br>
  1345. &nbsp;&nbsp;&nbsp; f.Controls.Add(l)</p>
  1346. <p class="Code-Background"></p>
  1347. <ol start="9">
  1348. <li>
  1349. <p class="Step" style="page-break-after:avoid">Register the event handler:</p>
  1350. </li>
  1351. </ol>
  1352. <p class="TypedExample">f.Click += click</p>
  1353. <p class="Code-Background"></p>
  1354. <ol start="10">
  1355. <li>
  1356. <p class="Step">Now clicking on the form with the mouse will add &quot;Hello&quot;
  1357. labels. We can also access the controls we just added via mouse clicks and
  1358. change them</p>
  1359. </li>
  1360. </ol>
  1361. <p class="TypedExample">for i in f.Controls: i.Font = Font(&quot;Verdana&quot;, 15)</p>
  1362. <p class="Code-Background"></p>
  1363. <p class="TypedExample">for i in f.Controls: i.Text = &quot;Hi&quot;</p>
  1364. <p class="Code-Background"></p>
  1365. <ol start="11">
  1366. <li>
  1367. <p class="Step">After a few moments of clicking, the form will get quite
  1368. crowded, so we can clear it out:</p>
  1369. </li>
  1370. </ol>
  1371. <p class="TypedExample">f.Controls.Clear()</p>
  1372. <p class="HiddenCode">f.Close()</p>
  1373. <p class="Code-Background"></p>
  1374. <ol start="12">
  1375. <li>
  1376. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
  1377. by Enter)</p>
  1378. </li>
  1379. </ol>
  1380. <p class="Body">The standalone version of this script is located in wfdemo.py
  1381. in the Tutorial directory.</p>
  1382. <h2><a name="T2.3">Exercise 3: Windows Presentation Foundation (Avalon)</a></h2>
  1383. <p class="Body">This exercise requires Windows Presentation Foundation installed.&nbsp; Please see <a href="#Avalon">prerequisites</a> for more information.</p>
  1384. <p class="Body">Just like Windows Forms, the Windows Presentation Foundation
  1385. also requires initialization to support interactive development. The initialization
  1386. code is available in the &quot;Tutorial\avalon.py&quot; file.</p>
  1387. <p class="Body">In this exercise, you will interactively create simple interactive
  1388. Windows Presentation Foundation application.</p>
  1389. <h3><a name="T2.3.1">Task 1: Simple Avalon Application</a></h3>
  1390. <ol>
  1391. <li>
  1392. <p class="Step">Start the IronPython console from the tutorial directory
  1393. (see <a href="#Intro">Introduction</a> for details).</p>
  1394. </li>
  1395. <li>
  1396. <p class="Step">Initialize Windows Presentation Foundation:</p>
  1397. </li>
  1398. </ol>
  1399. <p class="TypedExample">from avalon import *</p>
  1400. <p class="Code-Background"></p>
  1401. <ol start="3">
  1402. <li>
  1403. <p class="Step">Create Avalon window, display it, and set some of its properties:</p>
  1404. </li>
  1405. </ol>
  1406. <p class="TypedExample">w = Window()</p>
  1407. <p class="Code-Background"></p>
  1408. <p class="TypedExample">w.Show()</p>
  1409. <p class="Code-Background"></p>
  1410. <p class="Stepnonumbering">You may need to alt-tab or look for the running
  1411. application since it may not have popped to the top level on your desktop.&nbsp;
  1412. Now, let's do more.</p>
  1413. <p class="Code-Background"></p>
  1414. <p class="TypedExample">w.Title = &quot;My Avalon Application&quot;</p>
  1415. <p class="Code-Background"></p>
  1416. <p class="TypedExample">w.SizeToContent = SizeToContent.WidthAndHeight</p>
  1417. <p class="Code-Background"></p>
  1418. <p class="Stepnonumbering">By setting the window property to &quot;size to
  1419. content&quot;, the window shrinks.</p>
  1420. <ol start="4">
  1421. <li>
  1422. <p class="Step">Let&#39;s add the content now:</p>
  1423. </li>
  1424. </ol>
  1425. <p class="TypedExample">w.Content = TextBlock()</p>
  1426. <p class="Code-Background"></p>
  1427. <p class="TypedExample">w.Content.Text = &quot;Hello IronPython!&quot;</p>
  1428. <p class="Code-Background"></p>
  1429. <p class="TypedExample">w.Content.FontSize = 50</p>
  1430. <p class="Code-Background"></p>
  1431. <ol start="5">
  1432. <li>
  1433. <p class="Step">Remove the window content:</p>
  1434. </li>
  1435. </ol>
  1436. <p class="TypedExample">w.Content = None</p>
  1437. <h3><a name="T2.3.2">Task 2: Avalon calculator</a></h3>
  1438. <ol>
  1439. <li>
  1440. <p class="Step">If you are continuing from the Task 1, proceed to step 2.&nbsp; Otherwise, please follow the <a href="#T2.3.1">steps 1-3</a> from the Task
  1441. 1. </p>
  1442. </li>
  1443. <li>
  1444. <p class="Step">Windows Presentation Foundation uses the XAML format to describe
  1445. the graphical layout and basic behaviors of UI. Load the &quot;calc.xaml&quot; and display the resulting content:</p>
  1446. </li>
  1447. </ol>
  1448. <p class="TypedExample">from avalon import *</p>
  1449. <p class="Code-Background"></p>
  1450. <p class="TypedExample">w = Window()</p>
  1451. <p class="Code-Background"></p>
  1452. <p class="TypedExample">w.Show()</p>
  1453. <p class="Code-Background"></p>
  1454. <p class="TypedExample">w.Content = LoadXaml(&quot;calc.xaml&quot;)</p>
  1455. <p class="Code-Background"></p>
  1456. <p class="Stepnonumbering">If you flowed into this task from Task 1, then
  1457. w.SizeToContent may have been reset to manual, but in either case, you may
  1458. need to manually drag the window's border down and to the right to see the
  1459. calculator UI.</p>
  1460. <ol start="3">
  1461. <li>
  1462. <p class="Step">Let's walk the calculator&#39;s object model (function
  1463. Walk is defined in the avalon.py file)</p>
  1464. </li>
  1465. </ol>
  1466. <p class="TypedExample">for n in Walk(w): print n</p>
  1467. <p class="HiddenOutput">System.Windows.Window</p>
  1468. <p class="LooseVerify">Canvas
  1469. Canvas
  1470. Rectangle
  1471. Canvas</p>
  1472. <p class="HiddenOutput">System.Windows.Controls.TextBox
  1473. System.Windows.Controls.RichTextBox
  1474. System.Windows.Controls.Button: 1
  1475. 1
  1476. System.Windows.Controls.Button: 9
  1477. 9
  1478. System.Windows.Controls.Button: 8
  1479. 8
  1480. System.Windows.Controls.Button: 5
  1481. 5
  1482. System.Windows.Controls.Button: 4
  1483. 4
  1484. System.Windows.Controls.Button: 2
  1485. 2
  1486. System.Windows.Controls.Button: 3
  1487. 3
  1488. System.Windows.Controls.Button: 6
  1489. 6
  1490. System.Windows.Controls.Button: *
  1491. *
  1492. System.Windows.Controls.Button: 7
  1493. 7
  1494. System.Windows.Controls.Button: -
  1495. -
  1496. System.Windows.Controls.Button: 0
  1497. 0
  1498. System.Windows.Controls.Button: .
  1499. .
  1500. System.Windows.Controls.Button: =
  1501. =
  1502. System.Windows.Controls.Button: +
  1503. +
  1504. System.Windows.Controls.Button: /
  1505. /
  1506. System.Windows.Controls.Button: C
  1507. C</p>
  1508. <ol start="4">
  1509. <li>
  1510. <p class="Step">Using Python&#39;s list comprehension syntax we can capture
  1511. all buttons in the calculator:</p>
  1512. </li>
  1513. </ol>
  1514. <p class="TypedExample">[ n for n in Walk(w) if isinstance(n, Button) ]</p>
  1515. <p class="LooseVerify">System.Windows.Controls.Button</p>
  1516. <p class="Stepnonumbering">The console printed the list of all buttons.&nbsp; To
  1517. save the button list object in a variable, use the interpreter's &quot;_&quot;
  1518. variable, which always holds the last non-None value result printed by the
  1519. console:</p>
  1520. <p class="TypedExample">buttons = _</p>
  1521. <p class="Code-Background"></p>
  1522. <ol start="5">
  1523. <li>
  1524. <p class="Step">At this point we can make changes to all the buttons, for
  1525. example, change the colors and fonts:</p>
  1526. </li>
  1527. </ol>
  1528. <p class="TypedExample">for b in buttons: b.FontSize *= 2</p>
  1529. <p class="Code-Background"></p>
  1530. <p class="TypedExample">for b in buttons: b.Foreground = SolidColorBrush(Colors.Blue)</p>
  1531. <p class="Code-Background"></p>
  1532. <ol start="6">
  1533. <li>
  1534. <p class="Step" style="page-break-after:avoid">To bring the calculator alive,
  1535. we need to provide event handlers for each button.&nbsp; These can be imported
  1536. from the calculator.py file:</p>
  1537. </li>
  1538. </ol>
  1539. <p class="TypedExample">import calculator</p>
  1540. <p class="Code-Background"></p>
  1541. <ol start="7">
  1542. <li>
  1543. <p class="Step">The calculator module contains the Calculator class that
  1544. will be responsible for tracking the expression as it is being built by
  1545. the calculator.&nbsp; To bring the calculator alive (that is, register event
  1546. handlers for the UI), enter:</p>
  1547. </li>
  1548. </ol>
  1549. <p class="TypedExample">calculator.enliven(w)</p>
  1550. <p class="HiddenOutput">Registering self.on_One to handle One.Click
  1551. Registering self.on_Nine to handle Nine.Click
  1552. Registering self.on_Eight to handle Eight.Click
  1553. Registering self.on_Five to handle Five.Click
  1554. Registering self.on_Four to handle Four.Click
  1555. Registering self.on_Two to handle Two.Click
  1556. Registering self.on_Three to handle Three.Click
  1557. Registering self.on_Six to handle Six.Click
  1558. Registering self.on_Multiply to handle Multiply.Click
  1559. Registering self.on_Seven to handle Seven.Click
  1560. Registering self.on_Subtract to handle Subtract.Click
  1561. Registering self.on_Zero to handle Zero.Click
  1562. Registering self.on_DecimalPoint to handle DecimalPoint.Click
  1563. Registering self.on_Equals to handle Equals.Click
  1564. Registering self.on_Plus to handle Plus.Click
  1565. Registering self.on_Divide to handle Divide.Click
  1566. Registering self.on_Clear to handle Clear.Click</p>
  1567. <ol start="8">
  1568. <li>
  1569. <p class="Step">At this point you can click on the calculator buttons and
  1570. evaluate expressions.</p>
  1571. </li>
  1572. <li>
  1573. <p class="Step">Feel free to explore the calculator.py script file (located
  1574. in Tutorial directory).&nbsp; The point of interest is the Calculator.__init__
  1575. method:</p>
  1576. </li>
  1577. </ol>
  1578. <p class="CodeSample">def __init__(self, controls):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1579. (1)<br />
  1580. &nbsp;&nbsp;&nbsp; self.expression = &quot;&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1581. (2)<br />
  1582. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1583. (3)<br />
  1584. &nbsp;&nbsp;&nbsp; for i in controls:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1585. (4)<br />
  1586. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if isinstance(i, Button):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1587. (5)<br />
  1588. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if hasattr(self,
  1589. &quot;on_&quot; + i.Name):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1590. (6)<br />
  1591. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1592. i.Click += getattr(self, &quot;on_&quot; + i.Name)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1593. (7)<br />
  1594. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elif isinstance(i, TextBox):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1595. (8)<br />
  1596. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i.Name ==
  1597. &quot;Result&quot;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1598. (9)<br />
  1599. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1600. self.result = i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1601. (10)<br />
  1602. &nbsp;&nbsp;&nbsp; self.result.Text = self.expression&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  1603. (11)</p>
  1604. <p class="Stepnonumbering">The &quot;controls&quot; argument for the method is the list of buttons and
  1605. text boxes, very similar to the list of buttons created in steps 3 and 4 of this task.&nbsp;
  1606. The initialization code enumerates the list (line 4), identifies buttons (line 5), and uses the name of
  1607. the button (&quot;One&quot;, &quot;Multiply&quot;, &quot; Equals&quot;, ...) to find the calculator attribute
  1608. (method) with the corresponding name (for example, &quot;on_One&quot;, &quot;on_Multiply&quot;,
  1609. and &quot;on_Equals&quot;, respectively).&nbsp; If such an attribute (method) is available,
  1610. we hook the Click event event, using the name to fetch the attribute (line 7).</p>
  1611. <ol start="10">
  1612. <li>
  1613. <p class="Step">The second point of interest is the on_Equals method, especially
  1614. the highlighted line.&nbsp; Python has a built-in function, &quot;eval&quot;, which evaluates
  1615. an expression passed as a string and returns the resulting value.&nbsp; Calculator uses &quot;eval&quot;
  1616. to evaluate the calculator expressions.&nbsp; The &quot;str&quot; function will then convert the value
  1617. into a string for display.</p>
  1618. </li>
  1619. </ol>
  1620. <p class="CodeSample">def on_Equals(self, b, e):<br />
  1621. &nbsp;&nbsp;&nbsp; try:<br>
  1622. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result
  1623. = str(eval(self.expression))<br>
  1624. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.result.Text
  1625. = result<br />
  1626. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.expression = result<br />
  1627. &nbsp;&nbsp;&nbsp; except:<br />
  1628. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.result.Text = &quot;&lt;&lt;ERROR&gt;&gt;&quot;<br />
  1629. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.expression = &quot;&quot;</p>
  1630. <ol start="11">
  1631. <li>
  1632. <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
  1633. by Enter)</p>
  1634. </li>
  1635. </ol>
  1636. <p class="LabSummary">Tutorial Summary</p>
  1637. <p class="Body">IronPython provides a very easy way to develop live applications
  1638. in a dynamic and exploratory way. Both Windows Forms and Windows Presentation
  1639. Foundation (Avalon) applications can be easily developed this way with minimal
  1640. setup. The advantage is that changes are visible immediately and modifications
  1641. are happening to a live system and don&#39;t require recompilation.</p>
  1642. <p class="Body">In this tutorial you performed the following exercises:</p>
  1643. <ul>
  1644. <li>
  1645. <p class="ExerciseList"><a href="#T2.1">Events and Delegates</a></p>
  1646. </li>
  1647. <li>
  1648. <p class="ExerciseList"><a href="#T2.2">Windows Forms</a></p>
  1649. </li>
  1650. <li>
  1651. <p class="ExerciseList"><a href="#T2.3">Windows Presentation Foundation
  1652. (Avalon)</a></p>
  1653. </li>
  1654. </ul>
  1655. <p class="Body">&nbsp;</p>
  1656. <p class="Body">In this tutorial, you became familiar with using delegates and
  1657. handling events in IronPython - an essential part of interactive development
  1658. of Windows applications using WinForms or Avalon. Then you dynamically created
  1659. simple interactive application in Windows Forms and created two applications
  1660. using Windows Presentation Foundation. </p>
  1661. <h1><a name="T3">Tutorial 3: IronPython and COM interoperability</a></h1>
  1662. <p class="Body">COM interoperability is an important part of .NET Framework.
  1663. To use COM objects from the .NET application, an interop assembly that contains
  1664. the .NET metadata for the COM objects is required. This tutorial will outline
  1665. how the interop assemblies can be created (in the case they are not provided
  1666. by the creators of the COM object) and will demonstrate the ease with which
  1667. COM objects can be used from IronPython.</p>
  1668. <p class="Body">Estimated time to complete this tutorial: <b>20 minutes</b></p>
  1669. <p class="Body">The objective of this tutorial is to explore COM interoperability
  1670. from IronPython.</p>
  1671. <ul>
  1672. <li>
  1673. <p class="ExerciseList"><a href="#T3.1">Merlin the Wizard</a></p>
  1674. </li>
  1675. <li>
  1676. <p class="ExerciseList"><a href="#T3.2">Word Spell Checking</a></p>
  1677. </li>
  1678. </ul>
  1679. <h2><a name="T3.1">Exercise 1: Merlin the Wizard</a></h2>
  1680. <p class="Body">This exercise consists of two tasks.&nbsp; In the first one we will
  1681. create an interop assembly for a COM object library and explore it using the
  1682. .NET reflection tools.&nbsp; In the second task we will use the COM object library
  1683. from IronPython.</p>
  1684. <p class="Body">In this exercise, you will create a COM interop assembly and
  1685. use it to drive the COM object from IronPython.</p>
  1686. <h3><a name="T3.1.1">Task 1: Creating COM interop assemblies</a></h3>
  1687. <ol>
  1688. <li>
  1689. <p class="Step">Open the &quot;SDK Command Prompt&quot; or &quot;Visual Studio 2005 Command
  1690. Prompt&quot; from the start menu. Note, if you installed IronPython under Program
  1691. Files via the MSI installer, you'll need to run the command prompt as an
  1692. administrator.</p>
  1693. </li>
  1694. <li>
  1695. <p class="Step">The .NET Frameworks SDK comes with the &quot;tlbimp&quot; tool which converts
  1696. a COM type library into .NET metadata information -- the interop assembly.&nbsp; The COM object library we want to use from IronPython
  1697. is msagent, located
  1698. in %SystemRoot%\msagent\agentsvr.exe.&nbsp; Use the tlbimp tool to generate the
  1699. interop assembly for msagent (tlbimp writes to the current directory):</p>
  1700. </li>
  1701. </ol>
  1702. <p class="DOSCommand">tlbimp %SystemRoot%\msagent\agentsvr.exe</p>
  1703. <p class="Code-Highlighted">C:\IronPython\Tutorial&gt;tlbimp %SystemRoot%\msagent\agentsvr.exe<br />
  1704. Microsoft (R) .NET Framework Type Library to Assembly Converter 2.0.50727.42<br />
  1705. Copyright (C) Microsoft Corporation.&nbsp; All rights reserved.<br />
  1706. <br>
  1707. Type library imported to AgentServerObjects.dll</p>
  1708. <ol start="3">
  1709. <li>
  1710. <p class="Step">The .NET metadata information was saved in AgentServerObjects.dll.&nbsp; Use the ildasm tool to explore the generated DLL:</p>
  1711. </li>
  1712. </ol>
  1713. <p class="DOSCommand">ildasm AgentServerObjects.dll</p>
  1714. <ol start="4">
  1715. <li>
  1716. <p class="Step">As you browse the metadata tree, notice that at the root
  1717. of the hierarchy there is the &quot;AgentServerObjects&quot; namespace.&nbsp; The namespace
  1718. contains many interfaces and a single class - AgentServerClass.&nbsp; Explore
  1719. the methods on the class.&nbsp; Calling some of its methods will be the subject
  1720. of the next task.</p>
  1721. </li>
  1722. <li>
  1723. <p class="Step">When you are done exploring the AgentServerObjects.dll,
  1724. close the ildasm tool.&nbsp; Copy AgentServerObjects.dll to the tutorial
  1725. directory, and then close the Windows command prompt.</p>
  1726. </li>
  1727. </ol>
  1728. <h3><a name="T3.1.2">Task 2: Using COM objects from IronPython</a></h3>
  1729. <ol>
  1730. <li>
  1731. <p class="Step">Start the IronPython console from the tutorial directory
  1732. (see <a href="#Intro">Introduction</a> for details).</p>
  1733. </li>
  1734. <li>
  1735. <p class="Step">Using the &quot;AddReferenceToFile&quot; function in the
  1736. clr module,
  1737. add a reference to the AgentServerObjects.dll:</p>
  1738. </li>
  1739. </ol>
  1740. <p class="TypedExample">import clr</p>
  1741. <p class="Code-Background"></p>
  1742. <p class="TypedExample">clr.AddReferenceToFile(&quot;AgentServerObjects.dll&quot;)</p>
  1743. <p class="Code-Background"></p>
  1744. <ol start="3">
  1745. <li>
  1746. <p class="Step">Import the contents of the AgentServerObjects namespace
  1747. and explore the contents using dir():</p>
  1748. </li>
  1749. </ol>
  1750. <p class="TypedExample">from AgentServerObjects import *</p>
  1751. <p class="Code-Background"></p>
  1752. <p class="TypedExample">dir()</p>
  1753. <p class="HiddenOutput">['AgentServer', 'AgentServerClass', 'IAgent', 'IAgentAudioOutputProperties', 'IAgentAudioOutputPropertiesEx', 'IAgentBalloon', 'IAgentBalloonEx', 'IAgentCharacter', 'IAgentCharacterEx', 'IAgentCommand', 'IAgentCommandEx', 'IAgentCommandWindow', 'IAgentCommands', 'IAgentCommandsEx', 'IAgentEx', 'IAgentNotifySink', 'IAgentNotifySinkEx', 'IAgentPropertySheet', 'IAgentSpeechInputProperties', 'IAgentUserInput', '__builtins__', '__doc__', '__name__', 'clr']
  1754. </p>
  1755. <ol start="4">
  1756. <li>
  1757. <p class="Step">Create instance of the AgentServerClass and explore its
  1758. contents:</p>
  1759. </li>
  1760. </ol>
  1761. <p class="TypedExample">a = AgentServerClass()</p>
  1762. <p class="TypedExample">dir(a)</p>
  1763. <p class="Stepnonumbering">The output in the console window will be:</p>
  1764. <p class="Code-Highlighted">&gt;&gt;&gt; a = AgentServerClass()<br />
  1765. &gt;&gt;&gt; dir(a)</p>
  1766. <p class="Code-Background">['CreateObjRef','Equals','GetCharacter','GetCharacterEx','GetHashCode','GetLifetimeService','GetSuspended','GetType','GetVersion','InitializeLifetimeService','Load','MemberwiseClone','ReferenceEquals','Register','ShowDefaultCharacterProperties','ToString','Unload','Unregister','__class__','__delattr__','__doc__','__getattribute__','__hash__','__init__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__str__']</p>
  1767. <ol start="5">
  1768. <li>
  1769. <p class="Step">Load &quot;Merlin the Wizard&quot; character. (The character data
  1770. is stored in c:\WINDOWS\msagent\chars). The Load method returns multiple
  1771. values packed into a tuple - the
  1772. first value is the actual character ID. Capture the character id in the variable:</p>
  1773. </li>
  1774. </ol>
  1775. <p class="TypedExample">cid = clr.Reference[int]()</p>
  1776. <p class="Code-Background"></p>
  1777. <p class="TypedExample">reqid = clr.Reference[int]()</p>
  1778. <p class="Code-Background"></p>
  1779. <p class="TypedExample">a.Load(&quot;Merlin.acs&quot;, cid, reqid)</p>
  1780. <p class="Code-Background"></p>
  1781. <ol start="6">
  1782. <li>
  1783. <p class="Step">Call GetCharacter method on the AgentServerClass instance
  1784. to get the actual character, display the character and have him think about
  1785. IronPython Tutorial:</p>
  1786. </li>
  1787. </ol>
  1788. <p class="TypedExample">from System.Runtime.InteropServices import DispatchWrapper, UnknownWrapper</p>
  1789. <p class="TypedExample">c = clr.StrongBox[object](DispatchWrapper(None))</p>
  1790. <p class="HiddenOutput"></p>
  1791. <p class="TypedExample">a.GetCharacter(cid.Value, c)</p>
  1792. <p class="HiddenOutput"></p>
  1793. <p class="Code-Background"></p>
  1794. <p class="TypedExample">character = c.Value</p>
  1795. <p class="HiddenOutput"></p>
  1796. <p class="TypedExample">character.Show(0, reqid)</p>
  1797. <p class="HiddenOutput"></p>
  1798. <p class="TypedExample">character.Think(&quot;IronPython Tutorial&quot;, reqid)</p>
  1799. <p class="HiddenOutput"></p>
  1800. <ol start="7">
  1801. <li>
  1802. <p class="Step">Merlin has a lot of animations he can play.&nbsp; Get list of
  1803. all the animations by calling the GetAnimationNames method. Play one of the animations,
  1804. &quot;Read&quot;, by calling the Play method:</p>
  1805. </li>
  1806. </ol>
  1807. <p class="TypedExample">enum = clr.StrongBox[object](UnknownWrapper(None))</p>
  1808. <p class="HiddenOutput"></p>
  1809. <p class="TypedExample">character.GetAnimationNames(enum)</p>
  1810. <p class="HiddenOutput"></p>
  1811. <p class="TypedExample">animations = enum.Value</p>
  1812. <p class="HiddenOutput"></p>
  1813. <p class="TypedExample">for n in animations: print n</p>
  1814. <p class="HiddenOutput">RestPose<br>
  1815. Blink<br>
  1816. Idle2_2<br>
  1817. Idle2_1<br>
  1818. Idle1_1<br>
  1819. Idle1_3<br>
  1820. Idle1_2<br>
  1821. Idle1_4<br>
  1822. Greet<br>
  1823. Idle3_1<br>
  1824. GestureUp<br>
  1825. GestureDown<br>
  1826. GestureLeft<br>
  1827. GestureRight<br>
  1828. Show<br>
  1829. Hide<br>
  1830. Hearing_4<br>
  1831. Hearing_1<br>
  1832. Hearing_2<br>
  1833. Hearing_3<br>
  1834. Alert<br>
  1835. Explain<br>
  1836. Processing<br>
  1837. Thinking<br>
  1838. Searching<br>
  1839. Acknowledge<br>
  1840. Wave<br>
  1841. DontRecognize<br>
  1842. Uncertain<br>
  1843. Decline<br>
  1844. Sad<br>
  1845. StopListening<br>
  1846. GetAttention<br>
  1847. GetAttentionReturn<br>
  1848. Idle3_2<br>
  1849. Surprised<br>
  1850. Congratulate_2<br>
  1851. Reading<br>
  1852. Announce<br>
  1853. Read<br>
  1854. ReadReturn<br>
  1855. Writing<br>
  1856. Write<br>
  1857. WriteReturn<br>
  1858. Congratulate<br>
  1859. Confused<br>
  1860. Suggest<br>
  1861. MoveRight<br>
  1862. MoveLeft<br>
  1863. MoveUp<br>
  1864. MoveDown<br>
  1865. StartListening<br>
  1866. WriteContinued<br>
  1867. DoMagic1<br>
  1868. DoMagic2<br>
  1869. LookDown<br>
  1870. LookDownBlink<br>
  1871. LookDownReturn<br>
  1872. LookLeft<br>
  1873. LookLeftBlink<br>
  1874. LookLeftReturn<br>
  1875. LookRight<br>
  1876. LookRightBlink<br>
  1877. LookRightReturn<br>
  1878. LookUp<br>
  1879. LookUpBlink<br>
  1880. LookUpReturn<br>
  1881. ReadContinued<br>
  1882. Pleased<br>
  1883. GetAttentionContinued<br>
  1884. Process<br>
  1885. Search<br>
  1886. Think<br></p>
  1887. <p class="TypedExample">character.Play(&quot;Read&quot;, reqid)</p>
  1888. <p class="HiddenOutput"></p>
  1889. <ol start="8">
  1890. <li>
  1891. <p class="Step">(Optional) To call a series of animations, we could call character.Play(animation_name, reqid)
  1892. for each animation.&nbsp; Python&#39;s lamda functions can simplify this process.&nbsp; We can create global functions and assign them names based on the animation
  1893. name:</p>
  1894. </li>
  1895. </ol>
  1896. <p class="TypedExample">character.GetAnimationNames(enum)</p>
  1897. <p class="HiddenOutput"></p>
  1898. <p class="TypedExample">animations = enum.Value</p>
  1899. <p class="HiddenOutput"></p>
  1900. <p class="TypedExample">for n in animations: globals()[n] = lambda name=n: character.Play(name, reqid)</p>
  1901. <p class="HiddenOutput"></p>
  1902. <p class="Stepnonumbering">At this point we can have Merlin play animations
  1903. simply by calling a function from global namespace:</p>
  1904. <p class="TypedExample">Congratulate()</p>
  1905. <p class="HiddenOutput"></p>
  1906. <p class="Code-Background"></p>
  1907. <ol start="9">
  1908. <li>
  1909. <p class="Step">Stop Merlin&#39;s animations, hide him, and exit IronPython console</p>
  1910. </li>
  1911. </ol>
  1912. <p class="TypedExample">character.StopAll(0)</p>
  1913. <p class="HiddenOutput"></p>
  1914. <p class="TypedExample">character.Hide(0, reqid)</p>
  1915. <p class="HiddenOutput"></p>
  1916. <h2><a name="T3.2">Exercise 2: Use Word for Spell Checking</a></h2>
  1917. <p class="Body">In this exercise you will create an instance of Microsoft
  1918. Word and use it to check word spellings.</p>
  1919. <h3><a name="T3.2.1">Task 1: Accessing Word and Checking Spelling</a></h3>
  1920. <ol>
  1921. <li>
  1922. <p class="Step">Start the IronPython console from the tutorial directory
  1923. (see <a href="#Intro">Introduction</a> for details).</p>
  1924. </li>
  1925. <li>
  1926. <p class="Step">Import clr module and add a reference to the Word COM
  1927. interop assembly.</p>
  1928. </li>
  1929. </ol>
  1930. <p class="TypedExample">import clr</p>
  1931. <p class="Code-Background"></p>
  1932. <p class="TypedExample">clr.AddReferenceByPartialName(&quot;Microsoft.Office.Interop.Word&quot;)</p>
  1933. <p class="Code-Background"></p>
  1934. <p class="TypedExample">from Microsoft.Office.Interop.Word import ApplicationClass</p>
  1935. <p class="Code-Background"></p>
  1936. </p>
  1937. <ol start="3">
  1938. <li>
  1939. <p class="Step">Start an instance of Word as a COM server running.&nbsp;
  1940. You won't see it show up since it is hidden, but you can see it in the
  1941. Windows Task Manager by typing ctrl-shift-escape and looking for the
  1942. WINWORD.EXE process.</p></li>
  1943. </ol>
  1944. <p class="TypedExample">w = ApplicationClass()</p>
  1945. <p class="Code-Background"></p>
  1946. <ol start="4">
  1947. <li>
  1948. <p class="Step">Define the following function to check the spelling.&nbsp;
  1949. Remember to indent the lines of the function's body extra spaces, and you
  1950. have to hit an extra return or enter to complete the function's definition.</p></li>
  1951. </ol>
  1952. <p class="TypedExample">def check_word (word):<br>
  1953. &nbsp;&nbsp; return w.CheckSpelling(word)</p>
  1954. <p class="Code-Background"></p>
  1955. <p class="TypedExample">check_word(&quot;foo&quot;)</p>
  1956. <p class="HiddenOutput">False</p>
  1957. <p class="TypedExample">check_word(&quot;food&quot;)</p>
  1958. <p class="HiddenOutput">True</p>
  1959. <ol start="5">
  1960. <li>
  1961. <p class="Step">You can try that out on a couple of words, but now lets
  1962. define a function that will suggest corrections for us.&nbsp; First, we
  1963. need to add a document so that we can call GetSpellingSuggestions(),
  1964. which gives a nice error message if you try to call it with no documents
  1965. opened.</p></li>
  1966. </ol>
  1967. <p class="TypedExample">w.Documents.Add()</p>
  1968. <p class="LooseVerify">Microsoft.Office.Interop.Word.DocumentClass</p>
  1969. <ol start="6">
  1970. <li>
  1971. <p class="Step">The first result of
  1972. several return values from GetSpellingSuggestions() is a collection of
  1973. items, each of which is a correction suggestion.&nbsp; We use a Python
  1974. list comprehension to iterate through the COM collection object and call
  1975. the Name property on each item object in the collection.&nbsp; Each
  1976. item's Name property is a string that Word is suggesting as a correct
  1977. spelling.</p></li>
  1978. </ol>
  1979. <p class="TypedExample">def suggestions(word):<br>
  1980. &nbsp;&nbsp; res_objects = w.GetSpellingSuggestions(word)<br>
  1981. &nbsp;&nbsp; return [x.Name for x in res_objects]</p>
  1982. <p class="Code-Background"></p>
  1983. <ol start="7">
  1984. <li>
  1985. <p class="Step">Now, let's shut down Word and exit the IronPython
  1986. console.&nbsp; When you enter the next line and hit return, if you are
  1987. watching the Windows Task Manager, you will see the WINWORD.EXE process
  1988. go away.</p></li>
  1989. </ol>
  1990. <p class="TypedExample">w.Quit()</p>
  1991. <p class="Code-Background"></p>
  1992. <h3><a name="T3.2.2">Task 2: Use Windows Form Dialog to Correct Spelling</a></h3>
  1993. <p class="Body">In this task you will use an example already written that is
  1994. very similar to what you did in Task 1, but it demonstrates two additional
  1995. features.&nbsp; It uses a Python standard module to register a clean up
  1996. function so that when the IronPython console terminates, the Word process is
  1997. closed.&nbsp; The example also has a function, correct_word, that uses a
  1998. Windows Form as a dialog to let users select a correct word to return.</p>
  1999. <ol>
  2000. <li>
  2001. <p class="Step">Start the IronPython console from the tutorial directory
  2002. (see <a href="#Intro">Introduction</a> for details).</p>
  2003. </li>
  2004. <li>
  2005. <p class="Step">Import spellcheck.</p>
  2006. </li>
  2007. <li>
  2008. <p class="Step">Call spellcheck.correct_word on a correctly spelled
  2009. word, and you'll see the function returns the word.</p>
  2010. </li>
  2011. <li>
  2012. <p class="Step">Call spellcheck.correct_word on a misspelled word, and a
  2013. Windows Form similar to Word's spelling correction dialog appears.&nbsp;
  2014. You can pick from the list and click the Replace button, double click a
  2015. word in the suggestions list, enter custom text and click the Use Custom
  2016. button, click an Ignore button to return the misspelled word, and so on. </p>
  2017. </li>
  2018. <li>
  2019. <p class="Step">Open the spellcheck.py file to see the code for the the
  2020. Windows Form as well as the functions.</li>
  2021. </ol>
  2022. <p class="Body">&nbsp;</p>
  2023. <p class="LabSummary">Tutorial Summary</p>
  2024. <p class="Body">This tutorial was focused on using COM interop assemblies generated
  2025. via tlbimp tool (in the .NET Framework SDK) to control COM objects from the IronPython environment.</p>
  2026. <p class="Body">In this tutorial you performed the following exercises.</p>
  2027. <ul>
  2028. <li>
  2029. <p class="ExerciseList"><a href="#T3.1">Merlin the Wizard</a></p>
  2030. </li>
  2031. <li>
  2032. <p class="ExerciseList"><a href="#T3.2">Word Spell Checking</a></p>
  2033. </li>
  2034. </ul>
  2035. <p class="Body">&nbsp;</p>
  2036. <p class="Body">In this tutorial, you created a COM interop assembly for the
  2037. msagent COM object.&nbsp; You used the tlbimp tool which is part of the .NET Framework
  2038. SDK.&nbsp; Using the ildasm tool, you explored contents of the interop assembly.</p>
  2039. <p class="Body">Then, from IronPython you loaded the interop assembly, created
  2040. an instance of the COM object, and instructed Merlin to play different animations.</p>
  2041. <p class="Body">You also used Word to check the spelling of words, learned
  2042. how to supply missing optional arguments, and inspected code that builds a
  2043. Windows Form and uses it as a dialog.</p>
  2044. <p class="Normal">&nbsp;</p>
  2045. <h1><a name="T4">Tutorial 4: Debugging IronPython program</a></h1>
  2046. <p class="Body">This tutorial will walk you through very simple debug session,
  2047. debugging a Python script using Microsoft CLR Debugger.&nbsp; See
  2048. <a href="#T7">using Visual Studio</a> if you have a Visual Studio SKU and
  2049. consider skipping this exercise.</p>
  2050. <p class="Body">Estimated time to complete this tutorial: <b>10 minutes</b></p>
  2051. <p class="Body">The objective of this tutorial is debugging simple Python script
  2052. using Microsoft CLR Debugger.</p>
  2053. <ul>
  2054. <li>
  2055. <p class="Body"><a href="#T4.1">Debugging IronPython program</a></p>
  2056. </li>
  2057. </ul>
  2058. <h2><a name="T4.1">Exercise 1: Debugging IronPython program</a></h2>
  2059. <p class="Body">In this exercise, you will step through a simple Python script
  2060. in the Microsoft CLR Debugger.</p>
  2061. <h3><a name="T4.1.1">Task 1: Debugging IronPython program using Microsoft CLR
  2062. Debugger</a></h3>
  2063. <ol>
  2064. <li>
  2065. <p class="Step">Launch Microsoft CLR Debugger. </p>
  2066. </li>
  2067. <li>
  2068. <p class="Step">From the debugger Menu, select Debug / Program to Debug
  2069. ...</p>
  2070. </li>
  2071. <li>
  2072. <p class="Step">For Program, browse to the ipy.exe (located
  2073. in the installaton directory)</p>
  2074. </li>
  2075. <li>
  2076. <p class="Step">For Arguments, type in debugging.py</p>
  2077. </li>
  2078. <li>
  2079. <p class="Step">Change Working directory to the Tutorial directory</p>
  2080. </li>
  2081. <li>
  2082. <p class="Step">Click OK</p>
  2083. </li>
  2084. <li>
  2085. <p class="Step">From Menu, select File / Open / File. Browse to the Tutorial
  2086. directory and select two files to open:</p>
  2087. </li>
  2088. </ol>
  2089. <p class="Body">debugging.py</p>
  2090. <p class="Body">first.py</p>
  2091. <ol start="8">
  2092. <li>
  2093. <p class="Step">Place breakpoint at the following line of the debugging.py
  2094. file (Place cursor on the line and pres F9):</p>
  2095. </li>
  2096. </ol>
  2097. <p class="Body">print first.add(1, 2)</p>
  2098. <ol start="9">
  2099. <li>
  2100. <p class="Step">Press F5 - Start Debugging.</p>
  2101. </li>
  2102. </ol>
  2103. <p class="Stepnonumbering">IronPython will compile the debugging.py file and
  2104. start executing it. You will hit the breakpoint at the line 3.</p>
  2105. <p class="StepNote">Note: If you get poor performance starting the debugging
  2106. session, exit the debugger, open the Windows Explorer and delete the following
  2107. directory:</p>
  2108. <p class="StepNote">%USERPROFILE%\Application Data\Microsoft\DbgClr</p>
  2109. <ol start="10">
  2110. <li>
  2111. <p class="Step">Pressing F11, step through the execution of the program,
  2112. explore variables (even change the values of the variables in the watch
  2113. window) and explore the call stack. </p>
  2114. </li>
  2115. <li>
  2116. <p class="Step">End the debugging session and exit the debugger.</p>
  2117. </li>
  2118. </ol>
  2119. <p class="LabSummary">Tutorial Summary</p>
  2120. <p class="Body">In this tutorial you performed the following exercises.</p>
  2121. <ul>
  2122. <li>
  2123. <p class="Body"><a href="#T4.1">Debugging IronPython program</a></p>
  2124. </li>
  2125. </ul>
  2126. <p class="Body">In this tutorial, you walked through the simple debug session
  2127. of IronPython program. You used Microsoft CLR Debugger, placed breakpoints and
  2128. stepped through the Python program execution.</p>
  2129. <p class="Body">&nbsp;</p>
  2130. <h1><a name="T5">Tutorial 5: Extending IronPython</a></h1>
  2131. <p class="Body">Estimated time to complete this tutorial: <b>25- 60 minutes</b></p>
  2132. <p class="Body">The objective of this tutorial is to implement the class which
  2133. will seamlessly fit into the IronPython environment. You can choose to follow
  2134. Exercise 1 - C# implementation, Exercise 2 - Visual Basic, or both. Both tracks
  2135. will result in the same functionality.</p>
  2136. <ul>
  2137. <li>
  2138. <p class="Body"><a href="#T5.1">Extending using C#</a></p>
  2139. </li>
  2140. <li>
  2141. <p class="Body"><a href="#T5.2">Extending using Visual Basic.NET</a></p>
  2142. </li>
  2143. </ul>
  2144. <h2><a name="T5.1">Exercise 1: Extending using C#</a></h2>
  2145. <p class="Body">In this exercise you will use C# language to build a class that
  2146. supports enumeration, custom operators and delegates and you will use that class
  2147. from IronPython. It’s worth noting that as Python does not contain protected class members,
  2148. these members get promoted to public class members when imported into Python. Private
  2149. class members, however, will be invisible to Python when imported.</p>
  2150. <h3><a name="T5.1.1">Task 1: Implementing simple class - constructor and ToString</a></h3>
  2151. <ol>
  2152. <li>
  2153. <p class="Step">Open the &quot;SDK Command Prompt&quot; or &quot;Visual Studio 2005 Command
  2154. Prompt&quot; from the start menu.</p>
  2155. </li>
  2156. <li>
  2157. <p class="Step">Open the &quot;csextend.cs&quot; file in notepad. The file is initially
  2158. empty</p>
  2159. </li>
  2160. </ol>
  2161. <p class="DOSExample">notepad csextend.cs</p>
  2162. <ol start="3">
  2163. <li>
  2164. <p class="Step">Add using clauses at the beginning of the file:</p>
  2165. </li>
  2166. </ol>
  2167. <p class="CodeSample">using System;<br />
  2168. using System.Collections;</p>
  2169. <ol start="4">
  2170. <li>
  2171. <p class="Step">Define a simple class:</p>
  2172. </li>
  2173. </ol>
  2174. <p class="CodeSample">public class Simple {<br />
  2175. &nbsp;&nbsp;&nbsp; private int data;<br>
  2176. <br />
  2177. &nbsp;&nbsp;&nbsp; public Simple(int data) {<br />
  2178. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.data = data;<br />
  2179. &nbsp;&nbsp;&nbsp; }<br>
  2180. <br />
  2181. &nbsp;&nbsp;&nbsp; public override string ToString() {<br />
  2182. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data);<br />
  2183. &nbsp;&nbsp;&nbsp; }<br />
  2184. }</p>
  2185. <ol start="5">
  2186. <li>
  2187. <p class="Step">Switch back to the SDK Command Prompt window and build the
  2188. code using available csx.bat (C# extension):</p>
  2189. </li>
  2190. </ol>
  2191. <p class="DOSExample">csx</p>
  2192. <ol start="6">
  2193. <li>
  2194. <p class="Step">Start the IronPython console from the tutorial directory
  2195. (see <a href="#Intro">Introduction</a> for details).</p>
  2196. </li>
  2197. </ol>
  2198. <ol start="7">
  2199. <li>
  2200. <p class="Step">Load the dll that you just built (csextend.dll) into IronPython.
  2201. Then explore the Simple class using built-in dir() function:</p>
  2202. </li>
  2203. </ol>
  2204. <p class="TypedExample">import clr</p>
  2205. <p class="Code-Background"></p>
  2206. <p class="UserCode">clr.AddReferenceToFile(&quot;csextend.dll&quot;)</p>
  2207. <p class="HiddenCode">clr.AddReferenceToFile(&quot;csextend_5.1.1.dll&quot;)</p>
  2208. <p class="Code-Background"></p>
  2209. <p class="TypedExample">import Simple</p>
  2210. <p class="Code-Background"></p>
  2211. <p class="UserCode">dir(Simple)</p>
  2212. <p class="HiddenCode">set1 = set(dir(Simple))
  2213. set2 = set(dir(object))
  2214. list(set1-set2)</p>
  2215. <p class="HiddenOutput">
  2216. []</p>
  2217. <p class="Stepnonumbering">You will see following output:</p>
  2218. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2219. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;csextend.dll&quot;)<br />
  2220. &gt;&gt;&gt; import Simple<br />
  2221. &gt;&gt;&gt; dir(Simple)</p>
  2222. <p class="Code-Highlighted">['Equals', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
  2223. <ol start="8">
  2224. <li>
  2225. <p class="Step">Create instance of the Simple class:</p>
  2226. </li>
  2227. </ol>
  2228. <p class="TypedExample">s = Simple(10)</p>
  2229. <p class="Code-Background"></p>
  2230. <p class="TypedExample">print s</p>
  2231. <p class="Stepnonumbering">IronPython will output:</p>
  2232. <p class="Code-Highlighted">&gt;&gt;&gt; s = Simple(10)<br />
  2233. &gt;&gt;&gt; print s</p>
  2234. <p class="Code-Background">Simple&lt;10&gt;</p>
  2235. <ol start="9">
  2236. <li>
  2237. <p class="Step">You have just explored all the functionality currently available
  2238. in the Simple class. Exit IronPython and return back to the C# code to add
  2239. more functionality.</p>
  2240. </li>
  2241. </ol>
  2242. <h3><a name="T5.1.2">Task 2: Making the object enumerable</a></h3>
  2243. <ol>
  2244. <li>
  2245. <p class="Step">In Notepad, add more functionality to the Simple class.</p>
  2246. </li>
  2247. <li>
  2248. <p class="Step">First, inherit the Simple class from IEnumerable and implement
  2249. GetEnumerator() method. Use the C#&#39;s new &quot;yield return&quot; statement:</p>
  2250. </li>
  2251. </ol>
  2252. <p class="CodeSample">public class Simple : IEnumerable {<br>
  2253. <br />
  2254. &nbsp;&nbsp;&nbsp; private int data;<br />
  2255. &nbsp;&nbsp;&nbsp; public Simple(int data) {<br />
  2256. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.data = data;<br />
  2257. &nbsp;&nbsp;&nbsp; }<br />
  2258. &nbsp;&nbsp;&nbsp; public override string ToString() {<br />
  2259. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data);<br />
  2260. &nbsp;&nbsp;&nbsp; }<br />
  2261. &nbsp;<br>
  2262. &nbsp;&nbsp;&nbsp; public IEnumerator GetEnumerator()
  2263. {<br />
  2264. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; data; i ++) {<br />
  2265. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return
  2266. new Simple(i);<br />
  2267. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
  2268. &nbsp;&nbsp;&nbsp; }</p>
  2269. <p class="CodeSample">}</p>
  2270. <ol start="3">
  2271. <li>
  2272. <p class="Step">Save the changes, compile the code (csx), launch IronPython
  2273. Console (ip) and test the code:</p>
  2274. </li>
  2275. </ol>
  2276. <p class="TypedExample">import clr</p>
  2277. <p class="Code-Background"></p>
  2278. <p class="UserCode">clr.AddReferenceToFile(&quot;csextend.dll&quot;)</p>
  2279. <p class="HiddenCode">clr.AddReferenceToFile(&quot;csextend_5.1.2.dll&quot;)</p>
  2280. <p class="Code-Background"></p>
  2281. <p class="TypedExample">import Simple</p>
  2282. <p class="Code-Background"></p>
  2283. <p class="UserCode">dir(Simple)</p>
  2284. <p class="HiddenCode">set1 = set(dir(Simple))
  2285. set2 = set(dir(object))
  2286. list(set1-set2)</p>
  2287. <p class="HiddenOutput">
  2288. ['GetEnumerator', '__iter__']</p>
  2289. <p class="Code-Highlighted">['Equals', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
  2290. <p class="TypedExample">s = Simple(10)</p>
  2291. <p class="Code-Background"></p>
  2292. <p class="TypedExample">for i in s: print i</p>
  2293. <p class="Stepnonumbering">You will get the following output in the IronPython
  2294. console window:</p>
  2295. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2296. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;csextend.dll&quot;)<br />
  2297. &gt;&gt;&gt; import Simple<br />
  2298. &gt;&gt;&gt; dir(Simple)<br />
  2299. &gt;&gt;&gt; s = Simple(10)</p>
  2300. <p class="Code-Highlighted">&gt;&gt;&gt; for i in s: print i</p>
  2301. <p class="Code-Background">Simple&lt;0&gt;<br />
  2302. Simple&lt;1&gt;<br />
  2303. Simple&lt;2&gt;<br />
  2304. Simple&lt;3&gt;<br />
  2305. Simple&lt;4&gt;<br />
  2306. Simple&lt;5&gt;<br />
  2307. Simple&lt;6&gt;<br />
  2308. Simple&lt;7&gt;<br />
  2309. Simple&lt;8&gt;<br />
  2310. Simple&lt;9&gt;</p>
  2311. <p class="StepNote">Notice that the dir() function now returned the GetEnumerator
  2312. method.</p>
  2313. <ol start="4">
  2314. <li>
  2315. <p class="Step">Exit IronPython and return back to the C# code to add more
  2316. functionality.</p>
  2317. </li>
  2318. </ol>
  2319. <h3><a name="T5.1.3">Task 3: Adding custom operator</a></h3>
  2320. <ol>
  2321. <li>
  2322. <p class="Step">Add the operator + method:</p>
  2323. </li>
  2324. </ol>
  2325. <p class="CodeSample">using System;<br />
  2326. using System.Collections;</br>
  2327. <br />
  2328. public class Simple : IEnumerable {<br />
  2329. &nbsp;&nbsp;&nbsp; private int data;<br />
  2330. &nbsp;&nbsp;&nbsp; public Simple(int data) {<br />
  2331. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.data = data;<br />
  2332. &nbsp;&nbsp;&nbsp; }<br />
  2333. &nbsp;&nbsp;&nbsp; public override string ToString() {<br />
  2334. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data);<br />
  2335. &nbsp;&nbsp;&nbsp; }<br />
  2336. &nbsp;&nbsp;&nbsp; public IEnumerator GetEnumerator() {<br />
  2337. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; data; i ++) {<br />
  2338. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return
  2339. new Simple(i);<br />
  2340. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
  2341. &nbsp;&nbsp;&nbsp; }<br />
  2342. &nbsp;</br>
  2343. &nbsp;&nbsp;&nbsp; public static Simple operator
  2344. +(Simple a, Simple b) {<br />
  2345. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Simple(a.data + b.data);<br />
  2346. &nbsp;&nbsp;&nbsp; }</br>
  2347. }</p>
  2348. <ol start="2">
  2349. <li>
  2350. <p class="Step">Return to the command prompt, compile the code (csx), launch
  2351. IronPython Console (ip) and test the code:</p>
  2352. </li>
  2353. </ol>
  2354. <p class="TypedExample">import clr</p>
  2355. <p class="Code-Background"></p>
  2356. <p class="UserCode">clr.AddReferenceToFile(&quot;csextend.dll&quot;)</p>
  2357. <p class="HiddenCode">clr.AddReferenceToFile(&quot;csextend_5.1.3.dll&quot;)</p>
  2358. <p class="Code-Background"></p>
  2359. <p class="TypedExample">import Simple</p>
  2360. <p class="Code-Background"></p>
  2361. <p class="UserCode">dir(Simple)</p>
  2362. <p class="HiddenCode">set1 = set(dir(Simple))
  2363. set2 = set(dir(object))
  2364. list(set1-set2)</p>
  2365. <p class="HiddenOutput">
  2366. ['GetEnumerator', '__iter__', '__radd__', '__add__']</p>
  2367. <p class="TypedExample">a = Simple(10)</p>
  2368. <p class="Code-Background"></p>
  2369. <p class="TypedExample">b = Simple(20)</p>
  2370. <p class="Code-Background"></p>
  2371. <p class="TypedExample">a + b</p>
  2372. <p class="LooseVerify">Simple&lt;30</p>
  2373. <p class="Stepnonumbering">Notice that in the output of dir() call you will
  2374. now get additional methods __add__ and __radd__, Python&#39;s notion of custom operator
  2375. implementation:</p>
  2376. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2377. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;csextend.dll&quot;)<br />
  2378. &gt;&gt;&gt; import Simple<br />
  2379. &gt;&gt;&gt; dir(Simple)<br />
  2380. &gt;&gt;&gt; a = Simple(10)<br />
  2381. &gt;&gt;&gt; b = Simple(20)</p>
  2382. <p class="Code-Highlighted">&gt;&gt;&gt; a + b<br />
  2383. &lt;Simple object at 0x000000000000002B [Simple&lt;30]</p>
  2384. <ol start="3">
  2385. <li>
  2386. <p class="Step">Exit IronPython and return back to the C# code to add more
  2387. functionality.</p>
  2388. </li>
  2389. </ol>
  2390. <h3><a name="T5.1.4">Task 4: Adding delegate</a></h3>
  2391. <ol>
  2392. <li>
  2393. <p class="Step">Add the definition of the delegate to the top of the C#
  2394. source file:</p>
  2395. </li>
  2396. </ol>
  2397. <p class="CodeSample">using System;<br />
  2398. using System.Collections;<br />
  2399. &nbsp;<br>
  2400. public delegate int Transformer(int input);</p>
  2401. <ol start="2">
  2402. <li>
  2403. <p class="Step">Add &quot;Transform&quot; method to the Simple class that takes the
  2404. delegate as a parameter and invokes the delegate:</p>
  2405. </li>
  2406. </ol>
  2407. <p class="CodeSample">using System;<br />
  2408. using System.Collections;<br />
  2409. &nbsp;<br>
  2410. public delegate int Transformer(int input);<br>
  2411. <br />
  2412. public class Simple : IEnumerable {<br />
  2413. &nbsp;&nbsp;&nbsp; private int data;<br />
  2414. &nbsp;&nbsp;&nbsp; public Simple(int data) {<br />
  2415. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.data = data;<br />
  2416. &nbsp;&nbsp;&nbsp; }<br>
  2417. <br />
  2418. &nbsp;&nbsp;&nbsp; public override string ToString() {<br />
  2419. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data);<br />
  2420. &nbsp;&nbsp;&nbsp; }<br>
  2421. <br />
  2422. &nbsp;&nbsp;&nbsp; public IEnumerator GetEnumerator() {<br />
  2423. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; data; i ++) {<br />
  2424. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return
  2425. new Simple(i);<br />
  2426. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
  2427. &nbsp;&nbsp;&nbsp; }<br />
  2428. &nbsp;<br>
  2429. &nbsp;&nbsp;&nbsp; public int Transform(Transformer
  2430. t) {<br />
  2431. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return t(data);<br />
  2432. &nbsp;&nbsp;&nbsp; }<br>
  2433. <br />
  2434. &nbsp;&nbsp;&nbsp; public static Simple operator +(Simple a, Simple b) {<br />
  2435. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Simple(a.data + b.data);<br />
  2436. &nbsp;&nbsp;&nbsp; }<br />
  2437. }</p>
  2438. <ol start="3">
  2439. <li>
  2440. <p class="Step">Return back to the SDK command prompt, compile the code
  2441. (csx), launch IronPython Console (ip) and test the code:</p>
  2442. </li>
  2443. </ol>
  2444. <p class="TypedExample">import clr</p>
  2445. <p class="Code-Background"></p>
  2446. <p class="UserCode">clr.AddReferenceToFile(&quot;csextend.dll&quot;)</p>
  2447. <p class="HiddenCode">clr.AddReferenceToFile(&quot;csextend_5.1.4.dll&quot;)</p>
  2448. <p class="Code-Background"></p>
  2449. <p class="TypedExample">import Simple</p>
  2450. <p class="Code-Background"></p>
  2451. <p class="TypedExample">a = Simple(10)</p>
  2452. <p class="Code-Background"></p>
  2453. <p class="TypedExample">def X(i):<br>
  2454. &nbsp;&nbsp;&nbsp; return i + 100</p>
  2455. <p class="Code-Background"></p>
  2456. <p class="TypedExample">a.Transform(X)</p>
  2457. <p class="Stepnonumbering">The function X is getting passed as the delegate
  2458. to the Simple&#39;s Transform method. You will get following output:</p>
  2459. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2460. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;csextend.dll&quot;)<br />
  2461. &gt;&gt;&gt; import Simple<br />
  2462. &gt;&gt;&gt; a = Simple(10)</p>
  2463. <p class="Code-Highlighted">&gt;&gt;&gt; def X(i):<br />
  2464. ...&nbsp;&nbsp;&nbsp;&nbsp; return i + 100<br />
  2465. ...<br />
  2466. &gt;&gt;&gt; a.Transform(X)</p>
  2467. <p class="Code-Background">110</p>
  2468. <ol start="4">
  2469. <li>
  2470. <p class="Step">This concludes the C# extending example. If you are interested,
  2471. an interesting exercise is combining the debugging example and the extending
  2472. one. If you are inspired to do so, try debugging the script that you just
  2473. typed in. Debug the &quot;debugcsx.py&quot; script located in Tutorial directory and
  2474. place a breakpoint on the X function - you will see mixed call stack between
  2475. C# and Python.</p>
  2476. </li>
  2477. </ol>
  2478. <h2><a name="T5.2">Exercise 2: Extending using Visual Basic.NET</a></h2>
  2479. <p class="Body">In this exercise you will use Visual Basic .NET language to
  2480. build a class that supports enumeration, custom operators and delegates and
  2481. you will use that class from IronPython. It’s worth noting that as Python does not contain protected
  2482. class members, that these members get promoted to public class members when imported into Python.
  2483. Private class members, however, will be invisible to Python when imported.</p>
  2484. <h3><a name="T5.2.1">Task 1: Implementing simple class - constructor and ToString</a></h3>
  2485. <ol>
  2486. <li>
  2487. <p class="Step">Open the &quot;SDK Command Prompt&quot; or &quot;Visual Studio 2005 Command
  2488. Prompt&quot; from the start menu.</p>
  2489. </li>
  2490. <li>
  2491. <p class="Step">Open the &quot;vbextend.vb&quot; file in notepad. The file is initially
  2492. empty</p>
  2493. </li>
  2494. </ol>
  2495. <p class="DOSExample">notepad vbextend.vb</p>
  2496. <ol start="3">
  2497. <li>
  2498. <p class="Step">Add Imports clauses at the beginning of the file:</p>
  2499. </li>
  2500. </ol>
  2501. <p class="CodeSample">Imports System<br />
  2502. Imports System.Collections</p>
  2503. <ol start="4">
  2504. <li>
  2505. <p class="Step">Define a simple class:</p>
  2506. </li>
  2507. </ol>
  2508. <p class="CodeSample">Public Class Simple<br />
  2509. &nbsp;&nbsp;&nbsp; Private data As Integer<br />
  2510. <br />
  2511. &nbsp;&nbsp;&nbsp; Public Sub New(ByVal data As Integer)<br />
  2512. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.data = data<br />
  2513. &nbsp;&nbsp;&nbsp; End Sub<br />
  2514. <br />
  2515. &nbsp;&nbsp;&nbsp; Overrides Function ToString() As String<br />
  2516. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data)<br />
  2517. &nbsp;&nbsp;&nbsp; End Function<br />
  2518. &nbsp;</p>
  2519. <p class="CodeSample">End Class</p>
  2520. <ol start="5">
  2521. <li>
  2522. <p class="Step">Switch back to the SDK Command Prompt window and build the
  2523. code using the available vbx.bat (Visual Basic extension):</p>
  2524. </li>
  2525. </ol>
  2526. <p class="DOSExample">vbx</p>
  2527. <ol start="6">
  2528. <li>
  2529. <p class="Step">Start the IronPython console from the tutorial directory
  2530. (see <a href="#Intro">Introduction</a> for details).</p>
  2531. </li>
  2532. </ol>
  2533. <ol start="7">
  2534. <li>
  2535. <p class="Step">Load the dll that you just built (vbextend.dll) into IronPython.
  2536. Then explore the Simple class using built-in dir() function:</p>
  2537. </li>
  2538. </ol>
  2539. <p class="TypedExample">import clr</p>
  2540. <p class="Code-Background"></p>
  2541. <p class="UserCode">clr.AddReferenceToFile(&quot;vbextend.dll&quot;)</p>
  2542. <p class="HiddenCode">clr.AddReferenceToFile(&quot;vbextend_5.2.1.dll&quot;)</p>
  2543. <p class="Code-Background"></p>
  2544. <p class="TypedExample">import Simple</p>
  2545. <p class="Code-Background"></p>
  2546. <p class="UserCode">dir(Simple)</p>
  2547. <p class="HiddenCode">set1 = set(dir(Simple))
  2548. set2 = set(dir(object))
  2549. list(set1-set2)</p>
  2550. <p class="HiddenOutput">
  2551. []</p>
  2552. <p class="Stepnonumbering">You will see following output:</p>
  2553. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2554. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;vbextend.dll&quot;)<br />
  2555. &gt;&gt;&gt; import Simple<br />
  2556. &gt;&gt;&gt; dir(Simple)</p>
  2557. <p class="Code-Highlighted">['Equals', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
  2558. <ol start="8">
  2559. <li>
  2560. <p class="Step">Create instance of the Simple class:</p>
  2561. </li>
  2562. </ol>
  2563. <p class="TypedExample">s = Simple(10)</p>
  2564. <p class="Code-Background"></p>
  2565. <p class="TypedExample">print s</p>
  2566. <p class="Stepnonumbering">IronPython will output:</p>
  2567. <p class="Code-Highlighted">&gt;&gt;&gt; s = Simple(10)<br />
  2568. &gt;&gt;&gt; print s</p>
  2569. <p class="Code-Background">Simple&lt;10&gt;</p>
  2570. <ol start="9">
  2571. <li>
  2572. <p class="Step">You just have explored all the functionality available in
  2573. the Simple class. Exit IronPython and return back to the Visual Basic code
  2574. to add more functionality.</p>
  2575. </li>
  2576. </ol>
  2577. <h3><a name="T5.2.2">Task 2: Making the object enumerable</a></h3>
  2578. <ol>
  2579. <li>
  2580. <p class="Step">Back in Notepad, add more functionality to the vbextend.vb,
  2581. Simple class</p>
  2582. </li>
  2583. <li>
  2584. <p class="Step">First, inherit the Simple class from IEnumerable and implement
  2585. GetEnumerator() method. Unlike C#, Visual Basic does not offer the yield
  2586. keyword so implementing IEnumerable interface requires adding a helper class
  2587. SimpleEnum:</p>
  2588. </li>
  2589. </ol>
  2590. <p class="CodeSample">Imports System<br />
  2591. Imports System.Collections<br />
  2592. &nbsp;</p>
  2593. <p class="CodeSample">Public Class SimpleEnum<br />
  2594. &nbsp;&nbsp;&nbsp; Implements IEnumerator<br />
  2595. <br />
  2596. &nbsp;&nbsp;&nbsp; Private data As Integer<br />
  2597. &nbsp;&nbsp;&nbsp; Private curr As Integer<br />
  2598. <br />
  2599. &nbsp;&nbsp;&nbsp; Public Sub New(ByVal data As Integer)<br />
  2600. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.data = data<br />
  2601. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.curr = -1<br />
  2602. &nbsp;&nbsp;&nbsp; End Sub<br />
  2603. <br />
  2604. &nbsp;&nbsp;&nbsp; Public ReadOnly Property Current() As Object _<br />
  2605. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Implements IEnumerator.Current<br />
  2606. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br />
  2607. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return New Simple(curr)<br />
  2608. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br />
  2609. &nbsp;&nbsp;&nbsp; End Property<br />
  2610. <br />
  2611. &nbsp;&nbsp;&nbsp; Public Function MoveNext() As Boolean _<br />
  2612. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  2613. Implements IEnumerator.MoveNext<br />
  2614. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curr += 1<br />
  2615. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return curr &lt; data<br />
  2616. &nbsp;&nbsp;&nbsp; End Function<br />
  2617. <br />
  2618. &nbsp;&nbsp;&nbsp; Public Sub Reset() Implements IEnumerator.Reset<br />
  2619. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curr = -1<br />
  2620. &nbsp;&nbsp;&nbsp; End Sub<br />
  2621. End Class</p>
  2622. <p class="CodeSample"><br />
  2623. Public Class Simple</p>
  2624. <p class="CodeSample">&nbsp;&nbsp;&nbsp; Implements IEnumerable</p>
  2625. <p class="CodeSample">&nbsp;&nbsp;&nbsp; Private data As Integer<br />
  2626. <br />
  2627. &nbsp;&nbsp;&nbsp; Public Sub New(ByVal data As Integer)<br />
  2628. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.data = data<br />
  2629. &nbsp;&nbsp;&nbsp; End Sub<br />
  2630. <br />
  2631. &nbsp;&nbsp;&nbsp; Overrides Function ToString() As String<br />
  2632. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data)<br />
  2633. &nbsp;&nbsp;&nbsp; End Function<br />
  2634. &nbsp;</p>
  2635. <p class="CodeSample">&nbsp;&nbsp;&nbsp; Function GetEnumerator() As IEnumerator
  2636. _<br />
  2637. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  2638. Implements IEnumerable.GetEnumerator<br />
  2639. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return New SimpleEnum(data)<br />
  2640. &nbsp;&nbsp;&nbsp; End Function</p>
  2641. <p class="CodeSample"><br />
  2642. End Class</p>
  2643. <ol start="3">
  2644. <li>
  2645. <p class="Step">Compile the code (vbx), launch IronPython Console (ip) and
  2646. test the code:</p>
  2647. </li>
  2648. </ol>
  2649. <p class="TypedExample">import clr</p>
  2650. <p class="Code-Background"></p>
  2651. <p class="UserCode">clr.AddReferenceToFile(&quot;vbextend.dll&quot;)</p>
  2652. <p class="HiddenCode">clr.AddReferenceToFile(&quot;vbextend_5.2.2.dll&quot;)</p>
  2653. <p class="Code-Background"></p>
  2654. <p class="TypedExample">import Simple</p>
  2655. <p class="Code-Background"></p>
  2656. <p class="UserCode">dir(Simple)</p>
  2657. <p class="HiddenCode">set1 = set(dir(Simple))
  2658. set2 = set(dir(object))
  2659. list(set1-set2)</p>
  2660. <p class="HiddenOutput">
  2661. ['GetEnumerator', '__iter__']</p>
  2662. <p class="TypedExample">s = Simple(10)</p>
  2663. <p class="Code-Background"></p>
  2664. <p class="TypedExample">for i in s: print i</p>
  2665. <p class="Stepnonumbering">You will get the following output in the IronPython
  2666. console window:</p>
  2667. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2668. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;vbextend.dll&quot;)<br />
  2669. &gt;&gt;&gt; import Simple<br />
  2670. &gt;&gt;&gt; dir(Simple)<br />
  2671. &gt;&gt;&gt; s = Simple(10)</p>
  2672. <p class="Code-Highlighted">&gt;&gt;&gt; for i in s: print i</p>
  2673. <p class="Code-Background">Simple&lt;0&gt;<br />
  2674. Simple&lt;1&gt;<br />
  2675. Simple&lt;2&gt;<br />
  2676. Simple&lt;3&gt;<br />
  2677. Simple&lt;4&gt;<br />
  2678. Simple&lt;5&gt;<br />
  2679. Simple&lt;6&gt;<br />
  2680. Simple&lt;7&gt;<br />
  2681. Simple&lt;8&gt;<br />
  2682. Simple&lt;9&gt;</p>
  2683. <p class="Normal">&nbsp;</p>
  2684. <p class="StepNote">Notice that the dir() function now returned the GetEnumerator
  2685. method.</p>
  2686. <ol start="4">
  2687. <li>
  2688. <p class="Step">Exit IronPython and return back to the Visual Basic code
  2689. to add more functionality.</p>
  2690. </li>
  2691. </ol>
  2692. <h3><a name="T5.2.3">Task 3: Adding custom operator</a></h3>
  2693. <ol>
  2694. <li>
  2695. <p class="Step">Add the operator + method to the Simple class:</p>
  2696. </li>
  2697. </ol>
  2698. <p class="CodeSample">Public Class Simple<br />
  2699. &nbsp;&nbsp;&nbsp; Implements IEnumerable<br />
  2700. &nbsp;&nbsp;&nbsp; Private data As Integer<br />
  2701. <br />
  2702. &nbsp;&nbsp;&nbsp; Public Sub New(ByVal data As Integer)<br />
  2703. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.data = data<br />
  2704. &nbsp;&nbsp;&nbsp; End Sub<br />
  2705. <br />
  2706. &nbsp;&nbsp;&nbsp; Overrides Function ToString() As String<br />
  2707. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data)<br />
  2708. &nbsp;&nbsp;&nbsp; End Function<br />
  2709. <br />
  2710. &nbsp;&nbsp;&nbsp; Function GetEnumerator() As IEnumerator _<br />
  2711. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  2712. Implements IEnumerable.GetEnumerator<br />
  2713. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return New SimpleEnum(data)<br />
  2714. &nbsp;&nbsp;&nbsp; End Function<br />
  2715. &nbsp;</p>
  2716. <p class="CodeSample">&nbsp;&nbsp;&nbsp; Shared Operator +(ByVal a As
  2717. Simple, ByVal b As Simple) As Simple<br />
  2718. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return New Simple(a.data + b.data)<br />
  2719. &nbsp;&nbsp;&nbsp; End Operator</p>
  2720. <p class="CodeSample"><br />
  2721. End Class</p>
  2722. <ol start="2">
  2723. <li>
  2724. <p class="Step">Compile the code (vbx), launch IronPython Console (ip) and
  2725. test the code:</p>
  2726. </li>
  2727. </ol>
  2728. <p class="TypedExample">import clr</p>
  2729. <p class="Code-Background"></p>
  2730. <p class="UserCode">clr.AddReferenceToFile(&quot;vbextend.dll&quot;)</p>
  2731. <p class="HiddenCode">clr.AddReferenceToFile(&quot;vbextend_5.2.3.dll&quot;)</p>
  2732. <p class="Code-Background"></p>
  2733. <p class="TypedExample">import Simple</p>
  2734. <p class="Code-Background"></p>
  2735. <p class="UserCode">dir(Simple)</p>
  2736. <p class="HiddenCode">set1 = set(dir(Simple))
  2737. set2 = set(dir(object))
  2738. list(set1-set2)</p>
  2739. <p class="HiddenOutput">
  2740. ['GetEnumerator', '__iter__', '__radd__', '__add__']</p>
  2741. <p class="TypedExample">a = Simple(10)</p>
  2742. <p class="Code-Background"></p>
  2743. <p class="TypedExample">b = Simple(20)</p>
  2744. <p class="Code-Background"></p>
  2745. <p class="TypedExample">a + b</p>
  2746. <p class="LooseVerify">Simple&lt;30</p>
  2747. <p class="Stepnonumbering">Notice that in the output of dir() call you will
  2748. now get additional methods __add__ and __radd__, Python&#39;s notion of custom operator
  2749. implementation:</p>
  2750. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2751. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;vbextend.dll&quot;)<br />
  2752. &gt;&gt;&gt; import Simple<br />
  2753. &gt;&gt;&gt; dir(Simple)<br />
  2754. &gt;&gt;&gt; a = Simple(10)<br />
  2755. &gt;&gt;&gt; b = Simple(20)</p>
  2756. <p class="Code-Highlighted">&gt;&gt;&gt; a + b<br>
  2757. &lt;Simple object at 0x000000000000002B [Simple&lt;30]</p>
  2758. <ol start="3">
  2759. <li>
  2760. <p class="Step">Exit IronPython and return back to the Visual Basic .NET
  2761. code to add more functionality.</p>
  2762. </li>
  2763. </ol>
  2764. <h3><a name="T5.2.4">Task 4: Adding delegate</a></h3>
  2765. <ol>
  2766. <li>
  2767. <p class="Step">Add the definition of the delegate to the top of the Visual
  2768. Basic source file:</p>
  2769. </li>
  2770. </ol>
  2771. <p class="CodeSample">Imports System<br />
  2772. Imports System.Collections<br />
  2773. &nbsp;</p>
  2774. <p class="CodeSample">Public Delegate Function Transformer(ByVal input
  2775. As Integer) As Integer</p>
  2776. <ol start="2">
  2777. <li>
  2778. <p class="Step">Add &quot;Transform&quot; method to the Simple class that takes the
  2779. delegate as a parameter and invokes the delegate:</p>
  2780. </li>
  2781. </ol>
  2782. <p class="CodeSample">Public Class Simple<br />
  2783. &nbsp;&nbsp;&nbsp; Implements IEnumerable<br />
  2784. &nbsp;&nbsp;&nbsp; Private data As Integer<br />
  2785. <br />
  2786. &nbsp;&nbsp;&nbsp; Public Sub New(ByVal data As Integer)<br />
  2787. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.data = data<br />
  2788. &nbsp;&nbsp;&nbsp; End Sub<br />
  2789. <br />
  2790. &nbsp;&nbsp;&nbsp; Overrides Function ToString() As String<br />
  2791. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return String.Format(&quot;Simple&lt;{0}&gt;&quot;, data)<br />
  2792. &nbsp;&nbsp;&nbsp; End Function<br />
  2793. <br />
  2794. &nbsp;&nbsp;&nbsp; Function GetEnumerator() As IEnumerator _<br />
  2795. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  2796. Implements IEnumerable.GetEnumerator<br />
  2797. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return New SimpleEnum(data)<br />
  2798. &nbsp;&nbsp;&nbsp; End Function<br />
  2799. &nbsp;</p>
  2800. <p class="CodeSample">&nbsp;&nbsp;&nbsp; Function Transform(ByVal t As
  2801. Transformer) As Integer<br />
  2802. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return t(data)<br />
  2803. &nbsp;&nbsp;&nbsp; End Function</p>
  2804. <p class="CodeSample"><br />
  2805. &nbsp;&nbsp;&nbsp; Shared Operator +(ByVal a As Simple, ByVal b As Simple) As Simple<br />
  2806. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return New Simple(a.data + b.data)<br />
  2807. &nbsp;&nbsp;&nbsp; End Operator<br />
  2808. <br />
  2809. End Class</p>
  2810. <ol start="3">
  2811. <li>
  2812. <p class="Step">Return back to the SDK command prompt, compile the code
  2813. (vbx), launch IronPython Console (ip) and test the code:</p>
  2814. </li>
  2815. </ol>
  2816. <p class="TypedExample">import clr</p>
  2817. <p class="Code-Background"></p>
  2818. <p class="UserCode">clr.AddReferenceToFile(&quot;vbextend.dll&quot;)</p>
  2819. <p class="HiddenCode">clr.AddReferenceToFile(&quot;vbextend_5.2.4.dll&quot;)</p>
  2820. <p class="Code-Background"></p>
  2821. <p class="TypedExample">import Simple</p>
  2822. <p class="Code-Background"></p>
  2823. <p class="TypedExample">a = Simple(10)</p>
  2824. <p class="TypedExample">def X(i):<br>
  2825. &nbsp;&nbsp;&nbsp; return i + 100</p>
  2826. <p class="Code-Background"></p>
  2827. <p class="TypedExample">&nbsp;</p>
  2828. <p class="TypedExample">a.Transform(X)</p>
  2829. <p class="Code-Background"></p>
  2830. <p class="Stepnonumbering">The function X is getting passed as the delegate
  2831. to the Simple&#39;s Transform method. You will get following output:</p>
  2832. <p class="Code-Highlighted">&nbsp;</p>
  2833. <p class="Code-Highlighted">&gt;&gt;&gt; import clr<br />
  2834. &gt;&gt;&gt; clr.AddReferenceToFile(&quot;vbextend.dll&quot;)<br />
  2835. &gt;&gt;&gt; import Simple<br />
  2836. &gt;&gt;&gt; a = Simple(10)<br />
  2837. &gt;&gt;&gt; def X(i):</p>
  2838. <p class="Code-Highlighted">...&nbsp;&nbsp;&nbsp;&nbsp; return i + 100<br />
  2839. ...<br />
  2840. &gt;&gt;&gt; a.Transform(X)</p>
  2841. <p class="Code-Background">110</p>
  2842. <p class="Normal"></p>
  2843. <ol start="4">
  2844. <li>
  2845. <p class="Step">This concludes the Visual Basic extending example. If you
  2846. are interested, an interesting exercise is combining the debugging example
  2847. and the extending one. If you are inspired to do so, try debugging the script
  2848. that you just typed in. Debug the &quot;debugvbx.py&quot; script located in the Tutorial
  2849. directory. Place a breakpoint on the X function - you will see mixed call
  2850. stack between Visual Basic and Python.</p>
  2851. </li>
  2852. </ol>
  2853. <p class="LabSummary">Tutorial Summary</p>
  2854. <p class="Body">The complete version of the csextend.cs and vbextend.vb files
  2855. are located in the Tutorial\Extend directory along with files csxtest.py and
  2856. vbxtest.py which contain the test code for the C# and Visual Basic .NET extensions
  2857. respectively.</p>
  2858. <p class="Body">The code to experiment with debugging of Python and C# or Visual
  2859. Basic code, use Python scripts debugcsx.py and debugvbx.py respectively.</p>
  2860. <p class="Body">In this tutorial you performed the following exercises.</p>
  2861. <ul>
  2862. <li>
  2863. <p class="Body"><a href="#T5.1">Extending IronPython using C# code</a></p>
  2864. </li>
  2865. <li>
  2866. <p class="Body"><a href="#T5.2">Extending IronPython using Visual Basic
  2867. .NET</a></p>
  2868. </li>
  2869. </ul>
  2870. <p class="Body">In this tutorial, you implemented a simple class to be used
  2871. from IronPython. You added the ability for IronPython to enumerate the class,
  2872. added an operator to it and support for delegate. The implementation was in
  2873. either C# or Visual Basic, or both.</p>
  2874. <h1><a name="T7">Tutorial 6: Using Visual Studio to Edit .py Files and Debug
  2875. Them</a></h1>
  2876. <p class="Body">There's very basic support for editing .py files in Visual
  2877. Studio (no coloring or expression completion), but you get .NET debugging support.&nbsp; This tutorial shows
  2878. you how to quickly set up Visual Studio to work on Python scripts in a
  2879. directory.</p>
  2880. <p class="Body">Estimated time to complete this tutorial: <b>5 minutes</b></p>
  2881. <p class="Body">The objective of this tutorial is to set up Visual Studio
  2882. for some basic tool support for debugging.</p>
  2883. <ul>
  2884. <li>
  2885. <p class="Body"><a href="#T6.1">Setting up Visual Studio for IronPython
  2886. Debugging</a></p>
  2887. </li>
  2888. </ul>
  2889. <h2><a name="T6.1">Exercise 1: Setting up Visual Studio for IronPython
  2890. Debugging</a></h2>
  2891. <p class="Body">In this exercise you will set up a Visual Studio solution
  2892. that you can use to edit .py files in a directory and debug them using the
  2893. Visual Studio .NET debugger.&nbsp; We will use the Tutorial directory as an
  2894. example, but you could save your solution anywhere.</p>
  2895. <h3><a name="T6.1.1">Task 1: Setting up Visual Studio for IronPython
  2896. Debugging</a></h3>
  2897. <ol>
  2898. <li>
  2899. <p class="Step">Open Visual Studio and close any solution or projects
  2900. you might have open.</p>
  2901. </li>
  2902. <li>
  2903. <p class="Step">Use the File-&gt;Open-&gt;Project/Solution ... command and
  2904. browse to the ipy.exe application in your IronPython installation
  2905. (c:\IronPython\ipy.exe is where the tutorial assumes you have it).</p>
  2906. </li>
  2907. <li>
  2908. <p class="Step">We will use the Tutorial directory as an example, and
  2909. we'll want to set it up as the working directory for loading .py
  2910. scripts.&nbsp; Right click on the ipy.exe project node in the Visual
  2911. Studio's solution
  2912. explorer and choose the Properties command.</p>
  2913. </li>
  2914. <li>
  2915. <p class="Step">In the properties dialog, you will fill in two
  2916. fields, the Command Arguments and Working Directory.&nbsp; For the
  2917. Command Arguments, enter &quot;-D first.py&quot;.&nbsp; The -D argument enables
  2918. application debugging. For the Working Directory,
  2919. enter the path to the Tutorial directory (c:\IronPython\Tutorial\ is
  2920. where we assume you have it).&nbsp; Click Apply and OK to confirm your
  2921. changes.</p>
  2922. </li>
  2923. <li>
  2924. <p class="Step">Now let's save the solution with the File-&gt;Save All ...
  2925. command.&nbsp; Save it to the Tutorial directory.</p>
  2926. </li>
  2927. <li>
  2928. <p class="Step">To test out our set up, use Ctrl+O to open a file.&nbsp;
  2929. Browse to the &quot;first.py&quot; file in the Tutorial directory.&nbsp; Place the
  2930. caret on the line that reads &quot;def add(a, b):&quot;, and press F9 to set a
  2931. breakpoint.</p>
  2932. </li>
  2933. <li>
  2934. <p class="Step">Press F5 to run the script, and you will hit the
  2935. breakpoint.&nbsp; If you Press F10, you will step through the file, but
  2936. all it does is load the definitions and set some variables before
  2937. terminating.</p>
  2938. </li>
  2939. <li>
  2940. <p class="Step">To see more stepping, we'll add a line to the file and
  2941. set another breakpoint.&nbsp; Add a line to the end of the file to
  2942. invoke the factorial function (&quot;factorial(5)&quot;).&nbsp; Add a breakpoint to the line that reads
  2943. &quot;if n &lt; 1: return 1&quot;.&nbsp; Now Press F5 to run the script.&nbsp;
  2944. Press F10 repeatedly and notice the locals window where
  2945. the parameter &quot;n&quot; decrements to 0 and then goes back up to 5 as the
  2946. recursion unwinds.&nbsp; You can also hover the mouse over the &quot;n&quot;
  2947. in the editor window to get a data tip of its value each time you stop at the
  2948. breakpoint.</p>
  2949. </li>
  2950. </ol>
  2951. <p class="Body">To work on other scripts, just change the Command Arguments
  2952. property for the ipy.exe project as we did above to name another script you want
  2953. to load on F5.&nbsp; You might also find it useful to go to the
  2954. Tools-&gt;Options... dialog and change a property on the Environment-&gt;Documents
  2955. page to show the open script files.&nbsp; If you check the property &quot;Show Miscellaneous Files in the Solution
  2956. Explorer&quot;, then you will get a list of the .py files you are editing.&nbsp; Each
  2957. time you open this solution again at a later time, you will see all the .py
  2958. files you developed while using this solution file.</p>
  2959. <p class="LabSummary">Tutorial Summary</p>
  2960. <p class="Body">In this tutorial you performed the following exercises.</p>
  2961. <ul>
  2962. <li>
  2963. <p class="Body"><a href="#T6.1">Setting up Visual Studio for IronPython
  2964. Debugging</a></p>
  2965. </li>
  2966. </ul>
  2967. <p class="Normal">In this tutorial you set up Visual Studio to work on
  2968. Python scripts in a directory and debug them.</p>
  2969. </body>
  2970. </html>