line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
48885
|
use 5.006; # our |
|
1
|
|
|
|
|
3
|
|
2
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
18
|
|
3
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
60
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
package Acme::Data::Dumper::Extensions; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.001000'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# ABSTRACT: Experimental Enhancements to core Data::Dumper |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# AUTHORITY |
12
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
7
|
use Data::Dumper (); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
15
|
|
14
|
1
|
|
|
1
|
|
4
|
use Exporter (); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
26
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my $DD_Defaults; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
BEGIN { |
19
|
1
|
|
|
1
|
|
5
|
no warnings 'once'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
107
|
|
20
|
1
|
|
|
1
|
|
12
|
$DD_Defaults = { |
21
|
|
|
|
|
|
|
Bless => q[bless], |
22
|
|
|
|
|
|
|
Deepcopy => 0, |
23
|
|
|
|
|
|
|
Deparse => 0, |
24
|
|
|
|
|
|
|
Freezer => q[], |
25
|
|
|
|
|
|
|
Indent => 2, |
26
|
|
|
|
|
|
|
Maxdepth => 0, |
27
|
|
|
|
|
|
|
Pad => q[], |
28
|
|
|
|
|
|
|
Pair => q[ => ], |
29
|
|
|
|
|
|
|
Purity => 0, |
30
|
|
|
|
|
|
|
Quotekeys => 1, |
31
|
|
|
|
|
|
|
Sortkeys => 0, |
32
|
|
|
|
|
|
|
Terse => 0, |
33
|
|
|
|
|
|
|
Toaster => q[], |
34
|
|
|
|
|
|
|
Useperl => !( grep $_ eq 'Data::Dumper', @DynaLoader::dl_modules ), |
35
|
|
|
|
|
|
|
Useqq => 0, |
36
|
|
|
|
|
|
|
Varname => q[VAR], |
37
|
|
|
|
|
|
|
}; |
38
|
|
|
|
|
|
|
|
39
|
1
|
50
|
|
|
|
2
|
$DD_Defaults->{Sparseseen} = 0 if eval { Data::Dumper->VERSION(2.136) }; |
|
1
|
|
|
|
|
24
|
|
40
|
1
|
50
|
|
|
|
3
|
$DD_Defaults->{Maxrecurse} = 1000 if eval { Data::Dumper->VERSION(2.153) }; |
|
1
|
|
|
|
|
8
|
|
41
|
1
|
50
|
|
|
|
2
|
$DD_Defaults->{Trailingcomma} = 0 if eval { Data::Dumper->VERSION(2.160) }; |
|
1
|
|
|
|
|
278
|
|
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub DD_Defaults { |
45
|
0
|
|
|
0
|
0
|
|
{ %$DD_Defaults } |
|
0
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
our $_new_with_defaults = sub { |
49
|
|
|
|
|
|
|
my ( $self, $user_defaults ) = @_; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
my $instance = $self->new( [] ); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Initialise with system defaults |
54
|
|
|
|
|
|
|
my $instance_defaults = { %{$DD_Defaults} }; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Validate and overwrite user defaults |
57
|
|
|
|
|
|
|
for my $key ( sort keys %{ $user_defaults || {} } ) { |
58
|
|
|
|
|
|
|
if ( not exists $DD_Defaults->{$key} ) { |
59
|
|
|
|
|
|
|
my $guesskey = ucfirst( lc($key) ); |
60
|
|
|
|
|
|
|
my $dym = |
61
|
|
|
|
|
|
|
exists $DD_Defaults->{$guesskey} |
62
|
|
|
|
|
|
|
? sprintf q[ (did you mean '%s'?)], $guesskey |
63
|
|
|
|
|
|
|
: q[]; |
64
|
|
|
|
|
|
|
die sprintf "Unknown feature '%s'%s", $key, $dym; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
$instance_defaults->{$key} = $user_defaults->{$key}; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# Set all values |
70
|
|
|
|
|
|
|
for my $key ( sort keys %{$instance_defaults} ) { |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Properties that aren't methods are bad? |
73
|
|
|
|
|
|
|
my $sub = $instance->can($key); |
74
|
|
|
|
|
|
|
die "No setter for feature '$key'" unless $sub; |
75
|
|
|
|
|
|
|
$instance->$sub( $instance_defaults->{$key} ); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
return $instance; |
78
|
|
|
|
|
|
|
}; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
our $_DumpValues = sub { |
81
|
|
|
|
|
|
|
my ( $self, $values, $names ) = @_; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
die "Expected array of values to dump" if not defined $values; |
84
|
|
|
|
|
|
|
die "Dump values is not an array" unless q[ARRAY] eq ref $values; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
$names = [] unless defined $names; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
my (@out) = $self->Reset()->Names($names)->Values($values)->Dump; |
89
|
|
|
|
|
|
|
$self->Reset()->Names( [] )->Values( [] ); |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
return wantarray ? @out : join q[], @out; |
92
|
|
|
|
|
|
|
}; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
our @EXPORT_OK = qw( $_new_with_defaults $_DumpValues ); |
95
|
|
|
|
|
|
|
|
96
|
1
|
|
|
1
|
|
34
|
BEGIN { *import = \&Exporter::import; } |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
1; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=head1 NAME |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Acme::Data::Dumper::Extensions - Experimental Enhancements to core Data::Dumper |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 SYNOPSIS |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
use Data::Dumper; |
107
|
|
|
|
|
|
|
use Acme::Data::Dumper::Extensions qw/$_new_with_defaults/; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
local $Data::Dumper::Indent = 5; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
my $instance = Data::Dumper->$_new_with_defaults({ }); # Indent is still 2! |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
$instance = Data::Dumper->$_new_with_defaults({ |
114
|
|
|
|
|
|
|
Indent => 4, # Easier initalizer |
115
|
|
|
|
|
|
|
}); |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head1 DESCRIPTION |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
This is just a testing ground for things that I'm suggesting for Data::Dumper. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
It will likely be terrible because bolting on features after-the-fact its also |
122
|
|
|
|
|
|
|
pretty ugly. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
But its just a prototype. |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
For some, it will serve more as a proof-of-concept for various interfaces until |
127
|
|
|
|
|
|
|
they get accepted into core. |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=head1 EXPORTS |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head2 C<$_new_with_defaults> |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
This is a prototype function for construcing a Data::Dumper instance without |
134
|
|
|
|
|
|
|
being prone to leak from other people using the global values. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
At the time of this writing, if you need perfect consistency from Data::Dumper |
137
|
|
|
|
|
|
|
in widely used code, you by necessity have to know every version of |
138
|
|
|
|
|
|
|
Data::Dumper that exists, and know what the default values are of various |
139
|
|
|
|
|
|
|
arguments, in order to revert them to your "known good" state if 3rd party |
140
|
|
|
|
|
|
|
code decides to locally change those values for their own purposes. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Getting an instance of a Data::Dumper object before anyone tweaks those values |
143
|
|
|
|
|
|
|
would also work, but trying to bet on getting loaded and getting an instance |
144
|
|
|
|
|
|
|
before anyone else does is just foolhardy |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Additionally, due to how C<< ->Values >> works, having a global instance of |
147
|
|
|
|
|
|
|
Data::Dumper can lend itself to a memory leak and you have to take additional |
148
|
|
|
|
|
|
|
care to make sure you free values passed to it. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head3 Syntax |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
The name used here is C<$_new_with_defaults> as this makes it straight forward |
153
|
|
|
|
|
|
|
to migrate code that uses this once its adopted, without needing to |
154
|
|
|
|
|
|
|
monkey-patch Data::Dumper itself. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Data::Dumper->$_new_with_defaults( ... ) |
157
|
|
|
|
|
|
|
Data::Dumper->new_with_defaults( ... ) |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head3 Arguments |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Using the defaults |
162
|
|
|
|
|
|
|
Data::Dumper->$_new_with_defaults() |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Augmenting the defaults |
165
|
|
|
|
|
|
|
Data::Dumper->$_new_with_defaults({ Name => value, Name => value }); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
The approach I've taken here is to ignore the standard arguments to C, |
168
|
|
|
|
|
|
|
because it wasn't clear to me how else to organise this with the existing |
169
|
|
|
|
|
|
|
alternative interfaces. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Given there's an alternative way of passing the dump values, its suggested |
172
|
|
|
|
|
|
|
to just use those until this part of the design is sorted out: |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Data::Dumper->$_new_with_defaults()->Values([ stuff, to, dump ])->Dump(); |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Or use the other feature suggested in this module: |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
Data::Dumper->$_new_with_defaults()->$_DumpValues([ stuff, to, dump ]); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head3 Unrecognised Features |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
I'm still not sure how to handle what happens when somebody passes the name |
183
|
|
|
|
|
|
|
of a feature which doesn't exist yet, but does in a future version. |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Ideally, calling C<$_new_with_defaults()> should give you the same results in |
186
|
|
|
|
|
|
|
perpetuity ( or at least, from the date this feature gets added ) |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
For now I think the best thing to do is die fatally if a feature that is |
189
|
|
|
|
|
|
|
requested can't be provided, as that will produce output other than is desired |
190
|
|
|
|
|
|
|
and violate output consistency as a result. |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
This will just become a nightmare if somebody ever changes "The Default" for |
193
|
|
|
|
|
|
|
a I feature wherein, users have to I<< Opt-B >>, causing an |
194
|
|
|
|
|
|
|
explosion on older versions where that feature didn't exist. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
This should be a hazard to never even consider changing the default behaviour. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head2 C<$_DumpValues> |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
This function is a helper that does what people who maintain a long-lived |
201
|
|
|
|
|
|
|
C instance generally desire: The ability to just set up an |
202
|
|
|
|
|
|
|
instance, and then call it an arbitrary number of times with arbitrary inputs |
203
|
|
|
|
|
|
|
and have it act without side effects. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
However, the current implementation of Data::Dumper is such that if you have |
206
|
|
|
|
|
|
|
an instance, you must B store the data in the object, and B |
207
|
|
|
|
|
|
|
dump it, which introduces fun problems with your data living longer than you |
208
|
|
|
|
|
|
|
intended it to. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
Currently, you also must call C<< ->Reset >> after dumping to reset the |
211
|
|
|
|
|
|
|
C state. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
This function is designed to be used atomically. Any pre-existing variable |
214
|
|
|
|
|
|
|
state (eg: C, C, C ) should be thouroughly ignored, and |
215
|
|
|
|
|
|
|
any of those values will be left in a "reset" state after using this function. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
It is thus inadvisable to combine use of this function with others. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
If you need complex behaviours provided by the more advanced interfaces, its |
220
|
|
|
|
|
|
|
recommended to use those instead. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head3 Syntax |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# Dump array of values as a string |
225
|
|
|
|
|
|
|
$instance->$_DumpValues( [ values ] ); |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
# Dump array of values with predefined names |
228
|
|
|
|
|
|
|
$instance->$_DumpValues( [ values, ... ], [ names, ... ]); |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=head3 Arguments |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
The first argument (required) must be an C of values to dump. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
This value will B be used instead of any instances of C passed |
235
|
|
|
|
|
|
|
earlier. Any values previously passed to C will be preserved. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
The second (optional) argument is an C of names to use for values. |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
If this option is omitted, it will behave as if you'd passed C<[]>. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
If this option is present, passed values used instead. |