Filename | /home/ss5/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/Exception/Class.pm |
Statements | Executed 263 statements in 8.63ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 6.03ms | 29.1ms | BEGIN@10 | Exception::Class::
8 | 1 | 1 | 3.43ms | 6.92ms | _make_subclass | Exception::Class::
1 | 1 | 1 | 428µs | 7.40ms | import | Exception::Class::
1 | 1 | 1 | 67µs | 67µs | BEGIN@6 | Exception::Class::
8 | 1 | 1 | 62µs | 62µs | CORE:subst (opcode) | Exception::Class::
1 | 1 | 1 | 52µs | 52µs | CORE:sort (opcode) | Exception::Class::
1 | 1 | 1 | 38µs | 186µs | BEGIN@11 | Exception::Class::
1 | 1 | 1 | 36µs | 79µs | BEGIN@176 | Exception::Class::
1 | 1 | 1 | 34µs | 34µs | BEGIN@2 | Exception::Class::
1 | 1 | 1 | 34µs | 82µs | BEGIN@168 | Exception::Class::
1 | 1 | 1 | 28µs | 41µs | BEGIN@8 | Exception::Class::
1 | 1 | 1 | 27µs | 78µs | BEGIN@46 | Exception::Class::
1 | 1 | 1 | 26µs | 64µs | BEGIN@79 | Exception::Class::
1 | 1 | 1 | 15µs | 15µs | BEGIN@14 | Exception::Class::
2 | 1 | 1 | 14µs | 14µs | CORE:substcont (opcode) | Exception::Class::
0 | 0 | 0 | 0s | 0s | Classes | Exception::Class::
0 | 0 | 0 | 0s | 0s | __ANON__[:170] | Exception::Class::
0 | 0 | 0 | 0s | 0s | _make_parents | Exception::Class::
0 | 0 | 0 | 0s | 0s | caught | Exception::Class::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Exception::Class; | ||||
2 | # spent 34µs within Exception::Class::BEGIN@2 which was called:
# once (34µs+0s) by Iterator::BEGIN@22 at line 4 | ||||
3 | 1 | 31µs | $Exception::Class::VERSION = '1.32'; | ||
4 | 1 | 79µs | 1 | 34µs | } # spent 34µs making 1 call to Exception::Class::BEGIN@2 |
5 | |||||
6 | 2 | 194µs | 1 | 67µs | # spent 67µs within Exception::Class::BEGIN@6 which was called:
# once (67µs+0s) by Iterator::BEGIN@22 at line 6 # spent 67µs making 1 call to Exception::Class::BEGIN@6 |
7 | |||||
8 | 2 | 93µs | 2 | 54µs | # spent 41µs (28+13) within Exception::Class::BEGIN@8 which was called:
# once (28µs+13µs) by Iterator::BEGIN@22 at line 8 # spent 41µs making 1 call to Exception::Class::BEGIN@8
# spent 13µs making 1 call to strict::import |
9 | |||||
10 | 2 | 440µs | 1 | 29.1ms | # spent 29.1ms (6.03+23.0) within Exception::Class::BEGIN@10 which was called:
# once (6.03ms+23.0ms) by Iterator::BEGIN@22 at line 10 # spent 29.1ms making 1 call to Exception::Class::BEGIN@10 |
11 | 2 | 180µs | 2 | 335µs | # spent 186µs (38+148) within Exception::Class::BEGIN@11 which was called:
# once (38µs+148µs) by Iterator::BEGIN@22 at line 11 # spent 186µs making 1 call to Exception::Class::BEGIN@11
# spent 148µs making 1 call to Exporter::import |
12 | |||||
13 | 1 | 800ns | our $BASE_EXC_CLASS; | ||
14 | 1 | 537µs | 1 | 15µs | # spent 15µs within Exception::Class::BEGIN@14 which was called:
# once (15µs+0s) by Iterator::BEGIN@22 at line 14 # spent 15µs making 1 call to Exception::Class::BEGIN@14 |
15 | |||||
16 | 1 | 900ns | our %CLASSES; | ||
17 | |||||
18 | # spent 7.40ms (428µs+6.98) within Exception::Class::import which was called:
# once (428µs+6.98ms) by Iterator::BEGIN@22 at line 23 of Iterator.pm | ||||
19 | 1 | 3µs | my $class = shift; | ||
20 | |||||
21 | 1 | 4µs | local $Exception::Class::Caller = caller(); | ||
22 | |||||
23 | 1 | 1µs | my %c; | ||
24 | |||||
25 | 1 | 700ns | my %needs_parent; | ||
26 | 1 | 21µs | while ( my $subclass = shift ) { | ||
27 | 8 | 13µs | my $def = ref $_[0] ? shift : {}; | ||
28 | 8 | 38µs | $def->{isa} | ||
29 | = $def->{isa} | ||||
30 | ? ( ref $def->{isa} ? $def->{isa} : [ $def->{isa} ] ) | ||||
31 | : []; | ||||
32 | |||||
33 | 8 | 26µs | $c{$subclass} = $def; | ||
34 | } | ||||
35 | |||||
36 | # We need to sort by length because if we check for keys in the | ||||
37 | # Foo::Bar:: stash, this creates a "Bar::" key in the Foo:: stash! | ||||
38 | MAKE_CLASSES: | ||||
39 | 1 | 92µs | 1 | 52µs | foreach my $subclass ( sort { length $a <=> length $b } keys %c ) { # spent 52µs making 1 call to Exception::Class::CORE:sort |
40 | 8 | 19µs | my $def = $c{$subclass}; | ||
41 | |||||
42 | # We already made this one. | ||||
43 | 8 | 15µs | next if $CLASSES{$subclass}; | ||
44 | |||||
45 | { | ||||
46 | 10 | 668µs | 2 | 129µs | # spent 78µs (27+51) within Exception::Class::BEGIN@46 which was called:
# once (27µs+51µs) by Iterator::BEGIN@22 at line 46 # spent 78µs making 1 call to Exception::Class::BEGIN@46
# spent 51µs making 1 call to strict::unimport |
47 | 8 | 38µs | foreach my $parent ( @{ $def->{isa} } ) { | ||
48 | 7 | 52µs | unless ( keys %{"$parent\::"} ) { | ||
49 | $needs_parent{$subclass} = { | ||||
50 | parents => $def->{isa}, | ||||
51 | def => $def | ||||
52 | }; | ||||
53 | next MAKE_CLASSES; | ||||
54 | } | ||||
55 | } | ||||
56 | } | ||||
57 | |||||
58 | $class->_make_subclass( | ||||
59 | 8 | 85µs | 8 | 6.92ms | subclass => $subclass, # spent 6.92ms making 8 calls to Exception::Class::_make_subclass, avg 865µs/call |
60 | def => $def || {}, | ||||
61 | ); | ||||
62 | } | ||||
63 | |||||
64 | 1 | 25µs | foreach my $subclass ( keys %needs_parent ) { | ||
65 | |||||
66 | # This will be used to spot circular references. | ||||
67 | my %seen; | ||||
68 | $class->_make_parents( \%needs_parent, $subclass, \%seen ); | ||||
69 | } | ||||
70 | } | ||||
71 | |||||
72 | sub _make_parents { | ||||
73 | my $class = shift; | ||||
74 | my $needs = shift; | ||||
75 | my $subclass = shift; | ||||
76 | my $seen = shift; | ||||
77 | my $child = shift; # Just for error messages. | ||||
78 | |||||
79 | 2 | 1.66ms | 2 | 102µs | # spent 64µs (26+38) within Exception::Class::BEGIN@79 which was called:
# once (26µs+38µs) by Iterator::BEGIN@22 at line 79 # spent 64µs making 1 call to Exception::Class::BEGIN@79
# spent 38µs making 1 call to strict::unimport |
80 | |||||
81 | # What if someone makes a typo in specifying their 'isa' param? | ||||
82 | # This should catch it. Either it's been made because it didn't | ||||
83 | # have missing parents OR it's in our hash as needing a parent. | ||||
84 | # If neither of these is true then the _only_ place it is | ||||
85 | # mentioned is in the 'isa' param for some other class, which is | ||||
86 | # not a good enough reason to make a new class. | ||||
87 | die | ||||
88 | "Class $subclass appears to be a typo as it is only specified in the 'isa' param for $child\n" | ||||
89 | unless exists $needs->{$subclass} | ||||
90 | || $CLASSES{$subclass} | ||||
91 | || keys %{"$subclass\::"}; | ||||
92 | |||||
93 | foreach my $c ( @{ $needs->{$subclass}{parents} } ) { | ||||
94 | |||||
95 | # It's been made | ||||
96 | next if $CLASSES{$c} || keys %{"$c\::"}; | ||||
97 | |||||
98 | die "There appears to be some circularity involving $subclass\n" | ||||
99 | if $seen->{$subclass}; | ||||
100 | |||||
101 | $seen->{$subclass} = 1; | ||||
102 | |||||
103 | $class->_make_parents( $needs, $c, $seen, $subclass ); | ||||
104 | } | ||||
105 | |||||
106 | return if $CLASSES{$subclass} || keys %{"$subclass\::"}; | ||||
107 | |||||
108 | $class->_make_subclass( | ||||
109 | subclass => $subclass, | ||||
110 | def => $needs->{$subclass}{def} | ||||
111 | ); | ||||
112 | } | ||||
113 | |||||
114 | # spent 6.92ms (3.43+3.49) within Exception::Class::_make_subclass which was called 8 times, avg 865µs/call:
# 8 times (3.43ms+3.49ms) by Exception::Class::import at line 59, avg 865µs/call | ||||
115 | 8 | 11µs | my $class = shift; | ||
116 | 8 | 45µs | my %p = @_; | ||
117 | |||||
118 | 8 | 15µs | my $subclass = $p{subclass}; | ||
119 | 8 | 9µs | my $def = $p{def}; | ||
120 | |||||
121 | 8 | 4µs | my $isa; | ||
122 | 8 | 46µs | if ( $def->{isa} ) { | ||
123 | $isa = ref $def->{isa} ? join ' ', @{ $def->{isa} } : $def->{isa}; | ||||
124 | } | ||||
125 | 8 | 6µs | $isa ||= $BASE_EXC_CLASS; | ||
126 | |||||
127 | 8 | 8µs | my $version_name = 'VERSION'; | ||
128 | |||||
129 | 8 | 28µs | my $code = <<"EOPERL"; | ||
130 | package $subclass; | ||||
131 | |||||
132 | use base qw($isa); | ||||
133 | |||||
134 | our \$$version_name = '1.1'; | ||||
135 | |||||
136 | 1; | ||||
137 | |||||
138 | EOPERL | ||||
139 | |||||
140 | 8 | 18µs | if ( $def->{description} ) { | ||
141 | 8 | 194µs | 10 | 76µs | ( my $desc = $def->{description} ) =~ s/([\\\'])/\\$1/g; # spent 62µs making 8 calls to Exception::Class::CORE:subst, avg 8µs/call
# spent 14µs making 2 calls to Exception::Class::CORE:substcont, avg 7µs/call |
142 | 8 | 33µs | $code .= <<"EOPERL"; | ||
143 | sub description | ||||
144 | { | ||||
145 | return '$desc'; | ||||
146 | } | ||||
147 | EOPERL | ||||
148 | } | ||||
149 | |||||
150 | 8 | 6µs | my @fields; | ||
151 | 8 | 22µs | if ( my $fields = $def->{fields} ) { | ||
152 | 3 | 56µs | 3 | 19µs | @fields = UNIVERSAL::isa( $fields, 'ARRAY' ) ? @$fields : $fields; # spent 19µs making 3 calls to UNIVERSAL::isa, avg 6µs/call |
153 | |||||
154 | $code | ||||
155 | .= "sub Fields { return (\$_[0]->SUPER::Fields, " | ||||
156 | 3 | 31µs | . join( ", ", map {"'$_'"} @fields ) | ||
157 | . ") }\n\n"; | ||||
158 | |||||
159 | 3 | 9µs | foreach my $field (@fields) { | ||
160 | 3 | 30µs | $code .= sprintf( "sub %s { \$_[0]->{%s} }\n", $field, $field ); | ||
161 | } | ||||
162 | } | ||||
163 | |||||
164 | 8 | 15µs | if ( my $alias = $def->{alias} ) { | ||
165 | die "Cannot make alias without caller" | ||||
166 | unless defined $Exception::Class::Caller; | ||||
167 | |||||
168 | 2 | 499µs | 2 | 130µs | # spent 82µs (34+48) within Exception::Class::BEGIN@168 which was called:
# once (34µs+48µs) by Iterator::BEGIN@22 at line 168 # spent 82µs making 1 call to Exception::Class::BEGIN@168
# spent 48µs making 1 call to strict::unimport |
169 | *{"$Exception::Class::Caller\::$alias"} | ||||
170 | = sub { $subclass->throw(@_) }; | ||||
171 | } | ||||
172 | |||||
173 | 8 | 10µs | if ( my $defaults = $def->{defaults} ) { | ||
174 | $code | ||||
175 | .= "sub _defaults { return shift->SUPER::_defaults, our \%_DEFAULTS }\n"; | ||||
176 | 2 | 1.66ms | 2 | 122µs | # spent 79µs (36+43) within Exception::Class::BEGIN@176 which was called:
# once (36µs+43µs) by Iterator::BEGIN@22 at line 176 # spent 79µs making 1 call to Exception::Class::BEGIN@176
# spent 43µs making 1 call to strict::unimport |
177 | *{"$subclass\::_DEFAULTS"} = {%$defaults}; | ||||
178 | } | ||||
179 | |||||
180 | 8 | 1.40ms | eval $code; # spent 299µs executing statements in string eval # includes 37µs spent executing 1 call to 4 subs defined therein. # spent 296µs executing statements in string eval # includes 57µs spent executing 1 call to 4 subs defined therein. # spent 290µs executing statements in string eval # includes 44µs spent executing 1 call to 4 subs defined therein. # spent 195µs executing statements in string eval # includes 41µs spent executing 1 call to 2 subs defined therein. # spent 171µs executing statements in string eval # includes 46µs spent executing 1 call to 2 subs defined therein. # spent 161µs executing statements in string eval # includes 41µs spent executing 1 call to 2 subs defined therein. # spent 153µs executing statements in string eval # includes 60µs spent executing 1 call to 2 subs defined therein. # spent 149µs executing statements in string eval # includes 39µs spent executing 1 call to 2 subs defined therein. | ||
181 | |||||
182 | 8 | 6µs | die $@ if $@; | ||
183 | |||||
184 | 8 | 148µs | $CLASSES{$subclass} = 1; | ||
185 | } | ||||
186 | |||||
187 | sub caught { | ||||
188 | my $e = $@; | ||||
189 | |||||
190 | return $e unless $_[1]; | ||||
191 | |||||
192 | return unless blessed($e) && $e->isa( $_[1] ); | ||||
193 | return $e; | ||||
194 | } | ||||
195 | |||||
196 | sub Classes { sort keys %Exception::Class::CLASSES } | ||||
197 | |||||
198 | 1 | 13µs | 1; | ||
199 | |||||
200 | # ABSTRACT: A module that allows you to declare real exception classes in Perl | ||||
201 | |||||
- - | |||||
204 | =pod | ||||
205 | |||||
206 | =head1 NAME | ||||
207 | |||||
208 | Exception::Class - A module that allows you to declare real exception classes in Perl | ||||
209 | |||||
210 | =head1 VERSION | ||||
211 | |||||
212 | version 1.32 | ||||
213 | |||||
214 | =head1 SYNOPSIS | ||||
215 | |||||
216 | use Exception::Class ( | ||||
217 | 'MyException', | ||||
218 | |||||
219 | 'AnotherException' => { isa => 'MyException' }, | ||||
220 | |||||
221 | 'YetAnotherException' => { | ||||
222 | isa => 'AnotherException', | ||||
223 | description => 'These exceptions are related to IPC' | ||||
224 | }, | ||||
225 | |||||
226 | 'ExceptionWithFields' => { | ||||
227 | isa => 'YetAnotherException', | ||||
228 | fields => [ 'grandiosity', 'quixotic' ], | ||||
229 | alias => 'throw_fields', | ||||
230 | }, | ||||
231 | ); | ||||
232 | |||||
233 | # try | ||||
234 | eval { MyException->throw( error => 'I feel funny.' ) }; | ||||
235 | |||||
236 | my $e; | ||||
237 | |||||
238 | # catch | ||||
239 | if ( $e = Exception::Class->caught('MyException') ) { | ||||
240 | warn $e->error, "\n", $e->trace->as_string, "\n"; | ||||
241 | warn join ' ', $e->euid, $e->egid, $e->uid, $e->gid, $e->pid, $e->time; | ||||
242 | |||||
243 | exit; | ||||
244 | } | ||||
245 | elsif ( $e = Exception::Class->caught('ExceptionWithFields') ) { | ||||
246 | $e->quixotic ? do_something_wacky() : do_something_sane(); | ||||
247 | } | ||||
248 | else { | ||||
249 | $e = Exception::Class->caught(); | ||||
250 | ref $e ? $e->rethrow : die $e; | ||||
251 | } | ||||
252 | |||||
253 | # use an alias - without parens subroutine name is checked at | ||||
254 | # compile time | ||||
255 | throw_fields error => "No strawberry", grandiosity => "quite a bit"; | ||||
256 | |||||
257 | =head1 DESCRIPTION | ||||
258 | |||||
259 | Exception::Class allows you to declare exception hierarchies in your | ||||
260 | modules in a "Java-esque" manner. | ||||
261 | |||||
262 | It features a simple interface allowing programmers to 'declare' | ||||
263 | exception classes at compile time. It also has a base exception | ||||
264 | class, L<Exception::Class::Base>, that can be easily extended. | ||||
265 | |||||
266 | It is designed to make structured exception handling simpler and | ||||
267 | better by encouraging people to use hierarchies of exceptions in their | ||||
268 | applications, as opposed to a single catch-all exception class. | ||||
269 | |||||
270 | This module does not implement any try/catch syntax. Please see the | ||||
271 | "OTHER EXCEPTION MODULES (try/catch syntax)" section for more | ||||
272 | information on how to get this syntax. | ||||
273 | |||||
274 | You will also want to look at the documentation for | ||||
275 | L<Exception::Class::Base>, which is the default base class for all | ||||
276 | exception objects created by this module. | ||||
277 | |||||
278 | =head1 DECLARING EXCEPTION CLASSES | ||||
279 | |||||
280 | Importing C<Exception::Class> allows you to automagically create | ||||
281 | L<Exception::Class::Base> subclasses. You can also create subclasses | ||||
282 | via the traditional means of defining your own subclass with C<@ISA>. | ||||
283 | These two methods may be easily combined, so that you could subclass | ||||
284 | an exception class defined via the automagic import, if you desired | ||||
285 | this. | ||||
286 | |||||
287 | The syntax for the magic declarations is as follows: | ||||
288 | |||||
289 | 'MANDATORY CLASS NAME' => \%optional_hashref | ||||
290 | |||||
291 | The hashref may contain the following options: | ||||
292 | |||||
293 | =over 4 | ||||
294 | |||||
295 | =item * isa | ||||
296 | |||||
297 | This is the class's parent class. If this isn't provided then the | ||||
298 | class name in C<$Exception::Class::BASE_EXC_CLASS> is assumed to be | ||||
299 | the parent (see below). | ||||
300 | |||||
301 | This parameter lets you create arbitrarily deep class hierarchies. | ||||
302 | This can be any other L<Exception::Class::Base> subclass in your | ||||
303 | declaration I<or> a subclass loaded from a module. | ||||
304 | |||||
305 | To change the default exception class you will need to change the | ||||
306 | value of C<$Exception::Class::BASE_EXC_CLASS> I<before> calling | ||||
307 | C<import()>. To do this simply do something like this: | ||||
308 | |||||
309 | BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; } | ||||
310 | |||||
311 | If anyone can come up with a more elegant way to do this please let me | ||||
312 | know. | ||||
313 | |||||
314 | CAVEAT: If you want to automagically subclass an | ||||
315 | L<Exception::Class::Base> subclass loaded from a file, then you | ||||
316 | I<must> compile the class (via use or require or some other magic) | ||||
317 | I<before> you import C<Exception::Class> or you'll get a compile time | ||||
318 | error. | ||||
319 | |||||
320 | =item * fields | ||||
321 | |||||
322 | This allows you to define additional attributes for your exception | ||||
323 | class. Any field you define can be passed to the C<throw()> or | ||||
324 | C<new()> methods as additional parameters for the constructor. In | ||||
325 | addition, your exception object will have an accessor method for the | ||||
326 | fields you define. | ||||
327 | |||||
328 | This parameter can be either a scalar (for a single field) or an array | ||||
329 | reference if you need to define multiple fields. | ||||
330 | |||||
331 | Fields will be inherited by subclasses. | ||||
332 | |||||
333 | =item * alias | ||||
334 | |||||
335 | Specifying an alias causes this class to create a subroutine of the | ||||
336 | specified name in the I<caller's> namespace. Calling this subroutine | ||||
337 | is equivalent to calling C<< <class>->throw(@_) >> for the given | ||||
338 | exception class. | ||||
339 | |||||
340 | Besides convenience, using aliases also allows for additional compile | ||||
341 | time checking. If the alias is called I<without parentheses>, as in | ||||
342 | C<throw_fields "an error occurred">, then Perl checks for the | ||||
343 | existence of the C<throw_fields()> subroutine at compile time. If | ||||
344 | instead you do C<< ExceptionWithFields->throw(...) >>, then Perl | ||||
345 | checks the class name at runtime, meaning that typos may sneak | ||||
346 | through. | ||||
347 | |||||
348 | =item * description | ||||
349 | |||||
350 | Each exception class has a description method that returns a fixed | ||||
351 | string. This should describe the exception I<class> (as opposed to | ||||
352 | any particular exception object). This may be useful for debugging if | ||||
353 | you start catching exceptions you weren't expecting (particularly if | ||||
354 | someone forgot to document them) and you don't understand the error | ||||
355 | messages. | ||||
356 | |||||
357 | =back | ||||
358 | |||||
359 | The C<Exception::Class> magic attempts to detect circular class | ||||
360 | hierarchies and will die if it finds one. It also detects missing | ||||
361 | links in a chain, for example if you declare Bar to be a subclass of | ||||
362 | Foo and never declare Foo. | ||||
363 | |||||
364 | =head1 Catching Exceptions | ||||
365 | |||||
366 | C<Exception::Class> provides some syntactic sugar for catching | ||||
367 | exceptions in a safe manner: | ||||
368 | |||||
369 | eval {...}; | ||||
370 | |||||
371 | if ( my $e = Exception::Class->caught('My::Error') ) { | ||||
372 | cleanup(); | ||||
373 | do_something_with_exception($e); | ||||
374 | } | ||||
375 | |||||
376 | The C<caught()> method takes a class name and returns an exception | ||||
377 | object if the last thrown exception is of the given class, or a | ||||
378 | subclass of that class. If it is not given any arguments, it simply | ||||
379 | returns C<$@>. | ||||
380 | |||||
381 | You should B<always> make a copy of the exception object, rather than | ||||
382 | using C<$@> directly. This is necessary because if your C<cleanup()> | ||||
383 | function uses C<eval>, or calls something which uses it, then C<$@> is | ||||
384 | overwritten. Copying the exception preserves it for the call to | ||||
385 | C<do_something_with_exception()>. | ||||
386 | |||||
387 | Exception objects also provide a caught method so you can write: | ||||
388 | |||||
389 | if ( my $e = My::Error->caught() ) { | ||||
390 | cleanup(); | ||||
391 | do_something_with_exception($e); | ||||
392 | } | ||||
393 | |||||
394 | =head2 Uncatchable Exceptions | ||||
395 | |||||
396 | Internally, the C<caught()> method will call C<isa()> on the exception | ||||
397 | object. You could make an exception "uncatchable" by overriding | ||||
398 | C<isa()> in that class like this: | ||||
399 | |||||
400 | package Exception::Uncatchable; | ||||
401 | |||||
402 | sub isa { shift->rethrow } | ||||
403 | |||||
404 | Of course, this only works if you always call | ||||
405 | C<< Exception::Class->caught() >> after an C<eval>. | ||||
406 | |||||
407 | =head1 USAGE RECOMMENDATION | ||||
408 | |||||
409 | If you're creating a complex system that throws lots of different | ||||
410 | types of exceptions, consider putting all the exception declarations | ||||
411 | in one place. For an app called Foo you might make a | ||||
412 | C<Foo::Exceptions> module and use that in all your code. This module | ||||
413 | could just contain the code to make C<Exception::Class> do its | ||||
414 | automagic class creation. Doing this allows you to more easily see | ||||
415 | what exceptions you have, and makes it easier to keep track of them. | ||||
416 | |||||
417 | This might look something like this: | ||||
418 | |||||
419 | package Foo::Bar::Exceptions; | ||||
420 | |||||
421 | use Exception::Class ( | ||||
422 | Foo::Bar::Exception::Senses => | ||||
423 | { description => 'sense-related exception' }, | ||||
424 | |||||
425 | Foo::Bar::Exception::Smell => { | ||||
426 | isa => 'Foo::Bar::Exception::Senses', | ||||
427 | fields => 'odor', | ||||
428 | description => 'stinky!' | ||||
429 | }, | ||||
430 | |||||
431 | Foo::Bar::Exception::Taste => { | ||||
432 | isa => 'Foo::Bar::Exception::Senses', | ||||
433 | fields => [ 'taste', 'bitterness' ], | ||||
434 | description => 'like, gag me with a spoon!' | ||||
435 | }, | ||||
436 | |||||
437 | ... | ||||
438 | ); | ||||
439 | |||||
440 | You may want to create a real module to subclass | ||||
441 | L<Exception::Class::Base> as well, particularly if you want your | ||||
442 | exceptions to have more methods. | ||||
443 | |||||
444 | =head2 Subclassing Exception::Class::Base | ||||
445 | |||||
446 | As part of your usage of C<Exception::Class>, you may want to create | ||||
447 | your own base exception class which subclasses | ||||
448 | L<Exception::Class::Base>. You should feel free to subclass any of | ||||
449 | the methods documented above. For example, you may want to subclass | ||||
450 | C<new()> to add additional information to your exception objects. | ||||
451 | |||||
452 | =head1 Exception::Class FUNCTIONS | ||||
453 | |||||
454 | The C<Exception::Class> method offers one function, C<Classes()>, | ||||
455 | which is not exported. This method returns a list of the classes that | ||||
456 | have been created by calling the C<Exception::Class> import() method. | ||||
457 | Note that this is I<all> the subclasses that have been created, so it | ||||
458 | may include subclasses created by things like CPAN modules, etc. Also | ||||
459 | note that if you simply define a subclass via the normal Perl method | ||||
460 | of setting C<@ISA> or C<use base>, then your subclass will not be | ||||
461 | included. | ||||
462 | |||||
463 | =head1 OTHER EXCEPTION MODULES (try/catch syntax) | ||||
464 | |||||
465 | If you are interested in adding try/catch/finally syntactic sugar to | ||||
466 | your code then I recommend you check out U. Arun Kumar's C<Error.pm> | ||||
467 | module, which implements this syntax. It also includes its own base | ||||
468 | exception class, C<Error::Simple>. | ||||
469 | |||||
470 | If you would prefer to use the L<Exception::Class::Base> class | ||||
471 | included with this module, you'll have to add this to your code | ||||
472 | somewhere: | ||||
473 | |||||
474 | push @Exception::Class::Base::ISA, 'Error' | ||||
475 | unless Exception::Class::Base->isa('Error'); | ||||
476 | |||||
477 | It's a hack but apparently it works. | ||||
478 | |||||
479 | =head1 SUPPORT | ||||
480 | |||||
481 | Please submit bugs to the CPAN RT system at | ||||
482 | http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Exception%3A%3AClass or | ||||
483 | via email at bug-exception-class@rt.cpan.org. | ||||
484 | |||||
485 | =head1 DONATIONS | ||||
486 | |||||
487 | If you'd like to thank me for the work I've done on this module, | ||||
488 | please consider making a "donation" to me via PayPal. I spend a lot of | ||||
489 | free time creating free software, and would appreciate any support | ||||
490 | you'd care to offer. | ||||
491 | |||||
492 | Please note that B<I am not suggesting that you must do this> in order | ||||
493 | for me to continue working on this particular software. I will | ||||
494 | continue to do so, inasmuch as I have in the past, for as long as it | ||||
495 | interests me. | ||||
496 | |||||
497 | Similarly, a donation made in this way will probably not make me work | ||||
498 | on this software much more, unless I get so many donations that I can | ||||
499 | consider working on free software full time, which seems unlikely at | ||||
500 | best. | ||||
501 | |||||
502 | To donate, log into PayPal and send money to autarch@urth.org or use | ||||
503 | the button on this page: | ||||
504 | L<http://www.urth.org/~autarch/fs-donation.html> | ||||
505 | |||||
506 | =head1 AUTHOR | ||||
507 | |||||
508 | Dave Rolsky <autarch@urth.org> | ||||
509 | |||||
510 | =head1 COPYRIGHT AND LICENSE | ||||
511 | |||||
512 | This software is Copyright (c) 2010 by Dave Rolsky. | ||||
513 | |||||
514 | This is free software, licensed under: | ||||
515 | |||||
516 | The Artistic License 2.0 | ||||
517 | |||||
518 | =cut | ||||
519 | |||||
520 | |||||
521 | __END__ | ||||
# spent 52µs within Exception::Class::CORE:sort which was called:
# once (52µs+0s) by Exception::Class::import at line 39 | |||||
# spent 62µs within Exception::Class::CORE:subst which was called 8 times, avg 8µs/call:
# 8 times (62µs+0s) by Exception::Class::_make_subclass at line 141, avg 8µs/call | |||||
# spent 14µs within Exception::Class::CORE:substcont which was called 2 times, avg 7µs/call:
# 2 times (14µs+0s) by Exception::Class::_make_subclass at line 141, avg 7µs/call |