Wednesday, December 30, 2009

How hard is it to add IronPython support to Visual Studio?

Hard. Very hard.

Michael Foord has a good post about whether Microsoft cares about dynamic languages. Some people [who?] believe that because IronPython/IronRuby don't have full support in Visual Studio 2010 that Microsoft doesn't care about dynamic languages.

I think I can safely say that adding full, high-quality support for IronPython to Visual Studio would require at least a couple of man-years of work. The rabbit hole goes pretty deep when you consider all of the functionality that VS offers, not to mention the difficulty of doing IntelliSense well. I estimate they'd have to at least double the IronPython team to get full support into VS11. IronRuby would require the same commitment.

Also, IronPython and IronRuby have only recently got to the point where I would consider them production-ready. Thus, getting IronRuby or IronPython into VS2010 was never realistic.

Now, if they don't have some support in VS11 (VS2012?), well, that's a different story. At least the IronPython extensions should be pretty mature by then.

NWSGI 2.0 Release

I'm very pleased to announce the release of the final version of NWSGI 2.0. It's been a long road since it was first shown as "NWSGI 1.1 Preview1" way back in March. Since then most of the code has been overhauled to make maintenance easier and improve performance. IronPython has also come  a long way; the 2.6 release is a fantastic piece of work with much better performance and compatibility than 2.0. Both IronPython and NWSGI are reaching the point where it will soon be feasible to run most Python web apps with little to no modification – I'm hoping by this time next year that everything will "just work".

What's New

NWSGI 2.0 is mostly a lot of little changes that add up to a much better experience:

  • Easier configuration: In v1.0 there were different ways to configure NWSGI depending on your configuration. Now there is only one way to do it. The ambiguous options with multiple meanings are gone, and new options added to support the extra optional features of IronPython 2.6.
  • Better management UI: The new management UI is both easier to use and easier to maintain.
  • Performance improvements: NWSGI will now cache the WSGI callable and associated modules instead of reloading it each time. IronPython 2.6 is also much faster then 2.0.

More Information

My blog posts from earlier in the year are still relevant:

I'll be moving the information in these over to Codeplex soon, so that it's easier to find.

Please let me know what you think of the new release, and what it's being used for – I'm always curious to hear what people think.

IronPython Extensions for Visual Studio 0.4

UPDATE (Feb 28, 2010): The IronPython team recently announced IronPython Tools for Visual Studio, so this project is no longer being maintained.

Last week I uploaded version 0.4 of the IronPython Extensions for Visual Studio to BitBucket and the Visual Studio Gallery. This release includes a couple of new features and some minor performance improvements to the old features.

What's New

Squiggles! The editor will now underline inconsistent tabs (mixing tabs and spaces) and syntax errors. It doesn't currently display a tooltip explaining what the underline is for, or offer any automatic fixes, but those should be coming soon.
error-squiggles
Also new is an interactive console for use in Visual Studio. The advantage this has over a normal IronPython console is that it will syntax-highlight the console history. Eventually I'd like to have it pull the colour scheme from the editor.
IronPython Interactive Console

What Else is Included

This release includes the features of the previous release – syntax highlighting and outlining of classes and functions – but I've improved the performance of both to make the editor a little snappier (not much, mind you – ever try running a profiler on all of Visual Studio?).

What's Next

Besides some minor changes to all of the existing features that I'd like to make, there are two big pieces missing: a project system and IntelliSense. IntelliSense is the more interesting of the two, so I think I'm going to tackle it next. If anyone wants to tackle the project system, let me know and I'll give you some pointers.

Sunday, November 22, 2009

NWSGI 2.0 Release Candidate 2

The final release candidate of NWSGI 2.0 is now available. Except for version numbers, this is what will become NWSGI 2.0 as soon as IronPython 2.6 is released.

NWSGI 2.0 Release Candidate 2 includes all of the features of NWSGI 2.0 Release Candidate 1, and adds support configuring tracing, lightweight scopes, and the profiler. It is built against IronPython 2.6 RC3.

The following issues are fixed in this release:

IronPython Extensions for Visual Studio 2010

UPDATE (Feb 28, 2010): The IronPython team recently announced IronPython Tools for Visual Studio, so this project is no longer being maintained.
 
