Blog

The braces being finished.

The braces being finished.

Braces being built to hold shelves in the room downstairs. 37 braces for 9 12’ shelves and 5 4’ shelves.

Braces being built to hold shelves in the room downstairs. 37 braces for 9 12’ shelves and 5 4’ shelves.

So, we had a little bit of a storm the other day. Nothing spectacular, or so I thought. There were a few limbs down here and there, and then I got home:

Lucky.

It’s a boy.

It’s a boy.

Thoughts on Blocks

Or: How I Learned to Stop Worrying and Love the NIH

I’ve been interested in a few things lately with respect to web applications. The first is Seaside and its approach to stateful control flow through the use of continuations. Since I’d like to work in Python, continuations are not possible, but we do have something equally interesting, microthreads via Stackless Python.

The other is the fact that I have a lot of good, useful code already written to perform logic on data that I’d love to reuse in web applications. The problem is that most available frameworks enforce, to varying degrees, their own views on data modeling. Don’t get me wrong, the available web frameworks for Python are all very high-quality and useful in their own right. They’re just not always the best solution to the problems I’m trying to solve.

So, what I’ve set out to do is to create a lightweight framework that uses Stackless Python for control flow between discrete objects that function losely as the Controller in an MVC-like architecture. These objects can form a tree, with parents, children, and siblings, with state being preserved for that object no matter how the user finds their way to it.

It can be a little mind-bending at first, and it’s taken me a while to get my mind wrapped around it (assuming I actually have at this point), but I think I have the functional basis for a framework based on these ideas. I’m uncreatively calling it Blocks. Here’s an example I’ve written for the API documentation that may help to illustrate the basic ideas:

>>> import random
>>> from blocks.content import Block
>>> class IntegerInput(Block):
...     def validate(self, request, num):
...         try:
...             number = int(request.parameters.get("num"))
...         except ValueError:
...             return self.render(request)
...         else:
...             return number
...
...     def render(self, request):
...         self.callback('validate')
...         number = self.respond('''Enter a number!
...             <input type='text' name='num'/>''')
...         self.answer(number)
...
>>> class GuessTheNumber(Block):
...     def render(self, request):
...         secret_number = random.randint(1,100)
...         guess = self.call(IntegerInput(), request)
...         if guess == secret_number:
...             return "Yay! That's correct!"
...         return "Sorry, that's wrong."

This is a fairly simplistic number guessing game. The GuessTheNumber block passes control to another block that takes an integer input and returns it to the original block once its been received. The original then decides whether the guess was correct or not, and informs the user accordingly. This could be expanded to have the GuessTheNumber block loop until the user correctly guesses.

Because the content blocks are fairly generic (all they need is a ‘render’ method that returns something to give to the user), they can be exceptionally flexible in using existing code, data models, etc. Now, we can lay a few layers on top of that to get some nice templating, generic functionality, and more, but none of that is necessarily required.

I’m working on a couple of applications based on Blocks which will hopefully help me iron out any problems, bugs, design flaws, etc. Once I’m reasonably satisfied it’s possible to write something useful with Blocks, I’ll release it. Until then, I’ll probably get some introductory info up on its web page at Water-Powered Ideas, but I wanted to quickly describe what I’ve been working on for the past few months.

We have a Rachel.

We have a Rachel.

Loading C Plugins for PureDocs

I finally had a chance to sit back down with PureDocs, after getting the build process straightened out, and figure out how to load C plugins. Turns out, it’s pretty simple with ctypes. Let’s imagine I have a C library, compiled and linked as libtest, containing the following (a simple modification of my original example):

#include <stdio.h>
#include "puredocs.h"

Resource * test_function() {
    Resource * r = puredocs_createResource("foo");
    Resource * c = puredocs_createResource("bar");

    puredocs_setDocString(r, "omg some docs lol");
    puredocs_setDocString(c, "some bar docs omg lol");

    puredocs_setProperty(r, "feh", "omg");

    if ((puredocs_addChild(r, c)) < 0) {
        printf("OH NOES!\n");
    }

    return r;
}

This function can easily be called when loading the libary with“ctypes“’s PyDLL type (won’t release the Python interpreter’s GIL, which is important if we’re creating Python objects we want to use). The restype of the function needs to be set toctypes.py_object, since we’re returning a Python object. The whole process looks like this:

>>> from ctypes import *
>>> t = pydll.LoadLibrary("libtest.dylib")
>>> t.test_function.restype=py_object
>>> r = t.test_function()
>>> r
<Resource foo [<Resource bar []>]>

The whole point of this exercise is basically to make it possible to write C libraries that serve as plugins for PureDocs that don’t necessarily have any knowledge of Python. They’ll be linked against a PureDocs library that provides the glue-code. So, for PureDocs’s purpose, I now just need to wrap this around some library loading and registration code, and we’ll be ready to go!

Peanut thumbing her nose.

Peanut thumbing her nose.

Building PureDocs, Redux

After much trial and tribulation with Pyhton’s distutils and setuptools, I decided it wasn’t really appropriate to be building a C library with the Python tools. While the capability exists in distutils, it’s pretty obvious that it suffers from some pretty substantial code rot.

So, I’ve gone the autoconf route. I didn’t really want to, but really there’s no better solution that I can find that doesn’t involve setting PureDocs aside while I start yet another project.

In any case, the autoconf’ing isn’t complete, and it doesn’t quite work, but I’ve committed what I have so far. Once I get it all working well on multiple platforms, I’ll finish off the C API. Then Kate should be able to add some C-based plugins using the SID parser generator.