be Groovie

Viewing posts for Code

Aug 12 2005

Switched to Typo and some MT3 to Typo Migration Notes

So tonight I took the plunge, and converted the blog to Typo. It’s totally slick, and I’m digging it. Plus when I want to tweak stuff, I don’t have to mess around with Perl.

It’s currently lacking a feature I had grown accustomed to, Technorati auto-pinging. I’m thinking this would be a good thing to contribute, so I’ll start digging into the code and see what needs to be updated.

Migration was also a bit of a hassle, as it appears the MovableType 3 migration script only is happy if you use MySQL for your old and new blog. Getting it migrated to Typo required dumping the MovableType database using pg_dump, and loading it into the Typo database. Then the mt3.rb script needed to be edited to remove all the table prefixes. After this, the script happily imported all my prior posts, comments, and trackbacks.

Tags: Code Ruby Rails
Comments
Aug 11 2005

Explaining Recursion to a Non-Programmer

I was going on a walk the other night with my wife, and I think she noticed my far off expression and silence. She asked me what I was so thoughtful about, and I admitted my brain was a bit stuck on solving a complex algorithm involving recursion. At that point she asked me what recursion was, she’s very smart, just not a programmer. So I figured there must be some way I could explain recursion without referring to code, syntax, functions, etc.

Here’s the little explanation I came up with on a moments notice:

Let’s say we have a guy named Joe. Joe has some problems and special abilities.

Joe has the neat ability to make temporary clones of himself, when they’re done doing what he asks them, they disappear in a puff of smoke. Joe unfortunately has issues with math. If you hand him a basket of apple’s, he couldn’t tell you how many apples are in the basket, just seeing all those apples at once confuses him.

If you tell Joe a number though, he can easily add 1 to it. So you tell Joe, “Hey, if someone gives you a basket of apples, take one out, clone yourself, and hand the basket to your clone. If the basket is empty after taking the apple out, tell the one that created you there’s 1. When you get a number from the clone you made, add 1 to it, and tell that to the clone that created you.”

Since Joe’s clones know what he knows, they all know these directions as soon as Joe clones himself. So you proceed to hand a basket of 3 apples to Joe.

Joe takes one out, and hands the basket of 2 apples to his clone. Clone 1 takes an apple out, and handes the basket of 1 apple to a new Clone (Clone 2). Clone 2 takes out the apple, sees there’s no more left, and tells Clone 1, “Hey, there’s 1”. Clone 1 adds 1 to it, and tells Joe, “Hey, there’s 2”.

Joe adds 1 to this, and tells you, the basket has 3 apples in it.

You can hand Joe a basket of however many doodad’s as you want, and he’ll happily keep cloning himself until sooner or later a clone takes out the last doodad.

After this little story, you should be able to explain that:

  • A Terminating Condition is when Joe should stop cloning himself
  • Joe is recursive because he clones himself and repeats the task

If anyone else out there has a more elegant or shorter way to explain recursion to a non-programmer, I’d love to hear it. This story could also set you up to explain such fun concepts as tail-end recursion or the difference between truly recursive functions and one that could be easily re-written in a loop. I’ll leave that to someone else to translate to non-computer speak.

Tags: Code
Comments
Aug 08 2005

Porting Routes from Rails

I’ve begun porting the Routes system from Rails over the last weekend. It’s definitely been a good brain workout, as the one Nicholas Seckar wrote that drives Rails is quite a brain-fuck. His version actually does quite a bit of code generation based on the routes one sets up. At first I tried to do a fairly direct port of the Ruby code behind this to Python, but my brain just couldn’t wrap itself around what he was doing (He’s told me that quite a few others have said the same).

This left me kind of discouraged, and I left the project (more of a thought at that point) alone and proceed to replicate most of Rails ActionMailer in Python instead. Partly because I liked how ActionMailer assembled mail, and partly because after hearing a talk by Alex Martelli on Metaclasses and other Python “black magic” I just had to find some excuse to use a metaclass.

Why not just use Rails?

Now, before anyone starts yelling “Just use Rails!” at me, I should explain something. I am using Rails, and I rather like it. However, most companies wouldn’t be too thrilled with their employee’s changing the entire codebase of the company every year when the latest, greatest, way to write webapps comes along. Plus, since I already use Python extensively, a lot of stuff that makes life pleasant in Rails-land can be fairly easily adopted to Python-land.

