Yann's Blog - Software and hardware

August 8, 2011

History loaded to Github

Filed under: Hardware,Other Stuff,Python,Software,StackFoundry — Yann @ 9:39 pm

I’ve loaded a part of my back-catalog of software to github. Included into the transfer is:

  • an old Python application server (Cymbeline)
  • an audio player library (PyAudioPlay)
  • a project which combines the two (Shallot)
  • and even a very minimal NTP replacement (SNTS)

Note that this software is from the 2004 vintage, which reflects a previous era (before Git, before the end of college, etc). It was languishing on the StackFoundry website prior to its overhaul; I also couldn’t simply throw it away.

Also loaded onto github are slightly newer projects, such as:

  • the static site generator qsgen
  • a movie file browser (quick movie)
  • the ptee process/subshell tee augmentation
  • and finally an X11 keyboard wedge program for barcode readers (softwedge).

Most of the previous pages at StackFoundry now redirect to the appropriate github page.

Enjoy!

November 29, 2009

qsgen 0.2 available

Filed under: Python,Software — Yann @ 12:15 am

qsgen now is at version 0.2. There aren’t any new features, but some critical issues preventing installation with newer versions of setuptools has been fixed.

qsgen is a Python static website generator which uses Mako and Pygments. Its used to build the web content for the main StackFoundry page, along with TropicSSL and EntropyKing. Its “perfect” in that it does its job without fuss and configuration :)

January 22, 2009

yyafl 0.2.1 is now available

Filed under: Python,Software — Yann @ 9:59 pm

yyafl, a Python web form library operating on domain objects, now has version 0.2.1 available for download. This release includes numerous fixes for decorators, including the ability to attach multiple decorators to a form field or the wildcard ‘*’ field.

An example is given below, in the context of a CherryPy handler. This example is available in the download as

examples/layout02.py
import cherrypy
import yyafl
import yyafl.layout
from yyafl import fields
from yyafl.widgets import HiddenInput
 
# This example covers the user of custom decorators for required form fields
 
class Form1(yyafl.Form):
    name = fields.CharField(label = "User name", required = True)
    email = fields.CharField(label = "Your e-mail address", required = True)
    optional = fields.CharField(label = "Optional field", required = False)
    hidden = fields.CharField(widget = HiddenInput, default = "123")
    _layout = yyafl.layout.TableLayout()
 
class RequiredDecorator(yyafl.layout.NullDecorator):
    """ Draw a * next to all required fields """
    def extra_markup_widget(self, field, rendered_text):
        if field.required:
            return rendered_text + " * "
        return rendered_text
 
class FormTest(object):
 
    @cherrypy.expose
    def index(self, **kwargs):
        f = Form1(data = kwargs)
        # Add a global decorator
        f.layout().add_decorator('*', RequiredDecorator())
        content = ""
        content += "<html><body>"
 
        if f.is_valid() == False:
            content += "Errors: "
            for error in f.errors:
                content += error + " : " + f.errors[error] + "<br />"
        elif f.is_bound() and f.is_valid():
            content += "Thanks for the data!"
 
 
        content += "<p><form method=\"GET\" action=\"/\">"
 
        # Render using the layout specified in _layout above.
        content += f.render()
        # Or invoke the layout explicitly
        # l = yyafl.layout.TableLayout()
        # l.render(f)
 
        content += "<br /> <input type='submit' value='Submit' /></form>"
        return content
 
 
if __name__ == '__main__':
    cherrypy.quickstart(root = FormTest())

January 7, 2009

yyafl version 0.2.0 available for download

Filed under: Python,Software — Yann @ 12:56 am

Version 0.2.0 of Yann’s Yet Another Form Library is now available for download. I have been using this code in product for at least a month and felt it is pretty stable. You can grab it from the main site at stackfoundry.com or from the PyPI page.

yyafl is a partial reimplementation and adaptation of the Django ‘newforms’ library allowing it to exist outside of the Django infrastructure. It can be used in other frameworks such as CherryPy and Pylons. YYAFL provides:

  • Pluggable and skinnable forms, use either pure Python code or a compatible templating engine (such as Mako). Attach on the fly decorators (such as the ubiquitous red star to required form fields) or even apply whole layouts to forms.
  • Default properties can be added to the form object – for example, a default rendering layout can be chosen.
  • Comprehensive validation framework for many data types (which is easy to grow, similar in style to newforms)
  • Comprehensive widget collection, which is easy to grow, tweak, or extend for your application’s needs. (currently doesn’t support multi-widgets well, this wart will be fixed soon however)
  • Soon! Automatic CSRF managed forms – pass it a session store object and it can handle the rest by preventing cross site requests.

