/Languages/IronPython/Public/Tutorial/Tutorial.htm
HTML | 2821 lines | 2795 code | 26 blank | 0 comment | 0 complexity | f3649312a6d6a8ae14c1d3d28296cd5b MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
- <html>
- <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.NoVerify-Background { color : gray; }
- p.Code-Highlighted { color : gray; }
- p.NoVerify-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.UserExample { 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 additional .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 the 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">Use Word for Spell Checking</a></p>
- <p class="Toc3">Task 1: <a href="#T3.1.1">Accessing Word and Checking
- Spelling</a></p>
- <p class="Toc3">Task 2: <a href="#T3.1.2">Use Windows Form Dialog to Correct
- Spelling</a></p>
- <p class="Toc1">Tutorial 4: <a href="#T4">Debugging IronPython programs</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 a 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 a custom operator</a></p>
- <p class="Toc3">Task 4: <a href="#T5.1.4">Adding a 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 a 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 a custom operator</a></p>
- <p class="Toc3">Task 4: <a href="#T5.2.4">Adding a 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 imperative, object-oriented, and functional programming, and also allows
- you to seamlessly use existing .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 <a href="http://www.microsoft.com/com/default.mspx">COM</a>
- and extending IronPython with C# and/or Visual Basic. While we do explain some
- finer points of Python's syntax, 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
- <a href="http://oreilly.com/catalog/9780596513986/"><i>Learning Python</i></a>
- by Mark Lutz and David Ascher. In addition,
- <a href="http://www.ironpythoninaction.com/"><i>IronPython in Action</i></a>
- by Michael Foord and Christian Muirhead is a definitive guide that includes
- a wealth of IronPython-specific information.<br><br>
- Some of the exercises in this tutorial require specific software installations.
- The prerequisites to successfully complete the whole tutorial are:</p>
- <ul type="disc">
- <li class="Normal">Microsoft .NET Framework Version 4.0
- <ul type="circle">
- <li class="Normal">Required to run IronPython.</li>
- <li class="Normal">Download from
- <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en">here</a>.</li>
- </ul>
- </li>
- </ul>
- <ul>
- <li class="Normal">Visual Studio 2010
- <ul type="circle">
- <li class="Normal">Very useful for the C#/VB extending tutorials.</li>
- <li class="Normal">Separate .NET 4.0 installation is not required if
- Visual Studio 2010 is installed.</li>
- <li class="Normal">Download from
- <a href="http://www.microsoft.com/visualstudio">here</a>.</li>
- </ul>
- </li>
- <li class="Normal"><a name="Mapack">Mapack</a> (example assembly found
- on the internet)<ul>
- <li>Required for the turorial "<a href="#T1">Basic IronPython</a>"
- and exercise "<a href="#T1.3">Loading additional .NET Libraries</a>".</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">This tutorial assumes that the IronPython distribution was uncompressed
- into the directory C:\IronPython. Please note that your individual setup may
- vary.</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).</p>
- <a name="VS2005Note"></a>
- <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.7 (2.7.10920.0) on .NET 4.0.30319.1<br />
- Type "help", "copyright", "credits" or "license" for more information.</p>
- <p class="Code-Highlighted">>>> _</p>
- <ol start="2">
- <li>
- <p class="Step">IronPython's console interfaces with the user in a standard
- Read-Eval-Print Loop, or REPL. This means that the console repeatedly reads
- user input, evaluates the statement, prints the result (if any), and awaits
- more input. Try it out by executing the simple statements listed below.
- <b>Note:</b> The input line starting with 'for' requires an extra press of
- the enter key afterwards as a signal to the interpreter that there are no
- 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">The IronPython console supports multi-line statements, often
- used in function or class definitions. IronPython prompts for additional lines in a
- multi-line statement using:</p>
- </li>
- </ol>
- <p class="Code-Highlighted">...</p>
- <p class="Code-Background"></p>
- <p class="Body"> </p>
- <p class="Stepnonumbering">One of the more unique aspects of Python is its sensitivity to whitespace at the
- beginning of a line. Unlike C, 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 many
- constructs, including function and class definitions, the bodies of loops, 'if'...'elif'...'else' clauses,
- and 'try'...'except'...'finally' blocks. </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"> </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 function dir(), 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 including 'sys', which is
- one of the most frequently used. Load the 'sys' module using the 'import' keyword:</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. Python’s import doesn’t
- do that automatically, unless it is used in conjunction with the 'from'
- keyword (more on this later). To access the names or attributes in an imported
- module, prefix them 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">['__doc__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit', 'getsizeof', 'gettrace', 'getwindowsversion', 'hexversion', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'py3kwarning', 'setcheckinterval', 'setdefaultencoding', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions', 'winver']</p>
- <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">['.', '%DLR_ROOT%\\Test', '%DLR_ROOT%\\Languages\\IronPython\\Public\\Tutorial', '%DLR_ROOT%\\Languages\\IronPython\\Tests', '%DLR_ROOT%\\Test\\IronPythonTutorial', '%DLR_ROOT%\\bin\\Debug\\Lib', '%DLR_ROOT%\\bin\\Debug\\DLLs', '%DLR_ROOT%\\bin\\Debug']</p>
- <p class="TypedExample">sys.executable</p>
- <p class="LooseVerify">'%DLR_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 directory:</p>
- </li>
- </ol>
- <p class="TypedExample">import first</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">Because you launched ipy.exe from there, the Tutorial directory appears
- in sys.path, telling IronPython to look there in its search for 'first.py'.</p>
- <ol start="2">
- <li>
- <p class="Step">Explore the 'first' module using dir():</p>
- </li>
- </ol>
- <p class="TypedExample">dir(first)</p>
- <p class="Code-Highlighted">>>> dir(first)</p>
- <p class="Code-Background">['__builtins__', '__doc__', '__file__', '__name__', '__package__', '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">We will use the __doc__ attribute later to explore .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">Much of IronPython's power arises from its 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' keyword, 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"> </p>
- <p class="Stepnonumbering">The expected output of these commands is as follows
- (with 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','Is64BitOperatingSystem','Is64BitProcess','MachineName','MemberwiseClone','NewLine','OSVersion','ProcessorCount','ReferenceEquals','SetEnvironmentVariable','SpecialFolder','SpecialFolderOption','StackTrace','SystemDirectory','SystemPageSize','TickCount','ToString','UserDomainName','UserInteractive','UserName','Version','WorkingSet','__all__','__class__','__delattr__','__doc__','__format__','__getattribute__','__hash__','__init__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__']</p>
- <p class="NoVerify-Background">['CommandLine', 'CurrentDirectory', ... '__subclasshook__']</p>
- <p class="Code-Highlighted">>>> System.Environment.OSVersion</p>
- <p class="NoVerify-Background"><System.OperatingSystem object at 0x000000000000002B [Microsoft Windows NT 6.0.6000.0]</p>
- <p class="Code-Highlighted">>>> System.Environment.CommandLine</p>
- <p class="LooseVerify">'"%DLR_ROOT%\\Bin\\Debug\\ipy.exe"'</p>
- <p class="NoVerify-Background">'C:\\IronPython\\ipy.exe'</p>
- <ol start="4">
- <li>
- <p class="Step">The import statement can also be used to import contents of
- a class or module into the global namespace. Use the "from ... import ..."
- flavor of the import statement to do this, then use dir() to explore the contents of the
- global namespace.</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','Sin','Ceiling','Sinh','Atan','Tanh','__name__','Pow','Cos','Cosh','Abs','Round','Atan2','BigMul','Acos','DivRem','Truncate','E','Max','__builtins__','Log','Asin','Floor','PI','Log10','System','Sign','Exp','Min','IEEERemainder','Sqrt']</p>
- <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"> </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="NoVerify-Background">
- ['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">
-
- ['Keys','GetObjectData','Count','Contains','__getitem__','KeyEquals','hcp','Clone','SyncRoot','__setitem__','Remove','Clear','comparer','__len__','ContainsValue','Add','__add__','EqualityComparer','GetHash','IsFixedSize','ContainsKey','CopyTo','GetEnumerator','Synchronized','__iter__','IsReadOnly','__contains__','Item','Values','IsSynchronized','OnDeserialization']</p>
- <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 indexable 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="NoVerify-Highlighted" 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 as follows. Note that
- the input line starting with 'for' requires an extra return or enter key press because
- the interpreter prompts for more statements in the loop's body.</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 using instances
- of the 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 result in a type error:</p>
- <p class="Code-Highlighted">>>> l.Add(3)</p>
- <p class="NoVerify-Background">Traceback (most recent call last):<br />
- File "<stdin>", line 1, in <module><br />
- TypeError: expected str, got int<br /></p>
- <p class="Code-Highlighted">>>> l.Add(2.5)</p>
- <p class="NoVerify-Background">Traceback (most recent call last):<br />
- File "<stdin>", line 1, in <module><br />
- TypeError: expected str, got float<br /></p>
- <p class="Code-Highlighted">>>> l.Add([1,2,3])</p>
- <p class="NoVerify-Background">Traceback (most recent call last):<br />
- File "<stdin>", line 1, in <module><br />
- TypeError: expected str, got list<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"> </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 additional .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 kind of interactive exploration we see in this Tutorial. We recommend
- using the following functions in your code modules, since they provide more control
- over which assembly gets loaded.</p>
- </li>
- <li>
- <p class="Body"><b>clr.AddReferenceToFile</b> adds a 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 a 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 reference a 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. Reference 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','DtdProcessing','EntityHandling','Formatting','IHasXmlNode','IXmlLineInfo','IXmlNamespaceResolver','NameTable','NamespaceHandling','NewLineHandling','ReadState','Resolvers','Schema','Serialization','ValidationType','WhitespaceHandling','WriteState','XPath','XmlAttribute','XmlAttributeCollection','XmlCDataSection','XmlCharacterData','XmlComment','XmlConvert','XmlDateTimeSerializationMode','XmlDeclaration','XmlDocument','XmlDocumentFragment','XmlDocumentType','XmlElement','XmlEntity','XmlEntityReference','XmlException','XmlImplementation','XmlLinkedNode','XmlNameTable','XmlNamedNodeMap','XmlNamespaceManager','XmlNamespaceScope','XmlNode','XmlNodeChangedAction','XmlNodeChangedEventArgs','XmlNodeChangedEventHandler','XmlNodeList','XmlNodeOrder','XmlNodeReader','XmlNodeType','XmlNotation','XmlOutputMethod','XmlParserContext','XmlProcessingInstruction','XmlQualifiedName','XmlReader','XmlReaderSettings','XmlResolver','XmlSecureResolver','XmlSignificantWhitespace','XmlSpace','XmlText','XmlTextReader','XmlTextWriter','XmlTokenizedType','XmlUrlResolver','XmlValidatingReader','XmlWhitespace','XmlWriter','XmlWriterSettings','Xsl','__builtins__','__doc__','__name__','clr']</p>
- <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 Apache License, Version 2.0. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Apache License, Version 2.0, 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 Apache License, Version 2.0.
- *
- * 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 is iterating 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>
- <p class="StepNoNumbering"></p>
- <p class="StepNoNumbering">If you're having trouble getting this to work, make sure
- Mapack.dll is on the search path. One easy way to do this is to copy Mapack.dll into
- the Tutorial direcroty (or whichever directory you're running IronPython from).</p>
- <ol start="3">
- <li>
- <p class="Step">Instantiate the 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 how to discover which constructors are available.</p>
- <p class="Code-Highlighted">Traceback (most recent call last):<br />
- File "<stdin>", line 1, in <module><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: type, rows: int, columns: int)<br />
- __new__(cls:type, rows: int, columns: int, value: float)<br />
- __new__(cls:type, value: Array[Array[float]])
- </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<br />
- </p>
- <p class="Code-Highlighted">>>> print n</p>
- <p class="Code-Background">4<br />
- 0<br />
- </p>
- <ol start="6">
- <li>
- <p class="Step">(Optional) IronPython also supports overloaded operators.
- Matrix provides implementations of operators +, - (binary and unary), *,
- and equality. You can see the Python representation of these operators
- (__eq__, __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">
-
- ['FrobeniusNorm','InfinityNorm','Rows','__neg__','__radd__','Columns','__getitem__','Symmetric','__rmul__','Inverse','__rsub__','Solve','Clone','__setitem__','Multiply','Submatrix','Subtract','Random','__eq__','Diagonal','Trace','Negate','Add','Determinant','Norm1','__sub__','__add__','Transpose','Square','Item','__mul__','__ne__']</p>
- <ol start="7">
- <li>
- <p class="Step">Make simple calculations with the matrices:</p>
- </li>
- </ol>
- <p class="TypedExample">print m * n</p>
- <p class="TypedExample">print n.Transpose() * m</p>
- <p class="TypedExample">print m * 3</p>
- <p class="TypedExample">print n + -n</p>
- <p class="Stepnonumbering">The expected output of this step is:</p>
- <p class="Code-Highlighted">>>> print m * n</p>
- <p class="Code-Background">4.8<br />
- 0<br /><br />
- </p>
- <p class="Code-Highlighted">>>> print n.Transpose() * m</p>
- <p class="Code-Background">4.8 0
- <br /><br /></p>
- <p class="Code-Highlighted">>>> print m * 3</p>
- <p class="Code-Background">3.6 0<br />
- 0 3.6<br /><br />
- </p>
- <p class="Code-Highlighted">>>> print n + -n</p>
- <p class="Code-Background">0<br />
- 0<br /><br />
- </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 the Python Standard Library</a></h2>
- <p class="BodyNote"><b>Note:</b> If you installed IronPython using the MSI installer file, then the Python
- standard library is already included, and this exercise does not apply. These steps are only necessary
- if you installed IronPython using the ZIP file, which does not include the library. In that case,
- this exercise explians how you can obtain Python and direct IronPython to the Python
- standard library.<br /><br />
- If you're not sure how IronPython was installed, then attempt <a href="#T1.4.1.3">steps 3-4</a>
- below. If your output matches this tutorial's, then you already have access to the Python standard
- libraries, and this exercise may be skipped. If you get an ImportError message, then this exercise
- is necessary.</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 the
- default installer settings (e.g. installing to c:\python27).</p>
- </li>
- <li>
- <p class="Step">Create a file named 'site.py' and place it in your IronPython 'Lib'
- directory. There might be one there already, in which case you can simply edit
- it. This 'site.py' file is automatically executed every time you run IronPython,
- making it a convenient way to tell IronPython the location of Python's standard library. To
- do so, add the following code into IronPython's 'site.py'. (Replace
- c:\python27\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:\python27\lib")</p>
- <p class="SyntaxNote"><b>Syntax Note:</b> Preceding a string literal with 'r' tells
- Python to parse the string in "raw" mode, which does not require backslashes (\) to
- be escaped. This is helpful for the readability of certain strings, such as Windows
- paths.</p>
- <ol start="3">
- <li>
- <a name="T1.4.1.3"><p class="Step">Start the IronPython console from the tutorial directory
- (see <a href="#Intro">Introduction</a> for details).</p></a>
- </li>
- <li>
- <p class="Step">Now you can use the Python standard library from
- IronPython, for example to get the current working directory.</p>
- </li>
- </ol>
- <p class="TypedExample">import os</p>
- <p class="Code-Background"></p>
- <p class="TypedExample">os.getcwd()</p>
- <p class="Stepnonumbering">Assuming you're using the standard IronPython installation
- directory, the output should look like this:</p>
- <p class="Code-Highlighted">>>> import os<br />
- >>> os.getcwd()<br /></p>
- <p class="Code-Background">'C:\\ironpython\\Tutorial'</p>
- <p class="LooseVerify">
- '%DLR_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 additional .NET libraries</a></p>
- </li>
- <li>
- <p class="Body"><a href="#T1.4">Obtaining and Using the Python Standard
- Library</a></p>
- </li>
- </ul>
- <p class="Body">In this tutorial, you became acquainted with IronPython's interactive
- console and learned a powerful Python development technique -- the use of dir() and __doc__
- to dynamically 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 the standard Python libraries.</p>
- <p class="Body"> </p>
- <h1><a name="T2">Tutorial 2: Advanced IronPython</a></h1>
- <p class="Body">A large part of IronPython's beauty lies in its capacity for 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 handle the user's
- pressing the button).</p>
- <p class="Body">This tutorial will focus on creating delegates and handling
- events in IronPython, as well as creating Windows applications using Windows Forms and
- the new Windows Presentation Foundation, or WPF (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 an instance of the FileSystemWatcher class and set its
- '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">
- ['SynchronizingObject','Deleted','EnableRaisingEvents','DesignMode','GetLifetimeService','OnRenamed','InitializeLifetimeService','IncludeSubdirectories','WaitForChanged','NotifyFilter','Filter','__enter__','Renamed','Container','Site','Changed','Path','Created','CreateObjRef','GetService','InternalBufferSize','OnChanged','CanRaiseEvents','Dispose','Disposed','__exit__','BeginInit','OnCreated','Error','Events','EndInit','OnDeleted','OnError']</p>
- <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:</p>
- </li>
- </ol>
- <p class="TypedExample">def handle(*args): print args</p>
- <p class="Code-Background"></p>
- <p class="SyntaxNote"><b>Syntax Note:</b> The * operator in front of a function
- parameter signifies the aggregation of any (remaining) input arguments into a
- list by that name. As such, * is only acceptable in front of a function's final
- parameter.</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 no longer being handled by our 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-Background">
- ['Name', 'ChangeType', 'FullPath', 'Empty']</p>
- <ol start="2">
- <li>
- <p class="Step">Now with more knowledge of the FileSystemEventArgs object's
- properties, we can create a better event handler that will display its
- ChangeType and FullPath properties:</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 hook (the object which allows connecting and disconnecting of handler delegates) and the
- callable event-firing object.</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="SyntaxNote"><b>Syntax Note:</b> Python supports the "unpacking"
- of iterable objects, which is similar to pattern-matching on F# tuples. This feature
- is used like normal variable assignment, except the left-hand side of the '=' is a
- comma-separated list of variables, each of which is assigned the corresponding
- value in the iterable. Unpacking can only be used when the number of items returned
- by the right-hand side's iterator is known and exactly matches the length of the
- comma-separated variable list.</p>
- <br />
- <p class="Stepnonumbering">This has returned created for 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="Stepnonumbering">The console output should look like:</p>
- <p class="Code-Background">new inst: <object object at 0x000000000000002B></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">In this exercise, you will create simple Windows Forms applications
- dynamically from the IronPython interactive console.</p>
- <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 blocked, or unable 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 properly multithreaded
- Windows Forms development. See the tasks below.</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="SyntaxNote"><b>Syntax Note:</b> Python modules get automatically initialized
- (executed) when imported, meaning that the Windows Forms initialization code in
- winforms.py has executed due to 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's Text property:</p>
- </li>
- </ol>
- <p class="Stepnonumbering">This change should now appear in the form window's title bar.</p>
- <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 a tuple containing a Form
- object and a MouseEventArgs object, like so:</p>
- <p class="Noverify-Background">(<System.Windows.Forms.Form object at
- 0x000000000000002B [System.Windows.Forms.Form, Text: My First Interactive Application]>,
- <System.Windows.Forms.MouseEventArgs object at 0x000000000000002C
- [System.Windows.Forms.MouseEventArgs]>)</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 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">
- ['Button','Delta','Empty','Clicks','X','Y','Location']</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="SyntaxNote"><b>Syntax Note:</b> Python functions support named parameters
- such as the 'Text' parameter in the above invocation of 'Label'. This allows us to
- specify function arguments by name rather than their ordering, and synergizes nicely
- with Python's capacity for optional parameters.</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">In this exercise, you will interactively create a simple interactive
- Windows Presentation Foundation application.</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 "avalon.py" in your Tutorial directory.</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
- "SizeToContent", the window shrinks.</p>
- <ol start="4">
- <li>
- <p class="Step">Let's add some 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>
- <ol start="6">
- <li>
- <p class="Step">You may leave the interpreter open and continue on to Task 2.</p>
- </li>
- </ol>
- <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 Task 1, the
- relevant portions of which are repeated here:</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>
- <ol start="2">
- <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">w.Content = LoadXaml("calc.xaml")</p>
- <p class="Code-Background"></p>
- <p class="Stepnonumbering">Regardless of whether you flowed into this task
- from Task 1, w.SizeToContent has been reset to manual, so you will need to
- 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 tree (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<br />
- <System.Windows.Controls.Canvas object at 0x000000000000002B [System.Windows.Controls.Canvas]><br />
- <System.Windows.Controls.Canvas object at 0x000000000000002C [System.Windows.Controls.Canvas]><br />
- <System.Windows.Shapes.Rectangle object at 0x000000000000002D [System.Windows.Shapes.Rectangle]><br />
- <System.Windows.Controls.Canvas object at 0x000000000000002E [System.Windows.Controls.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 a generator, 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="SyntaxNote"><b>Syntax Note:</b> Python's generator syntax is a
- concise way of enumerating, filtering (by way of the optional "if
- ..." portion), and mapping over (by way of the leftmost portion, an
- identity expression in this example) an iterable.</p>
- <p class="Stepnonumbering">The console printed the list of all buttons. Let's
- store this list object in a variable for later use:</p>
- <p class="TypedExample">buttons = _</p>
- <p class="Code-Background"></p>
- <p class="SyntaxNote"><b>Syntax Note:</b> Available only in the interpreter,
- the "_" variable stores the last non-None result value printed by
- the console.</p>
- <ol start="5">
- <li>
- <p class="Step">At this point we can make changes to all the buttons. For
- example, let's 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__
- constructor 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>
- <br />
- <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 in this manner with minimal
- setup. The advantage is that changes are visible immediately, and modifications
- are happening to a live system without requiring recompilation or even re-execution.</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
- a simple interactive application in Windows Forms and 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>15 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">Word Spell Checking</a></p>
- </li>
- </ul>
- <h2><a name="T3.1">Exercise 1: 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.1.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.1.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 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">Word Spell Checking</a></p>
- </li>
- </ul>
- <p class="Body"> </p>
- <p class="Body">You 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 programs</a></h1>
- <p class="Body">This tutorial will walk you through a very simple debug session,
- debugging a Python script using the Microsoft CLR Debugger. If you have a
- Visual Studio SKU, see <a href="#T7">using Visual Studio</a>, 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 programs</a></p>
- </li>
- </ul>
- <h2><a name="T4.1">Exercise 1: Debugging IronPython programs</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 programs 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 "-D 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 the 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 you inserted at 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 programs</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. It’s worth noting that as Python does not contain protected class members,
- such members get promoted to public class members when imported into IronPython. Private
- class members, however, will be invisible in IronPython when imported.</p>
- <h3><a name="T5.1.1">Task 1: Implementing a simple class - constructor and ToString</a></h3>
- <ol>
- <li>
- <p class="Step">Open the "SDK Command Prompt" or "Visual Studio 2010
- Command Prompt" from the start menu. A more recent Visual Studio command
- prompt should also work.</p>
- </li>
- <li>
- <p class="Step">Open the "csextend.cs" file in Notepad or your favorite text
- editor. 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 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)<br /></p>
- <p class="Code-Highlighted">['Equals', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']</p>
- <ol start="8">
- <li>
- <p class="Step">Instantiate 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 to the C# code to add more.</p>
- </li>
- </ol>
- <h3><a name="T5.1.2">Task 2: Making the object enumerable</a></h3>
- <ol>
- <li>
- <p class="Step">Back in Notepad, open "csextend.cs" to add more functionality
- to the Simple class.</p>
- </li>
- <li>
- <p class="Step">First, inherit the Simple class from IEnumerable and implement the
- 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 /><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 />
- }</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="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 />
- <p class="Code-Highlighted">['Equals', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']</p>
- <p class="Code-Highlighted">>>> s = Simple(10)<br />
- >>> 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 shows the GetEnumerator
- method.</p>
- <ol start="4">
- <li>
- <p class="Step">Exit IronPython and return to the C# code to add more
- functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.1.3">Task 3: Adding a 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">
- ['__radd__','__add__','GetEnumerator','__iter__']</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 in the output of dir() that you will now see
- the 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)</p>
- <p class="Code-Highlighted">['Equals', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__add__', '__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']</p>
- <p class="Code-Highlighted">>>> a = Simple(10)<br />
- >>> b = Simple(20)</p>
- <p class="Code-Highlighted">>>> a + b</p>
- <p class="Code-Background"><Simple object at 0x000000000000002B [Simple<30>]></p>
- <ol start="3">
- <li>
- <p class="Step">Exit IronPython and return to the C# code to add more
- functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.1.4">Task 4: Adding a delegate</a></h3>
- <ol>
- <li>
- <p class="Step">Add the declaration 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 the "Transform" method to the Simple class,
- which takes the delegate as a parameter and invokes the it:</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 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.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. An interesting optional
- exercise is to combine the debugging example with this one. If you are so inclined,
- try debugging the script that you just typed in. To do so, open the
- "debugcsx.py" script located in Tutorial directory and place a breakpoint
- on the function 'X'. You will see a mixed call stack between C# and IronPython.</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 the Visual Basic .NET language to
- build a class that supports enumeration, custom operators and delegates, and
- you will use that class from IronPython. It’s worth noting that as Python does
- not contain protected class members, these members become public when imported into
- IronPython. Private class members, however, will be invisible from IronPython.</p>
- <h3><a name="T5.2.1">Task 1: Implementing a simple class - constructor and ToString</a></h3>
- <ol>
- <li>
- <p class="Step">Open the "SDK Command Prompt" or "Visual Studio
- 2010 Command Prompt" from the start menu. A more recent Visual Studio
- Command Prompt should also work.</p>
- </li>
- <li>
- <p class="Step">Open "vbextend.vb" in notepad or your favorite text editor. 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 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__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']</p>
- <ol start="8">
- <li>
- <p class="Step">Instantiate and print a Simple object:</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 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, open "vbextend.vb" to add more functionality
- to the Simple class.</p>
- </li>
- <li>
- <p class="Step">First, inherit the Simple class from IEnumerable and implement
- the 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<br />
- <br />
- <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)</p>
- <p class="Code-Highlighted">['Equals', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']</p>
- <p class="Code-Highlighted">>>> s = Simple(10)<br />
- >>> 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 shows the GetEnumerator
- method.</p>
- <ol start="4">
- <li>
- <p class="Step">Exit IronPython and return to the Visual Basic code
- to add more functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.2.3">Task 3: Adding a 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">
- ['__radd__','__add__','GetEnumerator','__iter__']</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 in the output of dir() that you now see the
- 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)</p>
- <p class="Code-Background">['Equals', 'GetEnumerator', 'GetHashCode', 'GetType', 'MemberwiseClone', 'ReferenceEquals', 'ToString', '__add__', '__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']</p>
- <p class="Code-Highlighted">>>> a = Simple(10)<br />
- >>> b = Simple(20)</p>
- <p class="Code-Highlighted">>>> a + b</p>
- <p class="Code-Background"><Simple object at 0x000000000000002B [Simple<30>]></p>
- <ol start="3">
- <li>
- <p class="Step">Exit IronPython and return to the Visual Basic .NET
- code to add more functionality.</p>
- </li>
- </ol>
- <h3><a name="T5.2.4">Task 4: Adding a delegate</a></h3>
- <ol>
- <li>
- <p class="Step">Add the declaration 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 the "Transform" method to the Simple class,
- which takes the delegate as a parameter and invokes it:</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 to the 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. An interesting
- optional exercise is to combine the debugging example with this one. If you are so
- inclined, try debugging the script that you just typed in. To do so, open the
- "debugvbx.py" script located in the Tutorial directory and place a
- breakpoint on the function 'X'. 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 Python and C# or Visual
- Basic code is located in the 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 a custon addition operator to it, and included support for a delegate.
- The implementation was in either C#, 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="BodyNote">There is a community technology preview add-in for
- Visual Studio 2010, IronPython Tools, which supports development of Python
- code. Not only does this include Python syntax highlighting, it also
- adds Python expression completion support to Visual Studio among other
- things! You can download IronPython Tools from
- <a href="http://www.ironpython.net/tools/">http://www.ironpython.net/tools/</a>.</p>
- <p class="BodyNote">If you would like to see more features added to this
- tool, we would love
- your feedback! Please vote and/or leave a comment
- <a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=475830">here</a>.</p>
- <p class="Body">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". 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>