Do I really want to re-write 5k or more lines of Python libraries in Ruby just so I can use Rails? Should the entire web team learn a new language and framework just because its a bit better than the current way? The time spent doing all this wouldn’t be paid off for at least a year or more, if that (and maybe some other language+framework will be the new thing by then). When it comes down to normal Python libraries, I don’t save any lines of code by moving to Ruby. So in the end, it makes sense to adopt part of Rails that make my life easier.

In Case You Didn’t Know

The Routes system from Rails is used by Rails in a lot of functions. Virtually all functions that require a URL to be written (url_for, link_to, form_tag, etc) all use the Routes system to figure out what URL to put in place.

In the Python world, as far as I know (and I’ve looked quite a bit), there is absolutely no web framework that will convert from controller/action -> URL.

Update (9/26/05): Phillip J. Eby rightfully pointed out that other Python web frameworks can do this. I should’ve been more specific in that none of them operate in this manner. Since putting word out about Routes I also found out Aquarium can designate routes for dispatch/generation in this manner, however Aquarium cannot do automatic route lookup to find the shortest URL. This ends up hard-coding the template URL to the route.

Plenty of web frameworks are happy to convert a regular expression into a dispatch command and let you tweak it (Myghty, Django, etc.) but they are all helpless if you want to generate a URL from the commands they used to dispatch.

Progress

Currently, I have URL generation (controller/action -> URL) and URL recognition (URL -> controller/action) working and passing all the tests that I’ve ported over from the Rails route testing. Since my version of Routes is independent of the framework, its my hope that multiple Python web frameworks will be able to incorporate the finished Route system I’m building. The URL -> controller/action results in a dict, that the web framework can choose to deal with as it pleases.

The first framework I plan on integrating this with is Myghty as the resolver system is fully user-customizable, no hacking on the framework source is needed to plug it in. The dispatch model will then follow Rails and make the same decisions for the user (controller goes in appdir/controllers/, name_controller.py, etc.) that Rails does.

Once I add a few more tests, and try and clean up my code some, I’ll put it out there. I’m considering a BSD license right now, in the meantime, here’s a sample:


>>> from routes import Mapper
>>> m = Mapper()
>>> m.connect('page/:id', controller='content', action='show_page', id =1)
>>> m.connect(':controller/:action/:id')
>>>
>>> m.generate(controller='content',action='index')
'/content'
>>> m.generate(controller='content', action='show_page')
'/page'
>>> m.generate(controller='content',action='show_page',id=4)
'/page/4'

Speed

My implementation choice was to rely heavily on the speed of set operations using the built-in set/frozenset functions in Python 2.4. Under Python 2.3 the sets module provides an ImmutableSet which I’ve also tested my port with. I was actually quite impressed with how fast the sets module is in 2.3, but there is a three-fold speed increase using Python 2.4 built-in sets.

Even under 2.3 the speed should be more than sufficient for most applications, plus, this is a first revision of the code. I’d hardly expect it to be the peak of efficiency right now.

What’s Missing

I currently haven’t implemented memory of the match that got to the current page. Rails does this so if you’re inside a template that was matched by ‘post/show/20’ and you call link_to :id => 30 it would give you a url of ‘post/show/30’. It does this by remembering the match that got you there. Since this match would be setup inside the web framework, I’m considering how to implement it without tying one to a specific framework.

The other noticeable feature missing is Named Routes which act as a sort of macro on top of the normal url generation calls. This shouldn’t be too tough to add at a later point.

Parting Thoughts (ala Jerry Springer)

Before you submit some comment saying I’m an idiot for porting this and should drink more Ruby kool-aid, don’t, please. I’m already drinking it, and it tastes quite good. But just because I like Ruby, doesn’t mean my taste for other languages has changed. Languages have their strong points, and they have things they lack (Yes, they both lack some things). When I’m writing Python, my web framework of choice is so very close to perfection for me, Routes is one of those things that would make it that much sweeter.

If you’re interested in adapting this to your Python web framework and want to start playing with the code I have so far, send me an email and remember boys and girls, be safe.

Tags: Python Code Rails
Comments
Aug 05 2005

Making Decisions for Others

Please Note: Reading the last post would help greatly for this one, and this post does end up comparing aspects of Django with Rails in terms of making decisions rather than actual usage.