YYAFL uses some large chunks of the form-model and metaclass system that newforms used, and as such uses the same license as Django. Work is being done to refactor portions of this code to add some flexibility for multi-widget data fields (such as Date being split amongst several form fields), which were somewhat unclean in Django’s implementation.

September 29, 2008

yyafl now has layout support, with decorators

Filed under: Python,Software — Yann @ 11:35 pm

Just finished adding in a flexible layout system to yyafl, my reimplementation of Django newforms for other Python web frameworks or WSGI adapters. Now its simple to add default layouts or render a different layout on demand.

For example, to add a simple TableLayout() to a form:

class Form1(yyafl.Form):
    name = fields.CharField(label = "User name", required = True)
    email = fields.CharField(label = "Your e-mail address", required = True)
    hidden = fields.CharField(widget = HiddenInput, default = "123")
    _layout = yyafl.layout.TableLayout()

and to render the form to HTML:

# Render using the layout specified in _layout above.
content += f.render()
# Or invoke the layout explicitly
l = yyafl.layout.TableLayout()
content += l.render(f)

yyafl Layout()s also understand decorators:

decorators = { '*' : MarkRequiredDecorator(),
    'name_field' : HighlightDecorator() }
layout = yyafl.layout.TableLayout(decorators = decorators)
layout.render(f)

Decorators can change attributes and wrap fields in markup blocks. In the above example, the ‘*’ signifies the decorator should apply to all fields, and the HighlightDecorator should only apply to the field called ‘name_field’.

There are still some not yet implemented ideas:

  • It doesn’t generated the <form> blocks yet, you need to roll your own.
  • Field reordering and grouping isn’t supported by the default layout engines yet, though you could write your own.
  • No AJAX form support (though its coming!)
  • Automatic CSRF prevention forms.
  • Error message printing in the form.

You can find these latest changes in the Git repository linked from the main yyafl web page.

September 24, 2008

Why I Use CherryPy, in someone elses words

Filed under: Python,Software — Yann @ 10:03 pm

With the popularity of Django or Rails, people have asked before why I use CherryPy. The reason is simple, I love the flexibility. I get to pick what I want to use inside, CherryPy simply worries about how to get the information to a web browser. I found this post to be a good overview of the strengths of CherryPy. Give it a good read. I completely agree with the author’s points, and wish CherryPy would get a bit more attention in the do everything web-framework era.

August 13, 2008

qsgen – The Quick Site Generator – Version 0.1 Released

Filed under: Python,Software — Yann @ 11:53 pm

qsgen, the single-script static web-site generator has just hit the first release, version 0.1.

In short, qsgen is a pure Python functional wrapper around Mako templates and the Pygments library. It lets you build a hierarchical set of .html pages and associated base templates using Mako, which will be transformed into static pages for serving on the web. In addition, it also includes support for Pygments syntax highlighting in-line with the HTML or even with source code sourced from separate files.

I’m using qsgen on both www.stackfoundry.com and tomeapi.com. If you feel making a dynamicaly scripted website just in order to display some simple content is silly, or feel the complexity and headaches of a true CMS system outweigh the benefits, then qsgen is for you.

(qsgen is very similar to a similar script called Maehan which I was using for many years. Consider qsgen a more feature packed and cleaner version of the old Perl Maehan).

July 19, 2008

Using Facebook’s Thrift with Python and HBase

Filed under: Python,Software — Tags: , , — Yann @ 1:25 am

Today I’m going to show you how to interface Python to Apache HBase using Facebook’s Thrift package. Hbase is a documented oriented database which is very similar to Google’s BigTable (in fact its more or less a clone of BigTable as seen in the BigTable paper). HBase has two primary interfaces – a REST API which is relatively slow, and a Thrift interface, which is recommended for high speed communication. For speed and other reasons, we’re going to be using the Thrift API.

Note that I am going to be touching on some Hbase jargon (such as column families). Its not essential to understand what those are if you are just trying to build a Python Thrift client. But if you’re trying to use HBase, I would consider that knowledge essential.

Getting Setup

