Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Data-Printer CPAN distribution.

Report information
The Basics
Id: 68597
Status: resolved
Priority: 0/
Queue: Data-Printer

People
Owner: Nobody in particular
Requestors: RANDIR [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 0.19



Subject: Filter output test is wrong
Despite of what's stated in documentation (test for defined), filter output is tested just to be true. That leads to some weird cases, like %cat Data/Printer/Filter/Z.pm package Data::Printer::Filter::Z; use Data::Printer::Filter; filter 'SCALAR', sub { my ($ref, $properties) = @_; my $val = $$ref; return $val + 1; }; 1;% perl -e 'use Data::Printer {filters => {-external => [ 'Z' ]}}; $a=[-2, -1, 0]; p $a' \ [ [0] -1, [1] , [2] 1 ] Furthermore, defining a filter that overrides default type (SCALAR/HASH/ARRAY) doesn't allow default fallback when filter doesn't return anything (contrary to class filters call). Patch for the 1st is attached, but 2nd - i prefer it to be corrected too, but don't know what should be filter expected behavior.
Subject: data-printer.filter-def.diff
--- lib/Data/Printer.pm +++ lib/Data/Printer.pm @@ -248,7 +248,7 @@ # filter item (if user set a filter for it) if ( exists $p->{filters}->{$ref} ) { foreach my $filter ( @{ $p->{filters}->{$ref} } ) { - if ( my $result = $filter->($item, $p) ) { + if ( defined(my $result = $filter->($item, $p)) ) { $string .= $result; last; } @@ -456,7 +456,7 @@ my $visited = 0; if ( exists $p->{filters}->{'-class'} ) { foreach my $filter ( @{ $p->{filters}->{'-class'} } ) { - if ( my $result = $filter->($item, $p) ) { + if ( defined(my $result = $filter->($item, $p)) ) { $string .= $result; $visited = 1; last;
On Wed Jun 01 10:25:00 2011, RANDIR wrote: Show quoted text
> Despite of what's stated in documentation (test for defined), filter > output is tested just to be true. That leads to some weird cases, like > > %cat Data/Printer/Filter/Z.pm > package Data::Printer::Filter::Z; > use Data::Printer::Filter; > > filter 'SCALAR', sub { > my ($ref, $properties) = @_; > my $val = $$ref; > return $val + 1; > }; > > 1;% > > perl -e 'use Data::Printer {filters => {-external => [ 'Z' ]}}; $a=[-2, > -1, 0]; p $a' > \ [ > [0] -1, > [1] , > [2] 1 > ] > > Furthermore, defining a filter that overrides default type > (SCALAR/HASH/ARRAY) doesn't allow default fallback when filter doesn't > return anything (contrary to class filters call). Patch for the 1st is > attached, but 2nd - i prefer it to be corrected too, but don't know what > should be filter expected behavior.
Hi again :) Thanks for the patch and for noticing the odd behavior. Indeed I initially only allowed non-native types to be stacked. As of version 0.17, it is possible to add several filters to native types as well, either by doing: use Data::Printer filters => { SCALAR => [ sub { ... }, sub { ... } ], }; or as stand-alone filters just like you did: filter 'SCALAR', sub { ... }; filter 'SCALAR', sub { ... }; Filters will be tried from newest to oldest added (LIFO). If a filter returns an undefined value (again, thanks for the patch) it will try the next one, eventually falling back to the default provided by Data::Printer. Please let me know as soon as you can confirm this is fixed so we can close the ticket :)
It looks good now for built-in types, both override case and fallback case, but fallback for '-classes' is missing, so the following test case fails: game@sigeon% cat Data/Printer/Filter/Z.pm package Data::Printer::Filter::Z; use Data::Printer::Filter; filter 'MyClass', sub { return; }; 1; game@sigeon% perl -e 'use Data::Printer {filters => {-external => [ 'Z' ]}}; $a=bless {}, "MyClass"; p $a' <nothing printed>
Quick fix: --- lib/Data/Printer.pm +++ lib/Data/Printer.pm @@ -193,15 +193,18 @@ # filter item (if user set a filter for it) + my $found = 0; if ( exists $p->{filters}->{$ref} ) { foreach my $filter ( @{ $p->{filters}->{$ref} } ) { if ( defined (my $result = $filter->($item, $p)) ) { + $found = 1; $string .= $result; last; } } } - else { + + if ( !$found ) { # let '-class' filters have a go foreach my $filter ( @{ $p->{filters}->{'-class'} } ) { if ( defined (my $result = $filter->($item, $p)) ) {
It's now OK in 0.19