Lately, I’ve been experimenting with the new editor APIs in Visual Studio 2010 to build some simple extensions to make Python editing a little better. Helpfully, IronPython exposes most of the complicated infrastructure (the tokenizer) to make the job easy. The documentation for the new editor APIs is still a bit weak; hopefully that will improve by the final release. In the meantime, the examples are the best source of information. There also a series of blog posts by Mike Feingold about the NDjango editor for VS2010 that form a great end-to-end example.

Download & Installation

Download IronPython Extensions for Visual Studio 2010 (and the source code; Ms-PL as always) from my BitBucket repository or from the Visual Studio Gallery (direct link). For direct downloads, just run (double-click) the .vsix file to install it into Visual Studio. Otherwise, you can use the extension manager (search for "IronPython") and install it directly from Visual Studio.

Features

The extensions provide three features so far: syntax highlighting, brace matching, and outlining.
IronPython-vs2010
In the future I'm planning on adding project support, templates, and (most difficult of all) IntelliSense.
an unknown author

Monday, September 28, 2009

NWSGI 2.0 Release Candidate 1 Released

To coincide with IronPython 2.6 RC1, NWSGI 2.0 RC1 is now available.

This release is identical to Beta 2, except for the version of IronPython is uses.

Friday, September 25, 2009

Using NWSGI 2.0 Beta 2 with IronPython 2.6 RC1

UPDATE: This won't work. The IronPython team made some changes that break the ABI (Microsoft.Dynamic, I'm looking at you) which renders this fix unworkable.

NWSGI is linked against specific versions of IronPython, so every time the IronPython team changes the AssemblyVersion, I need to respin NWSGI. In the meantime, an <assemblyBinding/> section can be used in web.config to make previous NWSGI version work with newer IronPython versions.

Thanks to Markus Törnqvist for coming up the specific elements for this case:

    <runtime>
       <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
           <dependentAssembly>
               <assemblyIdentity name="IronPython" publicKeyToken="31bf3856ad364e35" culture="neutral" />
               <bindingRedirect oldVersion="2.6.0.20" newVersion="2.6.10920.0" />
           </dependentAssembly>
           <dependentAssembly>
               <assemblyIdentity name="Microsoft.Scripting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
               <bindingRedirect oldVersion="0.9.6.20" newVersion="1.0.0.0" />
           </dependentAssembly>
       </assemblyBinding>
   </runtime>

I’ll try to get an update of NWSGI out as soon as possible.

Saturday, August 15, 2009

NWSGI 2.0 Beta 2 Released

NWSGI 2.0 Beta 2 is now available. This release in linked against IronPython 2.6 Beta 2, and also fixes a couple of bugs. The big change is that the install does not add NWSGI to the GAC; without IronPython also installed to the GAC, it doesn't make much sense to put NWSGI there.

Sunday, August 9, 2009

Biting Off More Than I Can Chew

I was going through the “Repositories” folder on my machine, looking at all of the stuff I’ve downloaded since, well, the last time I went through this exercise. This time around, a lot of it is stuff I’ve tried to get working on IronPython. Here’s a sampling:

  • Django
  • setuptools
  • Trac
  • Genshi
  • Mercurial
  • SCons
  • CherryPy
  • docutils
  • moin
  • pygments
  • pymarkdown
  • nose
  • sqlalchemy
  • IronRubyMVC

On top of that, there’s the stuff I wrote: NWSGI, IronPython.Zlib, adonet-dbapi, and more.

Unfortunately, I just don’t have time to track all (or even some) of those any more. Debugging things is also pretty difficult – IronPython is getting good enough that the only bugs are really obscure. It probably takes me ten times longer to find a bug and isolate it into a testcase than it does for Dino to fix it. There are other things in real life that have changed as well, drastically reducing the time I can spend on this stuff.

Somewhere along the line I developed a weird sense of duty to make that list of stuff work on IronPython, even though I didn’t have a use for most of it. Realistically, getting all of that to work, and finding all of the little corner cases of Python that they exploit but IronPython doesn’t implement, would be a full time job.