First thing’s first, you need need to grab a copy of both HBase and Thrift. For this tutorial, I am using the Subversion copy of HBase (as of July 18th) and Thrift version 20080411p1. Thrift is shipped as a source package, you will need a compiler toolchain, as well as any Python development packages or header files your system may require (such as python-dev on Debian/Ubuntu). You’ll also need the Java JDK package (such as sun-java6-jdk on Ubuntu).

Thrift can be compiled using the standard routine:

./configure
make -j4
sudo make install

After installing thrift, you should have a system-wide ‘thrift’ command available, which should provide some usage information. Thrift uses a descriptor file for the communication layer, available as a .thrift file. I’m not going to describe how to create such a descriptor file here (perhaps in a later blog post), as we’ll be using the one provided by HBase (with one small tweak). You will need the HBase source package for this exercise.

Build a Thrift Client Package

Open up [hbasesrc]/src/java/org/apache/hadoop/hbase/thrift/Hbase.thrift in your favorite text editor. Search for lines containing ruby_namespace, and add the following line in the same region:

namespace py hbase

(Alert readers will wonder why we didn’t use py_namespace. The reason is simple, the xxx_namespace Thrift commands are deprecated, replaced with namespace xxx).

Next up, we’ll generate our Python HBase thrift interface. Fire up your shell to the same location, and run

thrift --gen py Hbase.thrift

Now we have generated a set of Python classes in the gen-py folder which will allow you to talk to the Hbase thrift server automatically. Lets setup our Python Thrift server now. I’ll grab the hbase folder inside of the gen-py folder, and move it to a project directory of your choosing.

Building a Client

Next up, we’ll need to work on the Python Thrift client application. I suggest starting with the Thrift server tutorial for a boilerplate template. Below is the file we’re going to use (lets just assume it is called client.py for this discussion):

#!/usr/bin/env python
import sys
 
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
 
from hbase import Hbase
from hbase.ttypes import *

This is general Thrift boilerplate. The application specific portions up to now are the last two lines. Hbase is the name of the service as described in the Hbase.thrift file.

Next up, we’re going to try to connect to our HBase instance. To do that, we will first create a TSocket, then add a TBufferedTransport over the raw socket, and then wrap that in a TBinaryProtocol. If someone has studied too much Java, it was the Thrift developers ;) .

# Make socket
transport = TSocket.TSocket('localhost', 9090)
 
# Buffering is critical. Raw sockets are very slow
transport = TTransport.TBufferedTransport(transport)
 
# Wrap in a protocol
protocol = TBinaryProtocol.TBinaryProtocol(transport)

Now two application specific lines – we’re going to build a Hbase.Client() object, and then finally open up our transport.

client = Hbase.Client(protocol)
 
transport.open()

We can do a quick validation pass now, and start up Hbase (if you have a running Hbase server somewhere, you can omit this step of course). If you have a source checkout of Hbase, compiling is as simple as running the ant tool. Assuming you have the JDK installed, Hbase should be ready for action in under a minute. Start up a master Hbase instance by running bin/hbase master start &. Then, start up a thrift server for Hbase, by running bin/hbase thrift start.

Running our client script now should lead to no errors. If it does, stop, and try to figure out what is wrong (did you move the gen-py/hbase directory to where your client.py script is or set the python path appropriately?).

Using the Client

Lets call our first method: getTableNames(). Add this to the end of our script:

print client.getTableNames()

By default, it will simply print a blank list ([]), unless of course you have created tables. This is the simplest example of using Thrift with HBase and Python, where no special data structures are needed or passed around. But if we look at the HBase Thrift API (not up to date – for full details look at the Hbase.thrift file), we can see some methods will require parameters in the form of Thrift structs.

Lets try to create a table in Hbase. When we consult HBase.thrift, we can see it requires a list of ColumnDescriptors.

  /**
   * Create a table with the specified column families.  The name
   * field for each ColumnDescriptor must be set and must end in a
   * colon (:).  All other fields are optional and will get default
   * values if not explicitly specified.
   *
   * @param tableName name of table to create
   * @param columnFamilies list of column family descriptors
   *
   * @throws IllegalArgument if an input parameter is invalid
   * @throws AlreadyExists if the table name already exists
   */
  void createTable(1:Text tableName, 2:list columnFamilies)
    throws (1:IOError io, 2:IllegalArgument ia, 3:AlreadyExists exist)

