What is callable?

Jun 23, 2009 at 5:16 PM

Can you provide a quick sample on how to use Callable? I have the vaguest idea on what it is and how it works. I've read the readme.txt but they went way over my head.

Coordinator
Jun 24, 2009 at 12:33 AM

Are you using 1.0, 1.1, or 2.0?

Jun 24, 2009 at 9:27 AM

The latest 2.0.

Coordinator
Jun 24, 2009 at 11:43 PM

I agree; callables aren't particularily well documented, and most of what I have makes too many assumptions. I apologize if some of this is review; I plan to turn this into a blog post soon, so I'm writing in "blog-mode" :).

--

Callable Objects

In Python, callable objects are anything that can be, well, "called". In this case, "called" means "can have () after it". Functions and methods are the most common callables; in Python classes are callable, and any instance of a class with a __call__ method is also callable. If you've used C++ and overloaded operator() (so-called functors), this should seem familiar.

WSGI Applications

The WSGI sepcification describaes a WSGI application as a callable taking two arguments and returning and iterable (I'm not going to go into the details on iterable). For example:

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']

Now, this has simple_app as a a function, but it doesn't have to be. It could also be an instance of a class defining __call__; it could even be a class itself that implements the iterator protocol (thankfully, you don't see that very often).

NWSGI callables

Let's say you want to deploy the sample app above, and it's in a file called simple.wsgi in your application root:

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

Because the sample doesn't use "application" (the default, by convention), NWSGI needs to know what the name of the callable is so that it can call it and run the application.

Advanced Callables

This is all well and good, but we don't necessarily have to create a .wsgi file for every application. Most applications (f.e. Trac) provide a suitable application function already; why not use it directly?

<pythonPaths>
    <path path="C:\trac" />
</pythonPaths>
<scriptMappings>
    <scriptMapping scriptName="trac.wsgi" callable="trac.web.main.dispatch_request" />
</scriptMappings>

If you provide a dotted path to callable, it will try to import the module ("trac.web.main") and run the callable ("dispatch_request"). This removes the need for a .wsgi file at all.

That leaves the last common case: an application class that defines __call__. In this case, NWSGI needs an instance of the class to work with, so there's a handy shortcut:

<pythonPaths>
    <path path="C:\django" />
</pythonPaths>
<scriptMappings>
    <scriptMapping scriptName="django.wsgi" callable="django.core.handlers.wsgi.WSGIHandler()" />
</scriptMappings>

Notice the "()" at the end: this tells NWSGI to create an instance of the WSGIHandler class and use the instance as the WSGI application. This is limited to classes that take no arguments only.

End

I hope that helps. Let me know if there's anything that's still not clear, or where th wording could be improved, etc.

Jun 25, 2009 at 10:47 AM

How does this scriptmapping affect the url request?

So using your example above, scriptName="trac.wsgi", does it mean that I have to call /tract.wsgi to have it executed or will it become a default responder to any /xxx/xx.wsgi or /y.wsgi request.

And what happens if you have multiple scriptmappings? How do you divide which request handled by which script.

 

 

 

 

Coordinator
Jun 25, 2009 at 6:30 PM

Yes, the scriptName becomes part of the URL. For example, http://example.com/trac.wsgi/<whatever>.

If you have multiple scriptMappings, each one becomes a spearate path. You could, for example, have http://example.com/trac.wsgi/<whatever> and http://example.com/django.wsgi/<whatever> be valid by using two scriptMappings (not that it necessarily makes much sense, but it's possible).

If you want to get rid of the trac.wsgi URL wart, there are two options: use a wildcard mapping (must be configured on the server and using the <wildcard> element) or use URL rewriting. The second will probably be faster most of the time, but good URL rewriting on IIS 6 is more difficult (on IIS 7, there's no reason to use the wildcard option).

The physicalPath and callable attributes on the <wildcard> element have the exact same meaning as on <scriptMapping>. Also, you cannot use both wildcards and script mappings in the same application.