So, I’m cutting back. Way back. IronPython-wise, I’m only going to focus on the stuff I’ve written (and yes, I will be getting Beta 2 of NWSGI 2.0 out soon), and Iron[Ruby|Python]MVC . For me, those are going to be the most immediately rewarding, and I can also stop worrying about the others.

Now, with all of that said, I have an offer: if anyone wants to work on the top part of that list (up to and including SCons), I’ll help get you up to speed on some of the issues with those programs, and some of the tricks involved in debugging them (hint: Debugger.Break). This will be  limited-time offer, valid until I forget the details of the program in question. I really want to see these things compatible with IronPython, but I just no longer have the time to do it myself.

Thursday, July 2, 2009

NWSGI 2.0: Removing URL Warts

The normal procedure for configuring NWSGI leaves an unsightly URL wart: the URL must contain the .wsgi file. There are two ways to get rid of that wart: URL rewriting and wildcards.

URL Rewriting

When using URL rewriting, the web server changes ("rewrites") the incoming URL into something NWSGI can understand. IIS 7 has a URL rewriting extension to do just that. It's quite easy to use, too:

<rewrite> 
    <rules> 
        <clear /> 
        <rule name="Redirect Warty Requests" stopProcessing="true"> 
            <match url="simple.wsgi/(.*)" /> 
            <conditions logicalGrouping="MatchAll" /> 
            <action type="Redirect" url="{R:1}" redirectType="Permanent" /> 
        </rule> 
        <rule name="Remove WSGI Wart"> 
            <match url="^(.*)$" /> 
            <conditions logicalGrouping="MatchAll" /> 
            <action type="Rewrite" url="simple.wsgi/{R:1}" appendQueryString="true" /> 
        </rule> 
    </rules> 
</rewrite>

Replace simple.wsgi with the name of the .wsgi file you would normally use. Now, http://example.com/simple/simple.wsgi/Products/Widgets can be accessed as http://example.com/simple/Products/Widgets. The first rule ("Redirect Warty Requests") will redirect any uses of http://example.com/simple/simple.wsgi/Products/Widgets to http://example.com/simple/Products/Widgets to ensure that only one set of URLs is used (which is important for search engines). However, most modern applications expect to have their URLs rewritten and can be configured to generate the "clean" URLs by default.

If you are using IIS 6, you'll need to use something like ISAPI_Rewrite to achieve the same effect. The following should have the same effect as the above rules:

RewriteEngine On
RewriteRule ^hello.wsgi/(.*) $1 [NC, R=301]
RewriteRule ^(.*)$ hello.wsgi/$1 [NC]

Wildcards

Normally, IIS dispatches requests by extension; this is why we have the .wsgi file in the first place. However, it can be configured to pass all requests to a specific handler by configuring a wildcard extension. Unlike URL rewriting, which is transparent to NWSGI, NWSGI needs to know that it has been configured as a wildcard handler. To do this, add a <wildcard> element to the configuration:

<wsgi>
    <wildcard physicalPath="C:\simple\simple.wsgi" callable="simple_app" />
</wsgi>

<system.web>
    <httpHandlers>
        <add verb="*" path="*" type="NWSGI.WsgiHandler, NWSGI, Version=2.0.0.0, Culture=neutral, PublicKeyToken=41e64ddc1bf1fc86" />
    </httpHandlers>
</system.web>
<system.webServer>
    <handlers>
        <add name="WsgiHandler" path="*" verb="*" type="NWSGI.WsgiHandler, NWSGI, Version=2.0.0.0, Culture=neutral, PublicKeyToken=41e64ddc1bf1fc86" resourceType="Unspecified" />
    </handlers>
    <validation validateIntegratedModeConfiguration="false" />
</system.webServer>

The physicalPath and callable attributes have the same meaning as on the <scriptMapping> element. If the configuration includes a <wildcard> element, any <scriptMapping> elements are ignored. Also, make sure that the path attribute of the handler mappings in set to *.

Ultimately, the effect is the same as URL rewriting: http://example.com/simple/simple.wsgi/Products/Widgets can be accessed as http://example.com/simple/Products/Widgets.

Which to Choose

If possible, you should prefer URL rewriting, as it should be faster than using wildcard mappings; however, it requires support from the application. If you're on IIS 6 or IIS 7 without a URL Rewrite extension installed, or your application doesn't support rewritten URLs, then wildcard mappings are available.