Luckily, the thrift compiler has generated a Python class for this ColumnDescriptor (which we acquired by importing hbase.ttypes.*). Sadly, this isn’t the most Python of all classes, but will be quite serviceable for our needs. Lets build a ColumnDescriptor for a column-family called foo. For Hbase, we need to specify the column family in the name: format – so don’t forget that colon, or you will be faced with an IllegalArgumentException.

desc = ColumnDescriptor( { 'name' : 'foo:' } )

Note that there are many more fields you can use. Either consult the Hbase.thrift file or the hbase/ttypes.py file for details.

Now we’re ready to create our table!

client.createTable('our_table', [desc])
 
print client.getTableNames()

Running this script should yield a [] followed by ['our_table']. Now we have a table in Hbase! Congratulations!

Handling Errors

If you run the script again, you’ll notice that you get an exception since the table name is already in use. This is of course expected, but also highlights Thrift’s ability to propagate exceptions from the remote system.

Exceptions must be predefined in the .thrift interface file. For the case of the createTable method, there are three possible exceptions. Catching them is much like any other exception. Here is our program, changed to catch the AlreadyExists exception:

try:
    desc = ColumnDescriptor( d = { 'name' : 'foo:' } )
 
    client.createTable('our_table', [desc])
 
    print client.getTableNames()
 
except AlreadyExists, tx:
    print "Thrift exception"
    print '%s' % (tx.message)

Note specifically the presence of the message attribute. The Thrift compiler doesn’t generate a nice __str__ or __repr__ method for Python exceptions, so in many cases to determine the exact cause of the error, you need to grab the message attribute.

Wrapping Up

Before this turns into an exhaustive documentation of the HBase Thrift API, I’m going to put a close on this post :) . I hope this short example will help you with using Hbase and Python, and combining Hbase and Thrift. In a future post, I will touch upon how to create a Python Thrift server, and define your own Thrift interface file.

June 30, 2008

anyvcs: Python library for version control systems

Filed under: Python,Software — Yann @ 11:29 pm

What if you had a high-level library in Python for driving revision control systems and their working copies?

Well, anyvcs to the rescue! Or, as it stands today, not yet. There isn’t much code to go around with anyvcs yet – it only works with Git and can’t do much beyond tell you the version or what the latest commit ID is on a branch. But thats exciting right?

You can look at the source for anyvcs here and clone it via

git clone git://stackworks.net/anyvcs.git

The high level goals for this project include:

  1. Simple backend for most distributed VCS operations, such as checkout, branch, apply patch, reset, etc
  2. Targets primarily git and mercurial, or other VCSes which operate in a similar manner. Subversion isn’t a likely first target for instance, nor is bzr (though we would like to support both eventually).
  3. Provide a comprehensive wrapper for Git commands via a Python library. If some of the functionality doesn’t end up in the core anyvcs abstraction, anyvcs.git will provide some VCS specific operations.

There is a great reason for this project – but I won’t reveal everything just yet.

April 3, 2007

Announcing IRM 2, MkIII

Filed under: IRM 2,Java,PHP,Python,Software — Yann @ 4:13 pm

I’ve done a lot of thinking, some non-thinking, talking to people, users, and some (well ok, a lot) of prototyping. As a result of all that work, I have decided to revive and continue to work on a new IRM 2, the re-architectured Information Resource Manager application. New features, new code base, but same target, you, the dedicated IRM users.

I’ll get into all the details of what IRM 2 is going to do for you, but I’d first like to share some history with you about where IRM has come from, the previous short attempts at IRM 2, and how its influenced my current direction.

In the beginning was the command line.

Then came IRM. It was quite literally the second piece of software I wrote as a web application. It used the trendy new (well at the time) PHP 3.0. MySQL 3.22 was the in thing. The whole LAMP architecture was just in its infancy.IRM was created way back when (1999 for those keeping score) for my high school. It allowed people to post problems (using the odd nomenclature “Tracking”) about computers that were in its database. The database seed script that comes with IRM reflects these early beginnings, including the computer named Ants and the Library Back Room.IRM went through several versions, 0.5, 0.9, 0.9b, 0.9c, etc. Around the 1.0 release, a really great guy from the University of Tulsa , Keith Schoenefeld started contributing to IRM. He cleaned up a ton of my early major misguided attempts at software development (turns out ENDIF; is kinda not cool), and over time provided new functionality such as the FAQ and Knowledgebase system.