As I mentioned in my last post, Rails has been greatly helped by the decisions it makes for you. It decides the layout of your application directory, the directories you put stuff in, where you put what parts, etc. These decisions thankfully were done by someone familiar with good application design and had most likely even read Martin Fowler’s Refactoring to Patterns.

What results is a clean, well thought out application that you didn’t even need to think out very much. Before you know it, you fall into these useful and powerful design patterns without even thinking about it (I’d hope you would at least, they’re good patterns for a reason).

A lot of web frameworks make the assumption you are familiar with these patterns already, will setup your application to follow them, and use them in a way that makes sense. Part of the reason for this is because some web framework developers are rather appalled at the thought of making these decisions for the framework user. To be making those decisions for the framework user is looked at as holding their hand, and typically the programmers who write frameworks don’t need any hand holding and don’t expect their users to either (I’m assuming this based on the frameworks I’ve tried).

For example, during Ian Bicking’s test run with Rails he noted that having such a directory hierarchy setup for him put him off a little and mentions people arguing about file layout. I’ve seen very little, if anyone else, even comment on the directory structure that Rails lays out for you. The other irony of this particular post is that a lot of the stuff Ian finds “wrong” about Rails is actually Ruby’s “fault” (Implicit passing of names, mix-in’s, etc.). But moving on….

Ian clearly doesn’t want to lay down the law for users of his software, neither do other Python web framework developers. Having choice in how you lay out your application, with no clear direction what goes where, is considered a good thing. I don’t think there’s anything wrong with this approach, if the users you’re aiming your framework at are expected to be experienced, professional, programmers that are quite familiar with web applications and what works best for them. This does mean the audience will not be that large, and I think thats clearly reflected in the small communities most Python web frameworks have. While their communities are small, I’ve found them to be highly skilled and you get great answers to questions on their respective mailing lists.

The one Python web framework that has almost overnight gone from hardly any users, to at least a few dozen (probably more, but even a few dozen is quite good for a Python web framework), is Django. Django makes a lot of decisions for the user, more so even than Rails by a pretty good amount. While Rails was designed as a web application toolkit, and extracted form a large webapp, Django is designed more as a CMS web application toolkit as its been extracted from newspaper-style web sites. Thus, many of the decisions Django makes for you assume you will want users, user-access to the database objects, etc.

The question is, if someone else is making decisions for you, how important is it that they be good decisions?

One of the decisions the Django team made originally irritated me quite a bit. The Django framework is probably about 95% MVC in nature. It has database files that clearly are acting as Models (which it calls models), logic oriented files traditionally called Controllers (that it calls views), and template files that display the results to the user in a typical View role (though Django calls them templates).

The FAQ on the Django site notes that if you squint, sure enough the observations I just made do pop out, however because of the 5% non-MVC I mentioned they decided the names didn’t work. Rather than calling them by what they obviously were (or closest to), they swapped around names in a way that I think is bound to confuse Django programmers when they go into a real MVC environment and tell someone they edited the view when in fact it was the controller. If they had come up with completely different names that didn’t relate to the MVC paradigm at all, I think that would help to avoid later confusion on the part of a Django user.

Despite the naming of these parts, the decision made for the user is clearly for a MVC-style (or influenced) environment which I think is great ( please change the naming! ;) ). So what is the point of this whole thing?

I think its a good thing for developers of toolkits and especially frameworks to make some more decisions for the end-programmer of their work. This makes it easier for not so experienced programmers to get started quickly, and if you’re using a good design pattern even the experienced dev’s wont have anything to complain about. The two frameworks that currently are getting a lot of attention make a lot of decisions for the programmer using them, and this definitely increases the user-base (assuming you want a large user-base). Even though I know good practices on laying out stuff, it makes my life that much easier when its done for me.

Comments
Aug 02 2005

Dissing Programming Langauges…

A friend recently brought to my attention that I seem to have a knack for insulting a language based on a quick overview without actually getting into it. After thinking about this awhile I’ve noticed it definitely seems to be more of a trend than I’d like.

The latest example of this was Ruby, but before that Python (Lisp before that). With each language, I’d find new things to nitpick on before really diving in (Which I always seemed to do anyways). As a result of this, I think its time for me to really grow up and stop picking on new languages till I’ve at least had the time to write a few apps in them and truly understand where they’re lacking.

