Skip to content

Instantly share code, notes, and snippets.

@vyuh
Last active May 14, 2018 17:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vyuh/c02c909ef8e0cb46121f9456dae2b715 to your computer and use it in GitHub Desktop.
Save vyuh/c02c909ef8e0cb46121f9456dae2b715 to your computer and use it in GitHub Desktop.
Data::Walk Bug Report and Patch
Subject: Top Level Object should not have a container
Data::Walk Version 2.01 assigns `container` and `type` for top-level objects
in an inconsistent way. On one hand, A scalar at top level gets the
arrayref of `@args` as `container`, and `ARRAY` as `type`. Whereas
a hashref, or arrayref, at top-level gets *ITSELF* as the `container`,
and its own ref type (`ARRAY|HASH`) as `type`. The latter behaviour
is not consistent because it implies that the item is contained in
itself.
A set of rules for consistent behaviour regarding top-level objects can be:
- Top level object passed to `walk` has `$Data::Walk::depth == 1`.
- `$Data::Walk::container` and `$Data::Walk::type` is `undef` for such objects.
(They have no container, and hence, no container type.)
A patch against commit b3f9af86587a513d9a3a1e8f318ef6a30e328872 is included
here.
Summary of Changes:
- new file: t/05bug-container-type-at-depth-one.t
Tests the above consistent behaviour for
the following calls of `Data::Walk::walk`:
- Single hashref argument
`walk sub { ... }, $hashref;`
- Single arrayref argument
`walk sub { ... }, $arrayref;`
- Many argument with the first one as scalar
`walk sub { ... }, 5, $hash,$arrayref;`
- modified: t/04bug-container-type-by-depth.t
Makes the test compliant to the above mentioned consistent behaviour.
- modified: lib/Data/Walk.pm
Fix setting of Top-Level Objects' container
fix-setting-top-level-container.patch
-------------------------------------
diff --git a/lib/Data/Walk.pm b/lib/Data/Walk.pm
index 1ca491c..b714ce6 100755
--- a/lib/Data/Walk.pm
+++ b/lib/Data/Walk.pm
@@ -71,23 +71,7 @@ sub __walk {
local $index = 0;
foreach my $item (@args) {
- local ($container, $type, $depth);
- if (ref $item) {
- if (UNIVERSAL::isa ($item, 'HASH')) {
- $container = $item;
- $type = 'HASH';
- } elsif (UNIVERSAL::isa ($item, 'ARRAY')) {
- $container = $item;
- $type = 'ARRAY';
- } else {
- $container = \@args;
- $type = 'ARRAY';
- }
- } else {
- $container = \@args;
- $type = 'ARRAY';
- }
- $depth = 0;
+ local $depth = 0;
__recurse $options, $item;
++$index;
}
diff --git a/t/04bug-container-type-by-depth.t b/t/04bug-container-type-by-depth.t
index 6bed43c..3f18435 100755
--- a/t/04bug-container-type-by-depth.t
+++ b/t/04bug-container-type-by-depth.t
@@ -23,14 +23,36 @@ use Test;
use Data::Walk;
BEGIN {
- plan tests => 10;
+ plan tests => 20;
}
my $data = {
foo => 'bar',
baz => 'bazoo',
};
-walk sub {
- ok $Data::Walk::type, 'HASH';
- ok $Data::Walk::container, $data;
-}, $data;
+
+Data::Walk::walk +{
+ wanted => sub {
+ if ($Data::Walk::depth == 1) {
+ ok $Data::Walk::type, undef;
+ ok $Data::Walk::container, undef;
+ } elsif ($Data::Walk::depth == 2) {
+ ok $Data::Walk::type, 'HASH';
+ ok $Data::Walk::container, $data;
+ }
+ },
+ bydepth => 1
+ }, $data;
+Data::Walk::walk +{
+ wanted => sub {
+ if ($Data::Walk::depth == 1) {
+ ok $Data::Walk::type, undef;
+ ok $Data::Walk::container, undef;
+ } elsif ($Data::Walk::depth == 2) {
+ ok $Data::Walk::type, 'HASH';
+ ok $Data::Walk::container, $data;
+ }
+ },
+ bydepth => 0
+ }, $data;
+__END__
diff --git a/t/05bug-container-type-at-depth-one.t b/t/05bug-container-type-at-depth-one.t
new file mode 100644
index 0000000..027aff0
--- /dev/null
+++ b/t/05bug-container-type-at-depth-one.t
@@ -0,0 +1,83 @@
+# Data::Walk - Traverse Perl data structures.
+# Copyright (C) 2005-2016 Guido Flohr <guido.flohr@cantanea.com>,
+# all rights reserved.
+
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+# USA.
+
+use strict;
+
+use Test;
+use Data::Walk;
+
+BEGIN {
+ plan tests => 28;
+}
+
+my $hash = {
+ foo => 'bar',
+ baz => 'bazoo',
+};
+
+my $arr = [
+ "moo",
+ "foo",
+ 1
+];
+
+walk sub {
+ if ($Data::Walk::depth == 1) {
+ #The top level has no container
+ ok $Data::Walk::type, undef;
+ #Hence no type for container
+ ok $Data::Walk::container, undef;
+ }
+ elsif ( $Data::Walk::depth == 2) {
+ ok $Data::Walk::type, q/HASH/;
+ ok $Data::Walk::container, $hash;
+ }
+}, $hash;
+
+
+walk sub {
+ if ($Data::Walk::depth == 1) {
+ #The top level has no container
+ ok $Data::Walk::type, undef;
+ #Hence no type for container
+ ok $Data::Walk::container, undef;
+ }
+ elsif ( $Data::Walk::depth == 2) {
+ ok $Data::Walk::type, q/ARRAY/;
+ ok $Data::Walk::container, $arr;
+ }
+}, $arr;
+
+walk sub {
+ if ($Data::Walk::depth == 1) {
+ #The top level has no container
+ ok $Data::Walk::type, undef;
+ #Hence no type for container
+ ok $Data::Walk::container, undef;
+ }
+}, $hash, $arr;
+
+walk sub {
+ if ($Data::Walk::depth == 1) {
+ #The top level has no container
+ ok $Data::Walk::type, undef;
+ #Hence no type for container
+ ok $Data::Walk::container, undef;
+ }
+}, 1, $hash, $arr;
@gflohr
Copy link

gflohr commented May 14, 2018

I have moved Data-Walk to github: https://github.com/gflohr/Data-Walk

Do you want to create a pull request? That probably gives better documentation. Otherwise, I can also jsut apply your patch.

@vyuh
Copy link
Author

vyuh commented May 14, 2018

Ok, I'll create a pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment