AOLserver Python API

Release 0.6 of PyWX uses SWIG to provide Python access to almost all of the C API routines exposed by AOLserver. By this mechanism, almost all of AOLserver's facilities can be used straight from Python without going through a layer of Tcl. Advantages:

To use the Python API, import the Ns extension module into your Python script with "import Ns".

The primary reference for this API is AOLserver's C API documentation, because most of the functions, classes, and methods that are available in Ns have direct equivalents in the C API.

However, the interface has been given an object-oriented flavor, so the correspondence between the C API and the Python API is not entirely trivial. The following guidelines should help translate from C/C++ to Python.

  1. The prefix "Ns_" has been removed from function and structure names because it is redundant with the module name. Example:

    C/C++Python
    Ns_Set *conn = Ns_GetConn(); conn = Ns.GetConn()
    Similarly, "NS_" has been removed from the names of constants. Exception: The function Ns_Fatal() is called Ns.Ns_Fatal() because otherwise its name would have conflicted with that of the Fatal enum value.

  2. The important C structs have been wrapped as Python classes:

    C/C++Python
    Ns_Set Ns.Set
    Ns_Request Ns.Request
    Ns_Conn Ns.Conn
    Ns_DbHandle Ns.DbHandle

    Constructors and destructors have been provided where needed. The main access functions have been wrapped as class member functions, with the name of the class removed from the member name. For example, to work with an Ns_Set:

    C/C++Python
    Ns_Set *set = Ns_SetCreate("name");
    Ns_SetPut(set, "foo", "foovalue");
    char *value = Ns_SetGet(set, "foo");
    Ns_SetFree(set);
    set = Ns.Set('name')
    set.Put('foo', 'foovalue')
    value = set.Get('foo')
    del set
    [Actually, del set is not necessary; "owned" objects are freed automatically by calling the appropriate C API function when their Python reference counts go to zero.]

    Finally, Python-style `magic' functions have been added where appropriate. Examples:

    C/C++Python
    n = Ns_SetSize(set) n = len(set)
    Ns_SetPutValue(set, 2, "foovalue") set[2] = 'foovalue'
    Ns_SetUpdate(set, "foo", "foovalue") set['foo'] = 'foovalue'
    value = Ns_SetValue(set, 2) value = set[2]
    value = Ns_SetGet(set, "foo") value = set['foo']
    Ns_SetDelete(set, 2) del set[2]
    Ns_SetDeleteKey(set, "foo") del set['foo']

  3. Functions in the C API that return the status value NS_OK/NS_ERROR have been wrapped as Python functions that do not return anything but raise an exception if there is an error. Example:

    C/C++Python
    int retval = Ns_ConnFlushContent(conn);
    if (retval == NS_ERROR) {
        /* error occurred */
    }
    
    try:
        conn.FlushContent()
    except RuntimeError:
        # error occurred
    
    I/O-related C functions raise an IOError exception; others raise RuntimeError.

  4. C functions that take Ns_DString arguments as input have been wrapped as Python functions that take normal Python strings. Similarly, C functions that write their outputs in a Ns_DString pointer are wrapped as functions returning a python string. In fact, the Ns_DString structure is not even exposed in the Python API because it is not needed--conversion happens automatically whenever it is required.

    For C routines that have two version--one taking an Ns_DString and another taking a char *--only the former is wrapped for the Python API. The reason is that the Ns_DString version allows data containing NULLs.

  5. Functions that store their return values into a pointer argument have been wrapped as Python functions that omit that argument and instead return the result as the function's return value. A couple of functions that need to return two values return them as a tuple. Examples:

    C/C++Python
    Ns_DString s;
    Ns_QuoteHtml(&s, "Text&text");
    
    s = Ns.QuoteHtml('Text&text')
    
    int nrows;
    Ns_Set *set;
    set = Ns_Db0or1Row(
        dbhandle,sql,&nrows);
    
    (set,nrows) = dbhandle.Db0or1Row(sql)
    
    [Note that the Python name of Ns_Db0or1Row doesn't follow the usual convention because "0or1Row" is not a valid Python identifier.]

  6. C functions that allow a format string and a variable number of arguments have been wrapped as functions that take just a single string argument. Instead use Python's "%" formatting operator. Example:

    C/C++Python
    Ns_Log(Notice, "%d bytes", n);
    
    Ns.Log(Ns.Notice, '%d bytes' % n)
    

  7. The `compatibility macros' and functions listed as obsolete have not been wrapped.

  8. Python callback functions have not been implemented yet. Thus, functions dealing with callbacks are not yet available in the Python API.

If you need more information about the Ns module and the Python API, try looking at the source code--especially Ns.swig, which contains the SWIG interface file and lots of comments about interface details, and Ns.py, which contains sketchy Python definitions for the functions and classes. If all else fails, ask for help on one of the PyWX mailing lists, or contact Michael Haggerty (the author of the SWIG interface).

It is likely that there are still bugs in some of the wrapping functions, since only a small fraction of the API functions have been tested. (There are about 400 of them!). Please reports any bugs you find to the PyWX mailing list.