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.2206';
3              
4 394     403   842000 use strict;
  394         1031  
  394         14676  
5 394     402   2038 use warnings;
  394         2004  
  394         20144  
6              
7 394     402   25848 use Module::Runtime 0.014 'use_package_optimistically', 'module_notional_filename';
  394         93082  
  394         3747  
8 394     402   32418 use Data::OptList;
  394         134120  
  394         10784  
9 394     402   219383 use Sub::Exporter;
  394         1163836  
  394         3670  
10 394     402   88590 use Scalar::Util 'blessed';
  394         3891  
  394         24862  
11 394     402   5076 use List::Util 1.33 qw(first any all);
  394         9065  
  394         24559  
12 394     394   2739 use overload ();
  394         900  
  394         6613  
13 394     394   16945 use Try::Tiny;
  394         62029  
  394         1338351  
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 9562 my ($class_name, @args_to_exception) = @_;
46 1348         3631 my $class = "Moose::Exception::$class_name";
47 1348         3951 _load_user_class( $class );
48 1348         108938 die $class->new( @args_to_exception );
49             }
50              
51             ## some utils for the utils ...
52              
53 2306     2306 1 7641 sub find_meta { Class::MOP::class_of(@_) }
54              
55             ## the functions ...
56              
57             sub is_role {
58 7     7 1 21 my $package_or_obj = shift;
59              
60 7         20 my $meta = find_meta($package_or_obj);
61 7 100       22 return if not $meta;
62 5         45 return $meta->isa('Moose::Meta::Role');
63             }
64              
65             sub does_role {
66 122     122 1 3934 my ($class_or_obj, $role) = @_;
67              
68 122 100   122   723 if (try { $class_or_obj->isa('Moose::Object') }) {
  122         3778  
69 49         737 return $class_or_obj->does($role);
70             }
71              
72 73         1152 my $meta = find_meta($class_or_obj);
73              
74 73 100       233 return unless defined $meta;
75 70 100       393 return unless $meta->can('does_role');
76 58 100       200 return 1 if $meta->does_role($role);
77 6         34 return;
78             }
79              
80             sub search_class_by_role {
81 8     8 1 274 my ($class_or_obj, $role) = @_;
82              
83 8         18 my $meta = find_meta($class_or_obj);
84              
85 8 50       19 return unless defined $meta;
86              
87 8 100       39 my $role_name = blessed $role ? $role->name : $role;
88              
89 8         33 foreach my $class ($meta->class_precedence_list) {
90              
91 12         28 my $_meta = find_meta($class);
92              
93 12 50       28 next unless defined $_meta;
94              
95 12 50       16 foreach my $role (@{ $_meta->roles || [] }) {
  12         353  
96 6 50       71 return $class if $role->name eq $role_name;
97             }
98             }
99              
100 2         12 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 8 my $applicant = shift;
108 2     4   12 _apply_all_roles($applicant, sub { !does_role($applicant, $_) }, @_);
  4         21  
109             }
110              
111             sub apply_all_roles {
112 1642     1642 1 4357 my $applicant = shift;
113 1642         5487 _apply_all_roles($applicant, undef, @_);
114             }
115              
116             sub _apply_all_roles {
117 1644     1644   2957 my $applicant = shift;
118 1644         3397 my $role_filter = shift;
119              
120 1644 100       4837 unless (@_) {
121 3         19 require Moose;
122 3         15 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   10536 ! ref $_[0] or blessed($_[0]) && $_[0]->isa('Moose::Meta::Role')
135             }
136 1641         13843 });
137              
138 1641         58538 my @role_metas;
139 1641         4451 foreach my $role (@$roles) {
140 1924         3119 my $meta;
141              
142 1924 100       7400 if ( blessed $role->[0] ) {
143 26         77 $meta = $role->[0];
144             }
145             else {
146 1898         6176 _load_user_class( $role->[0] , $role->[1] );
147 1894         92857 $meta = find_meta( $role->[0] );
148             }
149              
150 1920 100 100     14687 unless ($meta && $meta->isa('Moose::Meta::Role') ) {
151 3         10 throw_exception( CanOnlyConsumeRole => role_name => $role->[0] );
152             }
153              
154 1917         7198 push @role_metas, [ $meta, $role->[1] ];
155             }
156              
157 1634 100       5201 if ( defined $role_filter ) {
158 2         5 @role_metas = grep { local $_ = $_->[0]; $role_filter->() } @role_metas;
  4         11  
  4         10  
159             }
160              
161 1634 100       4292 return unless @role_metas;
162              
163 1632 100 100     8356 _load_user_class($applicant)
164             unless blessed($applicant)
165             || Class::MOP::class_of($applicant);
166              
167 1632 100       7071 my $meta = ( blessed $applicant ? $applicant : Moose::Meta::Class->initialize($applicant) );
168              
169 1632 100       5038 if ( scalar @role_metas == 1 ) {
170 1406         2707 my ( $role, $params ) = @{ $role_metas[0] };
  1406         3851  
171 1406 100       7009 $role->apply( $meta, ( defined $params ? %$params : () ) );
172             }
173             else {
174 226         1508 Moose::Meta::Role->combine(@role_metas)->apply($meta);
175             }
176             }
177              
178             sub with_traits {
179 5     5 1 1399 my ($class, @roles) = @_;
180 5 100       18 return $class unless @roles;
181 4         43 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 2735 return resolve_metaclass_alias( @_, trait => 1 );
211             }
212              
213             sub _build_alias_package_name {
214 218     218   645 my ($type, $name, $trait) = @_;
215 218 100       1216 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 3157 my ( $type, $metaclass_name, %options ) = @_;
227              
228 498 100       1989 my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );
229             return $cache{$cache_key}{$metaclass_name}
230 498 100       2818 if $cache{$cache_key}{$metaclass_name};
231              
232             my $possible_full_name = _build_alias_package_name(
233             $type, $metaclass_name, $options{trait}
234 206         842 );
235              
236 206         678 my @possible = ($possible_full_name, $metaclass_name);
237 206         534 for my $package (@possible) {
238 330         1221 use_package_optimistically($package);
239 330 100       75063 if ($package->can('register_implementation')) {
    100          
240 81         578 return $cache{$cache_key}{$metaclass_name} =
241             $package->register_implementation;
242             }
243             elsif (find_meta($package)) {
244 121         1070 return $cache{$cache_key}{$metaclass_name} = $package;
245             }
246             }
247              
248 4         37 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 2180 my ( $class_or_obj, $modifier_name, $args ) = @_;
259 413 100       2345 my $meta
260             = $class_or_obj->can('add_before_method_modifier')
261             ? $class_or_obj
262             : find_meta($class_or_obj);
263 413         778 my $code = pop @{$args};
  413         840  
