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.2203';
3              
4 405     414   1103264 use strict;
  405         855  
  405         10979  
5 405     413   1772 use warnings;
  405         656  
  405         12172  
6              
7 405     413   21393 use Module::Runtime 0.014 'use_package_optimistically', 'module_notional_filename';
  405         76763  
  405         2287  
8 405     413   26129 use Data::OptList;
  405         116296  
  405         3602  
9 405     413   176704 use Sub::Exporter;
  405         1006159  
  405         1946  
10 405     413   77415 use Scalar::Util 'blessed';
  405         794  
  405         19203  
11 405     413   2196 use List::Util 1.33 qw(first any all);
  405         5620  
  405         20146  
12 405     405   2353 use overload ();
  405         773  
  405         6032  
13 405     405   15399 use Try::Tiny;
  405         55303  
  405         1205743  
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 1353     1353 1 8745 my ($class_name, @args_to_exception) = @_;
46 1353         3126 my $class = "Moose::Exception::$class_name";
47 1353         3709 _load_user_class( $class );
48 1353         99177 die $class->new( @args_to_exception );
49             }
50              
51             ## some utils for the utils ...
52              
53 2318     2318 1 6861 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         14 my $meta = find_meta($package_or_obj);
61 7 100       19 return if not $meta;
62 5         65 return $meta->isa('Moose::Meta::Role');
63             }
64              
65             sub does_role {
66 123     123 1 3991 my ($class_or_obj, $role) = @_;
67              
68 123 100   123   657 if (try { $class_or_obj->isa('Moose::Object') }) {
  123         3285  
69 49         667 return $class_or_obj->does($role);
70             }
71              
72 74         986 my $meta = find_meta($class_or_obj);
73              
74 74 100       181 return unless defined $meta;
75 71 100       338 return unless $meta->can('does_role');
76 59 100       177 return 1 if $meta->does_role($role);
77 6         26 return;
78             }
79              
80             sub search_class_by_role {
81 8     8 1 255 my ($class_or_obj, $role) = @_;
82              
83 8         23 my $meta = find_meta($class_or_obj);
84              
85 8 50       19 return unless defined $meta;
86              
87 8 100       40 my $role_name = blessed $role ? $role->name : $role;
88              
89 8         36 foreach my $class ($meta->class_precedence_list) {
90              
91 12         27 my $_meta = find_meta($class);
92              
93 12 50       26 next unless defined $_meta;
94              
95 12 50       19 foreach my $role (@{ $_meta->roles || [] }) {
  12         349  
96 6 50       59 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 6 my $applicant = shift;
108 2     4   12 _apply_all_roles($applicant, sub { !does_role($applicant, $_) }, @_);
  4         7  
109             }
110              
111             sub apply_all_roles {
112 1651     1651 1 3793 my $applicant = shift;
113 1651         4868 _apply_all_roles($applicant, undef, @_);
114             }
115              
116             sub _apply_all_roles {
117 1653     1653   2705 my $applicant = shift;
118 1653         3466 my $role_filter = shift;
119              
120 1653 100       4448 unless (@_) {
121 3         20 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 318 100 66 318   9167 ! ref $_[0] or blessed($_[0]) && $_[0]->isa('Moose::Meta::Role')
135             }
136 1650         12312 });
137              
138 1650         51357 my @role_metas;
139 1650         3969 foreach my $role (@$roles) {
140 1933         2919 my $meta;
141              
142 1933 100       7003 if ( blessed $role->[0] ) {
143 26         57 $meta = $role->[0];
144             }
145             else {
146 1907         5564 _load_user_class( $role->[0] , $role->[1] );
147 1903         80971 $meta = find_meta( $role->[0] );
148             }
149              
150 1929 100 100     13218 unless ($meta && $meta->isa('Moose::Meta::Role') ) {
151 3         20 throw_exception( CanOnlyConsumeRole => role_name => $role->[0] );
152             }
153              
154 1926         6253 push @role_metas, [ $meta, $role->[1] ];
155             }
156              
157 1643 100       6376 if ( defined $role_filter ) {
158 2         5 @role_metas = grep { local $_ = $_->[0]; $role_filter->() } @role_metas;
  4         7  
  4         7  
159             }
160              
161 1643 100       4058 return unless @role_metas;
162              
163 1641 100 100     9226 _load_user_class($applicant)
164             unless blessed($applicant)
165             || Class::MOP::class_of($applicant);
166              
167 1641 100       6417 my $meta = ( blessed $applicant ? $applicant : Moose::Meta::Class->initialize($applicant) );
168              
169 1641 100       4525 if ( scalar @role_metas == 1 ) {
170 1415         2581 my ( $role, $params ) = @{ $role_metas[0] };
  1415         3568  
171 1415 100       6455 $role->apply( $meta, ( defined $params ? %$params : () ) );
172             }
173             else {
174 226         1283 Moose::Meta::Role->combine(@role_metas)->apply($meta);
175             }
176             }
177              
178             sub with_traits {
179 5     5 1 2004 my ($class, @roles) = @_;
180 5 100       16 return $class unless @roles;
181 4         35 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 477     477 1 3056 return resolve_metaclass_alias( @_, trait => 1 );
211             }
212              
213             sub _build_alias_package_name {
214 219     219   557 my ($type, $name, $trait) = @_;
215 219 100       1023 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 504     504 1 3436 my ( $type, $metaclass_name, %options ) = @_;
227              
228 504 100       1790 my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );
229             return $cache{$cache_key}{$metaclass_name}
230 504 100       2539 if $cache{$cache_key}{$metaclass_name};
231              
232             my $possible_full_name = _build_alias_package_name(
233             $type, $metaclass_name, $options{trait}
234 207         758 );
235              
236 207         581 my @possible = ($possible_full_name, $metaclass_name);
237 207         505 for my $package (@possible) {
238 332         1113 use_package_optimistically($package);
239 332 100       62030 if ($package->can('register_implementation')) {
    100          
240 81         461 return $cache{$cache_key}{$metaclass_name} =
241             $package->register_implementation;
242             }
243             elsif (find_meta($package)) {
244 122         841 return $cache{$cache_key}{$metaclass_name} = $package;
245             }
246             }
247              
248 4         19 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 419     419 0 2297 my ( $class_or_obj, $modifier_name, $args ) = @_;
259 419 100       2102 my $meta
260             = $class_or_obj->can('add_before_method_modifier')
261             ? $class_or_obj
262             : find_meta($class_or_obj);
263 419         688 my $code = pop @{$args};
  419         755  
