Monday, August 20, 2012

Oh yeah, Ryan Davis is awesome

Found out about this talk from Ryan Davis at Cascadia RubyConf because of an incensed reaction to it from Giles Bowkett on his blog. Thing is, I like the talk. I even like the bits that Bowkett doesn't. Of course, I wasn't one of the folks specifically mentioned, and he was. So there's going to be a different perspective there. 

But I could have been. Heck, I tried my hand at cute ranty posts a few years back, and one of them threw what I thought was a light hearted jab at Ryan. But it really bugged him. He told me so the next time I logged into IRC, much later. I could see why it would when I looked back at the post and imagined it without context. The joke wasn't even that funny with context. Our posts on big or little blogs - or social networks, for that matter - have a reach far beyond what we might think when we're sitting at the keyboard. They can span the globe in a split second, and still be out there for years.

On revisiting the forgotten joke, I saw that it could be considered offensive if you weren't in the unique garden of my brain. I was really shaken by the fact that somebody I had such respect for (the guy is basically a genius in Ruby and other domains) had taken a lasting offense to something that I'd long forgotten about. So I cleared the post and got into the habit of checking myself before wrecking myself. 

I don't mind if someone somewhere thinks I'm a jerk. I want it to be for a better reason than me pretending to be an insult comic, though.

So, yeah. The guidelines mentioned by Ryan Davis for tending to the community are great, but it wouldn't do any harm to use them as guidelines for tending yourself. You know: "Don't be a dick!"


Monday, December 12, 2011

Testing G+ Connectivity

Um. Hey. Been a while. When did the Blogger editor get all awesome?

Anyways, I don't know how much I'll post here, as most of my thoughts fit comfortable in a G+ / Facebook / Diaspora post. But it's good to have the connection open.

Tuesday, April 19, 2011

The Spreadsheet Story 1: The General Idea

There is this spreadsheet project I have been working on. My wife works at a day shelter for homeless and formerly homeless women, as well as their children. At this shelter, they make use of an incentive point system. The ladies do some chore or favor, and they get points. There are preset ways to get points, with default values. Helping with the recycling gets this number of points, while putting chairs up gets that number of points. The points are just defaults, though. A client can get more or fewer than the default points depending on the situation. The staff can also create new chores or reasons for awarding points pretty much at their whim. A couple of times a week clients get the opportunity to spend those points in exchange for items.

It's a very popular program. Clients are constantly looking for ways to get more points, and asking what their point total is. Over the years, some clients have accumulated tens of thousands of points.

Tracking incentive points was a very tedious process involving punch cards, calculators, and the occasional mild profanity. I volunteered my geekiness to help come up with a better tracking system. I am mostly a Web programmer, so naturally my first impulse was a full-scale Rails, Django, or maybe even Catalyst Web application. Why not, right? It does sound like the perfect job for a CRUD framework:

  • Add and edit clients
  • Add and edit ways to get points
  • Log point changes for clients
  • Get the point total for any given client

There was just one tiny flaw in my proposal, which my wife was kind enough to point out: nobody would use it. The staff would prefer to keep things in a familiar framework, such as a spreadsheet. Spreadsheets are nice. They may not be the perfect choice for a database, but they do have a lot of built-in functionality that would take me forever to implement on my own.

Okay, I'm flexible. I made an Excel spreadsheet. I learned enough Excel to add some formulas and data validation rules. I even learned enough VBA to add some interactivity, reducing the tediousness a bit more. Well - reducing the tediousness for them. Not so much for me. Visual Basic is an interesting language, but I don't care for it.

What if I could use JavaScript? Google Apps Script uses JavaScript to add programming logic to spreadsheets and other documents. I don't know if it would be any easier than using VBA in Excel, but I know it would be more pleasant for me personally.

I have decided to go ahead and try it, now that the dust has settled on the Excel version. Hey - if it works well enough, they might actually use it. Regardless of whether it actually gets used, it'll provide a reasonable example of adding niftiness to a Google Spreadsheet. Somebody's bound to find that useful. Right?

The important thing is that I'll have some fun.

The Spreadsheet Itself

