houseabsolute / Params-ValidationCompiler

Build an optimized subroutine parameter validator once, use it forever
https://metacpan.org/release/Params-ValidationCompiler/
Other
4 stars 5 forks source link

Can't validate an array of enum #22

Closed 2shortplanks closed 6 years ago

2shortplanks commented 6 years ago

I'm not sure if this is a Params::ValidationCompiler issue or a moose issue, but...

#!/usr/bin/perl

use strict;
use warnings;

use Test2::Bundle::Extended;
use Params::ValidationCompiler qw(validation_for);

use MooseX::Types::Moose qw( ArrayRef );

use MooseX::Types -declare => [
    qw(
        DayOfTheWeek
        )
];

enum DayOfTheWeek, [
    qw(
        monday
        tuesday
        wednesday
        thursday
        friday
        saturday
        sunday
        )
];

my $dow_validator = validation_for(
    params => [
        days => { type => ArrayRef[ DayOfTheWeek ] },
    ],
    named_to_list => 1,
);

sub weekend {
    my ($days) = $dow_validator->(@_);
    return "My days off are " . join ',',@{ $days };
}

is(
    weekend(days => ['saturday','sunday']),
    "My days off are saturday, sunday"
);

done_testing;

Gives a horrible horrible error:

Mark@travis:~$ perl /tmp/foo.pl
Failed to compile source: Global symbol "%enums0" requires explicit package name (did you forget to declare "my %enums0"?) at (eval 258) line 61.

source:
sub { my %args;
if ( @_ % 2 == 0 ) {
    %args = @_;
}
elsif ( @_ == 1 ) {
    if ( ref $_[0] ) {
        if ( Scalar::Util::blessed( $_[0] ) ) {
            if ( overload::Overloaded( $_[0] )
                && defined overload::Method( $_[0], '%{}' ) ) {

                %args = %{ $_[0] };
            }
            else {
                Params::ValidationCompiler::Exception::BadArguments->throw(
                    message =>
                        'Expected a hash or hash reference but a single object argument was passed to an un-named validation subroutine',
                    show_trace => 1,
                );
            }
        }
        elsif ( ref $_[0] eq 'HASH' ) {
            %args = %{ $_[0] };
        }
        else {
            Params::ValidationCompiler::Exception::BadArguments->throw(
                message =>
                    'Expected a hash or hash reference but a single '
                    . ( ref $_[0] )
                    . ' reference argument was passed to an un-named validation subroutine',
                show_trace => 1,
            );
        }
    }
    else {
        Params::ValidationCompiler::Exception::BadArguments->throw(
            message =>
                'Expected a hash or hash reference but a single non-reference argument was passed to an un-named validation subroutine',
            show_trace => 1,
        );
    }
}
else {
    Params::ValidationCompiler::Exception::BadArguments->throw(
        message =>
            'Expected a hash or hash reference but an odd number of arguments was passed to an un-named validation subroutine',
        show_trace => 1,
    );
}

exists $args{"days"}
    or Params::ValidationCompiler::Exception::Named::Required->throw(
    message    => "days" . ' is a required parameter for an un-named validation subroutine',
    parameter  => "days",
    show_trace => 1,
    );

if ( !( do { do {my $check = $args{"days"};ref($check) eq "ARRAY" && &List::Util::all(sub { ( do { defined($_) && !ref($_) && $enums0{$_} } ) }, @{$check})} } ) ) {
    my $type  = $types{"days"};
    my $param = "days";
    my $value = $args{"days"};
    my $msg   = $param . q{ failed with: } . $type->get_message($value);
    die
        Params::ValidationCompiler::Exception::ValidationFailedForMooseTypeConstraint
        ->new(
        message   => $msg,
        parameter => $param,
        value     => $value,
        type      => $type,
        );
}

my @extra = grep { !$known{$_} } keys %args;
if (@extra) {
    my $u = join ', ', sort @extra;
    Params::ValidationCompiler::Exception::Named::Extra->throw(
        message    => "Found extra parameters passed to an un-named validation subroutine: [$u]",
        parameters => \@extra,
        show_trace => 1,
    );
}

return $args{"days"}; }; at /opt/markperl/lib/site_perl/5.22.0/Params/ValidationCompiler/Compiler.pm line 213.
autarch commented 6 years ago

This is almost certainly a bug in PVC. I thought I'd squashed this sort of bug though. Are you using the most recent version of PVC?

2shortplanks commented 6 years ago

I'm using version 0.26, so yes. Latest version of Moose too.

autarch commented 6 years ago

Yeah, I figured. This is definitely a bug. I'll try to look into it soonish, but feel free to nag me about it next week.

autarch commented 6 years ago

Frabjous day! It's a bug in Moose, not PVC ...

package Foo;

use strict;
use warnings;

use Devel::Dwarn;
use Moose::Util::TypeConstraints;

enum 'Colors' => [qw( red green blue )];

my $type = subtype( as 'ArrayRef[Colors]' );

warn $type->_inline_check('$foo');
Dwarn $type->_inline_environment;

And that prints ...

$> perl ./foo.pl 
( do { do {my $check = $foo;ref($check) eq "ARRAY" && &List::Util::all(sub { ( do { defined($_) && !ref($_) && $enums0{$_} } ) }, @{$check})} } ) at ./foo.pl line 13.
{}

So PR for Moose is welcome ;)

autarch commented 6 years ago

Actually, I take it back, it might be a bug in PVC ...

autarch commented 6 years ago

Fixed in v0.27