Friday, May 29, 2009

The Dual-Lived Problem

Chromatic writes about perl future. His recent post on The Dual-Lived Problem brought my attention and I had time to read it to the bottom. I'll stop on the following idea and will try to promote tools we at Best Practical develop for our needs:

First, improve the core's automated testing.
This helps everyone; it can identify changes
in the core code that affect the stability
and behavior of the standard library. It can
also identify changes in standard library
modules which do not work on important platforms.

I do believe that CHIMPS toolset can help with this. Can not saythat it's been tested for such purpose, but it used exactly inthis way by BPS. We tests each revision of our project on mostrecent revision of another project it depends on.

Hope people can try with some modules they care about and reportback issues. You should prefer developer releases I recentlyblogged about orrepositories on github.

Finally done a new release of CHIMPS client

CHIMPS is a collection of tools to smoke test projects out of repositories.

My adventure with this toolset started as a simple task. I wanted to add smoking of our product RTIR. Well, now I know for sure what "yak shaving" means. At the end we have git support, less bandwidth, faster tests, new options, API for new repositories and new options.

Some use cases have been described earlier.

Recently uploaded two new development releases of Test-Chimps and Test-Chimps-Client distributions to the CPAN. You're welcome to try with your projects and report back using or this blog.

Friday, May 22, 2009

Bleeding edge smoke testing of perl software

We use CHIMPS for smoking in Best Practical. It's modular client server testing toolkit. One of its parts is smoking client that works with SVN repositories.

It's really simple things, at least it was, you describe projects in repositories, dependencies between them, start smoker and commit to the repos without being affraid you break backwards compatibility.

There are multiple case when it's useful. Sure you just smoke test your projects, but also you can smoke your project against repository of a module you don't control, but depend on heavily.

For example, you use Moose a lot with fancy things, its bleeding edge features and some workarounds. Chimps may be the only way to help you prevent disaster before new broken version of Moose is on the CPAN. To do this you setup smoking your project and describe Moose repository as well, so smoking goes against Moose's HEAD.

You also can test your project with Moose that is installed on the system, with Moose's tag 0.01 and Moose's HEAD. All this in one smoker.


Several days ago I started implementing a new tiny thing in the smoker. This change end up in total refactoring of the module and now we can smoke from git too. Adding additional back end now is easy. You have to implement four methods in a class.

Sadly there were no releases since 2006, so you have to check it out from github. I'm planning on releasing a dev version on the CPAN.

Wednesday, May 20, 2009

Where can you find code behind

Hi, continuing with blogging around

Some people still think that is something hidden in Best Practical's cages where we hold it like a prisoner. It's not true for a long time.

Started simple about document. I hope peopl will find link to this document on the main page.

Tuesday, May 19, 2009

Report spam button on

May be you don't know, but when people complain about service.I'm one of responsible for some stupidities. Heh. I'm not going to protect myself.

Fruck. All the cpan authors are responsible. The code behind the service is freeand you can send patches and extensions. Do you know number of those we recieved?ZERO.

That was a headup. Now, about reporting spam, I've writen a simple RT extension soregular users can help report messages as spam. It's in best practical's repository:

I've installed it already, but it has several problems:

1. no icons for the button.

2. when you click on link, browser jumps to a page when it should be AJAX works locally, but doesn't on the service. It needs debugging.

Help is welcome. You can write to or find ruz/ruz_macon IRC channels.

The way to search those spam tickets is described in the README.

Monday, May 18, 2009

A "new" game you can play on a conference

Ok, YAPC::Russia 2009 is over, it was awesome event. I really liked it.

I'm going to talk about a game we played. Main idea is to gather new fantastic ideas for startups using -Ofun mode.

You have a subject, in our case it was the Perl.

You spend 15 minutes collecting a lot of events related to the subject that most pobably will happen in the near future (1-2 years), for example it's likely that perl5 will be in use on the same rate for the next couple of years. Chances are not 100% but very high, it's a perfect match.

It's ok to have things with lower chances to happen. This is prefectly fine.

At the end you should have a big list. We used some mindmap building software for managing and writing down ideas.

Then you decide that you're not interested in things that will happen for sure. And auditory spends next 15 minutes throwing away things that have 50% and more chances to happen and filling blanks with things that have lower chances. At the end you need from 3 to 5 events per 5-10 persons in the room.

For example microsoft releases perl6 or crazy things like nuclear war. It's better to avoid really crazy things.

Randomize list, split people into groups, each group gets from 3 to 5 events. People should imagine that they live in a world where events they recieved have happenned. Every group has 15 minutes to discuss new realities.

A delegate from each group present the future describing one or two things in their world. We were describing a CPAN module and an application writen in Perl. Here the list we had:

    1) big russian it companies organize a perl school
    2) CPAN gets simpler and understandable
    3) there is a perl CMS that you can distribute without a developer in the box
    4) russian kids study perl in low-school

Everything should be recorded in a file, so you have list of fancy ideas. You can compare different realities and come up with new ideas that applicable in the real world.

Wednesday, May 13, 2009

instrumenting twitter with perl

Yesterday decided that I finally want to use twitter. Too much noise around, however it look like a nice thing that doesn't take much time. And useful for tiny announces.

What a concidence, lately I got addicted to music by Glen Hansard and Marketa Irglova from Once movie. Twitter is perfect thing to say what you're listing to right now. Why not?

    sudo cpan Net::Twitter
    vi ~/bin/tw_song
    # 10 minutes of typing

One slight problem is how to get the current song from iTunes.

    # googling
    # AppleScript editor

    if appIsRunning("iTunes") then
            tell application "iTunes"
                    artist of current track & " - " & name of current track
            end tell
    end if

    on appIsRunning(appName)
            tell application "System Events" to (name of processes) contains appName
    end appIsRunning

That's it. From command line you can use it the following way:

    osascript /Users/ruz/Library/Scripts/say_current_itunes_song.scpt

Here is final perl script:


    use strict;
    use warnings;

    my $song = `osascript /Users/ruz/Library/Scripts/say_current_itunes_song.scpt`;
    return unless $song;
    $song =~ s/^\s*//;
    $song =~ s/\s*$//;

    my $status = "Listening $song";
    print $status, "\n";

    require Net::Twitter;
    my $twit = Net::Twitter->new({username=>"myuser", password => "mypass" });
    $twit->update({status => $status});

Saturday, May 09, 2009

Blogging for perl geeks

Hi, there. For a while I've been trying to return back to bloggingwithout much success. I don't like what's going on with LJ. It'scrappy these days. Have a personal blog there, mostly in Russian,don't want to turn it into an IT blog. Many months ago startedlooking for a new hosting and chose blogger for that. Made a fewposts, but html is killing me, composer sucks too.

What the hell, I can not blog using some simple syntax. That'sjust wrong.

Here is my first post from my own blogging software - pod2blog.

Yes, you heard me right. I use perl's Plain Old Documentation (POD)for blogging.

It was a little bit harder than I thought would be, but works:

    #!perl    use 5.008;    use strict;    use warnings;    use utf8;    use YAML::Any qw();    use LWP::UserAgent;    my $ua = LWP::UserAgent->new;    my $file = shift;    my $parser = MyParser->new;    $parser->parse_from_file( $file );    push_to_blogger( $parser->{'entry'} );    sub push_to_blogger {        my $entry = shift;        my $request = HTTP::Request->new();        $request->method( 'POST' );        $request->uri('');        $request->header( 'Content_Type' => 'application/atom+xml' );        $request->header( 'GData-Version' => 2 );        $request->header( 'Authorization' => 'GoogleLogin auth='. auth_token() );        $request->content( $entry->as_xml );        my $res = $ua->request( $request );        print $res->dump;    }    { my $cache = undef;    sub auth_token {        return $cache if $cache;        my $opt = config();        my $res = $ua->post( '', [            Email  => $opt->{'email'},            Passwd => $opt->{'password'},            service => 'blogger',            accountType => 'GOOGLE',            source => 'ruz_at_cpan-pod2blog-1',        ] );        my ($auth) = ($res->content =~ /^Auth=(.*?)$/m)            or die "Couldn't authenticate: ". $res->dump;        return $cache = $auth;    } }    { my $cache;    sub config {        return $cache if $cache;        require File::HomeDir;        require File::Spec;        require YAML::Any;        $cache = YAML::Any::LoadFile( File::Spec->catfile(            File::HomeDir->my_home, '.blogger.yml'        ) );        return $cache;    } }    use Pod::Parser;    package MyParser;    use base qw(Pod::Parser);    use XML::LibXML;    sub begin_input {        my $self = shift;        use XML::Atom::Entry;        $self->{'entry'} = XML::Atom::Entry->new( Namespace => '' );        my $doc = $self->{'doc'} = XML::LibXML->createDocument( "1.0", "UTF-8" );        my $root = $self->{'in'} = $doc->createElement('div');        $doc->setDocumentElement( $root );    }    sub end_input {        my $self = shift;        $self->{'entry'}->content(            $self->{'doc'}->documentElement->toString,        );        return $self->{'entry'};    }    sub command {         my ($self, $command, $paragraph, $line_num) = @_;        if ($command eq 'head1') {            my $expansion = $self->interpolate($paragraph, $line_num);            $self->{'entry'}->title( $expansion );        }        elsif ( $command eq 'tags' ) {            $self->{'entry'}->add_category( {term => $_, scheme => ''} )                foreach map { s/^\s+//;s/\s+$//;$_ } split /,/, $paragraph;        }    }    sub verbatim {         my ($self, $para, $line_num) = @_;        my $e;        if ( $self->{'last'} && $self->{'last'}->nodeName eq 'pre' ) {            $e = $self->{'last'};        } else {            $e = $self->{'last'} = $self->{'doc'}->createElement('pre');        }        $e->appendTextNode( $para );        $self->{'in'}->appendChild( $e );        return $e;    }    sub textblock {         my ($self, $paragraph, $line_num) = @_;        my %parse_opts = (            -expand_seq => 'interior_sequence',            -expand_text => sub { return $_[0]->{'doc'}->createTextNode( $_[1] ) },        );        my $expansion = $self->parse_text( \%parse_opts, $paragraph, $line_num );        my $e = $self->{'last'} = $self->{'doc'}->createElement('p');        $e->appendChild( $_ ) foreach $expansion->children;        $self->{'in'}->appendChild( $e );        return $e;    }    sub interior_sequence {         my ($self, $cmd, $arg, $node) = @_;        if ( $cmd eq 'B' ) {            my $e = $self->{'doc'}->createElement('strong');            $e->appendChild( $_ ) foreach $node->parse_tree->children;            return $e;        }        return $arg;    }    sub parse_from_file {        my $self = shift;        my $fname = $_[0];        # XXX: set publish time        return $self->SUPER::parse_from_file( @_ );    }