Tuesday, June 30, 2009

NWSGI 2.0: Advanced Dispatching

Function Callables

Let’s say we’re dealing with a much larger Python application, coolapp, that is installed at C:\coolapp-1.1\. Unfortunately, coolapp doesn’t provide a ready-made .wsgi file for us, but it does provide a function(coolapp.dispatchers.wsgi_application) that we can use by writing a little wrapper that looks something like:

import sys
sys.path.append("C:\coolapp-1.1")
import coolapp.dispatchers.wsgi_application
application = coolapp.dispatchers.wsgi_application

We could save this as coolapp.wsgi and follow either of two methods from last time, but since we’re not doing anything fancy in the wrapper, NWSGI provides a shortcut:

<wsgi>
    <pythonPaths>
        <path path="C:\coolapp-1.1" />
    </pythonPaths>
    <scriptMappings>
        <scriptMapping scriptName="coolapp.wsgi" callable="coolapp.dispatchers.wsgi_application" />
    </scriptMappings>
</wsgi>

First, we add C:\coolapp-1.1 to Python’s path so that we can import it. Next, we tell it that any requests for coolapp.wsgi should be dispatched to the function coolapp.dispatchers.wsgi_application. This is completely equivalent to the wrapper file, but saves us from creating it. Visiting http://example.com/coolapp.wsgi/ will run coolapp.

Class Callables

Functions aren’t the only things in Python that are callable; classes are also callable (it creates an instance of the class). Let’s say we upgrade coolapp to version 2.0 (installed in C:\coolapp-2.0). The team has made some changes, and their WSGI application is now a class, WsgiApplication. This class has a __call__ method (making its instances callable as well!), so our WSGI application is an instance of the WsgiApplication class. We could use a coolapp.wsgi wrapper again:

import sys
sys.path.append("C:\coolapp-2.1")
import coolapp.dispatchers.WsgiApplication
application = coolapp.dispatchers.WsgiApplication()

Again, our little wrapper doesn’t do much, so NWSGI provides a shortcut:

<wsgi>
    <pythonPaths>
        <path path="C:\coolapp-2.0" />
    </pythonPaths>
    <scriptMappings>
        <scriptMapping scriptName="coolapp.wsgi" callable="coolapp.dispatchers.WsgiApplication()" />
    </scriptMappings>
</wsgi>

This time, NWSGI will create an instance of WsgiApplication, and then call the instance and return the result to IIS. This shortcut will only work if the class doesn’t require any arguments; if it does, it needs to be wrapped in a .wsgi file (when in doubt, you can always use a wrapper file). Again, visit http://example.com/coolapp.wsgi/ to run the application.

There’s actually one more case: Python classes that implement the iterator protocol, but I don’t think two many applications are implemented that, so I’ll skip it. PEP 333 gives an example if you’re really interested.

Monday, June 29, 2009

NWSGI 2.0: Dispatching

NWSGI has a fairly simple task: given a URL, call some Python code that produces some output. The devil, as always, is in the details.

What is WSGI?

NWSGI is an implementation of the Python WSGI specification (PEP 333). WSGI is the Web Server Gateway Interface, “a simple and universal interface between web servers and web applications or frameworks”, as defined in PEP 333.

OK, so what does that mean?

The purpose of WSGI is to define how web servers (i.e. Apache, IIS, etc.) talk to Python web application or frameworks (i.e. Trac, Django, etc.). In theory, a web server with a WSGI implementation (such as mod_wsgi for Apache, or NWSGI for IIS) should be able to run any web application that is implemented as a WSGI application (prior to WSGI, many applications/frameworks were server-specific). Of course, that doesn’t always pan out in practice, but it’s a start.

What is a WSGI application?

A WSGI application is surprisingly simple:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

The simple_app function is the entire application! A WSGI application is a callable (a function, mostly) that takes two arguments and returns an iterable (a list or generator, mostly). There’s some extra goo in there as well (start_response, for example) that’s not really relevant as far as dispatching is concerned. Writing WSGI applications is probably a book’s worth of content, so I’ll leave it at that for now.