As a quick side-note, here are the things I found to nitpick on before actually learning these languages:

  • Objective-C: God, wtf is up with these [] all over the place?
  • Lisp: God, wtf is up with these () all over the place?
  • Python: God, wtf is up with these _____ all over the place, and who in their right mind uses white-space to designate blocks?
  • Ruby: God, wtf is up with these {|| } things all over the place?

Obviously I had issues with syntax, I hope to have purged myself of these issues as of this writing. Remember, sometimes a language has a damn good reason to have crazy characters all over the place.

Comments
Jul 05 2005

The Myghty Python Web Framework

Myghty is a powerful web application framework that builds on the strengths of Perl’s Mason using my favorite language, Python. While Myghty also handles page templating, it has some very powerful features that make it a full fledged framework in my opinion.

Wondering if Myghty is something you should check out?

I would highly recommend looking into Myghty if you’re looking for any of the following:

  • Clean, unobtrusive templating language for integrating Python data and HTML
  • An easy way to write pages that inherit their look/feel without needing .include statements
  • Re-usable code that you can carry from one project to the next
  • MVC programming paradigm , or page-driven paradigm (Myghty doesn’t care, it can be anywhere in between as well)
  • Advanced caching ability, tunable to just the time intensive sections of a page
  • Run as WSGI, FCGI, SCGI, mod_python, or stand-alone with hardly a single change to your code (to switch between them)
  • Architecture that scales, from a single developer’s personal project, to a multi-developer’s company website

History

Myghty first came into existence a little over a year ago when Mike Bayer looked around at the Python web application frameworks and couldn’t find one that really sucked him in. Having used Mason for various projects, but not finding anything as elegant as it for Python he decided to port Mason to Python.

This ported code was based on the Perl code almost line by line, resulting in a Python web application framework that worked almost exactly like Mason, except with Python as the base language. It wasn’t very long before Mike started adding to Myghty, such as Module Components, and threaded features not found in Mason.

Terms Used

MVC – Model, View, Controller paradigm is typically used to describe an approach that separates the code in these 3 steps rather than mingle them all in one place. Model usually refers to the database and its abstraction, the Controller handles the logic of dealing with the request, getting the data from the Model, and passing it to the View for display to the user.

Component – A component in Mason is what a template is known as. A template might display a full web-page, just one small section, or send data to other components. Components typically correspond to files on a filesystem, and appear as normal HTML pages with a few lines of Python in them, although they’re far from normal HTML pages…

Resolver – Used to describe the process of determining what to do with a given URL. Myghty has some incredible flexibility here.

Distinctive Features

Module Components

In Python, your modules contain all your Python code. In Myghty, the Component contains a mixture of Python with HTML. To handle a MVC approach to development, Myghty has Module Components. These are a cross of a Myghty Component with a Python Module, that leaves you with a fairly normal Python Module. It’s called directly from Myghty in a similar way to how Myghty would call a Component. These Module Components can be explicitly defined in the configuration, or called implicitly.

The Module Component allows you to directly handle URL’s, and respond from within the Module by sending data back to the client or processing data then sending it on to a normal Component for processing. Module Components work within the Resolving process, and have control passed to them according to a configuration mapping . The mapping uses regular expressions to match URL’s to modules that contain the method to be called, like so:


module_components = [
    {r'myapplication/home/.*' : 'myapp.home:HomeHandler'}, 
    {r'myapplication/login/.*' : 'myapp.login:LoginHandler'}, 
    {r'.*/cart' : 'myapp.cart:process_cart'}, 
    {r'.*' : 'myapp.home:HomeHandler'} 
]

This would map the URL http://yourapp/myapplication/home/blah to the HomeHandler component class, in the home module file, under the myapp package. The method in the HomeHandler class called can be done in two different ways, implicitly, or explicitly. For more details on this, read the Myghty docs on Module Components

While other frameworks implement an MVC approach, Myghty’s goes a step farther by letting you tie it into the resolution options used by the Resolver, and even use your own resolvers…

Advanced Resolver

