<commit_before>package Silki::Web::Session;

use strict;
use warnings;

use Silki::Types qw( ArrayRef HashRef NonEmptyStr ErrorForSession );

use Moose;
use MooseX::AttributeHelpers;
use MooseX::Params::Validate qw( pos_validated_list );
use MooseX::SemiAffordanceAccessor;
use MooseX::StrictConstructor;

has form_data => (
    is      => 'rw',
    isa     => 'HashRef',
    lazy    => 1,
    default => sub { {} },
);

has _errors => (
    metaclass => 'Collection::Array',
    is        => 'ro',
    isa       => ArrayRef[ NonEmptyStr | HashRef ],
    default   => sub { [] },
    init_arg  => undef,
    provides  => {
        push     => 'add_error',
        elements => 'errors',
    },
);

has _messages => (
    metaclass => 'Collection::Array',
    is        => 'ro',
    isa       => ArrayRef[NonEmptyStr],
    default   => sub { [] },
    init_arg  => undef,
    provides  => {
        push     => 'add_message',
        elements => 'messages',
    },
);

around add_error => sub {
    my $orig = shift;
    my $self = shift;

    return $self->$orig( map { $self->_error_text($_) } @_ );
};

sub _error_text {
    my $self = shift;
    my ($e) = pos_validated_list( \@_, { isa => ErrorForSession } );

    if ( eval { $e->can('messages') } && $e->messages() ) {
        return $e->messages();
    }
    elsif ( eval { $e->can('message') } ) {
        return $e->message();
    }
    elsif ( ref $e ) {
        return @{$e};
    }
    else {

        # force stringification
        return $e . q{};
    }
}

no Moose;

__PACKAGE__->meta()->make_immutable();

1;
<commit_msg>use native traits, not MXAH<commit_after>package Silki::Web::Session;

use strict;
use warnings;

use Silki::Types qw( ArrayRef HashRef NonEmptyStr ErrorForSession );

use Moose;
use MooseX::Params::Validate qw( pos_validated_list );
use MooseX::SemiAffordanceAccessor;
use MooseX::StrictConstructor;

has form_data => (
    is      => 'rw',
    isa     => HashRef,
    lazy    => 1,
    default => sub { {} },
);

has _errors => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => ArrayRef [ NonEmptyStr | HashRef ],
    default  => sub { [] },
    init_arg => undef,
    handles  => {
        add_error => 'push',
        errors    => 'elements',
    },
);

has _messages => (
    traits   => ['Array'],
    is       => 'ro',
    isa      => ArrayRef [NonEmptyStr],
    default  => sub { [] },
    init_arg => undef,
    handles  => {
        add_message => 'push',
        messages    => 'elements',
    },
);

around add_error => sub {
    my $orig = shift;
    my $self = shift;

    return $self->$orig( map { $self->_error_text($_) } @_ );
};

sub _error_text {
    my $self = shift;
    my ($e) = pos_validated_list( \@_, { isa => ErrorForSession } );

    if ( eval { $e->can('messages') } && $e->messages() ) {
        return $e->messages();
    }
    elsif ( eval { $e->can('message') } ) {
        return $e->message();
    }
    elsif ( ref $e ) {
        return @{$e};
    }
    else {

        # force stringification
        return $e . q{};
    }
}

no Moose;

__PACKAGE__->meta()->make_immutable();

1;

{'fraction_non_alphanumeric': 0.17296604740550928, 'fraction_numerical': 0.0012812299807815502, 'mean_word_length': 2.256517205422315, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3481267', 'n_tokens_mistral': 1084, 'n_tokens_neox': 1073, 'n_words': 243}