Hi list

I've stumbled upon (what I think is) a misleading error message from 
from_object(). Basically, the following code

  my $now = DateTime->now;
  my $copy = DateTime->from_object( $now );

should tell me I've omitted the mandatory 'object =>' key (as the docs state, 
so definitely my bad). However, the error message was confusing:

  The following parameter was passed in the call to DateTime::from_object but 
was not listed in the validation options: local_rd_secs

It seems I'm not the only person who's confused (e.g., 
http://code.google.com/p/panchanga/issues/detail?id=1 and a few more).

I've tried tracing the problem, but I admit it's beyond my comprehension. I 
vaguely suspect the overloading, because DateTime->from_object( $whatever ) 
--with $whatever being anything else than a DateTime object-- fails as it 
should, but I have no proof whatsoever.

I'm attaching a test script that exposes the behaviour, and an (ugly?) 
workaround. Useful?



Best regards
Edward Baudrez
--
Royal Meteorological Institute of Belgium
Remote Sensing from Space
Ringlaan 3, 1180 Ukkel, Belgium
+32 2 373 0623
[email protected]
use strict;
use warnings;
use Test::More;
use Test::Exception;
use DateTime;
use Carp qw( longmess confess );

# BACKGROUND
# this is the right way to call DateTime->from_object() (from the docs): the 'object' key is mandatory
my $now = DateTime->now;
ok $now;
my $copy = DateTime->from_object( object => $now );
ok $copy;
# calling DateTime->from_object() without 'object' dies:
throws_ok { DateTime->from_object( {} ) } qr/^Mandatory parameter 'object' missing in call to DateTime::from_object$/m;
# however, the following two die with an error message that is less explicit:
throws_ok { DateTime->from_object( 1 ) } qr/^Odd number of parameters in call to DateTime::from_object when named parameters were expected$/m;
throws_ok { DateTime->from_object( [] ) } qr/^Odd number of parameters in call to DateTime::from_object when named parameters were expected$/m;
# and this gives a misleading error message:
throws_ok { DateTime->from_object( $now ) }
	qr/^(Mandatory parameter 'object' missing in call to DateTime::from_object|Odd number of parameters in call to DateTime::from_object when named parameters were expected)$/m;
# fails instead with
# 'The following parameter was passed in the call to DateTime::from_object but was not listed in the validation options: local_rd_secs'

# INVESTIGATION
# inspecting the arguments that validate() receives (set $show_args = 1 below)
# shows that validate() receives the object as the only argument, but somehow
# fails to notice the absence of the 'object' key
*real_validate = \&DateTime::validate;
my $show_args = 0;
if( $show_args ) {
	no warnings 'redefine';
	local *DateTime::validate = sub (\@$) {
		note longmess '- CALLING validate()';
		note "\$_[$_] = ", explain $_[ $_ ] for 0 .. $#_;
		&real_validate
	};
	eval { DateTime->from_object( $now ) };
}

# POSSIBLE WORKAROUND
*real_from_object = \&DateTime::from_object;
{
	no warnings 'redefine';
	local *DateTime::from_object = sub {
		my $class = shift;
		confess( "Mandatory parameter 'object' missing in call to " . (caller 0)[3] . "\n" ) unless grep /^object$/, @_;
		real_from_object( $class, @_ );
	};
	throws_ok { DateTime->from_object( $now ) } qr/^Mandatory parameter 'object' missing in call to /;
}

done_testing;

Reply via email to