In version 0.97alpha2 (maybe a better naming scheme could be used? :) the resolver implementation was heavily rewritten to allow massive flexibility in how a URL is handled. When Myghty handles a request, it goes through a fairly complex process to determine what to do with it. This is called the default strategy:

  1. Translate the URL against the path translation options – This can act as an internal URL rewriting scheme, changing a URL to be handled differently
  2. Resolve a dhandler – This rule matches conditionally. It is only called if the rules under it don’t find a match, it then strips off part of the URL its looking for and adds dhandler. So a search for /article/view/38 becomes a search for /article/view/dhandler if 38 isn’t found. Read more about dhandlers
  3. Check the URI Cache – The URI cache is searched for the incoming URI at this point, to see if a component has matched it before. This rule is also executed on a conditional basis.
  4. Upwards Search – The 3rd conditional rule of the bunch, this rule is called during inheritance when a component searches parent paths for an autohandler. Read more about autohandlers
  5. Resolve a Module – Matches a Module Component to the incoming URI.
  6. Resolve a File – Matches a file under the component roots specified for a match to the incoming URI. This will directly call a Myghty template file on the system in response to a URL.

As soon as any of the non-conditional rules matches, the file or module component method is served up. Myghty gets an additional speed boost by keeping compiled versions of all your template files around, so that they’re only compiled the first time they’re called. By using the basic Python way of compiling the templates as .pyc files, it also ensures that they’re re-compiled the second you update one of them. This way you’re always sure you’re viewing the latest update of your template.

So where’s the real power in all this?

These are just the default rules. They can be completely, and utterly customized. You can switch the order around, you can remove resolver rules entirely, and you can even write your very own resolver rules.

Maybe you’ve decided you want to serve some of the components from a database instead of the file system. You could write a custom resolver rule that does just that, and loads the entire component from the database as well. You could write your own version of the Path Translate module to get its rewrite rules from a database table. As if this wasn’t powerful enough, Myghty also lets you have different resolver strategies for different contexts.

Conclusion

Myghty is a very powerful web framework. It has features that go beyond any pure “templating” language I’ve encountered. If you’re not quite happy with what you’re using right now, or something I described above makes you giddy with thoughts of power, maybe its time to take Myghty for a test drive.

In future posts, I’ll describe more of the features I use daily in Myghty, and share code tidbits that let you get complex tasks done easily.

Comments
Jan 02 2005

Sending RSS items to Growl via AppleScript / NetNewsWire

A friend alerted me the other day to some useful sites for tracking packages via RSS. There’s one for FedEx and one for UPS.

While these are quite cool, and nice to have in NetNewsWire, the same friend told me its even cooler to have updates to the feeds sent to Growl. That way you get a nice little pop-up window when one of your packages has moved on.

He wrote a Python script that sent RSS updates over the LAN to Growl (Note: The Python script requires netgrowl.py). While that was cool, his method of adding feeds to watch (editing a text file on a remote machine) didn’t seem that cool. It was about that time that I started thinking, well, why not have Net News Wire manage the feeds? That is what its for after all… so I started looking to see how I could tie this togther.

Searching through ranchero.com quickly led me to a page on calling scripts as subscriptions. So I figure, if I write an AppleScript, that searches a NetNewsWire (NNW) folder for unread items then sends them to Growl via the Applescript interface, that should do the trick.

So without further ado, here’s my little Applescript, based on Brent Simmons Folder Watch example, that searches a NNW folder for unread items, sends them to Growl, then marks them as read.

Installing

GrowlRSS.scpt:

Download this where desired, add it as a script in NNW using the File menu -> New Special Subscription -> Script. Then locate the GrowlRSS script, it will then open the Show Info window. Expand the Script Settings option, and put the name of the NNW folder to watch as the Args. Close, and hit refresh, and it should send any unread items in that folder to Growl.

Caveat

You should have Growl 0.6 from svn installed. It’s possible it’ll work with 0.5, but I haven’t tested that.

Comments
Dec 18 2004

Fast CGI with HTML::Mason

I decided the other day for a variety of reasons, to switch from the mod_perl web-app style to using Fast CGI with HTML::Mason. I only found one application out there that uses Mason with Fast CGI, which was the RT Ticket tracking system. However, the way it was setup didn’t match my requirements, nor the way their handler was configured.

After scouring the Internet some more, I hobbled together a working config section for my Apache+mod_fastcgi along with a template for the mason handler. Since I haven’t seen anything going over these basic steps anywhere else, here’s how I did it.

