MooseX-ClassAttribute-0.29/0000775000175000017500000000000012722657162015461 5ustar autarchautarchMooseX-ClassAttribute-0.29/dist.ini0000644000175000017500000000226112722657162017124 0ustar autarchautarchname = MooseX-ClassAttribute author = Dave Rolsky license = Artistic_2_0 copyright_holder = Dave Rolsky [@DROLSKY] dist = MooseX-ClassAttribute stopwords = API stopwords = metaclass stopwords = mixin stopwords = PayPal pod_coverage_trustme = MooseX::ClassAttribute => qr/^init_meta$/ pod_coverage_trustme = MooseX::ClassAttribute => qr/^class_has$/ pod_coverage_trustme = MooseX::ClassAttribute::Meta::Role::Attribute => qr/^new$/ pod_coverage_trustme = MooseX::ClassAttribute::Trait::Class => qr/^compute_all_applicable_class_attributes$/ pod_coverage_trustme = MooseX::ClassAttribute::Trait::Role =>qr/^composition_class_roles$/ pod_coverage_trustme = MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes => qr/^add_class_attribute$/ pod_coverage_trustme = MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes => qr/^get_class_attribute_map$/ pod_coverage_trustme = MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes => qr/^remove_class_attribute$/ -remove = Test::Synopsis [Prereqs::Soften] :version = 0.006000 module = MooseX::AttributeHelpers module = MooseX::Role::Parameterized module = MooseX::Role::Strict copy_to = develop.requires to_relationship = none MooseX-ClassAttribute-0.29/perltidyrc0000644000175000017500000000045512722657162017567 0ustar autarchautarch-l=78 -i=4 -ci=4 -se -b -bar -boc -vt=0 -vtc=0 -cti=0 -pt=1 -bt=1 -sbt=1 -bbt=1 -nolq -npro -nsfs --blank-lines-before-packages=0 --opening-hash-brace-right --no-outdent-long-comments --iterations=2 -wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x=" MooseX-ClassAttribute-0.29/cpanfile0000644000175000017500000000360112722657162017163 0ustar autarchautarchrequires "List::Util" => "1.45"; requires "Moose" => "2.00"; requires "Moose::Exporter" => "0"; requires "Moose::Meta::Role::Attribute" => "0"; requires "Moose::Role" => "0"; requires "Moose::Util" => "0"; requires "Moose::Util::MetaRole" => "0"; requires "Scalar::Util" => "0"; requires "namespace::autoclean" => "0.11"; requires "namespace::clean" => "0.20"; requires "strict" => "0"; requires "warnings" => "0"; on 'test' => sub { requires "ExtUtils::MakeMaker" => "0"; requires "File::Spec" => "0"; requires "Test::Fatal" => "0"; requires "Test::More" => "0.96"; requires "Test::Requires" => "0.05"; requires "lib" => "0"; requires "vars" => "0"; }; on 'test' => sub { recommends "CPAN::Meta" => "2.120900"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "0"; }; on 'develop' => sub { requires "Code::TidyAll::Plugin::Test::Vars" => "0.02"; requires "File::Spec" => "0"; requires "IO::Handle" => "0"; requires "IPC::Open3" => "0"; requires "MooseX::AttributeHelpers" => "0"; requires "MooseX::Role::Parameterized" => "0"; requires "MooseX::Role::Strict" => "0"; requires "Perl::Critic" => "1.126"; requires "Perl::Tidy" => "20160302"; requires "Pod::Coverage::TrustPod" => "0"; requires "Pod::Wordlist" => "0"; requires "Test::CPAN::Changes" => "0.19"; requires "Test::CPAN::Meta::JSON" => "0.16"; requires "Test::CleanNamespaces" => "0.15"; requires "Test::Code::TidyAll" => "0.24"; requires "Test::EOL" => "0"; requires "Test::Mojibake" => "0"; requires "Test::More" => "0.96"; requires "Test::NoTabs" => "0"; requires "Test::Pod" => "1.41"; requires "Test::Pod::Coverage" => "1.08"; requires "Test::Pod::LinkCheck" => "0"; requires "Test::Pod::No404s" => "0"; requires "Test::Spelling" => "0.12"; requires "Test::Vars" => "0.009"; requires "Test::Version" => "1"; requires "blib" => "1.01"; requires "perl" => "5.006"; }; MooseX-ClassAttribute-0.29/t/0000775000175000017500000000000012722657162015724 5ustar autarchautarchMooseX-ClassAttribute-0.29/t/05-with-attribute-helpers-backcompat.t0000644000175000017500000000074412722657162025054 0ustar autarchautarchuse strict; use warnings; use Test::More; use Test::Requires 0.05 { 'MooseX::AttributeHelpers' => 0.23, }; { package MyClass; use Moose; use MooseX::ClassAttribute; use MooseX::AttributeHelpers; class_has counter => ( metaclass => 'Counter', is => 'ro', provides => { inc => 'inc_counter', }, ); } is( MyClass->counter(), 0 ); MyClass->inc_counter(); is( MyClass->counter(), 1 ); done_testing(); MooseX-ClassAttribute-0.29/t/06-role.t0000644000175000017500000000513212722657162017274 0ustar autarchautarchuse strict; use warnings; use lib 't/lib'; use SharedTests; use Test::More; use Moose::Util qw( apply_all_roles ); { package RoleHCA; use Moose::Role; use MooseX::ClassAttribute; while ( my ( $name, $def ) = each %SharedTests::Attrs ) { class_has $name => %{$def}; } } { package ClassWithRoleHCA; use Moose; with 'RoleHCA'; has 'size' => ( is => 'rw', isa => 'Int', default => 5, ); sub BUILD { my $self = shift; $self->ObjectCount( $self->ObjectCount() + 1 ); } sub _BuildIt {42} sub _CallTrigger { push @{ $_[0]->TriggerRecord() }, [@_]; } } ok( ClassWithRoleHCA->meta()->does_role('RoleHCA'), 'ClassWithRoleHCA does RoleHCA' ); SharedTests::run_tests('ClassWithRoleHCA'); ClassWithRoleHCA->meta()->make_immutable(); ok( ClassWithRoleHCA->meta()->does_role('RoleHCA'), 'ClassWithRoleHCA (immutable) does RoleHCA' ); # These next tests are aimed at testing to-role application followed by # to-class application { package RoleWithRoleHCA; use Moose::Role; use MooseX::ClassAttribute; with 'RoleHCA'; } ok( RoleWithRoleHCA->meta()->does_role('RoleHCA'), 'RoleWithRoleHCA does RoleHCA' ); { package ClassWithRoleWithRoleHCA; use Moose; with 'RoleWithRoleHCA'; has 'size' => ( is => 'rw', isa => 'Int', default => 5, ); sub BUILD { my $self = shift; $self->ObjectCount( $self->ObjectCount() + 1 ); } sub _BuildIt {42} sub _CallTrigger { push @{ $_[0]->TriggerRecord() }, [@_]; } } ok( ClassWithRoleWithRoleHCA->meta()->does_role('RoleHCA'), 'ClassWithRoleWithRoleHCA does RoleHCA' ); SharedTests::run_tests('ClassWithRoleWithRoleHCA'); ClassWithRoleWithRoleHCA->meta()->make_immutable(); ok( ClassWithRoleWithRoleHCA->meta()->does_role('RoleHCA'), 'ClassWithRoleWithRoleHCA (immutable) does RoleHCA' ); { package InstanceWithRoleHCA; use Moose; has 'size' => ( is => 'rw', isa => 'Int', default => 5, ); sub _BuildIt {42} sub _CallTrigger { push @{ $_[0]->TriggerRecord() }, [@_]; } } my $instance = InstanceWithRoleHCA->new(); apply_all_roles( $instance, 'RoleHCA' ); ok( $instance->meta()->does_role('RoleHCA'), '$instance does RoleHCA' ); $instance->ObjectCount(1); SharedTests::run_tests($instance); $instance->meta()->make_immutable(); ok( $instance->meta()->does_role('RoleHCA'), '$instance (immutable) does RoleHCA' ); done_testing(); MooseX-ClassAttribute-0.29/t/09-bare-native-traits.t0000644000175000017500000000117712722657162022044 0ustar autarchautarch# reported in https://rt.cpan.org/Public/Bug/Display.html?id=59573 use strict; use warnings; use Test::More; use Test::Fatal; { package Foo; use Moose; use MooseX::ClassAttribute; class_has attr => ( is => 'bare', isa => 'HashRef[Str]', lazy => 1, default => sub { {} }, traits => ['Hash'], handles => { has_attr => 'exists', }, ); } is( exception { Foo->has_attr('key') }, undef, 'Default builder in a native attribute trait is properly run when the attribute is defined with no standard accessors' ); done_testing(); MooseX-ClassAttribute-0.29/t/08-role-composition.t0000644000175000017500000000256412722657162021645 0ustar autarchautarchuse strict; use warnings; use Test::More; { package Role; use Moose::Role; use MooseX::ClassAttribute; class_has 'CA' => ( is => 'ro', isa => 'HashRef', default => sub { {} }, ); } { package Role2; use Moose::Role; } { package Bar; use Moose; with 'Role2', 'Role'; } ok( Bar->can('CA'), 'Class attributes are preserved during role composition' ); { package Role3; use Moose::Role; with 'Role'; } { package Baz; use Moose; with 'Role3'; } ok( Baz->can('CA'), 'Class attributes are preserved when role is applied to another role' ); { package Role4; use Moose::Role; use MooseX::ClassAttribute; class_has 'CA2' => ( is => 'ro', isa => 'HashRef', default => sub { {} }, ); } { package Buz; use Moose; with 'Role', 'Role4'; } ok( Buz->can('CA'), 'Class attributes are merged from two roles (CA)' ); ok( Buz->can('CA2'), 'Class attributes are merged from two roles (CA2)' ); { package Role5; use Moose::Role; with 'Role', 'Role4'; } { package Quux; use Moose; with 'Role5'; } ok( Quux->can('CA'), 'Class attributes are merged from two roles (CA)' ); ok( Quux->can('CA2'), 'Class attributes are merged from two roles (CA2)' ); done_testing(); MooseX-ClassAttribute-0.29/t/10-strict-role-composition.t0000644000175000017500000000164212722657162023140 0ustar autarchautarch# Reported as https://rt.cpan.org/Public/Bug/Display.html?id=59663 use strict; use warnings; use Test::More; use Test::Fatal; use Test::Requires { 'MooseX::Role::Strict' => 0.01, }; { package Role; use MooseX::Role::Strict; use MooseX::ClassAttribute; class_has attr => ( traits => ['Hash'], is => 'ro', isa => 'HashRef[Str]', lazy => 1, default => sub { {} }, handles => { has_attr => 'exists', }, ); sub normal_method { Test::More::pass('a regular method from the role is composed'); } } { package Foo; use Moose; with 'Role'; } Foo->normal_method(); { local $TODO = 'This test does not yet pass'; is( exception { Foo->has_attr('key') }, undef, 'Delegated method from native attribute trait is properly composed from a strict role' ); } done_testing(); MooseX-ClassAttribute-0.29/t/00-report-prereqs.t0000644000175000017500000001273112722657162021322 0ustar autarchautarch#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.024 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do 't/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; if ( $source && $HAS_CPAN_META ) { if ( my $meta = eval { CPAN::Meta->load_file($source) } ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } } else { $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( @dep_errors ) { diag join("\n", "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n", "The following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: MooseX-ClassAttribute-0.29/t/07-parameterized-role.t0000644000175000017500000000136212722657162022130 0ustar autarchautarchuse strict; use warnings; use Test::More; use Test::Fatal; use Test::Requires { 'MooseX::Role::Parameterized' => '0', }; plan skip_all => 'This test will not pass without changes to MooseX::Role::Parmeterized'; { package Role; use MooseX::Role::Parameterized; use MooseX::ClassAttribute; parameter foo => ( is => 'rw' ); role { my $p = shift; class_has $p => ( is => 'rw' ); }; } { package Class; use Moose; with 'Role' => { foo => 'foo' }; } my $instance = Class->new(); isa_ok( $instance, 'Class' ); is( exception { $instance->foo('bar'); is( $instance->foo(), 'bar' ); }, undef, 'used class attribute from parameterized role' ); done_testing(); MooseX-ClassAttribute-0.29/t/11-moose-exporter.t0000644000175000017500000000140512722657162021316 0ustar autarchautarchuse strict; use warnings; use Test::More; BEGIN { plan skip_all => 'This test fails with a syntax error' } { package MooseX::Foo; use strict; use warnings; use Moose::Exporter; use MooseX::ClassAttribute (); Moose::Exporter->setup_import_methods( also => ['MooseX::ClassAttribute'], ); } { package MyClass; use Moose; # use MooseX::Foo; # normal use MooseX::Foo->import; # Now theoretically, this should work -- the 'class_has' method # should have been imported via the MooseX package above. class_has attr => ( is => 'ro', isa => 'Str', default => 'foo', ); } my $obj = MyClass->new(); is( $obj->attr(), 'foo', 'class attribute is properly created' ); done_testing(); MooseX-ClassAttribute-0.29/t/01-basic.t0000644000175000017500000000017712722657162017413 0ustar autarchautarchuse strict; use warnings; use lib 't/lib'; use SharedTests; use Test::More 0.88; SharedTests::run_tests(); done_testing(); MooseX-ClassAttribute-0.29/t/02-immutable.t0000644000175000017500000000031112722657162020300 0ustar autarchautarchuse strict; use warnings; use lib 't/lib'; use SharedTests; use Test::More; HasClassAttribute->meta()->make_immutable(); Child->meta()->make_immutable(); SharedTests::run_tests(); done_testing(); MooseX-ClassAttribute-0.29/t/lib/0000775000175000017500000000000012722657162016472 5ustar autarchautarchMooseX-ClassAttribute-0.29/t/lib/SharedTests.pm0000644000175000017500000001627712722657162021274 0ustar autarchautarchpackage SharedTests; use strict; use warnings; use Scalar::Util qw( isweak ); use Test::More; use vars qw($Lazy); our %Attrs = ( ObjectCount => { is => 'rw', isa => 'Int', default => 0, }, WeakAttribute => { is => 'rw', isa => 'Object', weak_ref => 1, }, LazyAttribute => { is => 'rw', isa => 'Int', lazy => 1, # The side effect is used to test that this was called # lazily. default => sub { $Lazy = 1 }, }, ReadOnlyAttribute => { is => 'ro', isa => 'Int', default => 10, }, ManyNames => { is => 'rw', isa => 'Int', reader => 'M', writer => 'SetM', clearer => 'ClearM', predicate => 'HasM', }, Delegatee => { is => 'rw', isa => 'Delegatee', handles => [ 'units', 'color' ], # if it's not lazy it makes a new object before we define # Delegatee's attributes. lazy => 1, default => sub { Delegatee->new() }, }, Mapping => { traits => ['Hash'], is => 'rw', isa => 'HashRef[Str]', default => sub { {} }, handles => { 'ExistsInMapping' => 'exists', 'IdsInMapping' => 'keys', 'GetMapping' => 'get', 'SetMapping' => 'set', }, }, Built => { is => 'ro', builder => '_BuildIt', }, LazyBuilt => { is => 'ro', lazy => 1, builder => '_BuildIt', }, Triggerish => { is => 'rw', trigger => sub { shift->_CallTrigger(@_) }, }, TriggerRecord => { is => 'ro', default => sub { [] }, }, ); { package HasClassAttribute; use Moose qw( has ); use MooseX::ClassAttribute; while ( my ( $name, $def ) = each %SharedTests::Attrs ) { class_has $name => %{$def}; } has 'size' => ( is => 'rw', isa => 'Int', default => 5, ); no Moose; sub BUILD { my $self = shift; $self->ObjectCount( $self->ObjectCount() + 1 ); } sub _BuildIt {42} sub _CallTrigger { push @{ $_[0]->TriggerRecord() }, [@_]; } sub make_immutable { my $class = shift; $class->meta()->make_immutable(); Delegatee->meta()->make_immutable(); } } { package Delegatee; use Moose; has 'units' => ( is => 'ro', default => 5, ); has 'color' => ( is => 'ro', default => 'blue', ); no Moose; } { package Child; use Moose; use MooseX::ClassAttribute; extends 'HasClassAttribute'; class_has '+ReadOnlyAttribute' => ( default => 30 ); class_has 'YetAnotherAttribute' => ( is => 'ro', default => 'thing', ); no Moose; } sub run_tests { my $thing = shift || 'HasClassAttribute'; local $Test::Builder::Level = $Test::Builder::Level + 1; $Lazy = 0; my $count = ref $thing ? 1 : 0; { is( $thing->ObjectCount(), $count, 'ObjectCount() is 0' ); unless ( ref $thing ) { my $hca1 = $thing->new(); is( $hca1->size(), 5, 'size is 5 - object attribute works as expected' ); is( $thing->ObjectCount(), 1, 'ObjectCount() is 1' ); my $hca2 = $thing->new( size => 10 ); is( $hca2->size(), 10, 'size is 10 - object attribute can be set via constructor' ); is( $thing->ObjectCount(), 2, 'ObjectCount() is 2' ); is( $hca2->ObjectCount(), 2, 'ObjectCount() is 2 - can call class attribute accessor on object' ); } } unless ( ref $thing ) { my $hca3 = $thing->new( ObjectCount => 20 ); is( $hca3->ObjectCount(), 3, 'class attributes passed to the constructor do not get set in the object' ); is( $thing->ObjectCount(), 3, 'class attributes are not affected by constructor params' ); } { my $object = bless {}, 'Thing'; $thing->WeakAttribute($object); undef $object; ok( !defined $thing->WeakAttribute(), 'weak class attributes are weak' ); } { is( $SharedTests::Lazy, 0, '$SharedTests::Lazy is 0' ); is( $thing->LazyAttribute(), 1, '$thing->LazyAttribute() is 1' ); is( $SharedTests::Lazy, 1, '$SharedTests::Lazy is 1 after calling LazyAttribute' ); } { eval { $thing->ReadOnlyAttribute(20) }; like( $@, qr/\QCannot assign a value to a read-only accessor/, 'cannot set read-only class attribute' ); } { is( Child->ReadOnlyAttribute(), 30, q{Child class can extend parent's class attribute} ); } { ok( !$thing->HasM(), 'HasM() returns false before M is set' ); $thing->SetM(22); ok( $thing->HasM(), 'HasM() returns true after M is set' ); is( $thing->M(), 22, 'M() returns 22' ); $thing->ClearM(); ok( !$thing->HasM(), 'HasM() returns false after M is cleared' ); } { isa_ok( $thing->Delegatee(), 'Delegatee', 'has a Delegetee object' ); is( $thing->units(), 5, 'units() delegates to Delegatee and returns 5' ); } { my @ids = $thing->IdsInMapping(); is( scalar @ids, 0, 'there are no keys in the mapping yet' ); ok( !$thing->ExistsInMapping('a'), 'key does not exist in mapping' ); $thing->SetMapping( a => 20 ); ok( $thing->ExistsInMapping('a'), 'key does exist in mapping' ); is( $thing->GetMapping('a'), 20, 'value for a in mapping is 20' ); } { is( $thing->Built(), 42, 'attribute with builder works' ); is( $thing->LazyBuilt(), 42, 'attribute with lazy builder works' ); } { $thing->Triggerish(42); is( scalar @{ $thing->TriggerRecord() }, 1, 'trigger was called' ); is( $thing->Triggerish(), 42, 'Triggerish is now 42' ); $thing->Triggerish(84); is( $thing->Triggerish(), 84, 'Triggerish is now 84' ); is_deeply( $thing->TriggerRecord(), [ [ $thing, qw( 42 ) ], [ $thing, qw( 84 42 ) ], ], 'trigger passes old value correctly' ); } } 1; MooseX-ClassAttribute-0.29/t/00-report-prereqs.dd0000644000175000017500000000721612722657162021450 0ustar autarchautarchdo { my $x = { 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '0' } }, 'develop' => { 'requires' => { 'Code::TidyAll::Plugin::Test::Vars' => '0.02', 'File::Spec' => '0', 'IO::Handle' => '0', 'IPC::Open3' => '0', 'MooseX::AttributeHelpers' => '0', 'MooseX::Role::Parameterized' => '0', 'MooseX::Role::Strict' => '0', 'Perl::Critic' => '1.126', 'Perl::Tidy' => '20160302', 'Pod::Coverage::TrustPod' => '0', 'Pod::Wordlist' => '0', 'Test::CPAN::Changes' => '0.19', 'Test::CPAN::Meta::JSON' => '0.16', 'Test::CleanNamespaces' => '0.15', 'Test::Code::TidyAll' => '0.24', 'Test::EOL' => '0', 'Test::Mojibake' => '0', 'Test::More' => '0.96', 'Test::NoTabs' => '0', 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.08', 'Test::Pod::LinkCheck' => '0', 'Test::Pod::No404s' => '0', 'Test::Spelling' => '0.12', 'Test::Vars' => '0.009', 'Test::Version' => '1', 'blib' => '1.01', 'perl' => '5.006' } }, 'runtime' => { 'requires' => { 'List::Util' => '1.45', 'Moose' => '2.00', 'Moose::Exporter' => '0', 'Moose::Meta::Role::Attribute' => '0', 'Moose::Role' => '0', 'Moose::Util' => '0', 'Moose::Util::MetaRole' => '0', 'Scalar::Util' => '0', 'namespace::autoclean' => '0.11', 'namespace::clean' => '0.20', 'strict' => '0', 'warnings' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'Test::Fatal' => '0', 'Test::More' => '0.96', 'Test::Requires' => '0.05', 'lib' => '0', 'vars' => '0' } } }; $x; }MooseX-ClassAttribute-0.29/t/04-with-native-traits.t0000644000175000017500000000061612722657162022076 0ustar autarchautarchuse strict; use warnings; use Test::More; { package MyClass; use Moose; use MooseX::ClassAttribute; class_has counter => ( traits => ['Counter'], is => 'ro', default => 0, handles => { inc_counter => 'inc', }, ); } is( MyClass->counter(), 0 ); MyClass->inc_counter(); is( MyClass->counter(), 1 ); done_testing(); MooseX-ClassAttribute-0.29/t/12-with-initializer.t0000644000175000017500000000272312722657162021627 0ustar autarchautarchuse strict; use warnings; use Test::More; { package ClassFoo; use Moose; use MooseX::ClassAttribute; class_has 'chas' => ( isa => 'Int', is => 'ro', default => 1, initializer => sub { $_[2]->( $_[1] + 1 ) } ); } { package ClassBar; use Moose; has 'chas' => ( isa => 'Int', is => 'ro', default => 1, initializer => sub { $_[2]->( $_[1] + 1 ) } ); } { package ClassBaz; use Moose; use MooseX::ClassAttribute; class_has 'chas' => ( isa => 'Str', is => 'rw', default => 'Foobar', trigger => sub { die __PACKAGE__ } ); } { package ClassQuz; use Moose; has 'chas' => ( isa => 'Str', is => 'rw', default => 'Foobar', trigger => sub { die __PACKAGE__ } ); } { local $TODO = 'Class attributes with an initializer are not initialized properly'; is( ClassFoo->chas, 2, "ClassFoo's class_has (ClassAttribute) initializer fires" ); } is( ClassBar->new->chas, 2, "ClassBar's has (non-ClassAttribute) initializer fires" ); eval { ClassBaz->new->chas('foobar') }; like( $@, qr/ClassBaz/, "ClassBaz's class_has (ClassAttribute) trigger fires" ); eval { ClassQuz->new->chas('foobar') }; like( $@, qr/ClassQuz/, "ClassQuz's has (non-ClassAttribute) trigger fires" ); done_testing(); MooseX-ClassAttribute-0.29/t/03-introspection.t0000644000175000017500000000520112722657162021225 0ustar autarchautarchuse strict; use warnings; use lib 't/lib'; use Test::More; # We just want the class definitions in here. use SharedTests; ok( HasClassAttribute->meta()->has_class_attribute('ObjectCount'), q{has_class_attribute('ObjectCount') returns true} ); ok( HasClassAttribute->meta()->get_class_attribute('ObjectCount')->meta() ->does_role('MooseX::ClassAttribute::Trait::Attribute'), 'get_class_attribute_list returns an object which does the MooseX::ClassAttribute::Trait::Attribute role' ); my @ca = qw( Delegatee LazyAttribute ManyNames Mapping ObjectCount ReadOnlyAttribute WeakAttribute Built LazyBuilt Triggerish TriggerRecord ); is_deeply( [ sort HasClassAttribute->meta()->get_class_attribute_list() ], [ sort @ca ], 'HasClassAttribute get_class_attribute_list gets all class attributes' ); is_deeply( [ sort map { $_->name() } HasClassAttribute->meta()->get_all_attributes() ], ['size'], 'HasClassAttribute get_all_attributes only finds size attribute' ); is_deeply( [ sort map { $_->name() } HasClassAttribute->meta()->get_all_class_attributes() ], [ sort @ca ], 'HasClassAttribute get_all_class_attributes gets all class attributes' ); is_deeply( [ sort keys %{ HasClassAttribute->meta()->get_class_attribute_map() } ], [ sort @ca ], 'HasClassAttribute get_class_attribute_map gets all class attributes' ); is_deeply( [ sort map { $_->name() } Child->meta()->get_all_class_attributes() ], [ sort ( @ca, 'YetAnotherAttribute' ) ], 'Child get_class_attribute_map gets all class attributes' ); ok( !Child->meta()->has_class_attribute('ObjectCount'), q{has_class_attribute('ObjectCount') returns false for Child} ); ok( Child->meta()->has_class_attribute('YetAnotherAttribute'), q{has_class_attribute('YetAnotherAttribute') returns true for Child} ); ok( Child->can('YetAnotherAttribute'), 'Child has accessor for YetAnotherAttribute' ); ok( Child->meta()->has_class_attribute_value('YetAnotherAttribute'), 'Child has class attribute value for YetAnotherAttribute' ); Child->meta()->remove_class_attribute('YetAnotherAttribute'); ok( !Child->meta()->has_class_attribute('YetAnotherAttribute'), q{... has_class_attribute('YetAnotherAttribute') returns false after remove_class_attribute} ); ok( !Child->can('YetAnotherAttribute'), 'accessor for YetAnotherAttribute has been removed' ); ok( !Child->meta()->has_class_attribute_value('YetAnotherAttribute'), 'Child does not have a class attribute value for YetAnotherAttribute' ); done_testing(); MooseX-ClassAttribute-0.29/Makefile.PL0000644000175000017500000000357012722657162017436 0ustar autarchautarch# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.005. use strict; use warnings; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Declare class attributes Moose-style", "AUTHOR" => "Dave Rolsky ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "MooseX-ClassAttribute", "LICENSE" => "artistic_2", "NAME" => "MooseX::ClassAttribute", "PREREQ_PM" => { "List::Util" => "1.45", "Moose" => "2.00", "Moose::Exporter" => 0, "Moose::Meta::Role::Attribute" => 0, "Moose::Role" => 0, "Moose::Util" => 0, "Moose::Util::MetaRole" => 0, "Scalar::Util" => 0, "namespace::autoclean" => "0.11", "namespace::clean" => "0.20", "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "Test::Fatal" => 0, "Test::More" => "0.96", "Test::Requires" => "0.05", "lib" => 0, "vars" => 0 }, "VERSION" => "0.29", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "List::Util" => "1.45", "Moose" => "2.00", "Moose::Exporter" => 0, "Moose::Meta::Role::Attribute" => 0, "Moose::Role" => 0, "Moose::Util" => 0, "Moose::Util::MetaRole" => 0, "Scalar::Util" => 0, "Test::Fatal" => 0, "Test::More" => "0.96", "Test::Requires" => "0.05", "lib" => 0, "namespace::autoclean" => "0.11", "namespace::clean" => "0.20", "strict" => 0, "vars" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); MooseX-ClassAttribute-0.29/META.yml0000644000175000017500000005307312722657162016740 0ustar autarchautarch--- abstract: 'Declare class attributes Moose-style' author: - 'Dave Rolsky ' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' Test::Fatal: '0' Test::More: '0.96' Test::Requires: '0.05' lib: '0' vars: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.005, CPAN::Meta::Converter version 2.150005' license: artistic_2 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: MooseX-ClassAttribute provides: MooseX::ClassAttribute: file: lib/MooseX/ClassAttribute.pm version: '0.29' MooseX::ClassAttribute::Meta::Role::Attribute: file: lib/MooseX/ClassAttribute/Meta/Role/Attribute.pm version: '0.29' MooseX::ClassAttribute::Trait::Application: file: lib/MooseX/ClassAttribute/Trait/Application.pm version: '0.29' MooseX::ClassAttribute::Trait::Application::ToClass: file: lib/MooseX/ClassAttribute/Trait/Application/ToClass.pm version: '0.29' MooseX::ClassAttribute::Trait::Application::ToRole: file: lib/MooseX/ClassAttribute/Trait/Application/ToRole.pm version: '0.29' MooseX::ClassAttribute::Trait::Attribute: file: lib/MooseX/ClassAttribute/Trait/Attribute.pm version: '0.29' MooseX::ClassAttribute::Trait::Class: file: lib/MooseX/ClassAttribute/Trait/Class.pm version: '0.29' MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes: file: lib/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm version: '0.29' MooseX::ClassAttribute::Trait::Role: file: lib/MooseX/ClassAttribute/Trait/Role.pm version: '0.29' MooseX::ClassAttribute::Trait::Role::Composite: file: lib/MooseX/ClassAttribute/Trait/Role/Composite.pm version: '0.29' requires: List::Util: '1.45' Moose: '2.00' Moose::Exporter: '0' Moose::Meta::Role::Attribute: '0' Moose::Role: '0' Moose::Util: '0' Moose::Util::MetaRole: '0' Scalar::Util: '0' namespace::autoclean: '0.11' namespace::clean: '0.20' strict: '0' warnings: '0' resources: bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-ClassAttribute homepage: http://metacpan.org/release/MooseX-ClassAttribute repository: git://github.com/moose/MooseX-ClassAttribute.git version: '0.29' x_Dist_Zilla: perl: version: '5.024000' plugins: - class: Dist::Zilla::Plugin::MakeMaker config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@DROLSKY/MakeMaker' version: '6.005' - class: Dist::Zilla::Plugin::Git::GatherDir config: Dist::Zilla::Plugin::GatherDir: exclude_filename: - Build.PL - CONTRIBUTING.md - LICENSE - Makefile.PL - README.md - cpanfile - ppport.h exclude_match: [] follow_symlinks: 0 include_dotfiles: 0 prefix: '' prune_directory: [] root: . Dist::Zilla::Plugin::Git::GatherDir: include_untracked: 0 name: '@DROLSKY/Git::GatherDir' version: '2.039' - class: Dist::Zilla::Plugin::ManifestSkip name: '@DROLSKY/ManifestSkip' version: '6.005' - class: Dist::Zilla::Plugin::License name: '@DROLSKY/License' version: '6.005' - class: Dist::Zilla::Plugin::ExecDir name: '@DROLSKY/ExecDir' version: '6.005' - class: Dist::Zilla::Plugin::ShareDir name: '@DROLSKY/ShareDir' version: '6.005' - class: Dist::Zilla::Plugin::Manifest name: '@DROLSKY/Manifest' version: '6.005' - class: Dist::Zilla::Plugin::CheckVersionIncrement name: '@DROLSKY/CheckVersionIncrement' version: '0.121750' - class: Dist::Zilla::Plugin::TestRelease name: '@DROLSKY/TestRelease' version: '6.005' - class: Dist::Zilla::Plugin::ConfirmRelease name: '@DROLSKY/ConfirmRelease' version: '6.005' - class: Dist::Zilla::Plugin::UploadToCPAN name: '@DROLSKY/UploadToCPAN' version: '6.005' - class: Dist::Zilla::Plugin::DROLSKY::VersionProvider name: '@DROLSKY/DROLSKY::VersionProvider' version: '0.58' - class: Dist::Zilla::Plugin::Authority name: '@DROLSKY/Authority' version: '1.009' - class: Dist::Zilla::Plugin::AutoPrereqs name: '@DROLSKY/AutoPrereqs' version: '6.005' - class: Dist::Zilla::Plugin::CopyFilesFromBuild name: '@DROLSKY/CopyFilesFromBuild' version: '0.161350' - class: Dist::Zilla::Plugin::GitHub::Meta name: '@DROLSKY/GitHub::Meta' version: '0.42' - class: Dist::Zilla::Plugin::GitHub::Update config: Dist::Zilla::Plugin::GitHub::Update: metacpan: 1 name: '@DROLSKY/GitHub::Update' version: '0.42' - class: Dist::Zilla::Plugin::MetaResources name: '@DROLSKY/MetaResources' version: '6.005' - class: Dist::Zilla::Plugin::MetaProvides::Package config: Dist::Zilla::Plugin::MetaProvides::Package: finder_objects: - class: Dist::Zilla::Plugin::FinderCode name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM' version: '6.005' Dist::Zilla::Role::MetaProvider::Provider: Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.001011' inherit_missing: '1' inherit_version: '1' meta_noindex: '1' name: '@DROLSKY/MetaProvides::Package' version: '2.003002' - class: Dist::Zilla::Plugin::MetaYAML name: '@DROLSKY/MetaYAML' version: '6.005' - class: Dist::Zilla::Plugin::Meta::Contributors name: '@DROLSKY/Meta::Contributors' version: '0.003' - class: Dist::Zilla::Plugin::MetaConfig name: '@DROLSKY/MetaConfig' version: '6.005' - class: Dist::Zilla::Plugin::MetaJSON name: '@DROLSKY/MetaJSON' version: '6.005' - class: Dist::Zilla::Plugin::NextRelease name: '@DROLSKY/NextRelease' version: '6.005' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: test type: requires name: '@DROLSKY/Test::More with subtest' version: '6.005' - class: Dist::Zilla::Plugin::Prereqs config: Dist::Zilla::Plugin::Prereqs: phase: develop type: requires name: '@DROLSKY/Modules for use with tidyall' version: '6.005' - class: Dist::Zilla::Plugin::PromptIfStale config: Dist::Zilla::Plugin::PromptIfStale: check_all_plugins: 1 check_all_prereqs: 1 modules: [] phase: build skip: - Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent - Dist::Zilla::Plugin::DROLSKY::Contributors - Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch - Dist::Zilla::Plugin::DROLSKY::License - Dist::Zilla::Plugin::DROLSKY::TidyAll - Dist::Zilla::Plugin::DROLSKY::VersionProvider - Pod::Weaver::PluginBundle::DROLSKY name: '@DROLSKY/PromptIfStale' version: '0.049' - class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable name: '@DROLSKY/Test::Pod::Coverage::Configurable' version: '0.06' - class: Dist::Zilla::Plugin::Test::PodSpelling config: Dist::Zilla::Plugin::Test::PodSpelling: directories: [] spell_cmd: '' stopwords: - API - DROLSKY - "DROLSKY's" - PayPal - PayPal - Rolsky - "Rolsky's" - drolsky - metaclass - mixin wordlist: Pod::Wordlist name: '@DROLSKY/Test::PodSpelling' version: '2.007002' - class: Dist::Zilla::Plugin::PodSyntaxTests name: '@DROLSKY/PodSyntaxTests' version: '6.005' - class: Dist::Zilla::Plugin::Test::Pod::LinkCheck name: '@DROLSKY/Test::Pod::LinkCheck' version: '1.002' - class: Dist::Zilla::Plugin::Test::Pod::No404s name: '@DROLSKY/Test::Pod::No404s' version: '1.003' - class: Dist::Zilla::Plugin::RunExtraTests config: Dist::Zilla::Role::TestRunner: default_jobs: 1 name: '@DROLSKY/RunExtraTests' version: '0.029' - class: Dist::Zilla::Plugin::MojibakeTests name: '@DROLSKY/MojibakeTests' version: '0.8' - class: Dist::Zilla::Plugin::Test::CleanNamespaces config: Dist::Zilla::Plugin::Test::CleanNamespaces: filename: xt/author/clean-namespaces.t skips: [] name: '@DROLSKY/Test::CleanNamespaces' version: '0.006' - class: Dist::Zilla::Plugin::Test::CPAN::Changes name: '@DROLSKY/Test::CPAN::Changes' version: '0.009' - class: Dist::Zilla::Plugin::Test::CPAN::Meta::JSON name: '@DROLSKY/Test::CPAN::Meta::JSON' version: '0.004' - class: Dist::Zilla::Plugin::Test::EOL config: Dist::Zilla::Plugin::Test::EOL: filename: xt/author/eol.t finder: - ':InstallModules' - ':ExecFiles' - ':TestFiles' trailing_whitespace: '1' name: '@DROLSKY/Test::EOL' version: '0.18' - class: Dist::Zilla::Plugin::Test::NoTabs config: Dist::Zilla::Plugin::Test::NoTabs: filename: xt/author/no-tabs.t finder: - ':InstallModules' - ':ExecFiles' - ':TestFiles' name: '@DROLSKY/Test::NoTabs' version: '0.15' - class: Dist::Zilla::Plugin::Test::Portability name: '@DROLSKY/Test::Portability' version: '2.000006' - class: Dist::Zilla::Plugin::Test::TidyAll name: '@DROLSKY/Test::TidyAll' version: '0.03' - class: Dist::Zilla::Plugin::Test::Compile config: Dist::Zilla::Plugin::Test::Compile: bail_out_on_fail: '0' fail_on_warning: author fake_home: 0 filename: xt/author/00-compile.t module_finder: - ':InstallModules' needs_display: 0 phase: develop script_finder: - ':PerlExecFiles' skips: [] name: '@DROLSKY/Test::Compile' version: '2.054' - class: Dist::Zilla::Plugin::Test::ReportPrereqs name: '@DROLSKY/Test::ReportPrereqs' version: '0.024' - class: Dist::Zilla::Plugin::Test::Version name: '@DROLSKY/Test::Version' version: '1.09' - class: Dist::Zilla::Plugin::DROLSKY::Contributors name: '@DROLSKY/DROLSKY::Contributors' version: '0.58' - class: Dist::Zilla::Plugin::Git::Contributors config: Dist::Zilla::Plugin::Git::Contributors: include_authors: 0 include_releaser: 1 order_by: name paths: - . name: '@DROLSKY/Git::Contributors' version: '0.023' - class: Dist::Zilla::Plugin::SurgicalPodWeaver config: Dist::Zilla::Plugin::PodWeaver: config_plugins: - '@DROLSKY' finder: - ':InstallModules' - ':ExecFiles' plugins: - class: Pod::Weaver::Plugin::EnsurePod5 name: '@CorePrep/EnsurePod5' version: '4.013' - class: Pod::Weaver::Plugin::H1Nester name: '@CorePrep/H1Nester' version: '4.013' - class: Pod::Weaver::Plugin::SingleEncoding name: '@DROLSKY/SingleEncoding' version: '4.013' - class: Pod::Weaver::Plugin::Transformer name: '@DROLSKY/List' version: '4.013' - class: Pod::Weaver::Plugin::Transformer name: '@DROLSKY/Verbatim' version: '4.013' - class: Pod::Weaver::Section::Region name: '@DROLSKY/header' version: '4.013' - class: Pod::Weaver::Section::Name name: '@DROLSKY/Name' version: '4.013' - class: Pod::Weaver::Section::Version name: '@DROLSKY/Version' version: '4.013' - class: Pod::Weaver::Section::Region name: '@DROLSKY/prelude' version: '4.013' - class: Pod::Weaver::Section::Generic name: SYNOPSIS version: '4.013' - class: Pod::Weaver::Section::Generic name: DESCRIPTION version: '4.013' - class: Pod::Weaver::Section::Generic name: OVERVIEW version: '4.013' - class: Pod::Weaver::Section::Collect name: ATTRIBUTES version: '4.013' - class: Pod::Weaver::Section::Collect name: METHODS version: '4.013' - class: Pod::Weaver::Section::Collect name: FUNCTIONS version: '4.013' - class: Pod::Weaver::Section::Collect name: TYPES version: '4.013' - class: Pod::Weaver::Section::Leftovers name: '@DROLSKY/Leftovers' version: '4.013' - class: Pod::Weaver::Section::Region name: '@DROLSKY/postlude' version: '4.013' - class: Pod::Weaver::Section::GenerateSection name: '@DROLSKY/generate SUPPORT' version: '1.01' - class: Pod::Weaver::Section::AllowOverride name: '@DROLSKY/allow override SUPPORT' version: '0.05' - class: Pod::Weaver::Section::GenerateSection name: '@DROLSKY/generate DONATIONS' version: '1.01' - class: Pod::Weaver::Section::Authors name: '@DROLSKY/Authors' version: '4.013' - class: Pod::Weaver::Section::Contributors name: '@DROLSKY/Contributors' version: '0.009' - class: Pod::Weaver::Section::Legal name: '@DROLSKY/Legal' version: '4.013' - class: Pod::Weaver::Section::Region name: '@DROLSKY/footer' version: '4.013' name: '@DROLSKY/SurgicalPodWeaver' version: '0.0023' - class: Dist::Zilla::Plugin::ReadmeAnyFromPod config: Dist::Zilla::Role::FileWatcher: version: '0.006' name: '@DROLSKY/README.md in build' version: '0.161170' - class: Dist::Zilla::Plugin::GenerateFile::FromShareDir config: Dist::Zilla::Plugin::GenerateFile::FromShareDir: destination_filename: CONTRIBUTING.md dist: Dist-Zilla-PluginBundle-DROLSKY encoding: UTF-8 has_xs: '0' location: build source_filename: CONTRIBUTING.md Dist::Zilla::Role::RepoFileInjector: allow_overwrite: 1 repo_root: . version: '0.006' name: '@DROLSKY/generate CONTRIBUTING' version: '0.009' - class: Dist::Zilla::Plugin::InstallGuide name: '@DROLSKY/InstallGuide' version: '1.200006' - class: Dist::Zilla::Plugin::CPANFile name: '@DROLSKY/CPANFile' version: '6.005' - class: Dist::Zilla::Plugin::DROLSKY::License name: '@DROLSKY/DROLSKY::License' version: '0.58' - class: Dist::Zilla::Plugin::CheckPrereqsIndexed name: '@DROLSKY/CheckPrereqsIndexed' version: '0.018' - class: Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent name: '@DROLSKY/DROLSKY::CheckChangesHasContent' version: '0.58' - class: Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch config: Dist::Zilla::Role::Git::Repo: repo_root: . name: '@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch' version: '0.58' - class: Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts config: Dist::Zilla::Role::Git::Repo: repo_root: . name: '@DROLSKY/Git::CheckFor::MergeConflicts' version: '0.013' - class: Dist::Zilla::Plugin::DROLSKY::TidyAll name: '@DROLSKY/DROLSKY::TidyAll' version: '0.58' - class: Dist::Zilla::Plugin::Git::Check config: Dist::Zilla::Plugin::Git::Check: untracked_files: die Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Build.PL - CONTRIBUTING.md - Changes - LICENSE - Makefile.PL - README.md - cpanfile - ppport.h - tidyall.ini allow_dirty_match: [] changelog: Changes Dist::Zilla::Role::Git::Repo: repo_root: . name: '@DROLSKY/Git::Check' version: '2.039' - class: Dist::Zilla::Plugin::Git::Commit config: Dist::Zilla::Plugin::Git::Commit: add_files_in: [] commit_msg: v%v%n%n%c Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Build.PL - CONTRIBUTING.md - Changes - LICENSE - Makefile.PL - README.md - cpanfile - ppport.h - tidyall.ini allow_dirty_match: [] changelog: Changes Dist::Zilla::Role::Git::Repo: repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@DROLSKY/commit generated files' version: '2.039' - class: Dist::Zilla::Plugin::Git::Tag config: Dist::Zilla::Plugin::Git::Tag: branch: ~ changelog: Changes signed: 0 tag: v0.29 tag_format: v%v tag_message: v%v Dist::Zilla::Role::Git::Repo: repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@DROLSKY/Git::Tag' version: '2.039' - class: Dist::Zilla::Plugin::Git::Push config: Dist::Zilla::Plugin::Git::Push: push_to: - origin remotes_must_exist: 1 Dist::Zilla::Role::Git::Repo: repo_root: . name: '@DROLSKY/Git::Push' version: '2.039' - class: Dist::Zilla::Plugin::BumpVersionAfterRelease config: Dist::Zilla::Plugin::BumpVersionAfterRelease: finders: - ':ExecFiles' - ':InstallModules' global: 0 munge_makefile_pl: 1 name: '@DROLSKY/BumpVersionAfterRelease' version: '0.015' - class: Dist::Zilla::Plugin::Git::Commit config: Dist::Zilla::Plugin::Git::Commit: add_files_in: [] commit_msg: 'Bump version after release' Dist::Zilla::Role::Git::DirtyFiles: allow_dirty: - Changes - dist.ini allow_dirty_match: - (?^:.+) changelog: Changes Dist::Zilla::Role::Git::Repo: repo_root: . Dist::Zilla::Role::Git::StringFormatter: time_zone: local name: '@DROLSKY/commit version bump' version: '2.039' - class: Dist::Zilla::Plugin::Git::Push config: Dist::Zilla::Plugin::Git::Push: push_to: - origin remotes_must_exist: 1 Dist::Zilla::Role::Git::Repo: repo_root: . name: '@DROLSKY/push version bump' version: '2.039' - class: Dist::Zilla::Plugin::Prereqs::Soften config: Dist::Zilla::Plugin::Prereqs::Soften: copy_to: - develop.requires modules: - MooseX::AttributeHelpers - MooseX::Role::Parameterized - MooseX::Role::Strict modules_from_features: ~ to_relationship: none name: Prereqs::Soften version: '0.006002' - class: Dist::Zilla::Plugin::FinderCode name: ':InstallModules' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':IncModules' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':TestFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':ExtraTestFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':ExecFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':PerlExecFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':ShareFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':MainModule' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':AllFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: ':NoFiles' version: '6.005' - class: Dist::Zilla::Plugin::FinderCode name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM' version: '6.005' zilla: class: Dist::Zilla::Dist::Builder config: is_trial: '0' version: '6.005' x_authority: cpan:DROLSKY x_contributors: - 'Andrew Rodland ' - 'Karen Etheridge ' - 'Rafael Kitover ' - 'Robert Buels ' - 'Shawn M Moore ' MooseX-ClassAttribute-0.29/LICENSE0000644000175000017500000002152012722657162016464 0ustar autarchautarchThis software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MooseX-ClassAttribute-0.29/xt/0000775000175000017500000000000012722657162016114 5ustar autarchautarchMooseX-ClassAttribute-0.29/xt/author/0000775000175000017500000000000012722657162017416 5ustar autarchautarchMooseX-ClassAttribute-0.29/xt/author/no-tabs.t0000644000175000017500000000225112722657162021144 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15 use Test::More 0.88; use Test::NoTabs; my @files = ( 'lib/MooseX/ClassAttribute.pm', 'lib/MooseX/ClassAttribute/Meta/Role/Attribute.pm', 'lib/MooseX/ClassAttribute/Trait/Application.pm', 'lib/MooseX/ClassAttribute/Trait/Application/ToClass.pm', 'lib/MooseX/ClassAttribute/Trait/Application/ToRole.pm', 'lib/MooseX/ClassAttribute/Trait/Attribute.pm', 'lib/MooseX/ClassAttribute/Trait/Class.pm', 'lib/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm', 'lib/MooseX/ClassAttribute/Trait/Role.pm', 'lib/MooseX/ClassAttribute/Trait/Role/Composite.pm', 't/00-report-prereqs.dd', 't/00-report-prereqs.t', 't/01-basic.t', 't/02-immutable.t', 't/03-introspection.t', 't/04-with-native-traits.t', 't/05-with-attribute-helpers-backcompat.t', 't/06-role.t', 't/07-parameterized-role.t', 't/08-role-composition.t', 't/09-bare-native-traits.t', 't/10-strict-role-composition.t', 't/11-moose-exporter.t', 't/12-with-initializer.t', 't/lib/SharedTests.pm' ); notabs_ok($_) foreach @files; done_testing; MooseX-ClassAttribute-0.29/xt/author/mojibake.t0000644000175000017500000000015112722657162021357 0ustar autarchautarch#!perl use strict; use warnings qw(all); use Test::More; use Test::Mojibake; all_files_encoding_ok(); MooseX-ClassAttribute-0.29/xt/author/pod-syntax.t0000644000175000017500000000025212722657162021706 0ustar autarchautarch#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); MooseX-ClassAttribute-0.29/xt/author/test-version.t0000644000175000017500000000063712722657162022251 0ustar autarchautarchuse strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::Version 1.09 use Test::Version; my @imports = qw( version_all_ok ); my $params = { is_strict => 1, has_version => 1, multiple => 0, }; push @imports, $params if version->parse( $Test::Version::VERSION ) >= version->parse('1.002'); Test::Version->import(@imports); version_all_ok; done_testing; MooseX-ClassAttribute-0.29/xt/author/eol.t0000644000175000017500000000230312722657162020356 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::EOL 0.18 use Test::More 0.88; use Test::EOL; my @files = ( 'lib/MooseX/ClassAttribute.pm', 'lib/MooseX/ClassAttribute/Meta/Role/Attribute.pm', 'lib/MooseX/ClassAttribute/Trait/Application.pm', 'lib/MooseX/ClassAttribute/Trait/Application/ToClass.pm', 'lib/MooseX/ClassAttribute/Trait/Application/ToRole.pm', 'lib/MooseX/ClassAttribute/Trait/Attribute.pm', 'lib/MooseX/ClassAttribute/Trait/Class.pm', 'lib/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm', 'lib/MooseX/ClassAttribute/Trait/Role.pm', 'lib/MooseX/ClassAttribute/Trait/Role/Composite.pm', 't/00-report-prereqs.dd', 't/00-report-prereqs.t', 't/01-basic.t', 't/02-immutable.t', 't/03-introspection.t', 't/04-with-native-traits.t', 't/05-with-attribute-helpers-backcompat.t', 't/06-role.t', 't/07-parameterized-role.t', 't/08-role-composition.t', 't/09-bare-native-traits.t', 't/10-strict-role-composition.t', 't/11-moose-exporter.t', 't/12-with-initializer.t', 't/lib/SharedTests.pm' ); eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; done_testing; MooseX-ClassAttribute-0.29/xt/author/pod-spell.t0000644000175000017500000000103112722657162021473 0ustar autarchautarchuse strict; use warnings; use Test::More; # generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007002 use Test::Spelling 0.12; use Pod::Wordlist; add_stopwords(); all_pod_files_spelling_ok( qw( bin lib ) ); __DATA__ drolsky DROLSKY DROLSKY's PayPal Rolsky Rolsky's API metaclass mixin Dave autarch Andrew Rodland andrew Karen Etheridge ether Rafael Kitover rkitover Robert Buels rmb32 Shawn Moore sartak lib MooseX ClassAttribute Meta Role Attribute Trait Application ToClass ToRole Class Mixin HasClassAttributes Composite MooseX-ClassAttribute-0.29/xt/author/pod-coverage.t0000644000175000017500000000432512722657162022160 0ustar autarchautarch#!perl # This file was automatically generated by Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable. use Test::Pod::Coverage 1.08; use Test::More 0.88; BEGIN { if ( $] <= 5.008008 ) { plan skip_all => 'These tests require Pod::Coverage::TrustPod, which only works with Perl 5.8.9+'; } } use Pod::Coverage::TrustPod; my %skip = map { $_ => 1 } qw( ); my @modules; for my $module ( all_modules() ) { next if $skip{$module}; push @modules, $module; } plan skip_all => 'All the modules we found were excluded from POD coverage test.' unless @modules; plan tests => scalar @modules; my %trustme = ( 'MooseX::ClassAttribute' => [ qr/^init_meta$/, qr/^class_has$/ ], 'MooseX::ClassAttribute::Trait::Role' => [ qr/^composition_class_roles$/ ], 'MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes' => [ qr/^add_class_attribute$/, qr/^get_class_attribute_map$/, qr/^remove_class_attribute$/ ], 'MooseX::ClassAttribute::Trait::Class' => [ qr/^compute_all_applicable_class_attributes$/ ], 'MooseX::ClassAttribute::Meta::Role::Attribute' => [ qr/^new$/ ] ); my @also_private; for my $module ( sort @modules ) { pod_coverage_ok( $module, { coverage_class => 'Pod::Coverage::TrustPod', also_private => \@also_private, trustme => $trustme{$module} || [], }, "pod coverage for $module" ); } done_testing(); MooseX-ClassAttribute-0.29/xt/author/pod-no404s.t0000644000175000017500000000052712722657162021414 0ustar autarchautarch#!perl use strict; use warnings; use Test::More; foreach my $env_skip ( qw( SKIP_POD_NO404S AUTOMATED_TESTING ) ){ plan skip_all => "\$ENV{$env_skip} is set, skipping" if $ENV{$env_skip}; } eval "use Test::Pod::No404s"; if ( $@ ) { plan skip_all => 'Test::Pod::No404s required for testing POD'; } else { all_pod_files_ok(); } MooseX-ClassAttribute-0.29/xt/author/00-compile.t0000644000175000017500000000317612722657162021455 0ustar autarchautarchuse 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.054 use Test::More; plan tests => 11; my @module_files = ( 'MooseX/ClassAttribute.pm', 'MooseX/ClassAttribute/Meta/Role/Attribute.pm', 'MooseX/ClassAttribute/Trait/Application.pm', 'MooseX/ClassAttribute/Trait/Application/ToClass.pm', 'MooseX/ClassAttribute/Trait/Application/ToRole.pm', 'MooseX/ClassAttribute/Trait/Attribute.pm', 'MooseX/ClassAttribute/Trait/Class.pm', 'MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm', 'MooseX/ClassAttribute/Trait/Role.pm', 'MooseX/ClassAttribute/Trait/Role/Composite.pm' ); # no fake home requested my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L my $stderr = IO::Handle->new; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { require blib; blib->VERSION('1.01') }; if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ); MooseX-ClassAttribute-0.29/xt/author/clean-namespaces.t0000644000175000017500000000036112722657162023000 0ustar autarchautarchuse strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::CleanNamespaces 0.006 use Test::More 0.94; use Test::CleanNamespaces 0.15; subtest all_namespaces_clean => sub { all_namespaces_clean() }; done_testing; MooseX-ClassAttribute-0.29/xt/release/0000775000175000017500000000000012722657162017534 5ustar autarchautarchMooseX-ClassAttribute-0.29/xt/release/meta-json.t0000644000175000017500000000006412722657162021614 0ustar autarchautarch#!perl use Test::CPAN::Meta::JSON; meta_json_ok(); MooseX-ClassAttribute-0.29/xt/release/tidyall.t0000644000175000017500000000055712722657162021370 0ustar autarchautarch# This file was automatically generated by Dist::Zilla::Plugin::Test::TidyAll v$VERSION use Test::More 0.88; BEGIN { if ( $] < 5.010 ) { plan skip_all => 'This test requires Perl version 5.010'; } } use Test::Code::TidyAll 0.24; tidyall_ok( verbose => ( exists $ENV{TEST_TIDYALL_VERBOSE} ? $ENV{TEST_TIDYALL_VERBOSE} : 1 ), ); done_testing(); MooseX-ClassAttribute-0.29/xt/release/portability.t0000644000175000017500000000027712722657162022267 0ustar autarchautarch#!perl use strict; use warnings; use Test::More; eval 'use Test::Portability::Files'; plan skip_all => 'Test::Portability::Files required for testing portability' if $@; run_tests(); MooseX-ClassAttribute-0.29/xt/release/cpan-changes.t0000644000175000017500000000026312722657162022247 0ustar autarchautarch#!perl use strict; use warnings; use Test::More 0.96 tests => 2; use_ok('Test::CPAN::Changes'); subtest 'changes_ok' => sub { changes_file_ok('Changes'); }; done_testing(); MooseX-ClassAttribute-0.29/xt/release/pod-linkcheck.t0000644000175000017500000000053712722657162022437 0ustar autarchautarch#!perl use strict; use warnings; use Test::More; foreach my $env_skip ( qw( SKIP_POD_LINKCHECK ) ){ plan skip_all => "\$ENV{$env_skip} is set, skipping" if $ENV{$env_skip}; } eval "use Test::Pod::LinkCheck"; if ( $@ ) { plan skip_all => 'Test::Pod::LinkCheck required for testing POD'; } else { Test::Pod::LinkCheck->new->all_pod_ok; } MooseX-ClassAttribute-0.29/lib/0000775000175000017500000000000012722657162016227 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/0000775000175000017500000000000012722657162017441 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute.pm0000644000175000017500000001252512722657162022733 0ustar autarchautarchpackage MooseX::ClassAttribute; use strict; use warnings; our $VERSION = '0.29'; # This module doesn't really need these pragmas - this is just for the benefit # of prereq scanning. use namespace::clean 0.20 (); use namespace::autoclean 0.11 (); use Moose 2.00 (); use Moose::Exporter; use Moose::Util; use MooseX::ClassAttribute::Trait::Class; use MooseX::ClassAttribute::Trait::Role; use MooseX::ClassAttribute::Trait::Application::ToClass; use MooseX::ClassAttribute::Trait::Application::ToRole; Moose::Exporter->setup_import_methods( with_meta => ['class_has'], class_metaroles => { class => ['MooseX::ClassAttribute::Trait::Class'], }, role_metaroles => { role => ['MooseX::ClassAttribute::Trait::Role'], application_to_class => ['MooseX::ClassAttribute::Trait::Application::ToClass'], application_to_role => ['MooseX::ClassAttribute::Trait::Application::ToRole'], }, ); sub class_has { my $meta = shift; my $name = shift; my $attrs = ref $name eq 'ARRAY' ? $name : [$name]; my %options = ( definition_context => _caller_info(), @_ ); $meta->add_class_attribute( $_, %options ) for @{$attrs}; } # Copied from Moose::Util in 2.06 sub _caller_info { my $level = @_ ? ( $_[0] + 1 ) : 2; my %info; @info{qw(package file line)} = caller($level); return \%info; } 1; # ABSTRACT: Declare class attributes Moose-style __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute - Declare class attributes Moose-style =head1 VERSION version 0.29 =head1 SYNOPSIS package My::Class; use Moose; use MooseX::ClassAttribute; class_has 'Cache' => ( is => 'rw', isa => 'HashRef', default => sub { {} }, ); __PACKAGE__->meta()->make_immutable(); no Moose; no MooseX::ClassAttribute; # then later ... My::Class->Cache()->{thing} = ...; =head1 DESCRIPTION This module allows you to declare class attributes in exactly the same way as object attributes, using C instead of C. You can use any feature of Moose's attribute declarations, including overriding a parent's attributes, delegation (C), attribute traits, etc. All features should just work. The one exception is the "required" flag, which is not allowed for class attributes. The accessor methods for class attribute may be called on the class directly, or on objects of that class. Passing a class attribute to the constructor will not set that attribute. =head1 FUNCTIONS This class exports one function when you use it, C. This works exactly like Moose's C, but it declares class attributes. One little nit is that if you include C in your class, you won't remove the C function. To do that you must include C as well. Or you can just use L instead. =head2 Implementation and Immutability This module will add a role to your class's metaclass, See L for details. This role provides introspection methods for class attributes. Class attributes themselves do the L role. =head2 Cooperation with Metaclasses and Traits This module should work with most attribute metaclasses and traits, but it's possible that conflicts could occur. This module has been tested to work with Moose's native traits. =head2 Class Attributes in Roles You can add a class attribute to a role. When that role is applied to a class, the class will have the relevant class attributes added. Note that attribute defaults will be calculated when the class attribute is composed into the class. =head1 SUPPORT Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 DONATIONS If you'd like to thank me for the work I've done on this module, please consider making a "donation" to me via PayPal. I spend a lot of free time creating free software, and would appreciate any support you'd care to offer. Please note that B in order for me to continue working on this particular software. I will continue to do so, inasmuch as I have in the past, for as long as it interests me. Similarly, a donation made in this way will probably not make me work on this software much more, unless I get so many donations that I can consider working on free software full time (let's all have a chuckle at that together). To donate, log into PayPal and send money to autarch@urth.org, or use the button at L. =head1 AUTHOR Dave Rolsky =head1 CONTRIBUTORS =for stopwords Andrew Rodland Karen Etheridge Rafael Kitover Robert Buels Shawn M Moore =over 4 =item * Andrew Rodland =item * Karen Etheridge =item * Rafael Kitover =item * Robert Buels =item * Shawn M Moore =back =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/0000775000175000017500000000000012722657162022372 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Meta/0000775000175000017500000000000012722657162023260 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Meta/Role/0000775000175000017500000000000012722657162024161 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Meta/Role/Attribute.pm0000644000175000017500000000254712722657162026470 0ustar autarchautarchpackage MooseX::ClassAttribute::Meta::Role::Attribute; use strict; use warnings; our $VERSION = '0.29'; use namespace::autoclean; use Moose; use List::Util 1.45 'uniq'; extends 'Moose::Meta::Role::Attribute'; sub new { my ( $class, $name, %options ) = @_; $options{traits} = [ uniq( @{ $options{traits} || [] } ), 'MooseX::ClassAttribute::Trait::Attribute' ]; return $class->SUPER::new( $name, %options ); } 1; # ABSTRACT: An attribute metaclass for class attributes in roles __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Meta::Role::Attribute - An attribute metaclass for class attributes in roles =head1 VERSION version 0.29 =head1 DESCRIPTION This class overrides L to support class attribute declaration in roles. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/0000775000175000017500000000000012722657162023455 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Attribute.pm0000644000175000017500000001345612722657162025765 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Attribute; use strict; use warnings; our $VERSION = '0.29'; use namespace::autoclean; use Moose::Role; # This is the worst role evar! Really, this should be a subclass, # because it overrides a lot of behavior. However, as a subclass it # won't cooperate with _other_ subclasses. around _process_options => sub { my $orig = shift; my $class = shift; my $name = shift; my $options = shift; confess 'A class attribute cannot be required' if $options->{required}; return $class->$orig( $name, $options ); }; after attach_to_class => sub { my $self = shift; my $meta = shift; $self->_initialize($meta) unless $self->is_lazy(); }; before detach_from_class => sub { my $self = shift; my $meta = shift; $self->clear_value($meta); }; sub _initialize { my $self = shift; my $metaclass = shift; if ( $self->has_default() ) { $self->set_value( undef, $self->default( $self->associated_class() ) ); } elsif ( $self->has_builder() ) { $self->set_value( undef, $self->_call_builder( $metaclass->name() ) ); } } around default => sub { my $orig = shift; my $self = shift; my $default = $self->$orig(); if ( $self->is_default_a_coderef() && @_ ) { return $default->(@_); } return $default; }; around _call_builder => sub { shift; my $self = shift; my $class = shift; my $builder = $self->builder(); return $class->$builder() if $class->can( $self->builder ); confess( "$class does not support builder method '" . $self->builder . "' for attribute '" . $self->name . "'" ); }; around set_value => sub { shift; my $self = shift; shift; # ignoring instance or class name my $value = shift; $self->associated_class() ->set_class_attribute_value( $self->name() => $value ); }; around get_value => sub { shift; my $self = shift; return $self->associated_class() ->get_class_attribute_value( $self->name() ); }; around has_value => sub { shift; my $self = shift; return $self->associated_class() ->has_class_attribute_value( $self->name() ); }; around clear_value => sub { shift; my $self = shift; return $self->associated_class() ->clear_class_attribute_value( $self->name() ); }; if ( $Moose::VERSION < 1.99 ) { around inline_get => sub { shift; my $self = shift; return $self->associated_class() ->_inline_get_class_slot_value( $self->slots() ); }; around inline_set => sub { shift; my $self = shift; shift; my $value = shift; my $meta = $self->associated_class(); my $code = $meta->_inline_set_class_slot_value( $self->slots(), $value ) . ";"; $code .= $meta->_inline_weaken_class_slot_value( $self->slots(), $value ) . " if ref $value;" if $self->is_weak_ref(); return $code; }; around inline_has => sub { shift; my $self = shift; return $self->associated_class() ->_inline_is_class_slot_initialized( $self->slots() ); }; around inline_clear => sub { shift; my $self = shift; return $self->associated_class() ->_inline_deinitialize_class_slot( $self->slots() ); }; } else { around _inline_instance_get => sub { shift; my $self = shift; return $self->associated_class() ->_inline_get_class_slot_value( $self->slots() ); }; around _inline_instance_set => sub { shift; my $self = shift; shift; my $value = shift; return $self->associated_class() ->_inline_set_class_slot_value( $self->slots(), $value ); }; around _inline_instance_has => sub { shift; my $self = shift; return $self->associated_class() ->_inline_is_class_slot_initialized( $self->slots() ); }; around _inline_instance_clear => sub { shift; my $self = shift; return $self->associated_class() ->_inline_deinitialize_class_slot( $self->slots() ); }; around _inline_weaken_value => sub { shift; my $self = shift; shift; my $value = shift; return unless $self->is_weak_ref(); return ( $self->associated_class->_inline_weaken_class_slot_value( $self->slots(), $value ), 'if ref ' . $value . ';', ); }; } 1; # ABSTRACT: A trait for class attributes __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Attribute - A trait for class attributes =head1 VERSION version 0.29 =head1 DESCRIPTION This role modifies the behavior of class attributes in various ways. It really should be a subclass of C, but if it were then it couldn't be combined with other attribute metaclasses, like C. There are no new public methods implemented by this role. All it does is change the behavior of a number of existing methods. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Class.pm0000644000175000017500000001705112722657162025062 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Class; use strict; use warnings; our $VERSION = '0.29'; use MooseX::ClassAttribute::Trait::Attribute; use Scalar::Util qw( blessed ); use namespace::autoclean; use Moose::Role; with 'MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes'; has _class_attribute_values => ( traits => ['Hash'], is => 'ro', isa => 'HashRef', handles => { 'get_class_attribute_value' => 'get', 'set_class_attribute_value' => 'set', 'has_class_attribute_value' => 'exists', 'clear_class_attribute_value' => 'delete', }, lazy => 1, default => sub { $_[0]->_class_attribute_values_hashref() }, init_arg => undef, ); around add_class_attribute => sub { my $orig = shift; my $self = shift; my $attr = ( blessed $_[0] && $_[0]->isa('Class::MOP::Attribute') ? $_[0] : $self->_process_class_attribute(@_) ); $self->$orig($attr); return $attr; }; sub _post_add_class_attribute { my $self = shift; my $attr = shift; my $name = $attr->name(); my $e = do { local $@; eval { $attr->install_accessors() }; $@; }; if ($e) { $self->remove_attribute($name); die $e; } } sub _attach_class_attribute { my ( $self, $attribute ) = @_; $attribute->attach_to_class($self); } # It'd be nice if I didn't have to replicate this for class # attributes, since it's basically just a copy of # Moose::Meta::Class->_process_attribute sub _process_class_attribute { my $self = shift; my $name = shift; my @args = @_; @args = %{ $args[0] } if scalar @args == 1 && ref( $args[0] ) eq 'HASH'; if ( $name =~ /^\+(.*)/ ) { return $self->_process_inherited_class_attribute( $1, @args ); } else { return $self->_process_new_class_attribute( $name, @args ); } } sub _process_new_class_attribute { my $self = shift; my $name = shift; my %p = @_; if ( $p{traits} ) { push @{ $p{traits} }, 'MooseX::ClassAttribute::Trait::Attribute'; } else { $p{traits} = ['MooseX::ClassAttribute::Trait::Attribute']; } return Moose::Meta::Attribute->interpolate_class_and_new( $name, %p ); } sub _process_inherited_class_attribute { my $self = shift; my $name = shift; my %p = @_; my $inherited_attr = $self->find_class_attribute_by_name($name); ( defined $inherited_attr ) || confess "Could not find an attribute by the name of '$name' to inherit from"; return $inherited_attr->clone_and_inherit_options(%p); } around remove_class_attribute => sub { my $orig = shift; my $self = shift; my $removed_attr = $self->$orig(@_) or return; $removed_attr->remove_accessors(); $removed_attr->detach_from_class(); return $removed_attr; }; sub get_all_class_attributes { my $self = shift; my %attrs = map { my $meta = Class::MOP::class_of($_); $meta && $meta->can('_class_attribute_map') ? %{ $meta->_class_attribute_map() } : () } reverse $self->linearized_isa; return values %attrs; } sub compute_all_applicable_class_attributes { warn 'The compute_all_applicable_class_attributes method has been deprecated.' . " Use get_all_class_attributes instead.\n"; shift->compute_all_applicable_class_attributes(@_); } sub find_class_attribute_by_name { my $self = shift; my $name = shift; foreach my $class ( $self->linearized_isa() ) { my $meta = Class::MOP::class_of($class) or next; return $meta->get_class_attribute($name) if $meta->can('has_class_attribute') && $meta->has_class_attribute($name); } return; } sub _class_attribute_values_hashref { my $self = shift; no strict 'refs'; return \%{ $self->_class_attribute_var_name() }; } sub _class_attribute_var_name { my $self = shift; return $self->name() . q'::__ClassAttributeValues'; } sub _inline_class_slot_access { my $self = shift; my $name = shift; return '$' . $self->_class_attribute_var_name . '{"' . quotemeta($name) . '"}'; } sub _inline_get_class_slot_value { my $self = shift; my $name = shift; return $self->_inline_class_slot_access($name); } sub _inline_set_class_slot_value { my $self = shift; my $name = shift; my $val_name = shift; return $self->_inline_class_slot_access($name) . ' = ' . $val_name; } sub _inline_is_class_slot_initialized { my $self = shift; my $name = shift; return 'exists ' . $self->_inline_class_slot_access($name); } sub _inline_deinitialize_class_slot { my $self = shift; my $name = shift; return 'delete ' . $self->_inline_class_slot_access($name); } sub _inline_weaken_class_slot_value { my $self = shift; my $name = shift; return 'Scalar::Util::weaken( ' . $self->_inline_class_slot_access($name) . ')'; } 1; # ABSTRACT: A trait for classes with class attributes __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Class - A trait for classes with class attributes =head1 VERSION version 0.29 =head1 SYNOPSIS for my $attr ( HasClassAttributes->meta()->get_all_class_attributes() ) { print $attr->name(); } =head1 DESCRIPTION This role adds awareness of class attributes to a metaclass object. It provides a set of introspection methods that largely parallel the existing attribute methods, except they operate on class attributes. =head1 METHODS Every method provided by this role has an analogous method in C or C for regular attributes. =head2 $meta->has_class_attribute($name) =head2 $meta->get_class_attribute($name) =head2 $meta->get_class_attribute_list() These methods operate on the current metaclass only. =head2 $meta->add_class_attribute(...) This accepts the same options as the L C method. However, if an attribute is specified as "required" an error will be thrown. =head2 $meta->remove_class_attribute($name) If the named class attribute exists, it is removed from the class, along with its accessor methods. =head2 $meta->get_all_class_attributes() This method returns a list of attribute objects for the class and all its parent classes. =head2 $meta->find_class_attribute_by_name($name) This method looks at the class and all its parent classes for the named class attribute. =head2 $meta->get_class_attribute_value($name) =head2 $meta->set_class_attribute_value($name, $value) =head2 $meta->set_class_attribute_value($name) =head2 $meta->clear_class_attribute_value($name) These methods operate on the storage for class attribute values, which is attached to the metaclass object. There's really no good reason for you to call these methods unless you're doing some deep hacking. They are named as public methods solely because they are used by other meta roles and classes in this distribution. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Application/0000775000175000017500000000000012722657162025720 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Application/ToRole.pm0000644000175000017500000000504212722657162027461 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Application::ToRole; use strict; use warnings; our $VERSION = '0.29'; use Moose::Util::MetaRole; use MooseX::ClassAttribute::Trait::Application::ToClass; use namespace::autoclean; use Moose::Role; with 'MooseX::ClassAttribute::Trait::Application'; around apply => sub { my $orig = shift; my $self = shift; my $role1 = shift; my $role2 = shift; $role2 = Moose::Util::MetaRole::apply_metaroles( for => $role2, role_metaroles => { role => ['MooseX::ClassAttribute::Trait::Role'], application_to_class => ['MooseX::ClassAttribute::Trait::Application::ToClass'], application_to_role => ['MooseX::ClassAttribute::Trait::Application::ToRole'], }, ); $self->$orig( $role1, $role2 ); }; sub _apply_class_attributes { my $self = shift; my $role1 = shift; my $role2 = shift; foreach my $attribute_name ( $role1->get_class_attribute_list() ) { if ( $role2->has_class_attribute($attribute_name) && $role2->get_class_attribute($attribute_name) != $role1->get_class_attribute($attribute_name) ) { require Moose; Moose->throw_error( "Role '" . $role1->name() . "' has encountered a class attribute conflict " . "during composition. This is fatal error and cannot be disambiguated." ); } else { $role2->add_class_attribute( $role1->get_class_attribute($attribute_name)->clone() ); } } } 1; # ABSTRACT: A trait that supports applying class attributes to roles __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Application::ToRole - A trait that supports applying class attributes to roles =head1 VERSION version 0.29 =head1 DESCRIPTION This trait is used to allow the application of roles containing class attributes to roles. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Application/ToClass.pm0000644000175000017500000000413612722657162027630 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Application::ToClass; use strict; use warnings; our $VERSION = '0.29'; use namespace::autoclean; use Moose::Role; with 'MooseX::ClassAttribute::Trait::Application'; around apply => sub { my $orig = shift; my $self = shift; my $role = shift; my $class = shift; $class = Moose::Util::MetaRole::apply_metaroles( for => $class, class_metaroles => { class => ['MooseX::ClassAttribute::Trait::Class'], }, ); $self->$orig( $role, $class ); }; sub _apply_class_attributes { my $self = shift; my $role = shift; my $class = shift; my $attr_metaclass = $class->attribute_metaclass(); foreach my $attribute_name ( $role->get_class_attribute_list() ) { if ( $class->has_class_attribute($attribute_name) && $class->get_class_attribute($attribute_name) != $role->get_class_attribute($attribute_name) ) { next; } else { $class->add_class_attribute( $role->get_class_attribute($attribute_name) ->attribute_for_class($attr_metaclass) ); } } } 1; # ABSTRACT: A trait that supports applying class attributes to classes __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Application::ToClass - A trait that supports applying class attributes to classes =head1 VERSION version 0.29 =head1 DESCRIPTION This trait is used to allow the application of roles containing class attributes to classes. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Mixin/0000775000175000017500000000000012722657162024541 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm0000644000175000017500000000612312722657162030647 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes; use strict; use warnings; our $VERSION = '0.29'; use namespace::autoclean; use Moose::Role; has _class_attribute_map => ( traits => ['Hash'], is => 'ro', isa => 'HashRef[Class::MOP::Mixin::AttributeCore]', handles => { '_add_class_attribute' => 'set', 'has_class_attribute' => 'exists', 'get_class_attribute' => 'get', '_remove_class_attribute' => 'delete', 'get_class_attribute_list' => 'keys', }, default => sub { {} }, init_arg => undef, ); # deprecated sub get_class_attribute_map { return $_[0]->_class_attribute_map(); } sub add_class_attribute { my $self = shift; my $attribute = shift; ( $attribute->isa('Class::MOP::Mixin::AttributeCore') ) || confess "Your attribute must be an instance of Class::MOP::Mixin::AttributeCore (or a subclass)"; $self->_attach_class_attribute($attribute); my $attr_name = $attribute->name; $self->remove_class_attribute($attr_name) if $self->has_class_attribute($attr_name); my $order = ( scalar keys %{ $self->_attribute_map } ); $attribute->_set_insertion_order($order); $self->_add_class_attribute( $attr_name => $attribute ); # This method is called to allow for installing accessors. Ideally, we'd # use method overriding, but then the subclass would be responsible for # making the attribute, which would end up with lots of code # duplication. Even more ideally, we'd use augment/inner, but this is # Class::MOP! $self->_post_add_class_attribute($attribute) if $self->can('_post_add_class_attribute'); return $attribute; } sub remove_class_attribute { my $self = shift; my $name = shift; ( defined $name && $name ) || confess 'You must provide an attribute name'; my $removed_attr = $self->get_class_attribute($name); return unless $removed_attr; $self->_remove_class_attribute($name); return $removed_attr; } 1; # ABSTRACT: A mixin trait for things which have class attributes __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes - A mixin trait for things which have class attributes =head1 VERSION version 0.29 =head1 DESCRIPTION This trait is like L, except that it works with class attributes instead of object attributes. See L and L for API details. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Application.pm0000644000175000017500000000222412722657162026254 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Application; use strict; use warnings; our $VERSION = '0.29'; use namespace::autoclean; use Moose::Role; after apply_attributes => sub { shift->_apply_class_attributes(@_); }; 1; # ABSTRACT: A trait that supports role application for roles with class attributes __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Application - A trait that supports role application for roles with class attributes =head1 VERSION version 0.29 =head1 DESCRIPTION This trait is used to allow the application of roles containing class attributes. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Role.pm0000644000175000017500000000510012722657162024706 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Role; use strict; use warnings; our $VERSION = '0.29'; use MooseX::ClassAttribute::Meta::Role::Attribute; use Scalar::Util qw( blessed ); use namespace::autoclean; use Moose::Role; with 'MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes'; around add_class_attribute => sub { my $orig = shift; my $self = shift; my $attr = ( blessed $_[0] && $_[0]->isa('Class::MOP::Mixin::AttributeCore') ? $_[0] : MooseX::ClassAttribute::Meta::Role::Attribute->new(@_) ); $self->$orig($attr); return $attr; }; sub _attach_class_attribute { my ( $self, $attribute ) = @_; $attribute->attach_to_role($self); } sub composition_class_roles { return 'MooseX::ClassAttribute::Trait::Role::Composite'; } 1; # ABSTRACT: A trait for roles with class attributes __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Role - A trait for roles with class attributes =head1 VERSION version 0.29 =head1 SYNOPSIS for my $attr ( HasClassAttributes->meta()->get_all_class_attributes() ) { print $attr->name(); } =head1 DESCRIPTION This role adds awareness of class attributes to a role metaclass object. It provides a set of introspection methods that largely parallel the existing attribute methods, except they operate on class attributes. =head1 METHODS Every method provided by this role has an analogous method in C or C for regular attributes. =head2 $meta->has_class_attribute($name) =head2 $meta->get_class_attribute($name) =head2 $meta->get_class_attribute_list() These methods are exactly like their counterparts in L. =head2 $meta->add_class_attribute(...) This accepts the same options as the L C method. However, if an attribute is specified as "required" an error will be thrown. =head2 $meta->remove_class_attribute($name) If the named class attribute exists, it is removed from the role. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Role/0000775000175000017500000000000012722657162024356 5ustar autarchautarchMooseX-ClassAttribute-0.29/lib/MooseX/ClassAttribute/Trait/Role/Composite.pm0000644000175000017500000000531312722657162026656 0ustar autarchautarchpackage MooseX::ClassAttribute::Trait::Role::Composite; use strict; use warnings; our $VERSION = '0.29'; use Moose::Util::MetaRole; use Moose::Util qw(does_role); use namespace::autoclean; use Moose::Role; with 'MooseX::ClassAttribute::Trait::Role'; sub _merge_class_attributes { my $self = shift; my @all_attributes; foreach my $role ( @{ $self->get_roles() } ) { if ( does_role( $role, 'MooseX::ClassAttribute::Trait::Role' ) ) { push @all_attributes, map { $role->get_class_attribute($_) } $role->get_class_attribute_list(); } } my %seen; foreach my $attribute (@all_attributes) { my $name = $attribute->name(); if ( exists $seen{$name} ) { next if $seen{$name} == $attribute; require Moose; Moose->throw_error( "Role '" . $self->name() . "' has encountered a class attribute conflict " . "during composition. This is a fatal error and " . "cannot be disambiguated." ); } $seen{$name} = $attribute; } foreach my $attribute (@all_attributes) { $self->add_class_attribute( $attribute->clone() ); } return keys %seen; } around apply_params => sub { my $orig = shift; my $self = shift; $self->$orig(@_); $self = Moose::Util::MetaRole::apply_metaroles( for => $self, role_metaroles => { application_to_class => ['MooseX::ClassAttribute::Trait::Application::ToClass'], application_to_role => ['MooseX::ClassAttribute::Trait::Application::ToRole'], }, ); $self->_merge_class_attributes(); return $self; }; 1; # ABSTRACT: A trait that supports applying multiple roles at once __END__ =pod =encoding UTF-8 =head1 NAME MooseX::ClassAttribute::Trait::Role::Composite - A trait that supports applying multiple roles at once =head1 VERSION version 0.29 =head1 DESCRIPTION This trait is used to allow the application of multiple roles (one or more of which contain class attributes) to a class or role. =head1 BUGS See L for details. Bugs may be submitted through L (or L). I am also usually active on IRC as 'drolsky' on C. =head1 AUTHOR Dave Rolsky =head1 COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) =cut MooseX-ClassAttribute-0.29/META.json0000644000175000017500000010345112722657162017104 0ustar autarchautarch{ "abstract" : "Declare class attributes Moose-style", "author" : [ "Dave Rolsky " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.005, CPAN::Meta::Converter version 2.150005", "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "MooseX-ClassAttribute", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Code::TidyAll::Plugin::Test::Vars" : "0.02", "File::Spec" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "MooseX::AttributeHelpers" : "0", "MooseX::Role::Parameterized" : "0", "MooseX::Role::Strict" : "0", "Perl::Critic" : "1.126", "Perl::Tidy" : "20160302", "Pod::Coverage::TrustPod" : "0", "Pod::Wordlist" : "0", "Test::CPAN::Changes" : "0.19", "Test::CPAN::Meta::JSON" : "0.16", "Test::CleanNamespaces" : "0.15", "Test::Code::TidyAll" : "0.24", "Test::EOL" : "0", "Test::Mojibake" : "0", "Test::More" : "0.96", "Test::NoTabs" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08", "Test::Pod::LinkCheck" : "0", "Test::Pod::No404s" : "0", "Test::Spelling" : "0.12", "Test::Vars" : "0.009", "Test::Version" : "1", "blib" : "1.01", "perl" : "5.006" } }, "runtime" : { "requires" : { "List::Util" : "1.45", "Moose" : "2.00", "Moose::Exporter" : "0", "Moose::Meta::Role::Attribute" : "0", "Moose::Role" : "0", "Moose::Util" : "0", "Moose::Util::MetaRole" : "0", "Scalar::Util" : "0", "namespace::autoclean" : "0.11", "namespace::clean" : "0.20", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "Test::Fatal" : "0", "Test::More" : "0.96", "Test::Requires" : "0.05", "lib" : "0", "vars" : "0" } } }, "provides" : { "MooseX::ClassAttribute" : { "file" : "lib/MooseX/ClassAttribute.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Meta::Role::Attribute" : { "file" : "lib/MooseX/ClassAttribute/Meta/Role/Attribute.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Application" : { "file" : "lib/MooseX/ClassAttribute/Trait/Application.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Application::ToClass" : { "file" : "lib/MooseX/ClassAttribute/Trait/Application/ToClass.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Application::ToRole" : { "file" : "lib/MooseX/ClassAttribute/Trait/Application/ToRole.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Attribute" : { "file" : "lib/MooseX/ClassAttribute/Trait/Attribute.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Class" : { "file" : "lib/MooseX/ClassAttribute/Trait/Class.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Mixin::HasClassAttributes" : { "file" : "lib/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Role" : { "file" : "lib/MooseX/ClassAttribute/Trait/Role.pm", "version" : "0.29" }, "MooseX::ClassAttribute::Trait::Role::Composite" : { "file" : "lib/MooseX/ClassAttribute/Trait/Role/Composite.pm", "version" : "0.29" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-moosex-classattribute@rt.cpan.org", "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-ClassAttribute" }, "homepage" : "http://metacpan.org/release/MooseX-ClassAttribute", "repository" : { "type" : "git", "url" : "git://github.com/moose/MooseX-ClassAttribute.git", "web" : "https://github.com/moose/MooseX-ClassAttribute" } }, "version" : "0.29", "x_Dist_Zilla" : { "perl" : { "version" : "5.024000" }, "plugins" : [ { "class" : "Dist::Zilla::Plugin::MakeMaker", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@DROLSKY/MakeMaker", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::Git::GatherDir", "config" : { "Dist::Zilla::Plugin::GatherDir" : { "exclude_filename" : [ "Build.PL", "CONTRIBUTING.md", "LICENSE", "Makefile.PL", "README.md", "cpanfile", "ppport.h" ], "exclude_match" : [], "follow_symlinks" : 0, "include_dotfiles" : 0, "prefix" : "", "prune_directory" : [], "root" : "." }, "Dist::Zilla::Plugin::Git::GatherDir" : { "include_untracked" : 0 } }, "name" : "@DROLSKY/Git::GatherDir", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::ManifestSkip", "name" : "@DROLSKY/ManifestSkip", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::License", "name" : "@DROLSKY/License", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::ExecDir", "name" : "@DROLSKY/ExecDir", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::ShareDir", "name" : "@DROLSKY/ShareDir", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::Manifest", "name" : "@DROLSKY/Manifest", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::CheckVersionIncrement", "name" : "@DROLSKY/CheckVersionIncrement", "version" : "0.121750" }, { "class" : "Dist::Zilla::Plugin::TestRelease", "name" : "@DROLSKY/TestRelease", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::ConfirmRelease", "name" : "@DROLSKY/ConfirmRelease", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::UploadToCPAN", "name" : "@DROLSKY/UploadToCPAN", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::VersionProvider", "name" : "@DROLSKY/DROLSKY::VersionProvider", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Authority", "name" : "@DROLSKY/Authority", "version" : "1.009" }, { "class" : "Dist::Zilla::Plugin::AutoPrereqs", "name" : "@DROLSKY/AutoPrereqs", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", "name" : "@DROLSKY/CopyFilesFromBuild", "version" : "0.161350" }, { "class" : "Dist::Zilla::Plugin::GitHub::Meta", "name" : "@DROLSKY/GitHub::Meta", "version" : "0.42" }, { "class" : "Dist::Zilla::Plugin::GitHub::Update", "config" : { "Dist::Zilla::Plugin::GitHub::Update" : { "metacpan" : 1 } }, "name" : "@DROLSKY/GitHub::Update", "version" : "0.42" }, { "class" : "Dist::Zilla::Plugin::MetaResources", "name" : "@DROLSKY/MetaResources", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::MetaProvides::Package", "config" : { "Dist::Zilla::Plugin::MetaProvides::Package" : { "finder_objects" : [ { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.005" } ] }, "Dist::Zilla::Role::MetaProvider::Provider" : { "Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.001011", "inherit_missing" : "1", "inherit_version" : "1", "meta_noindex" : "1" } }, "name" : "@DROLSKY/MetaProvides::Package", "version" : "2.003002" }, { "class" : "Dist::Zilla::Plugin::MetaYAML", "name" : "@DROLSKY/MetaYAML", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::Meta::Contributors", "name" : "@DROLSKY/Meta::Contributors", "version" : "0.003" }, { "class" : "Dist::Zilla::Plugin::MetaConfig", "name" : "@DROLSKY/MetaConfig", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::MetaJSON", "name" : "@DROLSKY/MetaJSON", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::NextRelease", "name" : "@DROLSKY/NextRelease", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "test", "type" : "requires" } }, "name" : "@DROLSKY/Test::More with subtest", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::Prereqs", "config" : { "Dist::Zilla::Plugin::Prereqs" : { "phase" : "develop", "type" : "requires" } }, "name" : "@DROLSKY/Modules for use with tidyall", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::PromptIfStale", "config" : { "Dist::Zilla::Plugin::PromptIfStale" : { "check_all_plugins" : 1, "check_all_prereqs" : 1, "modules" : [], "phase" : "build", "skip" : [ "Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent", "Dist::Zilla::Plugin::DROLSKY::Contributors", "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch", "Dist::Zilla::Plugin::DROLSKY::License", "Dist::Zilla::Plugin::DROLSKY::TidyAll", "Dist::Zilla::Plugin::DROLSKY::VersionProvider", "Pod::Weaver::PluginBundle::DROLSKY" ] } }, "name" : "@DROLSKY/PromptIfStale", "version" : "0.049" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", "name" : "@DROLSKY/Test::Pod::Coverage::Configurable", "version" : "0.06" }, { "class" : "Dist::Zilla::Plugin::Test::PodSpelling", "config" : { "Dist::Zilla::Plugin::Test::PodSpelling" : { "directories" : [], "spell_cmd" : "", "stopwords" : [ "API", "DROLSKY", "DROLSKY's", "PayPal", "PayPal", "Rolsky", "Rolsky's", "drolsky", "metaclass", "mixin" ], "wordlist" : "Pod::Wordlist" } }, "name" : "@DROLSKY/Test::PodSpelling", "version" : "2.007002" }, { "class" : "Dist::Zilla::Plugin::PodSyntaxTests", "name" : "@DROLSKY/PodSyntaxTests", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::LinkCheck", "name" : "@DROLSKY/Test::Pod::LinkCheck", "version" : "1.002" }, { "class" : "Dist::Zilla::Plugin::Test::Pod::No404s", "name" : "@DROLSKY/Test::Pod::No404s", "version" : "1.003" }, { "class" : "Dist::Zilla::Plugin::RunExtraTests", "config" : { "Dist::Zilla::Role::TestRunner" : { "default_jobs" : 1 } }, "name" : "@DROLSKY/RunExtraTests", "version" : "0.029" }, { "class" : "Dist::Zilla::Plugin::MojibakeTests", "name" : "@DROLSKY/MojibakeTests", "version" : "0.8" }, { "class" : "Dist::Zilla::Plugin::Test::CleanNamespaces", "config" : { "Dist::Zilla::Plugin::Test::CleanNamespaces" : { "filename" : "xt/author/clean-namespaces.t", "skips" : [] } }, "name" : "@DROLSKY/Test::CleanNamespaces", "version" : "0.006" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes", "name" : "@DROLSKY/Test::CPAN::Changes", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::Test::CPAN::Meta::JSON", "name" : "@DROLSKY/Test::CPAN::Meta::JSON", "version" : "0.004" }, { "class" : "Dist::Zilla::Plugin::Test::EOL", "config" : { "Dist::Zilla::Plugin::Test::EOL" : { "filename" : "xt/author/eol.t", "finder" : [ ":InstallModules", ":ExecFiles", ":TestFiles" ], "trailing_whitespace" : "1" } }, "name" : "@DROLSKY/Test::EOL", "version" : "0.18" }, { "class" : "Dist::Zilla::Plugin::Test::NoTabs", "config" : { "Dist::Zilla::Plugin::Test::NoTabs" : { "filename" : "xt/author/no-tabs.t", "finder" : [ ":InstallModules", ":ExecFiles", ":TestFiles" ] } }, "name" : "@DROLSKY/Test::NoTabs", "version" : "0.15" }, { "class" : "Dist::Zilla::Plugin::Test::Portability", "name" : "@DROLSKY/Test::Portability", "version" : "2.000006" }, { "class" : "Dist::Zilla::Plugin::Test::TidyAll", "name" : "@DROLSKY/Test::TidyAll", "version" : "0.03" }, { "class" : "Dist::Zilla::Plugin::Test::Compile", "config" : { "Dist::Zilla::Plugin::Test::Compile" : { "bail_out_on_fail" : "0", "fail_on_warning" : "author", "fake_home" : 0, "filename" : "xt/author/00-compile.t", "module_finder" : [ ":InstallModules" ], "needs_display" : 0, "phase" : "develop", "script_finder" : [ ":PerlExecFiles" ], "skips" : [] } }, "name" : "@DROLSKY/Test::Compile", "version" : "2.054" }, { "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", "name" : "@DROLSKY/Test::ReportPrereqs", "version" : "0.024" }, { "class" : "Dist::Zilla::Plugin::Test::Version", "name" : "@DROLSKY/Test::Version", "version" : "1.09" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::Contributors", "name" : "@DROLSKY/DROLSKY::Contributors", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Git::Contributors", "config" : { "Dist::Zilla::Plugin::Git::Contributors" : { "include_authors" : 0, "include_releaser" : 1, "order_by" : "name", "paths" : [ "." ] } }, "name" : "@DROLSKY/Git::Contributors", "version" : "0.023" }, { "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver", "config" : { "Dist::Zilla::Plugin::PodWeaver" : { "config_plugins" : [ "@DROLSKY" ], "finder" : [ ":InstallModules", ":ExecFiles" ], "plugins" : [ { "class" : "Pod::Weaver::Plugin::EnsurePod5", "name" : "@CorePrep/EnsurePod5", "version" : "4.013" }, { "class" : "Pod::Weaver::Plugin::H1Nester", "name" : "@CorePrep/H1Nester", "version" : "4.013" }, { "class" : "Pod::Weaver::Plugin::SingleEncoding", "name" : "@DROLSKY/SingleEncoding", "version" : "4.013" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@DROLSKY/List", "version" : "4.013" }, { "class" : "Pod::Weaver::Plugin::Transformer", "name" : "@DROLSKY/Verbatim", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/header", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Name", "name" : "@DROLSKY/Name", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Version", "name" : "@DROLSKY/Version", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/prelude", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "SYNOPSIS", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "DESCRIPTION", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Generic", "name" : "OVERVIEW", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "ATTRIBUTES", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "METHODS", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "FUNCTIONS", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Collect", "name" : "TYPES", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Leftovers", "name" : "@DROLSKY/Leftovers", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/postlude", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::GenerateSection", "name" : "@DROLSKY/generate SUPPORT", "version" : "1.01" }, { "class" : "Pod::Weaver::Section::AllowOverride", "name" : "@DROLSKY/allow override SUPPORT", "version" : "0.05" }, { "class" : "Pod::Weaver::Section::GenerateSection", "name" : "@DROLSKY/generate DONATIONS", "version" : "1.01" }, { "class" : "Pod::Weaver::Section::Authors", "name" : "@DROLSKY/Authors", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Contributors", "name" : "@DROLSKY/Contributors", "version" : "0.009" }, { "class" : "Pod::Weaver::Section::Legal", "name" : "@DROLSKY/Legal", "version" : "4.013" }, { "class" : "Pod::Weaver::Section::Region", "name" : "@DROLSKY/footer", "version" : "4.013" } ] } }, "name" : "@DROLSKY/SurgicalPodWeaver", "version" : "0.0023" }, { "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", "config" : { "Dist::Zilla::Role::FileWatcher" : { "version" : "0.006" } }, "name" : "@DROLSKY/README.md in build", "version" : "0.161170" }, { "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir", "config" : { "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : { "destination_filename" : "CONTRIBUTING.md", "dist" : "Dist-Zilla-PluginBundle-DROLSKY", "encoding" : "UTF-8", "has_xs" : "0", "location" : "build", "source_filename" : "CONTRIBUTING.md" }, "Dist::Zilla::Role::RepoFileInjector" : { "allow_overwrite" : 1, "repo_root" : ".", "version" : "0.006" } }, "name" : "@DROLSKY/generate CONTRIBUTING", "version" : "0.009" }, { "class" : "Dist::Zilla::Plugin::InstallGuide", "name" : "@DROLSKY/InstallGuide", "version" : "1.200006" }, { "class" : "Dist::Zilla::Plugin::CPANFile", "name" : "@DROLSKY/CPANFile", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::License", "name" : "@DROLSKY/DROLSKY::License", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed", "name" : "@DROLSKY/CheckPrereqsIndexed", "version" : "0.018" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent", "name" : "@DROLSKY/DROLSKY::CheckChangesHasContent", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch", "config" : { "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." } }, "name" : "@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts", "config" : { "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." } }, "name" : "@DROLSKY/Git::CheckFor::MergeConflicts", "version" : "0.013" }, { "class" : "Dist::Zilla::Plugin::DROLSKY::TidyAll", "name" : "@DROLSKY/DROLSKY::TidyAll", "version" : "0.58" }, { "class" : "Dist::Zilla::Plugin::Git::Check", "config" : { "Dist::Zilla::Plugin::Git::Check" : { "untracked_files" : "die" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Build.PL", "CONTRIBUTING.md", "Changes", "LICENSE", "Makefile.PL", "README.md", "cpanfile", "ppport.h", "tidyall.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." } }, "name" : "@DROLSKY/Git::Check", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "v%v%n%n%c" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Build.PL", "CONTRIBUTING.md", "Changes", "LICENSE", "Makefile.PL", "README.md", "cpanfile", "ppport.h", "tidyall.ini" ], "allow_dirty_match" : [], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@DROLSKY/commit generated files", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::Git::Tag", "config" : { "Dist::Zilla::Plugin::Git::Tag" : { "branch" : null, "changelog" : "Changes", "signed" : 0, "tag" : "v0.29", "tag_format" : "v%v", "tag_message" : "v%v" }, "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@DROLSKY/Git::Tag", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." } }, "name" : "@DROLSKY/Git::Push", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease", "config" : { "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { "finders" : [ ":ExecFiles", ":InstallModules" ], "global" : 0, "munge_makefile_pl" : 1 } }, "name" : "@DROLSKY/BumpVersionAfterRelease", "version" : "0.015" }, { "class" : "Dist::Zilla::Plugin::Git::Commit", "config" : { "Dist::Zilla::Plugin::Git::Commit" : { "add_files_in" : [], "commit_msg" : "Bump version after release" }, "Dist::Zilla::Role::Git::DirtyFiles" : { "allow_dirty" : [ "Changes", "dist.ini" ], "allow_dirty_match" : [ "(?^:.+)" ], "changelog" : "Changes" }, "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." }, "Dist::Zilla::Role::Git::StringFormatter" : { "time_zone" : "local" } }, "name" : "@DROLSKY/commit version bump", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::Git::Push", "config" : { "Dist::Zilla::Plugin::Git::Push" : { "push_to" : [ "origin" ], "remotes_must_exist" : 1 }, "Dist::Zilla::Role::Git::Repo" : { "repo_root" : "." } }, "name" : "@DROLSKY/push version bump", "version" : "2.039" }, { "class" : "Dist::Zilla::Plugin::Prereqs::Soften", "config" : { "Dist::Zilla::Plugin::Prereqs::Soften" : { "copy_to" : [ "develop.requires" ], "modules" : [ "MooseX::AttributeHelpers", "MooseX::Role::Parameterized", "MooseX::Role::Strict" ], "modules_from_features" : null, "to_relationship" : "none" } }, "name" : "Prereqs::Soften", "version" : "0.006002" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":InstallModules", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":IncModules", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":TestFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExtraTestFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ExecFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":PerlExecFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":ShareFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":MainModule", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":AllFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : ":NoFiles", "version" : "6.005" }, { "class" : "Dist::Zilla::Plugin::FinderCode", "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM", "version" : "6.005" } ], "zilla" : { "class" : "Dist::Zilla::Dist::Builder", "config" : { "is_trial" : "0" }, "version" : "6.005" } }, "x_authority" : "cpan:DROLSKY", "x_contributors" : [ "Andrew Rodland ", "Karen Etheridge ", "Rafael Kitover ", "Robert Buels ", "Shawn M Moore " ] } MooseX-ClassAttribute-0.29/tidyall.ini0000644000175000017500000000034212722657162017621 0ustar autarchautarch[PerlTidy] select = **/*.{pl,pm,t,psgi} ignore = .build/**/* ignore = MooseX-ClassAttribute-*/**/* ignore = blib/**/* ignore = t/00-* ignore = t/author-* ignore = t/release-* ignore = xt/**/* argv = --profile=$ROOT/perltidyrc MooseX-ClassAttribute-0.29/Changes0000644000175000017500000001111012722657162016744 0ustar autarchautarch0.29 2016-05-29 - Fix test prereqs on MooseX::AttributeHelpers and MooseX::Role::Strict. 0.28 2016-05-16 - Repository migrated to the github moose organization. (Karen Etheridge) - Removed dependency on List::MoreUtils. (Karen Etheridge) 0.27 2013-03-28 - The latest Moose release (2.08) broke this module. This release fixes MooseX::ClassAttribute to work with both new and old Mooses. Reported by Jonathan Stowe. RT #84263. 0.26 2011-06-06 - The default() method for class attributes always returned a value, even if the default was a subroutine ref, which isn't how the method works for regular attributes. This broke inlining with Moose HEAD. 0.25 2011-06-05 - Class attributes now have a definition context set, which means that errors thrown from generated methods associated with these attributes say something like "X at accessor MyClass::ClassAttribute (defined at path/to/file line 42)" rather than "generated method (unknown origin)". 0.24 2011-02-22 - This release provides forward compatibility with Moose 1.99+. It will still work with Moose 1.23 as well. Partially based on work originally done by Moritz Onken. 0.23 2011-02-13 - Fixed a bug where applying a role with class attributes didn't record the role as actually being applied in the meta class (or role) to which it was applied. Reported by Karen Etheridge. RT #59610. - Applying multiple roles to a class lost all class attributes from those roles. Fixed by Andrew Rodland. RT #59572. 0.22 2011-02-02 - Explicitly require namespace::clean 0.20 to avoid some bad interactions between namespace::clean and Package::Stash. 0.21 2010-10-29 - Switch from Test::Exception to Test::Fatal. 0.20 2010-10-07 - A test file tried to load MooseX::Role::Parameterized, which was not listed as a dep. Reported by Andreas Koenig. RT #61957. 0.19 2010-10-06 - Removed references to MooseX::ClassAttribute::Meta::Method::Accessor, which was removed in 0.18. This caused lots of test failures if you hadn't installed a previous version of this distribution. 0.18 2010-10-05 - Changes to work with (and require) Moose 1.15. 0.17 2010-09-26 - Changes to work with (and require) Moose 1.09. 0.16 2010-07-15 - More warnings fixes for next Moose release. - Fix bad repo metadata. 0.15 2010-07-14 - Fix bad uri for bugtracker in metadata 0.14 2010-07-14 - Use modern Moose APIs, to avoid warnings with the next Moose release. 0.13 2010-02-11 - Fixed tests that failed if you had an older version of MooseX::AttributeHelpers installed. 0.12 2010-02-10 - Fixed so that applying a role with class attributes to an instance works with Moose 0.98. 0.11 2010-02-09 - Roles can now have class attributes, which will be fully initialized when the role is applied to a class. - Many modules have been renamed from MooseX::ClassAttribute::Role::Meta::* to MooseX::ClassAttribute::Trait::*. - Deprecated the get_class_attribute_map method. - Added a version number to every .pm file. 0.10 2009-08-26 - Fixed to make triggers work with Moose 0.89+, and made triggers pass the old attribute value when appropriate just like non-class attributes. 0.09 2009-07-09 - An attribute with a builder that wasn't also lazy caused an exception when the attribute's accessor was called. Reported by Josh. 0.08 2009-04-07 - Make this module work with Moose 0.73_01+. - Deprecated compute_all_applicable_class_attributes. Use get_all_class_attributes instead. 0.07 2008-11-10 - Fixed a bug where class attributes did not honor the Class::MOP::Attribute properly, so things that used it directly failed. This bug could be tickled by using certain MooseX::AttributeHelpers attribute metaclasses with a class attribute. Fixed by Shawn Moore. 0.06 2008-09-06 - No code changes, just added a missing prereq for MooseX::AttributeHelpers. 0.05 2008-09-05 * Totally rewritten as proper meta classes, so it supports introspection and all that good stuff. This breaks some old code because there is no longer a "containing class" for class attributes. 0.04 2008-01-21 - An internals change to make this class work with Moose 0.34. 0.03 2007-12-08 - Split main functionality out of sugar sub class_has(), into process_class_attribute(). This makes it easier to create attributes on behalf of other classes. 0.02 2007-11-25 - Inherit from Exporter, rather than trying to import its import(). Unfortunately, older Exporters as shipped with Perl 5.6.x only allow subclassing. 0.01 2007-11-24 - First version, released on an unsuspecting world. MooseX-ClassAttribute-0.29/CONTRIBUTING.md0000644000175000017500000000765512722657162017725 0ustar autarchautarch# CONTRIBUTING Thank you for considering contributing to this distribution. This file contains instructions that will help you work with the source code. Please note that if you have any questions or difficulties, you can reach the maintainer(s) through the bug queue described later in this document (preferred), or by emailing the releaser directly. You are not required to follow any of the steps in this document to submit a patch or bug report; these are just recommendations, intended to help you (and help us help you faster). The distribution is managed with [Dist::Zilla](https://metacpan.org/release/Dist-Zilla). However, you can still compile and test the code with the `Makefile.PL` or `Build.PL` in the repository: perl Makefile.PL make make test or perl Build.PL ./Build ./Build test As well as: $ prove -bvr t or $ perl -Mblib t/some_test_file.t You may need to satisfy some dependencies. The easiest way to satisfy dependencies is to install the last release. This is available at https://metacpan.org/release/MooseX-ClassAttribute If you use cpanminus, you can do it without downloading the tarball first: $ cpanm --reinstall --installdeps --with-recommends MooseX::ClassAttribute Dist::Zilla is a very powerful authoring tool, but requires a number of author-specific plugins. If you would like to use it for contributing, install it from CPAN, then run one of the following commands, depending on your CPAN client: $ cpan `dzil authordeps --missing` or $ dzil authordeps --missing | cpanm They may also be additional requirements not needed by the dzil build which are needed for tests or other development: $ cpan `dzil listdeps --author --missing` or $ dzil listdeps --author --missing | cpanm Or, you can use the 'dzil stale' command to install all requirements at once: $ cpan Dist::Zilla::App::Command::stale $ cpan `dzil stale --all` or $ cpanm Dist::Zilla::App::Command::stale $ dzil stale --all | cpanm You can also do this via cpanm directly: $ cpanm --reinstall --installdeps --with-develop --with-recommends MooseX::ClassAttribute Once installed, here are some dzil commands you might try: $ dzil build $ dzil test $ dzil test --release $ dzil xtest $ dzil listdeps --json $ dzil build --notgz You can learn more about Dist::Zilla at http://dzil.org/. The code for this distribution is [hosted at GitHub](https://github.com/moose/MooseX-ClassAttribute). You can submit code changes by forking the repository, pushing your code changes to your clone, and then submitting a pull request. Detailed instructions for doing that is available here: https://help.github.com/articles/creating-a-pull-request If you have found a bug, but do not have an accompanying patch to fix it, you can submit an issue report [via the web](http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-ClassAttribute) or [via email](bug-moosex-classattribute@rt.cpan.org. This is a good place to send your questions about the usage of this distribution. ## Tidyall This distribution uses [Code::TidyAll](https://metacpan.org/release/Code-TidyAll) to enforce a uniform coding style. This is tested as part of the author testing suite. You can install and run tidyall by running the following commands: $ cpanm Code::TidyAll $ tidyall -a Please run this before committing your changes and address any issues it brings up. ## Contributor Names If you send me a patch or pull request, your name and email address will be included in the documentation as a contributor (using the attribution on the commit or patch), unless you specifically request for it not to be. If you wish to be listed under a different name or address, you should submit a pull request to the .mailmap file to contain the correct mapping. This file was generated via Dist::Zilla::Plugin::GenerateFile::FromShareDir 0.009 from a template file originating in Dist-Zilla-PluginBundle-DROLSKY-0.58. MooseX-ClassAttribute-0.29/MANIFEST0000644000175000017500000000256112722657162016614 0ustar autarchautarch# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.005. CONTRIBUTING.md Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL README.md cpanfile dist.ini lib/MooseX/ClassAttribute.pm lib/MooseX/ClassAttribute/Meta/Role/Attribute.pm lib/MooseX/ClassAttribute/Trait/Application.pm lib/MooseX/ClassAttribute/Trait/Application/ToClass.pm lib/MooseX/ClassAttribute/Trait/Application/ToRole.pm lib/MooseX/ClassAttribute/Trait/Attribute.pm lib/MooseX/ClassAttribute/Trait/Class.pm lib/MooseX/ClassAttribute/Trait/Mixin/HasClassAttributes.pm lib/MooseX/ClassAttribute/Trait/Role.pm lib/MooseX/ClassAttribute/Trait/Role/Composite.pm perlcriticrc perltidyrc t/00-report-prereqs.dd t/00-report-prereqs.t t/01-basic.t t/02-immutable.t t/03-introspection.t t/04-with-native-traits.t t/05-with-attribute-helpers-backcompat.t t/06-role.t t/07-parameterized-role.t t/08-role-composition.t t/09-bare-native-traits.t t/10-strict-role-composition.t t/11-moose-exporter.t t/12-with-initializer.t t/lib/SharedTests.pm tidyall.ini xt/author/00-compile.t xt/author/clean-namespaces.t xt/author/eol.t xt/author/mojibake.t xt/author/no-tabs.t xt/author/pod-coverage.t xt/author/pod-no404s.t xt/author/pod-spell.t xt/author/pod-syntax.t xt/author/test-version.t xt/release/cpan-changes.t xt/release/meta-json.t xt/release/pod-linkcheck.t xt/release/portability.t xt/release/tidyall.t MooseX-ClassAttribute-0.29/perlcriticrc0000644000175000017500000000347112722657162020074 0ustar autarchautarchseverity = 3 verbose = 11 theme = core + pbp + bugs + maintenance + cosmetic + complexity + security + tests + moose program-extensions = pl psgi t exclude = Subroutines::ProhibitCallsToUndeclaredSubs [BuiltinFunctions::ProhibitStringySplit] severity = 3 [CodeLayout::RequireTrailingCommas] severity = 3 [ControlStructures::ProhibitCStyleForLoops] severity = 3 [InputOutput::RequireCheckedSyscalls] functions = :builtins exclude_functions = sleep severity = 3 [RegularExpressions::ProhibitComplexRegexes] max_characters = 200 [RegularExpressions::ProhibitUnusualDelimiters] severity = 3 [Subroutines::ProhibitUnusedPrivateSubroutines] private_name_regex = _(?!build)\w+ [TestingAndDebugging::ProhibitNoWarnings] allow = redefine [ValuesAndExpressions::ProhibitEmptyQuotes] severity = 3 [ValuesAndExpressions::ProhibitInterpolationOfLiterals] severity = 3 [ValuesAndExpressions::RequireUpperCaseHeredocTerminator] severity = 3 [Variables::ProhibitPackageVars] add_packages = Carp Test::Builder [-Subroutines::RequireFinalReturn] # This incorrectly thinks signatures are prototypes. [-Subroutines::ProhibitSubroutinePrototypes] [-ErrorHandling::RequireCarping] # No need for /xsm everywhere [-RegularExpressions::RequireDotMatchAnything] [-RegularExpressions::RequireExtendedFormatting] [-RegularExpressions::RequireLineBoundaryMatching] # http://stackoverflow.com/questions/2275317/why-does-perlcritic-dislike-using-shift-to-populate-subroutine-variables [-Subroutines::RequireArgUnpacking] # "use v5.14" is more readable than "use 5.014" [-ValuesAndExpressions::ProhibitVersionStrings] # Explicitly returning undef is a _good_ thing in many cases, since it # prevents very common errors when using a sub in list context to construct a # hash and ending up with a missing value or key. [-Subroutines::ProhibitExplicitReturnUndef] MooseX-ClassAttribute-0.29/INSTALL0000644000175000017500000000177012722657162016515 0ustar autarchautarchThis is the Perl distribution MooseX-ClassAttribute. Installing MooseX-ClassAttribute is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm MooseX::ClassAttribute If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S MooseX::ClassAttribute ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan MooseX::ClassAttribute ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, then build it: % perl Makefile.PL % make && make test Then install it: % make install If you are installing into a system-wide directory, you may need to run: % sudo make install ## Documentation MooseX-ClassAttribute documentation is available as POD. You can run perldoc from a shell to read the documentation: % perldoc MooseX::ClassAttribute MooseX-ClassAttribute-0.29/README.md0000644000175000017500000000761512722657162016747 0ustar autarchautarch# NAME MooseX::ClassAttribute - Declare class attributes Moose-style # VERSION version 0.29 # SYNOPSIS package My::Class; use Moose; use MooseX::ClassAttribute; class_has 'Cache' => ( is => 'rw', isa => 'HashRef', default => sub { {} }, ); __PACKAGE__->meta()->make_immutable(); no Moose; no MooseX::ClassAttribute; # then later ... My::Class->Cache()->{thing} = ...; # DESCRIPTION This module allows you to declare class attributes in exactly the same way as object attributes, using `class_has()` instead of `has()`. You can use any feature of Moose's attribute declarations, including overriding a parent's attributes, delegation (`handles`), attribute traits, etc. All features should just work. The one exception is the "required" flag, which is not allowed for class attributes. The accessor methods for class attribute may be called on the class directly, or on objects of that class. Passing a class attribute to the constructor will not set that attribute. # FUNCTIONS This class exports one function when you use it, `class_has()`. This works exactly like Moose's `has()`, but it declares class attributes. One little nit is that if you include `no Moose` in your class, you won't remove the `class_has()` function. To do that you must include `no MooseX::ClassAttribute` as well. Or you can just use [namespace::autoclean](https://metacpan.org/pod/namespace::autoclean) instead. ## Implementation and Immutability This module will add a role to your class's metaclass, See [MooseX::ClassAttribute::Trait::Class](https://metacpan.org/pod/MooseX::ClassAttribute::Trait::Class) for details. This role provides introspection methods for class attributes. Class attributes themselves do the [MooseX::ClassAttribute::Trait::Attribute](https://metacpan.org/pod/MooseX::ClassAttribute::Trait::Attribute) role. ## Cooperation with Metaclasses and Traits This module should work with most attribute metaclasses and traits, but it's possible that conflicts could occur. This module has been tested to work with Moose's native traits. ## Class Attributes in Roles You can add a class attribute to a role. When that role is applied to a class, the class will have the relevant class attributes added. Note that attribute defaults will be calculated when the class attribute is composed into the class. # SUPPORT Bugs may be submitted through [the RT bug tracker](http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-ClassAttribute) (or [bug-moosex-classattribute@rt.cpan.org](mailto:bug-moosex-classattribute@rt.cpan.org)). I am also usually active on IRC as 'drolsky' on `irc://irc.perl.org`. # DONATIONS If you'd like to thank me for the work I've done on this module, please consider making a "donation" to me via PayPal. I spend a lot of free time creating free software, and would appreciate any support you'd care to offer. Please note that **I am not suggesting that you must do this** in order for me to continue working on this particular software. I will continue to do so, inasmuch as I have in the past, for as long as it interests me. Similarly, a donation made in this way will probably not make me work on this software much more, unless I get so many donations that I can consider working on free software full time (let's all have a chuckle at that together). To donate, log into PayPal and send money to autarch@urth.org, or use the button at [http://www.urth.org/~autarch/fs-donation.html](http://www.urth.org/~autarch/fs-donation.html). # AUTHOR Dave Rolsky # CONTRIBUTORS - Andrew Rodland - Karen Etheridge - Rafael Kitover - Robert Buels - Shawn M Moore # COPYRIGHT AND LICENCE This software is Copyright (c) 2016 by Dave Rolsky. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible)