Template::Timer and Test::MockObject don’t appear to play nice

My google juice didn’t seem to work today so I needed mst to help me find this.  I figured I’d better note it down so at least I can find it again in the future.

https://rt.cpan.org/Public/Bug/Display.html?id=16805

I was getting this error on a few (but definitely not all) of my tests when trying to load them up in the perl debugger.

Couldn't load class (OurApp) because: Couldn't load class (Company::AppKit::View::AppKitTT) because: Couldn't load class (Catalyst::View::TT) because: Died at Template/Timer.pm line 69.

This was a catalyst application. It turns out that Test::MockObject and Template::Timer don’t appear to get on. The bug report explains it all far better than I can. It also looks like no-one wants to fix it right now. The problem only really appears to affect debugging and only then with Test::MockObject so you should find it easy enough to patch that locally on your dev box only and not worry about it thereafter.

Getting out of CPAN hell

This is a quick and dirty way to reinstall/upgrade all your modules in cpan (assuming you have cpanm installed).


grep "C<Module> L<" `perldoc -l perllocal` | grep -v MyInternalModules | cut -c 46- | cut -d "|" -f 1 | sort | uniq | xargs cpanm --sudo

This is pretty brittle and only for emergencies.  Another trick pointed out by JJ who pointed me to perllocal is to grep the list further before the sort | uniq to just modules your likely to be interested in, to those starting Moose or Catalyst perhaps for example.

Another thing that I just realised is that while cpan* may not be perfect with spotting problem dependencies there are a lot of modules that make a fair effort to spot problems for you.  Moose and Catalyst both have checks in their makefiles to spot incompatble modules and warn you about them.  See the check_conflicts function in the Moose makefile for example.  This is the one area that running cpanm might bite.  The lack of spurious output also sometimes means lack of valuable output messages.  If you have run cpanm and are now experiencing problems you might want to check your logs to see if there were some conflicts,

find ~/.cpanm -name build.log -exec grep "conflicts with" {} \; -print

If you are upgrading a big module like Moose it might be worth flipping cpanm into verbose mode (-v) to spot those warnings when they happen.

* I don’t really mean the module CPAN.  Just the whole eco system of distributions and so on.  It’s a complex problem and not easily sorted in such a way that means it just works out of the box, although it’s pretty close…

 

More perl debuggin

I’ve been figuring out more about the perl debugger.  Specifically the watch command now.  At first I thought it was a fairly lame command but it looks like it has more potential than I realised, or at the very least it was instrumental in me figuring out a weird problem we were having with our Catalyst application.

When we took a look at our app’s module version number it came back as 0.00001 despite it plainly being something different.  When we build the module using Module::Install it created the package with the correct version number.  It wasn’t until we tried to display the version number on our pages that we realised everything else thought the version number was 0.00001.  Even a perl -I lib -MCompany::AppName\ 9999 displayed 0.00001.

In the end I loaded up the debugger and added a watch on $Company::AppName::VERSION to see what was happening.

DB<2> w $Company::AppName::VERSION
DB<3> c
Watchpoint 0:   $Company::AppName::VERSION changed:
 old value:  ''
 new value:  '1.01'
Company::AppName::CODE(0x2b6f930)(/home/colin/svn/Company/AppName/script/../lib/Company/AppName.pm:10):
10: Company::AppName::Builder->new( appname => __PACKAGE__ )->bootstrap;

DB<3> c
Watchpoint 0:   $Company::AppName::VERSION changed:
 old value:  '1.01'
 new value:  '0.00001'
Class::MOP::Module::_instantiate_module(/opt/perl5.10.1/lib/site_perl/5.10.1/x86_64-linux/Class/MOP/Module.pm:67):
67:     ${ $package_name . '::AUTHORITY' } = $authority if defined $authority;

DB<3> T
. = Class::MOP::Module::_instantiate_module(ref(Moose::Meta::Class), 0.00001, undef)
$ = Class::MOP::Class::create('Moose::Meta::Class', 'Company::AppName', 'superclasses', ref(ARRAY), 'version', 0.00001)
$ = Moose::Meta::Class::create('Moose::Meta::Class', 'Company::AppName', 'version', 0.00001, 'superclasses', ref(ARRAY))
. = CatalystX::AppBuilder::BUILD(ref(Company::AppName::Builder), ref(HASH))
. = Class::MOP::Method::execute(ref(Moose::Meta::Method), ref(Company::AppName::Builder), ref(HASH))
. = Moose::Object::BUILDALL(ref(Company::AppName::Builder), ref(HASH))
$ = Moose::Meta::Class::new_object(ref(Moose::Meta::Class), ref(HASH))

With the watchpoint installed as soon as the debugger loaded it was possible to see our version number being set, then see it being overwritten with the bogus value.  Each time the value changed the debugger stopped.  The second time I did a stack trace and a little investigation showed the new value was coming from CatalystX::AppBuilder.  We’re using that module to build our apps and it turns out that want you to set a version number and it will set that on your module.  If you don’t specify it you get it’s default 0.00001.  All we need to do is change our builder line to specify the version and our module version is preserved.

Company::AppName::Builder->new( appname => __PACKAGE__, version => $VERSION )->bootstrap;

I had thought watches were only really useful in a local scope when you were perhaps watching a loop to check what was happening with your variables, more as a way to save typing x, but it looks like it’s a lot more useful.

The main thing I haven’t managed to figure out yet is how to keep track of a variable that doesn’t have a globally accessible handle and gets passed about a lot.  Being able to spot changes in that type of variable would be really handy.