PageRenderTime 100ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/Public/Tutorial/Tutorial.htm

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