264 419         1072 my $add_modifier_method = 'add_' . $modifier_name . '_method_modifier';
265 419 100       1126 if ( my $method_modifier_type = ref( $args->[0] ) ) {
266 7 100       28 if ( $method_modifier_type eq 'Regexp' ) {
    100          
267 3         12 my @all_methods = $meta->get_all_methods;
268             my @matched_methods
269 3         9 = grep { $_->name =~ $args->[0] } @all_methods;
  42         151  
270             $meta->$add_modifier_method( $_->name, $code )
271 3         25 for @matched_methods;
272             }
273             elsif ($method_modifier_type eq 'ARRAY') {
274 2         5 $meta->$add_modifier_method( $_, $code ) for @{$args->[0]};
  2         17  
275             }
276             else {
277 2         8 throw_exception( IllegalMethodTypeToAddMethodModifier => class_or_object => $class_or_obj,
278             modifier_name => $modifier_name,
279             params => $args
280             );
281             }
282             }
283             else {
284 412         603 $meta->$add_modifier_method( $_, $code ) for @{$args};
  412         1771  
285             }
286             }
287              
288             sub english_list {
289 63     63 1 191 _english_list_and(@_);
290             }
291              
292             sub _english_list_and {
293 63     63   203 _english_list('and', \@_);
294             }
295              
296             sub _english_list_or {
297 55     55   146 _english_list('or', \@_);
298             }
299              
300             sub _english_list {
301 118     118   251 my ($conjunction, $items) = @_;
302              
303 118         415 my @items = sort @$items;
304              
305 118 100       327 return $items[0] if @items == 1;
306 103 100       479 return "$items[0] $conjunction $items[1]" if @items == 2;
307              
308 53         78 my $tail = pop @items;
309 53         112 my $list = join ', ', @items;
310 53         109 $list .= ", $conjunction " . $tail;
311              
312 53         356 return $list;
313             }
314              
315             sub _caller_info {
316 1945 50   1945   5516 my $level = @_ ? ($_[0] + 1) : 2;
317 1945         2881 my %info;
318 1945         15687 @info{qw(package file line)} = caller($level);
319 1945         11062 return %info;
320             }
321              
322             sub _create_alias {
323 12     12   43 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   112 register_implementation => sub { $for }
        11      
327 12         64 );
328             }
329              
330             sub meta_attribute_alias {
331 6     6 1 265 my ($to, $from) = @_;
332 6   66     30 $from ||= caller;
333 6         22 my $meta = Class::MOP::class_of($from);
334 6         51 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 292 my ($to, $from) = @_;
340 6   66     32 $from ||= caller;
341 6         23 my $meta = Class::MOP::class_of($from);
342 6         54 my $trait = $meta->isa('Moose::Meta::Role');
343 6         34 _create_alias('Class', $to, $trait, $from);
344             }
345              
346             sub _load_user_class {
347 8320     8320   15428 my ($class, $opts) = @_;
348             &use_package_optimistically(
349             $class,
350             $opts && $opts->{-version} ? $opts->{-version} : ()
351 8320 100 100     33068 );
352             }
353              
354             # XXX - this should be added to Params::Util
355             sub _STRINGLIKE0 ($) {
356 408 50   408   181766 return 0 if !defined $_[0];
357 408 100       1266 return 1 if !ref $_[0];
358 221 100       587 return 1 if overload::OverloadedStringify($_[0]);
359 197         14529 return 0;
360             }
361              
362             sub _reconcile_roles_for_metaclass {
363 61     61   117 my ($class_meta_name, $super_meta_name) = @_;
364              
365 61         124 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       165 return $super_meta_name
374             unless @role_differences;
375              
376             return Moose::Meta::Class->create_anon_class(
377             superclasses => [$super_meta_name],
378 58         146 roles => [map { $_->name } @role_differences],
  58         277  
379             cache => 1,
380             )->name;
381             }
382              
383             sub _role_differences {
384 61     61   102 my ($class_meta_name, $super_meta_name) = @_;
385             my @super_role_metas = map {
386             $_->isa('Moose::Meta::Role::Composite')
387 64 50       380 ? (@{ $_->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       197 ? @{ $super_meta_name->meta->roles }
  0 50       0  
393             : ();
394             my @role_metas = map {
395             $_->isa('Moose::Meta::Role::Composite')
396 67 100       307 ? (@{ $_->get_roles })
  3         67  
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       244 ? @{ $class_meta_name->meta->roles }
  0 50       0  
402             : ();
403 61         121 my @differences;
404 61         108 for my $role_meta (@role_metas) {
405             push @differences, $role_meta
406 70 100   70   322 unless any { $_->name eq $role_meta->name } @super_role_metas;
  70         410  
407             }
408 61         159 return @differences;
409             }
410              
411             sub _classes_differ_by_roles_only {
412 63     63   127 my ( $self_meta_name, $super_meta_name ) = @_;
413              
414 63         140 my $common_base_name
415             = _find_common_base( $self_meta_name, $super_meta_name );
416              
417 63 50       290 return unless defined $common_base_name;
418              
419             my @super_meta_name_ancestor_names
420 63         158 = _get_ancestors_until( $super_meta_name, $common_base_name );
421             my @class_meta_name_ancestor_names
422 63         140 = _get_ancestors_until( $self_meta_name, $common_base_name );
423              
424             return
425 133     133   266 unless all { _is_role_only_subclass($_) }
426 63 100       259 @super_meta_name_ancestor_names,
427             @class_meta_name_ancestor_names;
428              
429 61         295 return 1;
430             }
431              
432             sub _find_common_base {
433 63     63   115 my ($meta1, $meta2) = map { Class::MOP::class_of($_) } @_;
  126         228  
434 63 50 33     244 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         171 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
  607         966  
443              
444 63     129   348 return first { $meta1_parents{$_} } $meta2->linearized_isa;
  129         262  
445             }
446              
447             sub _get_ancestors_until {
448 126     126   189 my ($start_name, $until_name) = @_;
449              
450 126         139 my @ancestor_names;
451 126         229 for my $ancestor_name (Class::MOP::class_of($start_name)->linearized_isa) {
452 263 100       468 last if $ancestor_name eq $until_name;
453 137         208 push @ancestor_names, $ancestor_name;
454             }
455 126         298 return @ancestor_names;
456             }
457              
458             sub _is_role_only_subclass {
459 133     133   205 my ($meta_name) = @_;
460 133         340 my $meta = Class::MOP::Class->initialize($meta_name);
461 133         377 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       319 return unless @parent_names == 1;
466 133         217 my ($parent_name) = @parent_names;
467 133         298 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       583 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       334 return unless @roles;
477              
478             # loop over all methods that are a part of the current class
479             # (not inherited)
480 131         382 for my $method ( $meta->_get_local_methods ) {
481             # always ignore meta
482 169 100       589 next if $method->isa('Class::MOP::Method::Meta');
483             # we'll deal with attributes below
484 38 100       157 next if $method->can('associated_attribute');
485             # if the method comes from a role we consumed, ignore it
486 12 100 66     65 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   16 || 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   19 || 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         375 for my $attr (map { $meta->get_attribute($_) } $meta->get_attribute_list) {
  26         79  
510 26 50   26   158 next if any { $_->has_attribute($attr->name) } @roles;
  26         120  
511              
512 0         0 return 0;
513             }
514              
515 131         387 return 1;
516             }
517              
518             sub _is_package_loaded {
519 23     23   63 my ($package) = @_;
520 23         74 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.2203
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