Finding Callables in .wsgi Files

Local Files

Now that we have a callable for our application, NWSGI needs to know how to find it. The simplest way is to simply drop the file (let’s call it simple.wsgi) into the application root (i.e. C:\inetpub\wwwroot\, next to web.config). If you make a request to http://example.com/simple.wsgi/, IIS will see that .wsgi is associated with NWSGI and pass the request to it. NWSGI will then open simple.wsgi, try to find a variable called application (which is, by convention, the name of WSGI callables), call it, and return the result to IIS.

In this case, however, our callable is named simple_app, not application. To be able to run our app, NWSGI needs to know this! To do this, there needs to be a script mapping telling NWSGI how to run simple.wsgi.

<wsgi>
    <scriptMappings>
        <scriptMapping scriptName="simple.wsgi" callable="simple_app" />
    </scriptMappings>
</wsgi>

This configuration tells NWSGI that for the script simple.wsgi, it should use simple_app as the callable instead of application. (NOTE: This exact syntax requires 2.0b2 or later).

Other Files

Best practices for WSGI applications say that you should not put your application files in the web-exposed directory. This means that simple.wsgi should really live somewhere else; let’s say C:\simple\simple.wsgi. Of course, now NWSGI doesn’t have the slightest clue where it is, so we have to tell it:

<wsgi>
    <scriptMappings>
        <scriptMapping scriptName="simple.wsgi" physicalPath="C:\simple\simple.wsgi" callable="simple_app" />
    </scriptMappings>
</wsgi>

There is no longer a .wsgi in our application folder, but IIS doesn’t care. If you visit http://example.com/simple.wsgi/ with this configuration, IIS still happily passes the simple.wsgi script onto NWSGI. NWSGI looks at the script mappings and finds that simple.wsgi maps to C:\simple\simple.wsgi, so it loads that file instead (without looking for simple.wsgi in the application directory), looks up simple_app, and calls it.

Using .wsgi files is the simplest way to deploy an application, but NWSGI has a couple of shortcuts to make things easier for certain applications.

Friday, June 26, 2009

NWSGI 2.0: Configuration Details

For the most part, NWSGI can be used without any configuration. All you have to do is create a .wsgi file, throw it in a directory, let IIS know what’s going on, and you’re good to go! Of course, if it was always that easy, configuration wouldn’t exist. To really work with NWSGI, you need to understand its configuration. It helps if you’re already familiar with web.config files; if not, check this out (but hurry back!).

First Things First

NWSGI uses .NET’s built-in configuration system (System.Configuration), so the first thing that needs to be done is to let the .NET Framework know about the custom NWSGI configuration section:

<configSections>
    <section name="wsgi" type="NWSGI.WsgiSection" />
</configSections>

This must be the first entry in web.config, directly under the <configuration> element.

The <wsgi> element

All of the configuration options for NWSGI are under the <wsgi> element. The first ones we will look at are specified as attributes of the <wsgi> element: enableExtensions, adaptiveCompilation and frames.

enableExtensions
Enable extensions to NWSGI. Relying on these will make your application nonportable to other WSGI implementations. Required to use ASP.NET's built-in Session support, for example. Choices: true, false.
compilation
Control how IronPython compiles code. Choices: Adaptive, Compiled.
frames
Control sys._getframe. Enabling sys._getframe causes a performance hit. Choices: Off, On, Full.

Example:

<wsgi adaptiveCompilation="false" frames="Full" />

Adding Python Search Paths

If your application needs to access Python modules that are not in the default NWSGI search paths (~/, ~/Bin/ and ~/Bin/Lib/), you can use the <pythonPaths> element to add them. The <pythonPaths> element contains a set of <path> elements that are added (in order) to sys.path before the application is run. The <path> element has one required attribute – path – that contains the full path to a folder on disk containing the modules you want to use.

Example:

<wsgi>
    <pythonPaths>
        <path path="C:\django" />
    </pythonPaths>
</wsgi>

Adding WSGI Environment Variables

Most applications will require some configuration of their own; these options are passed in the environ parameter of the WSGI application. You can add entries to this list by using the <wsgiEnviron> element, which contains a set of <variable> elements. Each <variable> element has two required attributes, name and value.

