Also see Moose::Manual::Delta for more details of, and workarounds
for, noteworthy changes.
-0.88
- Japan Perl Association has sponsored Goro Fuji to improve
- startup performance of Class::MOP and Moose. These enhancements
- may break backwards compatibility if you're doing (or using)
- complex metaprogramming, so, as always, test your code!
- http://blog.perlassociation.org/2009/07/jpa-sponsors-moose-class-mop-work.html
-
- * Moose::Meta::Method::Accessor
- - No longer uses inline_slot_access in accessors, to support
- non-lvalue-based meta instances. (sorear)
-
+next version
* Moose::Meta::Attribute
- Added the currying syntax for delegation from AttributeHelpers
to the existing delegation API. (hdp)
- Moved in from MooseX with API tweaks. See Moose::Manual::Delta for
details. (hdp, jhannah, rbuels)
+ * Moose::Manual::Attributes
+ - Clarify "is", include discussion of "bare". (Sartak)
+
+ * Moose::Meta::Role::Method::Conflicting
+ * Moose::Meta::Role::Application::ToClass
+ - For the first set of roles involved in a conflict, report all
+ unresolved method conflicts, not just the first method. Fixes #47210
+ reported by Ovid. (Sartak)
+
+0.88 Fri Jul 24, 2009
* Moose::Manual::Contributing
- - Re-write the Moose::Manual::Contributing document to reflect the new
- layout and methods of work for the Git repository. All work now should
- be done in topic branches and reviewed by a core committer before
- being applied to master. All releases are done by a cabal member and
- merged from master to stable. This plan was devised by Yuval, blame
- him. (perigrin)
+ - Re-write the Moose::Manual::Contributing document to reflect
+ the new layout and methods of work for the Git repository. All
+ work now should be done in topic branches and reviewed by a
+ core committer before being applied to master. All releases
+ are done by a cabal member and merged from master to
+ stable. This plan was devised by Yuval, blame him. (perigrin)
* Moose::Meta::Role
- - Create metaclass attributes for the different role application classes.
- (rafl)
+ - Create metaclass attributes for the different role application
+ classes. (rafl)
+
* Moose::Util::MetaRole
- - Allow applying roles to a meta role's role application classes. (rafl)
+ - Allow applying roles to a meta role's role application
+ classes. (rafl)
+
+ * Moose::Meta::Attribute
+ - Add weak_ref to allowed options for "has '+foo'" (mst)
+
+ * Moose::Meta::Method::Accessor
+ - No longer uses inline_slot_access in accessors, to support
+ non-lvalue-based meta instances. (sorear)
0.87 Tue Jul 7, 2009
* Moose::Meta::Method::Delegation
-Moose version 0.87
+Moose version 0.88
===========================
See the individual module documentation for more information
use 5.008;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
attribute meta-object. This is very similar to the I<metaclass> option, but
allows you to use more than one extension at a time.
-See L<TRAIT NAME RESOLUTION> for details on how a trait name is
+See L<Trait Name Resolution> for details on how a trait name is
resolved to a class name.
Also see L<Moose::Cookbook::Meta::Recipe3> for a metaclass trait
This is very similar to the attribute traits feature. When you do
this, your class's C<meta> object will have the specified traits
-applied to it. See L<TRAIT NAME RESOLUTION> for more details.
+applied to it. See L<Trait Name Resolution> for more details.
=head2 Trait Name Resolution
isa => 'Str',
);
- sub BUILDARGS {
+ around BUILDARGS => sub {
+ my $orig = shift;
my $class = shift;
if ( @_ == 1 && ! ref $_[0] ) {
- return { ssn => $_[0] };
+ return $class->$orig(ssn => $_[0]);
}
else {
- return $class->SUPER::BUILDARGS(@_);
+ return $class->$orig(@_);
}
- }
+ };
sub BUILD {
my $self = shift;
The key part of our C<BUILDARGS> is this conditional:
if ( @_ == 1 && ! ref $_[0] ) {
- return { ssn => $_[0] };
+ return $class->$orig(ssn => $_[0]);
}
By default, Moose constructors accept a list of key-value pairs, or a
hash reference. We need to make sure that C<$_[0]> is not a reference
before assuming it is a social security number.
-We call C<< $class->SUPER::BUILDARGS(@_) >> to handle all the other
+We call the original C<BUILDARGS> method to handle all the other
cases. You should always do this in your own C<BUILDARGS> methods,
since L<Moose::Object> provides its own C<BUILDARGS> method that
handles hash references and a list of key-value pairs.
has 'node' => ( is => 'rw', isa => 'Any' );
Moose generates a read-write accessor for this attribute. The type
-constraint is C<Any>, which means literally means it can contain
-anything.
+constraint is C<Any>, which literally means it can contain anything.
We could have left out the C<isa> option, but in this case, we are
including it for the benefit of other programmers, not the computer.
like, as we showed in the second recipe.
Also, you can use C<builder> instead of C<default>. See
-L<Moose::Cookbook::Basics::Recipe9> for details.
+L<Moose::Cookbook::Basics::Recipe8> for details.
=back
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
The options passed to C<has> define the properties of the
attribute. There are many options, but in the simplest form you just
need to set C<is>, which can be either C<rw> (read-write) or C<ro>
-(read-only).
-
-(In fact, you could even omit C<is>, but that gives you an attribute
-that has no accessors, which is pointless unless you're doing some
-deep, dark magic).
+(read-only). When an attribute is C<rw>, you can change it by passing
+a value to its accessor. When an attribute is C<ro>, you may only read
+the current value of the attribute.
+
+In fact, you could even omit C<is>, but that gives you an attribute
+that has no accessor. This can be useful with other attribute options,
+such as C<handles>. However, if your attribute generates I<no>
+accessors, Moose will issue a warning, because that usually means the
+programmer forgot to say the attribute is read-only or read-write. If
+you really mean to have no accessors, you can silence this warning by
+setting C<is> to C<bare>.
=head2 Accessor methods
a hash or hash reference. We can use the C<BUILDARGS> method to
accommodate this calling style:
- sub BUILDARGS {
+ around BUILDARGS => sub {
+ my $orig = shift;
my $class = shift;
if ( @_ == 1 && ! ref $_[0] ) {
- return { ssn => $_[0] };
+ return $class->$orig(ssn => $_[0]);
}
else {
- return $class->SUPER::BUILDARGS(@_);
+ return $class->$orig(@_);
}
- }
+ };
-Note the call to C<SUPER::BUILDARGS>. This will call the default
+Note the call to C<< $class->$orig >>. This will call the default
C<BUILDARGS> in L<Moose::Object>. This method handles distinguishing
between a hash reference and a plain hash for you.
These people have worked with the Moose codebase for a while.
They've been responsible for large features or branches and can help review
-your changes and apply them to the master branch.
+your changes and apply them to the master branch using the basic
+L</APPROVAL WORKFLOW>.
They are also fairly well versed in Git, in order to merge the branches with
no mistakes (especially when the merge fails), and to provide advice to
git rebase --interactive # allowed
git push --force origin topic/my_feature # allowed
-Then go on IRC, ask for someone to review, and merge to master. If it merges
-cleanly and nobody has any objections, then it can be pushed to master.
+Then ask for a review/approval (see L</APPROVAL WORKFLOW>), and merge
+to master. If it merges cleanly and nobody has any objections, then it
+can be pushed to master.
If it doesn't merge as a fast forward, the author of the branch needs to run
All large changes should be documented in L<Moose::Manual::Delta>.
+=head1 APPROVAL WORKFLOW
+
+Moose is an open project but it is also an increasingly important one. Many
+modules depend on Moose being stable. Therefore, we have a basic set of
+criteria for reviewing and merging branches. What follows is a set of rough
+guidelines that ensures all new code is properly vetted before it is merged to
+the master branch.
+
+It should be noted that if you want your specific branch to be approved, it is
+B<your> responsibility to follow this process and advocate for your branch.
+The preferred way is to send a request to the mailing list for review/approval,
+this allows us to better keep track of the branches awaiting approval and those
+which have been approved.
+
+=over 4
+
+=item Small bug fixes, doc patches and additional passing tests.
+
+These items don't really require approval beyond one of the core contributors
+just doing a simple review.
+
+=item Larger bug fixes, doc additions and TODO or failing tests.
+
+Larger bug fixes should be reviewed by at least one cabal member and should be
+tested using the F<cpan-stable-smolder> script in the moose-dev-utils
+repository.
+
+New documentation is always welcome, but should also be reviewed by a cabal
+member for accuracy.
+
+TODO tests are basically feature requests, see our L</NEW FEATURES> section
+for more information on that. If your feature needs core support, create a
+topic/ branch using the L</STANDARD WORKFLOW> and start hacking away.
+
+Failing tests are basically bug reports. You should find a core contributor
+and/or cabal member to see if it is a real bug, then submit the bug and your
+test to the RT queue. Source control is not a bug reporting tool.
+
+=item New user-facing features.
+
+Anything that creates a new user-visible feature needs to be approved by
+B<more then one> cabal member.
+
+Make sure you have reviewed L</NEW FEATURES> to be sure that you are following
+the guidelines. Do not be surprised if a new feature is rejected for the core.
+
+=item New internals features.
+
+New features for Moose internals are less restrictive then user facing
+features, but still require approval by B<at least one> cabal member.
+
+Ideally you will have run the smolder script to be sure you are not breaking
+any MooseX module or causing any other unforeseen havoc. If you do this
+(rather then make us do it), it will only help to hasten your branch's
+approval.
+
+=item Backwards incompatible changes.
+
+Anything that breaks backwards compatibility must be discussed by the cabal
+and agreed to by a majority of the members.
+
+We have a policy for what we see as sane L</BACKWARDS COMPATIBILITY> for
+Moose. If your changes break back-compat, you must be ready to discuss and
+defend your change.
+
+=back
+
=head1 RELEASE WORKFLOW
git checkout master
Anyone can create the necessary fix by branching off of the stable branch:
git remote update
- git checkout -b topic/my-emergency-fix origin/master
+ git checkout -b topic/my-emergency-fix origin/stable
# hack
git commit
has 'size' => (
is => 'ro',
- isa => subtype 'Int' => where { $_ > 0 },
+ isa => subtype('Int' => where { $_ > 0 }),
);
This is handy when you want to create a one-off type and don't want to
use Scalar::Util 'blessed', 'weaken';
use overload ();
-our $VERSION = '0.87';
+our $VERSION = '0.88';
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Method::Accessor;
documentation lazy handles
builder type_constraint
definition_context
- lazy_build
+ lazy_build weak_ref
);
sub legal_options_for_inheritance { @legal_options_for_inheritance }
use List::MoreUtils qw( any all uniq first_index );
use Scalar::Util 'weaken', 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Class::MOP;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed', 'weaken', 'looks_like_number', 'refaddr';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
our $AUTHORITY = 'cpan:STEVAN';
use base 'Moose::Meta::Method',
use Carp 'confess';
use Scalar::Util 'blessed', 'weaken';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed', 'weaken';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Sub::Name 'subname';
use Devel::GlobalDestruction 'in_global_destruction';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use warnings;
use metaclass;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Role::Composite;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util 'english_list';
use Scalar::Util 'weaken', 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
if (@conflicts) {
my $conflict = $conflicts[0];
- my $roles = Moose::Util::english_list( map { q{'} . $_ . q{'} } @{ $conflict->roles } );
-
- $error
- .= "Due to a method name conflict in roles "
- . $roles
- . ", the method '"
- . $conflict->name
- . "' must be implemented or excluded by '"
- . $class->name
- . q{'};
+ my $roles = $conflict->roles_as_english_list;
+
+ my @same_role_conflicts = grep { $_->roles_as_english_list eq $roles } @conflicts;
+
+ if (@same_role_conflicts == 1) {
+ $error
+ .= "Due to a method name conflict in roles "
+ . $roles
+ . ", the method '"
+ . $conflict->name
+ . "' must be implemented or excluded by '"
+ . $class->name
+ . q{'};
+ }
+ else {
+ my $methods
+ = Moose::Util::english_list( map { q{'} . $_->name . q{'} } @same_role_conflicts );
+
+ $error
+ .= "Due to method name conflicts in roles "
+ . $roles
+ . ", the methods "
+ . $methods
+ . " must be implemented or excluded by '"
+ . $class->name
+ . q{'};
+ }
}
elsif (@missing) {
my $noun = @missing == 1 ? 'method' : 'methods';
use Scalar::Util 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
+use Moose::Util;
+
use base qw(Moose::Meta::Role::Method::Required);
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
required => 1,
));
+sub roles_as_english_list {
+ my $self = shift;
+ Moose::Util::english_list( map { q{'} . $_ . q{'} } @{ $self->roles } );
+}
+
1;
__END__
Returns the roles that generated this conflicting method, as provided to the
constructor.
+=item B<< $method->roles_as_english_list >>
+
+Returns the roles that generated this conflicting method as an English list.
+
=back
=head1 BUGS
use base qw(Class::MOP::Object);
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Attribute;
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use base qw(Class::MOP::Object);
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use warnings;
use metaclass;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util::TypeConstraints;
use Moose::Meta::TypeConstraint::Parameterizable;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::TypeCoercion::Union;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use if ( not our $__mx_is_compiled ), 'Moose::Meta::Class';
use if ( not our $__mx_is_compiled ), metaclass => 'Moose::Meta::Class';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Sub::Exporter;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
This is very similar to the attribute traits feature. When you do
this, your class's C<meta> object will have the specified traits
-applied to it. See L<Moose/TRAIT NAME RESOLUTION> for more details.
+applied to it. See L<Moose/Trait Name Resolution> for more details.
=head1 CAVEATS
use Scalar::Util 'blessed';
use Class::MOP 0.60;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util qw( blessed reftype );
use Moose::Exporter;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Class::MOP;
use Scalar::Util 'blessed', 'looks_like_number';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util 'does_role', 'find_meta';
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Class::MOP;
-our $VERSION = '0.87';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
has 'gorch' => (is => 'ro');
has 'gloum' => (is => 'ro', default => sub {[]});
+ has 'fleem' => (is => 'ro');
has 'bling' => (is => 'ro', isa => 'Thing');
has 'blang' => (is => 'ro', isa => 'Thing', handles => ['goodbye']);
} '... now can extend an attribute with a non-subtype';
::lives_ok {
+ has '+fleem' => (weak_ref => 1);
+ } '... now allowed to add the weak_ref option via inheritance';
+
+ ::lives_ok {
has '+bling' => (handles => ['hello']);
} '... we can add the handles attribute option';
::dies_ok {
has '+other_fail' => (trigger => sub {});
} '... cannot create an attribute with an illegal option';
- ::dies_ok {
- has '+other_fail' => (weak_ref => 1);
- } '... cannot create an attribute with an illegal option';
::throws_ok {
has '+does_not_exist' => (isa => 'Str');
} qr/in Bar/, '... cannot extend a non-existing attribute';
--- /dev/null
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+use Test::Exception;
+
+{
+ package Bomb;
+ use Moose::Role;
+
+ sub fuse { }
+ sub explode { }
+
+ package Spouse;
+ use Moose::Role;
+
+ sub fuse { }
+ sub explode { }
+
+ package Caninish;
+ use Moose::Role;
+
+ sub bark { }
+
+ package Treeve;
+ use Moose::Role;
+
+ sub bark { }
+}
+
+package PracticalJoke;
+use Moose;
+
+::throws_ok {
+ with 'Bomb', 'Spouse';
+} qr/Due to method name conflicts in roles 'Bomb' and 'Spouse', the methods 'explode' and 'fuse' must be implemented or excluded by 'PracticalJoke'/;
+
+::throws_ok {
+ with (
+ 'Bomb', 'Spouse',
+ 'Caninish', 'Treeve',
+ );
+} qr/Due to method name conflicts in roles 'Bomb' and 'Spouse', the methods 'explode' and 'fuse' must be implemented or excluded by 'PracticalJoke'/;
+
Unported
unsets
unsettable
+utils
whitelist
Whitelist
workflow