/IronPython_2_0/Tutorial/Tutorial.htm
HTML | 2996 lines | 2969 code | 26 blank | 1 comment | 0 complexity | 1623e1b5d96dc0645c03a305c88dde4e MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
- <html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
- <title>IronPython Tutorial</title>
- <!--link rel="stylesheet" type="text/css" href="../Doc/IronPython.css"-->
- <style type="text/css">
- p.AntiVerify { display : none; }
- p.Code-Background { color : gray; }
- p.Code-Highlighted { color : gray; }
- p.CodeSample { color:blue; }
- p.DOSCommand { color:green; }
- p.ExceptionExample { color:green; }
- p.ExceptionOutput {display : none; }
- p.HiddenCode { display : none; }
- p.HiddenOutput {display : none; }
- p.LooseVerify { display : none; }
- p.Stepnonumbering { text-indent: 2em; }
- p.TypedExample { color : green; }
- p.UserCode { color:green; }
- </style>
-
- </head>
-
- <body lang="EN-US">
-
- <div class="Section1">
- <p class="Title1">IronPython Tutorial</p>
- <p class="Title2">A tour of Python on .NET</p>
- <p class="Title2"> </p>
- <hr />
- <p class="CopyrightText">Information in this document is subject to change without
- notice. The example companies, organizations, products, people, and events depicted
- herein are fictitious. No association with any real company, organization, product,
- person or event is intended or should be inferred. Complying with all applicable
- copyright laws is the responsibility of the user. Without limiting the rights
- under copyright, no part of this document may be reproduced, stored in or introduced
- into a retrieval system, or transmitted in any form or by any means (electronic,
- mechanical, photocopying, recording, or otherwise), or for any purpose, without
- the express written permission of Microsoft Corporation.</p>
- <p class="CopyrightText"> </p>
- <p class="CopyrightText">Microsoft may have patents, patent applications, trademarked,
- copyrights, or other intellectual property rights covering subject matter in
- this document. Except as expressly provided in any written license agreement
- from Microsoft, the furnishing of this document does not give you any license
- to these patents, trademarks, copyrights, or other intellectual property.</p>
- <p class="CopyrightText"> </p>
- <p class="CopyrightText">Š Microsoft Corporation. All rights reserved.</p>
- <p class="CopyrightText"> </p>
- <p class="CopyrightText">Microsoft, MS-DOS, MS, Windows, Windows NT, MSDN, Active
- Directory, BizTalk, SQL Server, SharePoint, Outlook, PowerPoint, FrontPage,
- Visual Basic, Visual C++, Visual J++, Visual InterDev, Visual SourceSafe, Visual
- C#, Visual J#, and Visual Studio are either registered trademarks or trademarks
- of Microsoft Corporation in the U.S.A. and/or other countries.</p>
- <p class="CopyrightText"> </p>
- <p class="CopyrightText">Other product and company names herein may be the trademarks of their respective owners.</p>
- <hr />
- <p class="ContentsHeading">Contents</p>
- <p class="Toc1"><a href="#Intro">Introduction</a></p>
- <p class="Toc1">Tutorial 1: <a href="#T1">Basic IronPython</a></p>
- <p class="Toc2">Exercise 1: <a href="#T1.1">The IronPython interactive console</a></p>
- <p class="Toc3">Task 1: <a href="#T1.1.1">IronPython console</a></p>
- <p class="Toc3">Task 2: <a href="#T1.1.2">Built-in modules and interactive exploration</a></p>
- <p class="Toc3">Task 3: <a href="#T1.1.3">External Python modules</a></p>
- <p class="Toc2">Exercise 2: <a href="#T1.2">Using the standard .NET libraries from IronPython</a></p>
- <p class="Toc3">Task 1: <a href="#T1.2.1">Basic .NET library use</a></p>
- <p class="Toc3">Task 2: <a href="#T1.2.2">Working with .NET classes</a></p>
- <p class="Toc3">Task 3: <a href="#T1.2.3">Generics</a></p>
- <p class="Toc2">Exercise 3: <a href="#T1.3">Loading .NET libraries</a></p>
- <p class="Toc3">Task 1: <a href="#T1.3.1">Using System.Xml - AddReference</a></p>
- <p class="Toc3">Task 2: <a href="#T1.3.2">Mapack - Loading the .NET libraries - AddReferenceToFile</a></p>
- <p class="Toc2">Exercise 4: <a href="#T1.4">Obtaining and Using Python Standard Library</a></p>
- <p class="Toc3">Task 1: <a href="#T1.4.1">Configuring IronPython to use the Python standard library</a></p>
- <p class="Toc1">Tutorial 2: <a href="#T2">Advanced IronPython</a></p>
- <p class="Toc2">Exercise 1: <a href="#T2.1">Events and Delegates</a></p>
- <p class="Toc3">Task 1: <a href="#T2.1.1">File System Watcher</a></p>
- <p class="Toc3">Task 2: <a href="#T2.1.2">Improving the event handler</a></p>
- <p class="Toc3">Task 3: <a href="#T2.1.3">Defining events in Python</a></p>
- <p class="Toc2">Exercise 2: <a href="#T2.2">Windows Forms</a></p>
- <p class="Toc3">Task 1: <a href="#T2.2.1">Simple Windows Forms application</a></p>
- <p class="Toc2">Exercise 3: <a href="#T2.3">Windows Presentation Foundation (Avalon)</a></p>
- <p class="Toc3">Task 1: <a href="#T2.3.1">Simple Avalon Application</a></p>
- <p class="Toc3">Task 2: <a href="#T2.3.2">Avalon calculator</a></p>
- <p class="Toc1">Tutorial 3: <a href="#T3">IronPython and COM interoperability</a></p>
- <p class="Toc2">Exercise 1: <a href="#T3.1">Merlin the Wizard</a></p>
- <p class="Toc3">Task 1: <a href="#T3.1.1">Creating COM interop assemblies</a></p>
- <p class="Toc3">Task 2: <a href="#T3.1.2">Using COM objects from IronPython</a></p>
- <p class="Toc2">Exercise 2: <a href="#T3.2">Use Word for Spell Checking</a></p>
- <p class="Toc3">Task 1: <a href="#T3.2.1">Accessing Word and Checking
- Spelling</a></p>
- <p class="Toc3">Task 2: <a href="#T3.2.2">Use Windows Form Dialog to Correct
- Spelling</a></p>
- <p class="Toc1">Tutorial 4: <a href="#T4">Debugging IronPython program</a></p>
- <p class="Toc2">Exercise 1: <a href="#T4.1">Debugging IronPython programs</a></p>
- <p class="Toc3">Task 1: <a href="#T4.1.1">Debugging IronPython programs using Microsoft CLR Debugger</a></p>
- <p class="Toc1">Tutorial 5: <a href="#T5">Extending IronPython</a></p>
- <p class="Toc2">Exercise 1: <a href="#T5.1">Extending using C#</a></p>
- <p class="Toc3">Task 1: <a href="#T5.1.1">Implementing simple class - constructor and ToString</a></p>
- <p class="Toc3">Task 2: <a href="#T5.1.2">Making the object enumerable</a></p>
- <p class="Toc3">Task 3: <a href="#T5.1.3">Adding custom operator</a></p>
- <p class="Toc3">Task 4: <a href="#T5.1.4">Adding delegate</a></p>
- <p class="Toc2">Exercise 2: <a href="#T5.2">Extending using Visual Basic.NET</a></p>
- <p class="Toc3">Task 1: <a href="#T5.2.1">Implementing simple class - constructor and ToString</a></p>
- <p class="Toc3">Task 2: <a href="#T5.2.2">Making the object enumerable</a></p>
- <p class="Toc3">Task 3: <a href="#T5.2.3">Adding custom operator</a></p>
- <p class="Toc3">Task 4: <a href="#T5.2.4">Adding delegate</a></p>
- <p class="Toc1">Tutorial 6: <a href="#T7">Using Visual Studio to Edit .py
- Files and Debug Them</a></p>
- <p class="Toc2">Exercise 1: <a href="#T6.1">Setting up Visual Studio for
- IronPython Debugging</a></p>
- <p class="Toc3">Task 1: <a href="#T6.1.1">Setting up Visual Studio for
- IronPython Debugging</a></p>
- </div>
- <div class="Section2">
- <h1><a name="Intro">Introduction</a></h1>
- <p class="Normal">IronPython is the .NET implementation of the Python programming language
- (<a href="http://www.python.org">www.python.org</a>). It's a dynamically typed language with support
- for many programming paradigms such as object-oriented programming, and also allows
- you to seamlessly use .NET code.</p>
- <p class="Normal"> </p>
- <p class="Normal">The goal of this tutorial is to quickly
- familiarize you with the IronPython console, and to show you how to make use of the extensive .NET libraries available.
- This tutorial also shows you how to get started in more specialized areas
- such as interoperating with COM, extending IronPython with C#, and embedding
- IronPython. This tutorial is NOT meant to be an introduction to Python
- itself, and if you're looking for that, we recommend you start with the
- tutorial at <a href="http://docs.python.org/tut/tut.html">www.python.org</a>
- or the often recommended book <i>Learning Python</i> by Mark Lutz and David
- Ascher. For an introduction to both the Python language as well as the unique
- capabilities of IronPython, we recommend <i>IronPython in Action</i> by
- Michael Foord<br><br>
- Some of the exercises in this tutorial require prerequisites. The prerequisites to successfully complete the whole tutorial are:</p>
- <ul type="disc">
- <li class="Normal">Microsoft .NET Framework Version 3.5
- <ul type="circle">
- <li class="Normal">Required to run IronPython on Windows Vista.</li>
- <li class="Normal">Microsoft .NET Framework Version 3.0 SP1 or higher needed for Windows operating systems released prior to Windows Vista</li>
- <li class="Normal">Download from
- <a href="http://www.microsoft.com/downloads/details.aspx?familyid=333325FD-AE52-4E35-B531-508D977D32A6&displaylang=en ">
- here</a>.</li>
- </ul>
- </li>
- </ul>
- <ul>
- <li class="Normal">Visual Studio 2005 or 2008<ul type="circle">
- <li class="Normal">Required for "Setting up Visual Studio for IronPython Debugging" tutorials.</li>
- </ul>
- </li>
- </ul>
- <ul>
- <li class="Normal">Microsoft Word<ul type="circle">
- <li class="Normal">Required for "Use Word for Spell Checking" and "Merlin the Wizard" tutorials.</li>
- </ul>
- </li>
- </ul>
- <ul>
- <li class="Normal"><a name="Mapack">Mapack</a> (example assembly found
- on the internet)<ul>
- <li>Required for the "Basic IronPython" tutorial, exercise "Loading .NET
- Libraries".</li>
- <li>Download Mapack from
- <a href="http://www.lutzroeder.com/dotnet/">here</a> (direct link
- to the Mapack.zip download is
- <a href="http://www.lutzroeder.com/dotnet/Download.aspx?File=Mapack">
- here</a>).</li>
- <li>Extract Mapack.dll from the zip file directly into the Tutorial
- directory.</li>
- </ul>
- </li>
- </ul>
- <p class="Normal"> </p>
- <p class="Body">Visual Studio 2005 or 2008 can be used in place of the Microsoft .NET
- Framework Version 2.0 and the .NET Framework 2.0 Software Development Kit (SDK).
- Since Visual Studio installs both the .NET Framework 2.0 and the .NET Framework
- SDK, there is no need to install those explicitly if you have Visual Studio
- 2005 available. Visual Studio 2008 also installs .NET Framework 3.5. </p>
- <p class="Body">This tutorial also assumes that you will launch the
- IronPython console (c:\ironpython\ipy.exe) from the tutorial directory.
- When the tutorials direct you to start the IronPython console from the tutorial directory,
- you should change to the tutorial directory (>cd c:\ironpython\tutorial)
- and launch the console with the tutorial as your working directory (>..\ipy.exe). If you
- install IronPython via the MSI installer, it will install to c:\Program Files\IronPython 2.0
- by default. In this scenario, you can still run the tutorial, but several tutorials require
- write access to the tutorial directory, which will require administrator access if IronPython
- is installed under Program Files.</p>
- <p class="Body"> </p>
- <h1><a name="T1">Tutorial 1: Basic IronPython</a></h1>
- <p class="Body">The emphasis of this tutorial is on the basic interaction with
- the IronPython interpreter and using the interactive environment to explore
- the .NET libraries.</p>
- <p class="Body">Estimated time to complete this tutorial: <b>30 minutes</b></p>
- <p class="Body">The objective of this tutorial is to launch the IronPython interpreter,
- explore the environment of the interactive console and use IronPython to interact
- with .NET libraries.</p>
- <p class="Body">The exercises in this tutorial are:</p>
- <ul>
- <li>
- <p class="ExerciseList"><a href="#T1.1">The IronPython interactive console</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T1.2">Using the standard .NET libraries
- from IronPython</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T1.3">Loading additional .NET libraries</a></p>
- </li>
- </ul>
- <h2><a name="T1.1">Exercise 1: The IronPython interactive console</a></h2>
- <p class="Body">In this exercise, you will start the IronPython interactive
- interpreter and perform simple tasks to become acquainted with the IronPython
- environment.</p>
- <p class="Normal">If you are familiar with using the Python interactive console,
- the import statement and exploring the Python interactive environment using
- dir() function and __doc__ attribute, you can <a href="#T1.2">skip this exercise</a>.</p>
- <h3><a name="T1.1.1">Task 1: IronPython console</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- by changing to the tutorial directory (>cd c:\ironpython\tutorial) and
- launching the console c:\ironpython\ipy.exe executable (>..\ipy.exe).
- This is how you should always launch the console for the tutorials, but
- from now on, we'll just direct you to "start the IronPython console from
- the tutorial directory".</p>
- </li>
- </ol>
- <p class="Code-Highlighted">IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053<br />
- Copyright (c) Microsoft Corporation. All rights reserved.</p>
- <p class="Code-Highlighted">>>> _</p>
- <ol start="2">
- <li>
- <p class="Step">Execute simple statements listed below. After each statement IronPython prints the result, if any, and awaits more input.
- (The input line starting with "for" requires an extra return or enter
- key press because the interpreter prompts for more statements in the
- 'for' loop.)</p>
- </li>
- </ol>
- <p class="TypedExample">2+2</p>
- <p class="TypedExample">print "Hello World!"</p>
- <p class="TypedExample">for i in range(3): print i</p>
- <p class="TypedExample">x = 10</p>
- <p class="TypedExample">print x</p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">After this step, the console window will contain
- the following text:</p>
- <p class="Code-Highlighted">>>> 2+2</p>
- <p class="Code-Background">4</p>
- <p class="Code-Highlighted">>>> print "Hello World!"</p>
- <p class="Code-Background">Hello World!</p>
- <p class="Code-Highlighted">>>> for i in range(3): print i</p>
- <p class="Code-Highlighted">...</p>
- <p class="Code-Background">0<br />
- 1<br />
- 2</p>
- <p class="Code-Highlighted">>>> x = 10<br />
- >>> print x</p>
- <p class="Code-Background"></p>
- <p class="Code-Background">10</p>
- <p class="Code-Highlighted">>>> </p>
- <ol start="3">
- <li>
- <p class="Step">IronPython console supports multi-line statements, often
- used by function definitions. IronPython prompts for additional lines of
- multi-line statements using:</p>
- </li>
- </ol>
- <p class="Code-Highlighted">...</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">Unlike C# or Java, where blocks of code are grouped by curly brackets "{...}",
- blocks of code in Python are grouped based on their level of indentation. Every new block of code
- must be indented one more level than the previous block of code. Blocks of code are used for
- function and class definitions as well as 'if' statements and loops. </p>
- <p class="Stepnonumbering">Define the "add" function (note, you
- need to enter spaces before the 'return' statement):</p>
- <p class="TypedExample">def add(a, b):<br>
- return a + b</p>
- <p class="Stepnonumbering">To complete the function definition, press Enter
- once more at this point</p>
- <p class="TypedExample">add(3, 2)</p>
- <p class="TypedExample">add("Iron", "Python")</p>
- <p class="Stepnonumbering">After this step, the console contents will be:</p>
- <p class="Code-Highlighted">>>> def add(a, b):<br />
- ... return a + b<br />
- ...<br />
- >>> add(3, 2)</p>
- <p class="Code-Background">5</p>
- <p class="Code-Highlighted">>>> add("Iron", "Python")</p>
- <p class="Code-Background">'IronPython'</p>
- <p class="Code-Highlighted">>>> </p>
- <p class="Step"> </p>
- <ol start="4">
- <li>
- <p class="Step">To exit the IronPython interactive console, type Ctrl+Z and Enter (alternatively,
- press F6 followed by Enter).</p>
- </li>
- </ol>
- <p class="TypedExample">^Z</p>
- <h3><a name="T1.1.2">Task 2: Built-in modules and interactive exploration</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Using the built-in dir() function, list the contents of
- the IronPython environment:</p>
- </li>
- </ol>
- <p class="TypedExample">dir()</p>
- <p class="Stepnonumbering">The output in the console window will be:</p>
- <p class="Code-Highlighted">>>> dir()</p>
- <p class="Code-Background">['__builtins__', '__doc__', '__name__']<br />
- </p>
- <ol start="3">
- <li>
- <p class="Step">IronPython comes with several built-in modules, the most
- frequently used one being "sys". Import "sys" module using the "import"
- statement:</p>
- </li>
- </ol>
- <p class="TypedExample">import sys</p>
- <ol start="4">
- <li>
- <p class="Step">The Python import statement is similar to the "using" statement
- of C# or "Imports" statement of Visual Basic. The important difference is
- that the C# and VB statements bring the names from the imported namespace
- into the global namespace to be accessed directly. Pythons import doesnt
- do that. To access the names or attributes in an imported module, prefix
- the
- names with the module's name:</p>
- </li>
- </ol>
- <p class="UserExample">sys.version</p>
- <ol start="5">
- <li>
- <p class="Step">Use the dir() function to explore the environment:</p>
- </li>
- </ol>
- <p class="TypedExample">dir()</p>
- <p class="Stepnonumbering" style="margin-left: 0.5in">The environment (global namespace) has changed, now
- it contains the "sys" module:</p>
- <p class="Code-Highlighted">>>> dir()</p>
- <p class="Code-Background">['__builtins__', '__doc__', '__name__', 'sys']</p>
- <ol start="6">
- <li>
- <p class="Step">Use the dir() function to explore the contents of the "sys"
- module:</p>
- </li>
- </ol>
- <p class="TypedExample">dir(sys)</p>
- <p class="HiddenOutput">['__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit', 'hexversion', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdefaultencoding', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions', 'winver']</p>
- <ol start="7">
- <li>
- <p class="Step">Print the values of some of the "sys" module attributes:</p>
- </li>
- </ol>
- <p class="TypedExample">sys.path</p>
- <p class="LooseVerify">['.', '%MERLIN_ROOT%\\Test\\IronPythonTutorial', '%MERLIN_ROOT%\\Test', '%MERLIN_ROOT%\\Languages\\IronPython\\Tutorial', '%MERLIN_ROOT%\\Languages\\IronPython\\Tests', '%MERLIN_ROOT%\\Bin\\Debug\\Lib']</p>
- <p class="TypedExample">sys.executable</p>
- <p class="LooseVerify">'%MERLIN_ROOT%\\Bin\\Debug\\ipy.exe'</p>
- <h3><a name="T1.1.3">Task 3: External Python modules</a></h3>
- <p class="Normal">This task uses the module "first.py" located in the Tutorial
- folder.</p>
- <ol>
- <li>
- <p class="Step">Import the "first.py" module located in the Tutorial
- (because you launched ipy.exe from the Tutorial directory, "first" will
- be found on your sys.path):</p>
- </li>
- </ol>
- <p class="TypedExample">import first</p>
- <p class="Code-Background"></p>
- <ol start="2">
- <li>
- <p class="Step">Explore the module "first" using dir() function:</p>
- </li>
- </ol>
- <p class="TypedExample">dir(first)</p>
- <p class="Code-Highlighted">>>> dir(first)</p>
- <p class="Code-Background">['__builtins__', '__file__', '__name__', 'add', 'factorial', 'hi']</p>
- <ol start="3">
- <li>
- <p class="Step">Print the documentation for the "add" and "factorial" functions,
- using __doc__ attribute:</p>
- </li>
- </ol>
- <p class="TypedExample">first.add.__doc__</p>
- <p class="TypedExample">first.factorial.__doc__</p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">The __doc__ attribute will be later used also for
- exploring .NET methods and their parameter types.</p>
- <p class="Code-Highlighted">>>> first.add.__doc__</p>
- <p class="Code-Background">'add(a, b) -> returns a + b'</p>
- <p class="Code-Highlighted">>>> first.factorial.__doc__</p>
- <p class="Code-Background">'factorial(n) -> returns factorial of n'</p>
- <ol start="4">
- <li>
- <p class="Step">Call the methods in the "first" module and print the contents
- of the "hi" attribute</p>
- </li>
- </ol>
- <p class="TypedExample">first.add(1,2)</p>
- <p class="TypedExample">first.factorial(5)</p>
- <p class="TypedExample">first.hi</p>
- <p class="Stepnonumbering">The expected output is:</p>
- <p class="Code-Highlighted">>>> first.add(1,2)</p>
- <p class="Code-Background">3</p>
- <p class="Code-Highlighted">>>> first.factorial(5)</p>
- <p class="Code-Background">120</p>
- <p class="Code-Highlighted">>>> first.hi</p>
- <p class="Code-Background">'Hello from IronPython!'</p>
- <ol start="5">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
- by Enter)</p>
- </li>
- </ol>
- <h2><a name="T1.2">Exercise 2: Using the standard .NET libraries from IronPython</a></h2>
- <p class="Body">The power of IronPython lies within the ability to seamlessly
- access the wealth of .NET libraries. This exercise will demonstrate how the
- .NET libraries can be used from IronPython.</p>
- <p class="Body">In this exercise, you will use the standard .NET libraries from
- IronPython. </p>
- <h3><a name="T1.2.1">Task 1: Basic .NET library use</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Using the "import" statement, import the .NET System namespace:</p>
- </li>
- </ol>
- <p class="TypedExample">import System</p>
- <p class="Code-Background"></p>
- <ol start="3">
- <li>
- <p class="Step">Explore the System.Environment class and access some of
- its properties:</p>
- </li>
- </ol>
- <p class="TypedExample">dir(System.Environment)</p>
- <p class="UserCode">System.Environment.OSVersion</p>
- <p class="TypedExample">System.Environment.CommandLine</p>
- <p class="Stepnonumbering">The expected output of these commands is as follows
- (with some ellipsis for convenience):</p>
- <p class="Code-Highlighted">>>> dir(System.Environment)</p>
- <p class="HiddenOutput">['CommandLine', 'CurrentDirectory', 'Equals', 'Exit', 'ExitCode', 'ExpandEnvironmentVariables', 'FailFast', 'GetCommandLineArgs', 'GetEnvironmentVariable', 'GetEnvironmentVariables', 'GetFolderPath', 'GetHashCode', 'GetLogicalDrives', 'GetType', 'HasShutdownStarted', 'MachineName', 'MemberwiseClone', 'NewLine', 'OSVersion', 'ProcessorCount', 'ReferenceEquals', 'SetEnvironmentVariable', 'SpecialFolder', 'StackTrace', 'SystemDirectory', 'TickCount', 'ToString', 'UserDomainName', 'UserInteractive', 'UserName', 'Version', 'WorkingSet', '__all__', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
- <p class="Code-Highlighted">>>> System.Environment.OSVersion</p>
- <p class="Code-Highlighted"><System.OperatingSystem object at 0x000000000000002B [Microsoft Windows NT 6.0.6000.0]</p>
- <p class="Code-Highlighted">>>> System.Environment.CommandLine</p>
- <p class="Code-Highlighted">'C:\\IronPython\\ipy.exe'
- <p class="LooseVerify">'"%MERLIN_ROOT%\\Bin\\Debug\\ipy.exe"'
- </p>
- <ol start="4">
- <li>
- <p class="Step">The import statement can be used also to import contents of
- a class or module into the global namespace. Use the "from ... import ..."
- flavor of the import statement to do that and explore the contents of the
- global namespace using dir().</p>
- </li>
- </ol>
- <p class="TypedExample">from System.Math import *</p>
- <p class="UserCode">dir()</p>
- <p class="HiddenCode">set1 = set(dir())
- set2 = set(dir(object))
- list(set1-set2)
- </p>
- <p class="HiddenOutput">
-
- ['Tan','Sqrt','Acos','Sin','Abs','Round','Pow','Floor','Exp','Log','Atan2','IEEERemainder','Atan','__builtins__','Asin','System','E','Cosh','__name__', 'Ceiling','DivRem','BigMul','Cos','Truncate','Min','Tanh','Log10','Sign','Max','Sinh','PI']</p>
- <p class="Stepnonumbering">Now you can call Math methods without having to specify
- the namespace and class name prefix:</p>
- <p class="TypedExample">Sin(PI/2)</p>
- <p class="Stepnonumbering">The expected output is:</p>
- <p class="Code-Highlighted">>>> from System.Math import *</p>
- <p class="Code-Highlighted">>>> dir()</p>
- <p class="Code-Highlighted">['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>
- <p class="Code-Highlighted">>>> Sin(PI/2)</p>
- <p class="Code-Background">1.0</p>
- <h3><a name="T1.2.2">Task 2: Working with .NET classes</a></h3>
- <ol>
- <li>
- <p class="Step">Import the contents of the "System.Collections" namespace
- into the global namespace:</p>
- </li>
- </ol>
- <p class="TypedExample">from System.Collections import *</p>
- <p class="Code-Background"></p>
- <ol start="2">
- <li>
- <p class="Step">Create instance of the Hashtable class and explore the instance
- using dir():</p>
- </li>
- </ol>
- <p class="TypedExample">h = Hashtable()</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(h)</p>
- <p class="HiddenCode">set1 = set(dir(h))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['Clone','ContainsValue','SyncRoot','hcp','__setitem__','__contains__','KeyEquals','IsSynchronized','GetEnumerator','GetHash','Contains','Item','Values','ContainsKey','Remove','OnDeserialization','__iter__','Add','Synchronized','EqualityComparer','__len__','comparer','Keys','Clear','IsReadOnly','CopyTo','IsFixedSize','__add__','GetObjectData','Count','__getitem__']</p>
- <ol start="3">
- <li>
- <p class="Step">Insert a few elements into the hash table:</p>
- </li>
- </ol>
- <p class="TypedExample">h["a"] = "IronPython"</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">h["b"] = "Tutorial"</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">IronPython supports the C# - style syntax for accessing
- the hash table elements. The same syntax applies to any index-able object (Arrays,
- Array lists etc):</p>
- <p class="TypedExample">h["a"]</p>
- <p class="Stepnonumbering" style="page-break-after:avoid"> </p>
- <p class="Stepnonumbering" style="page-break-after:avoid">The output of this
- step will be:</p>
- <p class="Code-Background" style="page-break-after:avoid">>>> h["a"] = "IronPython"<br />
- >>> h["b"] = "Tutorial"</p>
- <p class="Code-Highlighted" style="page-break-after:avoid">>>> h["a"]</p>
- <p class="Code-Background">'IronPython'</p>
- <ol start="4">
- <li>
- <p class="Step">Enumerate the contents of the hash table using the "for
- ... in ..." statement. The hash table elements are instances of "DictionaryEntry"
- class. Print the "Key" and "Value" properties of each entry:</p>
- </li>
- </ol>
- <p class="TypedExample">for e in h: print e.Key, ":", e.Value</p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">The expected output in the console is (the input
- line starting with "for" requires an extra return or enter key press because
- the interpreter prompts for more statements in the 'for' loop.):</p>
- <p class="Code-Highlighted">>>> for e in h: print e.Key, ":", e.Value<br>
- ...</p>
- <p class="Code-Background">a : IronPython<br />
- b : Tutorial</p>
- <ol start="5">
- <li>
- <p class="Step">You can initialize the collection classes by passing in
- the Python built-in list or tuple data types as arguments. You can
- create a Python list by specifying the list of elements in square brackets: [1,2,3].
- You create tuples by specifying elements in the parentheses: (1,2,3).</p>
- </li>
- </ol>
- <p class="TypedExample">l = ArrayList([1,2,3])</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">for i in l: print i</p>
- <p class="TypedExample">s = Stack((1,2,3))</p>
- <p class="TypedExample">while s.Count: s.Pop()</p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">The expected output is:</p>
- <p class="Code-Highlighted">>>> l = ArrayList([1,2,3])<br />
- >>> for i in l: print i<br>
- ...</p>
- <p class="Code-Background">1<br />
- 2<br />
- 3</p>
- <p class="Code-Background"></p>
- <p class="Code-Highlighted">>>> s = Stack((1,2,3))<br />
- >>> while s.Count: s.Pop()<br>...</p>
- <p class="Code-Background">3<br />
- 2<br />
- 1</p>
- <h3><a name="T1.2.3">Task 3: Generics</a></h3>
- <ol>
- <li>
- <p class="Step">Import the Generic collections from the System.Collections.Generic
- namespace:</p>
- </li>
- </ol>
- <p class="TypedExample">from System.Collections.Generic import *</p>
- <p class="Code-Background"></p>
- <ol start="2">
- <li>
- <p class="Step">To instantiate a generic class, the generic type arguments
- must be specified. IronPython uses the following syntax to specify the type
- arguments: generic_type[type_argument, ...]. Create an instance of generic
- list of string:</p>
- </li>
- </ol>
- <p class="TypedExample">l = List[str]()</p>
- <p class="Code-Background"></p>
- <ol start="3">
- <li>
- <p class="Step">Add string values into the list. Since we created a list of
- string, adding strings is possible:</p>
- </li>
- </ol>
- <p class="TypedExample">l.Add("Hello")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">l.Add("Hi")</p>
- <p class="Code-Background"></p>
- <ol start="4">
- <li>
- <p class="Step">Try adding objects of types other than string:</p>
- </li>
- </ol>
- <p class="ExceptionExample">l.Add(3)</p>
- <p class="Code-Background"></p>
- <p class="ExceptionExample">l.Add(2.5)</p>
- <p class="Code-Background"></p>
- <p class="ExceptionExample">l.Add([1,2,3])</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">Obviously, adding non-strings will fail with type
- error:</p>
- <p class="Code-Highlighted">>>> l.Add(3)</p>
- <p class="Code-Highlighted">Traceback (most recent call last):<br>
-
- File , line unknown, in Initialize##40
- <br>
- TypeError: expected str, got int
- <br></p>
- <ol start="5">
- <li>
- <p class="Step">Enumerate the generic collection:</p>
- </li>
- </ol>
- <p class="TypedExample">for i in l: print i</p>
- <p class="Stepnonumbering">The output will be:</p>
- <p class="Code-Highlighted">>>> for i in l: print i<br>...</p>
- <p class="Code-Background">Hello<br />
- Hi</p>
- <p class="ExceptionOutput">TypeError: expected str, got int
- TypeError: expected str, got float
- TypeError: expected str, got list</p>
- <ol start="6">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
- by Enter)</p>
- </li>
- </ol>
- <h2><a name="T1.3">Exercise 3: Loading .NET libraries</a></h2>
- <p class="Body">IronPython can directly import only some of the .NET libraries
- - the most commonly used ones. To use additional .NET libraries, they must be
- explicitly referenced. IronPython maintains a list of all referenced
- assemblies (see clr.References in Task 1). To add a reference to a .NET assembly, use the functions
- available in the built-in "clr" module:</p>
- <ul>
- <li>
- <p class="Body"><b>clr.AddReference</b> adds a reference to the .NET assembly
- either by passing the .NET assembly object directly, or specifying the file
- name or the assembly name (full or partial). This function is provided primarily
- for the interactive exploration. We recommend using the following functions
- in the code modules, since they provide more control over which assembly
- is being loaded.</p>
- </li>
- <li>
- <p class="Body"><b>clr.AddReferenceToFile</b> adds reference to the assembly
- specified by its file name. This function will load the assembly from the
- file regardless of the assembly version. As a result, it doesn't guarantee
- that the correct assembly version is being loaded. To guarantee that correct
- assembly version is being loaded, use clr.AddReferenceByName. Moreover,
- AddReferenceToFile requires that the assembly be located in a
- directory listed in sys.path.</p>
- </li>
- <li>
- <p class="Body"><b>clr.AddReferenceToFileAndPath</b> provides similar
- functionality to AddReferenceToFile. The difference is that it accepts
- absolute path and before loading the assembly, AddReferenceToFileAndPath
- adds the file path into sys.path.</p>
- </li>
- <li>
- <p class="Body"><b>clr.AddReferenceByName</b> adds reference to the assembly
- specified by its full assembly name, for example: 'System.Xml, Version=2.0.0.0,
- Culture=neutral, PublicKeyToken=b77a5c561934e089'.</p>
- </li>
- <li>
- <p class="Body"><b>clr.AddReferenceByPartialName</b> adds reference to the
- assembly by specifying a partial assembly name. This function cannot guarantee
- that the correct version of the assembly is being loaded. Use clr.AddReferenceByName
- to add reference to specific version of the assembly.</p>
- </li>
- </ul>
- <h3><a name="T1.3.1">Task 1: Using System.Xml - AddReference</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">To import System.Xml, the reference to the assembly containing
- the Xml components must be first added to IronPython. Add reference to System.Xml
- using the following code (you can enter "clr.References" before
- and after the call to clr.AddReference to see it change if you want):</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">clr.AddReference("System.Xml")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">from System.Xml import *</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">dir()</p>
- <p class="HiddenOutput">['ConformanceLevel', 'EntityHandling', 'Formatting', 'IHasXmlNode', 'IXmlLineInfo', 'IXmlNamespaceResolver', 'NameTable', 'NewLineHandling', 'ReadState', 'Schema', 'Serialization', 'ValidationType', 'WhitespaceHandling', 'WriteState', 'XPath', 'XmlAttribute', 'XmlAttributeCollection', 'XmlCDataSection', 'XmlCharacterData', 'XmlComment', 'XmlConvert', 'XmlDateTimeSerializationMode', 'XmlDeclaration', 'XmlDocument', 'XmlDocumentFragment', 'XmlDocumentType', 'XmlElement', 'XmlEntity', 'XmlEntityReference', 'XmlException', 'XmlImplementation', 'XmlLinkedNode', 'XmlNameTable', 'XmlNamedNodeMap', 'XmlNamespaceManager', 'XmlNamespaceScope', 'XmlNode', 'XmlNodeChangedAction', 'XmlNodeChangedEventArgs', 'XmlNodeChangedEventHandler', 'XmlNodeList', 'XmlNodeOrder', 'XmlNodeReader', 'XmlNodeType', 'XmlNotation', 'XmlOutputMethod', 'XmlParserContext', 'XmlProcessingInstruction', 'XmlQualifiedName', 'XmlReader', 'XmlReaderSettings', 'XmlResolver', 'XmlSecureResolver', 'XmlSignificantWhitespace', 'XmlSpace', 'XmlText', 'XmlTextReader', 'XmlTextWriter', 'XmlTokenizedType', 'XmlUrlResolver', 'XmlValidatingReader', 'XmlWhitespace', 'XmlWriter', 'XmlWriterSettings', 'Xsl', '__builtins__', '__doc__', '__name__', 'clr']</p>
- <ol start="3">
- <li>
- <p class="Step">Note that the clr.AddReference function accepts either System.Reflection.Assembly object or string
- as a parameter. The string parameter can
- be a full assembly name, a partial assembly name, or a file name. For more control
- over the assembly references, use the appropriate functions described
- above. </p>
- <p class="Step">For example, consider the following alternatives for the statement clr.AddReference("System.Xml") above:</p>
- </li>
- </ol>
- <p class="TypedExample">clr.AddReferenceByName('System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">clr.AddReferenceByPartialName("System.Xml")</p>
- <p class="Code-Background"></p>
- <ol start="4">
- <li>
- <p class="Step">Load the XML file "load.xml" into the XmlDocument. The
- xml file contains sample savegame data from the IronPython sample "Puzzle" .
- For direct viewing, the load.xml file is located in the Tutorial folder</p>
- </li>
- </ol>
- <p class="TypedExample">d = XmlDocument()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">d.Load("load.xml")</p>
- <p class="Code-Background"></p>
- <ol start="5">
- <li>
- <p class="Step">We can now query the document. Query for all the saved games using the query below:</p>
- </li>
- </ol>
- <p class="TypedExample">n = d.SelectNodes("//Puzzle/SavedGames/Game/@caption")</p>
- <p class="TypedExample">for e in n: print e.Value</p>
- <p class="Stepnonumbering"> </p>
- <p class="Stepnonumbering">The output in the console window will be:</p>
- <p class="Code-Highlighted">>>> n = d.SelectNodes("//Puzzle/SavedGames/Game/@caption")<br />
- >>> for e in n: print e.Value<br>...</p>
- <p class="Code-Background">
- Seattle (default game)<br />
- New York<br />
- World<br />
- North America<br />
- </p>
- <ol start="6">
- <li>
- <p class="Step">(Optional) Import the "xmlutil.py" module located in the
- Tutorial directory and use the function provided in the module to walk the
- contents of the Xml document:</p>
- </li>
- </ol>
- <p class="TypedExample">import xmlutil</p>
- <p class="TypedExample">for e in xmlutil.Walk(d): print e.Name, e.Value</p>
- <p class="HiddenOutput">#document None
- #comment *************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Microsoft Public License. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Microsoft Public License, please send an email to
- * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Microsoft Public License.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************
- Puzzle None
- SavedGames None
- Game None
- caption Seattle (default game)
- type a
- y 714
- x 327
- level 11
- dimension 3
- Game None
- caption New York
- type r
- y 1538
- x 1205
- level 12
- dimension 3
- Game None
- caption World
- type h
- y 0
- x 0
- level 2
- dimension 4
- Game None
- caption North America
- type a
- x 2
- y 5
- level 4
- dimension 3
- TopLeftPreviewTile None
- x -3
- y -3
- dimension 3
- level 5
- Cache None
- allow true</p>
- <p class="Stepnonumbering">The Walk function is a generator (a Python function
- that contains a "yield" statement). As the Walk function executes, it returns
- (yields) the XML nodes one by one to the caller who iterates over the generator.
- The source for the Walk function is:</p>
- <p class="CodeSample">def Walk(xml):</br>
- yield xml</br><br>
- if hasattr(xml, "Attributes"):<br />
- attrs = xml.Attributes<br />
- if attrs:<br />
- for attr in attrs:</br>
-
- yield attr</br><br>
- for child in xml:<br />
- for c in Walk(child):</br>
-
- yield c</p>
- <ol start="7">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
- by Enter)</p>
- </li>
- </ol>
- <h3><a name="T1.3.2">Task 2: Mapack - Loading the .NET libraries - AddReferenceToFile</a></h3>
- <p class="Normal">This task requires the Mapack.dll library for linear algebra computations.
- The library is not part of the IronPython distribution. See <a href="#Mapack">prerequisites</a>
- for download details.</p>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Use the clr.AddReferenceToFile function to load the Matrix
- library "Mapack.dll":</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">clr.AddReferenceToFile("Mapack.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">from Mapack import *</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">dir()</p>
- <p class="Stepnonumbering">The expected output will be:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("Mapack.dll")<br />
- >>> from Mapack import *<br />
- >>> dir()</p>
- <p class="Code-Background">['CholeskyDecomposition', 'EigenvalueDecomposition', 'LuDecomposition', 'Matrix', 'QrDecomposition', 'SingularValueDecomposition', '__builtins__', '__doc__', '__name__', 'clr']</p>
- <ol start="3">
- <li>
- <p class="Step">Create instance of Matrix class:</p>
- </li>
- </ol>
- <p class="ExceptionExample">m = Matrix()</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">Oops, bad arguments for the constructor. In the next
- step you'll learn the way to discover the constructors available.</p>
- <p class="Code-Highlighted">Traceback (most recent call last):
- <br>
- File , line unknown, in Initialize##30
- <br>
- TypeError: Matrix() takes at least 1 argument (0 given)</p>
- <ol start="4">
- <li>
- <p class="Step">Using the __doc__ attribute, find out information about
- Matrix constructors:</p>
- </li>
- </ol>
- <p class="TypedExample">print Matrix.__new__.__doc__</p>
- <p class="Code-Highlighted">>>> print Matrix.__new__.__doc__</p>
- <p class="Code-Background">__new__(cls, int rows, int columns)<br />
- __new__(cls, int rows, int columns, float value)<br />
- __new__(cls, Array[Array[float]] value)
- </p>
- <ol start="5">
- <li>
- <p class="Step">Create instances of the Matrix class using the correct constructors
- and set some matrix elements manually. IronPython supports custom indexing
- on .NET classes. </p>
- </li>
- </ol>
- <p class="TypedExample">m = Matrix(2, 2, 1.2)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">n = Matrix(2,1)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">n[0,0] = 4</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">print m</p>
- <p class="TypedExample">print n</p>
- <p class="Code-Highlighted">>>> m = Matrix(2, 2, 1.2)<br />
- >>> n = Matrix(2,1)<br />
- >>> n[0,0] = 4<br />
- >>> print m</p>
- <p class="Code-Background">1.2 0 <br />
- 0 1.2
- </p>
- <p class="Code-Highlighted">>>> print n</p>
- <p class="Code-Background">4 <br />
- 0
- </p>
- <ol start="6">
- <li>
- <p class="Step">(Optional) IronPython also supports overloaded operators. Matrix does overload operators +, - (binary and unary) and *. You can see
- Python representation of the operators (__add__, __mul__, __sub__, ...)
- using dir():</p>
- </li>
- </ol>
- <p class="UserCode">dir(m)</p>
- <p class="HiddenCode">set1 = set(dir(m))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['Submatrix','Symmetric','Clone','__sub__','Columns','Trace','__ne__','InfinityNorm','Rows','__setitem__','Multiply','__neg__','Diagonal','Random','Subtract','Item','Square','FrobeniusNorm','Solve','__rmul__','Negate','Add','Inverse','__radd__','__rsub__','__mul__','Determinant','__add__','__eq__','__getitem__','Norm1','Transpose']</p>
- <ol start="7">
- <li>
- <p class="Step">Make simple calculations with the matrices:</p>
- </li>
- </ol>
- <p class="TypedExample">m * n</p>
- <p class="TypedExample">n.Transpose() * m</p>
- <p class="TypedExample">m * 3</p>
- <p class="TypedExample">n + -n</p>
- <p class="Stepnonumbering">The expected output of this step is:</p>
- <p class="Code-Highlighted">>>> m * n</p>
- <p class="LooseVerify">Mapack.Matrix</p>
- <p class="Code-Highlighted">>>> n.Transpose() * m</p>
- <p class="LooseVerify">Mapack.Matrix</p>
- <p class="Code-Highlighted">>>> m * 3</p>
- <p class="LooseVerify">Mapack.Matrix</p>
- <p class="Code-Highlighted">>>> n + -n</p>
- <p class="LooseVerify">Mapack.Matrix</p>
- <p class="ExceptionOutput">TypeError: Matrix() takes at least 1 argument (0 given)</p>
- <ol start="8">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
- by Enter)</p>
- </li>
- </ol>
- <h2><a name="T1.4">Exercise 4: Obtaining and Using Python Standard Library</a></h2>
- <p class="Body">In this exercise, you will obtain Python and point
- IronPython at the Python standard library. If you installed IronPython from the MSI installer,
- the Python standard library is installed by default and you can skip this exercise.</p>
- <h3><a name="T1.4.1">Task 1: Configuring IronPython to use the Python standard library</a></h3>
- <ol>
- <li>
- <p class="Step">Download the latest Python installer from
- <a href="http://www.python.org/download/">http://www.python.org/download/</a>
- and install Python. The rest of this exercise will assume you used
- defaults (and installed to c:\python25, for example).</p>
- </li>
- <li>
- <p class="Step">Create a file named "site.py" and place it into your
- IronPython "Lib" directory. There might be one there
- already, so you can just edit it. The "site.py" file is executed every time
- you run IronPython. To tell IronPython where the Python standard library
- is, you can add the "lib" directory of Python to IronPython's path. To
- do so, put the following code into IronPython's "site.py" file (replace
- c:\python25\lib with your actual path to the Python lib directory):</p>
- </li>
- </ol>
- <p class="TypedExample">import sys</p>
- <p class="TypedExample">sys.path.append(r"c:\python25\lib")</p>
- <ol start="3">
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Now you can use the Python standard library from
- IronPython, for example to get the current working directory (output
- uses assumed location of your IronPython installation):</p>
- </li>
- </ol>
- <p class="TypedExample">import os</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">os.getcwd()</p>
- <p class="Code-Highlighted">'C:\\ironpython\\Tutorial'</p>
- <p class="LooseVerify">
-
- '%MERLIN_ROOT%\\Test\\IronPythonTutorial'</p>
- <p class="LabSummary">Tutorial Summary</p>
- <p class="Body">In this tutorial you performed the following exercises.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T1.1">The IronPython interactive console</a></p>
- </li>
- <li>
- <p class="Body"><a href="#T1.2">Using the standard .NET libraries from IronPython</a></p>
- </li>
- <li>
- <p class="Body"><a href="#T1.3">Loading .NET libraries</a></p>
- </li>
- <li>
- <p class="Body"><a href="#T1.4">Obtaining and Using Python Standard
- Library</a></p>
- </li>
- </ul>
- <p class="Body">In this tutorial, you became acquainted with IronPython interactive
- console, including the dynamic exploratory way of development using the dir() function
- and __doc__ attribute to explore the environment. You learned to load and import
- .NET libraries from IronPython (using the import statement), create instances
- of .NET classes (including generic classes), call methods, enumerate .NET collections,
- and even use overloaded operators on .NET objects. Finally, you
- learned how to access standard Python libraries.</p>
- <p class="Body"> </p>
- <h1><a name="T2">Tutorial 2: Advanced IronPython</a></h1>
- <p class="Body">The large part of the beauty of IronPython lies within the dynamic-style
- development -- modifying the live application by adding functioning elements
- to it. With Windows applications, this often requires delegates and event handling
- (i.e., adding a button to an existing form and adding functionality to the button
- to handle the user pressing the button).</p>
- <p class="Body">This tutorial will focus on creating delegates, handling
- events in IronPython, and creating Windows applications using Windows Forms and
- the new Windows Presentation Foundation (formerly known as Avalon).</p>
- <p class="Body">Estimated time to complete this tutorial: <b>25 minutes</b></p>
- <p class="Body">The objective of this tutorial is to learn how to create delegates
- and handle events using IronPython, and to use that knowledge to build working Windows
- applications using Windows Forms and Windows Presentation Foundation.</p>
- <ul>
- <li>
- <p class="ExerciseList"><a href="#T2.1">Events and Delegates</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T2.2">Windows Forms</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T2.3">Windows Presentation Foundation
- (Avalon)</a></p>
- </li>
- </ul>
- <h2><a name="T2.1">Exercise 1: Events and Delegates</a></h2>
- <p class="Body">In this exercise, you will create a simple event handler and
- learn how to explore event handler use. The event handler we'll use in this
- exercise is the FileSystemWatcher - a component that raises events on file system
- changes.</p>
- <h3><a name="T2.1.1">Task 1: File System Watcher</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Import the contents of System.IO into the global namespace:</p>
- </li>
- </ol>
- <p class="TypedExample">from System.IO import *</p>
- <p class="Code-Background"></p>
- <ol start="3">
- <li>
- <p class="Step">Create instance of the FileSystemWatcher class and set Path
- property to watch over the current directory:</p>
- </li>
- </ol>
- <p class="TypedExample">w = FileSystemWatcher()</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(w)</p>
- <p class="HiddenCode">set1 = set(dir(w))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['GetLifetimeService', 'EndInit', 'IncludeSubdirectories', 'Filter', 'WaitForChanged', 'Disposed', 'OnChanged', 'DesignMode', 'InitializeLifetimeService', 'NotifyFilter', 'GetService', 'Path', 'Created', 'EnableRaisingEvents', 'InternalBufferSize', 'SynchronizingObject', 'OnError', 'Site', 'BeginInit', 'Deleted', 'Error', 'Dispose', '__enter__', 'CanRaiseEvents', 'Events', 'Changed', '__exit__', 'Container', 'OnRenamed', 'Renamed', 'CreateObjRef', 'OnCreated', 'OnDeleted']</p>
- <p class="TypedExample">w.Path = "."</p>
- <p class="Code-Background"></p>
- <ol start="4">
- <li>
- <p class="Step" style="page-break-after:avoid">Create the function to handle
- the events. Because we don't know yet what arguments the delegate will have,
- let's accept any number of arguments (the *arg notation):</p>
- </li>
- </ol>
- <p class="TypedExample">def handle(*args): print args</p>
- <p class="Code-Background"></p>
- <ol start="5">
- <li>
- <p class="Step">Register the event handler for the 'Changed', 'Created',
- and 'Deleted' events:</p>
- </li>
- </ol>
- <p class="TypedExample">w.Changed += handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Created += handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Deleted += handle</p>
- <p class="Code-Background"></p>
- <ol start="6">
- <li>
- <p class="Step">Enable the watcher to raise events:</p>
- </li>
- </ol>
- <p class="TypedExample">w.EnableRaisingEvents = True</p>
- <ol start="7">
- <li>
- <p class="Step">Open the Tutorial folder and create a file. An easy way
- to create the file is to right-click with the mouse and select "New\Text
- Document". The file watcher will raise the "Created" event.</p>
- </li>
- </ol>
- <p class="Stepnonumbering">You can then open the file in Notepad, type in any
- text, and save the file. This raises the "Changed" event.
- Then finish by deleting
- the file to see the "Deleted" event get raised.</p>
- <p class="Stepnonumbering">At the end of this step, the output in the command
- window will be similar to the following:</p>
- <p class="Code-Highlighted">(System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x03CE0BB8>)<br />
- (System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x039B3B4D>)<br />
- (System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x039B3B4D>)<br />
- (System.IO.FileSystemWatcher, <System.IO.FileSystemEventArgs object at 0x014EF022>)</p>
- <ol start="8">
- <li>
- <p class="Step">In the next task, we will create an improved event handler. For now, remove the current event handler from the file watcher events:</p>
- </li>
- </ol>
- <p class="TypedExample">w.Changed -= handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Created -= handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Deleted -= handle</p>
- <p class="Code-Background">
- </p>
- <ol start="9">
- <li>
- <p class="Step">(Optional) You can try step 7 again to see that the events,
- while they are still being raised, are not being handled by the Python "handler"
- function.</p>
- </li>
- </ol>
- <h3><a name="T2.1.2">Task 2: Improving the event handler</a></h3>
- <ol>
- <li>
- <p class="Step">In the previous task, step 7 we can see that the types of
- the parameters passed to all three events were the same:</p>
- </li>
- </ol>
- <p class="Stepnonumbering">FileSystemWatcher - the instance of the object that
- raised the event</p>
- <p class="Stepnonumbering">FileSystemEventArgs - the information about the event
- raised</p>
- <p class="Stepnonumbering">Use dir() to explore the event arguments class to
- find what information the event contains:</p>
- <p class="TypedExample">from System.IO import *</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w = FileSystemWatcher()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Path = "."</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(FileSystemEventArgs)</p>
- <p class="HiddenCode">set1 = set(dir(FileSystemEventArgs))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="Stepnonumbering" style="page-break-after:avoid">The output in the
- console window will be:</p>
- <p class="Code-Highlighted" style="page-break-after:avoid">>>> dir(FileSystemEventArgs)</p>
- <p class="Code-Highlighted">['ChangeType', 'Empty', 'Equals', 'FullPath', 'GetHashCode', 'GetType', 'MemberwiseClone', 'Name', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
- <p class="HiddenOutput">
-
- ['FullPath', 'Name', 'Empty', 'ChangeType']</p>
- <ol start="2">
- <li>
- <p class="Step">Now with more knowledge of the event argument properties,
- we can create a better event handler that will print ChangeType and FullPath
- properties of the event argument object:</p>
- </li>
- </ol>
- <p class="TypedExample">def handle(w, a): print a.ChangeType, a.FullPath</p>
- <ol start="3">
- <li>
- <p class="Step">Register the new event handler for the 'Changed', 'Created'
- and 'Deleted' events:</p>
- </li>
- </ol>
- <p class="TypedExample">w.Changed += handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Created += handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Deleted += handle</p>
- <p class="Code-Background">
-
- </p>
- <ol start="4">
- <li>
- <p class="Step">Make sure the raising of the events is enabled:</p>
- </li>
- </ol>
- <p class="TypedExample">w.EnableRaisingEvents = True</p>
- <ol start="5">
- <li>
- <p class="Step">Open the Tutorial folder again and create a new file ("Created"
- event), edit the file in Notepad and save it ("Changed" event) and finish
- by deleting the file ("Deleted" event).</p>
- </li>
- </ol>
- <p class="Stepnonumbering">At the end of this step, the output in the command
- window will be similar to the following:</p>
- <p class="Code-Highlighted">Created .\New Text Document.txt<br />
- Changed .\New Text Document.txt<br />
- Changed .\New Text Document.txt<br />
- Deleted .\New Text Document.txt</p>
- <ol start="6">
- <li>
- <p class="Step">Remove the event handler from the file watcher events:</p>
- </li>
- </ol>
- <p class="TypedExample">w.Changed -= handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Created -= handle</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Deleted -= handle</p>
- <p class="Code-Background"></p>
- <ol start="7">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6, followed
- by Enter).</p>
- </li>
- </ol>
-
- <h3><a name="T2.1.3">Task 3: Defining events in Python</a></h3>
- <ol>
- <li>
- <p class="Step">Finally let's look at how we can get event handler syntax from Python code:</p>
- </li>
- </ol>
- <p class="Stepnonumbering">pyevent - a module providing Python event support</p>
- <p class="Stepnonumbering">make_event - a function that returns an event tuple containing both the callable object and the object
- that allows connecting and unconnecting to the event.</p>
- <br/>
- <p class="Stepnonumbering" style="page-break-after:avoid">To create an event:</p>
- <br/>
- <p class="TypedExample">import pyevent</p>
- <p class="TypedExample">hook,caller = pyevent.make_event()</p>
- <br/>
- <p class="Stepnonumbering">This has returned back to us two objects. The first object allows a user to hook a
- function up to the event. The second object allows the owner of the event to cause the event to be raised.
- This allows for the separation of these abilities just like .NET. Now let's take this and put it into a class and
- see how it gets used.</p>
-
- <ol start="2">
- <li>
- <p class="Step">We'll define a class that has an event for</p>
- </li>
- </ol>
-
- <p class="TypedExample">class MyClass(object):<br>
- OnNewInstance,_NewInstance= pyevent.make_event()<br>
- def __new__(cls):<br>
- res = object.__new__(object)<br>
- MyClass._NewInstance(res)<br>
- </p>
- <p class="Code-Background"></p>
- <p class="Code-Background"></p>
- <p class="Code-Background"></p>
- <p class="TypedExample">def NewInst(x): print 'new inst: ', x </p>
- <p class="Code-Background"></p>
- <p class="TypedExample">MyClass.OnNewInstance += NewInst</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a = MyClass()</p>
- <p class="LooseVerify">new inst</p>
-
- <ol start="3">
- <li>
- <p class="Step">Just like with CLR events you can also remove event handlers:</p>
- </li>
- </ol>
- <p class="TypedExample">MyClass.OnNewInstance -= NewInst</p>
- <p class="Code-Background"></p>
-
- <h2><a name="T2.2">Exercise 2: Windows Forms</a></h2>
- <p class="Body">To interactively develop Windows applications, IronPython must
- be initialized for that purpose. By default, the Python console executes on one thread only. While this thread awaits text input in the console window, the Windows application
- being dynamically created from the console is not able to process Windows messages.
- Therefore, the application does not repaint itself or handle input to the UI.</p>
- <p class="Body">We provide a .py file to initialize IronPython for Windows Forms
- development, see tasks below.</p>
- <p class="Body">In this exercise, you will create simple Windows Forms applications
- dynamically from the IronPython interactive console.</p>
- <h3><a name="T2.2.1">Task 1: Simple Windows Forms application</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Initialize Windows Forms by loading the winforms module/script:</p>
- </li>
- </ol>
- <p class="TypedExample">import winforms</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">Python modules get automatically initialized
- (executed) upon import so the Windows Forms initialization code has executed
- as part of the import statement.</p>
- <ol start="3">
- <li>
- <p class="Step">Import the contents of the System.Windows.Forms and System.Drawing
- namespaces into the global namespace: </p>
- </li>
- </ol>
- <p class="TypedExample">from System.Windows.Forms import *</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">from System.Drawing import *</p>
- <p class="Code-Background"></p>
- <ol start="4">
- <li>
- <p class="Step">Create an instance of the Form class and display it:</p>
- </li>
- </ol>
- <p class="TypedExample">f = Form()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">f.Show()</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">You may need to alt-tab or look for the running
- application since it may not have popped to the top level on your desktop.</p>
- <ol start="5">
- <li>
- <p class="Step">Now set the form Text property:</p>
- </li>
- </ol>
- <p class="TypedExample">f.Text = "My First Interactive Application"</p>
- <p class="Code-Background"></p>
- <ol start="6">
- <li>
- <p class="Step">To bring the application alive, let's focus on the Click
- event of the form. Create an event handler for the Click event and click
- on the form to receive the event. Then remove the event handler</p>
- </li>
- </ol>
- <p class="TypedExample">def click(*args): print args</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">f.Click += click</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">Click on the form to receive the event..</p>
- <p class="Stepnonumbering">The output will be similar to:</p>
- <p class="Code-Highlighted">>>> (System.Windows.Forms.Form, Text: My First Interactive
- Application, <System.Windows.Forms.MouseEventArgs object at 0x02324551>)</p>
- <p class="Stepnonumbering">Now remove the click handler because we're going
- to further develop it.</p>
- <p class="TypedExample">f.Click -= click</p>
- <p class="Code-Background"></p>
- <ol start="7">
- <li>
- <p class="Step">Use dir() function to explore the MouseEventArgs</p>
- </li>
- </ol>
- <p class="UserCode">dir(MouseEventArgs)</p>
- <p class="HiddenCode">set1 = set(dir(MouseEventArgs))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['Location', 'Y', 'X', 'Button', 'Clicks', 'Empty', 'Delta']</p>
- <ol start="8">
- <li>
- <p class="Step" style="page-break-after:avoid">Knowing the contents of the
- MouseEventArgs, create an improved event handler for the Click event:</p>
- </li>
- </ol>
- <p class="TypedExample" style="page-break-after:avoid">def click(f, a):<br>
- l = Label(Text = "Hello")<br>
- l.Location = a.Location<br>
- f.Controls.Add(l)</p>
- <p class="Code-Background"></p>
- <ol start="9">
- <li>
- <p class="Step" style="page-break-after:avoid">Register the event handler:</p>
- </li>
- </ol>
- <p class="TypedExample">f.Click += click</p>
- <p class="Code-Background"></p>
- <ol start="10">
- <li>
- <p class="Step">Now clicking on the form with the mouse will add "Hello"
- labels. We can also access the controls we just added via mouse clicks and
- change them</p>
- </li>
- </ol>
- <p class="TypedExample">for i in f.Controls: i.Font = Font("Verdana", 15)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">for i in f.Controls: i.Text = "Hi"</p>
- <p class="Code-Background"></p>
- <ol start="11">
- <li>
- <p class="Step">After a few moments of clicking, the form will get quite
- crowded, so we can clear it out:</p>
- </li>
- </ol>
- <p class="TypedExample">f.Controls.Clear()</p>
- <p class="HiddenCode">f.Close()</p>
- <p class="Code-Background"></p>
- <ol start="12">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
- by Enter)</p>
- </li>
- </ol>
- <p class="Body">The standalone version of this script is located in wfdemo.py
- in the Tutorial directory.</p>
- <h2><a name="T2.3">Exercise 3: Windows Presentation Foundation (Avalon)</a></h2>
- <p class="Body">This exercise requires Windows Presentation Foundation installed. Please see <a href="#Avalon">prerequisites</a> for more information.</p>
- <p class="Body">Just like Windows Forms, the Windows Presentation Foundation
- also requires initialization to support interactive development. The initialization
- code is available in the "Tutorial\avalon.py" file.</p>
- <p class="Body">In this exercise, you will interactively create simple interactive
- Windows Presentation Foundation application.</p>
- <h3><a name="T2.3.1">Task 1: Simple Avalon Application</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Initialize Windows Presentation Foundation:</p>
- </li>
- </ol>
- <p class="TypedExample">from avalon import *</p>
- <p class="Code-Background"></p>
- <ol start="3">
- <li>
- <p class="Step">Create Avalon window, display it, and set some of its properties:</p>
- </li>
- </ol>
- <p class="TypedExample">w = Window()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Show()</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">You may need to alt-tab or look for the running
- application since it may not have popped to the top level on your desktop.
- Now, let's do more.</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Title = "My Avalon Application"</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.SizeToContent = SizeToContent.WidthAndHeight</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">By setting the window property to "size to
- content", the window shrinks.</p>
- <ol start="4">
- <li>
- <p class="Step">Let's add the content now:</p>
- </li>
- </ol>
- <p class="TypedExample">w.Content = TextBlock()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Content.Text = "Hello IronPython!"</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Content.FontSize = 50</p>
- <p class="Code-Background"></p>
- <ol start="5">
- <li>
- <p class="Step">Remove the window content:</p>
- </li>
- </ol>
- <p class="TypedExample">w.Content = None</p>
- <h3><a name="T2.3.2">Task 2: Avalon calculator</a></h3>
- <ol>
- <li>
- <p class="Step">If you are continuing from the Task 1, proceed to step 2. Otherwise, please follow the <a href="#T2.3.1">steps 1-3</a> from the Task
- 1. </p>
- </li>
- <li>
- <p class="Step">Windows Presentation Foundation uses the XAML format to describe
- the graphical layout and basic behaviors of UI. Load the "calc.xaml" and display the resulting content:</p>
- </li>
- </ol>
- <p class="TypedExample">from avalon import *</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w = Window()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Show()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">w.Content = LoadXaml("calc.xaml")</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">If you flowed into this task from Task 1, then
- w.SizeToContent may have been reset to manual, but in either case, you may
- need to manually drag the window's border down and to the right to see the
- calculator UI.</p>
- <ol start="3">
- <li>
- <p class="Step">Let's walk the calculator's object model (function
- Walk is defined in the avalon.py file)</p>
- </li>
- </ol>
- <p class="TypedExample">for n in Walk(w): print n</p>
- <p class="HiddenOutput">System.Windows.Window</p>
- <p class="LooseVerify">Canvas
- Canvas
- Rectangle
- Canvas</p>
- <p class="HiddenOutput">System.Windows.Controls.TextBox
- System.Windows.Controls.RichTextBox
- System.Windows.Controls.Button: 1
- 1
- System.Windows.Controls.Button: 9
- 9
- System.Windows.Controls.Button: 8
- 8
- System.Windows.Controls.Button: 5
- 5
- System.Windows.Controls.Button: 4
- 4
- System.Windows.Controls.Button: 2
- 2
- System.Windows.Controls.Button: 3
- 3
- System.Windows.Controls.Button: 6
- 6
- System.Windows.Controls.Button: *
- *
- System.Windows.Controls.Button: 7
- 7
- System.Windows.Controls.Button: -
- -
- System.Windows.Controls.Button: 0
- 0
- System.Windows.Controls.Button: .
- .
- System.Windows.Controls.Button: =
- =
- System.Windows.Controls.Button: +
- +
- System.Windows.Controls.Button: /
- /
- System.Windows.Controls.Button: C
- C</p>
- <ol start="4">
- <li>
- <p class="Step">Using Python's list comprehension syntax we can capture
- all buttons in the calculator:</p>
- </li>
- </ol>
- <p class="TypedExample">[ n for n in Walk(w) if isinstance(n, Button) ]</p>
- <p class="LooseVerify">System.Windows.Controls.Button</p>
- <p class="Stepnonumbering">The console printed the list of all buttons. To
- save the button list object in a variable, use the interpreter's "_"
- variable, which always holds the last non-None value result printed by the
- console:</p>
- <p class="TypedExample">buttons = _</p>
- <p class="Code-Background"></p>
- <ol start="5">
- <li>
- <p class="Step">At this point we can make changes to all the buttons, for
- example, change the colors and fonts:</p>
- </li>
- </ol>
- <p class="TypedExample">for b in buttons: b.FontSize *= 2</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">for b in buttons: b.Foreground = SolidColorBrush(Colors.Blue)</p>
- <p class="Code-Background"></p>
- <ol start="6">
- <li>
- <p class="Step" style="page-break-after:avoid">To bring the calculator alive,
- we need to provide event handlers for each button. These can be imported
- from the calculator.py file:</p>
- </li>
- </ol>
- <p class="TypedExample">import calculator</p>
- <p class="Code-Background"></p>
- <ol start="7">
- <li>
- <p class="Step">The calculator module contains the Calculator class that
- will be responsible for tracking the expression as it is being built by
- the calculator. To bring the calculator alive (that is, register event
- handlers for the UI), enter:</p>
- </li>
- </ol>
- <p class="TypedExample">calculator.enliven(w)</p>
- <p class="HiddenOutput">Registering self.on_One to handle One.Click
- Registering self.on_Nine to handle Nine.Click
- Registering self.on_Eight to handle Eight.Click
- Registering self.on_Five to handle Five.Click
- Registering self.on_Four to handle Four.Click
- Registering self.on_Two to handle Two.Click
- Registering self.on_Three to handle Three.Click
- Registering self.on_Six to handle Six.Click
- Registering self.on_Multiply to handle Multiply.Click
- Registering self.on_Seven to handle Seven.Click
- Registering self.on_Subtract to handle Subtract.Click
- Registering self.on_Zero to handle Zero.Click
- Registering self.on_DecimalPoint to handle DecimalPoint.Click
- Registering self.on_Equals to handle Equals.Click
- Registering self.on_Plus to handle Plus.Click
- Registering self.on_Divide to handle Divide.Click
- Registering self.on_Clear to handle Clear.Click</p>
- <ol start="8">
- <li>
- <p class="Step">At this point you can click on the calculator buttons and
- evaluate expressions.</p>
- </li>
- <li>
- <p class="Step">Feel free to explore the calculator.py script file (located
- in Tutorial directory). The point of interest is the Calculator.__init__
- method:</p>
- </li>
- </ol>
- <p class="CodeSample">def __init__(self, controls):
- (1)<br />
- self.expression = ""
- (2)<br />
-
- (3)<br />
- for i in controls:
- (4)<br />
- if isinstance(i, Button):
- (5)<br />
- if hasattr(self,
- "on_" + i.Name):
- (6)<br />
-
- i.Click += getattr(self, "on_" + i.Name)
- (7)<br />
- elif isinstance(i, TextBox):
- (8)<br />
- if i.Name ==
- "Result":
- (9)<br />
-
- self.result = i
- (10)<br />
- self.result.Text = self.expression
- (11)</p>
- <p class="Stepnonumbering">The "controls" argument for the method is the list of buttons and
- text boxes, very similar to the list of buttons created in steps 3 and 4 of this task.
- The initialization code enumerates the list (line 4), identifies buttons (line 5), and uses the name of
- the button ("One", "Multiply", " Equals", ...) to find the calculator attribute
- (method) with the corresponding name (for example, "on_One", "on_Multiply",
- and "on_Equals", respectively). If such an attribute (method) is available,
- we hook the Click event event, using the name to fetch the attribute (line 7).</p>
- <ol start="10">
- <li>
- <p class="Step">The second point of interest is the on_Equals method, especially
- the highlighted line. Python has a built-in function, "eval", which evaluates
- an expression passed as a string and returns the resulting value. Calculator uses "eval"
- to evaluate the calculator expressions. The "str" function will then convert the value
- into a string for display.</p>
- </li>
- </ol>
- <p class="CodeSample">def on_Equals(self, b, e):<br />
- try:<br>
- result
- = str(eval(self.expression))<br>
- self.result.Text
- = result<br />
- self.expression = result<br />
- except:<br />
- self.result.Text = "<<ERROR>>"<br />
- self.expression = ""</p>
- <ol start="11">
- <li>
- <p class="Step">Exit the IronPython Interactive console (Ctrl+Z or F6 followed
- by Enter)</p>
- </li>
- </ol>
- <p class="LabSummary">Tutorial Summary</p>
- <p class="Body">IronPython provides a very easy way to develop live applications
- in a dynamic and exploratory way. Both Windows Forms and Windows Presentation
- Foundation (Avalon) applications can be easily developed this way with minimal
- setup. The advantage is that changes are visible immediately and modifications
- are happening to a live system and don't require recompilation.</p>
- <p class="Body">In this tutorial you performed the following exercises:</p>
- <ul>
- <li>
- <p class="ExerciseList"><a href="#T2.1">Events and Delegates</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T2.2">Windows Forms</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T2.3">Windows Presentation Foundation
- (Avalon)</a></p>
- </li>
- </ul>
- <p class="Body"> </p>
- <p class="Body">In this tutorial, you became familiar with using delegates and
- handling events in IronPython - an essential part of interactive development
- of Windows applications using WinForms or Avalon. Then you dynamically created
- simple interactive application in Windows Forms and created two applications
- using Windows Presentation Foundation. </p>
- <h1><a name="T3">Tutorial 3: IronPython and COM interoperability</a></h1>
- <p class="Body">COM interoperability is an important part of .NET Framework.
- To use COM objects from the .NET application, an interop assembly that contains
- the .NET metadata for the COM objects is required. This tutorial will outline
- how the interop assemblies can be created (in the case they are not provided
- by the creators of the COM object) and will demonstrate the ease with which
- COM objects can be used from IronPython.</p>
- <p class="Body">Estimated time to complete this tutorial: <b>20 minutes</b></p>
- <p class="Body">The objective of this tutorial is to explore COM interoperability
- from IronPython.</p>
- <ul>
- <li>
- <p class="ExerciseList"><a href="#T3.1">Merlin the Wizard</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T3.2">Word Spell Checking</a></p>
- </li>
- </ul>
- <h2><a name="T3.1">Exercise 1: Merlin the Wizard</a></h2>
- <p class="Body">This exercise consists of two tasks. In the first one we will
- create an interop assembly for a COM object library and explore it using the
- .NET reflection tools. In the second task we will use the COM object library
- from IronPython.</p>
- <p class="Body">In this exercise, you will create a COM interop assembly and
- use it to drive the COM object from IronPython.</p>
- <h3><a name="T3.1.1">Task 1: Creating COM interop assemblies</a></h3>
- <ol>
- <li>
- <p class="Step">Open the "SDK Command Prompt" or "Visual Studio 2005 Command
- Prompt" from the start menu. Note, if you installed IronPython under Program
- Files via the MSI installer, you'll need to run the command prompt as an
- administrator.</p>
- </li>
- <li>
- <p class="Step">The .NET Frameworks SDK comes with the "tlbimp" tool which converts
- a COM type library into .NET metadata information -- the interop assembly. The COM object library we want to use from IronPython
- is msagent, located
- in %SystemRoot%\msagent\agentsvr.exe. Use the tlbimp tool to generate the
- interop assembly for msagent (tlbimp writes to the current directory):</p>
- </li>
- </ol>
- <p class="DOSCommand">tlbimp %SystemRoot%\msagent\agentsvr.exe</p>
- <p class="Code-Highlighted">C:\IronPython\Tutorial>tlbimp %SystemRoot%\msagent\agentsvr.exe<br />
- Microsoft (R) .NET Framework Type Library to Assembly Converter 2.0.50727.42<br />
- Copyright (C) Microsoft Corporation. All rights reserved.<br />
- <br>
- Type library imported to AgentServerObjects.dll</p>
- <ol start="3">
- <li>
- <p class="Step">The .NET metadata information was saved in AgentServerObjects.dll. Use the ildasm tool to explore the generated DLL:</p>
- </li>
- </ol>
- <p class="DOSCommand">ildasm AgentServerObjects.dll</p>
- <ol start="4">
- <li>
- <p class="Step">As you browse the metadata tree, notice that at the root
- of the hierarchy there is the "AgentServerObjects" namespace. The namespace
- contains many interfaces and a single class - AgentServerClass. Explore
- the methods on the class. Calling some of its methods will be the subject
- of the next task.</p>
- </li>
- <li>
- <p class="Step">When you are done exploring the AgentServerObjects.dll,
- close the ildasm tool. Copy AgentServerObjects.dll to the tutorial
- directory, and then close the Windows command prompt.</p>
- </li>
- </ol>
- <h3><a name="T3.1.2">Task 2: Using COM objects from IronPython</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Using the "AddReferenceToFile" function in the
- clr module,
- add a reference to the AgentServerObjects.dll:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">clr.AddReferenceToFile("AgentServerObjects.dll")</p>
- <p class="Code-Background"></p>
- <ol start="3">
- <li>
- <p class="Step">Import the contents of the AgentServerObjects namespace
- and explore the contents using dir():</p>
- </li>
- </ol>
- <p class="TypedExample">from AgentServerObjects import *</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">dir()</p>
- <p class="HiddenOutput">['AgentServer', 'AgentServerClass', 'IAgent', 'IAgentAudioOutputProperties', 'IAgentAudioOutputPropertiesEx', 'IAgentBalloon', 'IAgentBalloonEx', 'IAgentCharacter', 'IAgentCharacterEx', 'IAgentCommand', 'IAgentCommandEx', 'IAgentCommandWindow', 'IAgentCommands', 'IAgentCommandsEx', 'IAgentEx', 'IAgentNotifySink', 'IAgentNotifySinkEx', 'IAgentPropertySheet', 'IAgentSpeechInputProperties', 'IAgentUserInput', '__builtins__', '__doc__', '__name__', 'clr']
- </p>
- <ol start="4">
- <li>
- <p class="Step">Create instance of the AgentServerClass and explore its
- contents:</p>
- </li>
- </ol>
- <p class="TypedExample">a = AgentServerClass()</p>
- <p class="TypedExample">dir(a)</p>
- <p class="Stepnonumbering">The output in the console window will be:</p>
- <p class="Code-Highlighted">>>> a = AgentServerClass()<br />
- >>> dir(a)</p>
- <p class="Code-Background">['CreateObjRef','Equals','GetCharacter','GetCharacterEx','GetHashCode','GetLifetimeService','GetSuspended','GetType','GetVersion','InitializeLifetimeService','Load','MemberwiseClone','ReferenceEquals','Register','ShowDefaultCharacterProperties','ToString','Unload','Unregister','__class__','__delattr__','__doc__','__getattribute__','__hash__','__init__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__str__']</p>
- <ol start="5">
- <li>
- <p class="Step">Load "Merlin the Wizard" character. (The character data
- is stored in c:\WINDOWS\msagent\chars). The Load method returns multiple
- values packed into a tuple - the
- first value is the actual character ID. Capture the character id in the variable:</p>
- </li>
- </ol>
- <p class="TypedExample">cid = clr.Reference[int]()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">reqid = clr.Reference[int]()</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a.Load("Merlin.acs", cid, reqid)</p>
- <p class="Code-Background"></p>
- <ol start="6">
- <li>
- <p class="Step">Call GetCharacter method on the AgentServerClass instance
- to get the actual character, display the character and have him think about
- IronPython Tutorial:</p>
- </li>
- </ol>
- <p class="TypedExample">from System.Runtime.InteropServices import DispatchWrapper, UnknownWrapper</p>
- <p class="TypedExample">c = clr.StrongBox[object](DispatchWrapper(None))</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">a.GetCharacter(cid.Value, c)</p>
- <p class="HiddenOutput"></p>
- <p class="Code-Background"></p>
- <p class="TypedExample">character = c.Value</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">character.Show(0, reqid)</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">character.Think("IronPython Tutorial", reqid)</p>
- <p class="HiddenOutput"></p>
- <ol start="7">
- <li>
- <p class="Step">Merlin has a lot of animations he can play. Get list of
- all the animations by calling the GetAnimationNames method. Play one of the animations,
- "Read", by calling the Play method:</p>
- </li>
- </ol>
- <p class="TypedExample">enum = clr.StrongBox[object](UnknownWrapper(None))</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">character.GetAnimationNames(enum)</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">animations = enum.Value</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">for n in animations: print n</p>
- <p class="HiddenOutput">RestPose<br>
- Blink<br>
- Idle2_2<br>
- Idle2_1<br>
- Idle1_1<br>
- Idle1_3<br>
- Idle1_2<br>
- Idle1_4<br>
- Greet<br>
- Idle3_1<br>
- GestureUp<br>
- GestureDown<br>
- GestureLeft<br>
- GestureRight<br>
- Show<br>
- Hide<br>
- Hearing_4<br>
- Hearing_1<br>
- Hearing_2<br>
- Hearing_3<br>
- Alert<br>
- Explain<br>
- Processing<br>
- Thinking<br>
- Searching<br>
- Acknowledge<br>
- Wave<br>
- DontRecognize<br>
- Uncertain<br>
- Decline<br>
- Sad<br>
- StopListening<br>
- GetAttention<br>
- GetAttentionReturn<br>
- Idle3_2<br>
- Surprised<br>
- Congratulate_2<br>
- Reading<br>
- Announce<br>
- Read<br>
- ReadReturn<br>
- Writing<br>
- Write<br>
- WriteReturn<br>
- Congratulate<br>
- Confused<br>
- Suggest<br>
- MoveRight<br>
- MoveLeft<br>
- MoveUp<br>
- MoveDown<br>
- StartListening<br>
- WriteContinued<br>
- DoMagic1<br>
- DoMagic2<br>
- LookDown<br>
- LookDownBlink<br>
- LookDownReturn<br>
- LookLeft<br>
- LookLeftBlink<br>
- LookLeftReturn<br>
- LookRight<br>
- LookRightBlink<br>
- LookRightReturn<br>
- LookUp<br>
- LookUpBlink<br>
- LookUpReturn<br>
- ReadContinued<br>
- Pleased<br>
- GetAttentionContinued<br>
- Process<br>
- Search<br>
- Think<br></p>
- <p class="TypedExample">character.Play("Read", reqid)</p>
- <p class="HiddenOutput"></p>
- <ol start="8">
- <li>
- <p class="Step">(Optional) To call a series of animations, we could call character.Play(animation_name, reqid)
- for each animation. Python's lamda functions can simplify this process. We can create global functions and assign them names based on the animation
- name:</p>
- </li>
- </ol>
- <p class="TypedExample">character.GetAnimationNames(enum)</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">animations = enum.Value</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">for n in animations: globals()[n] = lambda name=n: character.Play(name, reqid)</p>
- <p class="HiddenOutput"></p>
- <p class="Stepnonumbering">At this point we can have Merlin play animations
- simply by calling a function from global namespace:</p>
- <p class="TypedExample">Congratulate()</p>
- <p class="HiddenOutput"></p>
- <p class="Code-Background"></p>
- <ol start="9">
- <li>
- <p class="Step">Stop Merlin's animations, hide him, and exit IronPython console</p>
- </li>
- </ol>
- <p class="TypedExample">character.StopAll(0)</p>
- <p class="HiddenOutput"></p>
- <p class="TypedExample">character.Hide(0, reqid)</p>
- <p class="HiddenOutput"></p>
- <h2><a name="T3.2">Exercise 2: Use Word for Spell Checking</a></h2>
- <p class="Body">In this exercise you will create an instance of Microsoft
- Word and use it to check word spellings.</p>
- <h3><a name="T3.2.1">Task 1: Accessing Word and Checking Spelling</a></h3>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Import clr module and add a reference to the Word COM
- interop assembly.</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">clr.AddReferenceByPartialName("Microsoft.Office.Interop.Word")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">from Microsoft.Office.Interop.Word import ApplicationClass</p>
- <p class="Code-Background"></p>
- </p>
- <ol start="3">
- <li>
- <p class="Step">Start an instance of Word as a COM server running.
- You won't see it show up since it is hidden, but you can see it in the
- Windows Task Manager by typing ctrl-shift-escape and looking for the
- WINWORD.EXE process.</p></li>
- </ol>
- <p class="TypedExample">w = ApplicationClass()</p>
- <p class="Code-Background"></p>
- <ol start="4">
- <li>
- <p class="Step">Define the following function to check the spelling.
- Remember to indent the lines of the function's body extra spaces, and you
- have to hit an extra return or enter to complete the function's definition.</p></li>
- </ol>
- <p class="TypedExample">def check_word (word):<br>
- return w.CheckSpelling(word)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">check_word("foo")</p>
- <p class="HiddenOutput">False</p>
- <p class="TypedExample">check_word("food")</p>
- <p class="HiddenOutput">True</p>
- <ol start="5">
- <li>
- <p class="Step">You can try that out on a couple of words, but now lets
- define a function that will suggest corrections for us. First, we
- need to add a document so that we can call GetSpellingSuggestions(),
- which gives a nice error message if you try to call it with no documents
- opened.</p></li>
- </ol>
- <p class="TypedExample">w.Documents.Add()</p>
- <p class="LooseVerify">Microsoft.Office.Interop.Word.DocumentClass</p>
- <ol start="6">
- <li>
- <p class="Step">The first result of
- several return values from GetSpellingSuggestions() is a collection of
- items, each of which is a correction suggestion. We use a Python
- list comprehension to iterate through the COM collection object and call
- the Name property on each item object in the collection. Each
- item's Name property is a string that Word is suggesting as a correct
- spelling.</p></li>
- </ol>
- <p class="TypedExample">def suggestions(word):<br>
- res_objects = w.GetSpellingSuggestions(word)<br>
- return [x.Name for x in res_objects]</p>
- <p class="Code-Background"></p>
- <ol start="7">
- <li>
- <p class="Step">Now, let's shut down Word and exit the IronPython
- console. When you enter the next line and hit return, if you are
- watching the Windows Task Manager, you will see the WINWORD.EXE process
- go away.</p></li>
- </ol>
- <p class="TypedExample">w.Quit()</p>
- <p class="Code-Background"></p>
- <h3><a name="T3.2.2">Task 2: Use Windows Form Dialog to Correct Spelling</a></h3>
- <p class="Body">In this task you will use an example already written that is
- very similar to what you did in Task 1, but it demonstrates two additional
- features. It uses a Python standard module to register a clean up
- function so that when the IronPython console terminates, the Word process is
- closed. The example also has a function, correct_word, that uses a
- Windows Form as a dialog to let users select a correct word to return.</p>
- <ol>
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- <li>
- <p class="Step">Import spellcheck.</p>
- </li>
- <li>
- <p class="Step">Call spellcheck.correct_word on a correctly spelled
- word, and you'll see the function returns the word.</p>
- </li>
- <li>
- <p class="Step">Call spellcheck.correct_word on a misspelled word, and a
- Windows Form similar to Word's spelling correction dialog appears.
- You can pick from the list and click the Replace button, double click a
- word in the suggestions list, enter custom text and click the Use Custom
- button, click an Ignore button to return the misspelled word, and so on. </p>
- </li>
- <li>
- <p class="Step">Open the spellcheck.py file to see the code for the the
- Windows Form as well as the functions.</li>
- </ol>
- <p class="Body"> </p>
- <p class="LabSummary">Tutorial Summary</p>
- <p class="Body">This tutorial was focused on using COM interop assemblies generated
- via tlbimp tool (in the .NET Framework SDK) to control COM objects from the IronPython environment.</p>
- <p class="Body">In this tutorial you performed the following exercises.</p>
- <ul>
- <li>
- <p class="ExerciseList"><a href="#T3.1">Merlin the Wizard</a></p>
- </li>
- <li>
- <p class="ExerciseList"><a href="#T3.2">Word Spell Checking</a></p>
- </li>
- </ul>
- <p class="Body"> </p>
- <p class="Body">In this tutorial, you created a COM interop assembly for the
- msagent COM object. You used the tlbimp tool which is part of the .NET Framework
- SDK. Using the ildasm tool, you explored contents of the interop assembly.</p>
- <p class="Body">Then, from IronPython you loaded the interop assembly, created
- an instance of the COM object, and instructed Merlin to play different animations.</p>
- <p class="Body">You also used Word to check the spelling of words, learned
- how to supply missing optional arguments, and inspected code that builds a
- Windows Form and uses it as a dialog.</p>
- <p class="Normal"> </p>
- <h1><a name="T4">Tutorial 4: Debugging IronPython program</a></h1>
- <p class="Body">This tutorial will walk you through very simple debug session,
- debugging a Python script using Microsoft CLR Debugger. See
- <a href="#T7">using Visual Studio</a> if you have a Visual Studio SKU and
- consider skipping this exercise.</p>
- <p class="Body">Estimated time to complete this tutorial: <b>10 minutes</b></p>
- <p class="Body">The objective of this tutorial is debugging simple Python script
- using Microsoft CLR Debugger.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T4.1">Debugging IronPython program</a></p>
- </li>
- </ul>
- <h2><a name="T4.1">Exercise 1: Debugging IronPython program</a></h2>
- <p class="Body">In this exercise, you will step through a simple Python script
- in the Microsoft CLR Debugger.</p>
- <h3><a name="T4.1.1">Task 1: Debugging IronPython program using Microsoft CLR
- Debugger</a></h3>
- <ol>
- <li>
- <p class="Step">Launch Microsoft CLR Debugger. </p>
- </li>
- <li>
- <p class="Step">From the debugger Menu, select Debug / Program to Debug
- ...</p>
- </li>
- <li>
- <p class="Step">For Program, browse to the ipy.exe (located
- in the installaton directory)</p>
- </li>
- <li>
- <p class="Step">For Arguments, type in debugging.py</p>
- </li>
- <li>
- <p class="Step">Change Working directory to the Tutorial directory</p>
- </li>
- <li>
- <p class="Step">Click OK</p>
- </li>
- <li>
- <p class="Step">From Menu, select File / Open / File. Browse to the Tutorial
- directory and select two files to open:</p>
- </li>
- </ol>
- <p class="Body">debugging.py</p>
- <p class="Body">first.py</p>
- <ol start="8">
- <li>
- <p class="Step">Place breakpoint at the following line of the debugging.py
- file (Place cursor on the line and pres F9):</p>
- </li>
- </ol>
- <p class="Body">print first.add(1, 2)</p>
- <ol start="9">
- <li>
- <p class="Step">Press F5 - Start Debugging.</p>
- </li>
- </ol>
- <p class="Stepnonumbering">IronPython will compile the debugging.py file and
- start executing it. You will hit the breakpoint at the line 3.</p>
- <p class="StepNote">Note: If you get poor performance starting the debugging
- session, exit the debugger, open the Windows Explorer and delete the following
- directory:</p>
- <p class="StepNote">%USERPROFILE%\Application Data\Microsoft\DbgClr</p>
- <ol start="10">
- <li>
- <p class="Step">Pressing F11, step through the execution of the program,
- explore variables (even change the values of the variables in the watch
- window) and explore the call stack. </p>
- </li>
- <li>
- <p class="Step">End the debugging session and exit the debugger.</p>
- </li>
- </ol>
- <p class="LabSummary">Tutorial Summary</p>
- <p class="Body">In this tutorial you performed the following exercises.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T4.1">Debugging IronPython program</a></p>
- </li>
- </ul>
- <p class="Body">In this tutorial, you walked through the simple debug session
- of IronPython program. You used Microsoft CLR Debugger, placed breakpoints and
- stepped through the Python program execution.</p>
- <p class="Body"> </p>
- <h1><a name="T5">Tutorial 5: Extending IronPython</a></h1>
- <p class="Body">Estimated time to complete this tutorial: <b>25- 60 minutes</b></p>
- <p class="Body">The objective of this tutorial is to implement the class which
- will seamlessly fit into the IronPython environment. You can choose to follow
- Exercise 1 - C# implementation, Exercise 2 - Visual Basic, or both. Both tracks
- will result in the same functionality.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T5.1">Extending using C#</a></p>
- </li>
- <li>
- <p class="Body"><a href="#T5.2">Extending using Visual Basic.NET</a></p>
- </li>
- </ul>
- <h2><a name="T5.1">Exercise 1: Extending using C#</a></h2>
- <p class="Body">In this exercise you will use C# language to build a class that
- supports enumeration, custom operators and delegates and you will use that class
- from IronPython. Its worth noting that as Python does not contain protected class members,
- these members get promoted to public class members when imported into Python. Private
- class members, however, will be invisible to Python when imported.</p>
- <h3><a name="T5.1.1">Task 1: Implementing simple class - constructor and ToString</a></h3>
- <ol>
- <li>
- <p class="Step">Open the "SDK Command Prompt" or "Visual Studio 2005 Command
- Prompt" from the start menu.</p>
- </li>
- <li>
- <p class="Step">Open the "csextend.cs" file in notepad. The file is initially
- empty</p>
- </li>
- </ol>
- <p class="DOSExample">notepad csextend.cs</p>
- <ol start="3">
- <li>
- <p class="Step">Add using clauses at the beginning of the file:</p>
- </li>
- </ol>
- <p class="CodeSample">using System;<br />
- using System.Collections;</p>
- <ol start="4">
- <li>
- <p class="Step">Define a simple class:</p>
- </li>
- </ol>
- <p class="CodeSample">public class Simple {<br />
- private int data;<br>
- <br />
- public Simple(int data) {<br />
- this.data = data;<br />
- }<br>
- <br />
- public override string ToString() {<br />
- return String.Format("Simple<{0}>", data);<br />
- }<br />
- }</p>
- <ol start="5">
- <li>
- <p class="Step">Switch back to the SDK Command Prompt window and build the
- code using available csx.bat (C# extension):</p>
- </li>
- </ol>
- <p class="DOSExample">csx</p>
- <ol start="6">
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- </ol>
- <ol start="7">
- <li>
- <p class="Step">Load the dll that you just built (csextend.dll) into IronPython.
- Then explore the Simple class using built-in dir() function:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("csextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("csextend_5.1.1.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(Simple)</p>
- <p class="HiddenCode">set1 = set(dir(Simple))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- []</p>
- <p class="Stepnonumbering">You will see following output:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("csextend.dll")<br />
- >>> import Simple<br />
- >>> dir(Simple)</p>
- <p class="Code-Highlighted">['Equals', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
- <ol start="8">
- <li>
- <p class="Step">Create instance of the Simple class:</p>
- </li>
- </ol>
- <p class="TypedExample">s = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">print s</p>
- <p class="Stepnonumbering">IronPython will output:</p>
- <p class="Code-Highlighted">>>> s = Simple(10)<br />
- >>> print s</p>
- <p class="Code-Background">Simple<10></p>
- <ol start="9">
- <li>
- <p class="Step">You have just explored all the functionality currently available
- in the Simple class. Exit IronPython and return back to the C# code to add
- more functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.1.2">Task 2: Making the object enumerable</a></h3>
- <ol>
- <li>
- <p class="Step">In Notepad, add more functionality to the Simple class.</p>
- </li>
- <li>
- <p class="Step">First, inherit the Simple class from IEnumerable and implement
- GetEnumerator() method. Use the C#'s new "yield return" statement:</p>
- </li>
- </ol>
- <p class="CodeSample">public class Simple : IEnumerable {<br>
- <br />
- private int data;<br />
- public Simple(int data) {<br />
- this.data = data;<br />
- }<br />
- public override string ToString() {<br />
- return String.Format("Simple<{0}>", data);<br />
- }<br />
- <br>
- public IEnumerator GetEnumerator()
- {<br />
- for (int i = 0; i < data; i ++) {<br />
- yield return
- new Simple(i);<br />
- }<br />
- }</p>
- <p class="CodeSample">}</p>
- <ol start="3">
- <li>
- <p class="Step">Save the changes, compile the code (csx), launch IronPython
- Console (ip) and test the code:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("csextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("csextend_5.1.2.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(Simple)</p>
- <p class="HiddenCode">set1 = set(dir(Simple))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['GetEnumerator', '__iter__']</p>
- <p class="Code-Highlighted">['Equals', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
- <p class="TypedExample">s = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">for i in s: print i</p>
- <p class="Stepnonumbering">You will get the following output in the IronPython
- console window:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("csextend.dll")<br />
- >>> import Simple<br />
- >>> dir(Simple)<br />
- >>> s = Simple(10)</p>
- <p class="Code-Highlighted">>>> for i in s: print i</p>
- <p class="Code-Background">Simple<0><br />
- Simple<1><br />
- Simple<2><br />
- Simple<3><br />
- Simple<4><br />
- Simple<5><br />
- Simple<6><br />
- Simple<7><br />
- Simple<8><br />
- Simple<9></p>
- <p class="StepNote">Notice that the dir() function now returned the GetEnumerator
- method.</p>
- <ol start="4">
- <li>
- <p class="Step">Exit IronPython and return back to the C# code to add more
- functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.1.3">Task 3: Adding custom operator</a></h3>
- <ol>
- <li>
- <p class="Step">Add the operator + method:</p>
- </li>
- </ol>
- <p class="CodeSample">using System;<br />
- using System.Collections;</br>
- <br />
- public class Simple : IEnumerable {<br />
- private int data;<br />
- public Simple(int data) {<br />
- this.data = data;<br />
- }<br />
- public override string ToString() {<br />
- return String.Format("Simple<{0}>", data);<br />
- }<br />
- public IEnumerator GetEnumerator() {<br />
- for (int i = 0; i < data; i ++) {<br />
- yield return
- new Simple(i);<br />
- }<br />
- }<br />
- </br>
- public static Simple operator
- +(Simple a, Simple b) {<br />
- return new Simple(a.data + b.data);<br />
- }</br>
- }</p>
- <ol start="2">
- <li>
- <p class="Step">Return to the command prompt, compile the code (csx), launch
- IronPython Console (ip) and test the code:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("csextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("csextend_5.1.3.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(Simple)</p>
- <p class="HiddenCode">set1 = set(dir(Simple))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['GetEnumerator', '__iter__', '__radd__', '__add__']</p>
- <p class="TypedExample">a = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">b = Simple(20)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a + b</p>
- <p class="LooseVerify">Simple<30</p>
- <p class="Stepnonumbering">Notice that in the output of dir() call you will
- now get additional methods __add__ and __radd__, Python's notion of custom operator
- implementation:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("csextend.dll")<br />
- >>> import Simple<br />
- >>> dir(Simple)<br />
- >>> a = Simple(10)<br />
- >>> b = Simple(20)</p>
- <p class="Code-Highlighted">>>> a + b<br />
- <Simple object at 0x000000000000002B [Simple<30]</p>
- <ol start="3">
- <li>
- <p class="Step">Exit IronPython and return back to the C# code to add more
- functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.1.4">Task 4: Adding delegate</a></h3>
- <ol>
- <li>
- <p class="Step">Add the definition of the delegate to the top of the C#
- source file:</p>
- </li>
- </ol>
- <p class="CodeSample">using System;<br />
- using System.Collections;<br />
- <br>
- public delegate int Transformer(int input);</p>
- <ol start="2">
- <li>
- <p class="Step">Add "Transform" method to the Simple class that takes the
- delegate as a parameter and invokes the delegate:</p>
- </li>
- </ol>
- <p class="CodeSample">using System;<br />
- using System.Collections;<br />
- <br>
- public delegate int Transformer(int input);<br>
- <br />
- public class Simple : IEnumerable {<br />
- private int data;<br />
- public Simple(int data) {<br />
- this.data = data;<br />
- }<br>
- <br />
- public override string ToString() {<br />
- return String.Format("Simple<{0}>", data);<br />
- }<br>
- <br />
- public IEnumerator GetEnumerator() {<br />
- for (int i = 0; i < data; i ++) {<br />
- yield return
- new Simple(i);<br />
- }<br />
- }<br />
- <br>
- public int Transform(Transformer
- t) {<br />
- return t(data);<br />
- }<br>
- <br />
- public static Simple operator +(Simple a, Simple b) {<br />
- return new Simple(a.data + b.data);<br />
- }<br />
- }</p>
- <ol start="3">
- <li>
- <p class="Step">Return back to the SDK command prompt, compile the code
- (csx), launch IronPython Console (ip) and test the code:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("csextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("csextend_5.1.4.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">def X(i):<br>
- return i + 100</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a.Transform(X)</p>
- <p class="Stepnonumbering">The function X is getting passed as the delegate
- to the Simple's Transform method. You will get following output:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("csextend.dll")<br />
- >>> import Simple<br />
- >>> a = Simple(10)</p>
- <p class="Code-Highlighted">>>> def X(i):<br />
- ... return i + 100<br />
- ...<br />
- >>> a.Transform(X)</p>
- <p class="Code-Background">110</p>
- <ol start="4">
- <li>
- <p class="Step">This concludes the C# extending example. If you are interested,
- an interesting exercise is combining the debugging example and the extending
- one. If you are inspired to do so, try debugging the script that you just
- typed in. Debug the "debugcsx.py" script located in Tutorial directory and
- place a breakpoint on the X function - you will see mixed call stack between
- C# and Python.</p>
- </li>
- </ol>
- <h2><a name="T5.2">Exercise 2: Extending using Visual Basic.NET</a></h2>
- <p class="Body">In this exercise you will use Visual Basic .NET language to
- build a class that supports enumeration, custom operators and delegates and
- you will use that class from IronPython. Its worth noting that as Python does not contain protected
- class members, that these members get promoted to public class members when imported into Python.
- Private class members, however, will be invisible to Python when imported.</p>
- <h3><a name="T5.2.1">Task 1: Implementing simple class - constructor and ToString</a></h3>
- <ol>
- <li>
- <p class="Step">Open the "SDK Command Prompt" or "Visual Studio 2005 Command
- Prompt" from the start menu.</p>
- </li>
- <li>
- <p class="Step">Open the "vbextend.vb" file in notepad. The file is initially
- empty</p>
- </li>
- </ol>
- <p class="DOSExample">notepad vbextend.vb</p>
- <ol start="3">
- <li>
- <p class="Step">Add Imports clauses at the beginning of the file:</p>
- </li>
- </ol>
- <p class="CodeSample">Imports System<br />
- Imports System.Collections</p>
- <ol start="4">
- <li>
- <p class="Step">Define a simple class:</p>
- </li>
- </ol>
- <p class="CodeSample">Public Class Simple<br />
- Private data As Integer<br />
- <br />
- Public Sub New(ByVal data As Integer)<br />
- Me.data = data<br />
- End Sub<br />
- <br />
- Overrides Function ToString() As String<br />
- Return String.Format("Simple<{0}>", data)<br />
- End Function<br />
- </p>
- <p class="CodeSample">End Class</p>
- <ol start="5">
- <li>
- <p class="Step">Switch back to the SDK Command Prompt window and build the
- code using the available vbx.bat (Visual Basic extension):</p>
- </li>
- </ol>
- <p class="DOSExample">vbx</p>
- <ol start="6">
- <li>
- <p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p>
- </li>
- </ol>
- <ol start="7">
- <li>
- <p class="Step">Load the dll that you just built (vbextend.dll) into IronPython.
- Then explore the Simple class using built-in dir() function:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("vbextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("vbextend_5.2.1.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(Simple)</p>
- <p class="HiddenCode">set1 = set(dir(Simple))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- []</p>
- <p class="Stepnonumbering">You will see following output:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("vbextend.dll")<br />
- >>> import Simple<br />
- >>> dir(Simple)</p>
- <p class="Code-Highlighted">['Equals', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__']</p>
- <ol start="8">
- <li>
- <p class="Step">Create instance of the Simple class:</p>
- </li>
- </ol>
- <p class="TypedExample">s = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">print s</p>
- <p class="Stepnonumbering">IronPython will output:</p>
- <p class="Code-Highlighted">>>> s = Simple(10)<br />
- >>> print s</p>
- <p class="Code-Background">Simple<10></p>
- <ol start="9">
- <li>
- <p class="Step">You just have explored all the functionality available in
- the Simple class. Exit IronPython and return back to the Visual Basic code
- to add more functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.2.2">Task 2: Making the object enumerable</a></h3>
- <ol>
- <li>
- <p class="Step">Back in Notepad, add more functionality to the vbextend.vb,
- Simple class</p>
- </li>
- <li>
- <p class="Step">First, inherit the Simple class from IEnumerable and implement
- GetEnumerator() method. Unlike C#, Visual Basic does not offer the yield
- keyword so implementing IEnumerable interface requires adding a helper class
- SimpleEnum:</p>
- </li>
- </ol>
- <p class="CodeSample">Imports System<br />
- Imports System.Collections<br />
- </p>
- <p class="CodeSample">Public Class SimpleEnum<br />
- Implements IEnumerator<br />
- <br />
- Private data As Integer<br />
- Private curr As Integer<br />
- <br />
- Public Sub New(ByVal data As Integer)<br />
- Me.data = data<br />
- Me.curr = -1<br />
- End Sub<br />
- <br />
- Public ReadOnly Property Current() As Object _<br />
- Implements IEnumerator.Current<br />
- Get<br />
- Return New Simple(curr)<br />
- End Get<br />
- End Property<br />
- <br />
- Public Function MoveNext() As Boolean _<br />
-
- Implements IEnumerator.MoveNext<br />
- curr += 1<br />
- Return curr < data<br />
- End Function<br />
- <br />
- Public Sub Reset() Implements IEnumerator.Reset<br />
- curr = -1<br />
- End Sub<br />
- End Class</p>
- <p class="CodeSample"><br />
- Public Class Simple</p>
- <p class="CodeSample"> Implements IEnumerable</p>
- <p class="CodeSample"> Private data As Integer<br />
- <br />
- Public Sub New(ByVal data As Integer)<br />
- Me.data = data<br />
- End Sub<br />
- <br />
- Overrides Function ToString() As String<br />
- Return String.Format("Simple<{0}>", data)<br />
- End Function<br />
- </p>
- <p class="CodeSample"> Function GetEnumerator() As IEnumerator
- _<br />
-
- Implements IEnumerable.GetEnumerator<br />
- Return New SimpleEnum(data)<br />
- End Function</p>
- <p class="CodeSample"><br />
- End Class</p>
- <ol start="3">
- <li>
- <p class="Step">Compile the code (vbx), launch IronPython Console (ip) and
- test the code:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("vbextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("vbextend_5.2.2.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(Simple)</p>
- <p class="HiddenCode">set1 = set(dir(Simple))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['GetEnumerator', '__iter__']</p>
- <p class="TypedExample">s = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">for i in s: print i</p>
- <p class="Stepnonumbering">You will get the following output in the IronPython
- console window:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("vbextend.dll")<br />
- >>> import Simple<br />
- >>> dir(Simple)<br />
- >>> s = Simple(10)</p>
- <p class="Code-Highlighted">>>> for i in s: print i</p>
- <p class="Code-Background">Simple<0><br />
- Simple<1><br />
- Simple<2><br />
- Simple<3><br />
- Simple<4><br />
- Simple<5><br />
- Simple<6><br />
- Simple<7><br />
- Simple<8><br />
- Simple<9></p>
- <p class="Normal"> </p>
- <p class="StepNote">Notice that the dir() function now returned the GetEnumerator
- method.</p>
- <ol start="4">
- <li>
- <p class="Step">Exit IronPython and return back to the Visual Basic code
- to add more functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.2.3">Task 3: Adding custom operator</a></h3>
- <ol>
- <li>
- <p class="Step">Add the operator + method to the Simple class:</p>
- </li>
- </ol>
- <p class="CodeSample">Public Class Simple<br />
- Implements IEnumerable<br />
- Private data As Integer<br />
- <br />
- Public Sub New(ByVal data As Integer)<br />
- Me.data = data<br />
- End Sub<br />
- <br />
- Overrides Function ToString() As String<br />
- Return String.Format("Simple<{0}>", data)<br />
- End Function<br />
- <br />
- Function GetEnumerator() As IEnumerator _<br />
-
- Implements IEnumerable.GetEnumerator<br />
- Return New SimpleEnum(data)<br />
- End Function<br />
- </p>
- <p class="CodeSample"> Shared Operator +(ByVal a As
- Simple, ByVal b As Simple) As Simple<br />
- Return New Simple(a.data + b.data)<br />
- End Operator</p>
- <p class="CodeSample"><br />
- End Class</p>
- <ol start="2">
- <li>
- <p class="Step">Compile the code (vbx), launch IronPython Console (ip) and
- test the code:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("vbextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("vbextend_5.2.3.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="UserCode">dir(Simple)</p>
- <p class="HiddenCode">set1 = set(dir(Simple))
- set2 = set(dir(object))
- list(set1-set2)</p>
- <p class="HiddenOutput">
-
- ['GetEnumerator', '__iter__', '__radd__', '__add__']</p>
- <p class="TypedExample">a = Simple(10)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">b = Simple(20)</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a + b</p>
- <p class="LooseVerify">Simple<30</p>
- <p class="Stepnonumbering">Notice that in the output of dir() call you will
- now get additional methods __add__ and __radd__, Python's notion of custom operator
- implementation:</p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("vbextend.dll")<br />
- >>> import Simple<br />
- >>> dir(Simple)<br />
- >>> a = Simple(10)<br />
- >>> b = Simple(20)</p>
- <p class="Code-Highlighted">>>> a + b<br>
- <Simple object at 0x000000000000002B [Simple<30]</p>
- <ol start="3">
- <li>
- <p class="Step">Exit IronPython and return back to the Visual Basic .NET
- code to add more functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.2.4">Task 4: Adding delegate</a></h3>
- <ol>
- <li>
- <p class="Step">Add the definition of the delegate to the top of the Visual
- Basic source file:</p>
- </li>
- </ol>
- <p class="CodeSample">Imports System<br />
- Imports System.Collections<br />
- </p>
- <p class="CodeSample">Public Delegate Function Transformer(ByVal input
- As Integer) As Integer</p>
- <ol start="2">
- <li>
- <p class="Step">Add "Transform" method to the Simple class that takes the
- delegate as a parameter and invokes the delegate:</p>
- </li>
- </ol>
- <p class="CodeSample">Public Class Simple<br />
- Implements IEnumerable<br />
- Private data As Integer<br />
- <br />
- Public Sub New(ByVal data As Integer)<br />
- Me.data = data<br />
- End Sub<br />
- <br />
- Overrides Function ToString() As String<br />
- Return String.Format("Simple<{0}>", data)<br />
- End Function<br />
- <br />
- Function GetEnumerator() As IEnumerator _<br />
-
- Implements IEnumerable.GetEnumerator<br />
- Return New SimpleEnum(data)<br />
- End Function<br />
- </p>
- <p class="CodeSample"> Function Transform(ByVal t As
- Transformer) As Integer<br />
- Return t(data)<br />
- End Function</p>
- <p class="CodeSample"><br />
- Shared Operator +(ByVal a As Simple, ByVal b As Simple) As Simple<br />
- Return New Simple(a.data + b.data)<br />
- End Operator<br />
- <br />
- End Class</p>
- <ol start="3">
- <li>
- <p class="Step">Return back to the SDK command prompt, compile the code
- (vbx), launch IronPython Console (ip) and test the code:</p>
- </li>
- </ol>
- <p class="TypedExample">import clr</p>
- <p class="Code-Background"></p>
- <p class="UserCode">clr.AddReferenceToFile("vbextend.dll")</p>
- <p class="HiddenCode">clr.AddReferenceToFile("vbextend_5.2.4.dll")</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">import Simple</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">a = Simple(10)</p>
- <p class="TypedExample">def X(i):<br>
- return i + 100</p>
- <p class="Code-Background"></p>
- <p class="TypedExample"> </p>
- <p class="TypedExample">a.Transform(X)</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">The function X is getting passed as the delegate
- to the Simple's Transform method. You will get following output:</p>
- <p class="Code-Highlighted"> </p>
- <p class="Code-Highlighted">>>> import clr<br />
- >>> clr.AddReferenceToFile("vbextend.dll")<br />
- >>> import Simple<br />
- >>> a = Simple(10)<br />
- >>> def X(i):</p>
- <p class="Code-Highlighted">... return i + 100<br />
- ...<br />
- >>> a.Transform(X)</p>
- <p class="Code-Background">110</p>
- <p class="Normal"></p>
- <ol start="4">
- <li>
- <p class="Step">This concludes the Visual Basic extending example. If you
- are interested, an interesting exercise is combining the debugging example
- and the extending one. If you are inspired to do so, try debugging the script
- that you just typed in. Debug the "debugvbx.py" script located in the Tutorial
- directory. Place a breakpoint on the X function - you will see mixed call
- stack between Visual Basic and Python.</p>
- </li>
- </ol>
- <p class="LabSummary">Tutorial Summary</p>
- <p class="Body">The complete version of the csextend.cs and vbextend.vb files
- are located in the Tutorial\Extend directory along with files csxtest.py and
- vbxtest.py which contain the test code for the C# and Visual Basic .NET extensions
- respectively.</p>
- <p class="Body">The code to experiment with debugging of Python and C# or Visual
- Basic code, use Python scripts debugcsx.py and debugvbx.py respectively.</p>
- <p class="Body">In this tutorial you performed the following exercises.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T5.1">Extending IronPython using C# code</a></p>
- </li>
- <li>
- <p class="Body"><a href="#T5.2">Extending IronPython using Visual Basic
- .NET</a></p>
- </li>
- </ul>
- <p class="Body">In this tutorial, you implemented a simple class to be used
- from IronPython. You added the ability for IronPython to enumerate the class,
- added an operator to it and support for delegate. The implementation was in
- either C# or Visual Basic, or both.</p>
- <h1><a name="T7">Tutorial 6: Using Visual Studio to Edit .py Files and Debug
- Them</a></h1>
- <p class="Body">There's very basic support for editing .py files in Visual
- Studio (no coloring or expression completion), but you get .NET debugging support. This tutorial shows
- you how to quickly set up Visual Studio to work on Python scripts in a
- directory.</p>
- <p class="Body">Estimated time to complete this tutorial: <b>5 minutes</b></p>
- <p class="Body">The objective of this tutorial is to set up Visual Studio
- for some basic tool support for debugging.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T6.1">Setting up Visual Studio for IronPython
- Debugging</a></p>
- </li>
- </ul>
- <h2><a name="T6.1">Exercise 1: Setting up Visual Studio for IronPython
- Debugging</a></h2>
- <p class="Body">In this exercise you will set up a Visual Studio solution
- that you can use to edit .py files in a directory and debug them using the
- Visual Studio .NET debugger. We will use the Tutorial directory as an
- example, but you could save your solution anywhere.</p>
- <h3><a name="T6.1.1">Task 1: Setting up Visual Studio for IronPython
- Debugging</a></h3>
- <ol>
- <li>
- <p class="Step">Open Visual Studio and close any solution or projects
- you might have open.</p>
- </li>
- <li>
- <p class="Step">Use the File->Open->Project/Solution ... command and
- browse to the ipy.exe application in your IronPython installation
- (c:\IronPython\ipy.exe is where the tutorial assumes you have it).</p>
- </li>
- <li>
- <p class="Step">We will use the Tutorial directory as an example, and
- we'll want to set it up as the working directory for loading .py
- scripts. Right click on the ipy.exe project node in the Visual
- Studio's solution
- explorer and choose the Properties command.</p>
- </li>
- <li>
- <p class="Step">In the properties dialog, you will fill in two
- fields, the Command Arguments and Working Directory. For the
- Command Arguments, enter "-D first.py". The -D argument enables
- application debugging. For the Working Directory,
- enter the path to the Tutorial directory (c:\IronPython\Tutorial\ is
- where we assume you have it). Click Apply and OK to confirm your
- changes.</p>
- </li>
- <li>
- <p class="Step">Now let's save the solution with the File->Save All ...
- command. Save it to the Tutorial directory.</p>
- </li>
- <li>
- <p class="Step">To test out our set up, use Ctrl+O to open a file.
- Browse to the "first.py" file in the Tutorial directory. Place the
- caret on the line that reads "def add(a, b):", and press F9 to set a
- breakpoint.</p>
- </li>
- <li>
- <p class="Step">Press F5 to run the script, and you will hit the
- breakpoint. If you Press F10, you will step through the file, but
- all it does is load the definitions and set some variables before
- terminating.</p>
- </li>
- <li>
- <p class="Step">To see more stepping, we'll add a line to the file and
- set another breakpoint. Add a line to the end of the file to
- invoke the factorial function ("factorial(5)"). Add a breakpoint to the line that reads
- "if n < 1: return 1". Now Press F5 to run the script.
- Press F10 repeatedly and notice the locals window where
- the parameter "n" decrements to 0 and then goes back up to 5 as the
- recursion unwinds. You can also hover the mouse over the "n"
- in the editor window to get a data tip of its value each time you stop at the
- breakpoint.</p>
- </li>
- </ol>
- <p class="Body">To work on other scripts, just change the Command Arguments
- property for the ipy.exe project as we did above to name another script you want
- to load on F5. You might also find it useful to go to the
- Tools->Options... dialog and change a property on the Environment->Documents
- page to show the open script files. If you check the property "Show Miscellaneous Files in the Solution
- Explorer", then you will get a list of the .py files you are editing. Each
- time you open this solution again at a later time, you will see all the .py
- files you developed while using this solution file.</p>
- <p class="LabSummary">Tutorial Summary</p>
- <p class="Body">In this tutorial you performed the following exercises.</p>
- <ul>
- <li>
- <p class="Body"><a href="#T6.1">Setting up Visual Studio for IronPython
- Debugging</a></p>
- </li>
- </ul>
- <p class="Normal">In this tutorial you set up Visual Studio to work on
- Python scripts in a directory and debug them.</p>
-
- </body>
-
- </html>