line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::Easy; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# PORTIONS FROM Sub::Identify and common::sense |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
BEGIN { |
6
|
6
|
|
|
6
|
|
14
|
our $VERSION = '0.18'; |
7
|
6
|
|
|
|
|
9
|
our @ISA; |
8
|
|
|
|
|
|
|
|
9
|
6
|
|
|
6
|
|
7139
|
use Class::Easy::Import; |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
33
|
|
10
|
|
|
|
|
|
|
|
11
|
6
|
|
|
|
|
11
|
my $loaded; |
12
|
6
|
50
|
|
|
|
28
|
unless ($ENV{PERL_SUB_IDENTIFY_PP}) { |
13
|
6
|
|
|
|
|
10
|
local $@; |
14
|
6
|
|
|
|
|
9
|
eval { |
15
|
6
|
|
|
|
|
32
|
require XSLoader; |
16
|
6
|
|
|
|
|
4097
|
XSLoader::load(__PACKAGE__, $VERSION); |
17
|
|
|
|
|
|
|
}; |
18
|
|
|
|
|
|
|
|
19
|
6
|
50
|
33
|
|
|
62
|
die $@ if $@ && $@ !~ /object version|loadable object/; |
20
|
|
|
|
|
|
|
|
21
|
6
|
50
|
|
|
|
25
|
$loaded = 1 unless $@; |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
6
|
|
|
|
|
14
|
our $is_pure_perl = !$loaded; |
25
|
|
|
|
|
|
|
|
26
|
6
|
50
|
|
|
|
11442
|
if ($is_pure_perl) { |
27
|
0
|
|
|
|
|
0
|
require Class::Easy::PP; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
require Class::Easy::Timer; |
33
|
|
|
|
|
|
|
|
34
|
0
|
|
|
0
|
1
|
0
|
sub stash_name ($) { (get_coderef_info($_[0]))[0] } |
35
|
0
|
|
|
0
|
1
|
0
|
sub sub_name ($) { (get_coderef_info($_[0]))[1] } |
36
|
0
|
|
|
0
|
1
|
0
|
sub sub_fullname ($) { join '::', get_coderef_info($_[0]) } |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
our @EXPORT = qw(has try_to_use try_to_use_quiet try_to_use_inc try_to_use_inc_quiet make_accessor timer); |
40
|
|
|
|
|
|
|
our @EXPORT_OK = qw(sub_name stash_name sub_fullname get_coderef_info); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
our %EXPORT_FOREIGN = ( |
43
|
|
|
|
|
|
|
'Class::Easy::Log' => [qw(debug critical debug_depth logger catch_stderr release_stderr)], |
44
|
|
|
|
|
|
|
# 'Class::Easy::Timer' => [qw(timer)], |
45
|
|
|
|
|
|
|
); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
our $LOG = ''; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub timer { |
50
|
3
|
|
|
3
|
1
|
1301
|
return Class::Easy::Timer->new (@_); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub import { |
54
|
5
|
|
|
5
|
|
216
|
my $mypkg = shift; |
55
|
5
|
|
|
|
|
11
|
my $callpkg = caller; |
56
|
|
|
|
|
|
|
|
57
|
5
|
|
|
|
|
16
|
my %params = @_; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# use warnings |
60
|
5
|
|
|
|
|
19
|
${^WARNING_BITS} = $Class::Easy::Import::WARN; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# use strict, use utf8; |
63
|
5
|
|
|
|
|
15
|
$^H |= $Class::Easy::Import::H; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# use feature |
66
|
5
|
|
|
|
|
70
|
$^H{feature_switch} = $^H{feature_say} = $^H{feature_state} = 1; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# probably check for try_to_use is enough |
69
|
|
|
|
|
|
|
return |
70
|
5
|
|
|
|
|
55
|
if defined *{"$callpkg\::try_to_use"}{CODE} |
|
0
|
|
|
|
|
0
|
|
71
|
5
|
50
|
33
|
|
|
11
|
and sub_fullname (*{"$callpkg\::try_to_use"}{CODE}) eq __PACKAGE__.'::__ANON__'; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# export subs |
74
|
5
|
|
|
|
|
19
|
*{"$callpkg\::$_"} = \&{"$mypkg\::$_"} foreach @EXPORT; |
|
35
|
|
|
|
|
132
|
|
|
35
|
|
|
|
|
164
|
|
75
|
5
|
|
|
|
|
21
|
foreach my $p (keys %EXPORT_FOREIGN) { |
76
|
5
|
|
|
|
|
10
|
*{"$callpkg\::$_"} = \&{"$p\::$_"} foreach @{$EXPORT_FOREIGN{$p}}; |
|
5
|
|
|
|
|
23
|
|
|
30
|
|
|
|
|
310
|
|
|
30
|
|
|
|
|
118
|
|
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub has ($;%) { |
81
|
|
|
|
|
|
|
|
82
|
14
|
|
|
14
|
1
|
708
|
my ($caller) = caller; |
83
|
14
|
|
|
|
|
20
|
my $accessor = shift; |
84
|
|
|
|
|
|
|
|
85
|
14
|
|
|
|
|
33
|
return make_accessor ($caller, $accessor, _unless_exists => 1, @_); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub make_accessor ($;$;$;%) { |
89
|
51
|
|
|
51
|
1
|
963
|
my $caller = shift; |
90
|
51
|
|
|
|
|
65
|
my $name = shift; |
91
|
|
|
|
|
|
|
|
92
|
51
|
|
|
|
|
250
|
my $full_ref = "${caller}::$name"; |
93
|
|
|
|
|
|
|
|
94
|
51
|
|
|
|
|
54
|
my $default; |
95
|
51
|
100
|
66
|
|
|
271
|
$default = pop |
96
|
|
|
|
|
|
|
if @_ == 1 or @_ == 3; # _from_has support |
97
|
|
|
|
|
|
|
|
98
|
51
|
50
|
|
|
|
195
|
die 'bad call from: ' . join (', ', caller) |
99
|
|
|
|
|
|
|
if scalar @_ % 2; |
100
|
51
|
|
|
|
|
137
|
my %config = @_; |
101
|
|
|
|
|
|
|
|
102
|
51
|
|
|
|
|
73
|
my $isa = $config{isa}; |
103
|
51
|
|
100
|
|
|
174
|
my $is = $config{is} || 'ro'; |
104
|
51
|
100
|
|
|
|
113
|
$default = $config{default} |
105
|
|
|
|
|
|
|
if exists $config{default}; |
106
|
|
|
|
|
|
|
|
107
|
51
|
100
|
100
|
|
|
229
|
$config{global} = 1 |
108
|
|
|
|
|
|
|
if defined $default and $is eq 'ro'; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# when make_accessor called from has, we must check for already created |
111
|
|
|
|
|
|
|
# accessor and redefine only if redefined flag supplied |
112
|
51
|
50
|
66
|
|
|
138
|
if (delete $config{_unless_exists} and defined *{$full_ref}{CODE}) { |
|
14
|
|
|
|
|
87
|
|
113
|
0
|
|
|
|
|
0
|
return; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
51
|
|
|
|
|
56
|
my $mode; |
117
|
51
|
100
|
|
|
|
109
|
$mode = 1 if $is eq 'ro'; |
118
|
51
|
100
|
|
|
|
101
|
$mode = 2 if $is eq 'rw'; |
119
|
|
|
|
|
|
|
|
120
|
51
|
50
|
|
|
|
200
|
die "unknown accessor type: $is" |
121
|
|
|
|
|
|
|
unless $is =~ /^r[ow]$/; |
122
|
|
|
|
|
|
|
|
123
|
51
|
100
|
|
|
|
141
|
if (ref $default eq 'CODE') { |
|
|
100
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
125
|
13
|
|
|
|
|
15
|
*{$full_ref} = $default; |
|
13
|
|
|
|
|
146
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
} elsif ($config{global}) { |
128
|
|
|
|
|
|
|
|
129
|
14
|
|
|
|
|
150
|
*{$full_ref} = sub { |
130
|
|
|
|
|
|
|
|
131
|
18
|
|
|
18
|
|
39
|
my $c = @_; |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# return &$default if $c == 1 and ref $default eq 'CODE'; |
134
|
18
|
100
|
|
|
|
79
|
return $default if $c == 1; |
135
|
6
|
100
|
|
|
|
19
|
_has_error ($caller, $name, $c - 1) if $c ^ $mode; |
136
|
|
|
|
|
|
|
|
137
|
5
|
|
33
|
|
|
28
|
make_accessor (ref $_[0] || $_[0], $name, %config, default => $_[1]); |
138
|
14
|
|
|
|
|
48
|
}; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
} else { |
141
|
24
|
|
|
|
|
154
|
*{$full_ref} = sub { |
142
|
|
|
|
|
|
|
|
143
|
21
|
|
|
21
|
|
461
|
my $c = @_; |
144
|
|
|
|
|
|
|
|
145
|
21
|
100
|
|
|
|
103
|
return $_[0]->{$name} if $c == 1; |
146
|
9
|
100
|
|
|
|
26
|
_has_error ($caller, $name, $c - 1) if $c ^ $mode; |
147
|
|
|
|
|
|
|
|
148
|
7
|
|
|
|
|
44
|
$_[0]->{$name} = $_[1]; |
149
|
|
|
|
|
|
|
|
150
|
24
|
|
|
|
|
109
|
}; |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub _has_error { |
156
|
3
|
|
|
3
|
|
5
|
my $caller = shift; |
157
|
3
|
|
|
|
|
6
|
my $name = shift; |
158
|
3
|
|
|
|
|
5
|
my $argc = shift; |
159
|
|
|
|
|
|
|
|
160
|
3
|
|
|
|
|
21
|
my ($acc_caller, $line) = (caller(1))[0, 2]; |
161
|
3
|
|
|
|
|
33
|
die "too many parameters ($argc) for accessor $caller\->$name at $acc_caller line $line.\n"; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub _try_to_use { |
165
|
17
|
|
|
17
|
|
24
|
my $use_lib = shift; |
166
|
17
|
|
|
|
|
20
|
my $quiet = shift; |
167
|
17
|
|
|
|
|
34
|
my @chunks = @_; |
168
|
|
|
|
|
|
|
|
169
|
17
|
|
|
|
|
43
|
my $package = join '::', @chunks; |
170
|
17
|
|
|
|
|
68
|
@chunks = split '::', $package; |
171
|
17
|
|
|
|
|
45
|
my $path = join ('/', @chunks) . '.pm'; |
172
|
|
|
|
|
|
|
|
173
|
17
|
|
|
|
|
27
|
$@ = ''; |
174
|
|
|
|
|
|
|
|
175
|
17
|
100
|
|
|
|
69
|
if ($use_lib) { |
176
|
1
|
50
|
|
|
|
4
|
return "exists in \%INC" |
177
|
|
|
|
|
|
|
if exists $INC{$path}; |
178
|
|
|
|
|
|
|
} else { |
179
|
|
|
|
|
|
|
# OLD: we removed "or ! exists $INC{$path}" statement because |
180
|
|
|
|
|
|
|
# "used" package always available via symbol table |
181
|
16
|
100
|
|
|
|
1560
|
if (eval ("scalar grep {!/\\w+\:\:/} keys \%$package\::;") > 0) { |
182
|
2
|
|
|
|
|
12
|
return "exists in symbol table"; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
6
|
|
|
6
|
|
5781
|
eval "use $package"; |
|
6
|
|
|
6
|
|
7723
|
|
|
6
|
|
|
2
|
|
256
|
|
|
6
|
|
|
1
|
|
2552
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
2
|
|
|
|
|
842
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
362
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
15
|
|
|
|
|
889
|
|
187
|
|
|
|
|
|
|
|
188
|
15
|
100
|
|
|
|
65
|
if ($@) { |
189
|
9
|
100
|
|
|
|
72
|
Class::Easy::Log::debug ("i can't load module ($path): $@") |
190
|
|
|
|
|
|
|
unless $quiet; |
191
|
9
|
|
|
|
|
52
|
return; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
6
|
|
|
|
|
35
|
return 1; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub try_to_use { |
198
|
13
|
|
|
13
|
1
|
19849
|
return _try_to_use (0, 0, @_); |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub try_to_use_quiet { |
202
|
3
|
|
|
3
|
1
|
11
|
return _try_to_use (0, 1, @_); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub try_to_use_inc { |
206
|
0
|
|
|
0
|
1
|
0
|
return _try_to_use (1, 0, @_); |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub try_to_use_inc_quiet { |
210
|
1
|
|
|
1
|
1
|
3
|
return _try_to_use (1, 1, @_); |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub list_local_subs_for { |
214
|
7
|
|
|
7
|
1
|
11
|
my $module = shift; |
215
|
7
|
|
50
|
|
|
30
|
my $enum_imported = shift || 0; |
216
|
|
|
|
|
|
|
|
217
|
7
|
|
|
|
|
7
|
my $namespace = \%{$module . '::'}; |
|
7
|
|
|
|
|
23
|
|
218
|
|
|
|
|
|
|
|
219
|
119
|
|
|
|
|
359
|
my @sub_list = grep { |
220
|
119
|
|
|
|
|
96
|
defined *{"$module\::$_"}{CODE} |
|
7
|
|
|
|
|
47
|
|
221
|
7
|
|
|
|
|
10
|
} keys %{$namespace}; |
222
|
|
|
|
|
|
|
|
223
|
7
|
|
|
|
|
49
|
my $sub_by_type = { |
224
|
|
|
|
|
|
|
method => {}, |
225
|
|
|
|
|
|
|
imported => {}, |
226
|
|
|
|
|
|
|
runtime => {} |
227
|
|
|
|
|
|
|
}; |
228
|
|
|
|
|
|
|
|
229
|
7
|
|
|
|
|
15
|
foreach my $sub (@sub_list) { |
230
|
94
|
|
|
|
|
87
|
my ($real_package, $real_sub) = (get_coderef_info (*{"$module\::$sub"}{CODE})); |
|
94
|
|
|
|
|
386
|
|
231
|
|
|
|
|
|
|
|
232
|
94
|
100
|
|
|
|
215
|
if ($real_package eq $module) { |
|
|
100
|
|
|
|
|
|
233
|
19
|
|
|
|
|
48
|
$sub_by_type->{method}->{$sub} = 1; |
234
|
|
|
|
|
|
|
} elsif ($real_sub eq '__ANON__') { |
235
|
23
|
|
|
|
|
47
|
$sub_by_type->{runtime}->{$sub} = 1; |
236
|
|
|
|
|
|
|
} else { |
237
|
52
|
|
|
|
|
123
|
$sub_by_type->{imported}->{$real_package}->{$real_sub} = $sub; # who needs $real_sub ? |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
wantarray |
242
|
7
|
100
|
|
|
|
27
|
? (keys %{$sub_by_type->{method}}, keys %{$sub_by_type->{runtime}}) |
|
4
|
|
|
|
|
13
|
|
|
4
|
|
|
|
|
42
|
|
243
|
|
|
|
|
|
|
: $sub_by_type; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub list_all_subs_for { |
247
|
3
|
|
33
|
3
|
1
|
551
|
my $module = shift || (caller)[0]; |
248
|
3
|
|
50
|
|
|
19
|
my $filter = shift || ''; |
249
|
|
|
|
|
|
|
|
250
|
3
|
100
|
|
|
|
11
|
$module = ref $module |
251
|
|
|
|
|
|
|
if ref $module; |
252
|
|
|
|
|
|
|
|
253
|
3
|
|
|
|
|
4
|
my $namespace = \%{$module . '::'}; |
|
3
|
|
|
|
|
10
|
|
254
|
|
|
|
|
|
|
|
255
|
3
|
|
|
|
|
5
|
my $linear_isa; |
256
|
|
|
|
|
|
|
|
257
|
3
|
50
|
|
|
|
14
|
if ($] < 5.009_005) { |
258
|
0
|
|
|
|
|
0
|
require Class::Easy::MRO; |
259
|
0
|
|
|
|
|
0
|
$linear_isa = __get_linear_isa ($module); |
260
|
|
|
|
|
|
|
} else { |
261
|
3
|
|
|
|
|
2580
|
require mro; |
262
|
3
|
|
|
|
|
1520
|
$linear_isa = mro::get_linear_isa ($module); |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
3
|
|
|
|
|
18
|
my $sub_by_type = list_local_subs_for ($module); |
266
|
7
|
|
|
|
|
31
|
$sub_by_type->{inherited}->{$_} = [list_local_subs_for ($_)] |
267
|
3
|
|
|
|
|
7
|
foreach grep {$_ ne $module} @$linear_isa; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
wantarray |
270
|
|
|
|
|
|
|
? ( |
271
|
0
|
|
|
|
|
|
keys %{$sub_by_type->{method}}, |
|
0
|
|
|
|
|
|
|
272
|
0
|
|
|
|
|
|
keys %{$sub_by_type->{runtime}}, |
273
|
3
|
50
|
|
|
|
15
|
map {@{$sub_by_type->{inherited}->{$_}}} keys %{$sub_by_type->{inherited}}) |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
: $sub_by_type; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
1; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head1 NAME |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
Class::Easy - make class routine easy |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=head1 ABSTRACT |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
This module is a functionality compilation of some good modules from CPAN. |
286
|
|
|
|
|
|
|
Ideas are taken from Class::Data::Inheritable, Class::Accessor, Modern::Perl |
287
|
|
|
|
|
|
|
and Moose at least. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
Instead of building monstrous alternatives to Moose or making thousand modules |
290
|
|
|
|
|
|
|
for every function I need, I decide to write small and efficient libraries for |
291
|
|
|
|
|
|
|
everyday use. Class::Easy::Base is a base component for classes. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 SYNOPSIS |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
SYNOPSIS |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# automatic loading of strict, warnings and utf8, like common::sense |
298
|
|
|
|
|
|
|
use Class::Easy::Import; |
299
|
|
|
|
|
|
|
# or same as above + functions like 'has', 'try_to_use', 'timer' and 'logger' |
300
|
|
|
|
|
|
|
use Class::Easy; |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# try to load package IO::Easy, return 1 when success |
303
|
|
|
|
|
|
|
try_to_use ('IO::Easy'); |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# try to load package IO::Easy, but search for package existence |
306
|
|
|
|
|
|
|
# within %INC instead of symbolic table |
307
|
|
|
|
|
|
|
try_to_use_inc ('IO::Easy'); |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# for current package |
310
|
|
|
|
|
|
|
has "property_ro"; # make readonly object accessor |
311
|
|
|
|
|
|
|
has "property_rw", is => 'rw'; # make readwrite object accessor |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
has global25 => 25; # make readonly static accessor with value 25 |
314
|
|
|
|
|
|
|
has "global", global => 1, is => 'rw'; # make readwrite static accessor |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# make subroutine in package main |
317
|
|
|
|
|
|
|
make_accessor ('main', 'initialize', default => sub { |
318
|
|
|
|
|
|
|
$::initialized = 1; |
319
|
|
|
|
|
|
|
return "initialized!"; |
320
|
|
|
|
|
|
|
}); |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# see documentation for Class::Easy::Log |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# string "[PID] [PACKAGE(STRING)] [DBG] something" logged |
325
|
|
|
|
|
|
|
debug "something"; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# see documentation for Class::Easy::Timer |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
my $t = timer ('long operation'); |
330
|
|
|
|
|
|
|
# … long operation |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
my $time = $t->lap ('another long op'); |
333
|
|
|
|
|
|
|
# … |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
$time = $t->end; |
336
|
|
|
|
|
|
|
# $time contains time between last 'lap' or 'timer' |
337
|
|
|
|
|
|
|
# and 'end' call |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
$time = $t->total; |
340
|
|
|
|
|
|
|
# now $time contains total time between timer init |
341
|
|
|
|
|
|
|
# and end call |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=head1 FUNCTIONS |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=head2 has ($name [, is => 'ro' | 'rw'] [, default => $default], [, global => 1]) |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
create accessor named $name in current scope |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=cut |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 make_accessor ($scope, $name) |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
create accessor in selected scope |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
=cut |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head2 try_to_use, try_to_use_quiet |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
tries to use specified package with printing error message to STDERR |
360
|
|
|
|
|
|
|
or "_quiet" version. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
return true value in case of successful operation or existing non-package |
363
|
|
|
|
|
|
|
references in symbol table. correctly works with virtual packages. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
takes package name or package name chunks, for example: |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
try_to_use ('IO::Easy'); |
368
|
|
|
|
|
|
|
# or equivalent |
369
|
|
|
|
|
|
|
try_to_use (qw(IO Easy)); |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
if you want to separate io errors from syntax errors you may want to |
372
|
|
|
|
|
|
|
check $! variable; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
for example: |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
use Errno qw(:POSIX); |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
if (!try_to_use ('IO::Easy')) { |
379
|
|
|
|
|
|
|
die 'file not found for package IO::Easy' |
380
|
|
|
|
|
|
|
if $!{ENOENT}; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=cut |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=head2 try_to_use_inc, try_to_use_inc_quiet |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
similar to the try_to_use, but check for module presence in %INC |
388
|
|
|
|
|
|
|
instead of symbol table lookup. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=cut |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=head2 timer |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
create new L object |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=cut |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=head2 get_coderef_info, stash_name, sub_name, sub_fullname |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
retrieve real name for coderef. useful for anonymous or imported functions |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
get_coderef_info (*{Class::Easy::timer}{CODE}); # ('Class::Easy', 'timer') |
403
|
|
|
|
|
|
|
stash_name (*{Class::Easy::timer}{CODE}); # 'Class::Easy' |
404
|
|
|
|
|
|
|
sub_name (*{Class::Easy::timer}{CODE}); # 'timer' |
405
|
|
|
|
|
|
|
sub_fullname (*{Class::Easy::timer}{CODE}); # 'Class::Easy::timer' |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=cut |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=head2 list_all_subs_for, list_local_subs_for |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
in scalar context return hashref with complete coderef info for class. |
412
|
|
|
|
|
|
|
- key 'inherited' contains all inherited methods, separated by class name, |
413
|
|
|
|
|
|
|
- key 'runtime' contains all code references in current package which point |
414
|
|
|
|
|
|
|
to anonymous method, |
415
|
|
|
|
|
|
|
- key 'method' contains all local methods, |
416
|
|
|
|
|
|
|
- key 'imported' contains all imported subs, separated by class name |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
{ |
419
|
|
|
|
|
|
|
'inherited' => { |
420
|
|
|
|
|
|
|
'My::Circle' => [ |
421
|
|
|
|
|
|
|
'new', |
422
|
|
|
|
|
|
|
'global_hash', |
423
|
|
|
|
|
|
|
'global_hash_rw', |
424
|
|
|
|
|
|
|
'new_default', |
425
|
|
|
|
|
|
|
'global_hash_rw_default', |
426
|
|
|
|
|
|
|
'dim_x', |
427
|
|
|
|
|
|
|
'id', |
428
|
|
|
|
|
|
|
'dim_y' |
429
|
|
|
|
|
|
|
] |
430
|
|
|
|
|
|
|
}, |
431
|
|
|
|
|
|
|
'runtime' => { |
432
|
|
|
|
|
|
|
'global_ro' => 1, |
433
|
|
|
|
|
|
|
'global_one' => 1, |
434
|
|
|
|
|
|
|
'global_one_defined' => 1, |
435
|
|
|
|
|
|
|
'dim_z' => 1, |
436
|
|
|
|
|
|
|
'accessor' => 1 |
437
|
|
|
|
|
|
|
}, |
438
|
|
|
|
|
|
|
'method' => { |
439
|
|
|
|
|
|
|
'sub_z' => 1 |
440
|
|
|
|
|
|
|
}, |
441
|
|
|
|
|
|
|
'imported' => { |
442
|
|
|
|
|
|
|
'Class::Easy' => { |
443
|
|
|
|
|
|
|
'make_accessor' => 'make_accessor', |
444
|
|
|
|
|
|
|
'try_to_use' => 'try_to_use', |
445
|
|
|
|
|
|
|
'try_to_use_inc' => 'try_to_use_inc', |
446
|
|
|
|
|
|
|
'try_to_use_quiet' => 'try_to_use_quiet', |
447
|
|
|
|
|
|
|
'has' => 'has', |
448
|
|
|
|
|
|
|
'timer' => 'timer', |
449
|
|
|
|
|
|
|
'try_to_use_inc_quiet' => 'try_to_use_inc_quiet' |
450
|
|
|
|
|
|
|
}, |
451
|
|
|
|
|
|
|
'Class::Easy::Log' => { |
452
|
|
|
|
|
|
|
'critical' => 'critical', |
453
|
|
|
|
|
|
|
'release_stderr' => 'release_stderr', |
454
|
|
|
|
|
|
|
'catch_stderr' => 'catch_stderr', |
455
|
|
|
|
|
|
|
'debug' => 'debug', |
456
|
|
|
|
|
|
|
'debug_depth' => 'debug_depth', |
457
|
|
|
|
|
|
|
'logger' => 'logger' |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
}; |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
'local' version of subroutine doesn't contains any inherited methods |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=cut |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=head1 AUTHOR |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
Ivan Baktsheev, C<< >> |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=head1 BUGS |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
Please report any bugs or feature requests to my email address, |
476
|
|
|
|
|
|
|
or through the web interface at L. |
477
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified |
478
|
|
|
|
|
|
|
of progress on your bug as I make changes. |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=head1 SUPPORT |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Copyright 2008-2009 Ivan Baktsheev |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
493
|
|
|
|
|
|
|
under the same terms as Perl itself. |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=cut |