1package Role::Tiny; 2use strict; 3use warnings; 4 5our $VERSION = '2.002004'; 6$VERSION =~ tr/_//d; 7 8our %INFO; 9our %APPLIED_TO; 10our %COMPOSED; 11our %COMPOSITE_INFO; 12our @ON_ROLE_CREATE; 13 14# Module state workaround totally stolen from Zefram's Module::Runtime. 15 16BEGIN { 17 *_WORK_AROUND_BROKEN_MODULE_STATE = "$]" < 5.009 ? sub(){1} : sub(){0}; 18 *_WORK_AROUND_HINT_LEAKAGE 19 = "$]" < 5.011 && !("$]" >= 5.009004 && "$]" < 5.010001) 20 ? sub(){1} : sub(){0}; 21 *_CONSTANTS_DEFLATE = "$]" >= 5.012 && "$]" < 5.020 ? sub(){1} : sub(){0}; 22} 23 24sub _getglob { no strict 'refs'; \*{$_[0]} } 25sub _getstash { no strict 'refs'; \%{"$_[0]::"} } 26 27sub croak { 28 require Carp; 29 no warnings 'redefine'; 30 *croak = \&Carp::croak; 31 goto &Carp::croak; 32} 33 34sub Role::Tiny::__GUARD__::DESTROY { 35 delete $INC{$_[0]->[0]} if @{$_[0]}; 36} 37 38sub _load_module { 39 my ($module) = @_; 40 (my $file = "$module.pm") =~ s{::}{/}g; 41 return 1 42 if $INC{$file}; 43 44 # can't just ->can('can') because a sub-package Foo::Bar::Baz 45 # creates a 'Baz::' key in Foo::Bar's symbol table 46 return 1 47 if grep !/::\z/, keys %{_getstash($module)}; 48 my $guard = _WORK_AROUND_BROKEN_MODULE_STATE 49 && bless([ $file ], 'Role::Tiny::__GUARD__'); 50 local %^H if _WORK_AROUND_HINT_LEAKAGE; 51 require $file; 52 pop @$guard if _WORK_AROUND_BROKEN_MODULE_STATE; 53 return 1; 54} 55 56sub _require_module { 57 _load_module($_[1]); 58} 59 60sub _all_subs { 61 my ($me, $package) = @_; 62 my $stash = _getstash($package); 63 return { 64 map {; 65 no strict 'refs'; 66 # this is an ugly hack to populate the scalar slot of any globs, to 67 # prevent perl from converting constants back into scalar refs in the 68 # stash when they are used (perl 5.12 - 5.18). scalar slots on their own 69 # aren't detectable through pure perl, so this seems like an acceptable 70 # compromise. 71 ${"${package}::${_}"} = ${"${package}::${_}"} 72 if _CONSTANTS_DEFLATE; 73 $_ => \&{"${package}::${_}"} 74 } 75 grep exists &{"${package}::${_}"}, 76 grep !/::\z/, 77 keys %$stash 78 }; 79} 80 81sub import { 82 my $target = caller; 83 my $me = shift; 84 strict->import; 85 warnings->import; 86 my $non_methods = $me->_non_methods($target); 87 $me->_install_subs($target, @_); 88 $me->make_role($target); 89 $me->_mark_new_non_methods($target, $non_methods) 90 if $non_methods && %$non_methods; 91 return; 92} 93 94sub _mark_new_non_methods { 95 my ($me, $target, $old_non_methods) = @_; 96 97 my $non_methods = $INFO{$target}{non_methods}; 98 99 my $subs = $me->_all_subs($target); 100 for my $sub (keys %$subs) { 101 if ( exists $old_non_methods->{$sub} && $non_methods->{$sub} != $subs->{$sub} ) { 102 $non_methods->{$sub} = $subs->{$sub}; 103 } 104 } 105 106 return; 107} 108 109sub make_role { 110 my ($me, $target) = @_; 111 112 return if $me->is_role($target); 113 $INFO{$target}{is_role} = 1; 114 115 my $non_methods = $me->_all_subs($target); 116 delete @{$non_methods}{grep /\A\(/, keys %$non_methods}; 117 $INFO{$target}{non_methods} = $non_methods; 118 119 # a role does itself 120 $APPLIED_TO{$target} = { $target => undef }; 121 foreach my $hook (@ON_ROLE_CREATE) { 122 $hook->($target); 123 } 124} 125 126sub _install_subs { 127 my ($me, $target) = @_; 128 return if $me->is_role($target); 129 my %install = $me->_gen_subs($target); 130 *{_getglob("${target}::${_}")} = $install{$_} 131 for sort keys %install; 132 return; 133} 134 135sub _gen_subs { 136 my ($me, $target) = @_; 137 ( 138 (map {; 139 my $type = $_; 140 $type => sub { 141 my $code = pop; 142 my @names = ref $_[0] eq 'ARRAY' ? @{ $_[0] } : @_; 143 push @{$INFO{$target}{modifiers}||=[]}, [ $type, @names, $code ]; 144 return; 145 }; 146 } qw(before after around)), 147 requires => sub { 148 push @{$INFO{$target}{requires}||=[]}, @_; 149 return; 150 }, 151 with => sub { 152 $me->apply_roles_to_package($target, @_); 153 return; 154 }, 155 ); 156} 157 158sub role_application_steps { 159 qw( 160 _install_methods 161 _check_requires 162 _install_modifiers 163 _copy_applied_list 164 ); 165} 166 167sub _copy_applied_list { 168 my ($me, $to, $role) = @_; 169 # copy our role list into the target's 170 @{$APPLIED_TO{$to}||={}}{keys %{$APPLIED_TO{$role}}} = (); 171} 172 173sub apply_roles_to_object { 174 my ($me, $object, @roles) = @_; 175 my $class = ref($object); 176 # on perl < 5.8.9, magic isn't copied to all ref copies. bless the parameter 177 # directly, so at least the variable passed to us will get any magic applied 178 bless($_[1], $me->create_class_with_roles($class, @roles)); 179} 180 181my $role_suffix = 'A000'; 182sub _composite_name { 183 my ($me, $superclass, @roles) = @_; 184 185 my $new_name = $superclass . '__WITH__' . join '__AND__', @roles; 186 187 if (length($new_name) > 252) { 188 $new_name = $COMPOSED{abbrev}{$new_name} ||= do { 189 my $abbrev = substr $new_name, 0, 250 - length $role_suffix; 190 $abbrev =~ s/(?<!:):$//; 191 $abbrev.'__'.$role_suffix++; 192 }; 193 } 194 return $new_name; 195} 196 197sub create_class_with_roles { 198 my ($me, $superclass, @roles) = @_; 199 200 $me->_require_module($superclass); 201 $me->_check_roles(@roles); 202 203 my $new_name = $me->_composite_name($superclass, @roles); 204 205 return $new_name 206 if $COMPOSED{class}{$new_name}; 207 208 return $me->_build_class_with_roles($new_name, $superclass, @roles); 209} 210 211sub _build_class_with_roles { 212 my ($me, $new_name, $superclass, @roles) = @_; 213 214 $COMPOSED{base}{$new_name} = $superclass; 215 @{*{_getglob("${new_name}::ISA")}} = ( $superclass ); 216 $me->apply_roles_to_package($new_name, @roles); 217 $COMPOSED{class}{$new_name} = 1; 218 return $new_name; 219} 220 221sub _check_roles { 222 my ($me, @roles) = @_; 223 croak "No roles supplied!" unless @roles; 224 225 my %seen; 226 if (my @dupes = grep 1 == $seen{$_}++, @roles) { 227 croak "Duplicated roles: ".join(', ', @dupes); 228 } 229 230 foreach my $role (@roles) { 231 $me->_require_module($role); 232 croak "${role} is not a ${me}" unless $me->is_role($role); 233 } 234} 235 236our %BACKCOMPAT_HACK; 237$BACKCOMPAT_HACK{+__PACKAGE__} = 0; 238sub _want_backcompat_hack { 239 my $me = shift; 240 return $BACKCOMPAT_HACK{$me} 241 if exists $BACKCOMPAT_HACK{$me}; 242 no warnings 'uninitialized'; 243 $BACKCOMPAT_HACK{$me} = 244 $me->can('apply_single_role_to_package') != \&apply_single_role_to_package 245 && $me->can('role_application_steps') == \&role_application_steps 246} 247 248our $IN_APPLY_ROLES; 249sub apply_single_role_to_package { 250 return 251 if $IN_APPLY_ROLES; 252 local $IN_APPLY_ROLES = 1; 253 254 my ($me, $to, $role) = @_; 255 $me->apply_roles_to_package($to, $role); 256} 257 258sub apply_role_to_package { 259 my ($me, $to, $role) = @_; 260 $me->apply_roles_to_package($to, $role); 261} 262 263sub apply_roles_to_package { 264 my ($me, $to, @roles) = @_; 265 croak "Can't apply roles to object with apply_roles_to_package" 266 if ref $to; 267 268 $me->_check_roles(@roles); 269 270 my @have_conflicts; 271 my %role_methods; 272 273 if (@roles > 1) { 274 my %conflicts = %{$me->_composite_info_for(@roles)->{conflicts}}; 275 @have_conflicts = grep $to->can($_), keys %conflicts; 276 delete @conflicts{@have_conflicts}; 277 278 if (keys %conflicts) { 279 my $class = $COMPOSED{base}{$to} || $to; 280 my $fail = 281 join "\n", 282 map { 283 "Due to a method name conflict between roles " 284 .join(' and ', map "'$_'", sort values %{$conflicts{$_}}) 285 .", the method '$_' must be implemented by '$class'" 286 } sort keys %conflicts; 287 croak $fail; 288 } 289 290 %role_methods = map +($_ => $me->_concrete_methods_of($_)), @roles; 291 } 292 293 if (!$IN_APPLY_ROLES and _want_backcompat_hack($me)) { 294 local $IN_APPLY_ROLES = 1; 295 foreach my $role (@roles) { 296 $me->apply_single_role_to_package($to, $role); 297 } 298 } 299 300 my $role_methods; 301 foreach my $step ($me->role_application_steps) { 302 foreach my $role (@roles) { 303 # conflicting methods are supposed to be treated as required by the 304 # composed role. we don't have an actual composed role, but because 305 # we know the target class already provides them, we can instead 306 # pretend that the roles don't do for the duration of application. 307 $role_methods = $role_methods{$role} and ( 308 (local @{$role_methods}{@have_conflicts}), 309 (delete @{$role_methods}{@have_conflicts}), 310 ); 311 312 $me->$step($to, $role); 313 } 314 } 315 $APPLIED_TO{$to}{join('|',@roles)} = 1; 316} 317 318sub _composite_info_for { 319 my ($me, @roles) = @_; 320 $COMPOSITE_INFO{join('|', sort @roles)} ||= do { 321 my %methods; 322 foreach my $role (@roles) { 323 my $this_methods = $me->_concrete_methods_of($role); 324 $methods{$_}{$this_methods->{$_}} = $role for keys %$this_methods; 325 } 326 delete $methods{$_} for grep keys(%{$methods{$_}}) == 1, keys %methods; 327 +{ conflicts => \%methods } 328 }; 329} 330 331sub _check_requires { 332 my ($me, $to, $name, $requires) = @_; 333 $requires ||= $INFO{$name}{requires} || []; 334 if (my @requires_fail = grep !$to->can($_), @$requires) { 335 # role -> role, add to requires, role -> class, error out 336 if (my $to_info = $INFO{$to}) { 337 push @{$to_info->{requires}||=[]}, @requires_fail; 338 } else { 339 croak "Can't apply ${name} to ${to} - missing ".join(', ', @requires_fail); 340 } 341 } 342} 343 344sub _non_methods { 345 my ($me, $role) = @_; 346 my $info = $INFO{$role} or return {}; 347 348 my %non_methods = %{ $info->{non_methods} || {} }; 349 350 # this is only for backwards compatibility with older Moo, which 351 # reimplements method tracking rather than calling our method 352 my %not_methods = reverse %{ $info->{not_methods} || {} }; 353 return \%non_methods unless keys %not_methods; 354 355 my $subs = $me->_all_subs($role); 356 for my $sub (grep !/\A\(/, keys %$subs) { 357 my $code = $subs->{$sub}; 358 if (exists $not_methods{$code}) { 359 $non_methods{$sub} = $code; 360 } 361 } 362 363 return \%non_methods; 364} 365 366sub _concrete_methods_of { 367 my ($me, $role) = @_; 368 my $info = $INFO{$role}; 369 370 return $info->{methods} 371 if $info && $info->{methods}; 372 373 my $non_methods = $me->_non_methods($role); 374 375 my $subs = $me->_all_subs($role); 376 for my $sub (keys %$subs) { 377 if ( exists $non_methods->{$sub} && $non_methods->{$sub} == $subs->{$sub} ) { 378 delete $subs->{$sub}; 379 } 380 } 381 382 if ($info) { 383 $info->{methods} = $subs; 384 } 385 return $subs; 386} 387 388sub methods_provided_by { 389 my ($me, $role) = @_; 390 $me->_require_module($role); 391 croak "${role} is not a ${me}" unless $me->is_role($role); 392 sort (keys %{$me->_concrete_methods_of($role)}, @{$INFO{$role}->{requires}||[]}); 393} 394 395sub _install_methods { 396 my ($me, $to, $role) = @_; 397 398 my $methods = $me->_concrete_methods_of($role); 399 400 my %existing_methods; 401 @existing_methods{keys %{ $me->_all_subs($to) }} = (); 402 403 # _concrete_methods_of caches its result on roles. that cache needs to be 404 # invalidated after applying roles 405 delete $INFO{$to}{methods} if $INFO{$to}; 406 407 foreach my $i (keys %$methods) { 408 next 409 if exists $existing_methods{$i}; 410 411 my $glob = _getglob "${to}::${i}"; 412 *$glob = $methods->{$i}; 413 414 # overloads using method names have the method stored in the scalar slot 415 # and &overload::nil in the code slot. 416 next 417 unless $i =~ /^\(/ 418 && ((defined &overload::nil && $methods->{$i} == \&overload::nil) 419 || (defined &overload::_nil && $methods->{$i} == \&overload::_nil)); 420 421 my $overload = ${ _getglob "${role}::${i}" }; 422 next 423 unless defined $overload; 424 425 *$glob = \$overload; 426 } 427 428 $me->_install_does($to); 429} 430 431sub _install_modifiers { 432 my ($me, $to, $name) = @_; 433 return unless my $modifiers = $INFO{$name}{modifiers}; 434 my $info = $INFO{$to}; 435 my $existing = ($info ? $info->{modifiers} : $COMPOSED{modifiers}{$to}) ||= []; 436 my @modifiers = grep { 437 my $modifier = $_; 438 !grep $_ == $modifier, @$existing; 439 } @{$modifiers||[]}; 440 push @$existing, @modifiers; 441 442 if (!$info) { 443 foreach my $modifier (@modifiers) { 444 $me->_install_single_modifier($to, @$modifier); 445 } 446 } 447} 448 449my $vcheck_error; 450 451sub _install_single_modifier { 452 my ($me, @args) = @_; 453 defined($vcheck_error) or $vcheck_error = do { 454 local $@; 455 eval { 456 require Class::Method::Modifiers; 457 Class::Method::Modifiers->VERSION(1.05); 458 1; 459 } ? 0 : $@; 460 }; 461 $vcheck_error and die $vcheck_error; 462 Class::Method::Modifiers::install_modifier(@args); 463} 464 465my $FALLBACK = sub { 0 }; 466sub _install_does { 467 my ($me, $to) = @_; 468 469 # only add does() method to classes 470 return if $me->is_role($to); 471 472 my $does = $me->can('does_role'); 473 # add does() only if they don't have one 474 *{_getglob "${to}::does"} = $does unless $to->can('does'); 475 476 return 477 if $to->can('DOES') and $to->can('DOES') != (UNIVERSAL->can('DOES') || 0); 478 479 my $existing = $to->can('DOES') || $to->can('isa') || $FALLBACK; 480 my $new_sub = sub { 481 my ($proto, $role) = @_; 482 $proto->$does($role) or $proto->$existing($role); 483 }; 484 no warnings 'redefine'; 485 return *{_getglob "${to}::DOES"} = $new_sub; 486} 487 488# optimize for newer perls 489require mro 490 if "$]" >= 5.009_005; 491 492if (defined &mro::get_linear_isa) { 493 *_linear_isa = \&mro::get_linear_isa; 494} 495else { 496 my $e; 497 { 498 local $@; 499# this routine is simplified and not fully compatible with mro::get_linear_isa 500# but for our use the order doesn't matter, so we don't need to care 501 eval <<'END_CODE' or $e = $@; 502sub _linear_isa($;$) { 503 if (defined &mro::get_linear_isa) { 504 no warnings 'redefine', 'prototype'; 505 *_linear_isa = \&mro::get_linear_isa; 506 goto &mro::get_linear_isa; 507 } 508 509 my @check = shift; 510 my @lin; 511 512 my %found; 513 while (defined(my $check = shift @check)) { 514 push @lin, $check; 515 no strict 'refs'; 516 unshift @check, grep !$found{$_}++, @{"$check\::ISA"}; 517 } 518 519 return \@lin; 520} 521 5221; 523END_CODE 524 } 525 die $e if defined $e; 526} 527 528sub does_role { 529 my ($proto, $role) = @_; 530 foreach my $class (@{_linear_isa(ref($proto)||$proto)}) { 531 return 1 if exists $APPLIED_TO{$class}{$role}; 532 } 533 return 0; 534} 535 536sub is_role { 537 my ($me, $role) = @_; 538 return !!($INFO{$role} && ( 539 $INFO{$role}{is_role} 540 # these are for backward compatibility with older Moo that overrode some 541 # methods without calling the originals, thus not getting is_role set 542 || $INFO{$role}{requires} 543 || $INFO{$role}{not_methods} 544 || $INFO{$role}{non_methods} 545 )); 546} 547 5481; 549__END__ 550 551=encoding utf-8 552 553=head1 NAME 554 555Role::Tiny - Roles: a nouvelle cuisine portion size slice of Moose 556 557=head1 SYNOPSIS 558 559 package Some::Role; 560 561 use Role::Tiny; 562 563 sub foo { ... } 564 565 sub bar { ... } 566 567 around baz => sub { ... }; 568 569 1; 570 571elsewhere 572 573 package Some::Class; 574 575 use Role::Tiny::With; 576 577 # bar gets imported, but not foo 578 with 'Some::Role'; 579 580 sub foo { ... } 581 582 # baz is wrapped in the around modifier by Class::Method::Modifiers 583 sub baz { ... } 584 585 1; 586 587If you wanted attributes as well, look at L<Moo::Role>. 588 589=head1 DESCRIPTION 590 591C<Role::Tiny> is a minimalist role composition tool. 592 593=head1 ROLE COMPOSITION 594 595Role composition can be thought of as much more clever and meaningful multiple 596inheritance. The basics of this implementation of roles is: 597 598=over 2 599 600=item * 601 602If a method is already defined on a class, that method will not be composed in 603from the role. A method inherited by a class gets overridden by the role's 604method of the same name, though. 605 606=item * 607 608If a method that the role L</requires> to be implemented is not implemented, 609role application will fail loudly. 610 611=back 612 613Unlike L<Class::C3>, where the B<last> class inherited from "wins," role 614composition is the other way around, where the class wins. If multiple roles 615are applied in a single call (single with statement), then if any of their 616provided methods clash, an exception is raised unless the class provides 617a method since this conflict indicates a potential problem. 618 619=head2 ROLE METHODS 620 621All subs created after importing Role::Tiny will be considered methods to be 622composed. For example: 623 624 package MyRole; 625 use List::Util qw(min); 626 sub mysub { } 627 use Role::Tiny; 628 use List::Util qw(max); 629 sub mymethod { } 630 631In this role, C<max> and C<mymethod> will be included when composing MyRole, 632and C<min> and C<mysub> will not. For additional control, L<namespace::clean> 633can be used to exclude undesired subs from roles. 634 635=head1 IMPORTED SUBROUTINES 636 637=head2 requires 638 639 requires qw(foo bar); 640 641Declares a list of methods that must be defined to compose role. 642 643=head2 with 644 645 with 'Some::Role1'; 646 647 with 'Some::Role1', 'Some::Role2'; 648 649Composes another role into the current role (or class via L<Role::Tiny::With>). 650 651If you have conflicts and want to resolve them in favour of Some::Role1 you 652can instead write: 653 654 with 'Some::Role1'; 655 with 'Some::Role2'; 656 657If you have conflicts and want to resolve different conflicts in favour of 658different roles, please refactor your codebase. 659 660=head2 before 661 662 before foo => sub { ... }; 663 664See L<< Class::Method::Modifiers/before method(s) => sub { ... }; >> for full 665documentation. 666 667Note that since you are not required to use method modifiers, 668L<Class::Method::Modifiers> is lazily loaded and we do not declare it as 669a dependency. If your L<Role::Tiny> role uses modifiers you must depend on 670both L<Class::Method::Modifiers> and L<Role::Tiny>. 671 672=head2 around 673 674 around foo => sub { ... }; 675 676See L<< Class::Method::Modifiers/around method(s) => sub { ... }; >> for full 677documentation. 678 679Note that since you are not required to use method modifiers, 680L<Class::Method::Modifiers> is lazily loaded and we do not declare it as 681a dependency. If your L<Role::Tiny> role uses modifiers you must depend on 682both L<Class::Method::Modifiers> and L<Role::Tiny>. 683 684=head2 after 685 686 after foo => sub { ... }; 687 688See L<< Class::Method::Modifiers/after method(s) => sub { ... }; >> for full 689documentation. 690 691Note that since you are not required to use method modifiers, 692L<Class::Method::Modifiers> is lazily loaded and we do not declare it as 693a dependency. If your L<Role::Tiny> role uses modifiers you must depend on 694both L<Class::Method::Modifiers> and L<Role::Tiny>. 695 696=head2 Strict and Warnings 697 698In addition to importing subroutines, using C<Role::Tiny> applies L<strict> and 699L<warnings> to the caller. 700 701=head1 SUBROUTINES 702 703=head2 does_role 704 705 if (Role::Tiny::does_role($foo, 'Some::Role')) { 706 ... 707 } 708 709Returns true if class has been composed with role. 710 711This subroutine is also installed as ->does on any class a Role::Tiny is 712composed into unless that class already has an ->does method, so 713 714 if ($foo->does('Some::Role')) { 715 ... 716 } 717 718will work for classes but to test a role, one must use ::does_role directly. 719 720Additionally, Role::Tiny will override the standard Perl C<DOES> method 721for your class. However, if C<any> class in your class' inheritance 722hierarchy provides C<DOES>, then Role::Tiny will not override it. 723 724=head1 METHODS 725 726=head2 make_role 727 728 Role::Tiny->make_role('Some::Role'); 729 730Makes a package into a role, but does not export any subs into it. 731 732=head2 apply_roles_to_package 733 734 Role::Tiny->apply_roles_to_package( 735 'Some::Package', 'Some::Role', 'Some::Other::Role' 736 ); 737 738Composes role with package. See also L<Role::Tiny::With>. 739 740=head2 apply_roles_to_object 741 742 Role::Tiny->apply_roles_to_object($foo, qw(Some::Role1 Some::Role2)); 743 744Composes roles in order into object directly. Object is reblessed into the 745resulting class. Note that the object's methods get overridden by the role's 746ones with the same names. 747 748=head2 create_class_with_roles 749 750 Role::Tiny->create_class_with_roles('Some::Base', qw(Some::Role1 Some::Role2)); 751 752Creates a new class based on base, with the roles composed into it in order. 753New class is returned. 754 755=head2 is_role 756 757 Role::Tiny->is_role('Some::Role1') 758 759Returns true if the given package is a role. 760 761=head1 CAVEATS 762 763=over 4 764 765=item * On perl 5.8.8 and earlier, applying a role to an object won't apply any 766overloads from the role to other copies of the object. 767 768=item * On perl 5.16 and earlier, applying a role to a class won't apply any 769overloads from the role to any existing instances of the class. 770 771=back 772 773=head1 SEE ALSO 774 775L<Role::Tiny> is the attribute-less subset of L<Moo::Role>; L<Moo::Role> is 776a meta-protocol-less subset of the king of role systems, L<Moose::Role>. 777 778Ovid's L<Role::Basic> provides roles with a similar scope, but without method 779modifiers, and having some extra usage restrictions. 780 781=head1 AUTHOR 782 783mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk> 784 785=head1 CONTRIBUTORS 786 787dg - David Leadbeater (cpan:DGL) <dgl@dgl.cx> 788 789frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com> 790 791hobbs - Andrew Rodland (cpan:ARODLAND) <arodland@cpan.org> 792 793jnap - John Napiorkowski (cpan:JJNAPIORK) <jjn1056@yahoo.com> 794 795ribasushi - Peter Rabbitson (cpan:RIBASUSHI) <ribasushi@cpan.org> 796 797chip - Chip Salzenberg (cpan:CHIPS) <chip@pobox.com> 798 799ajgb - Alex J. G. Burzyński (cpan:AJGB) <ajgb@cpan.org> 800 801doy - Jesse Luehrs (cpan:DOY) <doy at tozt dot net> 802 803perigrin - Chris Prather (cpan:PERIGRIN) <chris@prather.org> 804 805Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com> 806 807ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) <ilmari@ilmari.org> 808 809tobyink - Toby Inkster (cpan:TOBYINK) <tobyink@cpan.org> 810 811haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org> 812 813=head1 COPYRIGHT 814 815Copyright (c) 2010-2012 the Role::Tiny L</AUTHOR> and L</CONTRIBUTORS> 816as listed above. 817 818=head1 LICENSE 819 820This library is free software and may be distributed under the same terms 821as perl itself. 822 823=cut 824