File Coverage

blib/lib/Moose/Util.pm
Criterion Covered Total %
statement 216 232 93.1
branch 95 114 83.3
condition 24 42 57.1
subroutine 49 53 92.4
pod 15 16 93.7
total 399 457 87.3


line stmt bran cond sub pod time code
1             package Moose::Util;
2             our $VERSION = '2.2205';
3              
4 394     403   855416 use strict;
  394         1021  
  394         13381  
5 394     402   4650 use warnings;
  394         886  
  394         19945  
6              
7 394     402   23977 use Module::Runtime 0.014 'use_package_optimistically', 'module_notional_filename';
  394         93227  
  394         4927  
8 394     402   30701 use Data::OptList;
  394         142152  
  394         8135  
9 394     402   221202 use Sub::Exporter;
  394         1172423  
  394         2264  
10 394     402   88872 use Scalar::Util 'blessed';
  394         3463  
  394         23799  
11 394     402   4151 use List::Util 1.33 qw(first any all);
  394         10152  
  394         24809  
12 394     394   2743 use overload ();
  394         935  
  394         6614  
13 394     394   17054 use Try::Tiny;
  394         61244  
  394         1343347  
14              
15              
16             my @exports = qw[
17             find_meta
18             is_role
19             does_role
20             search_class_by_role
21             ensure_all_roles
22             apply_all_roles
23             with_traits
24             get_all_init_args
25             get_all_attribute_values
26             resolve_metatrait_alias
27             resolve_metaclass_alias
28             add_method_modifier
29             english_list
30             meta_attribute_alias
31             meta_class_alias
32             throw_exception
33             ];
34              
35             Sub::Exporter::setup_exporter({
36             exports => \@exports,
37             groups => { all => \@exports }
38             });
39              
40             # Things that need to ->import from Moose::Util
41             # should be loaded after Moose::Util defines ->import
42             require Class::MOP;
43              
44             sub throw_exception {
45 1348     1348 1 10866 my ($class_name, @args_to_exception) = @_;
46 1348         3795 my $class = "Moose::Exception::$class_name";
47 1348         4472 _load_user_class( $class );
48 1348         121418 die $class->new( @args_to_exception );
49             }
50              
51             ## some utils for the utils ...
52              
53 2306     2306 1 7907 sub find_meta { Class::MOP::class_of(@_) }
54              
55             ## the functions ...
56              
57             sub is_role {
58 7     7 1 23 my $package_or_obj = shift;
59              
60 7         14 my $meta = find_meta($package_or_obj);
61 7 100       22 return if not $meta;
62 5         39 return $meta->isa('Moose::Meta::Role');
63             }
64              
65             sub does_role {
66 122     122 1 3596 my ($class_or_obj, $role) = @_;
67              
68 122 100   122   684 if (try { $class_or_obj->isa('Moose::Object') }) {
  122         3830  
69 49         745 return $class_or_obj->does($role);
70             }
71              
72 73         1167 my $meta = find_meta($class_or_obj);
73              
74 73 100       223 return unless defined $meta;
75 70 100       394 return unless $meta->can('does_role');
76 58 100       192 return 1 if $meta->does_role($role);
77 6         32 return;
78             }
79              
80             sub search_class_by_role {
81 8     8 1 283 my ($class_or_obj, $role) = @_;
82              
83 8         23 my $meta = find_meta($class_or_obj);
84              
85 8 50       21 return unless defined $meta;
86              
87 8 100       49 my $role_name = blessed $role ? $role->name : $role;
88              
89 8         43 foreach my $class ($meta->class_precedence_list) {
90              
91 12         29 my $_meta = find_meta($class);
92              
93 12 50       25 next unless defined $_meta;
94              
95 12 50       18 foreach my $role (@{ $_meta->roles || [] }) {
  12         371  
96 6 50       69 return $class if $role->name eq $role_name;
97             }
98             }
99              
100 2         15 return;
101             }
102              
103             # this can possibly behave in unexpected ways because the roles being composed
104             # before being applied could differ from call to call; I'm not sure if or how
105             # to document this possible quirk.
106             sub ensure_all_roles {
107 2     2 1 9 my $applicant = shift;
108 2     4   13 _apply_all_roles($applicant, sub { !does_role($applicant, $_) }, @_);
  4         11  
109             }
110              
111             sub apply_all_roles {
112 1642     1642 1 4215 my $applicant = shift;
113 1642         5923 _apply_all_roles($applicant, undef, @_);
114             }
115              
116             sub _apply_all_roles {
117 1644     1644   2970 my $applicant = shift;
118 1644         3616 my $role_filter = shift;
119              
120 1644 100       4960 unless (@_) {
121 3         25 require Moose;
122 3         9 throw_exception( MustSpecifyAtleastOneRoleToApplicant => applicant => $applicant );
123             }
124              
125             # If @_ contains role meta objects, mkopt will think that they're values,
126             # because they're references. In other words (roleobj1, roleobj2,
127             # roleobj3) will become [ [ roleobj1, roleobj2 ], [ roleobj3, undef ] ]
128             # -- this is no good. We'll preprocess @_ first to eliminate the potential
129             # bug.
130             # -- rjbs, 2011-04-08
131             my $roles = Data::OptList::mkopt( [@_], {
132             moniker => 'role',
133             name_test => sub {
134 314 100 66 314   10478 ! ref $_[0] or blessed($_[0]) && $_[0]->isa('Moose::Meta::Role')
135             }
136 1641         13646 });
137              
138 1641         58826 my @role_metas;
139 1641         4442 foreach my $role (@$roles) {
140 1924         3258 my $meta;
141              
142 1924 100       7788 if ( blessed $role->[0] ) {
143 26         75 $meta = $role->[0];
144             }
145             else {
146 1898         6297 _load_user_class( $role->[0] , $role->[1] );
147 1894         92389 $meta = find_meta( $role->[0] );
148             }
149              
150 1920 100 100     14833 unless ($meta && $meta->isa('Moose::Meta::Role') ) {
151 3         11 throw_exception( CanOnlyConsumeRole => role_name => $role->[0] );
152             }
153              
154 1917         7382 push @role_metas, [ $meta, $role->[1] ];
155             }
156              
157 1634 100       5506 if ( defined $role_filter ) {
158 2         5 @role_metas = grep { local $_ = $_->[0]; $role_filter->() } @role_metas;
  4         10  
  4         8  
159             }
160              
161 1634 100       4595 return unless @role_metas;
162              
163 1632 100 100     8849 _load_user_class($applicant)
164             unless blessed($applicant)
165             || Class::MOP::class_of($applicant);
166              
167 1632 100       7437 my $meta = ( blessed $applicant ? $applicant : Moose::Meta::Class->initialize($applicant) );
168              
169 1632 100       5304 if ( scalar @role_metas == 1 ) {
170 1406         2785 my ( $role, $params ) = @{ $role_metas[0] };
  1406         3851  
171 1406 100       7069 $role->apply( $meta, ( defined $params ? %$params : () ) );
172             }
173             else {
174 226         1487 Moose::Meta::Role->combine(@role_metas)->apply($meta);
175             }
176             }
177              
178             sub with_traits {
179 5     5 1 1820 my ($class, @roles) = @_;
180 5 100       19 return $class unless @roles;
181 4         37 return Moose::Meta::Class->create_anon_class(
182             superclasses => [$class],
183             roles => \@roles,
184             cache => 1,
185             )->name;
186             }
187              
188             # instance deconstruction ...
189              
190             sub get_all_attribute_values {
191 0     0 1 0 my ($class, $instance) = @_;
192             return +{
193 0         0 map { $_->name => $_->get_value($instance) }
194 0         0 grep { $_->has_value($instance) }
  0         0  
195             $class->get_all_attributes
196             };
197             }
198              
199             sub get_all_init_args {
200 0     0 1 0 my ($class, $instance) = @_;
201             return +{
202 0         0 map { $_->init_arg => $_->get_value($instance) }
203 0         0 grep { $_->has_value($instance) }
204 0         0 grep { defined($_->init_arg) }
  0         0  
205             $class->get_all_attributes
206             };
207             }
208              
209             sub resolve_metatrait_alias {
210 471     471 1 3124 return resolve_metaclass_alias( @_, trait => 1 );
211             }
212              
213             sub _build_alias_package_name {
214 218     218   701 my ($type, $name, $trait) = @_;
215 218 100       1211 return 'Moose::Meta::'
216             . $type
217             . '::Custom::'
218             . ( $trait ? 'Trait::' : '' )
219             . $name;
220             }
221              
222             {
223             my %cache;
224              
225             sub resolve_metaclass_alias {
226 498     498 1 3280 my ( $type, $metaclass_name, %options ) = @_;
227              
228 498 100       2738 my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );
229             return $cache{$cache_key}{$metaclass_name}
230 498 100       2912 if $cache{$cache_key}{$metaclass_name};
231              
232             my $possible_full_name = _build_alias_package_name(
233             $type, $metaclass_name, $options{trait}
234 206         900 );
235              
236 206         732 my @possible = ($possible_full_name, $metaclass_name);
237 206         567 for my $package (@possible) {
238 330         1303 use_package_optimistically($package);
239 330 100       76712 if ($package->can('register_implementation')) {
    100          
240 81         557 return $cache{$cache_key}{$metaclass_name} =
241             $package->register_implementation;
242             }
243             elsif (find_meta($package)) {
244 121         1093 return $cache{$cache_key}{$metaclass_name} = $package;
245             }
246             }
247              
248 4         35 throw_exception( CannotLocatePackageInINC => possible_packages => _english_list_or(@possible),
249             INC => \@INC,
250             type => $type,
251             metaclass_name => $metaclass_name,
252             params => \%options
253             );
254             }
255             }
256              
257             sub add_method_modifier {
258 413     413 0 2322 my ( $class_or_obj, $modifier_name, $args ) = @_;
259 413 100       2418 my $meta
260             = $class_or_obj->can('add_before_method_modifier')
261             ? $class_or_obj
262             : find_meta($class_or_obj);
263 413         864 my $code = pop @{$args};
  413         830  
264 413         1289 my $add_modifier_method = 'add_' . $modifier_name . '_method_modifier';
265 413 100       1270 if ( my $method_modifier_type = ref( $args->[0] ) ) {
266 7 100       31 if ( $method_modifier_type eq 'Regexp' ) {
    100          
267 3         13 my @all_methods = $meta->get_all_methods;
268             my @matched_methods
269 3         9 = grep { $_->name =~ $args->[0] } @all_methods;
  42         165  
270             $meta->$add_modifier_method( $_->name, $code )
271 3         45 for @matched_methods;
272             }
273             elsif ($method_modifier_type eq 'ARRAY') {
274 2         4 $meta->$add_modifier_method( $_, $code ) for @{$args->[0]};
  2         22  
275             }
276             else {
277 2         10 throw_exception( IllegalMethodTypeToAddMethodModifier => class_or_object => $class_or_obj,
278             modifier_name => $modifier_name,
279             params => $args
280             );
281             }
282             }
283             else {
284 406         708 $meta->$add_modifier_method( $_, $code ) for @{$args};
  406         2047  
285             }
286             }
287              
288             sub english_list {
289 63     63 1 233 _english_list_and(@_);
290             }
291              
292             sub _english_list_and {
293 63     63   232 _english_list('and', \@_);
294             }
295              
296             sub _english_list_or {
297 55     55   175 _english_list('or', \@_);
298             }
299              
300             sub _english_list {
301 118     118   284 my ($conjunction, $items) = @_;
302              
303 118         496 my @items = sort @$items;
304              
305 118 100       401 return $items[0] if @items == 1;
306 103 100       580 return "$items[0] $conjunction $items[1]" if @items == 2;
307              
308 53         124 my $tail = pop @items;
309 53         140 my $list = join ', ', @items;
310 53         132 $list .= ", $conjunction " . $tail;
311              
312 53         412 return $list;
313             }
314              
315             sub _caller_info {
316 1930 50   1930   6318 my $level = @_ ? ($_[0] + 1) : 2;
317 1930         3320 my %info;
318 1930         18357 @info{qw(package file line)} = caller($level);
319 1930         12833 return %info;
320             }
321              
322             sub _create_alias {
323 12     12   34 my ($type, $name, $trait, $for) = @_;
324 12         37 my $package = _build_alias_package_name($type, $name, $trait);
325             Class::MOP::Class->initialize($package)->add_method(
326 11     11   111 register_implementation => sub { $for }
        11      
327 12         58 );
328             }
329              
330             sub meta_attribute_alias {
331 6     6 1 237 my ($to, $from) = @_;
332 6   66     44 $from ||= caller;
333 6         29 my $meta = Class::MOP::class_of($from);
334 6         54 my $trait = $meta->isa('Moose::Meta::Role');
335 6         18 _create_alias('Attribute', $to, $trait, $from);
336             }
337              
338             sub meta_class_alias {
339 6     6 1 221 my ($to, $from) = @_;
340 6   66     34 $from ||= caller;
341 6         23 my $meta = Class::MOP::class_of($from);
342 6         50 my $trait = $meta->isa('Moose::Meta::Role');
343 6         20 _create_alias('Class', $to, $trait, $from);
344             }
345              
346             sub _load_user_class {
347 8234     8234   17672 my ($class, $opts) = @_;
348             &use_package_optimistically(
349             $class,
350             $opts && $opts->{-version} ? $opts->{-version} : ()
351 8234 100 100     36897 );
352             }
353              
354             # XXX - this should be added to Params::Util
355             sub _STRINGLIKE0 ($) {
356 408 50   408   185575 return 0 if !defined $_[0];
357 408 100       1544 return 1 if !ref $_[0];
358 221 100       712 return 1 if overload::OverloadedStringify($_[0]);
359 197         17694 return 0;
360             }
361              
362             sub _reconcile_roles_for_metaclass {
363 61     61   140 my ($class_meta_name, $super_meta_name) = @_;
364              
365 61         146 my @role_differences = _role_differences(
366             $class_meta_name, $super_meta_name,
367             );
368              
369             # handle the case where we need to fix compatibility between a class and
370             # its parent, but all roles in the class are already also done by the
371             # parent
372             # see t/metaclasses/metaclass_compat_no_fixing_bug.t
373 61 100       205 return $super_meta_name
374             unless @role_differences;
375              
376             return Moose::Meta::Class->create_anon_class(
377             superclasses => [$super_meta_name],
378 58         173 roles => [map { $_->name } @role_differences],
  58         318  
379             cache => 1,
380             )->name;
381             }
382              
383             sub _role_differences {
384 61     61   110 my ($class_meta_name, $super_meta_name) = @_;
385             my @super_role_metas = map {
386             $_->isa('Moose::Meta::Role::Composite')
387 64 50       459 ? (@{ $_->get_roles })
  0         0  
388             : ($_)
389             } $super_meta_name->meta->can('_roles_with_inheritance')
390             ? $super_meta_name->meta->_roles_with_inheritance
391             : $super_meta_name->meta->can('roles')
392 61 0       219 ? @{ $super_meta_name->meta->roles }
  0 50       0  
393             : ();
394             my @role_metas = map {
395             $_->isa('Moose::Meta::Role::Composite')
396 67 100       376 ? (@{ $_->get_roles })
  3         84  
397             : ($_)
398             } $class_meta_name->meta->can('_roles_with_inheritance')
399             ? $class_meta_name->meta->_roles_with_inheritance
400             : $class_meta_name->meta->can('roles')
401 61 0       286 ? @{ $class_meta_name->meta->roles }
  0 50       0  
402             : ();
403 61         143 my @differences;
404 61         132 for my $role_meta (@role_metas) {
405             push @differences, $role_meta
406 70 100   70   352 unless any { $_->name eq $role_meta->name } @super_role_metas;
  70         498  
407             }
408 61         193 return @differences;
409             }
410              
411             sub _classes_differ_by_roles_only {
412 63     63   142 my ( $self_meta_name, $super_meta_name ) = @_;
413              
414 63         151 my $common_base_name
415             = _find_common_base( $self_meta_name, $super_meta_name );
416              
417 63 50       334 return unless defined $common_base_name;
418              
419             my @super_meta_name_ancestor_names
420 63         166 = _get_ancestors_until( $super_meta_name, $common_base_name );
421             my @class_meta_name_ancestor_names
422 63         144 = _get_ancestors_until( $self_meta_name, $common_base_name );
423              
424             return
425 133     133   282 unless all { _is_role_only_subclass($_) }
426 63 100       316 @super_meta_name_ancestor_names,
427             @class_meta_name_ancestor_names;
428              
429 61         334 return 1;
430             }
431              
432             sub _find_common_base {
433 63     63   169 my ($meta1, $meta2) = map { Class::MOP::class_of($_) } @_;
  126         274  
434 63 50 33     313 return unless defined $meta1 && defined $meta2;
435              
436             # FIXME? This doesn't account for multiple inheritance (not sure
437             # if it needs to though). For example, if somewhere in $meta1's
438             # history it inherits from both ClassA and ClassB, and $meta2
439             # inherits from ClassB & ClassA, does it matter? And what crazy
440             # fool would do that anyway?
441              
442 63         213 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
  607         1160  
443              
444 63     129   429 return first { $meta1_parents{$_} } $meta2->linearized_isa;
  129         332  
445             }
446              
447             sub _get_ancestors_until {
448 126     126   238 my ($start_name, $until_name) = @_;
449              
450 126         189 my @ancestor_names;
451 126         251 for my $ancestor_name (Class::MOP::class_of($start_name)->linearized_isa) {
452 263 100       536 last if $ancestor_name eq $until_name;
453 137         244 push @ancestor_names, $ancestor_name;
454             }
455 126         357 return @ancestor_names;
456             }
457              
458             sub _is_role_only_subclass {
459 133     133   238 my ($meta_name) = @_;
460 133         407 my $meta = Class::MOP::Class->initialize($meta_name);
461 133         438 my @parent_names = $meta->superclasses;
462              
463             # XXX: don't feel like messing with multiple inheritance here... what would
464             # that even do?
465 133 50       367 return unless @parent_names == 1;
466 133         253 my ($parent_name) = @parent_names;
467 133         319 my $parent_meta = Class::MOP::Class->initialize($parent_name);
468              
469             # only get the roles attached to this particular class, don't look at
470             # superclasses
471 133 50       668 my @roles = $meta->can('calculate_all_roles')
472             ? $meta->calculate_all_roles
473             : ();
474              
475             # it's obviously not a role-only subclass if it doesn't do any roles
476 133 100       370 return unless @roles;
477              
478             # loop over all methods that are a part of the current class
479             # (not inherited)
480 131         428 for my $method ( $meta->_get_local_methods ) {
481             # always ignore meta
482 169 100       693 next if $method->isa('Class::MOP::Method::Meta');
483             # we'll deal with attributes below
484 38 100       162 next if $method->can('associated_attribute');
485             # if the method comes from a role we consumed, ignore it
486 12 100 66     78 next if $meta->can('does_role')
487             && $meta->does_role($method->original_package_name);
488             # FIXME - this really isn't right. Just because a modifier is
489             # defined in a role doesn't mean it isn't _also_ defined in the
490             # subclass.
491             next if $method->isa('Class::MOP::Method::Wrapped')
492             && (
493             (!scalar($method->around_modifiers)
494 3     3   22 || any { $_->has_around_method_modifiers($method->name) } @roles)
495             && (!scalar($method->before_modifiers)
496 0     0   0 || any { $_->has_before_method_modifiers($method->name) } @roles)
497             && (!scalar($method->after_modifiers)
498 3 50 33 0   25 || any { $_->has_after_method_modifiers($method->name) } @roles)
  0   33     0  
      33        
      33        
      33        
      33        
499             );
500              
501 0         0 return 0;
502             }
503              
504             # loop over all attributes that are a part of the current class
505             # (not inherited)
506             # FIXME - this really isn't right. Just because an attribute is
507             # defined in a role doesn't mean it isn't _also_ defined in the
508             # subclass.
509 131         429 for my $attr (map { $meta->get_attribute($_) } $meta->get_attribute_list) {
  26         76  
510 26 50   26   145 next if any { $_->has_attribute($attr->name) } @roles;
  26         133  
511              
512 0         0 return 0;
513             }
514              
515 131         443 return 1;
516             }
517              
518             sub _is_package_loaded {
519 23     23   56 my ($package) = @_;
520 23         91 defined $INC{module_notional_filename($package)};
521             }
522              
523             1;
524              
525             # ABSTRACT: Utilities for working with Moose classes
526              
527             __END__
528              
529             =pod
530              
531             =encoding UTF-8
532              
533             =head1 NAME
534              
535             Moose::Util - Utilities for working with Moose classes
536              
537             =head1 VERSION
538              
539             version 2.2205
540              
541             =head1 SYNOPSIS
542              
543             use Moose::Util qw/find_meta does_role search_class_by_role/;
544              
545             my $meta = find_meta($object) || die "No metaclass found";
546              
547             if (does_role($object, $role)) {
548             print "The object can do $role!\n";
549             }
550              
551             my $class = search_class_by_role($object, 'FooRole');
552             print "Nearest class with 'FooRole' is $class\n";
553              
554             =head1 DESCRIPTION
555              
556             This module provides a set of utility functions. Many of these
557             functions are intended for use in Moose itself or MooseX modules, but
558             some of them may be useful for use in your own code.
559              
560             =head1 EXPORTED FUNCTIONS
561              
562             =head2 find_meta($class_or_obj)
563              
564             This method takes a class name or object and attempts to find a
565             metaclass for the class, if one exists. It will B<not> create one if it
566             does not yet exist.
567              
568             =head2 is_role($package_or_obj)
569              
570             Returns true if the provided package name or object is a L<Moose::Role>.
571              
572             =head2 does_role($class_or_obj, $role_or_obj)
573              
574             Returns true if C<$class_or_obj> does the given C<$role_or_obj>. The role can
575             be provided as a name or a L<Moose::Meta::Role> object.
576              
577             The class must already have a metaclass for this to work. If it doesn't, this
578             function simply returns false.
579              
580             =head2 search_class_by_role($class_or_obj, $role_or_obj)
581              
582             Returns the first class in the class's precedence list that does
583             C<$role_or_obj>, if any. The role can be either a name or a
584             L<Moose::Meta::Role> object.
585              
586             The class must already have a metaclass for this to work.
587              
588             =head2 apply_all_roles($applicant, @roles)
589              
590             This function applies one or more roles to the given C<$applicant>. The
591             applicant can be a role name, class name, or object.
592              
593             The C<$applicant> must already have a metaclass object.
594              
595             The list of C<@roles> should a list of names or L<Moose::Meta::Role> objects,
596             each of which can be followed by an optional hash reference of options
597             (C<-excludes> and C<-alias>).
598              
599             =head2 ensure_all_roles($applicant, @roles)
600              
601             This function is similar to C<apply_all_roles>, but only applies roles that
602             C<$applicant> does not already consume.
603              
604             =head2 with_traits($class_name, @role_names)
605              
606             This function creates a new class from C<$class_name> with each of
607             C<@role_names> applied. It returns the name of the new class.
608              
609             =head2 get_all_attribute_values($meta, $instance)
610              
611             Returns a hash reference containing all of the C<$instance>'s
612             attributes. The keys are attribute names.
613              
614             =head2 get_all_init_args($meta, $instance)
615              
616             Returns a hash reference containing all of the C<init_arg> values for
617             the instance's attributes. The values are the associated attribute
618             values. If an attribute does not have a defined C<init_arg>, it is
619             skipped.
620              
621             This could be useful in cloning an object.
622              
623             =head2 resolve_metaclass_alias($category, $name, %options)
624              
625             =head2 resolve_metatrait_alias($category, $name, %options)
626              
627             Resolves a short name to a full class name. Short names are often used
628             when specifying the C<metaclass> or C<traits> option for an attribute:
629              
630             has foo => (
631             metaclass => "Bar",
632             );
633              
634             The name resolution mechanism is covered in
635             L<Moose/Metaclass and Trait Name Resolution>.
636              
637             =head2 meta_class_alias($to[, $from])
638              
639             =head2 meta_attribute_alias($to[, $from])
640              
641             Create an alias from the class C<$from> (or the current package, if
642             C<$from> is unspecified), so that
643             L<Moose/Metaclass and Trait Name Resolution> works properly.
644              
645             =head2 english_list(@items)
646              
647             Given a list of scalars, turns them into a proper list in English
648             ("one and two", "one, two, three, and four"). This is used to help us
649             make nicer error messages.
650              
651             =head2 throw_exception( $class_name, %arguments_to_exception)
652              
653             Calls die with an object of Moose::Exception::$class_name, with
654             %arguments_to_exception passed as arguments.
655              
656             =head1 TODO
657              
658             Here is a list of possible functions to write
659              
660             =over 4
661              
662             =item discovering original method from modified method
663              
664             =item search for origin class of a method or attribute
665              
666             =back
667              
668             =head1 BUGS
669              
670             See L<Moose/BUGS> for details on reporting bugs.
671              
672             =head1 AUTHORS
673              
674             =over 4
675              
676             =item *
677              
678             Stevan Little <stevan@cpan.org>
679              
680             =item *
681              
682             Dave Rolsky <autarch@urth.org>
683              
684             =item *
685              
686             Jesse Luehrs <doy@cpan.org>
687              
688             =item *
689              
690             Shawn M Moore <sartak@cpan.org>
691              
692             =item *
693              
694             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
695              
696             =item *
697              
698             Karen Etheridge <ether@cpan.org>
699              
700             =item *
701              
702             Florian Ragwitz <rafl@debian.org>
703              
704             =item *
705              
706             Hans Dieter Pearcey <hdp@cpan.org>
707              
708             =item *
709              
710             Chris Prather <chris@prather.org>
711              
712             =item *
713              
714             Matt S Trout <mstrout@cpan.org>
715              
716             =back
717              
718             =head1 COPYRIGHT AND LICENSE
719              
720             This software is copyright (c) 2006 by Infinity Interactive, Inc.
721              
722             This is free software; you can redistribute it and/or modify it under
723             the same terms as the Perl 5 programming language system itself.
724              
725             =cut