Skip Menu |

This queue is for tickets about the Params-Validate CPAN distribution.

Report information
The Basics
Id: 4089
Status: resolved
Priority: 0/
Queue: Params-Validate

People
Owner: Nobody in particular
Requestors: marek.rouchal [...] infineon.com
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 0.67
Fixed in: (no value)



Subject: Use Error to throw validation exceptions
I'd like Params::Validate to throw exceptions a la Error::Simple (see the "Error" module). The problem I face is that I cannot simply say: use Error; Params::Validate::validation_options( on_fail => sub { throw Error::Simple($_[0]); } ); since this would report the exception happening in the anonymous sub, and not in the real place (i.e. the sub where validate(...) was called). A quick hack (see below) solves the problem, but has the disadvantage that it does not work when validate is called in an anonymous sub - i did not find a simple way how to determine the real calling sub in that context. Note that the caller stack looks rather different when the validate call is in a "try { ... }" block or not - which means I cannot use a constant value for caller(). Here is a sample script (using latest Params::Validate and Error): #!/usr/bin/perl -w use strict; use Error qw(:try); use Params::Validate qw(validate_pos); ####################################################################### # THE FOLLOWING COULD BE AN EXTENSION FOR PARAMS::VALIDATE ####################################################################### package Error::Params::Validate; @Error::Params::Validate::ISA = qw(Error); sub new { my ($self, $msg) = @_; my ($pack,$file,$line,$sub); my $i = 0; do { ($pack,$file,$line,$sub) = caller(++$i); #print "DEBUG: p=$pack f=$file l=$line s=$sub\n"; } while($pack =~ /^Error::/ || $sub =~ /^Error::|__ANON__$/); chomp $msg; $msg =~ s/\S+::__ANON__\b/$sub/; local $Error::Depth = $Error::Depth + 1; $self->SUPER::new(-text => $msg, -file => $file, -line => $line, '-package' => $pack) } sub stringify { my $self = shift; my $text = $self->SUPER::stringify; $text .= sprintf(" at %s line %d.\n", $self->file, $self->line) unless($text =~ /\n$/s); $text; } ####################################################################### # END (THE FOLLOWING COULD BE AN EXTENSION FOR PARAMS::VALIDATE) ####################################################################### package main; Params::Validate::validation_options( on_fail => sub { throw Error::Params::Validate $_[0]; } ); mysub('foobar'); mysub2('foobar'); exit 0; sub mysub { my @par = @_; try { validate_pos( @par, 1, 1 ); } catch Error::Params::Validate with { my $E = shift; print "ERROR:\n"; foreach(sort keys %$E) { print " $_ => ",$E->{$_},"\n"; } }; print "mysub GOT: +$_[0]+\n"; } sub mysub2 { my @par = @_; validate_pos( @par, 1, 1 ); print "mysub2 GOT: +$_[0]+\n"; } __END__ I think the best would be if one could specify sth. like Params::Validate::validation_options( on_fail_throw => 'Error::Params::Validate' } ); or the like... and of course it has to work if the "validate" call is in a try { ... } block or not. By the way: the Params::Validate manual contains this: * on_fail => $callback If given, this callback will be called whenever a valĀ­ idation check fails. It will be called with a single parameter, which will be a string describing the failĀ­ ure. This is useful if you wish to have this module throw exceptions as objects rather than as strings, for example. I missed an example here - maybe everything is very simple and I just did not get it. Best regards, Marek
[MAREKR - Mon Oct 13 02:49:23 2003]: Show quoted text
> I'd like Params::Validate to throw exceptions a la Error::Simple > (see the "Error" module). The problem I face is that I cannot simply > say:
Well, I'm not a big fan of the Error module. You'll note that I'm the author of Exception::Class, so if I were to integrate any exception throwing, it'd probably be with Exception::Class. I _think_ that the best way to solve this, however, is to write your own custom Error subclass that goes back on the stack til it finds the relevant caller (not in Params::Validate) using caller(), and sets the various Error object fields appropriately.