First, the things you should have installed on your system (which I’m assuming is *nix):

  • HTML::Mason
  • CGI::Fast
  • Apache w/mod_fastcgi

Fast CGI runs your CGI application for you, and handles connections between your application, and the webserver. To configure your application, you just use one of the Fast CGI development kits for the response event loop within which your application will process requests.

Since we’re using Perl, there’s already a handy module available from CPAN that I chose to use called CGI::Fast. Then we just wrap our Mason call within a CGI::Fast loop to handle requests. This Perl script will be kept running persistently so that you get the advantage of not having to startup the Perl interpreter on every web page request.

Why Fast CGI instead of mod_perl?

  • You can use the connection feature of Fast CGI to run your app on a different machine than the webserver
  • Your application takes up only as much ram as Perl + your modules
  • It’s more portable, you don’t even need to use Apache, any webserver supporting Fast CGI will work
  • Less configuration files to maintain

Before showing my standard handler template, you should be aware of how I organize a Mason site using Fast CGI. Here’s what my directory structure looks like under the fictional GroovieWebapp:

  • GroovieWebapp/
    • site/
    • modules/
    • libs/
    • mdata/
    • mason-handler.fcgi

Site is where all of our Mason code (and images, css, etc.) is going to go. Modules is for putting any of your own Perl modules into that you made specifically for this webapp. libs for Mason libs, mdata for your Mason data dir, and finally the handler itself. This structure puts your whole webapp under one directory which is also useful under version control systems like Subversion.

Here’s what my standard handler template looks like (mason-handler.fcgi):


#!/usr/bin/perl
use FindBin qw($Bin);
use lib “$Bin/modules”;

use strict;
use HTML::Mason::CGIHandler;
use MIME::Lite; # Need this to e-mail the error

  1. Enter CGI::Fast mode, which should also work as a vanilla CGI script.

require CGI::Fast;

my $h;
my $show_error = 1; # Should we e-mail the error, or dump to the web?

if ($show_error) { $h = HTML::Mason::CGIHandler->new ( comp_root => [ [main => “/usr/local/www/GroovieWebapp/site”], [libs => “/usr/local/www/GroovieWebapp/libs”] ], data_dir => “/usr/local/www/GroovieWebapp/mdata”, allow_globals => [qw($Schema $Session)] );
} else { $h = HTML::Mason::CGIHandler->new ( comp_root => [ [main => “/usr/local/www/GroovieWebapp/site”], [libs => “/usr/local/www/GroovieWebapp/libs”] ], data_dir => “/usr/local/www/GroovieWebapp/mdata”, error_format => 'text’, error_mode => 'fatal’, allow_globals => [qw($Schema $Session)] );
}

  1. Setup our global vars for the request, preload our modules