264 413         1210 my $add_modifier_method = 'add_' . $modifier_name . '_method_modifier';
265 413 100       1259 if ( my $method_modifier_type = ref( $args->[0] ) ) {
266 7 100       30 if ( $method_modifier_type eq 'Regexp' ) {
    100          
267 3         13 my @all_methods = $meta->get_all_methods;
268             my @matched_methods
269 3         10 = grep { $_->name =~ $args->[0] } @all_methods;
  42         164  
270             $meta->$add_modifier_method( $_->name, $code )
271 3         28 for @matched_methods;
272             }
273             elsif ($method_modifier_type eq 'ARRAY') {
274 2         6 $meta->$add_modifier_method( $_, $code ) for @{$args->[0]};
  2         19  
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         695 $meta->$add_modifier_method( $_, $code ) for @{$args};
  406         2081  
285             }
286             }
287              
288             sub english_list {
289 63     63 1 198 _english_list_and(@_);
290             }
291              
292             sub _english_list_and {
293 63     63   215 _english_list('and', \@_);
294             }
295              
296             sub _english_list_or {
297 55     55   184 _english_list('or', \@_);
298             }
299              
300             sub _english_list {
301 118     118   282 my ($conjunction, $items) = @_;
302              
303 118         513 my @items = sort @$items;
304              
305 118 100       417 return $items[0] if @items == 1;
306 103 100       592 return "$items[0] $conjunction $items[1]" if @items == 2;
307              
308 53         101 my $tail = pop @items;
309 53         133 my $list = join ', ', @items;
310 53         127 $list .= ", $conjunction " . $tail;
311              
312 53         417 return $list;
313             }
314              
315             sub _caller_info {
316 1930 50   1930   6226 my $level = @_ ? ($_[0] + 1) : 2;
317 1930         3354 my %info;
318 1930         17973 @info{qw(package file line)} = caller($level);
319 1930         12733 return %info;
320             }
321              
322             sub _create_alias {
323 12     12   41 my ($type, $name, $trait, $for) = @_;
324 12         42 my $package = _build_alias_package_name($type, $name, $trait);
325             Class::MOP::Class->initialize($package)->add_method(
326 11     11   98 register_implementation => sub { $for }
        11      
327 12         61 );
328             }
329              
330             sub meta_attribute_alias {
331 6     6 1 215 my ($to, $from) = @_;
332 6   66     49 $from ||= caller;
333 6         24 my $meta = Class::MOP::class_of($from);
334 6         50 my $trait = $meta->isa('Moose::Meta::Role');
335 6         20 _create_alias('Attribute', $to, $trait, $from);
336             }
337              
338             sub meta_class_alias {
339 6     6 1 254 my ($to, $from) = @_;
340 6   66     38 $from ||= caller;
341 6         23 my $meta = Class::MOP::class_of($from);
342 6         56 my $trait = $meta->isa('Moose::Meta::Role');
343 6         25 _create_alias('Class', $to, $trait, $from);
344             }
345              
346             sub _load_user_class {
347 8234     8234   17144 my ($class, $opts) = @_;
348             &use_package_optimistically(
349             $class,
350             $opts && $opts->{-version} ? $opts->{-version} : ()
351 8234 100 100     36253 );
352             }
353              
354             # XXX - this should be added to Params::Util
355             sub _STRINGLIKE0 ($) {
356 408 50   408   185485 return 0 if !defined $_[0];
357 408 100       1496 return 1 if !ref $_[0];
358 221 100       761 return 1 if overload::OverloadedStringify($_[0]);
359 197         17960 return 0;
360             }
361              
362             sub _reconcile_roles_for_metaclass {
363 61     61   136 my ($class_meta_name, $super_meta_name) = @_;
364              
365 61         147 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       161 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   121 my ($class_meta_name, $super_meta_name) = @_;
385             my @super_role_metas = map {
386             $_->isa('Moose::Meta::Role::Composite')
387 64 50       453 ? (@{ $_->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       227 ? @{ $super_meta_name->meta->roles }
  0 50       0  
393             : ();
394             my @role_metas = map {
395             $_->isa('Moose::Meta::Role::Composite')
396 67 100       357 ? (@{ $_->get_roles })
  3         99  
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       274 ? @{ $class_meta_name->meta->roles }
  0 50       0  
402             : ();
403 61         176 my @differences;
404 61         142 for my $role_meta (@role_metas) {
405             push @differences, $role_meta
406 70 100   70   364 unless any { $_->name eq $role_meta->name } @super_role_metas;
  70         493  
407             }
408 61         178 return @differences;
409             }
410              
411             sub _classes_differ_by_roles_only {
412 63     63   148 my ( $self_meta_name, $super_meta_name ) = @_;
413              
414 63         162 my $common_base_name
415             = _find_common_base( $self_meta_name, $super_meta_name );
416              
417 63 50       407 return unless defined $common_base_name;
418              
419             my @super_meta_name_ancestor_names
420 63         190 = _get_ancestors_until( $super_meta_name, $common_base_name );
421             my @class_meta_name_ancestor_names
422 63         150 = _get_ancestors_until( $self_meta_name, $common_base_name );
423              
424             return
425 133     133   292 unless all { _is_role_only_subclass($_) }
426 63 100       334 @super_meta_name_ancestor_names,
427             @class_meta_name_ancestor_names;
428              
429 61         342 return 1;
430             }
431              
432             sub _find_common_base {
433 63     63   135 my ($meta1, $meta2) = map { Class::MOP::class_of($_) } @_;
  126         275  
434 63 50 33     319 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         209 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
  607         1147  
443              
444 63     129   410 return first { $meta1_parents{$_} } $meta2->linearized_isa;
  129         309  
445             }
446              
447             sub _get_ancestors_until {
448 126     126   254 my ($start_name, $until_name) = @_;
449              
450 126         172 my @ancestor_names;
451 126         260 for my $ancestor_name (Class::MOP::class_of($start_name)->linearized_isa) {
452 263 100       589 last if $ancestor_name eq $until_name;
453 137         256 push @ancestor_names, $ancestor_name;
454             }
455 126         378 return @ancestor_names;
456             }
457              
458             sub _is_role_only_subclass {
459 133     133   261 my ($meta_name) = @_;
460 133         416 my $meta = Class::MOP::Class->initialize($meta_name);
461 133         442 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       354 return unless @parent_names == 1;
466 133         241 my ($parent_name) = @parent_names;
467 133         314 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       657 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       442 return unless @roles;
477              
478             # loop over all methods that are a part of the current class
479             # (not inherited)
480 131         420 for my $method ( $meta->_get_local_methods ) {
481             # always ignore meta
482 169 100       715 next if $method->isa('Class::MOP::Method::Meta');
483             # we'll deal with attributes below
484 38 100       188 next if $method->can('associated_attribute');
485             # if the method comes from a role we consumed, ignore it
486 12 100 66     87 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   19 || 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   35 || 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         479 for my $attr (map { $meta->get_attribute($_) } $meta->get_attribute_list) {
  26         79  
510 26 50   26   144 next if any { $_->has_attribute($attr->name) } @roles;
  26         135  
511              
512 0         0 return 0;
513             }
514              
515 131         458 return 1;
516             }
517              
518             sub _is_package_loaded {
519 23     23   56 my ($package) = @_;
520 23         98 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.2206
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