IRM grew in leaps and bounds, adding the Software subsystem, the Reports subsystem, and then Networking. Patch submissions from Mica Curie also started, and some key features were added to the project.
In 2004-2005 another contributer joined the project, Matt Palmer. Not only did he make a nice Debian package for IRM (apt-get install irm is so much easier :) ), he allowed for the full translation of the IRM source. Version 1.4 and then 1.5 were released under his guidance. By that time I had started full time at UC Davis, so my time was becoming slim catching up with all those college things. Matt graciously took up the maintainer role for IRM 1.5 and released several versions, culminating in 1.5.8-dev, the current recommended version (or 1.5.7 for the squeemish).

During all of those time, I became increasingly dissatisfied with the PHP structure that IRM was running on. Its underpinnings were still dating back from 1999, PHP 3.0 code, strange code reuse, no abstract templating, and a fixed database structure. In 2002 I attempted a partial rewrite of IRM called IRT (Information Resource Tracker) in a custom mod_perl framework (the job I had at the time was developing a custom mod_perl application for footagesearch.com – still used to this day, though its had numerous updates). It failed miserably. I can’t even find the source code.

Next up was IRM 2.0 in Python. It included some new ideas for abstract schemas and relational linking. Its asset manager actually worked. It was developed in a custom Python application server Cymbeline, which was probably a bad move as I was spending more time developing Cymbeline than IRM 2. This also fell by the wayside during those college years. But it was a great learning exercise in what worked and what didn’t.

And thats the history in a summary. If you were a contributor (I know I left a bunch out, especially when I was not active maintainer :( ), let me know and I’ll add you to the history :)

Since working on IRM, my life has changed a lot. I graduated high school (yes, IRM is that old), graduated college, and got a good “real job.” More importantly, I’ve built lots of real software in between, for personal use, research work, as well as commercial contract work. I’ve been around the block a few times, and tried on a large number of hats, all of which will reflect themselves in the design and implementation of IRM 2.


So, that gives us IRM 2, Mk III. The third incarnation of IRM2. And better, more powerful, and very different from the rest. Read on.

To begin, its still a web application. IRM is never going to be solely a desktop application, though the line between web application and desktop application is really blurring these days.

It utilizes Java. I can already hear the complaints trickling in. I’ve grown quite fond of Java at my day job, and really recognized what strengths it brings to the enterprise web application front. The Sun Java VM is now also Open Source, with the rest of the classpath libraries becoming Open Source in the near future. There are multiple Java vendors, and Java does really run everywhere these days. Java is also very quick, and the framework provided with it are top-notch. A considerably worse choice would be to move to .NET and ASP.NET.

It utilizes Enterprise JavaBeans 3.0 . These are not the EJBs of 2.0 and 1.0 days, which were, to put it mildly, horrible. EJB3.0 is actually a joy to work with, and brings with it an amazing amount of functionality, such as transactional support, security, and scalability.

It utilizes the Java Persistence API 1.0, along with Hibernate when the JPA doesn’t go far enough. Both of these technologies are wonderful to use, and greatly speed development (and makes maintenance much easier).

For the presentation layer, Apache Tapestry won out over other packages such as Struts2, JSF, and Spring. While I prefer to use Java Community standards whenever possible, I compromised for Tapestry as it is a wonderful (though not well known) package.

All of this can successfully run in the JBoss Application Server, making deployment a snap on any platform. It can also be run in any mostly-EJB3.0 compliant container, though drop-in portability will not be a focus of the first releases. By utilizing Java Persistence, we will automatically support any JDBC compliant database server, from good old MySQL, Oracle, PostgreSQL, Microsoft SQL, DB2, to the built in HSQLDB.

I am working on a master roadmap which lays out our development cycles and sets goals. Look here in the next few days for updates on how its going to look.

In short, IRM 2 will feature:

  • The asset manager interface from PythonIRM2. User definable schemas for any device, item, location, or thought you can think of. Fully linkable schemas let you associate users, software, locations, peripherals, and potted plants together into an AssetMeshtm. Since everything is associated in real life, why not let your asset manager let you express that?
  • Trouble ticket system to manage user problems, your own problems, and let you keep your head on straight. Includes both user ticketing, technician ticketing, and phone support ticketing.
  • User self help system, bringing back the FAQ, user trouble reporting, and other features which made IRM into such a successful integrated application for the IT helpdesk.
  • And more!

To bright futures ahead, but remembering the beginnings…

Powered by WordPress