About Kent Cowgill
Articles filed under...
abs ab_ripper andylester arms back baggyshorts bestpractices biceps bike birthday blog bugs bus calculator cardio catalyst cgi chart chest chinups code cpan datamodel dbi doctor documentation exercise exhaustion fitness flattire flat_tire google gps heart_rate helmet history home houston html humor journal kate kenpo kenpo_x kettlebell knees lazy legs lisa lisanne maps math matthew michaelmckenna mom montreal motivation movie mysql oops orm P90X pain park patellar_tendonitis patrick pdf perl phb photos physical_therapy plyometrics poor_gait presentation procrastination progress pullups pushups pyramid rabbits racecondition rant refactor rest ribs ride route running shoulders situps slides sore spike sql statistics syntax test testing textile timex training triceps ups versioncontrol video vim vimrc walk warren work workouts yapc yapcna2007 yoga youtube

A R C H I V E S

(3)
(1)
(3)
(2)
(7)
(15)
(16)
(25)
(3)
(4)
(2)
(4)
(11)
(1)
(1)
(3)
(2)
(2)
(10)
(5)
(2)
(3)
(4)
(9)
(21)
(3)
(3)
(1)
(6)
(4)
(1)
(4)
(3)
(2)
(1)


    Is Kent Cowgill Online?
    View Kent Cowgill's profile on LinkedIn
    Add to Technorati Favorites

    Recent Entries...

    Re: Catching up through week 7

    testing video ...

    Re: Porting a non-Moose object to Moose

    Wow, look what I found, greedy genius ...

    Re: Porting a non-Moose object to Moose

    Kevin, You're right, that does seem a little confusing. ...

    Re: Porting a non-Moose object to Moose

    Wait. I'm confused. Moose isn't the tool to reach for. So...

    Re: Porting a non-Moose object to Moose

    You should switch to MooseX::Types to declare your Typed and...

    Porting a non-Moose object to Moose

    I'm currently working with a lot of legacy code in an envi...

    Testing strategy for mocking code

    I keep finding myself using the following idiom for writing ...

    Re: Library Woes on OSX

    Have you considered changing your hosts file so it connects ...

    Re: Library Woes on OSX

    Right now the tests for Device::USB are failing. I've turne...

    Re: Library Woes on OSX

    What's the USB device you are trying to connect?...

    weblog | `web·lôg -läg |
    noun
    Another term for BLOG
    ORIGIN 1990s: from web in the sense [World Wide Web] and log in the sense [regular record of incidents.]
    blog | bläg |
    noun
    A web site on which an individual or group of users produces an ongoing narrative.
    ORIGIN a shortening of WEBLOG.

    Porting a non-Moose object to Moose

    Kent Cowgill

    I'm currently working with a lot of legacy code in an environment where the other developers haven't been brought up to speed on things like Moose just yet. I've been tasked with writing some modules in support of this legacy code on a legacy platform - so Moose probably isn't the first choice of tools to reach for.

    The module I created is a lightweight wrapper around PDF::API2 that handles a very specific case - adding an image to an existing PDF file. Naturally, Moose is installed on my laptop, so after creating a recent module in older style perl with a hash based object I decided to re-implement it in Moose.

    The first comparison I'll look at is object instantiation.

    use constant ARGS => qw/pdf_template image new_filename/;

    sub new {
      my( $class, $arg_ref ) = @_;
      
      my( $pdf_template, $image_file, $new_filename )
        = ref $arg_ref eq 'HASH'
          ? @{ $arg_ref }{ ( ARGS ) }
          : ( $arg_ref );

      my $self = {};
      bless $self, $class;
      $self->_clear_saved;
      
      die "Can't read PDF template - $!" unless $pdf_template && -r $pdf_template;

      $self->_set_pdf( PDF::API2->open( $pdf_template ) );
      $self->add_image( $image_file ) if $image_file;
      $self->save( $new_filename ) if $image_file && $new_filename;

      return $self;
    }

    sub _set_pdf {
      my( $self, $pdf ) = @_;
      die "Invalid PDF object" unless $pdf && ( ref $pdf ) =~ /^PDF::API2/;
      $self->{pdf} = $pdf;
      $self->_set_page( $self->_load_page );
      $self->_set_gfx( $self->_load_gfx );
      $self->_set_dimensions( $self->_load_dimensions );
      return;
    }

    There's really just a few things to point out here.

    I've designed the object so that it will either accept a single string as an argument, or a hashref containing key => value pairs of the pieces of data used to setup the object; in this case a PDF template filename, an image filename, and a new filename to save a resultant file as. To make this module as easy as possible to use, I have it setup so that if all arguments are passed in the constructor, the object knows enough about what's needed from it and does everything - even saves the new file.

    I've included the _set_pdf() method because that one is always called for my definition of a successful object instantiation. As you can see, once it sets the private object member {pdf} to the new PDF::API2 object passed in, it also sets a few other object member data based on the PDF::API2 object.

    After setting these in _set_pdf(), the code checks to see if there's an image file and a new filename. We'll get to that part later.

    One way to create the analog to the above code using Moose :

    use Moose;
    use Moose::Util::TypeConstraints;

    has 'pdf_template' => (
      is => 'rw',
      isa => 'Str',
      required => 1
    );

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

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

    has 'image' => (
      is => 'rw',
      isa => 'PDF::API2::Resource::XObject::Image::JPEG'
    );

    subtype 'MyPDF'
      => as 'PDF::API2';
      
    coerce 'MyPDF'
      => from 'Str'
      => via { PDF::API2->open( $_ ) };
      
    has 'pdf' => (
      is => 'ro',
      isa => 'MyPDF',
      coerce => 1,
      lazy_build => 1,
    );

    sub _build_pdf { shift->pdf_template }

    sub BUILD {
      my $self = shift;

      if( my $image = $self->image_file ){
        $self->image( $image );
        if( my $filename = $self->new_filename ){
          $self->save( $filename );
        }
      }
    }

    The first item of interest is that I'm letting Moose::Util::TypeConstriants handle the coercion of a string (the PDf filename) to a PDF::API2 object. I'm also setting the pdf attribute to lazy_build. A little more on that later.

    Additionally - for the rest of the attributes, most of the work is done for me by Moose - I only need to tell it what attributes my class is going to have, and Moose does all the setting and type checking for me.

    Notice there's no new() subroutine - that's because Moose takes care of creating a default constructor, which will take care of parsing the argument(s) to the constructor for us.

    Because I am creating a literal translation of the previous object in Moose , I decided to give it the exact same behavior. I originally started adding the extra functionality to the constructor by creating an after() modifier, but that had a couple of problems - the first of which was the fact that I could no longer follow the Moose best practice of making the class immutable .

    I also ran into an issue using after() with deep recursion - notice how after setting the pdf attribute I use it (the pdf attribute) again to set the page attribute. This had the fun effect of calling after() again, after accessing the pdf attribute. Oops :)

    I then tried around() but that had also didn't let me set the class to be immutable. So I settled on using a BUILD() method.

    I originally had a few more calls to other attributes' setup inside my BUILD() subroutine, but Chris Prather suggested I move those pieces to lazy_build attributes , in which advice (and the accompanying documentation) I found great wisdom. The thinking is that the value for these attributes depend on another attribute - so these attributes /must/ be lazy. I've left out those definitions, but I'll get to those in a later post.

    Related Photos: perl

    Testing strategy for mocking code

    Kent Cowgill

    I keep finding myself using the following idiom for writing unit tests in perl for modules that have to interact with other modules.

    use strict;
    use warnings;

    use Test::More tests => 4;

    {
      no warnings qw/redefine once/;
      local *ModuleToMock::MethodToMock = sub {
        ok( 1, 'got a call to the method' );
        is( ref $_[1], 'HASH', 'got an hashref as an arg' );
        is( $_[1]->{param}, 'value', 'got a reasonable value as a param' );
        return 'sensible return value';
      };

      my $obj = ModuleThatsBeingTested->new();

      my $return = $obj->OtherMethodThatCallsMockedModule(
        param_passed_along => { param => 'value' }
      );

      like( $return, qr/sensible return/, 'got a reasonable return' );
    }


    Yes, I know about Test::MockObject but for some reason I never reach for it these days. For comparison purposes, using Test::MockObject in the above example might look like:

    use strict;
    use warnings;

    use Test::More tests => 4;

    use Test::MockObject;

    my $mock = Test::MockObject->new();

    $mock->fake_module(
      'ModuleToMock',
      MethodToMock => sub {
        ok( 1, 'got a call to the method' );
        is( ref $_[1], 'HASH', 'got an hashref as an arg' );
        is( $_[1]->{param}, 'value', 'got a reasonable value as a param' );
        return 'sensible return value';
      },
    );

    my $obj = ModuleThatsBeingTested->new();

    my $return = $obj->OtherMethodThatCallsMockedModule(
      param_passed_along => { param => 'value' }
    );

    like( $return, qr/sensible return/, 'got a reasonable return' );

    I'm not sure what caused me to stop using it, though. I've heard recently (in fact, as I was writing this post and pondering its use):

    NOOOOOOOO! it loads UNIVERSAL::isa and ::can. If I want to mock something I make a mock class.

    But I'm sure that never entered my thought process.

    Maybe I just thought it was too much setup, even though it's really only a couple of lines of code more.

    Maybe it's because I can never remember the exact syntax for setting something up with it, without consulting either previous test code I've written or the documentation. I had to check both before posting this.

    Related Photos: perl

    Library Woes on OSX

    Kent Cowgill

    I've been trying off and on to get Device::USB up and running on my mac in order to be able to talk to some USB devices via perl. But that depends on having libusb installed (properly, mind you) - which I have just had no luck getting to work.

    I did find some precompiled binaries for my OS version, but Device::USB doesn't seem to like it.

    Maybe I'll grab the source for libusb and compile it myself and see how that goes. I have high hopes.

    Related Photos: code mac perl

    Tired eyes

    Kent Cowgill

    It's so easy to miss things if you're just casually trying to familiarize yourself with some perl code that's brand new to you.

    It wasn't until I was creating a comprehensive set of unit tests and calculating code coverage metrics that I saw this not once, but three times in a row...

    if( condition ){
      die "some appropriate error message";
      return;
    }

    Of course, even when writing the tests, I didn't spot it until I was writing a test for the last if.

    Thankfully Devel::Cover quickly highlighted that no matter what I tried, I couldn't write test code to exercise that return; statement.

    Same thing with this one:

    sub method {
      my( $self, $args ) = @_;
      return unless $args->{ key };

      # more code ...

      if( $args ){
        # more code here that uses $args
      }
      # etc...
    }

    I couldn't understand why I couldn't manage to manipulate the inputs of method to cover all branches of that if.

    And then I realized it would never get that far with the early short-circuit return. Duh.

    Related Photos: code perl

    Slide slight of hand

    Kent Cowgill

    If you've already downloaded a copy of the slides from my first talk (Testing Code and Assuring Quality) then this update is for you.

    By popular demand, I've added the lolcats back into the presentation in the appropriate places.

    But more importantly, I'm no longer at the company for which I created this testing infrastructure. As such, I've updated the company name and technology name(s) to anonymize them a bit.

    Just in case.

    The biggest thing this means is that I need to re-record the screencasts before I can release those as well, being sure to remove any non-anonymous and non-proprietary information that may or may not already be in the recordings.

    Which will take some time. :(

    The good news is that the other talk I've prepared (and presented) on "Simple Photo Processing and Web Display" has never had any such information in it, so once I've got it in its final polished state, the publishing of the slides will be that much quicker.

    Keep an eye on my slideshare slidespace for updates.

    Related Photos: perl

    Slides for my first talk posted

    Kent Cowgill

    So, I finally decided to stop putting it off and upload the slides from my testing talk onto slideshare.net. Click here to view these slides, as well as any future slides I make public.

    Unfortunately, this presentation/slide set was heavy with screencasts, which don't survive the transition to PDFs very well. I'm considering hosting the screencasts elsewhere.

    Enjoy!

    Related Photos: perl yapc

    Released more code

    Kent Cowgill

    Hello, I forgot to post a note about this.

    My third contribution to CPAN is an important one. It is Acme::LOLCAT.

    Or, to translate this announcement into LOLCAT using this module:

    OH HAI, I FRGOT TO POST NOTE ABOUT THIZ.

    MUH THIRD CONTRIBUSHUN TO CPAN AR TEH AN IMPORTANT ONE. IT AR TEH ACME::LOLCAT. KTHX.

    OR, TO TRANSLATE THIZ ANNOUNCEMENT INTO LOLCAT USIN THIZ MODULE:

    Related Photos: lolcat perl

    Indirect confusion

    Kent Cowgill

    I'm really not understanding something. I've run into a module for which I had a lot of difficulty writing the first few tests. This usually happens when the module under scrutiny does something a little weird, so I'm used to it by now.

    But this one is a lot weird.

    The code for the module I'm looking at is structured exactly like this:

    package foo;

    use strict;
    use warnings;

    sub firstSub {
      my $string_orig = shift;

      # in the production code, this
      # somehow works and doesn't die
      my $string = secondSub $string_orig;

      return ( foo => $string, bar => $string_orig );
    }

    sub secondSub {
      my $string = shift;
      my $ret = join '', reverse split //, $string;
      return $ret;
    }

    1;

    What's strange is that when I use the module and try to call "firstSub", I get a Can't locate method object secondSub via package VALUE_PASSED at line blah, of course substituting VALUE_PASSED for whatever value I actually pass :) But the module - as is - works on the development server, and has worked on the production server for years with this exact structure and syntax.

    So for this example, this code (reduced to the smallest example that still exhibits the behavior, but essentially the same structure) tries to call the modules' subroutine via:

    use foo;

    my %q = foo::firstSub( 'MTFNPY' );
      
    print "$_: $q{$_}" for keys %q;

    And the output I get is:

    Can't locate object method "secondSub" via package "MTFNPY" (perhaps you forgot to load "MTFNPY"?) at foo.pm line 13.

    A little boggling. I tried a few things, including this ugliness:

    {
      no warnings 'once';
      *MTFNPY::secondSub = \&foo::secondSub;
    }

    ... but of course that will only work as long as I'm passing the value of "MTFNPY".

    Running the code through B::Deparse confirms that line is interpreted as my $string = $string_orig->secondSub.

    I see I've got a couple of options:

    1. Fix the code minimally - re-order the subroutines inside the module so the second subroutine is defined first, so it will be correctly interpreted as a function call.
    2. Fix the code a little less minimally - add parens around the argument to secondSub.
    3. Fix* my tests and don't touch the original code until my tests are complete so I am 100% certain I don't break anything else. (I'm fairly sure either of these changes won't, but "fairly" isn't 100%).

    * By which I mean 'just make it work'

    So, I add this near the top of my test file:

    BEGIN {
    package foo;
      use subs 'secondSub';
    }
    use_ok( 'foo' );

    ... which basically tells the interpreter that package foo will be defining a subroutine called secondSub, which is to say predeclaring them - before the foo module has a chance to load, by taking place inside a BEGIN block.

    And lo, testing successful.

    But what I still don't understand is how exactly the code in the original module works at all! I'm testing on the same box where the code lives - where the code runs day in and day out without bringing the test server down to a screeching halt. I know - I added trace debugging statements all around, thinking that perhaps the code has always been silently failing and the failure was just dealt with. But no, the code was making it through that step and doing exactly what my predecessor(s) expected it to do. It's just doing it wrong.

    Related Photos: perl

    More code contributed to the world.

    Kent Cowgill

    So, I released another module to CPAN today.

    It's called Perl::Critic::Nits, which at this point only has one policy module, one that discourages accessing what appears to be private member data of a class. Feel free to have a look. Though if you're reading this post significantly after the date I'm posting it, that version may no longer be the most recent release.

    It pretty much looks for anything that accesses a hashref subscript or an arrayref subscript. And in case you can't guess - that can be a problem if you're not dealing with an object. Like if, for instance, you have a regular old hash reference.

    Drat.

    Elliot Shank reminded me that the code being examined isn't compiled, so it's a little tough to figure out whether or not something isa blessed object, or just a plain hashref. D'oh.

    At least it's easy enough to disable a policy. :/

    However, it will definitely catch attempts to access an object's member data directly, so I don't feel so bad about that. So long as the pseudo convention of assigning $_[0] to a variable called at least either $self, $package, or $class.

    Please enjoy, and let me know if you run into any bugs.

    Related Photos: perl

    Picking too fine a nit?

    Kent Cowgill

    So, I'm dutifully going through some 129 modules in our codebase, creating documentation and tests for everything I find.

    I mean absolutely everything.

    But I wonder if I'm going too far?

    For instance, I happened upon a module called Boolean.pm. Seems like it ought to be fairly low-hanging fruit, so I open it up to find that the whole of the module looks like this:

    package Boolean;
    use strict;
    use base q(Exporter);
    @Boolean::EXPORT = qw(TRUE FALSE);

    use constant TRUE => 1;
    use constant FALSE => 0;

    1;
    __END__

    No joke.

    Fine, the tests will be easy enough. I won't repeat them here for brevity, but suffice it to say that the only thing that threw me for a loop is that use_ok didn't seem to import the exported constants into the namespace of my test file - after testing the module, I just use Boolean; and then I can test the constants. Could I have just called import as the module inherited from Exporter? Probably, but I didn't.

    The next module I come across is another top level namespace module named Database.pm. Whose primary purpose is to figure out which database server to have the rest of the code connect to, depending on a few external conditions. Part of the module declares a number of constants - the database connection strings - for internal (to the module) use only, and doesn't use base 'Exporter' and subsequently export those constants. However, it makes sense to me that I ought to test those constants as part of my test suite.

    So, fresh with my knowledge that constants aren't imported into the test file's namespace via use_ok, I add a use Database; and expect my tests to pass. Oops, not so fast - because I'm testing the constants as barewords, and they're not exported via @EXPORT, they're not recognized as constants and my test file (with use strict at the top) fails miserably complaining about my usage of barewords.

    So, what to do?

    I decided I would force the Database module to be @ISA = 'Exporter' and add the constants to @EXPORT myself, on behalf of the module, in the test file. So now my test file looks a bit like this:

    use strict;
    use warnings;

    use Test::More tests => 2;

    BEGIN {
      use Exporter;
      @Database::ISA = ( 'Exporter' );
      @Database::EXPORT = qw/PROD DEV/;
    }

    use_ok( 'Database' );

    use Database;

    is( PROD, 'production:dsn:etc',
        'PROD points to correct db' );
    is( DEV, 'development:dsn:etc',
        'DEV points to correct db' );

    ... but I have to wonder if this is worth all the bother. I suppose for now I'll leave it.

    Related Photos: perl

    Testing and Documenting Legacy Code

    Kent Cowgill

    &qidYou may have guessed by now, but I've taken up a particularly onerous gauntlet at my job. I'm afraid to touch any modules. But holy cow, do they need touching.

    What do we learn from Refactoring: Improving the Design of Existing Code ? Well, we learn that without tests, you can't refactor. Well, you can - it's really not wise to do so, however. It will be difficult to know if you've broken something or slightly altered a particular functionality.

    Of course, tests also help you prove what you've got is a set of modules that performs to their specifications - or in the absense of a specification - proving that the code does what it looks like it's supposed to do based on certain circumstance.

    Given that our codebase is huge, undocumented, and more important untested, I've come up with a few snippets of shell code to really move me pretty far forward with my task.

    First, to create a directory hierarchy to house all my new tests:

    for i in $(find . -name "*.pm")
      do touch $(echo $i | \
    sed -e 's/\./\/path\/to\/dir/' | \
    sed -e 's/\.pm$/.t/')
    done

    And to give the files some default content (it's ugly but it sorta works, YMMV):

    for i in $(find . -size 0)
      do echo '#!/usr/bin/perl' >> $i
        echo "" >> $i
        echo "use strict;" >> $i
        echo "use warnings;" >> $i
        echo "" >> $i
        echo "Test::More 'no_plan';" >> $i
        echo "" >> $i
        echo "use_ok( '`sed -e 's/\//::/' | \
    sed -e 's/\.t//'`' );" >> $i
      done

    These snippets, plus my previously mentioned vim tip are really getting me pretty fair along in creating a comprehensive test suite and a good set of documentation for all of our legacy code.

    Oh, and as a side benefit, I'm getting to know the modules pretty well while I'm at it :)

    Related Photos: perl

    HTML Test Reporting

    Kent Cowgill

    I wrote a few days ago about writing my own Test::Harness parser since I had been unable to install the module that does that, and does it well.

    On my machine, Test::TAP::HTMLMatrix is beautifully installed - however where this module could do me the most good - as in having tests run all the time for me - I have historically had issues getting modules installed. At the very least, I need to identify all the various dependencies of every module and their dependencies in order for the SAs to search for .rpm files for ease in making the modules easily installable on every other production machine in the cluster. Which makes a certain amount of sense. As long as you don't remember that this test reporting module has no business on production anyhow.

    But a brief perusal of the source for HTMLMatrix, and I'm starting to get the impression that having the SAs install it, plus all it's dependencies, plus all their dependencies, might be more hassle and take longer than I'd like.

    Since I got my html harness pretty much working before trying to install HTML Matrix again, I might as well start using that at work to keep at-a-glace test results at a handy web page. Without all those dependencies.

    So I did. And I copied all the tests over to our dev server. And I tweaked the hell out of them to make them actually run. More on that later.

    The above picture is just a snippet of it to be able to fit into my blog, but you can see a fuller version here.

    The code to create this is pretty simple. Here are the important bits of it:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use Test::Harness::Straps;

    my $strap = Test::Harness::Straps->new();

    my $graph_width = 600;
    my $filename_width = 150;
    my $percent_width = 75;

    print report_head();

    my $cnt = 1;
    my $tot = 0;
    my $ok = 0;

    for my $file( @ARGV ){
      next unless -f $file;
      $cnt++;
      my $style = $cnt % 2 ? 'blue' : 'tan';
      my $result = $strap->analyze_file( $file );
      my( $this_tot, $this_ok )
        = ( $result->seen, $result->ok );
      $tot += $this_tot;
      $ok += $this_ok;
      my $graph
        = return_graph( $this_tot, $this_ok );
      my $percent
        = int( $this_ok / $this_tot * 100 );
      my $status = $percent < 100
          ? '<span style="color:red;">NOK</span>'
          : 'OK';
      my $perstyle = get_percent_style( $percent );
      printf <<END_REPORT, $style, $file,
    $file, $status, $graph, $perstyle, $percent;
    <tr class="row">
    <td class="%s">
    <a href="%s">%s</a>
    </td>
    <td class="status">%s</td>
    <td>
    <table class="graph">
    <tr>
    %s
    </tr>
    </table>
    </td>
    <td class="%s ctr">%d\%</td>
    </tr>
    END_REPORT
    }

    print report_end();

    sub return_graph {
      my( $cnt, $run ) = @_;
      my $width = int( $graph_width / $cnt );
      my $leftover = $cnt - $run;
      my $bad_cell
        = qq{<td class="nok" style="width: }
        . qq{${width}px"> </td>};
      my $good_cell
        = qq{<td class="ok" style="width: }
        . qq{${width}px"> </td>};
      my $cells = $good_cell x $run;
      $cells .= $bad_cell x $leftover;
      return $cells;
    }

    sub get_percent_style {
      my $pct = shift;
      return
             $pct == 100 ? 'hundred'
           : $pct >= 95 ? 'ninetyfive'
           : $pct >= 90 ? 'ninety'
           : $pct >= 80 ? 'eighty'
           : $pct >= 70 ? 'seventy'
           : $pct >= 60 ? 'sixty'
           : $pct >= 50 ? 'fifty'
           : $pct >= 40 ? 'forty'
           : $pct >= 30 ? 'thirty'
           : $pct >= 20 ? 'twenty'
           : 'ten';
    }

    The missing report_header() and report_end() routines add the head, title, stylesheet, body tags, etc. to turn the meat of the output into a web page.

    Btw, if you have 1) unresponsive SAs or 2) too much bureaucracy to get modules installed, and 3) have an improper Scalar::Util installation, and 4) need to use Test::MockObject (or some other module that 'optionally' uses Scalar::Util::weaken - and some Enterprise Linux Distributions ship a broken version of Scalar::Util) you can use this sneaky workaround:

    BEGIN {
      # We're not using feature XYZ in
      # Obj::Using::Weaken, so don't
      # care about our improperly
      # installed Scalar::Util
      require Scalar::Util; # load it into memory
      # we know this causes warnings
      no warnings 'redefine';
      # load our own versions that do nothing.
      *Scalar::Util::weaken = sub { return @_ };
      *Scalar::Util::export_fail = sub { return };
    }

    Related Photos: perl

    Handy vim mapping

    Kent Cowgill

    I'm going through a lot of legacy code lately, and got tired of manually opening up the first legacy file I documented (to make sure I was following the same standard I had implemented - it's not quite in my long term memory just yet), scrolling through the tedious documentation, copying (or retyping(!)) the text into the file I was working on, etc.

    So, I decided to write a quick little mapping for that menial task.

    First step is to create a template for the POD I want to insert:

    ~/podtemplate
    __END__

    =NAME

    =SYNOPSIS

    =DESCRIPTION

    ...

    And then this helpful mapping in my ~/.vimrc

    " Automatically add a POD template
    " to the end of a file
    noremap ,ap maG:r ~/podtemplate<cr>'a

    Mnemonic: Add Pod.

    ... which is at least smart enough to set a mark at your current position, move to the end of the file, insert the contents of ~/podtemplate, and return to your saved position. Caveats: It's NOT smart enough to know if you've already set an 'a' mark, and it's NOT smart enough to NOT insert the template if there's already POD in the file.

    Related Photos: perl

    CPAN annoyance

    Kent Cowgill

    Ok, to be fair - it's really not a problem I have with CPAN.

    A month or so ago, I won a copy of Perl Testing: A Developer's Notebook as a 'door prize' at a Chicago Perl Mongers meeting. I devoured it within a few days, reading it during my daily commute.

    Of special interest was the section on creating a test harness (or custom status report) for testing output by making use of Test::Harness::Straps . This was very cool because I had tried to get Test::TAP::HTMLMatrix to install on my Mac earlier this year only to be met with failing tests, or failing tests of dependencies. I don't recall, but I was really bummed. Figuring out the issue was beyond me at the time - I looked into it, but didn't have a ton of time, and I couldn't quickly see the issue.

    Anyhow, today I had a bit a inspiration to make use of the example code from the book and see if I couldn't use it to produce some fancy HTML output of my own to give an at-a-glance status of tests I had run, similar in nature to the cool Pugs Smoke Reports . So, I whipped open my copy of Perl Testing , typed in the example code, ran it against some tests I had recently written at work, fixed the bits that were broken (by consulting the documentation for Test::Harness::Results )... run, view, tweak, repeat ad nauseum.

    I finally got something fairly close to approximating those cool Pugs reports. But there were some big differences - which I couldn't figure out how to implement quickly (after all - the rest of the development of this parser was really quick and easy) - and I was running short on supplemental time. I actually thought it might be beneficial to take another look at HTMLMatrix and see if I could tweak that a bit.

    I took a look in my .cpan cache directory, but it wasn't still there. So I fire up my CPAN shell and try to install it (knowing full well it will fail, but my fingers are trained to type install MODULE).

    And before I know it, it's successfully installed.

    Related Photos: perl

    Perlbuzz.com launches

    Kent Cowgill

    Have you heard?

    I just heard that perlbuzz.com just launched. From the announcement:

    Introducing a new Perl news site with a difference. Via three blogs, Perlbuzz.com brings you the best of the world of Perl. Perl Buzz reports on the interesting software, websites and users of Perl. Project Hum tracks what's happening in projects around the net. CPAN Watch keeps an eye on CPAN uploads and reports on what's worth your notice.

    I just hope Andy remembers that he said he'd post up something about my perl testing vim plugin :-)

    Related Photos: perl

    I'm kind of a big deal.

    Kent Cowgill

    I don't know how to put this, but I'm kind of a big deal. People know me. I'm very important. I have many O'Reilly books, and my house smells of computers.

    Every once in a while, you just have to google yourself. I tend to do it while I'm alone - but sometimes I do it at work. I just finished googling myself a few minutes ago, and was happy to find that I am 10 out of the first 10 google hits for "kent cowgill" (without the quotes, even).

    Even better, I am 39 of the first 50 google hits.

    The other three Kent Cowgill's've got nothin' on me, even though one's a marginally popular medievalist author, one doesn't even have Kent as his first name and has written (or reviewed, it's not clear) a journal article or two, and the last is (or has been) apparently an english professor at WSU.

    Don't be fooled, though. Even though meetup.com makes it look I'm from Lombard, I'm not. (I'm still in Chicago).

    I also didn't attend the Chicago Hackathon in 11-06. I wanted to, but I was out of town that weekend :(

    If any CPAN links show up, make sure you're looking at the most recent version of a module.

    That's really my wishlist on page two. Feel free to get my anythingon that list. Or an iPhone. It's not on the list, but I won't mind if you go "off-list" for that.

    I do have helpful advice about out-of-towners sharing cabs from O'Hare to one location, specifically when a bunch of perl geeks converge on Chicago for YAPC::NA::2006.

    I was linked to from Sun's BigAdmin portal for my article about chrooting sftp on Solaris 8. I was really proud about that. Even though at this point it's completely out of date. UNLESS you happen to be nursing along an old Solaris 8 box.

    I'm starting to give talks at my local perl mongers meetings. I'll probably post more of those types of things.

    That's me at UniForm Chicago. My first meeting I'm presenting at, too.

    I gave a lightning talk a year or so ago golfing perl, and David Romano wants to see it sometime. Now anyone can.

    I helped Andy Lester a little with perl101.com. Just a little CSS if I recall correctly.

    I also helped Andy with the name for his wiki, xoa. I just threw out a name or two, and one of 'em stuck.

    I registered at the TWiki dev site. And gave some helful advice. And promptly lost all interest, as I no longer has a job requiring me to admin and/or work heavily with TWiki.

    It appears Marcus Ramberg linked to my blog (this one!) on del.icio.us. A nod always feels nice from one of the core developers of the framework this very blog runs on.

    I participated in a Catalyst BOF, and a Hackathon after YAPC::NA::2007 in Houston. I didn't do much other than help a lot with logistics - arriving early, procuring the room, finding network connectivity, hooking it up, figuring out why it didn't work, helping to rig up an intermediary solution... etc.. Did a little QA work with Marcus Ramberg and Jon Rockway on the mojomojo project - a catalyst based wiki.

    I sought help trying to run linux on a handhelp ipaq (which I apparently posted shortly after I came back from my bike ride - having raised $7,080 for a worthy cause, and a heck of a physical challenge - hit the ride tag to the right for more info on that).

    And the rest of the hits for kent cowgill either point to this blog, or variations on the themes above.

    I recall the good old days (more like a year ago) where the primary things google turned up were 10-12 year old emails I sent to a MacPerl mailing list for a job many moons ago, about topics that frankly at this point, are a little embarrassing :)

    Related Photos: perl

    Code contributed to the world

    Kent Cowgill

    So I've decided to spread my testing goodness throughout the world.

    It started with a vim plugin to quickly go through some perl source and create stub test files for a given source code file.

    Then I got the bright idea to create a perl module to do the same thing. Partially helped by a suggestion from Jon Rockway after a quick lightning talk about my plugin.

    Available for your enjoyment is the original vim plugin as well as the perl module it evolved into, the current version of which is located in my CPAN directory

    Hopefully these are of some use or helpfulness to someone. Possibly even you. :)

    Related Photos: perl

    Testing with vim

    Kent Cowgill

    Wrote a quick little perl wrapper around vim to automate posting entries to my blog.

    Really threw it together pretty quickly, but wanted to save myself the trouble of opening a web browser, typing in the site name, scrolling down, clicking on "login", logging in, etc. Just a whole lot of work. Quite honestly, no one should have to put up with that.

    Maybe I should see about writing a plugin for vim, since the perl wrapper is a little hackish.

    Related Photos: perl

    Trying to display pre tags inside a pre block

    Kent Cowgill

    I think I know why I can't show HTML pre tags inside a pre block, and it's not Kate's fault, and it's not Textile's fault.

    It's my fault.

    if( $text =~ m/<pre class="([^"]+)"/s ){
        $lang = $1;
        $text =~ s/<pre[^>]+>(.*)<\/pre>/$1/s;
      }

    See the problem?

    I'll probably have a few more posts about this until I figure it out.

    But it's not like you were doing anything better than reading this :)

    Related Photos: perl

    Figured it out, pictures are a-flowin'

    Kent Cowgill

    Sweet.

    It only took re-writing the thing from the ground up, switching out completely the modules I was using - but I finally managed to get that silly picture stripper/thumbnailer working again.

    Were it not for Imager by Tony Cook or Email::MIME::Attachment::Stripper by Casey West (with my friend Yaakov recommending the former and perlmonks.org for the alternative to MIME::Parser) - I'd still be spinning my wheels.

    During the debugging, I'd get MIME::Parser to appear to work, but then Image::Magick would stop working. Or MIME::Parser would fail me in strange and non-reproducibly ways but Image::Magick would faithfully render an incomplete image file.

    But no more.

    Related Photos: perl photos

    Main Page | Login

    Do you want to buy me ? Find more gift ideas at my wishlist