Example:

<wsgi>
    <wsgiEnviron>
        <variable name="trac.env_path" value="C:\trac\projects" />
    </wsgiEnviron>
</wsgi>

Advanced Script Usage

There are cases where you may need to configure how NWSGI handles a particular script file. In these cases you need a virtual script mapping; NWSGI will always check script mappings before looking for a file on disk. Not surprisingly, these are stored in the <scriptMappings> element, which contains a set of <scriptMapping> elements. There are three parts to a script mapping:

scriptNamerequired
The name of the virtual script; overrides any scripts on disk.
physicalPath
The path to the actual file to execute. This can be a full path (i.e. C:\myapp\myapp.wsgi) or an app-relative path (i.e. ~/scripts/myapp.wsgi).
callable
If physicalPath is set, the name of the callable object in that file; if it is not set, an entry point for the application.

Entry points are used to specify a particular function in a Python module on sys.path (see the <pythonPaths> element above for how to control sys.path). For example, for Django the entry point would be "django.core.handlers.wsgi.WSGIHandler()". This mimics the standard Python syntax for creating an object; it is this object that is used as the application. If, instead, the application provides a function (like trac), the entry point would be "trac.web.main.dispatch_request".

Example:

<scriptMappings>
    <scriptMapping scriptName="myapp.wsgi" physicalPath="C:\myapp\myapp.wsgi" callable="myapp" />
</scriptMappings>

Wildcard Settings

When IIS is configured in wildcard mode, all requests for an application are passed to NWSGI, instead of only requests for .wsgi files. You can enable this by setting path="*" in the handler/httpHandler definition. Because NWSGI normally expects there to be a .wsgi file in the URL, but in wildcard mode there isn't one, the <wildcard> element is required to tell NWSGI what script to execute. The available settings – physicalPath and callable – have the same meaning as the same settings for script mappings (above). If the <wildcard> element is present, the <scriptMappings> element is ignored.

Example:

<wildcard physicalPath="C:\HelloWorld\hello.wsgi" callable="hello" />

Conclusion

NWSGI is extremely configurable; in many cases, you don't even need a .wsgi file. That said, the configuration can be complex, so please ask if you run into any problems. A later post will go into more detail on the mechanics of callables.

Wednesday, June 24, 2009

NWSGI 2.0: Configuration Changes

One of the two areas to see the most changes in NWSGI 2.0 was its configuration. Some of the options in v1.0 were overloaded in strange ways; even I wasn’t entirely sure what some combinations would produce. There was also the small problem of where to put the configuration section; it varied depending on how NWSGI was installed. For v2.0, both problems needed to be fixed. Doing so required a re-think of how configuration was handled.

Configuring Wildcards

In v1.0, configuring NWSGI to operate in wildcard mode required setting options that were designed for other things in particular ways that made no sense. In v2.0, there is a special <wildcard> element under <wsgi> (replacing the wildcardModule option) that is specifically used for configuring these settings. If the <wildcard> element exists, then NWSGI will ignore the <scriptMappings> element.

The callable option has also been removed from the <wsgi> element as it is no longer necessary (it defaults to “application”). To specify a custom callable name for a script, create a <scriptMapping>.

Where to put it?

The first problem was to put the <wsgi> section in the same place all the time. In v1.0 it could be directly under <configuration> (if you were using xcopy deployment) or under <system.webServer> (if you installed it on IIS7). The two could not necessarily coexist in the same web.config file, either! IIS 7 uses a different configuration assembly (Microsoft.Web.Administration) than ASP.NET (System.Configuration), and they’re no compatible, to boot.

The fix is relatively simple: rather than trying to use the appropriate configuration system from the handler, v2.0 always uses System.Configuration. This means that the <wsgi> section is always directly under <configuration>. The only downside is that the section always has to be declared at the top of web.config:

<configSections>
    <section name="wsgi" type="NWSGI.WsgiSection, NWSGI, Version=1.99.1.0, Culture=neutral, PublicKeyToken=41e64ddc1bf1fc86" />
</configSections>

New Options

There are also two new options: compilation and frames. The compilation option controls how IronPython generates code. The frames option is used to control sys._getframe; as tracking frames incurs a performance hit, it must be explicitly enabled.

