Python Server Pages (PSP) provides the capability for producing dynamic web pages for use with the Webware WebKit Python Servlet engine simply by writing standard HTML. The HTML code is interspersed with special tags that indicate special actions that should be taken when the page is served. The general syntax for PSP has been based on the popular Java Server Pages specification used with the Java Servlet framework.
Since the Webware WebKit is analogous to Java Servlets, PSP provides a scripting language for use with it that includes all of the power of Python. You will find that PSP compares favorably to other server side web scripting languages, such as ASP, PHP and JSP.
Features of PSP include:
The PSP for Webware project is fully open source. Help in all areas is encouraged and appreciated. Comments should be directed to the Webware Discussion mailing list. This is a relatively low volume list and you are encouraged to join the list if you wish to participate in the development of PSP or Webware, or if you plan on developing an application using the framework.
Directives are not output into the HTML output, but instead tell the PSP parser to do something special. Directives have at least two elements, the type of directive, and one or more parameters in the form of param="value" pairs.
Supported Directives include:
The page directive tells the PSP parser about special requirements of this page, or sets some optional output options for this page. Directives set in page apply to the elements in the current PSP source file and to any included files.
Supported Page parameters:
The format of this directive is as follows:
Example<%@ page imports="sys,os"%>
The value of the imports parameter may have multiple, comma separated items.
from X import Y is supported by separating the source package from the object to be imported with a colon (:), like this:
Example <%@ page imports="os:path" %> This will import the path object from the os module.
Please note the = sign used in this directive. Those who are used to python might try to skip it.
Example <%@ page extends="MyPSPBaseClass"%>
This is a very powerful feature of PSP and Webware. The developer can code a series of Servlets that have common functionality for a series of pages, and then use PSP and the extends attribute to change only the pieces of that base servlet that are specific to a certain page. In conjunction with the BaseMethod page attribute, described below, and/or the <psp:method tag, entire sites can be based on a few custom PSP base classes. The default base class is PSPPage.py, which is inherited from the standard WebKit Page.py servlet.
You can also have your PSP inherit from multiple base classes. To do this, separate the base classes using commas, for example <%@ page extends="BaseClass1,BaseClass2"%>. If you use a base class in <%@ page extends="..."%> that is not specifically imported in a <%@ page imports="..."%> directive, the base class will be assumed to follow the servlet convention of being in a file of the same name as the base class plus the ".py" extension.
Example - <%@ page method="WriteHTML"%>
Standard methods are WriteHTML, of the standard HTTPServlet class, and writeBody, of the Page and PSPPage classes. The default is writeBody. However, depending on the base class you choose for your PSP class, you may want to override some other method.
Example - <%@page threadSafe="yes"%>
valid values are "yes" and "no". The default is "no".
Example - <%@ page isInstanceSafe="yes"%>
Valid values are "yes" and "no". The default is "yes".
Example - <%@ page indentType="tabs"%>
This is a bit of a tricky item, because many editors will automatically replace tabs with spaces in their output, without the user realizing it. If you are having trouble with complex blocks, look at that first.
Example - <%@ page indentSpaces="8" %>
Example - <%@ page gobbleWhitspace="No"%>
Valid values are "yes" and "no". The default is "yes".
Example
<%@ page imports="MyUtils" %>
<%@ page formatter="MyUtils.myFormatter" %>
The include directive tells the parser to insert another file at this point in the page and to parse it for psp content. It is generally no problem to include an html file this way. However, if you do not want your include file to be parsed, you may use the <psp:include tag described below.
Example - <%@ include file="myfile.txt"%>
The expression tag simply evaluates a python variable and inserts its text representation into the HTML response. You may include anything that will evaluate to a value that can be represented as a string inside the tag.
Example - The current time is <%=time.time()%>
When the PSP parsing engine encounters Expression tags, it wraps the contents in a call to the python str() function. Multiple lines are not supported in a PSP expression tag.
The script tag is used to enclose python code that should be run by the WebKit Servlet runner when requests are processed by the Servlet which this PSP page produces. Any valid Python code can be used in Script tags. Inside a script tag, indentation is up to the author, and is used just like in regular python. (More info on blocks below) The PSP Engine actually just outputs the strings in a Script tag into the method body that is being produced by this PSP page.
Example
<% for i in range(5):
res.write("<b>This is number" + str(i) + "</b><br>")
%>
The Python code within script tags has access to all local and class variables declared in the PSP page, as well as to all variables of the enclosing class of this PSP page.
Special local variables that will be available in all PSP pages are:
req | the HTTRequest object for this page | |
res | the HTTPResponse object for this page. The HTTPResponse object includes the write method that is used to output HTML to the client. | |
trans | The Transaction object for this client request. The Transaction object provides access to the objects involved in servicing this client request. |
Python Code Blocks that span PSP Script Tags
The Python code structure, which uses whitespace to signify blocks of code, presents a
special challenge in PSP pages. In order to allow for readable HTML code that does not impose
restrictions on straight HTML within PSP pages, PSP uses a special syntax
to handle Python blocks that span script tags.
Automatic Blocks
Any script tag with Python code that ends with a colon (:) is considered to begin a block. (a
comment tag may follow the colon). After this tag, any following HTML is considered to be part
of the block begun within the previous script tag. To end the block, insert a new script tag with the word "end" as the only statement.
Example of Script/HTML block
<% for i in range(5): %>   #the blocks starts here, no need for indenting the following HTML
<tr><td><%= i%></td></tr>
<% end %> The "end" statement ends the block.
These blocks can be nested, with no need for special indentation, and each script tag that only contains a solitary end
statement will reduce the block indent by one.
Manual Blocks
It is also possible to force a block of HTML statements to be included in a block. You might want to do this if your start a loop of some kind in a script tag, but need the first line of the loop to also be inside the script tag. In this case, the automatic indenting described above wouldn't notice the block, because the last line in the script tag wouldn't be a ":". In this case, you need to end the script tag with $%>. When a script tag ends with $%>, the PSP Parser will indent the following HTML at the same level as the last line of the script tag. To end this level of indentation, just start another script tag. Easy.
Example of Manual Indention Script/HTML block
<% for i in range(5):
          icubed = i*i $%> ##The following lines of straight HTML will be included in the same block this line is on
