Codebase list libdata-printer-perl / 07365fa
Merge tag 'upstream/0.31' Upstream version 0.31 Nuno Carvalho 11 years ago
65 changed file(s) with 1310 addition(s) and 141 deletion(s). Raw diff Collapse all Expand all
00 Revision history for Data-Printer
1
2 0.31 2012-08-09
3 BUG FIXES:
4 - fixed test failures in 5.8
5
6 OTHER:
7 - releasing as stable version
8
9 0.30_06 2012-07-22
10 NEW FEATURES:
11 - new filter for DateTime::Tiny
12
13 OTHER:
14 - new tip: using DDP with Template Toolkit
15
16 0.30_05 2012-07-21
17 NEW FEATURES:
18 - Add support for FORMAT and LVALUE refs (Rebecca Turner)
19
20 BUG FIXES:
21 - prevent warning when dumping refs to unopened or closed
22 file handles (Rebecca Turner)
23 - on Win32, it is allowed to use an RC file without
24 read-only permissions
25
26 0.30_04 2012-07-08
27 NEW FEATURES:
28 - Improved support for unknown core datatypes (Rebecca Turner)
29
30 BUG FIXES:
31 - fixed indentation when using colored output (Stanislaw Pusep)
32 - fixed t/05-obj.t on older perls (Mike Doherty)
33 - fixed dev-only pod tests
34 - Issue warning (carp) when color/colour is not a hashref
35
36 0.30_03 2012-07-05
37 NEW FEATURES:
38 - new class property 'universal', letting you choose whether
39 to include UNIVERSAL methods during inheritance display
40 or not (default is 1, meaning to show).
41 - support for VSTRINGs (Rebecca Turner)
42
43 NEW ***EXPERIMENTAL*** FEATURES:
44 - new 'show_readonly' property, off by default, to show
45 variables marked as read-only
46 (scalars only for now, patches welcome!)
47
48 BUG FIXES:
49 - fixed issue with t/05-obj.t
50 - minor pod fixes (Rebecca Turner, myself)
51 - Protect against unknown core data types that don't implement "can" (Rebecca Turner)
52
53 0.30_02 2012-07-02
54 BUG FIXES:
55 - RC file under taint mode should be properly parsed now.
56
57 OTHER:
58 - Rob Hoeltz and Stephen Thirlwall added to the
59 contributors list. Thanks guys!
60
61 0.30_01 2012-07-02
62 CHANGES THAT BREAK BACKWARDS COMPATIBILITY:
63 - linear_isa option is now set to 'auto' by default (see below)
64
65 NEW FEATURES:
66 - linear_isa can now be set to 'auto', in which case
67 it will show the @ISA only if the object has more than
68 one parent. Other values are 0 (never show) and 1 (always show)
69 - new "Digest" filter bundle, for MD5, SHA and other Digest objects!
70 - separate colours for classes and methods (feature request
71 by Ivan Bessarabov)
72 - environment variable DATAPRINTERRC overrides .dataprinter
73 and lets you pick different RCs at will (Stephen Thirlwall)
74 - new option 'separator' lets you pick a custom separator
75 for array/hash elements, including none (''). Default is ','.
76 - new option 'end_separator' can be set to 1 to show the last
77 item of an array or hash with a separator (Ivan Bessarabov)
78 - DateTime filter bundle now also handles DateTime::TimeZone
79 objects (RT#77755)
80
81 BUG FIXES:
82 - RC file now works under taint mode, with restrictions
83 (feature request by Rob Hoelz)
84 - class_method call now includes properties hashref (Joel Berger)
85
86 OTHER:
87 - Replacement of dependencies to permit pure perl operation:
88 Class::MOP is replaced with mro and Package::Stash
89 Clone is replaced with Clone::PP
90 Hash::FieldHash is replaced with Hash::Util::FieldHash
91 Note that if <5.10 is detected, Data::Printer also requires:
92 MRO::Compat to provide mro
93 Hash::Util::FieldHash::Compat to provide Hash::Util::FieldHash
94 As a result, Data::Printer should now be fatpackable (cpan:MSTROUT)
95 - new /examples dir, with a sample file to let you easily try
96 different color schemes (Yanick Champoux)
97 - pod coverage tests (developer only)
198
299 0.30 2012-02-13
3100 CHANGES THAT BREAK BACKWARDS COMPATIBILITY:
17114 - new 'quote_keys' property to add quotes in hash
18115 keys. Defaults to 'auto' which means it will
19116 quote keys containing spaces (and empty keys)
117
20118 BUG FIXES:
21119 - fixed temporary file handling during tests. Thanks
22120 Andy Bach for reporting and providing a patch.
00 Changes
1 examples/try_me.pl
12 lib/Data/Printer.pm
23 lib/Data/Printer/Filter.pm
34 lib/Data/Printer/Filter/DateTime.pm
45 lib/Data/Printer/Filter/DB.pm
6 lib/Data/Printer/Filter/Digest.pm
57 lib/DDP.pm
68 Makefile.PL
79 MANIFEST This list of files
2426 t/12-filter_class.t
2527 t/13-filter_datetime.t
2628 t/13.2-filter_db.t
29 t/13.3-filter_digest.t
2730 t/14-local_conf.t
2831 t/15-rc_file.t
2932 t/16-rc_file2.t
3033 t/16.2-rc_overwrite.t
34 t/16.3-rc_env.t
35 t/16.4-rc_env2.t
36 t/16.5-rc_env3.t
3137 t/17-parallel.t
3238 t/18-class_method.t
3339 t/19-tied.t
4854 t/30.2-print_escapes.t
4955 t/31-bad_parameters.t
5056 t/32-quote_keys.t
57 t/33-end_separator.t
58 t/33-separator.t
59 t/34-show_readonly.t
60 t/35-vstrings.t
61 t/36-valign.t
62 t/37-format.t
63 t/38-lvalue.t
64 t/pod-coverage.t
5165 t/pod.t
5266 META.yml Module YAML meta-data (added by MakeMaker)
5367 META.json Module JSON meta-data (added by MakeMaker)
00 ^\.git
1 .pl$
1 ^[^/]+\.pl$
22 ^\ignore.txt
33 ^_build
44 ^Build$
33 "Breno G. de Oliveira <garu@cpan.org>"
44 ],
55 "dynamic_config" : 1,
6 "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.113640",
6 "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921",
77 "license" : [
88 "perl_5"
99 ],
2121 "prereqs" : {
2222 "build" : {
2323 "requires" : {
24 "ExtUtils::MakeMaker" : 0
24 "ExtUtils::MakeMaker" : "0"
2525 }
2626 },
2727 "configure" : {
2828 "requires" : {
29 "ExtUtils::MakeMaker" : 0
29 "ExtUtils::MakeMaker" : "0"
3030 }
3131 },
3232 "runtime" : {
3333 "requires" : {
34 "Carp" : 0,
35 "Class::MOP" : "0.81",
36 "Clone" : 0,
37 "Fcntl" : 0,
34 "Carp" : "0",
35 "Clone::PP" : "0",
36 "Fcntl" : "0",
3837 "File::HomeDir" : "0.91",
39 "File::Spec" : 0,
40 "File::Temp" : 0,
41 "Hash::FieldHash" : 0,
42 "Scalar::Util" : 0,
43 "Sort::Naturally" : 0,
38 "File::Spec" : "0",
39 "File::Temp" : "0",
40 "Package::Stash" : "0.3",
41 "Scalar::Util" : "0",
42 "Sort::Naturally" : "0",
4443 "Term::ANSIColor" : "3",
45 "Test::More" : "0.88"
44 "Test::More" : "0.88",
45 "version" : "0.77"
4646 }
4747 }
4848 },
5858 "url" : "http://github.com/garu/Data-Printer"
5959 }
6060 },
61 "version" : "0.3"
61 "version" : "0.31"
6262 }
66 configure_requires:
77 ExtUtils::MakeMaker: 0
88 dynamic_config: 1
9 generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.113640'
9 generated_by: 'ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921'
1010 license: perl
1111 meta-spec:
1212 url: http://module-build.sourceforge.net/META-spec-v1.4.html
1818 - inc
1919 requires:
2020 Carp: 0
21 Class::MOP: 0.81
22 Clone: 0
21 Clone::PP: 0
2322 Fcntl: 0
2423 File::HomeDir: 0.91
2524 File::Spec: 0
2625 File::Temp: 0
27 Hash::FieldHash: 0
26 Package::Stash: 0.3
2827 Scalar::Util: 0
2928 Sort::Naturally: 0
3029 Term::ANSIColor: 3
3130 Test::More: 0.88
31 version: 0.77
3232 resources:
3333 bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Data-Printer
3434 license: http://dev.perl.org/licenses/
3535 repository: http://github.com/garu/Data-Printer
36 version: 0.3
36 version: 0.31
1212 'Test::More' => 0.88,
1313 'Term::ANSIColor' => 3.0, # introduces 'bright_*' colors
1414 'Scalar::Util' => 0,
15 'version' => 0.77, # handling VSTRINGS
1516 'Sort::Naturally' => 0,
16 'Class::MOP' => 0.81, # get_all_methods() is introduced in 0.65,
17 # but ActivePerl complains about < 0.81
17 'Package::Stash' => 0.30,
1818 'Carp' => 0,
19 'Clone' => 0,
20 'Hash::FieldHash' => 0,
19 'Clone::PP' => 0,
2120 'File::HomeDir' => 0.91, # introduces File::HomeDir::Test
2221 'File::Spec' => 0,
2322 'File::Temp' => 0,
2423 'Fcntl' => 0,
24 ($] >= 5.010
25 ? ()
26 : (
27 'MRO::Compat' => 0.09,
28 'Hash::Util::FieldHash::Compat' => 0.03,
29 )
30 ),
2531 },
2632 META_MERGE => {
2733 resources => {
0 #!/usr/bin/env perl
1 use strict;
2 use warnings;
3 use Scalar::Util qw(weaken);
4
5 # This sample code is available to you so you
6 # can see Data::Printer working out of the box.
7 # It can be used as a quick way to test your
8 # color palette scheme!
9
10 package My::SampleClass;
11 sub new { bless {}, shift }
12 sub public_method { 42 }
13 sub _private_method { 'sample' }
14
15
16 package main;
17
18 my $obj = My::SampleClass->new;
19
20 my %sample = (
21 number => 123.456,
22 string => 'a string',
23 array => [ "foo\0has\tescapes", 6, undef ],
24 hash => {
25 foo => 'bar',
26 baz => 789,
27 },
28 regexp => qr/foo.*bar/i,
29 glob => \*STDOUT,
30 code => sub { return 42 },
31 class => $obj,
32 );
33
34 $sample{ref} = \%sample;
35 weaken $sample{ref};
36
37 use DDP; p %sample;
38
00 package DDP;
1 use strict;
2 use warnings;
13 use Data::Printer;
24
35 BEGIN {
4 push @ISA, 'Data::Printer';
6 push our @ISA, 'Data::Printer';
57 our $VERSION = $Data::Printer::VERSION;
68 }
79 1;
10 __END__
11
12 =head1 DDP - Data::Printer shortcut for faster debugging
13
14 =head1 SYNOPSIS
15
16 use DDP; p $my_data;
17
18 =head1 DESCRIPTION
19
20 Tired of typing C<use Data::Printer> every time? C<DDP> lets you quickly call
21 your favorite variable dumper!
22
23 It behaves exacly like L<Data::Printer> - it is, indeed, just an alias to it :)
24
25 Happy debugging!
26
27 =head1 SEE ALSO
28
29 L<Data::Printer>
30
9898 {
9999 filters => {
100100 -external => [ 'DB' ],
101 },
101102 };
102103
103104
1616 return _format( $string, @_ );
1717 };
1818
19 # DateTime::TimeZone filters
20 filter '-class' => sub {
21 my ($obj, $properties) = @_;
22
23 if ( $obj->isa('DateTime::TimeZone' ) ) {
24 return $obj->name;
25 }
26 else {
27 return;
28 }
29 };
30
1931 filter 'DateTime::Incomplete', sub {
2032 return _format( $_[0]->iso8601, @_ );
2133 };
3042 my $string = "$dur[0]y $dur[1]m $dur[2]d $dur[3]h $dur[4]m $dur[5]s";
3143
3244 return _format( $string, @_ );
45 };
46
47 filter 'DateTime::Tiny', sub {
48 return _format( $_[0]->as_string, @_ );
3349 };
3450
3551 filter 'Date::Calc::Object', sub {
0 package Data::Printer::Filter::Digest;
1 use strict;
2 use warnings;
3 use Data::Printer::Filter;
4 use Term::ANSIColor;
5
6 foreach my $digest (
7 qw( Digest::Adler32 Digest::MD2 Digest::MD4
8 Digest::MD5 Digest::SHA Digest::SHA1
9 Digest::Whirlpool Digest::Haval256
10 )
11 ) {
12 filter $digest, sub {
13 my ($obj, $p) = @_;
14 my $digest = $obj->clone->hexdigest;
15 my $str = $digest;
16 my $ref = ref $obj;
17
18 if ( $p->{digest}{show_class_name} ) {
19 $str .= " ($ref)";
20 }
21
22 unless ( exists $p->{digest}{show_reset}
23 and !$p->{digest}{show_reset}
24 ) {
25 if ($digest eq $ref->new->hexdigest) {
26 $str .= ' [reset]';
27 }
28 }
29
30 my $color = $p->{color}{digest};
31 $color = 'bright_green' unless defined $color;
32
33 return colored( $str, $color );
34
35 };
36 }
37
38 1;
39
40 __END__
41
42 =head1 NAME
43
44 Data::Printer::Filter::Digest - pretty-printing MD5, SHA and friends
45
46 =head1 SYNOPSIS
47
48 In your program:
49
50 use Data::Printer filters => {
51 -external => [ 'Digest' ],
52 };
53
54 or, in your C<.dataprinter> file:
55
56 {
57 filters => {
58 -external => [ 'Digest' ],
59 },
60 };
61
62 You can also setup color and display details:
63
64 use Data::Printer
65 filters => {
66 -external => [ 'Digest' ],
67 },
68 color => {
69 digest => 'bright_green',
70 }
71 digest => {
72 show_class_name => 0, # default.
73 show_reset => 1, # default.
74 },
75 };
76
77 =head1 DESCRIPTION
78
79 This is a filter plugin for L<Data::Printer>. It filters through
80 several digest classes and displays their current value in
81 hexadecimal format as a string.
82
83 =head2 Parsed Modules
84
85 =over 4
86
87 =item * L<Digest::Adler32>
88
89 =item * L<Digest::MD2>
90
91 =item * L<Digest::MD4>
92
93 =item * L<Digest::MD5>
94
95 =item * L<Digest::SHA>
96
97 =item * L<Digest::SHA1>
98
99 =item * L<Digest::Whirlpool>
100
101 =item * L<Digest::Haval256>
102
103 =back
104
105 If you have any suggestions for more modules or better output,
106 please let us know.
107
108 =head2 Extra Options
109
110 Aside from the display color, there are a few other options to
111 be customized via the C<digest> option key:
112
113 =head3 show_class_name
114
115 Set this to true to display the class name right next to the
116 hexadecimal digest. Default is 0 (false).
117
118 =head3 show_reset
119
120 If set to true (the default), the filter will add a C<[reset]>
121 tag after dumping an empty digest object. See the rationale below.
122
123 =head2 Note on dumping Digest::* objects
124
125 The digest operation is effectively a destructive, read-once operation. Once it has been performed, most Digest::* objects are automatically reset and can be used to calculate another digest value.
126
127 This behaviour - or, rather, forgetting about this behaviour - is
128 a common source of issues when working with Digests.
129
130 This Data::Printer filter will B<not> destroy your object. Instead, we work on a cloned version to display the hexdigest, leaving your
131 original object untouched.
132
133 As another debugging convenience for developers, since the empty
134 object will produce a digest even after being used, this filter
135 adds by default a C<[reset]> tag to indicate that the object is
136 empty, in a 'reset' state - i.e. its hexdigest is the same as
137 the hexdigest of a new, empty object of that same class.
138
139 =head1 SEE ALSO
140
141 L<Data::Printer>
142
143
00 package Data::Printer::Filter;
11 use strict;
22 use warnings;
3 use Clone qw(clone);
3 use Clone::PP qw(clone);
4 require Carp;
45 require Data::Printer;
56
67 my %_filters_for = ();
1314
1415 my $filter = sub {
1516 my ($type, $code) = @_;
17
18 Carp::croak "syntax: filter 'Class', sub { ... }"
19 unless $type and $code and ref $code eq 'CODE';
1620
1721 unshift @{ $_filters_for{$id}{$type} }, sub {
1822 my ($item, $p) = @_;
4751
4852 my $imported = sub (\[@$%&];%) {
4953 my ($item, $p) = @_;
50 require Data::Printer;
5154 return Data::Printer::p( $item, %properties );
5255 };
5356
101104
102105 return $ref->some_method; # or whatever
103106
104 # see L</HELPER FUNCTIONS> below for
107 # see 'HELPER FUNCTIONS' below for
105108 # customization options, including
106109 # proper indentation.
107 }
110 };
108111
109112 1;
110113
00 package Data::Printer;
11 use strict;
22 use warnings;
3 use Term::ANSIColor qw(color colored colorstrip);
3 use Term::ANSIColor qw(color colored);
44 use Scalar::Util;
55 use Sort::Naturally;
66 use Carp qw(croak);
7 use Clone qw(clone);
8 use Hash::FieldHash qw(fieldhash);
7 use Clone::PP qw(clone);
8 use if $] >= 5.010, 'Hash::Util::FieldHash' => qw(fieldhash);
9 use if $] < 5.010, 'Hash::Util::FieldHash::Compat' => qw(fieldhash);
910 use File::Spec;
1011 use File::HomeDir ();
1112 use Fcntl;
12
13 our $VERSION = 0.30;
13 use version 0.77 ();
14
15 our $VERSION = '0.31';
1416
1517 BEGIN {
1618 if ($^O =~ /Win32/i) {
3133 'sort_keys' => 1,
3234 'deparse' => 0,
3335 'hash_separator' => ' ',
36 'separator' => ',',
37 'end_separator' => 0,
3438 'show_tied' => 1,
3539 'show_tainted' => 1,
3640 'show_weak' => 1,
41 'show_readonly' => 0,
42 'show_lvalue' => 1,
3743 #'escape_chars' => 1, ### <== DEPRECATED!!!
3844 'print_escapes' => 0,
3945 'quote_keys' => 'auto',
4955 'number' => 'bright_blue',
5056 'string' => 'bright_yellow',
5157 'class' => 'bright_green',
58 'method' => 'bright_green',
5259 'undef' => 'bright_red',
5360 'hash' => 'magenta',
5461 'regex' => 'yellow',
5562 'code' => 'green',
5663 'glob' => 'bright_cyan',
64 'vstring' => 'bright_blue',
65 'lvalue' => 'bright_white',
66 'format' => 'bright_cyan',
5767 'repeated' => 'white on_red',
5868 'caller_info' => 'bright_cyan',
5969 'weak' => 'cyan',
6070 'tainted' => 'red',
6171 'escaped' => 'bright_red',
72 'unknown' => 'bright_yellow on_blue',
6273 },
6374 'class' => {
6475 inherited => 'none', # also 'all', 'public' or 'private'
76 universal => 1,
6577 parents => 1,
66 linear_isa => 1,
78 linear_isa => 'auto',
6779 expand => 1, # how many levels to expand. 0 for none, 'all' for all
6880 internals => 1,
6981 export => 1,
7385 _depth => 0, # used internally
7486 },
7587 'filters' => {
76 SCALAR => [ \&SCALAR ],
77 ARRAY => [ \&ARRAY ],
78 HASH => [ \&HASH ],
79 REF => [ \&REF ],
80 CODE => [ \&CODE ],
81 GLOB => [ \&GLOB ],
82 Regexp => [ \&Regexp ],
83 -class => [ \&_class ],
88 # The IO ref type isn't supported as you can't actually create one,
89 # any handle you make is automatically blessed into an IO::* object,
90 # and those are separately handled.
91 SCALAR => [ \&SCALAR ],
92 ARRAY => [ \&ARRAY ],
93 HASH => [ \&HASH ],
94 REF => [ \&REF ],
95 CODE => [ \&CODE ],
96 GLOB => [ \&GLOB ],
97 VSTRING => [ \&VSTRING ],
98 LVALUE => [ \&LVALUE ],
99 FORMAT => [ \&FORMAT ],
100 Regexp => [ \&Regexp ],
101 -unknown=> [ \&_unknown ],
102 -class => [ \&_class ],
84103 },
85104
86105 _output => *STDERR, # used internally
104123 # the RC file overrides the defaults,
105124 # (and we load it only once)
106125 unless( exists $properties->{_initialized} ) {
107 my $file = ( $args && exists $args->{rc_file} )
108 ? $args->{rc_file}
109 : File::Spec->catfile(File::HomeDir->my_home,'.dataprinter')
110 ;
111
112 if (-e $file) {
113 if ( open my $fh, '<', $file ) {
114 my $rc_data;
115 { local $/; $rc_data = <$fh> }
116 close $fh;
117
118 my $config = eval $rc_data;
119 if ( $@ ) {
120 warn "Error loading $file: $@\n";
121 }
122 elsif (!ref $config or ref $config ne 'HASH') {
123 warn "Error loading $file: config file must return a hash reference\n";
124 }
125 else {
126 $properties = _merge( $config );
127 }
128 }
129 else {
130 warn "error opening '$file': $!\n";
131 }
132 }
126 _load_rc_file($args);
133127 $properties->{_initialized} = 1;
134128 }
135129
180174 elsif ($ref eq 'HASH') {
181175 return %{ $item };
182176 }
183 elsif ( grep { $ref eq $_ } qw(REF SCALAR CODE Regexp GLOB) ) {
177 elsif ( grep { $ref eq $_ } qw(REF SCALAR CODE Regexp GLOB VSTRING) ) {
184178 return $$item;
185179 }
186180 else {
279273 }
280274 }
281275
282 if (not $found) {
276 if (not $found and Scalar::Util::blessed($item) ) {
283277 # let '-class' filters have a go
284278 foreach my $filter ( @{ $p->{filters}->{'-class'} } ) {
285279 if ( defined (my $result = $filter->($item, $p)) ) {
286280 $string .= $result;
281 $found = 1;
282 last;
283 }
284 }
285 }
286
287 if ( not $found ) {
288 # if it's not a class and not a known core type, we must be in
289 # a future perl with some type we're unaware of
290 foreach my $filter ( @{ $p->{filters}->{'-unknown'} } ) {
291 if ( defined (my $result = $filter->($item, $p)) ) {
292 $string .= $result;
287293 last;
288294 }
289295 }
322328 if $p->{show_tainted} and Scalar::Util::tainted($$item);
323329
324330 $p->{_tie} = ref tied $$item;
331
332 if ($p->{show_readonly} and &Internals::SvREADONLY( $item )) {
333 $string .= ' (read-only)';
334 }
325335
326336 return $string;
327337 }
401411 $string .= ' ' . colored('(weak)', $p->{color}->{'weak'})
402412 if $ref and Scalar::Util::isweak($item->[$i]) and $p->{show_weak};
403413
404 $string .= ($i == $#{$item} ? '' : ',') . $BREAK;
414 $string .= $p->{separator}
415 if $i < $#{$item} || $p->{end_separator};
416
417 $string .= $BREAK;
418
405419 my $size = 2 + length($i); # [10], [100], etc
406420 substr $p->{name}, -$size, $size, '';
407421 }
498512
499513 # length of the largest key is used for indenting
500514 if ($multiline) {
501 my $l = length colorstrip($colored);
515 my $l = length $colored;
502516 $len = $l if $l > $len;
503517 }
504518 }
530544 and $p->{show_weak}
531545 and Scalar::Util::isweak($item->{$raw_key});
532546
533 $string .= (--$total_keys == 0 ? '' : ',') . $BREAK;
547 $string .= $p->{separator}
548 if --$total_keys > 0 || $p->{end_separator};
549
550 $string .= $BREAK;
534551
535552 my $size = 2 + length($raw_key); # {foo}, {z}, etc
536553 substr $p->{name}, -$size, $size, '';
566583 return $string;
567584 }
568585
586 sub VSTRING {
587 my ($item, $p) = @_;
588 my $string = '';
589 $string .= colored(version->declare($$item)->normal, $p->{color}->{'vstring'});
590 return $string;
591 }
592
593 sub FORMAT {
594 my ($item, $p) = @_;
595 my $string = '';
596 $string .= colored("FORMAT", $p->{color}->{'format'});
597 return $string;
598 }
599
600 sub LVALUE {
601 my ($item, $p) = @_;
602 my $string = SCALAR( $item, $p );
603 $string .= colored( ' (LVALUE)', $p->{color}{lvalue} )
604 if $p->{show_lvalue};
605
606 return $string;
607 }
569608
570609 sub GLOB {
571610 my ($item, $p) = @_;
579618 # implement some of these flags (maybe not even
580619 # fcntl() itself, so we must wrap it.
581620 my $flags;
582 eval { $flags = fcntl($$item, F_GETFL, 0) };
621 eval { no warnings qw( unopened closed ); $flags = fcntl($$item, F_GETFL, 0) };
583622 if ($flags) {
584623 $extra .= ($flags & O_WRONLY) ? 'write-only'
585624 : ($flags & O_RDWR) ? 'read/write'
592631 # Solaris, for example, doesn't have O_ASYNC :(
593632 my %flags = ();
594633 eval { $flags{'append'} = O_APPEND };
595 eval { $flags{'async'} = O_ASYNC };
634 eval { $flags{'async'} = O_ASYNC }; # leont says this is the only one I should care for.
596635 eval { $flags{'create'} = O_CREAT };
597636 eval { $flags{'truncate'} = O_TRUNC };
598637 eval { $flags{'nonblocking'} = O_NONBLOCK };
603642 $extra .= ', ';
604643 }
605644 my @layers = ();
606 eval { @layers = PerlIO::get_layers $$item };
645 eval { @layers = PerlIO::get_layers $$item }; # TODO: try PerlIO::Layers::get_layers (leont)
607646 unless ($@) {
608647 $extra .= "layers: @layers";
609648 }
613652 return $string;
614653 }
615654
655
656 sub _unknown {
657 my($item, $p) = @_;
658 my $ref = ref $item;
659
660 my $string = '';
661 $string = colored($ref, $p->{color}->{'unknown'});
662 return $string;
663 }
616664
617665 sub _class {
618666 my ($item, $p) = @_;
619667 my $ref = ref $item;
620668
621669 # if the user specified a method to use instead, we do that
622 if ( $p->{class_method} and $item->can($p->{class_method}) ) {
623 my $method = $p->{class_method};
624 return $item->$method;
670 if ( $p->{class_method} and my $method = $item->can($p->{class_method}) ) {
671 return $method->($item, $p);
625672 }
626673
627674 my $string = '';
643690
644691 $p->{_current_indent} += $p->{indent};
645692
646 require Class::MOP;
647 my $meta = Class::MOP::Class->initialize($ref);
648
649 if ( my @superclasses = $meta->superclasses ) {
693 if ($] >= 5.010) {
694 require mro;
695 } else {
696 require MRO::Compat;
697 }
698 require Package::Stash;
699
700 my $stash = Package::Stash->new($ref);
701
702 if ( my @superclasses = @{$stash->get_symbol('@ISA')||[]} ) {
650703 if ($p->{class}{parents}) {
651704 $string .= (' ' x $p->{_current_indent})
652705 . 'Parents '
655708 ) . $BREAK;
656709 }
657710
658 if ($p->{class}{linear_isa}) {
711 if ( $p->{class}{linear_isa} and
712 (
713 ($p->{class}{linear_isa} eq 'auto' and @superclasses > 1)
714 or
715 ($p->{class}{linear_isa} ne 'auto')
716 )
717 ) {
659718 $string .= (' ' x $p->{_current_indent})
660719 . 'Linear @ISA '
661720 . join(', ', map { colored( $_, $p->{color}->{'class'}) }
662 $meta->linearized_isa
721 @{mro::get_linear_isa($ref)}
663722 ) . $BREAK;
664723 }
665724 }
666725
667 $string .= _show_methods($ref, $meta, $p)
726 $string .= _show_methods($ref, $p)
668727 if $p->{class}{show_methods} and $p->{class}{show_methods} ne 'none';
669728
670729 if ( $p->{'class'}->{'internals'} ) {
708767
709768
710769 sub _show_methods {
711 my ($ref, $meta, $p) = @_;
770 my ($ref, $p) = @_;
712771
713772 my $string = '';
714773 my $methods = {
717776 };
718777 my $inherited = $p->{class}{inherited} || 'none';
719778
779 require B;
780
781 my $methods_of = sub {
782 my ($name) = @_;
783 map {
784 my $m;
785 if ($_
786 and $m = B::svref_2object($_)
787 and $m->isa('B::CV')
788 and not $m->GV->isa('B::Special')
789 ) {
790 [ $m->GV->STASH->NAME, $m->GV->NAME ]
791 } else {
792 ()
793 }
794 } values %{Package::Stash->new($name)->get_all_symbols('CODE')}
795 };
796
797 my %seen_method_name;
798
720799 METHOD:
721 foreach my $method ($meta->get_all_methods) {
722 my $method_string = $method->name;
800 foreach my $method (
801 map $methods_of->($_), @{mro::get_linear_isa($ref)},
802 $p->{class}{universal} ? 'UNIVERSAL' : ()
803 ) {
804 my ($package_string, $method_string) = @$method;
805
806 next METHOD if $seen_method_name{$method_string}++;
807
723808 my $type = substr($method_string, 0, 1) eq '_' ? 'private' : 'public';
724809
725 if ($method->package_name ne $ref) {
810 if ($package_string ne $ref) {
726811 next METHOD unless $inherited ne 'none'
727812 and ($inherited eq 'all' or $type eq $inherited);
728 $method_string .= ' (' . $method->package_name . ')';
813 $method_string .= ' (' . $package_string . ')';
729814 }
730815
731816 push @{ $methods->{$type} }, $method_string;
742827 $string .= (' ' x $p->{_current_indent})
743828 . "$type methods (" . scalar @list . ')'
744829 . (@list ? ' : ' : '')
745 . join(', ', map { colored($_, $p->{color}->{class}) }
830 . join(', ', map { colored($_, $p->{color}->{method}) }
746831 @list
747832 ) . $BREAK;
748833 }
784869 foreach my $key (keys %$p) {
785870 if ($key eq 'color' or $key eq 'colour') {
786871 my $color = $p->{$key};
787 if (defined $color and not $color) {
872 if ( not ref $color or ref $color ne 'HASH' ) {
873 Carp::carp q['color' should be a HASH reference. Did you mean 'colored'?];
788874 $clone->{color} = {};
789875 }
790876 else {
791 foreach my $target ( keys %{$p->{$key}} ) {
877 foreach my $target ( keys %$color ) {
792878 $clone->{color}->{$target} = $p->{$key}->{$target};
793879 }
794880 }
875961 }
876962
877963
964 sub _load_rc_file {
965 my $args = shift || {};
966
967 my $file = exists $args->{rc_file} ? $args->{rc_file}
968 : exists $ENV{DATAPRINTERRC} ? $ENV{DATAPRINTERRC}
969 : File::Spec->catfile(File::HomeDir->my_home,'.dataprinter');
970
971 return unless -e $file;
972
973 my $mode = (stat $file )[2];
974 if ($^O !~ /Win32/i && ($mode & 0020 || $mode & 0002) ) {
975 warn "rc file '$file' must NOT be writeable to other users. Skipping.\n";
976 return;
977 }
978
979 if ( -l $file || (!-f _) || -p _ || -S _ || -b _ || -c _ ) {
980 warn "rc file '$file' doesn't look like a plain file. Skipping.\n";
981 return;
982 }
983
984 unless (-o $file) {
985 warn "rc file '$file' must be owned by your (effective) user. Skipping.\n";
986 return;
987 }
988
989 if ( open my $fh, '<', $file ) {
990 my $rc_data;
991 { local $/; $rc_data = <$fh> }
992 close $fh;
993
994 if( ${^TAINT} != 0 ) {
995 if ( $args->{allow_tainted} ) {
996 warn "WARNING: Reading tainted file '$file' due to user override.\n";
997 $rc_data =~ /(.+)/s; # very bad idea - god help you
998 $rc_data = $1;
999 }
1000 else {
1001 warn "taint mode on: skipping rc file '$file'.\n";
1002 return;
1003 }
1004 }
1005
1006 my $config = eval $rc_data;
1007 if ( $@ ) {
1008 warn "Error loading $file: $@\n";
1009 }
1010 elsif (!ref $config or ref $config ne 'HASH') {
1011 warn "Error loading $file: config file must return a hash reference\n";
1012 }
1013 else {
1014 $properties = _merge( $config );
1015 }
1016 }
1017 else {
1018 warn "error opening '$file': $!\n";
1019 }
1020 }
1021
1022
8781023 1;
8791024 __END__
8801025
10831228 number => 'bright_blue', # numbers
10841229 string => 'bright_yellow', # strings
10851230 class => 'bright_green', # class names
1231 method => 'bright_green', # method names
10861232 undef => 'bright_red', # the 'undef' value
10871233 hash => 'magenta', # hash keys
10881234 regex => 'yellow', # regular expressions
10891235 code => 'green', # code references
10901236 glob => 'bright_cyan', # globs (usually file handles)
1237 vstring => 'bright_blue', # version strings (v5.16.0, etc)
10911238 repeated => 'white on_red', # references to seen values
10921239 caller_info => 'bright_cyan', # details on what's being printed
10931240 weak => 'cyan', # weak references
10941241 tainted => 'red', # tainted content
10951242 escaped => 'bright_red', # escaped characters (\t, \n, etc)
1243
1244 # potential new Perl datatypes, unknown to Data::Printer
1245 unknown => 'bright_yellow on_blue',
10961246 },
10971247 };
10981248
11481298 show_tied => 1, # expose tied variables
11491299 show_tainted => 1, # expose tainted variables
11501300 show_weak => 1, # expose weak references
1301 show_readonly => 0, # expose scalar variables marked as read-only
1302 show_lvalue => 1, # expose lvalue types
11511303 print_escapes => 0, # print non-printable chars as "\n", "\t", etc.
11521304 quote_keys => 'auto', # quote hash keys (1 for always, 0 for never).
11531305 # 'auto' will quote when key is empty/space-only.
1306 separator => ',', # uses ',' to separate array/hash elements
1307 end_separator => 0, # prints the separator after last element in array/hash.
1308 # the default is 0 that means not to print
11541309
11551310 caller_info => 0, # include information on what's being printed
11561311 use_prototypes => 1, # allow p(%foo), but prevent anonymous data
11671322 inherited => 'none', # show inherited methods,
11681323 # can also be 'all', 'private', or 'public'.
11691324
1170 parents => 1, # show parents?
1171 linear_isa => 1, # show the entire @ISA, linearized
1325 universal => 1, # include UNIVERSAL methods in inheritance list
1326
1327 parents => 1, # show parents, if there are any
1328 linear_isa => 'auto', # show the entire @ISA, linearized, whenever
1329 # the object has more than one parent. Can
1330 # also be set to 1 (always show) or 0 (never).
11721331
11731332 expand => 1, # how deep to traverse the object (in case
11741333 # it contains other objects). Defaults to
13261485
13271486 You can even set this to undef or to a non-existing file to disable your
13281487 RC file at will.
1488
1489 The RC file location can also be specified with the C<DATAPRINTERRC>
1490 environment variable. Using C<rc_file> in code will override the environment
1491 variable.
1492
1493 =head2 RC File Security
1494
1495 The C<.dataprinter> RC file is nothing but a Perl hash that
1496 gets C<eval>'d back into the code. This means that whatever
1497 is in your RC file B<WILL BE INTERPRETED BY PERL AT RUNTIME>.
1498 This can be quite worrying if you're not the one in control
1499 of the RC file.
1500
1501 For this reason, Data::Printer takes extra precaution before
1502 loading the file:
1503
1504 =over 4
1505
1506 =item * The file has to be in your home directory unless you
1507 specifically point elsewhere via the 'C<rc_file>' property or
1508 the DATAPRINTERRC environment variable;
1509
1510 =item * The file B<must> be a plain file, never a symbolic
1511 link, named pipe or socket;
1512
1513 =item * The file B<must> be owned by you (i.e. the effective
1514 user id that ran the script using Data::Printer);
1515
1516 =item * The file B<must> be read-only for everyone but your user.
1517 This usually means permissions C<0644>, C<0640> or C<0600> in
1518 Unix-like systems. B<THIS IS NOT CHECKED IN WIN32>;
1519
1520 =item * The file will B<NOT> be loaded in Taint mode, unless
1521 you specifically load Data::Printer with the 'allow_tainted'
1522 option set to true. And even if you do that, Data::Printer
1523 will still issue a warning before loading the file. But
1524 seriously, don't do that.
1525
1526 =back
1527
1528 Failure to comply with the security rules above will result in
1529 the RC file not being loaded (likely with a warning on what went
1530 wrong).
1531
13291532
13301533 =head1 THE "DDP" PACKAGE ALIAS
13311534
16401843 HTML escaped output of C<p($object)>, so you can print it for
16411844 later inspection or render it (if it's a web app).
16421845
1846 =head2 Using Data::Printer with Template Toolkit
1847
1848 I<< (contributed by Stephen Thirlwall (sdt)) >>
1849
1850 If you use Template Toolkit and want to dump your variables using Data::Printer,
1851 install the L<Template::Plugin::DataPrinter> module and load it in your template:
1852
1853 [% USE DataPrinter %]
1854
1855 The provided methods match those of C<Template::Plugin::Dumper>:
1856
1857 ansi-colored dump of the data structure in "myvar":
1858 [% DataPrinter.dump( myvar ) %]
1859
1860 html-formatted, colored dump of the same data structure:
1861 [% DataPrinter.dump_html( myvar ) %]
1862
1863 The module allows several customization options, even letting you load it as a
1864 complete drop-in replacement for Template::Plugin::Dumper so you don't even have
1865 to change your previous templates!
1866
16431867 =head2 Unified interface for Data::Printer and other debug formatters
16441868
16451869 I<< (contributed by Kevin McGrath (catlgrep)) >>
16951919
16961920 You can check you L<dip>'s own documentation for more information and options.
16971921
1922 =head2 Sample output for color fine-tuning
1923
1924 I<< (contributed by Yanick Champoux (yanick)) >>
1925
1926 The "examples/try_me.pl" file included in this distribution has a sample
1927 dump with a complex data structure to let you quickly test color schemes.
1928
16981929
16991930 =head1 BUGS
17001931
17561987
17571988 =item * Fitz Elliott
17581989
1990 =item * Ivan Bessarabov (bessarabv)
1991
17591992 =item * J Mash
17601993
17611994 =item * Jesse Luehrs (doy)
17621995
1996 =item * Joel Berger (jberger)
1997
17631998 =item * Kartik Thakore (kthakore)
17641999
17652000 =item * Kevin Dawson (bowtie)
17802015
17812016 =item * Przemysław Wesołek (jest)
17822017
2018 =item * Rebecca Turner (iarna)
2019
2020 =item * Rob Hoelz (hoelzro)
2021
17832022 =item * Sebastian Willing (Sewi)
17842023
17852024 =item * Sergey Aleynikov (randir)
17862025
2026 =item * Stanislaw Pusep (syp)
2027
2028 =item * Stephen Thirlwall (sdt)
2029
17872030 =item * sugyan
17882031
17892032 =item * Tatsuhiko Miyagawa (miyagawa)
17932036 =item * Torsten Raudssus (Getty)
17942037
17952038 =item * Wesley Dal`Col (blabos)
2039
2040 =item * Yanick Champoux (yanick)
17962041
17972042 =back
17982043
00 #!perl
11
2 use Test::More tests => 2;
2 use Test::More tests => 1;
33
44 BEGIN {
55 diag( "Beginning Data::Printer tests in $^O with Perl $], $^X" );
6 use_ok( 'Class::MOP' ) || print "Bail out!
7 ";
8 diag( "Trying to load Data::Printer with Class::MOP $Class::MOP::VERSION" );
96 use_ok( 'Data::Printer' ) || print "Bail out!
107 ";
118 }
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33
44 BEGIN {
55 delete $ENV{ANSI_COLORS_DISABLED};
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use_ok ('Term::ANSIColor');
89 use_ok ('Data::Printer', colored => 1);
33
44 BEGIN {
55 delete $ENV{ANSI_COLORS_DISABLED};
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use Term::ANSIColor;
89 };
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
22
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67 };
78
2324
2425 1;
2526
27 package Baz;
28 sub bar { 42 }
29
30 1;
31
32 package Meep;
33 our @ISA = qw(Foo Baz);
34
35 1;
36
37 package ParentLess;
38 sub new { bless {}, shift }
39
40 1;
41
2642 package main;
2743 use Test::More;
2844 use Data::Printer;
2945
30 my $old_MOP = 0;
31 eval 'use Class::MOP 2.0300';
32 $old_MOP = 1 if $@;
33
3446 my $obj = Foo->new;
3547
3648 is( p($obj), 'Foo {
3749 Parents Bar
50 public methods (4) : baz, borg, foo, new
51 private methods (1) : _other
52 internals: {
53 test 42
54 }
55 }', 'testing objects' );
56
57 is( p($obj, class => { linear_isa => 1 }), 'Foo {
58 Parents Bar
3859 Linear @ISA Foo, Bar
3960 public methods (4) : baz, borg, foo, new
4061 private methods (1) : _other
4162 internals: {
4263 test 42
4364 }
44 }', 'testing objects' );
65 }', 'testing objects, forcing linear @ISA' );
4566
4667 is( p($obj, class => { parents => 0 }), 'Foo {
47 Linear @ISA Foo, Bar
4868 public methods (4) : baz, borg, foo, new
4969 private methods (1) : _other
5070 internals: {
5272 }
5373 }', 'testing objects (parents => 0)' );
5474
55 is( p($obj, class => { linear_isa => 0 }), 'Foo {
56 Parents Bar
57 public methods (4) : baz, borg, foo, new
58 private methods (1) : _other
59 internals: {
60 test 42
61 }
62 }', 'testing objects (linear_isa => 0)' );
63
6475 is( p($obj, class => { show_methods => 'none' }), 'Foo {
6576 Parents Bar
66 Linear @ISA Foo, Bar
6777 internals: {
6878 test 42
6979 }
7181
7282 is( p($obj, class => { show_methods => 'public' }), 'Foo {
7383 Parents Bar
74 Linear @ISA Foo, Bar
7584 public methods (4) : baz, borg, foo, new
7685 internals: {
7786 test 42
8089
8190 is( p($obj, class => { show_methods => 'private' }), 'Foo {
8291 Parents Bar
83 Linear @ISA Foo, Bar
8492 private methods (1) : _other
8593 internals: {
8694 test 42
8997
9098 is( p($obj, class => { show_methods => 'all' }), 'Foo {
9199 Parents Bar
92 Linear @ISA Foo, Bar
93100 public methods (4) : baz, borg, foo, new
94101 private methods (1) : _other
95102 internals: {
100107 is( p($obj, class => { internals => 0 } ),
101108 'Foo {
102109 Parents Bar
103 Linear @ISA Foo, Bar
104110 public methods (4) : baz, borg, foo, new
105111 private methods (1) : _other
106112 }', 'testing objects (no internals)' );
107113
108114 is( p($obj, class => { inherited => 0 }), 'Foo {
109115 Parents Bar
110 Linear @ISA Foo, Bar
111116 public methods (4) : baz, borg, foo, new
112117 private methods (1) : _other
113118 internals: {
115120 }
116121 }', 'testing objects (inherited => 0)' );
117122
118 my $public = $old_MOP
119 ? 'public methods (5) : bar (Bar), baz, borg, foo, new'
120 : 'public methods (9) : bar (Bar), baz, borg, can (UNIVERSAL), DOES (UNIVERSAL), foo, isa (UNIVERSAL), new, VERSION (UNIVERSAL)'
121 ;
123 my $extra_field = ( $] < 5.010 ) ? '' : ' DOES (UNIVERSAL),';
122124
123125 is( p($obj, class => { inherited => 'all' }), "Foo {
124126 Parents Bar
125 Linear \@ISA Foo, Bar
126 $public
127 public methods (9) : bar (Bar), baz, borg, can (UNIVERSAL),$extra_field foo, isa (UNIVERSAL), new, VERSION (UNIVERSAL)
127128 private methods (2) : _moo (Bar), _other
128129 internals: {
129130 test 42
130131 }
131132 }", 'testing objects (inherited => "all")' );
132133
134 is( p($obj, class => { inherited => 'all', universal => 0 }), "Foo {
135 Parents Bar
136 public methods (5) : bar (Bar), baz, borg, foo, new
137 private methods (2) : _moo (Bar), _other
138 internals: {
139 test 42
140 }
141 }", 'testing objects (inherited => "all", universal => 0)' );
133142
134143 is( p($obj, class => { inherited => 'public' }), "Foo {
135144 Parents Bar
136 Linear \@ISA Foo, Bar
137 $public
145 public methods (9) : bar (Bar), baz, borg, can (UNIVERSAL),$extra_field foo, isa (UNIVERSAL), new, VERSION (UNIVERSAL)
138146 private methods (1) : _other
139147 internals: {
140148 test 42
141149 }
142150 }", 'testing objects (inherited => "public")' );
143151
152 is( p($obj, class => { inherited => 'public', universal => 0 }), "Foo {
153 Parents Bar
154 public methods (5) : bar (Bar), baz, borg, foo, new
155 private methods (1) : _other
156 internals: {
157 test 42
158 }
159 }", 'testing objects (inherited => "public", universal => 0)' );
160
144161 is( p($obj, class => { inherited => 'private' }), 'Foo {
145162 Parents Bar
146 Linear @ISA Foo, Bar
147163 public methods (4) : baz, borg, foo, new
148164 private methods (2) : _moo (Bar), _other
149165 internals: {
158174
159175 is( p($obj), 'Foo {
160176 Parents Bar
161 Linear @ISA Foo, Bar
162177 public methods (4) : baz, borg, foo, new
163178 private methods (1) : _other
164179 internals: {
169184
170185 is( p($obj, class => { expand => 'all'} ), 'Foo {
171186 Parents Bar
172 Linear @ISA Foo, Bar
173187 public methods (4) : baz, borg, foo, new
174188 private methods (1) : _other
175189 internals: {
176190 borg Foo {
177191 Parents Bar
178 Linear @ISA Foo, Bar
179192 public methods (4) : baz, borg, foo, new
180193 private methods (1) : _other
181194 internals: {
186199 }
187200 }', 'testing nested objects with expansion' );
188201
189
202 my $obj_with_isa = Meep->new;
203
204 is( p($obj_with_isa), 'Meep {
205 Parents Foo, Baz
206 Linear @ISA Meep, Foo, Bar, Baz
207 public methods (0)
208 private methods (0)
209 internals: {
210 test 42
211 }
212 }', 'testing objects with @ISA' );
213
214 is( p($obj_with_isa, class => { linear_isa => 0 }), 'Meep {
215 Parents Foo, Baz
216 public methods (0)
217 private methods (0)
218 internals: {
219 test 42
220 }
221 }', 'testing objects with @ISA, opting out the @ISA' );
222
223 is( p($obj_with_isa, class => { linear_isa => 0 }), 'Meep {
224 Parents Foo, Baz
225 public methods (0)
226 private methods (0)
227 internals: {
228 test 42
229 }
230 }', 'testing objects with @ISA' );
231
232 my $parentless = ParentLess->new;
233
234 is( p($parentless), 'ParentLess {
235 public methods (1) : new
236 private methods (0)
237 internals: {}
238 }', 'testing parentless object' );
190239
191240 done_testing;
22
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67 };
78
1313 use Test::More;
1414 BEGIN {
1515 $ENV{ANSI_COLORS_DISABLED} = 1;
16 delete $ENV{DATAPRINTERRC};
1617 use File::HomeDir::Test; # avoid user's .dataprinter
1718 };
1819
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
55
66 BEGIN {
77 $ENV{ANSI_COLORS_DISABLED} = 1;
8 delete $ENV{DATAPRINTERRC};
89 use File::HomeDir::Test; # avoid user's .dataprinter
910
1011 # Time::Piece is only able to overload
4950
5051 SKIP: {
5152 eval 'use DateTime';
52 skip 'DateTime not available', 3 if $@;
53 skip 'DateTime not available', 4 if $@;
5354
5455 my $d1 = DateTime->new( year => 1981, month => 9, day => 29 );
5556 my $d2 = DateTime->new( year => 1984, month => 11, day => 15 );
6768 };
6869
6970 SKIP: {
71 eval 'use DateTime::TimeZone';
72 skip 'DateTime::TimeZone not available', 2 if $@;
73
74 my $d = DateTime::TimeZone->new( name => 'America/Sao_Paulo' );
75 is( p($d), 'America/Sao_Paulo', 'DateTime::TimeZone' );
76 my @list = ($d, { foo => 1 });
77 is( p(@list), '[
78 [0] America/Sao_Paulo,
79 [1] this is a hash
80 ]', 'inline and class filters together (DateTime::TimeZone)'
81 );
82 };
83
84 SKIP: {
7085 eval 'use DateTime::Incomplete';
7186 skip 'DateTime::Incomplete not available', 2 if $@;
7287
7792 [0] 2003-xx-xxTxx:xx:xx,
7893 [1] this is a hash
7994 ]', 'inline and class filters together (DateTime::Incomplete)'
95 );
96 };
97
98 SKIP: {
99 eval 'use DateTime::Tiny';
100 skip 'DateTime::Tiny not available', 2 if $@;
101
102 my $d = DateTime::Tiny->new( year => 2003, month => 3, day => 11 );
103 is( p($d), '2003-03-11T00:00:00', 'DateTime::Tiny' );
104 my @list = ($d, { foo => 1 });
105 is( p(@list), '[
106 [0] 2003-03-11T00:00:00,
107 [1] this is a hash
108 ]', 'inline and class filters together (DateTime::Tiny)'
80109 );
81110 };
82111
55
66 BEGIN {
77 $ENV{ANSI_COLORS_DISABLED} = 1;
8 delete $ENV{DATAPRINTERRC};
89 use File::HomeDir::Test;
910 };
1011
0 use strict;
1 use warnings;
2 use Test::More;
3
4 BEGIN {
5 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
7 use File::HomeDir::Test; # avoid user's .dataprinter
8 };
9
10 use Data::Printer {
11 filters => {
12 -external => [ 'Digest' ],
13 HASH => sub { 'this is a hash' }
14 },
15 };
16
17 my $data = 'I can has Digest?';
18
19 foreach my $module (qw( Digest::Adler32 Digest::MD2 Digest::MD4 Digest::MD5
20 Digest::SHA Digest::SHA1
21 Digest::Whirlpool Digest::Haval256
22 )) {
23
24 SKIP: {
25 eval "use $module";
26 skip "$module not available", 1 if $@;
27
28 my $digest = $module->new;
29 $digest->add( $data );
30
31 my $dump = p $digest;
32 my $named_dump = p $digest, digest => { show_class_name => 1 };
33
34 my @list = ($digest, { foo => 1 });
35 my $list_dump = p @list;
36 my $hex = $digest->hexdigest;
37
38 is( $dump, $hex, $module );
39 is( $named_dump, "$hex ($module)", "$module with class name" );
40
41 is( $list_dump, "[
42 [0] $hex,
43 [1] this is a hash
44 ]", "inline and class filters together ($module)"
45 );
46
47 is( p($digest), $digest->hexdigest . ' [reset]', "reset $module");
48 };
49
50 }
51
52 done_testing;
33
44 BEGIN {
55 delete $ENV{ANSI_COLORS_DISABLED};
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use_ok 'Term::ANSIColor';
89 use_ok 'Data::Printer', colored => 1;
44 my $file;
55 BEGIN {
66 delete $ENV{ANSI_COLORS_DISABLED};
7 delete $ENV{DATAPRINTERRC};
78 use Term::ANSIColor;
89 use File::HomeDir::Test;
910 use File::HomeDir;
1718 if (-e $file) {
1819 plan skip_all => 'File .dataprinter should not be in test homedir';
1920 }
21 umask 0022;
2022 open my $fh, '>', $file
2123 or plan skip_all => "error opening .dataprinter: $!";
2224
44 my $file;
55 BEGIN {
66 delete $ENV{ANSI_COLORS_DISABLED};
7 delete $ENV{DATAPRINTERRC};
78 use_ok ('Term::ANSIColor');
89 use_ok ('File::HomeDir::Test');
910 use_ok ('File::HomeDir');
1718 if (-e $file) {
1819 plan skip_all => 'File .dataprinter should not be in test homedir';
1920 }
21 umask 0022;
2022 open my $fh, '>', $file
2123 or plan skip_all => "error opening .dataprinter: $!";
2224
44 my $file;
55 BEGIN {
66 delete $ENV{ANSI_COLORS_DISABLED};
7 delete $ENV{DATAPRINTERRC};
78 use Term::ANSIColor;
89 use File::HomeDir::Test;
910 use File::HomeDir;
1718 if (-e $file) {
1819 plan skip_all => 'File my_rc_file should not be in test homedir';
1920 }
21 umask 0022;
2022 open my $fh, '>', $file
2123 or plan skip_all => "error opening .dataprinter: $!";
2224
0 use strict;
1 use warnings;
2 use Test::More;
3
4 sub create_rc_file {
5 my ($filename, $content) = @_;
6
7 my $file = File::Spec->catfile(
8 File::HomeDir->my_home,
9 $filename
10 );
11
12 if (-e $file) {
13 plan skip_all => "File $filename should not be in test homedir";
14 }
15 umask 0022;
16 open my $fh, '>', $file
17 or plan skip_all => "error opening $filename: $!";
18
19 print {$fh} $content
20 or plan skip_all => "error writing to $filename: $!";
21
22 close $fh;
23 return $file;
24 }
25
26 my $standard_rcfile;
27 my $custom_rcfile;
28 BEGIN {
29 delete $ENV{ANSI_COLORS_DISABLED};
30 use_ok ('Term::ANSIColor');
31 use_ok ('File::HomeDir::Test');
32 use_ok ('File::HomeDir');
33 use_ok ('File::Spec');
34
35 $standard_rcfile = create_rc_file('.dataprinter',
36 '{ colored => 1, color => { hash => "red" }, hash_separator => " + "}'
37 );
38 $custom_rcfile = create_rc_file('.customrc',
39 '{ colored => 1, color => { hash => "green" }, hash_separator => " % "}'
40 );
41 $ENV{DATAPRINTERRC} = $custom_rcfile;
42
43 # standard and custom rc files created
44 # check that the custom rc overrides the standard one
45 use_ok ('Data::Printer');
46
47 unlink $standard_rcfile or fail('error removing test file');
48 unlink $custom_rcfile or fail('error removing test file');
49 };
50
51 my %hash = ( key => 'value' );
52
53 is( p(%hash), color('reset') . "{$/ "
54 . colored('key', 'green')
55 . ' % '
56 . colored('"value"', 'bright_yellow')
57 . "$/}"
58 , 'custom rc file overrides standard rc file');
59
60 is( p(%hash, color => { hash => 'blue' }, hash_separator => ' * ' ), color('reset') . "{$/ "
61 . colored('key', 'blue')
62 . ' * '
63 . colored('"value"', 'bright_yellow')
64 . "$/}"
65 , 'in-code configuration overrides custom rc file');
66
67 done_testing;
0 use strict;
1 use warnings;
2 use Test::More;
3
4 my $file;
5 BEGIN {
6 delete $ENV{ANSI_COLORS_DISABLED};
7 use_ok ('Term::ANSIColor');
8 use_ok ('File::HomeDir::Test');
9 use_ok ('File::HomeDir');
10 use_ok ('File::Spec');
11
12 $file = File::Spec->catfile(
13 File::HomeDir->my_home,
14 '.customrc'
15 );
16
17 if (-e $file) {
18 plan skip_all => 'File .customrc should not be in test homedir';
19 }
20 umask 0022;
21 open my $fh, '>', $file
22 or plan skip_all => "error opening .customrc: $!";
23
24 print {$fh} '{ colored => 1, color => { hash => "red" }, hash_separator => " + "}'
25 or plan skip_all => "error writing to .customrc: $!";
26
27 close $fh;
28
29 $ENV{DATAPRINTERRC} = $file;
30
31 # file created and in place, check that the explicit configuration below
32 # overrides the custom rc file
33 use_ok ('Data::Printer', {
34 color => {
35 hash => 'blue'
36 },
37 hash_separator => ' * ',
38 });
39 unlink $file or fail('error removing test file');
40 };
41
42 my %hash = ( key => 'value' );
43
44 is( p(%hash), color('reset') . "{$/ "
45 . colored('key', 'blue')
46 . ' * '
47 . colored('"value"', 'bright_yellow')
48 . "$/}"
49 , 'global configuration overrides our custom rc file');
50
51 done_testing;
0 use strict;
1 use warnings;
2 use Test::More;
3
4 sub create_rc_file {
5 my ($filename, $content) = @_;
6
7 my $file = File::Spec->catfile(
8 File::HomeDir->my_home,
9 $filename
10 );
11
12 if (-e $file) {
13 plan skip_all => "File $filename should not be in test homedir";
14 }
15 umask 0022;
16 open my $fh, '>', $file
17 or plan skip_all => "error opening $filename: $!";
18
19 print {$fh} $content
20 or plan skip_all => "error writing to $filename: $!";
21
22 close $fh;
23 return $file;
24 }
25
26 my $code_rcfile;
27 my $env_rcfile;
28 BEGIN {
29 delete $ENV{ANSI_COLORS_DISABLED};
30 use_ok ('Term::ANSIColor');
31 use_ok ('File::HomeDir::Test');
32 use_ok ('File::HomeDir');
33 use_ok ('File::Spec');
34
35 $code_rcfile = create_rc_file('.coderc',
36 '{ colored => 1, color => { hash => "red" }, hash_separator => " + "}'
37 );
38 $env_rcfile = create_rc_file('.envrc',
39 '{ colored => 1, color => { hash => "green" }, hash_separator => " % "}'
40 );
41 $ENV{DATAPRINTERRC} = $env_rcfile;
42
43 # code and env rc files created
44 # check that the rc file specified with rc_file overrides the one
45 # specified with $ENV{DATAPRINTERRC}
46 use_ok ('Data::Printer', rc_file => $code_rcfile);
47
48 unlink $code_rcfile or fail('error removing test file');
49 unlink $env_rcfile or fail('error removing test file');
50 };
51
52 my %hash = ( key => 'value' );
53
54 is( p(%hash), color('reset') . "{$/ "
55 . colored('key', 'red')
56 . ' + '
57 . colored('"value"', 'bright_yellow')
58 . "$/}"
59 , 'custom configuration overrides standard rc file');
60
61 done_testing;
00 use strict;
11 use warnings;
22 BEGIN {
3 delete $ENV{DATAPRINTERRC};
34 use File::HomeDir::Test; # avoid user's .dataprinter
45 use Term::ANSIColor;
56 };
22
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67 };
78
89 package Foo;
9 sub bar { "I exist with " . scalar @_ . " argument" }
10 sub bar { "I exist with " . scalar @_ . " arguments" }
1011 sub _moo { }
1112 sub new { bless {}, shift }
1213
1920
2021 my $obj = Foo->new;
2122
22 is p($obj), 'I exist with 1 argument', 'printing object via class_method "bar()"';
23 is p($obj), 'I exist with 2 arguments', 'printing object via class_method "bar()"';
22
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67 };
78
33 my ($var, $filename);
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use File::HomeDir;
89 use File::Spec;
22
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67
78 use Test::More;
22
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67 };
78
11 use warnings;
22
33 BEGIN {
4 delete $ENV{DATAPRINTERRC};
45 use File::HomeDir::Test; # avoid user's .dataprinter
56 use Term::ANSIColor;
67 };
1213 my $filepath = _get_path();
1314
1415 my $var = [ 1, { foo => 'bar' } ];
15 is p($var), "Printing in line 16 of $filepath:
16 is p($var), "Printing in line " . __LINE__ . " of $filepath:
1617 \\ [
1718 [0] 1,
1819 [1] {
2627 3', 'output with custom caller message';
2728
2829 is p($var, colored => 1), color('reset')
29 . colored("Printing in line 29 of $filepath:", 'bright_cyan')
30 . colored("Printing in line " . (__LINE__ - 1) . " of $filepath:", 'bright_cyan')
3031 . "\n" . colored($var, 'bright_blue')
3132 , 'colored caller message';
3233
3334 is p( $var, colored => 1, color => { caller_info => 'red' } ), color('reset')
34 . colored("Printing in line 34 of $filepath:", 'red')
35 . colored("Printing in line " . (__LINE__ - 1) . " of $filepath:", 'red')
3536 . "\n" . colored($var, 'bright_blue')
3637 , 'custom colored caller message';
3738
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33
44 BEGIN {
55 delete $ENV{ANSI_COLORS_DISABLED};
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use_ok ('Term::ANSIColor');
89 use_ok ('Scalar::Util', qw(weaken));
1313 unless tainted($path);
1414
1515 delete $ENV{ANSI_COLORS_DISABLED};
16 delete $ENV{DATAPRINTERRC};
1617 use File::HomeDir::Test; # avoid user's .dataprinter
1718 use_ok ('Term::ANSIColor');
1819 use_ok ('Data::Printer', colored => 1);
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
22 use Test::More;
33 BEGIN {
44 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
56 use File::HomeDir::Test; # avoid user's .dataprinter
67 };
78
1111 ###########################################
1212 BEGIN {
1313 delete $ENV{ANSI_COLORS_DISABLED};
14 delete $ENV{DATAPRINTERRC};
1415 use File::HomeDir::Test; # avoid user's .dataprinter
1516 use_ok ('Term::ANSIColor');
1617 use_ok (
33
44 BEGIN {
55 delete $ENV{ANSI_COLORS_DISABLED};
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use_ok ('Term::ANSIColor');
89 use_ok (
33 use Test::More;
44 BEGIN {
55 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 };
89
33
44 BEGIN {
55 delete $ENV{ANSI_COLORS_DISABLED};
6 delete $ENV{DATAPRINTERRC};
67 use File::HomeDir::Test; # avoid user's .dataprinter
78 use_ok ('Term::ANSIColor');
89 use_ok (
0 use strict;
1 use warnings;
2
3 use Test::More tests => 1;
4 BEGIN {
5 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
7 use File::HomeDir::Test; # avoid user's .dataprinter
8 };
9
10 use Data::Printer end_separator => 1, separator => '--';
11
12 my $structure = [
13 1,
14 2,
15 {
16 a => 1,
17 b => 2,
18 long_line => 3,
19 },
20 ];
21
22 my $end_comma_output = '\ [
23 [0] 1--
24 [1] 2--
25 [2] {
26 a 1--
27 b 2--
28 long_line 3--
29 }--
30 ]';
31
32 is(
33 p($structure),
34 $end_comma_output,
35 "Got correct structure with end_separator => 1 and separator => '--'",
36 );
37
0 use strict;
1 use warnings;
2
3 use Test::More tests => 3;
4 BEGIN {
5 $ENV{ANSI_COLORS_DISABLED} = 1;
6 delete $ENV{DATAPRINTERRC};
7 use File::HomeDir::Test; # avoid user's .dataprinter
8 };
9
10 use Data::Printer separator => '--';
11
12 my $structure = [
13 1,
14 2,
15 {
16 a => 1,
17 b => 2,
18 long_line => 3,
19 },
20 ];
21
22 my $end_comma_output = '\ [
23 [0] 1--
24 [1] 2--
25 [2] {
26 a 1--
27 b 2--
28 long_line 3
29 }
30 ]';
31
32 is(
33 p($structure),
34 $end_comma_output,
35 "Got correct structure with separator => '--'",
36 );
37
38 $end_comma_output = '\ [
39 [0] 1
40 [1] 2
41 [2] {
42 a 1
43 b 2
44 long_line 3
45 }
46 ]';
47
48 is(
49 p($structure, separator => ''),
50 $end_comma_output,
51 "Got correct structure with no separator",
52 );
53
54 is(
55 p($structure, separator => '', end_separator => 1),
56 $end_comma_output,
57 "Got correct structure with no separator, even with end_separator set to 1",
58 );
0 ######################################
1 ######## EXPERIMENTAL FEATURE ########
2 ######################################
3 use strict;
4 use warnings;
5
6 use Test::More tests => 1;
7 BEGIN {
8 $ENV{ANSI_COLORS_DISABLED} = 1;
9 delete $ENV{DATAPRINTERRC};
10 use File::HomeDir::Test; # avoid user's .dataprinter
11 };
12
13 use Data::Printer show_readonly => 1;
14
15 my $foo = 42;
16
17 &Internals::SvREADONLY( \$foo, 1 );
18
19 is p($foo), '42 (read-only)', 'readonly variables (experimental)';
0 use strict;
1 use warnings;
2
3 BEGIN {
4 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
6 use File::HomeDir::Test; # avoid user's .dataprinter
7
8 use Test::More;
9 use Data::Printer;
10
11 }
12
13 my $scalar = v1.2.3;
14 eval {
15 is( p($scalar), 'v1.2.3', "VSTRINGs" );
16 };
17 if ($@) {
18 fail( "VSTRINGs" );
19 diag( $@ );
20 }
21
22 done_testing();
0 # making sure data is properly aligned
1 use strict;
2 use warnings;
3
4 use Test::More tests => 1;
5
6 BEGIN {
7 $ENV{ANSI_COLORS_DISABLED} = 1;
8 delete $ENV{DATAPRINTERRC};
9 use File::HomeDir::Test; # avoid user's .dataprinter
10 use Data::Printer;
11 };
12
13 my $var = { q[foo bar],2,3,4};
14
15 is(
16 p($var),
17 q{\ {
18 3 4,
19 'foo bar' 2
20 }},
21 'colored alignment'
22 );
23
24
0 use strict;
1 use warnings;
2
3 BEGIN {
4 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
6 use File::HomeDir::Test; # avoid user's .dataprinter
7
8 use Test::More;
9 use Data::Printer;
10
11 }
12
13 format TEST =
14 .
15
16 my $form = *TEST{FORMAT};
17 my $test_name = "FORMAT refs";
18 eval {
19 is( p($form), 'FORMAT', $test_name );
20 };
21 if ($@) {
22 fail( $test_name );
23 diag( $@ );
24 }
25
26 done_testing();
0 use strict;
1 use warnings;
2
3 BEGIN {
4 $ENV{ANSI_COLORS_DISABLED} = 1;
5 delete $ENV{DATAPRINTERRC};
6 use File::HomeDir::Test; # avoid user's .dataprinter
7
8 use Test::More;
9 use Data::Printer;
10
11 }
12
13 my $scalar = \substr( "abc", 2);
14 my $test_name = "LVALUE refs";
15 eval {
16 is( p($scalar), '"c" (LVALUE)', $test_name );
17 is( p($scalar, show_lvalue => 0), '"c"', 'disabled ' . $test_name );
18 };
19 if ($@) {
20 fail( $test_name );
21 diag( $@ );
22 }
23
24 done_testing();
0 use strict;
1 use warnings;
2 use Test::More;
3
4 eval "use Test::Pod::Coverage 1.04";
5 plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@;
6
7 plan skip_all => 'set TEST_POD to enable this test (developer only!)'
8 unless $ENV{TEST_POD};
9
10 all_pod_coverage_ok({
11 also_private => [ qr/^(?:ARRAY|CODE|GLOB|HASH|REF|VSTRING|Regexp|FORMAT|LVALUE)$/, qr/^np$/ ],
12 });