p5-p5u / lib / P5U / Lib / Testers.pm

Toby Inkster 9c2a00a 



Toby Inkster a7ee9a5 


Toby Inkster e241efe 
Toby Inkster a7ee9a5 

Toby Inkster e8551ab 
Toby Inkster b9132f3 
Toby Inkster 9c2a00a 



Toby Inkster b9132f3 
Toby Inkster 3d36826 
Toby Inkster 9c2a00a 


Toby Inkster 4b7c103 
Toby Inkster b9132f3 
Toby Inkster 4b7c103 
Toby Inkster 9c2a00a 


Toby Inkster e8551ab 
Toby Inkster b9132f3 
Toby Inkster 9c2a00a 


Toby Inkster e8551ab 
Toby Inkster b9132f3 
Toby Inkster e8551ab 
Toby Inkster 9c2a00a 


Toby Inkster e8551ab 
Toby Inkster b9132f3 
Toby Inkster e8551ab 
Toby Inkster 9c2a00a 

Toby Inkster 4b7c103 
Toby Inkster e8551ab 
Toby Inkster b9132f3 
Toby Inkster 4b7c103 


Toby Inkster e8551ab 
Toby Inkster b9132f3 
Toby Inkster 4b7c103 

Toby Inkster 9c2a00a 


















































































Toby Inkster 3d36826 
Toby Inkster 9c2a00a 









Toby Inkster 3d36826 
Toby Inkster 9c2a00a 









Toby Inkster 3d36826 
Toby Inkster a7ee9a5 
Toby Inkster 9c2a00a 

Toby Inkster 3d36826 
Toby Inkster 9c2a00a 



Toby Inkster 4b7c103 




Toby Inkster d934b01 
Toby Inkster 4b7c103 





















Toby Inkster e8551ab 
Toby Inkster 4b7c103 








































































































package P5U::Lib::Testers;

use 5.010;
use utf8;

BEGIN {
	$P5U::Lib::Testers::AUTHORITY = 'cpan:TOBYINK';
	$P5U::Lib::Testers::VERSION   = '0.006';
};

use Moo;
use MooX::Types::MooseLike::Base qw< ArrayRef Bool Str InstanceOf >;
use File::Spec       0 qw< >;
use JSON             0 qw< from_json >;
use LWP::Simple      0 qw< mirror is_success >;
use List::Util       0 qw< maxstr >;
use Object::AUTHORITY  qw< AUTHORITY >;
use Path::Class      0 qw< dir file >;
use namespace::clean;

has distro => (
	is         => 'ro',
	isa        => Str,
	required   => 1,
);

has version => (
	is         => 'lazy',
	isa        => Str,
);

has os_data => (
	is         => 'ro',
	isa        => Bool,
	default    => sub { 0 },
);

has stable => (
	is         => 'ro',
	isa        => Bool,
	default    => sub { 0 },
);

has cache_dir => (
	is         => 'lazy',
	isa        => InstanceOf['Path::Class::Dir'],
);

has results => (
	is         => 'lazy',
	isa        => ArrayRef,
);

sub version_data
{
	my ($self) = @_;
	my %data;
	foreach (@{$self->results})
	{
		next unless $_->{version} eq $self->version;
		my ($pv) = ($_->{perl} =~ /^5\.(\d+)/) or next;
		next if $pv ~~ [9, 11, 13, 15];
		my $key = $self->os_data
			? sprintf("Perl 5.%03d, %s", $pv, $_->{ostext})
			: sprintf("Perl 5.%03d", $pv);
		my $num  = { PASS => 0, FAIL => 1 }->{$_->{status}} // 2;
		$data{$key}[$num]++;
	}
	return \%data;
}

sub summary_data
{
	my ($self) = @_;
	my %data;
	foreach (@{$self->results})
	{
		my $key  = $_->{version};
		my $num  = { PASS => 0, FAIL => 1 }->{$_->{status}} // 2;
		$data{$key}[$num]++;
	}
	return \%data;
}

sub format_report
{
	my ($self, $title, $data) = @_;
	no warnings;
	join "\n" => (
		$title,
		q(),
		sprintf("%-32s%6s%6s%6s", q(), qw(PASS FAIL ETC)),
		(
			map { sprintf "%-32s% 6d% 6d% 6d", $_, @{$data->{$_}} }
			sort keys %$data
		),
		q(),
	);
}

sub version_report
{
	my ($self) = @_;
	
	$self->format_report(
		sprintf("CPAN Testers results for %s version %s", $self->distro, $self->version),
		$self->version_data,
	);
}

sub summary_report
{
	my ($self, $os_data) = @_;
	
	$self->format_report(
		sprintf("CPAN Testers results for %s", $self->distro),
		$self->summary_data,
	);
}

sub _build_version
{
	maxstr
		map { $_->{version} }
		@{ shift->results }
}

sub _build_results
{
	my $self = shift;
	
	my $results_uri = sprintf(
		'http://www.cpantesters.org/distro/%s/%s.json',
		substr($self->distro, 0, 1),
		$self->distro,
	);
	my $results_file = file(
		$self->cache_dir,
		sprintf('%s.json', $self->distro),
	);
	
	is_success mirror($results_uri => $results_file)
		or do {
			unlink $results_file;
			die "Failed to retrieve URI $results_uri\n";
		};
		
	my $results = from_json scalar $results_file->slurp;
	die "Unexpected non-ARRAY content from $results_uri\n"
		unless ref $results eq 'ARRAY';
	
	$self->stable
		? [ grep { $_->{version} !~ /_/ } @$results ]
		: $results;
}

sub _build_cache_dir
{
	my $dir = dir(
		File::Spec::->tmpdir,
		'CpanTesters',
	);
	dir($dir)->mktree unless -d $dir;
	return $dir;
}

1;

__END__

=head1 NAME

P5U::Lib::Testers - support library implementing p5u's testers command

=head1 SYNOPSIS

 use P5U::Lib::DebianRelease;
 use Path::Class qw(file dir);
 
 my $dr = P5U::Lib::DebianRelease->new(
   cache_file  => file("/tmp/debian.data"),
 );
 
 my $author_data = $dr->author_data('tobyink');
 foreach my $dist (@$author_data)
 {
   print "Dist:   $dist->[0]\n";
   print "CPAN:   $dist->[1]\n";
   print "Debian: $dist->[2]\n\n";
 }

=head1 DESCRIPTION

This is a support library for the testers command.

It's a L<Moo>-based class.

=head2 Constructor

=over

=item C<< new(%attributes) >>

Creates a new instance of the class.

=back

=head2 Attributes

=over

=item C<distro>

Distribution name; read-only; string; required.

=item C<version>

Version number; read-only; string.

If omitted, the latest version for which CPAN Testers results are available
is assumed.

=item C<os_data>

Indicates that reports should be split by operating system. Read-only;
boolean; default false.

=item C<stable>

Indicates that reports should ignore development releases. Read-only;
boolean; default false.

=item C<cache_dir>

A directory for caching JSON files into. Read-only; string. If omitted,
something sensible will be used.

=item C<results>

The CPAN testsers results, as an array of hashes. You generally do not
want to set this yourself, but rely on this module to build it for you!

=back

=head2 Methods

=over

=item C<version_data>

Returns a hashref. Keys are Perl versions such as "Perl 5.008", or if
C<os_data> is true "Perl 5.008, Linux". Values are arrayrefs of three
numbers indicating counts of passes, fails and other results respectively.

=item C<summary_data>

Returns a similar hash of arrays (HoA) structure to C<version_data>,
except keys are versions of the distribution, not versions of Perl.

=item C<format_report>

Given an HoA structure as above, formats it into a single string for printing
to a terminal or other output device using a fixed-width font.

=item C<< version_report >>

C<version_data> and C<format_report> in a single method call.

=item C<< summary_report >>

C<summary_data> and C<format_report> in a single method call.

=back

=head1 BUGS

Please report any bugs to
L<http://rt.cpan.org/Dist/Display.html?Queue=P5U>.

=head1 SEE ALSO

L<p5u>.

L<http://www.perlmonks.org/?node_id=978606>.

=head1 AUTHOR

Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

=head1 COPYRIGHT AND LICENCE

This software is copyright (c) 2012 by Toby Inkster.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=head1 DISCLAIMER OF WARRANTIES

THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.