misleading error message from from_object?

[email protected] (Edward Baudrez)
Newsgroups perl.datetime
Message-ID <[email protected]>
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]
from_object.t (text/troff, 2.2 KB)
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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.