<tr><td><%= icubed%></td></tr>
<% pass %> ##Any new script statement resets the HTML indentation level
You could also start a new script block that just continues at the same indentation level that the HTML and the previous scipt block were at.
Braces
PSP also supports using braces to handle indentation. This goes against the grain of python, we know, but is useful for this specific application. To use this feature, specify it as you indentation style in a page directive, like so: <%@page indentType="braces" %>
Now use braces to signify the start and end of blocks. The braces can span multiple script tags. No automatic indentation will occur. However, you must use braces for all blocks! Tabs and spaces at the start of lines will be ignored and removed!
Example
This is <i>Straight HTML</i><br>
<%
for i in range(5): { %># Now I'm starting a block for this loop
z = i*i
%>
<!-- Now I'm ending the scripting tag that started the block,
but the following lines are still in the block -->
More straight HTML. But this is inside the loop started above.<br>
My i value is now <%= i %><br>
Now I will process it again.<br>
<%
v = z*z
%>
Now it is <%=v >
<% }% > # End the block
The Method tag is used to declare new methods of the Servlet class this page is producing. It will generally be more effective to place method declarations in a Servlet class and then have the PSP page inherit from that class, but this tag is here for quick methods. The Method tag may also be useful for over-riding the default functionality of a base class method, as opposed to creating a Servlet class with only a slight change from another.
The syntax for PSP methods is a little different from that of other tags. The PSP Method declaration uses a compound tag. There is a beginning tag <psp:method name="methname" params="param1, param2"> that designates the start of the method definition and defines the method name and the names of its parameters. The text following this tag is the actual Python code for the method. This is standard Python code, with indentation used to mark blocks and no raw HTML support. It is not necessary to start the method definition with indentation, the first level of indention is provided by PSP.
To end the method definition block, the close tag </psp:method> is used.
Example
<psp:method name="MyClassMethod" params="var1, var2">
import string
return string.join((var1,var2),'')
</psp:method >
This is a silly function that just joins two strings. Please note that it is not necessary to declare the self parameter as one of the function's parameters. This will be done automatically in the code that PSP generates.
A PSP:Method can be declared anywhere in the psp sourcefile and will be available throughout the PSP file through the standard self.PSPMethodName(parameters) syntax.
The include tag pauses processing on the page and immediately passes the request on the the specified URL. THe output of that URL will be inserted into the output stream, and then processing will continue on the original page. The main parameter is path, which should be set to the path to the resources to be included. This will be relative to the current page, unless the path is specified as absolute by having the first character as "/". The path parameter can point to any valid url on this WebKit AppServer. This functionality is accomplshed using the WebKit Application's forwardRequestFast function, which means that the current Request, Response and Session objects will also be used by the URL to which this request is sent.
Example - <psp:include path="myfile.html" >
The insert tag inserts a file into the output stream that the psp page will produce, but does not parse that included file for psp content. The main parameter is file, which should be set to the filename to be inserted. If the filename starts with a "/", it is assumed to be an absolute path. If it doesn't start with a "/", the file path is assumed to be relative to the psp file. The contents of the insert file will not be escaped in any way except for triple-double-quotes ("""), which will be escaped.
At every request of this servlet, this file will be read from disk and sent along with the rest of the ouput of the page.
This tag accepts one additional parameter, "static", which can be set to "true" or "1". Setting this attribute to true will cause the inserted file's contents to be embedded in the PSP class at generation time. Any subsequent changes to the file will not be seen by the servlet. (This was the default behavior prior to PSP 0.4).
Example - <psp:insert file="myfile.html" >
Copyright 2002 Webware Development Team
Some architectural aspects of PSP were inspired by the Jakarta Project.