I can almost pretend this is a MVC application. The spreadsheet itself is the model layer, with each sheet representing a specific model. My knowledge of spreadsheets is incomplete at best, but the available formulas don't seem to provide the validation constraints that I'm looking for. It looks this will be what those in the know call a "fat controller" approach, with a disproportionate amount of the logic going into the scripting layer. That scripting layer, driven by Google Apps Script, will handle lookup and validation details. At least, it will until I figure out more about how Google Spreadsheets works. The scripting layer will also provide a view, insulating users from the worksheets by presenting dialogs for the most common tasks.

Yeah, I know. It's not really MVC. I have made a terrible analogy. But at least my terrible analogy has helped me divide the thing into logical components, rather than just looking at it as a spreadsheet with some scripts.

So. Let's look at the worksheets. I also made mock ups of the common task views, just for the fun of it.

People

Presents information about the clients that take part in the incentive program.

Name Used
The most common name used by this person. Must be unique. That's generally handled by including the initial of the last name or a nickname.
Full Name
The full name of the client, if available.
Other Names
Nicknames and aliases are common. Use this field to list any other known names for the client.
Starting Points
How many points the client had when the spreadsheet started being used. Nobody wants to lose their accumulated points, and this provides one way to differentiate it from points gained after. Could also be handy for importing, such as setting up different workbooks for different time periods.
Total Points
How many points this person has, after gaining and spending is taken into account.
Add Person Dialog

Categories

The different ways to gain and lose points. Pretty much a list of predefined chores and a couple of catchall buckets.

Name
A unique name for this point category, like "Wash breakfast dishes".
Default Points
Unless the user specifies otherwise, this represents the gain or loss in points for the client.
Add Category Dialog

Points Log

This sheet contains records of the actual transactions which affect a client's point total. It depends on the other worksheets for some of its information.

Person
Who gets the points? 'People'!'Name Used'
Points Category
What are they getting the points for? 'Categories':'Name'
Points
How many points are they getting? Based on 'Categories':'Default Points'
Date
When did they do whatever it was that got (or cost) them points?
Points Logger Dialog

What's Missing

There is no sheet to track inventory for items available in the incentive store. The items and their value vary too much for this to be a practical feature right now.

What Do I Have Now?

I have an incredibly dull spreadsheet.

What's Next?

I plan to spend the next few days - or weeks, depending on how much bloggy spreadsheet time I have - exploring Google Apps Script, particularly the Spreadsheet and Ui Services, in order to implement the dialog boxes I have so lovingly created mockups of. I will be taking it in small steps, depending on what I can manage in my copious free time. My next post will cover the simplest dialog: creating new Categories.

Thursday, April 14, 2011

Elaborate Answers To Simple Questions: Python, Strings, and Email

tl;dr: Use string methods instead of importing string. Build email messages with the standard email library.

I saw an email last night from somebody with a simple Python question.

Hi,

... I have some issues in my python program. I have installed python27 in C:\Python27. I started learning python with small programs. I’m saving all python programs in C:\ROUGH When I am executing these scripts through command prompt facing some problem with "import". Please help me out

My program:

import sys
#import C:\Python27\Lib\string
import string
 
Subject = "Testmail"
To = "yeahright@nonotreallyawebsiteihope.com"
From = "yeahright@nonotreallyawebsiteihope.com"
text = "Test"
body = string.join(("From: %s" % From,
                    "To: %s" % To,
                    "Subject: %s" %Subject,
                    text
                    ),"\r\n")
 
print body

ERROR IS:

C:\Python27>python.exe c:\ROUGH\addingsubtofrm.py
Traceback (most recent call last):
  File "c:\ROUGH\addingsubtofrm.py", line 12, in 
    body = string.join(("From: %s" % From,
AttributeError: 'module' object has no attribute 'join'

...

For some reason, I do not get any error when I try to run her code with Python 2.7.1 on Windows XP. That's okay, though. I can still help a little bit on the style.

Although join is part of the string module, it is also directly attached to strings. So instead of using string.join(items, separator), you could use separator.join(items). That's considered the standard way to join a list of items into a single string these days.

Subject = "Testmail"
To = "yeahright@nonotreallyawebsiteihope.com"
From = "yeahright@nonotreallyawebsiteihope.com"
text = "Test"
body = "\r\n".join(("From: %s" % From,
                    "To: %s" % To,
                    "Subject: %s" %Subject,
                    text
                    ))
print body 

This probably answers her question, but I am apparently in the mood to spend a lot of time writing about Python basics. Sounds like blog gold to me.

There's a problem with body if you want to use it for an actual email message. There needs to be a blank line between the headers and the body. One way to do that is to use join twice: once to build the header block and again to create a properly laid-out email message.

Subject = "Testmail"
To = "yeahright@nonotreallyawebsiteihope.com"
From = "yeahright@nonotreallyawebsiteihope.com"

text = "Test"

header_block = "\r\n".join((
    "From: %s" % From,
    "To: %s" % To,
    "Subject: %s" % Subject
))

# A full email has a blank line between the header block and the message body
body = "\r\n\r\n".join((header_block, text))
print body

The header block still looks a little clumsy. I am sure there is a prettier way to generate it. When I look at how the header block is printed, I realize that it looks a lot like a Python dictionary. Does the code look any clearer if I use a dictionary?

headers = {
    "Subject": "Testmail",
    "To": "yeahright@nonotreallyawebsiteihope.com",
    "From": "yeahright@nonotreallyawebsiteihope.com"
}

text = "Test"

# Each line of a header block contains a single email header,
# which looks like "Header-Field: Header-Value"
header_block = "\r\n".join(("From: %s" % headers['From'],
                            "To: %s" % headers['To'],
                            "Subject: %s" % headers['Subject']))

# A full email has a blank line between the header block and the message body
body = "\r\n\r\n".join((header_block, text))

print body

Well, no. Not really. I think I'm actually typing more than I was before, and it's not really any easier to read. It's all that "From: %s" % headers['From']" nonsense.

`join` takes a sequence. I do not have to hand it a literal like we have been doing so far. Let's build a list of header lines, and *then* join them.

headers = {
    "Subject": "Testmail",
    "To": "yeahright@nonotreallyawebsiteihope.com",
    "From": "yeahright@nonotreallyawebsiteihope.com"
}

text = "Test"

# Each line of a header block contains a single email header,
# which looks like "Header-Field: Header-Value"
header_lines = []

for field, value in headers.items():
    header_line = "%s: %s" % (field, value)
    header_lines.append(header_line)
  
header_block = "\r\n".join(header_lines)

# A full email has a blank line between the header block and the message body
body = "\r\n\r\n".join((header_block, text))

print body

It is easier to read, even if it is a little longer. We are building a list of header lines by stepping through each of the key/value pairs that make up the headers dictionary. Oh, and don't worry about what order the items are printed in. That order doesn't matter in email messages.

One thing - and this is a little thing - is that it takes us four lines of code to build the list. Like I said, it's a little thing. But building lists like this is so common that Python provides powerful tools called list comprehensions, which can reduce those four lines into one.

headers = {
    "Subject": "Testmail",
    "To": "yeahright@nonotreallyawebsiteihope.com",
    "From": "yeahright@nonotreallyawebsiteihope.com"
}

text = "Test"

# Each line of a header block contains a single email header,
# which looks like "Header-Field: Header-Value"
header_lines = ["%s: %s" % (field, value) for (field, value) in headers.items()]  
header_block = "\r\n".join(header_lines)

# A full email has a blank line between the header block and the message body
body = "\r\n\r\n".join((header_block, text))

print body

All right. Now if this were an actual email, there are some missing headers. There are probably also some details missing that are related to email handling. Rather than try to figure out what's missing, I'm going to suggest that you use the email library that comes standard with Python.

from email.mime.text import MIMEText

headers = {
    "Subject": "Testmail",
    "To": "yeahright@nonotreallyawebsiteihope.com",
    "From": "yeahright@nonotreallyawebsiteihope.com"
}

text = "Test"

msg = MIMEText(text)
for field, value in headers.items():
    msg[field] = value

print msg.as_string()

And what does the end result look like?

Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
To: yeahright@nonotreallyawebsiteihope.com
From: yeahright@nonotreallyawebsiteihope.com
Subject: Testmail

Test

There you go. If your end goal is generating emails, use the Python email library.

Monday, April 11, 2011

My Parrot and Rakudo TODO

This is more of a personal reminder than a big announcement or anything like that. I have a tendency to get an idea in my  head and then lose it when a bright shiny object comes into my field of view.

I have a lot of love for the Parrot Virtual Machine, but my Parrot projects have been left sadly neglected for several months now. Spring is here. The cherry blossoms are almost done blooming in Seattle. Parrot stable is at 3.0. Dev is at 3.2, which means a new stable release is days away. Rakudo has moved on to a 3-month cycle relying on the stable Parrot releases. That means my focus on the stable Parrot is useful

The Parrot Babysteps still talk about Parrot 2.6. My parrot-handler project sits idle and unloved. This is unacceptable.

I have heard rumblings about PIR going away. This is a source of frustration for me, since PIR is the sole focus of the Parrot Babysteps. But hey - it might not happen, and maybe it's not such a bad thing if it does. There are plenty of nifty Parroty ideas to occupy my time while I dig through the mailing list archives to see if I can determine PIR's fate.

I have a Babystep path in mind for using the Parrot tools to build a custom language, and I could use the basic template of the PIR Babysteps for Rakudo. Actually, I could use that basic template for Python and Ruby, too. One thing at a time, though.

Here's my Parrot / Rakudo TODO list, in no particular order.


  • Update the existing Parrot Babysteps for Parrot 3.0
  • Work on parrot-handler, or at least poke at it.
  • Start a Babysteps path for building a language with Parrot (a language I want to use, obviously)
  • Start a Rakudo Babysteps path modelled after the existing Parrot PIR Babysteps.


Now  I should get back to work, which nothing to do with Parrot, PIR, Rakudo, Python, or Ruby.

Wednesday, March 16, 2011

A Glance at Client-Side Frameworks

I was one of those lucky suckers who got a Google CR-48 netbook a few months back. Although I've failed miserably in making it my primary machine, it has gotten me thinking a lot more about browser applications and JavaScript frameworks. That's good. It got me out of my twelve year server-side rut.

A lot has happened to JavaScript since I started hating it in 1998. It's a real programming language, with multiple solid implementations. Smart people have been making it work from the command line, while other smart people have been establishing a solid base to build browser applications on. I've been looking at a few different frameworks, thinking that I'll find the One True Framework. No such luck. There are three biggies that I'm going to end up bouncing back and forth between.

  • jQuery gives me what I need to add awesome interactive features to a site right now. I would like to compare its virtue of immediate gratification to that of PHP. There's a lot of hate out there for PHP, so I won't. Except I just did. Oh, the inconsistency.
  • Google Closure is this massive collection that seemingly provides everything that core JavaScript is missing: type annotations, templating, compilation, and probably a lot of other stuff. Oh, and the basic framework stuff you get in toolkits like jQuery. It could be amazing. It could be terrible. It will take me a while to find out. One thing's for sure. Closure rewards the patient more than those of us who like instant gratification.
  • SproutCore is somewhere in between the two. There's some instant gratification, assuming you're already familiar with basic MVC as seen on the Web. It's designed for building full-scale client applications, though. Stuff like the NPR webapp. Closure is as well, but it's not as locked into the single point of entry that SproutCore seems to be. It could be. I don't know. I'm still learning about JSDoc tags.

SproutCore is the most interesting to me right now, probably because it's the newest. Its main disadvantage to me is that it targets HTML 5. My job forces me to maintain compatibility with Internet Explorer 6, which is most definitely not compatible with HTML 5 features. So I can learn SproutCore, but should not expect to use it on the clock.

There you have it. Three frameworks that charm me in different ways. I plan to more or less learn each of them. All because Google sent me a netbook.

Tuesday, March 08, 2011

Syntax Highlighting Test

Just testing out the MLA Wire Blogger Syntax Highlighting instructions.

Here's Ruby.

class MyDumbClass < TheirDumbClass
  attr_handler :name

  def show_name
    puts @name
  end
end

Perl.

package MyDumbClass;
use 5.012;
use base "TheirDumbClass";

has name => (
  isa => 'Str',
  is  => 'rw',
);

sub show_name {
  my $self = shift;
  say $self->name;
}

1;

And Python.

class MyDumbClass(TheirDumbClass):
  def __init__(self, name=""):
    self.name = name
  def show_name(self):
    print self.name

Test ends.