Wrapping Up

The changes to configuration (which will break any existing configurations) are the main reason for bumping the version to 2.0. The clean up of the options resulted in much cleaner implementations for the management and especially for the handler itself. As always, if you have any comments, let me know.

Monday, June 22, 2009

NWSGI 2.0: Installation & Usage

There are two ways to use NWSGI: by installing it or by using xcopy deployment. Each method has its advantages and disadvantages, but their functionality is the same.

Installation

The quickest way to get NWSGI up and running is to use the MSI installer. This will add NWSGI to the GAC, making it available for all applications. If you are running IIS 7, it will also install the IIS 7 management components. The installer will also put a copy of the NWSGI assembly along with the README and HelloWorld example in C:\Program Files\NWSGI. This is the preferred approach, unless you do not have administrator rights to the server and cannot convince the server administrator to install it.

xcopy Deployment

The term “xcopy deployment” refers to the Windows xcopy command, which is used to (among other things) copy entire directory trees. Using this method is useful if you can’t (or don’t want to) use the installer package. If this is the case, download the .zip package instead of the MSI installer. To use this method, simply copy NWSGI.dll into your application’s Bin/ directory, and then copy the whole application folder to the server.

Setting Up the Hello World Example

Once you have decided which method you are going to use, the easiest way to check that it is working is to use the HelloWorld example that is included with both packages. I’m only going to describe the most common configuration, and I’m also going to assume you have access to the server; if you have a custom setup (such as a hosted site), just ask.

  1. Copy the HelloWorld sample folder to C:\inetpub\wwwroot.
  2. Mark C:\inetpub\wwwroot\HelloWorld as an application.
    • IIS 6/7: From the IIS management UI, mark the folder as an application.
    • IIS 7: From an elevated command prompt, run: appcmd add app /site.name:"Default Web Site" /path:/HelloWorld /physicalPath:C:\inetput\wwwroot\HelloWorld
  3. Visit http://localhost/HelloWorld/hello.wsgi.

If the browser says “Hello, World!”, you’re good to go! If not, please ask in the forum, and I’ll try to help you out.

Thursday, June 18, 2009

NWSGI 2.0 Beta 1

NWSGI 2.0 Beta 1 is now available. This is a major update to NWSGI that makes it easier to install and use and dramatically improves the management story.

So, what happened to 1.1?

Originally, NWSGI 1.1 was going to be a refresh of v1.0 that supported IronPython 2.6 and fixed a few bugs. NWSGI 2.0 was going to completely overhaul large parts of the management UI and make some deeper changes to the handler itself. However, I got a week off with some rain and v2.0 progressed much quicker than expected; v1.1 was obsolete before it was even released.

So, v1.1 was dropped and v2.0 will be the first IronPython 2.6-compatible release. It’s easy to make breaking changes when you have no customers :).

What’s New

  • Easier configuration. In v1.0 there were different ways to configure NWSGI depending on your configuration. Now there is only one way to do it. Some of the more ambiguous options have also been cleaned up, and new ones added to support IronPython 2.6.
  • Better management UI. IIS 7 includes a rich UI framework for developing management extensions, but doesn’t have much documentation on it. Some spelunking with reflector showed me better ways to do pretty much everything; not much of the v1.0 management code is left.
  • Performance improvements. NWSGI will now cache the WSGI callable instead of reloading it each time.
  • Other misc. fixes. I really need to get into the habit of adding a Codeplex issue for each bug so that I can keep track of what I’ve fixed.

Give it a spin

The Codeplex wiki needs to be updated to reflect the new documentation, but the included readme is up to date. I’ll also be posting a series of blogs posts over the next few weeks that will explain all the features of NWSGI and provide some helpful examples. Remember, this is a Beta release, so please let me know if you encounter any issues.

Saturday, April 25, 2009

Ctypes for IronPython

I've been spending the last little while working ctypes support for IronPython. It's certainly an interesting problem, mapping from Python –> .NET –> C, and I've learned more than I ever wanted to know about extending IronPython. Support isn't anywhere close to complete – it passes a whopping 5/101 tests. IronPython 2.6 is required.

