Recently I have started developing an application using the excellent Python web framework web2py. Web2py comes with its own a web-based integrated development environment that makes it easy to write small web based applications from within your browser. However once you start developing something bigger you will want the convenience of a real IDE. Code completion, multiple open files and a debugger will all make the experience more comfortable. However due to web2py’s mode of operation your IDE will require some additional help from you to allow its full powers to blossom.
Web2py’s mode of operation
Contrary to other Python web frameworks, such a Django, web2py doesn’t use Python’s import statement to load your code. Instead it executes your code using Python’s built in function execfile and supplies it with a prepared environment that contains a number of global objects that are central to web2py’s programming model (e.g. request, response, session objects, HTML helper functions, etc). This also means that your IDE has no knowledge of these objects and functions unless you explicitly tell it about them.
Informing your IDE about web2py’s prepared environment
Even though I use Eclipse/PyDev, the trick to let any Python aware IDE know about these objects is the same. In fact I got the idea from the How-To Using Wing IDE with web2py.
From the IDE’s point of view there are two types of files that it requires additional information about:
- models
- controllers
Simply adding import statements for the global objects and functions web2py is going to provide us with at runtime might cause unforeseen problems. Hence we need to import them conditionally.
For models adding the following snippet of code at the top will suffice:
if 0:
from gluon.sql import *
from gluon.validators import *
For controllers the following will do:
if 0:
from gluon.globals import *
from gluon.html import *
from gluon.http import *
from gluon.sqlhtml import SQLFORM, SQLTABLE, form_factory
session = Session()
request = Request()
response = Response()
How does this work? The conditional 0 will always evaluate to False. This means that at run-time the statements following the if statement will never be executed. It’s dead code and hence will never interfere with whatever web2py has setup for us in its prepared environment.
It’s different for the IDE. The Python parser that’s part of your preferred Python IDE only parses your code. It does not evaluate it as Python does. As such it has to take the possibility into account that it might be executed at some point in time and that other code might depend on it. It has to read in the imports and consequently has all the information needed for code completion. Your IDE is now aware of web2py’s prepared environment