{ package HTML::Mason::Commands; use Apache::Session::File (); # My favorite for session tracking use CGI::Cookie; # Also for session tracking use DBI; # It’s nice to load and establish our db connection in advance DBI->install_driver(“mysql”); # Put in whatever connection you use, etc. # This allows our $Schema variable to be accessed from anywhere in our Mason site our $Schema = DBI->connect_cached(“dbi:mysql:DB_NAME”,“DB_USER”, “DB_PASSWORD” ); }

  1. These two subroutines add Mason functionality that was lost by using CGIHandler instead
  2. of the ApacheHandler.

sub HTML::Mason::FakeApache::document_root { my $self = shift; return $ENV{'DOCUMENT_ROOT’};
}
sub HTML::Mason::FakeApache::param { my $self = shift; my $key = shift; my %args = HTML::Mason::Utils::cgi_request_args($self->query,$self->query->request_method); my @keys = (keys %args); if ($key) { return $args{$key}; } else { return @keys; } }
  1. For e-mailing the error

sub send_email { my $error = shift; my $cgi = shift; my $site = $cgi->virtual_host(); my $time = localtime; my $body = “————————————————————\n”; $body .= “———— ERROR OCCURRED\n”; $body .= “————————————————————\n”; $body .= “\n\n”; $body .= “WEBSITE INFO\n”; $body .= “Site: $site\n”; $body .= “Full URI Request: “.$ENV{'REQUEST_URI’}.”\n”; $body .= “Time: $time\n”; $body .= “\n\n”; $body .= “USER INFO\n”; $body .= “Referrer: “.$cgi->referer().”\n”; $body .= “User-agent: “.$cgi->user_agent().”\n”; $body .= “IP Address: “.$cgi->remote_host().”\n”; $body .= “Cookie info: “.$cgi->raw_cookie().”\n”; $body .= “\n\n”; $body .= “MASON ERROR\n”; $body .= $error; my $msg = MIME::Lite->new( From => 'YOUR SITE ', To => 'YOUR_EMAIL_ADDRESS’, Subject => “$site Mason Website Error occured at $time”, Data => $body, ); $msg->send('smtp’,'YOUR_SMTP_SERVER’); }

while (my $cgi = new CGI::Fast) { # the whole point of fastcgi requires the env to get reset here.. # So we must squash it again (This was copied from RT’s Fast CGI handler) $ENV{'PATH’} = ‘bin:/usr/bin’; $ENV{'CDPATH’} = '’ if defined $ENV{'CDPATH’}; $ENV{'SHELL’} = ‘bin/sh’ if defined $ENV{'SHELL’}; $ENV{'ENV’} = '’ if defined $ENV{'ENV’}; $ENV{'IFS’} = '’ if defined $ENV{'IFS’};

# The Mason $r->uri includes the script name unless we do this $ENV{'SCRIPT_NAME’} = '’; # This deals with someone entering yoursite.com/ to make sure it serves index.html if ( ( !$h->interp->comp_exists( $cgi->path_info ) ) && ( $h->interp->comp_exists( $cgi->path_info . “index.html” ) ) ) { $cgi->path_info( $cgi->path_info . “index.html” ); } #$cgi->header(-charset=>'utf-8’); # If your site uses utf-8 characters # Ping our db handle $HTML::Mason::Commands::Schema->ping; # Lets try and handle this… eval { $h->handle_cgi_object($cgi); }; # Something happened, if it couldn’t find the component, don’t fatal # we’ll re-process as a 404 if ($@) { if ($@ =~ /could not find component/) { # If you want Mason to handle the error so you can keep your site appearence, # this will call Mason to display your error page. If the error was in the # code that is called on every page, this will cause trouble. $cgi->path_info(’/errordocs/404.html’); $h->handle_cgi_object($cgi); } else { send_email($@,$cgi); } } }

This template has the option of either showing the Mason debugging output to the screen, or capturing the error, displaying a pretty 404 of your desire, and e-mailing you the error that occured.

Now for the Apache httpd.conf:


  1. Tell FastCGI to put its temporary files somewhere sane.

FastCgiIpcDir /tmp
  1. Increases processes if you have heavy loads to deal with

FastCgiServer /usr/local/www/GroovieWebapp/mason-handler.fcgi -idle-timeout 120 -processes 2

ServerAdmin webmaster@YOUR_SERVER ServerName YOUR_SERVER_NAME

AddHandler fastcgi-script fcgi ScriptAliasMatch (.*\.html$) /usr/local/www/GroovieWebapp/mason-handler.fcgi$1 ScriptAliasMatch (.*\/$) /usr/local/www/GroovieWebapp/mason-handler.fcgi$1 DocumentRoot /usr/local/www/GroovieWebapp

Restart apache, and check apache’s error_log to see that Fast CGI started up your application properly. Obviously, tailor these samples as needed. Another useful trick when running your webapp this way, is that if you kill the perl processes the apache Fast CGI process manager starts for you, it’ll re-spawn them. I find this a quick way to re-load individual webapps if I made changes to a module they’re using.

Enjoy!

Tags: Perl Code
Comments
Nov 26 2004

A Mason component to fill-in error messages

How often have you seen those sites with a form, and after you miss a field, it pops up a little message in red under the text box indicating what went wrong? I’m guessing a lot, and when writing web applications this can be a pain to code in.

Typically in Perl/PHP, you’d add this by going through your form, adding little bits of code under each and every form element to display the error on invalid input. I quickly got tired of this, and decided to simplify the process.

In examining HTML::FillInForm, I noticed I needed a slightly different tool to easily parse the HTML form. After a little bit of shopping about, I decided on HTML::Parser to do the heavy lifting. Here’s a snippet from a Mason page using my error_fill.mas component to toss in the error messages:


% if ($form_status eq 'errors') {
<&| /lib/error_fill.mas, errors => $errors_hash_ref &>
<p style="color: red; font-weight:bold;">Errors Found: Please correct the fields indicated.
<& /forms/myform.mas, %ARGS &>
</&>
% } else {
<& /forms/myform.mas, %ARGS &>
% }

$errors_hash_ref is a hash ref that is keyed by the form field name, with the value set to the error message you want displayed. Right now, error_fill.mas does not have custom pre/post-fix variables for you to tweak how the error message is inserted. It currently puts a <br> followed by a red span element containing your message.

myform.mas is the form I want to display, I prefer to split sections out in Mason to keep my web application modular and the sections of my pages more reusable.

Here’s error_fill.mas:




$errors
%args>
  1. $errors is a hash reference keyed as:
  2. 'field name’ > 'Error message’

use HTML::Parser;
my $form = $m->content;

my $p = HTML::Parser->new(api_version > 3);
$p->handler(default => sub { print _ }, "text"); $p->handler(end => sub { my ($tagname, $text, $attr) = _; if (($tagname eq ‘select’) && (exists $errors->{$attr->{name}})) { print $text; print ‘’; foreach my $err (@{$errors->{$attr->{name}}}) { print ‘
’.$err; } print ‘
’;

} else { print $text; } }, “tagname, text, attr”); $p->handler(start => sub { my ($tagname, $text, $attr) = _; if (($tagname eq 'input') && (exists $errors->{$attr->{name}})) { print $text; print '<span style="color:red;">'; foreach my $err ({$errors->{$attr->{name}}}) { print ‘
’.$err; } print ”; } else { print $text; } }, “tagname, text, attr”); $p->parse($form); %init>
Hopefully this will help some people out.
Tags: Perl Code
Comments
Nov 20 2004

XML-RPC interface for Growl

Growl is a rather spiffy little notifier for OS X I’ve started using lately. Currently however, it’s lacking a nice way to send messages over the network. Since a project I’m working on would be even slicker with a way to communicate updates, I quickly tacked a Python XML-RPC Server onto Growl using Growl’s Python bindings.

In the future, Growl will have its own network interface, I’ve heard. Until then, this does the job quite nicely.

Please note: You will need to install the latest svn of Growl, the PyObjC bridge, and have Xcode 1.5 to get this working. Everything in ALL_CAPS should be changed as needed, this also assumes you want to use icons and they’re in a myIcons dir.


#!/usr/bin/python

import Growl
import SimpleXMLRPCServer
from AppKit import NSImage
import sys, os.path

iconPath = 'myIcons/’
Icons = { 'MESSAGE_1’ : 'MESSAGE_1.tiff’, \ 'MESSAGE_2’ : 'MESSAGE_2.tiff’ }

class MemberFunctions: def init(self,Icons): gn = Growl.GrowlNotifier() gn.applicationName = 'YOUR_APP_NAME’ gn.applicationIcon = Icons['appIcon’] gn.notifications = ['MESSAGE_1’,'MESSAGE_2’] gn.register() self.gn = gn self.Icons = Icons

def notify(self, ntype, title, description, sticky): gn = self.gn Icons = self.Icons nIcon = Icons['appIcon’] if ntype 'MESSAGE_1': nIcon = Icons['MESSAGE_1'] elif ntype 'MESSAGE_2’: nIcon = Icons['MESSAGE_2’] gn.notify(noteType=ntype,title=title,description=description, icon=nIcon, sticky=sticky) return 1

def loadIcons(icons): global iconPath for icon in icons.keys(): filename = icons[icon] nImagePath = os.path.abspath(iconPath+filename) nIcon = NSImage.alloc().initWithContentsOfFile_(nImagePath).autorelease() if not nIcon: sys.stderr.write(“Couldn’t load file %s\n” % nImagePath) icons[icon] = nIcon return icons

Icons = loadIcons(Icons)

  1. Make our XMLRPC Server, create our instance, and assign it

server = SimpleXMLRPCServer.SimpleXMLRPCServer((“IP_TO_BIND_TO”, 7300))
memfun = MemberFunctions(Icons)
server.register_function(memfun.notify)

  1. Start the server

server.serve_forever()

If you’d like to see a running example of this, check out hellagrowler.py that this example is based heavily on.
Tags: Python Code
Comments
Page 1 of 6