What's complete:

  • Primitive (c_*) types
  • Simple structures, nested structures
  • Loading DLLs
  • Calling functions
  • byref() parameters

What's missing:

  • Unions
  • Subclassed structures
  • POINTERs
  • Arrays
  • Probably lots of other stuff…

It does work for simple functions, like so:

from ctypes import *

libc = cdll.msvcrt

i = c_int()
f = c_float()
libc.sscanf("1 3.14", "%d %f", byref(i), byref(f))

Download the DLL. Drop the DLL in the "DLLs" directory of your IronPython 2.6 installation (create it if it doesn't exist).

Huge thanks to Seo Sanghyeon for the original FePy implementation (written in Python – I'm still not sure rewriting in C# was a good idea) and Curt Hagenlocher for providing me with the code to generate types on the fly. If you want to check out the source, go to my hg repository. As always, the code is under the MS-PL.

UPDATE: It turns out ctypes will be part of IronPython 2.6 (not based on this code, but a completely different implementation).

Sunday, March 29, 2009

NWSGI 1.1 Preview 1

A preview of NWSGI 1.1 is now available on Codeplex. This preview is linked against IronPython 2.6a1 so that I can start testing against 2.6 with enough lead time to actually get any bugs fixed before release :). There are also some enhancements to the configuration that can simplify some common scenarios; see the release notes or changes.txt for more information. I'll write up more detailed instructions on how to take advantage of those changes in the future.

Monday, February 16, 2009

IronPython in Action

IronPython in Action is an upcoming book from Manning Publications by Michael Foord and Christian Muirhead. It describes the intersection of the .Net Framework and IronPython with a large number of examples, covering a reasonably large swath of the .Net Framework: WinForms, WPF, ASP.NET, Silverlight, XML processing, and more.

IronPython in Action is exactly what it says on the tin: this book is a large collection of real-world(ish) examples showing how the .Net Framework can be used in conjunction with the Python language. To go with this book, I'd recommend a Python language reference and a reference for whichever .Net technologies you are working with. This book doesn't try to by the definitive reference for either Python or .Net; it focuses on the intersection of the two. For the most part there is very little mismatch between the two; C# (or VB) can be translated into Python and everything will (mostly) work fine.

The first part of the book gives a very quick overview of the history of Python, .Net, and IronPython; this is followed by a brief introduction to the Python language and how to access various .Net features (classes, enums, events, etc.) from IronPython.

The second part of the book is the creation of a simple WinForms application that is used to demonstrate some .Net framework classes and some Python design techniques and idioms. In particular, it covers the basics of WinForms programming and XML processing, along with some insights into patterns and unit testing in Python. The final chapter of this section (Ch. 8) covers Python metaprogramming and protocols, and some gory details about interacting with the CLR – in particular, arrays and reference parameters are tricky to use from the Python side.

Part 3 of the book covers a wide range of topics: WPF, systems administration, ASP.NET, database access, web services, and Silverlight. Again, none of these subjects are covered in detail – each could (and has!) fill a couple of volumes. Instead, the authors focus on getting everything going and covering some of the issues that may come up. The ASP.NET demonstration is particularly clever as it is simply a recasting of the example editor from Part 2 as a web site; the WinForms code had to be swapped for WebForms code, but none of the rest of the code (the controllers and the model) had to be changed. The database section uses PostgreSQL as the  database target; the only major difference to SQL Server would be the connection string (and some edge cases in the SQL).

The final section of the book covers embedding and extending IronPython. It is a nice, simple introduction to building a C# (or VB) IronPython extension, followed by demonstrating how to embed the IronPython engine into a .Net program. The embedding section, in particular, has some tricks that are hard to learn otherwise – the functionality is a bit spread out, and the current documentation is only passable. Thankfully, Ch. 15 will be unnecessary (or at least very different) with C# 4.0.

I wasn't really sure what to expect when given this book. Having read it, I now see that it is exactly what it says it is – IronPython, in action. For any serious work with IronPython (more than just using it as an alternative Python interpreter), than this book will save you a ton of learning time. The examples are clear, concise, and – most importantly – realistic. Even if you already know Python and .Net inside and out, but are new to IronPython, this book will save you some headaches learning about how they interact.