Module-CPANTS-Analyse-0.96/0000755000175000017500000000000012434531241015416 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/README0000644000175000017500000000243112411273577016310 0ustar ishigakiishigaki=encoding UTF-8 Module-CPANTS-Analyse =head1 NAME README - basic information for users prior to downloading =head1 DESCRIPTION Module-CPANTS-Analyse tests a dist for Kwalitee. This module is part of the L. =head1 AUTHOR L, C<< >> =head2 Distribution maintainer L, C<< >> =head2 Contributors See file F. =head1 COPYRIGHT Copyright © 2003–2009 L, C<< >> Some files are Copyright © 2006–2008 L, C<< >> Some files are Copyright © 2006 L, C<< >> Some files are Copyright © 2012 L, C<< >> Some files are Copyright © 2013- L, C<< >> Copyright © 2012, Perl QA team The module distributions in the F directory are copyright by their respective authors. =head1 LICENSE This code is distributed under the same license as Perl. Module-CPANTS-Analyse-0.96/AUTHORS0000644000175000017500000000160212411273577016477 0ustar ishigakiishigaki=encoding UTF-8 =head1 NAME AUTHORS - Authors of and contributors to Module-CPANTS-Analyse =head2 Principal authors =over =item L =item L =item L =item L =item L =back =head2 Contributors =over =item L =item L =item L =item L =item L =back Many other people who provided unattributed patches, advice and bug reports are mentioned in the F file. Module-CPANTS-Analyse-0.96/lib/0000755000175000017500000000000012434531241016164 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/lib/Module/0000755000175000017500000000000012434531241017411 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/lib/Module/CPANTS/0000755000175000017500000000000012434531241020401 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee.pm0000644000175000017500000001233112434527337022517 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee; use 5.006; use strict; use warnings; use base qw(Class::Accessor); use Carp; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic __PACKAGE__->mk_accessors(qw(generators _gencache _genhashcache _available _total)); sub import { my $class = shift; my %search_path = map {(/^Module::CPANTS::/ ? $_ : "Module::CPANTS::$_") => 1 } @_; $search_path{'Module::CPANTS::Kwalitee'} = 1; require Module::Pluggable; Module::Pluggable->import(search_path => [keys %search_path]); } sub new { my $class=shift; my $me=bless {},$class; my %generators; foreach my $gen ($me->plugins) { ## no critic (ProhibitStringyEval) eval "require $gen"; croak qq{cannot load $gen: $@} if $@; $generators{$gen}= [ $gen->order, $gen ]; } # sort by 'order' first, then name my @generators=sort { $generators{$a}->[0] <=> $generators{$b}->[0] || $generators{$a}->[1] cmp $generators{$b}->[1] } keys %generators; $me->generators(\@generators); $me->_gencache({}); return $me; } sub get_indicators { my $self=shift; my $type = shift || 'all'; $type='is_extra' if $type eq 'optional'; $type='is_experimental' if $type eq 'experimental'; my $indicators; if ($self->_gencache->{$type}) { $indicators=$self->_gencache->{$type}; } else { my @aggregators; foreach my $gen (@{$self->generators}) { foreach my $ind (@{$gen->kwalitee_indicators}) { if ($type eq 'all' || ($type eq 'core' && !$ind->{is_extra} && !$ind->{is_experimental}) || $ind->{$type}) { $ind->{defined_in}=$gen; if ($ind->{aggregating}) { push @aggregators, $ind; next; } push(@$indicators,$ind); } } } push @$indicators, @aggregators; $self->_gencache->{$type}=$indicators; } return wantarray ? @$indicators : $indicators; } sub get_indicators_hash { my $self=shift; my $indicators; if ($self->_genhashcache) { $indicators=$self->_genhashcache; } else { foreach my $gen (@{$self->generators}) { foreach my $ind (@{$gen->kwalitee_indicators}) { $ind->{defined_in}=$gen; $indicators->{$ind->{name}}=$ind; } } $self->_genhashcache($indicators); } return $indicators; } sub available_kwalitee { my $self=shift; my $mem=$self->_available; return $mem if $mem; my $available; foreach my $g ($self->get_indicators) { $available++ unless $g->{is_extra} || $g->{is_experimental}; } $self->_available($available); } sub total_kwalitee { my $self=shift; my $mem=$self->_total; return $mem if $mem; my $available; foreach my $g ($self->get_indicators) { $available++ unless $g->{is_experimental}; } $self->_total($available); } sub all_indicator_names { my $self=shift; my @all=map { $_->{name} } $self->get_indicators; return wantarray ? @all : \@all; } sub core_indicator_names { my $self=shift; my @all=map { $_->{name} } grep { !$_->{is_extra} && !$_->{is_experimental} } $self->get_indicators; return wantarray ? @all : \@all; } sub optional_indicator_names { my $self=shift; my @all=map { $_->{name} } grep { $_->{is_extra} } $self->get_indicators; return wantarray ? @all : \@all; } sub experimental_indicator_names { my $self=shift; my @all=map { $_->{name} } grep { $_->{is_experimental} } $self->get_indicators; return wantarray ? @all : \@all; } q{Favourite record of the moment: Jahcoozi: Pure Breed Mongrel}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee - Interface to Kwalitee generators =head1 SYNOPSIS my $mck=Module::CPANTS::Kwalitee->new; my @generators=$mck->generators; =head1 DESCRIPTION =head2 Methods =head3 new Plain old constructor. Loads all Plugins. =head3 get_indicators Get the list of all Kwalitee indicators, either as an ARRAY or ARRAYREF. =head3 get_indicators_hash Get the list of all Kwalitee indicators as an HASHREF. =head3 core_indicator_names Get a list of core indicator names (NOT the whole indicator HASHREF). =head3 optional_indicator_names Get a list of optional indicator names (NOT the whole indicator HASHREF). =head3 experimental_indicator_names Get a list of experimental indicator names (NOT the whole indicator HASHREF). =head3 all_indicator_names Get a list of all indicator names (NOT the whole indicator HASHREF). =head3 available_kwalitee Get the number of available kwalitee points =head3 total_kwalitee Get the total number of kwalitee points. This is bigger the available_kwalitee as some kwalitee metrics are marked as 'extra' (eg is_prereq). =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/0000755000175000017500000000000012434531241022146 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Pod.pm0000644000175000017500000001347212434527337023250 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Pod; use warnings; use strict; use File::Spec::Functions qw/catfile/; use Encode; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic our @ABSTRACT_STUBS = ( q{Perl extension for blah blah blah}, # h2xs q{[One line description of module's purpose here]}, # Module::Starter etc q{The great new}, # Module::Starter q{It's new $module}, # Minilla ); sub order { 100 } ################################################################## # Analyse ################################################################## sub analyse { my ($class, $me) = @_; my $distdir = $me->distdir; my %abstract; my @errors; for my $module (@{$me->d->{modules} || []}) { my ($package, $abstract, $error) = $class->_parse_abstract(catfile($distdir, $module->{file})); push @errors, "$error ($package)" if $error; $me->d->{abstracts_in_pod}{$package} = $abstract if $package; } # sometimes pod for .pm file is put into .pod for my $file (@{$me->d->{files_array} || []}) { next unless $file =~ /\.pod$/ && ($file =~ m!^lib/! or $file =~ m!^[^/]+$!); local $@; my ($package, $abstract, $error) = $class->_parse_abstract(catfile($distdir, $file)); push @errors, "$error ($package)" if $error; $me->d->{abstracts_in_pod}{$package} = $abstract if $package; } $me->d->{error}{has_abstract_in_pod} = join ';', @errors if @errors; } # adapted from ExtUtils::MM_Unix and Module::Build::PodParser sub _parse_abstract { my ($class, $file) = @_; my ($package, $abstract); my $inpod = 0; open my $fh, '<', $file or return; my $directive; my $encoding; while(<$fh>) { if (/^=encoding\s+(.+)/) { $encoding = $1; } if (/^=(?!cut)(.+)/) { $directive = $1; $inpod = 1; } elsif (/^=cut/) { $inpod = 0; } next if !$inpod; next unless $directive =~ /^head/; if ( /^\s*((?:[A-Za-z0-9_]+::)*[A-Za-z0-9_]+ | [BCIF] < (?:[A-Za-z0-9_]+::)*[A-Za-z0-9_]+ >) \s+ -+ (?:\s+ (.*)\s*$|$)/x ) { ($package, $abstract) = ($1, $2); $package =~ s![BCIF]<([^>]+)>!$1!; next; } next unless $abstract; last if /^\s*$/ || /^=/; s/\s+$//s; $abstract .= "\n$_"; } my $error; if ($encoding && $abstract) { my $encoder = find_encoding($encoding); if (!$encoder) { $error = "unknown encoding: $encoding"; } else { $abstract = eval { $encoder->decode($abstract) }; if ($@) { $error = $@; $error =~ s|\s*at .+ line \d+.+$||s; } } } return ($package, $abstract, $error); } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { return [ { name => 'has_abstract_in_pod', error => q{No abstract (short description of a module) is found in pod from this distribution.}, remedy => q{Provide a short description in the NAME section of the pod (after the module name followed by a hyphen) at least for the main module of this distribution.}, code => sub { my $d = shift; return 0 if $d->{error}{has_abstract_in_pod}; my @abstracts = grep {defined $_ && length $_} values %{$d->{abstracts_in_pod} || {}}; return @abstracts ? 1 : 0; }, details => sub { my $d = shift; return "No abstracts in pod"; }, }, { name => 'no_abstract_stub_in_pod', is_extra => 1, error => q{A well-known abstract stub (typically generated by an authoring tool) is found in this distribution.}, remedy => q{Modify the stub. You might need to modify other stubs (for name, synopsis, license, etc) as well.}, code => sub { my $d = shift; my %mapping = map {$_ => 1} @ABSTRACT_STUBS; my @errors; for (sort keys %{$d->{abstracts_in_pod} || {}}) { push @errors, $_ if $mapping{$d->{abstracts_in_pod}{$_} || ''}; } if (@errors) { $d->{error}{no_abstract_stub_in_pod} = join ',', @errors; } return @errors ? 0 : 1; }, details => sub { my $d = shift; my %mapping = map {$_ => 1} @ABSTRACT_STUBS; return "Abstracts in the following packages are stubs:". $d->{error}{no_abstract_stub_in_pod}; }, }, ]; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Pod - Check Pod =head1 SYNOPSIS Some of the check in this module has moved to L to double-check the pod correctness on the server side. If you do care, it is recommended to add a test to test pod (with L) in "xt/" directory in your distribution. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse Parses pod to see if it has a proper abstract. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over 4 =item * has_abstract_in_pod =item * no_abstract_stub_in_pod =back =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Signature.pm0000644000175000017500000000266412434527337024470 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Signature; use strict; use warnings; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 100 } sub analyse { my ($class, $self) = @_; # NOTE: The analysis/metric in this module has moved to # Module::CPANTS::SiteKwalitee because this requires an external # tool (though optional) and decent network connection to # validate a signature. # Note also that this stub should not be removed so that # this can replace the old ::Signature module, and the old # metrics will not be loaded while loading plugins. } sub kwalitee_indicators { return []; } 1; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Signature - dist has a valid signature =head1 SYNOPSIS The metrics in this module have moved to L. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse Does nothing now. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =head1 SEE ALSO L =head1 AUTHOR Lars Dɪᴇᴄᴋᴏᴡ C<< >> =head1 LICENCE AND COPYRIGHT Copyright © 2012, Lars Dɪᴇᴄᴋᴏᴡ C<< >>. This module is free software; you can redistribute it and/or modify it under the same terms as Perl 5.14. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Distname.pm0000644000175000017500000000364712434527337024275 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Distname; use warnings; use strict; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 20 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; # NOTE: The analysis code has moved to ::Analyse to avoid # duplication. # Note also that this stub should not be removed so that # this can replace the old ::Distname module, and the old # metrics will not be loaded while loading plugins. return; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { # NOTE: The metrics in this module have moved to # Module::CPANTS::SiteKwalitee because these require an archived # distribution which you don't have while testing local Kwalitee # with Test::Kwalitee. return []; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Distname - Proper Distname layout =head1 SYNOPSIS The metrics in this module have moved to L. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<20>. =head3 analyse Does nothing now. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =back =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Repackageable.pm0000644000175000017500000000350512434527337025230 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Repackageable; use warnings; use strict; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 900 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; # NOTE: The analysis/metric in this module has moved to # Module::CPANTS::SiteKwalitee. # Note also that this stub should not be removed so that # this can replace the old ::Repackageable module, and the old # metrics will not be loaded while loading plugins. return; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators{ return []; } q{Favourite record of the moment: Lili Allen - Allright, still}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Repackageable - Checks for various signs that make a module packageable =head1 SYNOPSIS The metrics in this module have moved to L. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. =head3 analyse =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =head1 SEE ALSO L =head1 AUTHOR L and L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2009 L Copyright © 2006–2008 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/BrokenInstaller.pm0000644000175000017500000001162612434527337025623 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::BrokenInstaller; use warnings; use strict; use File::Spec::Functions qw(catfile); our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 100 } sub analyse { my $class = shift; my $me = shift; my $distdir = $me->distdir; # inc/Module/Install.pm file my $mi = catfile($distdir, 'inc', 'Module', 'Install.pm'); # Must be okay if not using Module::Install return if not -f $mi; open my $ih, '<', $mi or die "Could not open file '$mi' for checking the bad_installer metric: $!"; my $buf; read $ih, $buf, 100000 or die $!; close $ih; if ($buf =~ /VERSION\s*=\s*("|'|)(\d+|\d*\.\d+(?:_\d+)?)\1/m) { $me->d->{module_install}{version} = my $version = $2; my $non_devel = $version; $non_devel =~ s/_\d+$//; if ($non_devel < 0.61 or $non_devel == 1.04) { $me->d->{module_install}{broken} = 1; } if ($non_devel < 0.89) { my $makefilepl = catfile($distdir, 'Makefile.PL'); return if not -f $makefilepl; open my $ih, '<', $makefilepl or die "Could not open file '$makefilepl' for checking the bad_installer metric: $!"; local $/ = undef; my $mftext = <$ih>; close $ih; return if not defined $mftext; if ($mftext =~ /auto_install/) { $me->d->{module_install}{broken_auto_install} = 1; } else { return; } if ($non_devel < 0.64) { $me->d->{module_install}{broken} = 1; } } } else { # Unknown version (parsing $VERSION failed) $me->d->{module_install}{broken} = 1; } return; } sub kwalitee_indicators { return [ { name=>'no_broken_module_install', error=>q{This distribution uses an obsolete version of Module::Install. Versions of Module::Install prior to 0.61 might not work on some systems at all. Additionally if your Makefile.PL uses the 'auto_install()' feature, you need at least version 0.64. Also, 1.04 is known to be broken.}, remedy=>q{Upgrade the bundled version of Module::Install to the most current release. Alternatively, you can switch to another build system / installer that does not suffer from this problem. (ExtUtils::MakeMaker, Module::Build both of which have their own set of problems.)}, code=>sub { my $d = shift; return 1 unless exists $d->{module_install}; $d->{module_install}{broken} ? 0 : 1; }, details=> sub { q{This distribution uses obsolete Module::Install version }.(shift->{module_install}{version}); }, }, { name=>'no_broken_auto_install', error=>q{This distribution uses an old version of Module::Install. Versions of Module::Install prior to 0.89 do not detect correcty that CPAN/CPANPLUS shell is used.}, remedy=>q{Upgrade the bundled version of Module::Install to at least 0.89, but preferably to the most current release. Alternatively, you can switch to another build system / installer that does not suffer from this problem. (ExtUtils::MakeMaker, Module::Build both of which have their own set of problems.)}, code=>sub { my $d = shift; return 1 unless exists $d->{module_install}; $d->{module_install}{broken_auto_install} ? 0 : 1; }, details=> sub { q{This distribution uses obsolete Module::Install version }.(shift->{module_install}{version}); }, }, ]; } 1 __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::BrokenInstaller - Check for broken Module::Install =head1 SYNOPSIS Find out whether the distribution uses an outdated version of Module::Install. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>, as data generated by this should not be used by any other tests. =head3 analyse C checks whether the distribution uses Module::Install and if so whether it uses a reasonably current version of it (0.61 or later). It also checks whether the F uses the C feature. If so, C should be at least version 0.64. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * no_broken_module_install =item * no_broken_auto_install =back =head1 SEE ALSO L =head1 AUTHOR L L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2009 L Copyright © 2006 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/MetaYML.pm0000644000175000017500000002537412434527337024002 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::MetaYML; use warnings; use strict; use File::Spec::Functions qw(catfile); use CPAN::Meta::YAML; use CPAN::Meta::Validator; use CPAN::Meta::Converter; use JSON::MaybeXS; use List::Util qw/first/; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 10 } my $JSON_CLASS; ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $distdir=$me->distdir; my $meta_yml = catfile($distdir,'META.yml'); my $meta_json = catfile($distdir,'META.json'); my $mymeta_yml = catfile($distdir,'MYMETA.yml'); # META.yml is not always the most preferred meta file, # but test it anyway because it may be broken sometimes. if (-f $meta_yml && -r _) { _analyse_yml($me, $meta_yml); } # check also META.json (if exists). if (-f $meta_json && -r _) { _analyse_json($me, $meta_json); } # If, and only if META.yml and META.json don't exist, # try MYMETA.yml if (!$me->d->{meta_yml} && -f $mymeta_yml && -r _) { _analyse_yml($me, $mymeta_yml); } if (!$me->d->{meta_yml}) { return; } # Theoretically it might be better to convert 1.* to 2.0. # However, converting 2.0 to 1.4 is much cheaper for CPANTS # website as it's much rarer as of this writing. if (($me->d->{meta_yml_spec_version} || '1.0') gt '1.4') { my $cmc = CPAN::Meta::Converter->new($me->d->{meta_yml}); my $meta_14 = eval { $cmc->convert(version => '1.4') }; if (!$@ && $meta_14) { $me->d->{meta_yml} = $meta_14; } } $me->d->{dynamic_config} = $me->d->{meta_yml}{dynamic_config} ? 1 : 0; } sub _analyse_yml { my ($me, $file) = @_; eval { my $meta = CPAN::Meta::YAML->read($file) or die CPAN::Meta::YAML->errstr; # Broken META.yml may return a "YAML 1.0" string first. # eg. M/MH/MHASCH/Date-Gregorian-0.07.tar.gz if (@$meta > 1 or ref $meta->[0] ne ref {}) { $me->d->{meta_yml}=first { ref $_ eq ref {} } @$meta; $me->d->{error}{meta_yml_is_parsable}="multiple parts found in META.yml"; } else { $me->d->{meta_yml}=$meta->[0]; $me->d->{meta_yml_is_parsable}=1; } }; if (my $error = $@) { $error =~ s/ at \S+ line \d+.+$//s; $me->d->{error}{meta_yml_is_parsable}=$error; } if ($me->d->{meta_yml}) { my ($spec, $error) = _validate_meta($me->d->{meta_yml}); $me->d->{error}{meta_yml_conforms_to_known_spec} = $error if $error; $me->d->{meta_yml_spec_version} = $spec->{spec}; } } sub _analyse_json { my ($me, $file) = @_; my $meta; eval { my $json = do { open my $fh, '<', $file or die "$file: $!"; local $/; <$fh> }; $meta = decode_json($json); $me->d->{meta_json_is_parsable} = 1; }; if (my $error = $@) { $error =~ s/ at \S+ line \d+.+$//s; $me->d->{error}{meta_json_is_parsable} = $error; } if ($meta) { my ($spec, $error) = _validate_meta($meta); $me->d->{error}{meta_json_conforms_to_known_spec} = $error if $error; $me->d->{meta_json_spec_version} = $spec->{spec}; } if (!$me->d->{meta_yml}) { $me->d->{meta_yml} = $meta; $me->d->{meta_yml_spec_version} = $me->d->{meta_json_spec_version}; $me->d->{meta_yml_is_meta_json} = 1; } } sub _validate_meta { my $meta = shift; my $error; my $spec = eval { CPAN::Meta::Validator->new($meta) }; if ($error = $@) { $error =~ s/ at \S+ line \d+.+$//s; } elsif (!$spec->is_valid) { $error = join ';', sort $spec->errors; } return ($spec, $error); } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators{ return [ { name=>'meta_yml_is_parsable', error=>q{The META.yml file of this distribution could not be parsed by the version of CPAN::Meta::YAML.pm CPANTS is using.}, remedy=>q{Upgrade your YAML generator so it produces valid YAML.}, code=>sub { my $d = shift; !$d->{error}{meta_yml_is_parsable} ? 1 : 0 }, details=>sub { my $d = shift; $d->{error}{meta_yml_is_parsable}; }, }, { name=>'meta_json_is_parsable', error=>q{The META.json file of this distribution could not be parsed by the version of JSON parser CPANTS is using.}, remedy=>q{Upgrade your META.json generator so it produces valid JSON.}, code=>sub { my $d = shift; !$d->{error}{meta_json_is_parsable} ? 1 : 0 }, details=>sub { my $d = shift; $d->{error}{meta_json_is_parsable}; }, }, { name=>'meta_yml_has_provides', is_experimental=>1, error=>q{This distribution does not have a list of provided modules defined in META.yml.}, remedy=>q{Add all modules contained in this distribution to the META.yml field 'provides'. Module::Build or Dist::Zilla::Plugin::MetaProvides do this automatically for you.}, code=>sub { my $d=shift; return 1 if !$d->{meta_yml}; return 1 if $d->{meta_yml}{provides}; return 0; }, details=>sub { my $d = shift; return "No META.yml." unless $d->{meta_yml}; return q{No "provides" was found in META.yml.}; }, }, { name=>'meta_yml_conforms_to_known_spec', error=>q{META.yml does not conform to any recognised META.yml Spec.}, remedy=>q{Take a look at the META.yml Spec at http://module-build.sourceforge.net/META-spec-v1.4.html (for version 1.4) or http://search.cpan.org/perldoc?CPAN::Meta::Spec (for version 2), and change your META.yml accordingly.}, code=>sub { my $d=shift; return 0 if $d->{error}{meta_yml_conforms_to_known_spec}; return 1; }, details=>sub { my $d = shift; return "No META.yml." unless $d->{meta_yml}; return "META.yml is broken." unless $d->{meta_yml_is_parsable}; return $d->{error}{meta_yml_conforms_to_known_spec}; }, }, { name=>'meta_json_conforms_to_known_spec', error=>q{META.json does not conform to any recognised META Spec.}, remedy=>q{Take a look at the META.json Spec at http://module-build.sourceforge.net/META-spec-v1.4.html (for version 1.4) or http://search.cpan.org/perldoc?CPAN::Meta::Spec (for version 2), and change your META.json accordingly.}, code=>sub { my $d=shift; return 0 if $d->{error}{meta_json_is_parsable}; return 0 if $d->{error}{meta_json_conforms_to_known_spec}; return 1; }, details=>sub { my $d = shift; return "META.json is broken." unless $d->{meta_json_is_parsable}; return $d->{error}{meta_json_conforms_to_known_spec}; }, }, { name=>'meta_yml_declares_perl_version', error=>q{This distribution does not declare the minimum perl version in META.yml.}, is_extra=>1, remedy=>q{If you are using Build.PL define the {requires}{perl} = VERSION field. If you are using MakeMaker (Makefile.PL) you should upgrade ExtUtils::MakeMaker to 6.48 and use MIN_PERL_VERSION parameter. Perl::MinimumVersion can help you determine which version of Perl your module needs.}, code=>sub { my $d=shift; my $yaml=$d->{meta_yml}; return 1 unless $yaml; return ref $yaml->{requires} eq ref {} && $yaml->{requires}{perl} ? 1 : 0; }, details=>sub { my $d = shift; my $yaml = $d->{meta_yml}; return "No META.yml." unless $yaml; return q{No "requires" was found in META.yml.} unless ref $yaml->{requires} eq ref {}; return q{No "perl" subkey was found in META.yml.} unless $yaml->{requires}{perl}; }, }, { name=>'meta_yml_has_repository_resource', is_experimental=>1, error=>q{This distribution does not have a link to a repository in META.yml.}, remedy=>q{Add a 'repository' resource to the META.yml via 'meta_add' accessor (for Module::Build) or META_ADD parameter (for ExtUtils::MakeMaker).}, code=>sub { my $d=shift; my $yaml = $d->{meta_yml}; return 1 unless $yaml; return ref $yaml->{resources} eq ref {} && $yaml->{resources}{repository} ? 1 : 0; }, details=>sub { my $d = shift; my $yaml = $d->{meta_yml}; return "No META.yml." unless $yaml; return q{No "resources" was found in META.yml.} unless ref $yaml->{resources} eq ref {}; return q{No "repository" subkey was found in META.yml.} unless $yaml->{resources}{repository}; }, }, ]; } q{Barbies Favourite record of the moment: Nine Inch Nails: Year Zero}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::MetaYML - Checks data available in META.yml =head1 SYNOPSIS Checks various pieces of information in META.yml =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<10>. MetaYML should be checked earlier than Files to handle no_index correctly. =head3 analyse C checks C. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * meta_yml_is_parsable =item * meta_yml_has_provides =item * meta_yml_conforms_to_known_spec =item * meta_yml_declares_perl_version =item * meta_yml_has_repository_resource =item * meta_json_is_parsable =item * meta_json_conforms_to_known_spec =back =head1 SEE ALSO L =head1 AUTHOR L and L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2009 L Copyright © 2006–2008 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Uses.pm0000644000175000017500000002521212434527337023440 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Uses; use warnings; use strict; use File::Spec::Functions qw(catfile); use Module::ExtractUse 0.33; use Set::Scalar qw(); use version; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic # These equivalents should be reasonably well-known and, preferably, # well-documented. Don't add obscure modules used by only one person # or a few people, to keep the list relatively small and to encourage # people to use a better equivalent. # "use_(strict|warnings)" should fail if someone feels the need # to add "use $1;" in the modules. our @STRICT_EQUIV = qw( strict ); our @WARNINGS_EQUIV = qw( warnings warnings::compat ); our @STRICT_WARNINGS_EQUIV = qw( common::sense Any::Moose Catmandu::Sane Coat Dancer Mo Modern::Perl Moo Moo::Role Moose Moose::Role Moose::Exporter MooseX::Declare MooseX::Role::Parameterized MooseX::Types Mouse Mouse::Role perl5 perl5i::1 perl5i::2 perl5i::latest Role::Tiny strictures ); # These modules require a flag to enforce strictness. push @STRICT_WARNINGS_EQUIV, qw( Mojo::Base Spiffy ); sub order { 100 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $distdir=$me->distdir; my $modules=$me->d->{modules}; my $files=$me->d->{files_hash}; # NOTE: all files in xt/ should be ignored because they are # for authors only and their dependencies may not be (and # often are not) listed in meta files. my @tests=grep {m|^t\b.*\.t|} sort keys %$files; $me->d->{test_files} = \@tests; my @test_modules = map { my $m = $_; $m =~ s|\.pm$||; $m =~ s|^t/(?:lib/)?||; $m =~ s|/|::|g; $m; } grep {m|^t\b.*\.pm$|} keys %$files; my %test_modules = map {$_ => 1} @test_modules; my %skip=map {$_->{module}=>1 } @$modules; my %uses; # used in modules foreach my $module (@$modules) { my $combined = $class->_extract_use($me, $module->{file}); for my $key (keys %$combined) { for my $mod (keys %{$combined->{$key}}) { next if $skip{$mod}; $uses{$key.'_in_code'}{$mod} += $combined->{$key}{$mod}; } } } # used in tests foreach my $tf (@tests) { my $combined = $class->_extract_use($me, $tf); for my $key (keys %$combined) { for my $mod (keys %{$combined->{$key}}) { next if $mod =~ /^t::/; next if $skip{$mod}; next if $test_modules{$mod}; $uses{$key.'_in_tests'}{$mod} += $combined->{$key}{$mod}; } } } # used in Makefile.PL/Build.PL foreach my $f (grep /\b(?:Makefile|Build)\.PL$/, @{$me->d->{files_array} || []}) { my $combined = $class->_extract_use($me, $f); for my $key (keys %$combined) { for my $mod (keys %{$combined->{$key}}) { next if $skip{$mod}; $uses{$key.'_in_config'}{$mod} += $combined->{$key}{$mod}; } } } $me->d->{uses}=\%uses; return; } sub _extract_use { my ($class, $me, $path) = @_; my $file = catfile($me->distdir, $path); $file =~ s|\\|/|g; return unless -f $file; my $p = Module::ExtractUse->new; $p->extract_use($file); # used actually contains required/noed my %used = %{ $p->used || {} }; my %required = %{ $p->required || {} }; my %noed = %{ $p->noed || {} }; my %combined; for my $mod (keys %used) { next if $mod =~ /::$/; # see RT#35092 next unless $mod =~ /^(?:v?5\.[0-9.]+|[A-za-z0-9:_]+)$/; $combined{used}{$mod} += $used{$mod}; if (my $used_in_eval = $p->used_in_eval($mod)) { $combined{used_in_eval}{$mod} += $used_in_eval; $combined{used}{$mod} -= $used_in_eval; } if ($required{$mod}) { $combined{used}{$mod} -= $required{$mod}; $combined{required}{$mod} += $required{$mod}; if (my $required_in_eval = $p->required_in_eval($mod)) { $combined{used}{$mod} += $required_in_eval; $combined{used_in_eval}{$mod} -= $required_in_eval; $combined{required}{$mod} -= $required_in_eval; $combined{required_in_eval}{$mod} += $required_in_eval; } } if ($noed{$mod}) { $combined{used}{$mod} -= $noed{$mod}; $combined{noed}{$mod} += $noed{$mod}; if (my $noed_in_eval = $p->noed_in_eval($mod)) { $combined{used}{$mod} += $noed_in_eval; $combined{used_in_eval}{$mod} -= $noed_in_eval; $combined{noed}{$mod} -= $noed_in_eval; $combined{noed_in_eval}{$mod} += $noed_in_eval; } } for (qw/used used_in_eval required noed/) { delete $combined{$_}{$mod} unless $combined{$_}{$mod}; } } for my $key (keys %combined) { next unless %{$combined{$key}}; $me->d->{files_hash}{$path}{$key} = [sort keys %{$combined{$key}}]; } return \%combined; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { return [ { name=>'use_strict', error=>q{This distribution does not 'use strict;' (or its equivalents) in all of its modules. Note that this is not about the actual strictness of the modules. It's bad if nobody can tell whether the modules are strictly written or not, without reading the source code of your favorite clever module that actually enforces strictness. In other words, it's bad if someone feels the need to add 'use strict' to your modules.}, remedy=>q{Add 'use strict' (or its equivalents) to all modules, or convince us that your favorite module is well-known enough and people can easily see the modules are strictly written.}, ignorable => 1, code=>sub { my $d = shift; my $files = $d->{files_hash} || {}; # There are lots of acceptable strict alternatives my $strict_equivalents = Set::Scalar->new->insert(@STRICT_EQUIV, @STRICT_WARNINGS_EQUIV); my $perl_version_with_implicit_stricture = version->new('5.011')->numify; my @no_strict; for my $file (keys %$files) { next unless exists $files->{$file}{module}; next if $files->{$file}{unreadable}; next if $file =~ /\.pod$/; my $module = $files->{$file}{module}; my %used; for my $key (qw/used required/) { next unless exists $files->{$file}{$key}; $used{$_} = 1 for @{$files->{$file}{$key} || []}; } next if grep {/^v?5\./ && version->parse($_)->numify >= $perl_version_with_implicit_stricture} keys %used; push @no_strict, $module if $strict_equivalents ->intersection(Set::Scalar->new(keys %used)) ->is_empty; } if (@no_strict) { $d->{error}{use_strict} = join ", ", @no_strict; return 0; } return 1; }, details=>sub { my $d = shift; return "The following modules don't use strict (or equivalents): " . $d->{error}{use_strict}; }, }, { name=>'use_warnings', error=>q{This distribution does not 'use warnings;' (or its equivalents) in all of its modules. Note that this is not about that your modules actually warn when something bad happens. It's bad if nobody can tell if a module warns or not, without reading the source code of your favorite module that actually enforces warnings. In other words, it's bad if someone feels the need to add 'use warnings' to your modules.}, is_extra=>1, ignorable => 1, remedy=>q{Add 'use warnings' (or its equivalents) to all modules (this will require perl > 5.6), or convince us that your favorite module is well-known enough and people can easily see the modules warn when something bad happens.}, code=>sub { my $d = shift; my $files = $d->{files_hash} || {}; my $warnings_equivalents = Set::Scalar->new->insert(@WARNINGS_EQUIV, @STRICT_WARNINGS_EQUIV); my @no_warnings; for my $file (keys %$files) { next unless exists $files->{$file}{module}; next if $files->{$file}{unreadable}; next if $file =~ /\.pod$/; my $module = $files->{$file}{module}; my %used; for my $key (qw/used required/) { next unless exists $files->{$file}{$key}; $used{$_} = 1 for @{$files->{$file}{$key} || []}; } push @no_warnings, $module if $warnings_equivalents ->intersection(Set::Scalar->new(keys %used)) ->is_empty; } if (@no_warnings) { $d->{error}{use_warnings} = join ", ", @no_warnings; return 0; } return 1; }, details=>sub { my $d = shift; return "The following modules don't use warnings (or equivalents): " . $d->{error}{use_warnings}; }, }, ]; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Uses - Checks which modules are used =head1 SYNOPSIS Check which modules are actually used in the code. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse C uses C to find all C statements in code (actual code and tests). =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * use_strict =item * use_warnings =back =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Prereq.pm0000644000175000017500000002553712434527337023771 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Prereq; use warnings; use strict; use File::Spec::Functions qw(catfile); use Text::Balanced qw/extract_bracketed/; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 100 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; $class->_from_meta($me) or $class->_from_cpanfile($me) or $class->_from_build_pl($me) or $class->_from_makefile_pl($me) or $class->_from_dist_ini($me); } sub _from_meta { my ($class, $me) = @_; my $meta = $me->d->{meta_yml}; return unless $meta && ref $meta eq ref {}; my $spec = $meta->{'meta-spec'}; my %res; if ($spec && ref $spec eq ref {} && ($spec->{version} || 0) =~ /^(\d+)/ && $1 >= 2) { # meta spec ver2 my $prereqs = $meta->{prereqs}; %res = $class->_handle_prereqs_v2($meta->{prereqs}); } else { # meta spec ver1 my %map = ( requires => 'is_prereq', build_requires => 'is_build_prereq', recommends => 'is_optional_prereq', ); for my $rel (qw/requires recommends build_requires configure_requires conflicts/) { if ($meta->{$rel} && ref $meta->{$rel} eq ref {}) { my $prereqs_r = $meta->{$rel}; next unless $prereqs_r && ref $prereqs_r eq ref {}; for my $module (keys %$prereqs_r) { my $type = $rel =~ /_/ ? $rel : "runtime_$rel"; push @{$res{$module} ||= []}, { requires => $module, version => $prereqs_r->{$module}, type => $type, ($map{$rel} ? ($map{$rel} => 1) : ()), }; } } } # TODO: optional_features handling } return unless %res; $me->d->{prereq} = [map {@$_} values %res]; $me->d->{got_prereq_from} = 'META.yml'; } sub _from_cpanfile { my ($class, $me) = @_; my $cpanfile = catfile($me->distdir, "cpanfile"); return unless -f $cpanfile; eval { require Module::CPANfile; 1 }; return if $@; my $prereqs = Module::CPANfile->load($cpanfile)->prereqs->as_string_hash; my %res = $class->_handle_prereqs_v2($prereqs); return unless %res; $me->d->{prereq} = [map {@$_} values %res]; $me->d->{got_prereq_from} = 'cpanfile'; } sub _from_build_pl { my ($class, $me) = @_; my $build_pl_file = catfile($me->distdir, "Build.PL"); return unless -f $build_pl_file; my $build_pl = do { local $/; open my $fh, '<', $build_pl_file; <$fh> }; return unless $build_pl; my %map = ( requires => 'is_prereq', build_requires => 'is_build_prereq', test_requires => 'is_build_prereq', recommends => 'is_optional_prereq', ); my %res; # TODO: auto_features while($build_pl =~ s/^.*?((?:(?:configure|build|test)_)?requires|recommends|conflicts)\s*=>\s*\{/{/s) { my $rel = $1; my ($block, $left) = extract_bracketed($build_pl, '{}'); last unless $block; my $hashref = do { no strict; no warnings; eval $block }; ## no critic if ($hashref && ref $hashref eq ref {}) { for my $module (keys %$hashref) { my $type = $rel =~ /_/ ? $rel : "runtime_$rel"; my ($version) = ($hashref->{$module} || 0) =~ /^([0-9.]+)/; push @{$res{$module} ||= []}, { requires => $module, version => $version, type => $type, ($map{$rel} ? ($map{$rel} => 1) : ()), }; } } $build_pl = $left; } $me->d->{prereq} = [map {@$_} values %res]; $me->d->{got_prereq_from} = 'Build.PL'; } sub _from_makefile_pl { my ($class, $me) = @_; my $distdir = $me->distdir; my %map = ( PREREQ_PM => 'is_prereq', BUILD_REQUIRES => 'is_build_prereq', TEST_REQUIRES => 'is_build_prereq', ); # There may be multiple Makefile.PLs in a distribution my %res; for my $file (@{$me->d->{files_array} || []}) { next unless $file =~ /Makefile\.PL$/; my $makefile_pl_file = catfile($distdir, $file); next unless -f $makefile_pl_file; my $makefile_pl = do { local $/; open my $fh, '<', $makefile_pl_file; <$fh> }; next unless $makefile_pl; if ($makefile_pl =~ /use\s+inc::Module::Install/) { # Module::Install # TODO while($makefile_pl =~ s/(?:^|;).+?((?:(?:configure|build|test)_)?requires|recommends)\s*([^;]+);//s) { my ($rel, $tuple_text) = ($1, $2); my @tuples = do { no strict; no warnings; eval $tuple_text }; ## no critic my $type = $rel =~ /_/ ? $rel : "runtime_$rel"; while(@tuples) { my $module = shift @tuples or last; my $version = shift @tuples || 0; push @{$res{$module} ||= []}, { requires => $module, version => $version, type => $type, ($map{$rel} ? ($map{$rel} => 1) : ()), }; } } } else { # EUMM while($makefile_pl =~ s/^.*?((?:BUILD|TEST)_REQUIRES|PREREQ_PM)\s*=>\s*\{/{/s) { my $rel = $1; my ($block, $left) = extract_bracketed($makefile_pl, '{}'); last unless $block; my $hashref = do { no strict; no warnings; eval $block }; ## no critic if ($hashref && ref $hashref eq ref {}) { for my $module (keys %$hashref) { my $type = $rel eq 'PREREQ_PM' ? "runtime_requires" : lc $rel; push @{$res{$module} ||= []}, { requires => $module, version => $hashref->{$module}, type => $type, ($map{$rel} ? ($map{$rel} => 1) : ()), }; } } $makefile_pl = $left; } } } $me->d->{prereq} = [map {@$_} values %res]; $me->d->{got_prereq_from} = 'Makefile.PL'; } # for META spec v2 and cpanfile sub _handle_prereqs_v2 { my ($class, $prereqs) = @_; return unless $prereqs && ref $prereqs eq ref {}; # XXX: this mapping is for backward compat only my %map = ( runtime_requires => 'is_prereq', build_requires => 'is_build_prereq', test_requires => 'is_build_prereq', runtime_recommends => 'is_optional_prereq', build_recommends => 'is_optional_prereq', test_recommends => 'is_optional_prereq', runtime_suggests => 'is_optional_prereq', build_suggests => 'is_optional_prereq', test_suggests => 'is_optional_prereq', ); my %res; for my $phase (keys %$prereqs) { my $prereqs_p = $prereqs->{$phase}; next unless $prereqs_p && ref $prereqs_p eq ref {}; for my $rel (keys %$prereqs_p) { my $prereqs_r = $prereqs_p->{$rel}; next unless $prereqs_r && ref $prereqs_r eq ref {}; for my $module (keys %$prereqs_r) { my $type = join '_', $phase, $rel; push @{$res{$module} ||= []}, { requires => $module, version => $prereqs_r->{$module}, type => $type, ($map{$type} ? ($map{$type} => 1) : ()), }; } } } %res; } sub _from_dist_ini { my ($class, $me) = @_; my $inifile = catfile($me->distdir, "dist.ini"); return unless -f $inifile; eval { require Config::INI::Reader } or return; my $config = Config::INI::Reader->read_file($inifile); return unless $config && ref $config eq ref {}; my %map = ( runtime_requires => 'is_prereq', build_requires => 'is_build_prereq', test_requires => 'is_build_prereq', runtime_recommends => 'is_optional_prereq', build_recommends => 'is_optional_prereq', test_recommends => 'is_optional_prereq', runtime_suggests => 'is_optional_prereq', build_suggests => 'is_optional_prereq', test_suggests => 'is_optional_prereq', ); my %res; for my $key (keys %$config) { next unless $key =~ /^Prereqs\b/; my ($phase, $rel) = qw(runtime requires); (undef, my $type) = split /\s*\/\s*/, $key, 2; if ($type) { if ($type =~ s/^(Configure|Build|Test|Runtime)//) { $phase = lc $1; } if ($type =~ s/^(Requires|Recommends|Suggests)//) { $rel = lc $1; } } my $conf = $config->{$key}; next unless $conf && ref $conf eq ref {}; if ($conf->{-phase}) { $phase = delete $conf->{-phase}; } if ($conf->{-relationship}) { $rel = delete $conf->{-relationship}; } for my $module (keys %$conf) { $type = join '_', $phase, $rel; push @{$res{$module} ||= []}, { requires => $module, version => $conf->{$module}, type => $type, ($map{$type} ? ($map{$type} => 1) : ()), }; } } $me->d->{prereq} = [map {@$_} values %res]; $me->d->{got_prereq_from} = 'dist.ini'; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators{ # NOTE: The metrics in this module have moved to # Module::CPANTS::SiteKwalitee because these require databases. return []; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Prereq - Checks listed prerequisites =head1 SYNOPSIS The metrics in this module have moved to L. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse Find information on prerequisite distributions from meta files etc. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/FindModules.pm0000644000175000017500000001434512434527337024737 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::FindModules; use warnings; use strict; use File::Spec::Functions qw(catfile); our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 30 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $files=$me->d->{files_array} || []; if ($me->d->{meta_yml} && $me->d->{meta_yml}{provides}) { my $provides = $me->d->{meta_yml}{provides}; while (my ($module,$data)=each %$provides) { next unless ref $data eq ref {}; # ignore wrong format my $file=$data->{file} || ''; my $found={ module=>$module, file=>$file, in_basedir=>0, in_lib=>0, }; my $loc; if ($file=~/^lib\W/) { $found->{in_lib}=1; } elsif ($file !~/\//) { $found->{in_basedir}=1; } push(@{$me->d->{modules}},$found); if (exists $me->d->{files_hash}{$file}) { $me->d->{files_hash}{$file}{module} = $module; } } } else { my %in_basedir= map {$_=>1} grep {/^[^\/]+\.pm$/} @$files; foreach my $file (@$files) { next unless $file=~/\.pm$/; next if $file=~m{^x?t/}; next if $file=~m{^test/}; next if $file=~m/^(bin|scripts?|ex|eg|examples?|samples?|demos?)\/\w/i; next if $file=~m{^inc/}; # skip Module::Install stuff next if $file=~m{^(local|perl5|fatlib)/}; # proper file in lib/ if ($file=~m|^lib/(.*)\.pm$|) { my $module=$1; $module=~s|/|::|g; push (@{$me->d->{modules}},{ module=>$module, file=>$file, in_basedir=>0, in_lib=>1, }); $me->d->{files_hash}{$file}{module} = $module; } else { # open file and find first package my $module; my $max_lines_to_look_at=666; open (my $fh,"<",catfile($me->distdir,$file)) || die "__PACKAGE__: Cannot open $file to find package declaration: $!"; while (my $line = <$fh>) { next if $line =~/^\s*#/; # ignore comments if ($line =~/^\s*package\s*(.*?)\s*;/) { $module=$1; last; } last if $line =~/^__(DATA|END)__/; $max_lines_to_look_at--; last unless $max_lines_to_look_at; } # try to guess from filename unless ($module) { $file=~m|(.*)\.pm$|; $module=$1; $module=~s|^[a-z]+/||; # remove lowercase prefixes which most likely are not part of the distname (but something like 'src/') $module=~s|/|::|g; } if ($module) { push(@{$me->d->{modules}}, { module=>$module, file=>$file, in_basedir=> $in_basedir{$file} ? 1 : 0, in_lib=>0, }); $me->d->{files_hash}{$file}{module} = $module; } } } } for my $file (keys %{$me->d->{files_hash}}) { next unless $file =~ /^inc\/(.+)\.pm/; my $module = $1; $module =~ s|/|::|g; push @{$me->d->{included_modules} ||= []}, $module; } return 1; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { return [ { name=>'proper_libs', error=>q{There is more than one .pm file in the base dir, or the .pm files are not in lib/ directory.}, remedy=>q{Move your *.pm files in a directory named 'lib'. The directory structure should look like 'lib/Your/Module.pm' for a module named 'Your::Module'.}, is_extra => 1, code=>sub { my $d=shift; my @modules = @{$d->{modules} || []}; return 1 unless @modules; my @not_in_lib = grep { !$_->{in_lib} } @modules; return 1 unless @not_in_lib; my @in_basedir=grep { $_->{in_basedir} } @not_in_lib; return 1 if @in_basedir == 1; $d->{error}{proper_libs} = join ', ', map {$_->{file}} @not_in_lib; return 0; }, details=>sub { my $d = shift; my @modules = @{$d->{modules} || []}; return "No modules were found" unless @modules; return "The following files were found: ".$d->{error}{proper_libs}; }, }, ]; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::FindModules - Find modules provided by a dist =head1 SYNOPSIS Finds and reports all modules (i.e. F<*.pm> files) in a distribution. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<30>, as data generated by C is used by other tests. =head3 analyse C first looks in C and F for C<*.pm> files. If it doesn't find any, it looks in the whole dist, but the C kwalitee point is only awarded if the modules are F or there's only one module in C. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * proper_libs =back =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Manifest.pm0000644000175000017500000000756112434527337024276 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Manifest; use warnings; use strict; use File::Spec::Functions qw(catfile); use Array::Diff; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 100 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $distdir=$me->distdir; my $manifest_file=catfile($distdir,'MANIFEST'); if (-e $manifest_file) { # read manifest open(my $fh, '<', $manifest_file) || die "cannot read MANIFEST $manifest_file: $!"; my @manifest; while (<$fh>) { chomp; next if /^\s*#/; # discard pure comments if (s/^'(\\[\\']|.+)+'\s*.*/$1/) { s/\\([\\'])/$1/g; } else { s/\s.*$//; } # strip quotes and comments next unless $_; # discard blank lines push(@manifest,$_); } close $fh; @manifest=sort @manifest; my @files=sort keys %{$me->d->{files_hash} || {}}; my $diff=Array::Diff->diff(\@manifest,\@files); if ($diff->count == 0) { $me->d->{manifest_matches_dist}=1; } else { $me->d->{manifest_matches_dist}=0; my @error = ( 'MANIFEST ('.@manifest.') does not match dist ('.@files."):", "Missing in MANIFEST: ".join(', ',@{$diff->added}), "Missing in Dist: " . join(', ',@{$diff->deleted})); $me->d->{error}{manifest_matches_dist} = \@error; } # Tweak symlinks error for a local distribution (RT #97858) if ($me->d->{is_local_distribution} && $me->d->{error}{symlinks}) { my %manifested = map {$_ => 1} @manifest; my @symlinks = grep {$manifested{$_}} split ',', $me->d->{error}{symlinks}; if (@symlinks) { $me->d->{error}{symlinks} = join ',', @symlinks; } else { delete $me->d->{error}{symlinks}; } } } else { $me->d->{manifest_matches_dist}=0; $me->d->{error}{manifest_matches_dist}=q{Cannot find MANIFEST in dist.}; } } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { return [ { name=>'manifest_matches_dist', error=>q{MANIFEST does not match the contents of this distribution.}, remedy=>q{Run a proper command ("make manifest" or "./Build manifest", maybe with a force option), or use a distribution builder to generate the MANIFEST. Or update MANIFEST manually.}, code=>sub { shift->{manifest_matches_dist} ? 1 : 0 }, details=>sub { my $d = shift; my $error = $d->{error}{manifest_matches_dist}; return $error unless ref $error; return join "\n", @$error; }, } ]; } q{Listening to: YAPC::Europe 2007}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Manifest - Check MANIFEST =head1 SYNOPSIS Check if MANIFEST and dist contents match. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse Check if MANIFEST and dist contents match. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * manifest_matches_dist =back =head1 SEE ALSO L =head1 AUTHOR Thomas Klausner, , http://domm.plix.at =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/License.pm0000644000175000017500000002165512434527337024112 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::License; use warnings; use strict; use File::Spec::Functions qw(catfile); use Software::LicenseUtils; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 100 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $distdir=$me->distdir; # check META.yml my $yaml=$me->d->{meta_yml}; $me->d->{license} = ''; if ($yaml) { if ($yaml->{license} and $yaml->{license} ne 'unknown') { $me->d->{license_from_yaml} = $yaml->{license}; $me->d->{license} = $yaml->{license}.' defined in META.yml'; } } # use "files_array" to exclude files listed in "no_index". my $files = $me->d->{files_array} || []; # check if there's a LICEN[CS]E file if (my ($file) = grep {$_ =~ /^(?:LICEN[CS]E|COPYING)$/} @$files) { $me->d->{license} .= " defined in $file"; $me->d->{external_license_file}=$file; } # check pod my %licenses; foreach my $file (grep { /\.p(m|od|l)$/ } sort @$files ) { my $path = catfile($distdir, $file); next unless -r $path; # skip if not readable open my $fh, '<', $path or next; my $in_pod = 0; my $pod = ''; my $pod_head = ''; my @possible_licenses; my @unknown_license_texts; while(<$fh>) { if (/^=head\d\s+.*\b(?i:LICEN[CS]E|LICEN[CS]ING|COPYRIGHT|LEGAL)\b/) { $me->d->{license_in_pod} = 1; $me->d->{license} ||= "defined in POD ($file)"; if ($in_pod) { my @guessed = Software::LicenseUtils->guess_license_from_pod("=head1 LICENSE\n$pod\n\n=cut\n"); if (@guessed) { push @possible_licenses, @guessed; } else { push @unknown_license_texts, "$pod_head$pod"; } } $in_pod = 1; $pod_head = $_; $pod = ''; } elsif (/^=(?:head\d\s+|cut)\b/) { if ($in_pod) { my @guessed = Software::LicenseUtils->guess_license_from_pod("=head1 LICENSE\n$pod\n\n=cut\n"); if (@guessed) { push @possible_licenses, @guessed; } else { push @unknown_license_texts, "$pod_head$pod"; } } $in_pod = 0; $pod = ''; } elsif ($in_pod) { $pod .= $_; } } if ($pod) { my @guessed = Software::LicenseUtils->guess_license_from_pod("=head1 LICENSE\n$pod\n\n=cut\n"); if (@guessed) { push @possible_licenses, @guessed; } else { push @unknown_license_texts, "$pod_head$pod"; } } if (@possible_licenses) { @possible_licenses = map { s/^Software::License:://; $_ } @possible_licenses; push @{$licenses{$_} ||= []}, $file for @possible_licenses; $me->d->{files_hash}{$file}{license} = join ',', @possible_licenses; } else { $me->d->{unknown_license_texts}{$file} = join "\n", @unknown_license_texts if @unknown_license_texts; } } if (%licenses) { $me->d->{licenses} = \%licenses; my @possible_licenses = keys %licenses; if (@possible_licenses == 1) { my ($type) = @possible_licenses; $me->d->{license_type} = $type; $me->d->{license_file} = join ',', @{$licenses{$type}}; } } return; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators{ return [ { name=>'meta_yml_has_license', error=>q{This distribution does not have a license defined in META.yml.}, remedy=>q{Define the license if you are using in Build.PL. If you are using MakeMaker (Makefile.PL) you should upgrade to ExtUtils::MakeMaker version 6.31.}, is_extra=>1, code=>sub { my $d=shift; my $yaml=$d->{meta_yml}; ($yaml->{license} and $yaml->{license} ne 'unknown') ? 1 : 0 }, details=>sub { my $d = shift; my $yaml = $d->{meta_yml}; return "No META.yml." unless $yaml; return "No license was found in META.yml." unless $yaml->{license}; return "Unknown license was found in META.yml."; }, }, { name=>'has_human_readable_license', error=>q{This distribution does not have a license defined in the documentation or in a file called LICENSE}, remedy=>q{Add a section called "LICENSE" to the documentation, or add a file named LICENSE to the distribution.}, code=>sub { my $d = shift; return $d->{external_license_file} || $d->{license_in_pod} ? 1 : 0; }, details=>sub { my $d = shift; return "Neither LICENSE file nor LICENSE section in pod was found."; }, }, { name=>'has_separate_license_file', error=>q{This distribution does not have a LICENSE or LICENCE file in its root directory.}, remedy=>q{This is not a critical issue. Currently mainly informative for the CPANTS authors. It might be removed later.}, is_experimental=>1, code=>sub { shift->{external_license_file} ? 1 : 0 }, details=>sub { my $d = shift; return "LICENSE file was found."; }, }, { name=>'has_license_in_source_file', error=>q{Does not have license information in any of its source files}, remedy=>q{Add =head1 LICENSE and the text of the license to the main module in your code.}, code=>sub { my $d = shift; return $d->{license_in_pod} ? 1 : 0; }, details=>sub { my $d = shift; return "LICENSE section was not found in the pod."; }, }, { name=>'has_known_license_in_source_file', error=>q{Does not have license information in any of its source files, or the information is not recognized by Software::License}, remedy=>q{Add =head1 LICENSE and/or the proper text of the well-known license to the main module in your code.}, is_extra => 1, code=>sub { my $d = shift; return 0 unless $d->{license_in_pod}; my @files_with_licenses = grep {$d->{files_hash}{$_}{license}} keys %{$d->{files_hash}}; return @files_with_licenses ? 1 : 0; }, details=>sub { my $d = shift; return "LICENSE section was not found in the pod, or the license information was not recognized by Software::License."; }, }, ]; } q{Favourite record of the moment: Lili Allen - Allright, still}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::License - Checks if there is a license =head1 SYNOPSIS Checks if the distribution specifies a license. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse C checks if there's a C field C. Additionally, it looks for a file called LICENSE and a POD section named LICENSE =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * meta_yml_has_license =item * has_known_license_in_source_file =item * has_license_in_source_file =item * has_human_readable_license =item * has_separate_license_file =back =head2 License information Places where the license information is taken from: Has a LICENSE file file_license 1|0 Content of LICENSE file matches License X from Software::License License in META.yml License in META.yml matches one of the known licenses License in source files recognized by Software::LicenseUtils For each file keep where is was it recognized. Has license or copyright entry in pod (that might not be recognized by Software::LicenseUtils) # has_license =head1 SEE ALSO L =head1 AUTHOR L and L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2009 L Copyright © 2006–2008 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Distros.pm0000644000175000017500000000421412434527337024147 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Distros; use warnings; use strict; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 800 } ################################################################## # Analyse ################################################################## my $debian; sub analyse { my $class=shift; my $me=shift; # NOTE: The data source of these debian metrics has not been # updated for more than a year, and mirroring stuff from # external source every time you test is very nasty. # These metrics are deprecated and actually removed to # reduce unwanted dependencies for Test::Kwalitee users. # Note also that this stub should not be removed so that # this can replace the old ::Distro module, and the old # metrics will not be loaded while loading plugins. return; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators{ return []; } q{Favourite record of the moment: Lili Allen - Allright, still}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Distros - Information retrieved from the various Linux and other distributions =head1 SYNOPSIS The metrics here were based on data provided by the various downstream packaging systems, but are deprecated now. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. =head3 analyse Does nothing now. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =head1 SEE ALSO L =head1 AUTHOR L and L with the help of Martín Ferrari and the L. =head1 COPYRIGHT AND LICENSE Copyright © 2003–2009 L Copyright © 2006–2008 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Files.pm0000644000175000017500000003111012434527337023555 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Files; use warnings; use strict; use File::Find::Object; use File::Spec::Functions qw(catfile); use File::stat; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 15 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $distdir=$me->distdir; $distdir =~ s|\\|/|g if $^O eq 'MSWin32'; # Respect no_index if possible my $no_index_re = $class->_make_no_index_regex($me); my (%files, %dirs); my (@files_array, @dirs_array); my $size = 0; my $latest_mtime = 0; my @base_dirs; my $finder = File::Find::Object->new({ depth => 1, }, $distdir); while(defined(my $name = $finder->next)) { $name =~ s|\\|/|g if $^O eq 'MSWin32'; (my $path = $name) =~ s!^\Q$distdir\E(?:/|$)!! or next; next if $path eq ''; if (-d $name) { $dirs{$path} ||= {}; if (-l $name) { $dirs{$path}{symlink} = 1; } push @dirs_array, $path; next; } if ($me->d->{is_local_distribution}) { next if $path =~ m!/\.!; } if (my $stat = stat($name)) { $files{$path}{size} = $stat->size || 0; $size += $files{$path}{size}; my $mtime = $files{$path}{mtime} = $stat->mtime; $latest_mtime = $mtime if $mtime > $latest_mtime; } else { $files{$path}{stat_error} = $!; next; } if (-l $name) { $files{$path}{symlink} = 1; } if (!-r $name) { $files{$path}{unreadable} = 1; next; } if ($no_index_re && $path =~ qr/$no_index_re/) { $files{$path}{no_index} = 1; next; } # ignore files in dot directories (probably VCS stuff) next if $path =~ m!(?:^|/)\.[^/]+/!; push @files_array, $path; # distribution may have several Makefile.PLs, thus # several 'lib' or 't' directories to care if ($path =~ m!/Makefile\.PL$! && $path !~ m!(^|/)x?t/!) { (my $dir = $path) =~ s|/[^/]+$||; push @base_dirs, $dir; } } $me->d->{size_unpacked}=$size; $me->d->{latest_mtime}=$latest_mtime; my @symlinks = sort {$a cmp $b} ( grep({ $files{$_}{symlink} } keys %files), grep({ $dirs{$_}{symlink} } keys %dirs) ); if (@symlinks) { $me->d->{error}{symlinks} = join ',', @symlinks; } $me->d->{base_dirs} = \@base_dirs if @base_dirs; my $base_dirs_re = join '|', '', map {quotemeta "$_/"} @base_dirs; # find special files/dirs my @special_files=(qw(Makefile.PL Build.PL META.yml META.json MYMETA.yml MYMETA.json dist.ini cpanfile SIGNATURE MANIFEST test.pl LICENSE LICENCE)); my @special_dirs=(qw(lib t xt)); my %special_files_re=( file_changelog=>qr{^(?:$base_dirs_re)(?:chang|history)}i, file_readme=>qr{^(?:$base_dirs_re)readme(?:\.(?:txt|md|pod))?}i, ); for my $base_dir ('', @base_dirs) { $base_dir = "$base_dir/" if $base_dir; for my $name (@special_files) { my $file = "$base_dir$name"; if (exists $files{$file}) { (my $key = "file_".lc $name) =~ s/\./_/; $me->d->{$key} = $me->d->{$key} ? "$me->d->{$key},$file" : $file; } } for my $name (@special_dirs) { my $dir = "$base_dir$name"; if (exists $dirs{$dir}) { my $key = "dir_$name"; $me->d->{$key} = $me->d->{$key} ? "$me->d->{$key},$dir" : $dir; } } } for my $file (keys %files) { next unless $file =~ m!^(?:$base_dirs_re)[^/]+$!; while(my ($key, $re) = each %special_files_re) { if ($file =~ /$re/) { $me->d->{$key} = $me->d->{$key} ? $me->d->{$key}.",$file" : $file; } } } # store stuff $me->d->{files}=scalar @files_array; $me->d->{files_array}=\@files_array; $me->d->{files_hash}=\%files; $me->d->{dirs}=scalar @dirs_array; $me->d->{dirs_array}=\@dirs_array; my @ignored = grep {$files{$_}{no_index}} sort keys %files; $me->d->{ignored_files_array}=\@ignored if @ignored; # check STDIN in Makefile.PL and Build.PL # objective: convince people to use prompt(); # http://www.perlfoundation.org/perl5/index.cgi?cpan_packaging for my $type (qw/makefile_pl build_pl/) { for my $path (split ',', $me->d->{"file_$type"} || '') { next unless $path; my $file = catfile($me->distdir,$path); next if not -e $file; open my $fh, '<', $file or next; my $content = do { local $/; <$fh> } or next; $me->d->{"stdin_in_$type"} = 1 if $content =~ //; } } return; } sub _make_no_index_regex { my ($class, $me) = @_; my $meta = $me->d->{meta_yml}; return unless $meta && ref $meta eq ref {}; my $no_index = $meta->{no_index} || $meta->{private}; return unless $no_index && ref $no_index eq ref {}; my %map = ( file => '\z', directory => '/', ); my @ignore; for my $type (qw/file directory/) { next unless $no_index->{$type}; my $rest = $map{$type}; my @entries = ref $no_index->{$type} eq ref [] ? @{ $no_index->{$type} } : ( $no_index->{$type} ); push @ignore, map {"^$_$rest"} @entries; } return unless @ignore; $me->d->{no_index} = join ';', sort @ignore; return '(?:' . (join '|', @ignore) . ')'; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { return [ { name=>'has_readme', error=>q{The file "README" is missing from this distribution. The README provides some basic information to users prior to downloading and unpacking the distribution.}, remedy=>q{Add a README to the distribution. It should contain a quick description of your module and how to install it.}, code=>sub { shift->{file_readme} ? 1 : 0 }, details=>sub { my $d = shift; return "README was not found."; }, }, { name=>'has_manifest', error=>q{The file "MANIFEST" is missing from this distribution. The MANIFEST lists all files included in the distribution.}, remedy=>q{Add a MANIFEST to the distribution. Your buildtool should be able to autogenerate it (eg "make manifest" or "./Build manifest")}, code=>sub { shift->{file_manifest} ? 1 : 0 }, details=>sub { my $d = shift; return "MANIFEST was not found."; }, }, { name=>'has_meta_yml', error=>q{The file "META.yml" is missing from this distribution. META.yml is needed by people maintaining module collections (like CPAN), for people writing installation tools, or just people who want to know some stuff about a distribution before downloading it.}, remedy=>q{Add a META.yml to the distribution. Your buildtool should be able to autogenerate it.}, code=>sub { my $d = shift; return 1 if $d->{file_meta_yml}; return 1 if $d->{is_local_distribution} && $d->{file_mymeta_yml}; return 0; }, details=>sub { my $d = shift; return "META.yml was not found."; }, }, { name=>'has_buildtool', error=>q{Makefile.PL and/or Build.PL are missing. This makes installing this distribution hard for humans and impossible for automated tools like CPAN/CPANPLUS/cpanminus.}, remedy=>q{Add a Makefile.PL (for ExtUtils::MakeMaker/Module::Install) or a Build.PL (for Module::Build and its friends), or use a distribution builder such as Dist::Zilla, Dist::Milla, Minilla.}, code=>sub { my $d=shift; return 1 if $d->{file_makefile_pl} || $d->{file_build_pl}; return 0; }, details=>sub { my $d = shift; return "Neither Makefile.PL nor Build.PL was found."; }, }, { name=>'has_changelog', error=>q{The distribution hasn't got a Changelog (named something like m/^chang(es?|log)|history$/i. A Changelog helps people decide if they want to upgrade to a new version.}, remedy=>q{Add a Changelog (best named 'Changes') to the distribution. It should list at least major changes implemented in newer versions.}, code=>sub { shift->{file_changelog} ? 1 : 0 }, details=>sub { my $d = shift; return "Any Changelog file was not found."; }, }, { name=>'no_symlinks', error=>q{This distribution includes symbolic links (symlinks). This is bad, because there are operating systems that do not handle symlinks.}, remedy=>q{Remove the symlinks from the distribution.}, code=>sub {shift->{error}{symlinks} ? 0 : 1}, details=>sub { my $d = shift; return "The following symlinks were found: ".$d->{error}{symlinks}; }, }, { name=>'has_tests', error=>q{This distribution doesn't contain either a file called 'test.pl' or a directory called 't'. This indicates that it doesn't contain even the most basic test-suite. This is really BAD!}, remedy=>q{Add tests!}, code=>sub { my $d=shift; # TODO: make sure if .t files do exist in t/ directory. return 1 if $d->{file_test_pl} || $d->{dir_t}; return 0; }, details=>sub { my $d = shift; return q{Neither "test.pl" nor "t/" directory was not found.}; }, }, { name=>'has_tests_in_t_dir', is_extra=>1, error=>q{This distribution contains either a file called 'test.pl' (the old test file) or is missing a directory called 't'. This indicates that it uses the old test mechanism or it has no test-suite.}, remedy=>q{Add tests or move tests.pl to the t/ directory!}, code=>sub { my $d=shift; # TODO: make sure if .t files do exist in t/ directory. return 1 if !$d->{file_test_pl} && $d->{dir_t}; return 0; }, details=>sub { my $d = shift; return q{"test.pl" was found.} if $d->{file_test_pl}; return q{"t/" directory was not found.}; }, }, { name=>'no_stdin_for_prompting', error=>q{This distribution is using direct call from STDIN instead of prompt(). Make sure STDIN is not used in Makefile.PL or Build.PL. See http://www.perlfoundation.org/perl5/index.cgi?cpan_packaging}, is_extra=>1, remedy=>q{Use the prompt() method from ExtUtils::MakeMaker/Module::Build.}, code=>sub { my $d=shift; if ($d->{stdin_in_makefile_pl}||$d->{stdin_in_build_pl}) { return 0; } return 1; }, details=>sub { my $d = shift; return " was found in Makefile.PL" if $d->{stdin_in_makefile_pl}; return " was found in Build.PL" if $d->{stdin_in_build_pl}; }, }, ]; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Files - Check for various files =head1 SYNOPSIS Find various files and directories that should be part of every self-respecting distribution. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<15>, as data generated by C is used by all other tests. =head3 analyse C uses C to get a list of all files and dirs in a dist. It checks if certain crucial files are there, and does some other file-specific stuff. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * has_readme =item * has_manifest =item * has_meta_yml =item * has_buildtool =item * has_changelog =item * no_symlinks =item * has_tests =item * has_tests_in_t_dir =item * no_stdin_for_prompting =back =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/CpantsErrors.pm0000644000175000017500000000500512434527337025144 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::CpantsErrors; use warnings; use strict; use version; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 1000 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; return if $me->opts->{no_capture} or $INC{'Test/More.pm'}; my $sout=$me->capture_stdout; my $serr=$me->capture_stderr; $sout->stop; $serr->stop; my @eout=$sout->read; my @eerr=$serr->read; if (@eerr || @eout) { $me->d->{error}{cpants}=join("\n",'STDERR:',@eerr,'STDOUT:',@eout); } } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { # NOTE: CPANTS error should be logged somewhere, but it # should not annoy people. If anything wrong or interesting # is found in the log, add some metrics (if it's worth), # or just fix our problems. # Older Test::Kwalitee (prior to 1.08) has hardcoded metrics # names in it, and if those metrics are gone from # Module::CPANTS::Kwalitee, it fails because the number of tests # is not as expected. This is not beautiful, but better than # to break others' distributions needlessly. if ($INC{"Test/Kwalitee.pm"}) { return [ map {+{name => $_, code => sub {1}}} qw/extractable no_pod_errors has_test_pod has_test_pod_coverage/ ] if version->parse(Test::Kwalitee->VERSION) < version->parse(1.08); } return []; } q{Listeing to: FM4 the early years}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::CpantsErrors - Check for CPANTS testing errors =head1 SYNOPSIS Checks if something strange happened during testing =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<1000>. =head3 analyse Uses C to check for any strange things that might happen during testing =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/Version.pm0000644000175000017500000000336112434527337024147 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::Version; use warnings; use strict; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 100 } ################################################################## # Analyse ################################################################## sub analyse { # NOTE: The analysis/metrics in this module have moved to # Module::CPANTS::SiteKwalitee because these require # a finalized META file to detect (or ignore) versions # correctly. # Note also that this stub should not be removed so that # this can replace the old ::Version module, and the old # metrics will not be loaded while loading plugins. } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators { return []; } q{Favourite record of the moment: Fat Freddys Drop: Based on a true story}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::Version - check versions =head1 SYNOPSIS The metrics in this module have moved to L. =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<100>. =head3 analyse Does nothing now. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2003–2006, 2009 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Kwalitee/NeedsCompiler.pm0000644000175000017500000000473512434527337025261 0ustar ishigakiishigakipackage Module::CPANTS::Kwalitee::NeedsCompiler; use warnings; use strict; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic sub order { 200 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $files=$me->d->{files_array}; foreach my $f (@$files) { if ($f =~ /\.[hc]$/i or $f =~ /\.xs$/i) { $me->d->{needs_compiler}=1; return; } } if (defined ref($me->d->{prereq}) and ref($me->d->{prereq}) eq 'ARRAY') { for my $m (@{ $me->d->{prereq} }) { if ($m->{requires} =~ /^Inline::/ or $m->{requires} eq 'ExtUtils::CBuilder' or $m->{requires} eq 'ExtUtils::ParseXS') { $me->d->{needs_compiler}=1; return; } } } return; } ################################################################## # Kwalitee Indicators ################################################################## sub kwalitee_indicators{ return [ ]; } q{Favourite compiler: gcc}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Kwalitee::NeedsCompiler - Checks if the module needs a (probably C) compiler =head1 SYNOPSIS Checks if there is some indication in the module that it needs a C compiler to build and install =head1 DESCRIPTION =head2 Methods =head3 order Defines the order in which Kwalitee tests should be run. Returns C<200>. =head3 analyse Checks for file with .c, .h or .xs extensions. Check is the module depends on any of the Inline:: modules or on ExtUtils::CBuilder or ExtUtils::ParseXS. =head3 TODO: How to recognize cases such as http://search.cpan.org/dist/Perl-API/ and http://search.cpan.org/dist/Term-Size-Perl that generate the .c files during installation In addition there are modules that can work without their XS part. E.g. Scalar-List-Utils, Net-DNS, Template-Toolkit For our purposes these all should be marked as "need C compiler" as they need it for their full functionality and speed. =head3 kwalitee_indicators No Kwalitee Indicator. =head1 SEE ALSO L =head1 AUTHOR L =head1 COPYRIGHT AND LICENSE Copyright © 2006–2008 L You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/lib/Module/CPANTS/Analyse.pm0000644000175000017500000001674512434527337022363 0ustar ishigakiishigakipackage Module::CPANTS::Analyse; use 5.006; use strict; use warnings; use base qw(Class::Accessor); use File::Temp qw(tempdir); use File::Spec::Functions qw(catfile catdir splitpath); use File::Copy; use File::stat; use Archive::Any::Lite; use Carp; use IO::Capture::Stdout; use IO::Capture::Stderr; use CPAN::DistnameInfo; our $VERSION = '0.96'; $VERSION = eval $VERSION; ## no critic # setup logger if (! main->can('logger')) { *main::logger = sub { print "## $_[0]\n" if $main::logging; }; } __PACKAGE__->mk_accessors(qw(dist opts tarball distdir d mck capture_stdout capture_stderr)); __PACKAGE__->mk_accessors(qw(_testdir _dont_cleanup _tarball _x_opts)); sub import { my $class = shift; require Module::CPANTS::Kwalitee; Module::CPANTS::Kwalitee->import(@_); } sub new { my $class=shift; my $opts=shift || {}; $opts->{d}={}; $opts->{opts} ||= {}; my $me=bless $opts,$class; $main::logging = 1 if $me->opts->{verbose}; Carp::croak("need a dist") if not defined $opts->{dist}; main::logger("distro: $opts->{dist}"); $me->mck(Module::CPANTS::Kwalitee->new); # For Test::Kwalitee and friends $me->d->{is_local_distribution} = 1 if -d $opts->{dist}; unless ($me->opts->{no_capture} or $INC{'Test/More.pm'}) { my $cserr=IO::Capture::Stderr->new; my $csout=IO::Capture::Stdout->new; $cserr->start; $csout->start; $me->capture_stderr($cserr); $me->capture_stdout($csout); } return $me; } sub run { my $me = shift; $me->unpack unless $me->d->{is_local_distribution}; $me->analyse; $me->calc_kwalitee; $me->d; } sub unpack { my $me=shift; return 'cant find dist' unless $me->dist; my $di=CPAN::DistnameInfo->new($me->dist); my $ext=$di->extension || 'unknown'; $me->d->{package}=$di->filename; $me->d->{vname}=$di->distvname; $me->d->{extension}=$ext; $me->d->{version}=$di->version; $me->d->{dist}=$di->dist; $me->d->{author}=$di->cpanid; $me->d->{released} = stat($me->dist)->mtime; $me->d->{size_packed}=-s $me->dist; unless($me->d->{package}) { $me->d->{package}=$me->tarball; } copy($me->dist,$me->testfile); eval { my $archive=Archive::Any::Lite->new($me->testfile); $archive->extract($me->testdir); }; if (my $error=$@) { if (not $INC{'Test/More.pm'}) { $me->capture_stdout->stop; $me->capture_stderr->stop; } $me->d->{extractable}=0; $me->d->{error}{extractable}=$error; $me->d->{kwalitee}{extractable}=0; my ($vol,$dir,$name)=splitpath($me->dist); $name=~s/\..*$//; $name=~s/\-[\d\.]+$//; $name=~s/\-TRIAL[0-9]*//; $me->d->{dist}=$name; return $error; } $me->d->{extractable}=1; unlink($me->testfile); opendir(my $fh_testdir,$me->testdir) || die "Cannot open ".$me->testdir.": $!"; my @stuff=grep {/\w/} readdir($fh_testdir); if (@stuff == 1) { $me->distdir(catdir($me->testdir,$stuff[0])); if (-d $me->distdir) { my $vname = $di->distvname; $vname =~ s/\-TRIAL[0-9]*//; $me->d->{extracts_nicely}=1 if $vname eq $stuff[0]; } else { $me->distdir($me->testdir); $me->d->{extracts_nicely}=0; } } else { $me->distdir($me->testdir); $me->d->{extracts_nicely}=0; } return; } sub analyse { my $me=shift; foreach my $mod (@{$me->mck->generators}) { main::logger("analyse $mod"); $mod->analyse($me); } } sub calc_kwalitee { my $me=shift; my $kwalitee=0; $me->d->{kwalitee}={}; my %x_ignore = %{$me->x_opts->{ignore} || {}}; foreach my $i ($me->mck->get_indicators) { next if $i->{needs_db}; main::logger($i->{name}); my $rv=$i->{code}($me->d, $i); $me->d->{kwalitee}{$i->{name}}=$rv; if ($x_ignore{$i->{name}} && $i->{ignorable}) { $me->d->{kwalitee}{$i->{name}} = 1; if ($me->d->{error}{$i->{name}}) { $me->d->{error}{$i->{name}} .= ' [ignored]'; } } $kwalitee+=$rv; } $me->d->{'kwalitee'}{'kwalitee'}=$kwalitee; main::logger("done"); } #---------------------------------------------------------------- # helper methods #---------------------------------------------------------------- sub testdir { my $me=shift; return $me->_testdir if $me->_testdir; if ($me->_dont_cleanup) { return $me->_testdir(tempdir()); } else { return $me->_testdir(tempdir(CLEANUP => 1)); } } sub testfile { my $me=shift; return catfile($me->testdir,$me->tarball); } sub tarball { my $me=shift; return $me->_tarball if $me->_tarball; my (undef,undef,$tb)=splitpath($me->dist); return $me->_tarball($tb); } sub x_opts { my $me = shift; return $me->_x_opts if $me->_x_opts; my %opts; if (my $x_cpants = $me->d->{meta_yml}{x_cpants}) { if (my $ignore = $x_cpants->{ignore}) { if (ref $ignore eq ref {}) { $opts{ignore} = $ignore; } else { $me->d->{error}{x_cpants} = "x_cpants ignore should be a hash reference (key: metric, value: reason to ignore)"; } } } $me->_x_opts(\%opts); } q{Favourite record of the moment: Jahcoozi: Pure Breed Mongrel}; __END__ =encoding UTF-8 =head1 NAME Module::CPANTS::Analyse - Generate Kwalitee ratings for a distribution =head1 SYNOPSIS use Module::CPANTS::Analyse; my $analyser=Module::CPANTS::Analyse->new({ dist=>'path/to/Foo-Bar-1.42.tgz', }); $analyser->run; # results are in $analyser->d; =head1 DESCRIPTION =head2 Methods =head3 new my $analyser=Module::CPANTS::Analyse->new({dist=>'path/to/file'}); Plain old constructor. =head3 unpack Unpack the distribution into a temporary directory. Returns an error if something went wrong, C if all went well. =head3 analyse Run all analysers (defined in C on the dist. =head3 calc_kwalitee Check if the dist conforms to the Kwalitee indicators. =head3 run Unpacks, analyses, and calculates kwalitee, and returns a resulting stash. =head2 Helper Methods =head3 testdir Returns the path to the unique temp directory. =head3 testfile Returns the location of the unextracted tarball. =head3 tarball Returns the filename of the tarball. =head3 x_opts Returns a hash reference that holds normalized information set in the "x_cpants" custom META field. =head1 WEBSITE L =head1 BUGS Please report any bugs or feature requests, or send any patches, to bug-module-cpants-analyse at rt.cpan.org, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 AUTHOR L Please use the C mailing list for discussing all things CPANTS: L Based on work by L and the original idea proposed by L. =head1 LICENSE This code is Copyright © 2003–2006 L. All rights reserved. You may use and distribute this module according to the same terms that Perl is distributed under. Module-CPANTS-Analyse-0.96/t/0000755000175000017500000000000012434531241015661 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/t/lib/0000755000175000017500000000000012434531241016427 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/t/lib/Module/0000755000175000017500000000000012434531241017654 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/t/lib/Module/CPANTS/0000755000175000017500000000000012434531241020644 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/t/lib/Module/CPANTS/TestAnalyse.pm0000644000175000017500000000570612411274466023456 0ustar ishigakiishigakipackage # Module::CPANTS::TestAnalyse; use strict; use warnings; use Carp; use base 'Exporter'; use File::Temp qw/tempdir/; use File::Path; use File::Spec::Functions qw/splitpath catfile abs2rel/; use File::Find; use Cwd; use Module::CPANTS::Analyse; use CPAN::Meta::YAML; use Test::More; our @EXPORT = qw/ test_distribution write_file write_pmfile write_metayml archive_and_analyse /; push @EXPORT, \$Test::More::TODO, grep {Test::More->can($_)} qw/ ok use_ok require_ok is isnt like unlike is_deeply cmp_ok skip todo_skip pass fail eq_array eq_hash eq_set plan done_testing can_ok isa_ok new_ok diag note explain BAIL_OUT subtest nest /; sub test_distribution (&) { my $code = shift; my $cwd = cwd; my $dir = tempdir(CLEANUP => 1); my $mca = Module::CPANTS::Analyse->new({ dist => $dir, distdir => $dir, }); note "tests under $dir"; eval { $code->($mca, $dir) }; ok !$@, "no errors"; chdir $cwd; rmtree $dir; } sub write_file { my ($path, $content) = @_; my ($vol, $dir, $file) = splitpath($path); $dir = "$vol$dir" if $vol; mkpath $dir unless -d $dir; open my $fh, '>:encoding(utf8)', $path or croak "Can't open $path: $!"; print $fh $content; note "wrote to $path"; } sub write_pmfile { my ($path, $content) = @_; my @lines = ('package '.'Module::CPANTS::Analyse::Test'); push @lines, $content if defined $content; push @lines, '1'; write_file($path, join ";\n", @lines, ""); } sub write_metayml { my ($path, $args) = @_; my $meta = { name => 'Module::CPANTS::Analyse::Test', abstract => 'test', author => ['A.U.Thor'], generated_by => 'hand', license => 'perl', 'meta-spec' => {version => '1.4', url => 'http://module-build.sourceforge.net/META-spec-v1.4.html'}, version => '0.01', %{$args || {}}, }; write_file($path, CPAN::Meta::YAML->new($meta)->write_string); } sub archive_and_analyse { my ($dir, $name) = @_; my $archive_path = catfile($dir, $name); (my $basename = $name) =~ s/(?:\.tar\.(?:gz|bz)|\.zip)$//; require Archive::Tar; my $archive = Archive::Tar->new; find({ wanted => sub { my $file = $File::Find::name; my $relpath = abs2rel($file, $dir); return if $relpath =~ /^\./; my $path = catfile($basename, $relpath); if (-l $file) { $archive->add_data($path, '', { type => Archive::Tar::SYMLINK, linkname => readlink $file, }) or die "failed to add symlink: $path"; } elsif (-f $file) { my $content = do { local $/; open my $fh, '<', $file; <$fh> }; $archive->add_data($path, $content); } elsif (-d $dir && $path ne '.') { $archive->add_data($path, '', Archive::Tar::DIR) or die "failed to add dir: $path"; } }, no_chdir => 1, }, $dir); $archive->write($archive_path, Archive::Tar::COMPRESS_GZIP); ok -f $archive_path, "archive exists"; Module::CPANTS::Analyse->new({ dist => $archive_path, })->run; } 1; Module-CPANTS-Analyse-0.96/t/analyse/0000755000175000017500000000000012434531241017315 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/t/analyse/manifest.t0000644000175000017500000000402312411273577021321 0ustar ishigakiishigakiuse strict; use warnings; use FindBin; use lib "$FindBin::Bin/../lib"; use Module::CPANTS::TestAnalyse; test_distribution { my ($mca, $dir) = @_; write_file("$dir/MANIFEST", <<"EOF"); lib/Module/CPANTS/Analyse/Test.pm MANIFEST EOF write_pmfile("$dir/lib/Module/CPANTS/Analyse/Test.pm"); my $stash = $mca->run; is $stash->{manifest_matches_dist} => 1, "manifest matches dist"; }; test_distribution { my ($mca, $dir) = @_; write_pmfile("$dir/lib/Module/CPANTS/Analyse/Test.pm"); my $stash = $mca->run; is $stash->{manifest_matches_dist} => 0, "manifest does not match dist"; like $stash->{error}{manifest_matches_dist} => qr/^Cannot find MANIFEST/, "proper error message"; }; test_distribution { my ($mca, $dir) = @_; write_file("$dir/MANIFEST", <<"EOF"); eg/demo.pl lib/Module/CPANTS/Analyse/Test.pm MANIFEST EOF write_pmfile("$dir/lib/Module/CPANTS/Analyse/Test.pm"); write_file("$dir/TODO", "TODO!"); my $stash = $mca->run; is $stash->{manifest_matches_dist} => 0, "manifest does not match dist"; my @errors = @{ $stash->{error}{manifest_matches_dist} || [] }; ok grep /^Missing in MANIFEST: TODO/, @errors; ok grep /^Missing in Dist: eg\/demo\.pl/, @errors; }; # should hide symlink errors not in MANIFEST for a local distribution test_distribution { my ($mca, $dir) = @_; write_file("$dir/MANIFEST", <<"EOF"); MANIFEST EOF eval { symlink "$dir/MANIFEST", "$dir/MANIFEST.lnk" }; if ($@) { diag "symlink is not supported"; return; } my $stash = $mca->run; ok !$stash->{error}{symlinks}, "symlinks not listed in MANIFEST is ignored for a local distribution"; }; test_distribution { my ($mca, $dir) = @_; write_file("$dir/MANIFEST", <<"EOF"); MANIFEST EOF eval { symlink "$dir/MANIFEST", "$dir/MANIFEST.lnk" }; if ($@) { diag "symlink is not supported"; return; } my $stash = archive_and_analyse($dir, "Module-CPANTS-Analyse-Test-0.01.tar.gz"); ok $stash->{error}{symlinks}, "symlinks not listed in MANIFEST is not ignored for a non-local distribution"; }; done_testing; Module-CPANTS-Analyse-0.96/t/analyse/pod.t0000644000175000017500000000110612411273577020274 0ustar ishigakiishigakiuse strict; use warnings; use FindBin; use lib "$FindBin::Bin/../lib"; use Module::CPANTS::TestAnalyse; test_distribution { my ($mca, $dir) = @_; my $content = join "\n\n", ( '=pod', '=encoding utf-8;', '=head1 NAME', 'Module::CPANTS::Analyse::Test - test abstract', '=cut', ); write_pmfile("$dir/lib/Module/CPANTS/Analyse/Test.pm", $content); my $stash = $mca->run; like $stash->{error}{has_abstract_in_pod} => qr/^unknown encoding: utf-8;/; is $stash->{abstracts_in_pod}{'Module::CPANTS::Analyse::Test'} => 'test abstract'; }; done_testing; Module-CPANTS-Analyse-0.96/t/05_testfile.t0000644000175000017500000000061212411274466020200 0ustar ishigakiishigakiuse strict; use warnings; use Test::More; use Test::FailWarnings; use Module::CPANTS::Analyse; use File::Basename; my $a=Module::CPANTS::Analyse->new({ dist=>'D/DO/DOMM/Foo-Bar-1.05.tgz', }); my $td=$a->testdir; ok(-e $td,"testdir $td created"); $td=basename($td); like($a->testfile,qr/$td/,"testdir in testfile"); like($a->testfile,qr/Foo-Bar/,"filename in testfile"); done_testing; Module-CPANTS-Analyse-0.96/t/00_load.t0000644000175000017500000000020112411274466017265 0ustar ishigakiishigakiuse strict; use warnings; use Test::More; use Test::FailWarnings; BEGIN { use_ok( 'Module::CPANTS::Analyse' ); } done_testing; Module-CPANTS-Analyse-0.96/t/05_testdir.t0000644000175000017500000000043312411274466020040 0ustar ishigakiishigakiuse strict; use warnings; use Test::More; use Test::FailWarnings; use Module::CPANTS::Analyse; my $a=Module::CPANTS::Analyse->new({dist => 'dummy'}); my $td=$a->testdir; ok(-e $td,"testdir $td created"); my $td2=$a->testdir; is($td,$td2,"still the same testdir"); done_testing; Module-CPANTS-Analyse-0.96/t/older_test_kwalitee.t0000644000175000017500000000127112411273577022112 0ustar ishigakiishigakiuse strict; use warnings; use Test::More; use Module::CPANTS::Kwalitee; local $INC{"Test/Kwalitee.pm"} = 1; local $Test::Kwalitee::VERSION = 1.01; my @hardcoded_metrics = qw/ extractable has_readme has_manifest has_meta_yml has_buildtool has_changelog no_symlinks has_tests proper_libs no_pod_errors use_strict has_test_pod has_test_pod_coverage /; my %seen; my $kwalitee = Module::CPANTS::Kwalitee->new; for my $generator (@{ $kwalitee->generators }) { for (@{ $generator->kwalitee_indicators }) { $seen{$_->{name}}++ if ref $_->{code} eq ref sub {}; } } for (@hardcoded_metrics) { is $seen{$_} => 1, "$_ is available for Test::Kwalitee"; } done_testing; Module-CPANTS-Analyse-0.96/t/x_cpants.t0000644000175000017500000000303112411273577017674 0ustar ishigakiishigakiuse strict; use warnings; use FindBin; use lib "$FindBin::Bin/lib"; use Module::CPANTS::TestAnalyse; test_distribution { my ($mca, $dir) = @_; write_metayml("$dir/META.yml"); write_pmfile("$dir/Test.pm"); my $res = $mca->run; ok !$res->{kwalitee}{use_strict}, "use_strict fails correctly"; ok !$res->{kwalitee}{has_tests}, "has_tests fails correctly"; }; test_distribution { my ($mca, $dir) = @_; write_pmfile("$dir/Test.pm"); write_metayml("$dir/META.yml", { x_cpants => {ignore => { use_strict => 'for some reason', }} }); my $res = $mca->run; ok $res->{kwalitee}{use_strict}, "use_strict is ignored (and treated as pass)"; ok $res->{error}{use_strict} && $res->{error}{use_strict} =~ /Module::CPANTS::Analyse::Test/ && $res->{error}{use_strict} =~ /ignored/, "error is not removed and marked as 'ignored'"; ok !$res->{kwalitee}{has_tests}, "has_tests fails correctly"; }; test_distribution { my ($mca, $dir) = @_; write_pmfile("$dir/Test.pm"); write_metayml("$dir/META.yml", { x_cpants => {ignore => { use_strict => 'for some reason', has_tests => 'because I am so lazy', }} }); my $res = $mca->run; ok $res->{kwalitee}{use_strict}, "use_strict is ignored (and treated as pass)"; ok $res->{error}{use_strict} && $res->{error}{use_strict} =~ /Module::CPANTS::Analyse::Test/ && $res->{error}{use_strict} =~ /ignored/, "error is not removed and marked as 'ignored'"; ok !$res->{kwalitee}{has_tests}, "has_tests fails correctly regardless of the x_cpants"; }; done_testing; Module-CPANTS-Analyse-0.96/TODO0000644000175000017500000001521012411273577016117 0ustar ishigakiishigaki#----------------------------------------------------------------- # TODO Module-CPANTS-Analyse # $Rev: 409 $ # $Date: 2006-09-14 19:42:31 +0200 (Thu, 14 Sep 2006) $ #----------------------------------------------------------------- #----------------------------------------------------------------- # BUGS #----------------------------------------------------------------- Robert 'phaylon' Sedlacek Meldung, dass 'has_proper_version' nicht bestanden wird. http://rt.cpan.org/Ticket/Display.html?id=21370 Win32 test fail: analyse.t, analyse_afs.t, calc.t, testfile.t Moose and MooseX turn on strict, so count Moose[X] as use_strict The "ownership of a modules does not seem to get updated" e.g. still shows DAGOLDEN even tough it should be ADAMK http://cpants.perl.org/dist/external/Perl-Dist-Strawberry #----------------------------------------------------------------- # New Metrics #----------------------------------------------------------------- - no_boilerplate - has_valid_filenames - declares_dependencies - no_open_bugs - no_old_open_bugs (older than a year?) - license_is_actual might be a good addition, like "copyright 2001-2002" is rather outdated - add list of modules that fail the use_warnings to $d->{error}{use_warnings} - same for use_strict - Allow the Debian and/or the Fedora packagers to "manually" report problems they encounter with certain packages directly from their systems. So if there is a module that cannot automatically packaged (or tested?) because they are interactive (in the wrong way) or they need network access... On the Debian list it was discussed that they might start saving this information from themself and then export this information with the rest of the data about packages. - Signature checking ? - has_rating ? - relation of subs to lines of code ? - easily_repackagable - easily_repackagable_by_debian - easily_repackagable_by_fedora on http://www.perlfoundation.org/perl5/index.cgi?cpan_packaging there are guidelines for module authors to make their modules easily repackagable by downstream distros. It would be great if we could add as many to CPANTS as possible. Some we can check without executing code. Others might be verified by the CPAN Testers, reported by the tools and then collected from the reports by CPANTS. - version_number_is_sane There are several issues here: 1) Is the version number sane for perl (I think there is a metric already) 2) Is the version number sane for Debian/RedHat (they have different meaning of sane) 3) Is the scheme of the version numbers stable? (In Debian they don't like when ppl are changing from D.DD to a D.D scheme or vice versa. 1.1.1 is not considered correct by MakeMaker but it is currently accepted by CPANTS http://cpants.perl.org/dist/kwalitee/Sys-HostIP http://www.nntp.perl.org/group/perl.qa/2007/12/msg10025.html - has_same_version_number_in_all_files ??? Some people will argue that when one of the files does not change, there is no need to change its version number. So this might not be a good metric. - no_bugs_in_freebsd - has_patches_in_freebsd The Debian and FreeBSD ppl will provide the interface for this -probably a csv file that can be fetched using http. This should be (an optional?) negative metric in case the module is included in FreeBSD or Debian but it had to be patched. (Maybe we need to make sure that we set this negative metric only when the module versions are the same so we won't penalize a module because XYZ has not yet integrated the newer version that possibly already includes the patch. - We might even have an optional metric to show that "the latest version of the module is included in Debian/FreeBSD etc". This will be lost every time a new version of a module is released but over time it will become ok again. (in xt/ or in t/ and the same file has RELEASE_TESTING in it) - has_no_indirect_code Check the source code (and/or) the documentation if you see new Module::Name anywhere mark the metric as failed. - all_links_in_the_documentation_still_exist - declares_minimal_version_of_perl It has "use N" somewhere in the Makefile.PL and/or Build.PL and/or the source code. (and they match to each other :-) (No specific N should be required) - "something about has good perl code" (e.g. if uses 3 param open but does not say use perl 5.6 or similar) - has_humanreadable_license the actual name of the license (perl, etc.) is in the database, use it Module::License::Report integration (though I am not sure if that should mean the main .pm file only or all the files or what) - licenses_are_consistent Locate places where hard-coded pathes to perl (or other files?) are: > > my @cmd = qw{/usr/bin/perl -Ilib -MPod::HtmlEasy -e}; actually try to locate places where perl is called instead of $^X <@Tux> has no open bugs in RT older than 2 months <@Tux> and debian shipped last version is only ok is last version is older than 3 months #----------------------------------------------------------------- # Other Stuff #----------------------------------------------------------------- - include more dists in test (for better test coverage) - improve NeedsCompiler (see its TODO) - Perl Critic report: As this is not really in the consensus probably it is better not add it as a metric now but it might be nice to run it on each module (starting at level 5 ) and display it along with the metrics. Maybe it can be added as an optional metric. - http://cpants.perl.org/author/search should also work on partial names adding % % automatically (or at least tell the users on the search page to use % as wildcards. - create stats (or metrics) for distros that were uploaded recently with failing metrics. e.g. the fact that 9920 Distributions failing 'metayml_has_license' is skewed by the many modules that were not updated in the past 1-2 years. It would be more important to see the number of modules uploaded in the last year without metayml of without license field in the metayaml. - Export the kwalitee of each distro in a csv file like so it can be easily integrated into other web sites such as the search engines. - Export the kwalitee of each distro in a csv file like so it can be easily integrated into other web sites such as the search engines. - Create a hierarchical report (aka CPANDepth) showing all the dependencies their kwalitee, their age, their license (the name of the license from META.yml for now) - honor the META.yml key no_index. See RT#32777 - Display the version of CPANTS used for indexing and show the date when the last update was executed. Maybe do so per distribution? Module-CPANTS-Analyse-0.96/META.json0000644000175000017500000000403212434531241017036 0ustar ishigakiishigaki{ "abstract" : "Generate Kwalitee ratings for a distribution", "author" : [ "Thomas Klausner ", "Kenichi Ishigaki " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.142060", "keywords" : [ "CPANTS", "kwalitee" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Module-CPANTS-Analyse", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Cwd" : "0", "ExtUtils::MakeMaker" : "0", "Test::FailWarnings" : "0", "Test::More" : "0.88" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker::CPANfile" : "0.06" } }, "runtime" : { "requires" : { "Archive::Any::Lite" : "0.06", "Archive::Tar" : "1.48", "Array::Diff" : "0.04", "CPAN::DistnameInfo" : "0.06", "CPAN::Meta::Validator" : "2.133380", "CPAN::Meta::YAML" : "0.008", "Class::Accessor" : "0.19", "File::Find::Object" : "v0.2.1", "IO::Capture" : "0.05", "JSON::MaybeXS" : "0", "Module::ExtractUse" : "0.33", "Module::Pluggable" : "2.96", "Set::Scalar" : "0", "Software::License" : "0.103008", "Software::License::CC_BY_SA_3_0" : "0", "Text::Balanced" : "0", "version" : "0.73" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Module-CPANTS-Analyse" }, "homepage" : "http://cpants.cpanauthors.org", "repository" : { "url" : "https://github.com/cpants/Module-CPANTS-Analyse" } }, "version" : "0.96" } Module-CPANTS-Analyse-0.96/Changes0000644000175000017500000003435012434527337016731 0ustar ishigakiishigakiRevision history for Module-CPANTS-Analyse 0.96 2014-11-24 - Added an import option to load extra Kwalitee plugins. - Fixed RT#100512 - has_readme now accepts README.pod as well - Improved no_abstract_stub_in_pod to detect "The great new" as a boilerplate - Switched to File::Find::Object 0.95 2014-09-26 - Switched to Test::FailWarnings to make CPAN testers happier 0.94 2014-09-26 - Fixed RT#99141 - use_strict metric does not recognize `use v5.14` syntax (ishigaki) 0.93_04 2014-09-05 - Accept COPYING as a license file - Take included module (under inc/) into consideration while analyzing prereq_matches_use - Changed most of the META.yml metrics to pass if META.yml doesn't exist 0.93_03 2014-08-13 - Added meta_json_is_parsable and meta_json_conforms_to_known_spec - Added meta_yml_has_repository_resource - Renamed metayml_ metrics to meta_yml_ - Fixed abstract encoding issues - Refactored tests - Fixed not to ignore directory symlinks - Fixed RT#97858 - wrong no_symlinks test in files not in MANIFEST (for a local distribution; CPANTS site doesn't ignore symlinks not listed in MANIFEST) - Fixed RT#97601 - Test::Kwalitee incorrectly reports non-use of strict in Inline::CPP 0.93_02 2014-06-30 - Removed cpants_lint.pl in favor of App::CPANTS::Lint - Fixed RT#94468 - "use_strict" metric doesn't like .pod files that contain no perl (ishigaki) - Fixed RT#96492 - 0.93_01 test failures on OSX (ether) 0.93_01 2014-05-27 - Added the following metrics: - has_known_license_in_source_file - has_abstract_in_pod - no_abstract_stub_in_pod - Removed metayml_conforms_spec_current metric. - Supported x_cpants custom META field to tell analyzer to ignore some of the metrics (only) when calculating a kwalitee score. - Refactored several Kwalitee files, and internal stash layout has changed rather significantly. You might need to modify your tools if they happen to depend on the stash directly. 0.92 2013-09-22 - Fixed a case when more than one license sections come in row (spotted by ysasaki++) (ishigaki) - stopped checking auto_features (ishigaki) 0.91 2013-09-05 - Fixed RT#69233 - doesn't detect use >= 5.012 as use strict (ishigaki) - Fixed RT#83336 - Fails to detect strict via `use MooseX::Types` (ether) - Fixed RT#83851 - 'use v5.16' and greater not deemed "strict" (ishigaki) - Fixed RT#86504 - fix sort order of Kwalitee generators (ether) - Fixed RT#87155 - more Module::Install tests needed (1.04 is broken) (ishigaki) - Fixed RT#87597 - proper_libs is a dubious test (ishigaki) - Fixed RT#87598 - Can't use an undefined value as an ARRAY reference at .../FindModules.pm line 115. (ishigaki) - Fixed RT#87988 - Fix use of $Test::Kwalitee::VERSION (ether) - Fixed RT#88216 - extracts_nicely metric fails for -TRIAL releases (ishigaki) - Fixed RT#88365 - YAML/JSON tests are not failing when improperly encoded characters are seen (ishigaki) - Moose::Exporter also provides strict and warnings (doy) 0.90_02 2013-08-03 - Fixed rt#87535 - incorrect version specification in 0.90_01 (ether) - Fixed rt#87534 - Test failure in 0.90_01 (ether) - Fixed rt#87561 - t/11_hash_random.t fails due to undeclared test dependency (wyant) 0.90_01 2013-08-01 - Applied all the changes in 0.88 again, and removed a few non-portable metrics for Test::Kwalitee. 0.89 2013-08-01 - Tentatively reverted all the changes in 0.88 0.88 2013-08-01 - add metric "no_dot_underscore_files" (daxim, charsbar) - remove metrics "distributed_by_debian", "latest_version_distributed_by_debian", "has_no_bugs_reported_in_debian", "has_no_patches_in_debian", "no_cpants_errors", "uses_test_nowarnings", "has_test_pod", "has_test_pod_coverage", "has_examples" (charsbar) - add metric "portable_filenames" (charsbar) - numerous fixes for a smoother operation of www-cpants (charsbar) 0.87 2013-02-12 - fix rt#80225 - Test failures due to Test::CPAN::Meta::YAML::Version interface change (wyant) - fix rt#82939 - Hash-Randomization causes 10_analyse.t to fail (kentnl, chorny) - fix rt#44796 - Module::CPANTS::Kwalitee::Manifest broken for MANIFESTs containing files with spaces (rivy) 0.86 2012-04-11 - add several strict and warnings equivalents & make it easy to add more - fix when Moose is used and strict is not used - add info about "MIN_PERL_VERSION" - better remedy for metayml_declares_perl_version - metayml_declares_perl_version moved from experimental to extra some pod improvements (jquelin) - fix rt#65903 - no more "Test::YAML::Meta::Version" on CPAN (jquelin) - replace YAML::Syck with YAML::Any (jquelin) - no_symlinks checks only files in MANIFEST, use "maniread" in ExtUtils::Manifest (rurban) - add more equivalents for use_strict and use_warnings tests (doherty) - implement valid_signature metric (daxim) 0.85 2009-07-12, Alexandr Ciornii - fix fails on non-Win32 0.84 2009-07-08, Alexandr Ciornii - require Test::Warn 0.11 - add Test::More to deps - add LWP::Simple to deps - fix calc_test_yaml_meta.t - better META.yml - list of changes for 0.83 (domm) 0.83 2009-06-10 - ignore "no_index" when searching for examples (xdaveg) - skip the debian metrics and downloading the debian file when in LINT (szabgab) - has_test_pod and has_test_pod_coverage are now optional metrics (domm) 0.82 2008-07-08 10:23:30 - update META.yml spec to 1.4 - fixed experimental metrics - use Moose now counts for using strict - lots of commits from Gábor - honor META.yml key "no_index". - Fixes RT#32777 and an IRC complaint by BinGOs 0.81 Sun Apr 13 16:45:29 CEST 2008 - fixed doc bug in SYNOPSIS (reported by ADAMOWSKI as RT#34773) - made Module::CPANTS::Kwalitee::FindModules smarter (domm): If available, use META.yml "provides". If not, look for "package" statements in files. It now also finds stuff like Tk::Widget and App::Ack upgrade to Software::License 0.003 (Gábor) 0.80 Sat Apr 12 10:53:40 CEST 2008 domm: - add metayml_has_provides metric Gábor Szabó: - simplify the way the VERSION number is looked up, keep the full version line - increase the no_large_files limit to 200_000 - some unit test fixes thanks to Tux - some of {error} fields are now ARRAY refs instead of strings - more detailed unit tests - add "LICENCE" to the list of special files (not only LICENSE) - collect the license information of each file using Software::LicenseUtils - add has_separate_license_file metric - add has_license_in_source_file metric 0.79 Tue Apr 8 01:25:12 CEST 2008 - released at the Oslo QA Hackathon 2008 Gábor Szabó: - replace File::Find by File::Find::Rule - add no_large_files metrics - add fits_fedora_license metric that was inside the - easily_repackageable_by_fedora metric - add "is_experimental" flag to some of the metrics - add aggregating key to metric to list the other metrics being aggregated - unhide some errors during testing - renamed some error fields - add metayml_declares_perl_version metric 0.78 2008-04-06 - released at the Oslo QA Hackathon 2008 - very hacky workaround for problems with Meta.YML, version objects, etc - moved "has_version_in_each_file" into - Module::CPANTS::Kwalitee::Version & fixed a bug in it Gábor Szabó: - add fits_fedora_license metric that was inside the - easily_repackageable_by_fedora metric - add "is_experimental" and "is_aggregate" flags to some of the metrics - unhide some errors during testing - add no_generated_files metric - add easily_repackageable_by_fedora, - easily_repackagable_by_debian and easily_repackageable metric - add has_version_in_each_file metric - add has_tests_in_t_dir metric - add no_stdin_for_prompting metric checking for STDIN in Makefile.PL and Build.PL 0.77 2008-01-29 - made prereq_matches_use and build_prereq_matches_use optional metrics - changed data structure: all errors are now in a hashref called "error" 0.76 2007-11-14 - added new metrics prereq_matches_use and build_prereq_matches_use - added "needs_db" to metrics and removed hardcoded workaround for is_prereq - removed workaround in Module::CPANTS::Kwalitee::MetaYML (Barbie fixed it the problem in Test::YAML::Meta) - reworded metayml_is_parsable remedy 0.75 2007-10-29 - added optional metric use_warnings - added directory xt as a potential location for test files - finally applied patch provided by Adriano Ferreira to fix some issues in Module::CPANTS::Kwalitee::Manifest. See RT #28982 0.74 2007-10-24 - removed metric "metayml_conforms_spec_1_0" - fixed bug in "check_spec_conformance" in Module::CPANTS::Kwalitee::MetaYML, which caused wrong results in metayml_conforms_spec* - switched to YAML::Syck - work around Pod::Simple::Checker returning strange data 0.73 2007-09-12 - added version of dist to dump file name - fixed bug in Module::CPANTS::Kwalitee::NeedsCompiler (RT #28134 plus all reported merged into that one) 0.72 2007-06-30 - added docs to cpants_lint.pl - cpants_lint.pl can now dump metadata to a file - added YAML output to cpants_lint.pl Gábor Szabó: - added Module::CPANTS::Kwalitee::NeedsCompiler MCK::NeedsCompiler does not contain any "kwalitee_indicator", but adds much needed metadata. Barbie: - Module::CPANTS::Analyse assumes Unix paths after munging with File::Spec, thus breaking portability at every turn in a non-Unix-like environment… bad Thomas no biscuit! Refined META.yml metrics using Test::YAML::Meta and brought *current spec* up to date with version 1.3 :) 0.71 2007-04-23 - moved svn repo to - has_license now also checks for LICENCE (as suggested by David Cantrell) - fixed RT #26535 reported by MTHURN - has_example now also checks for "p(m|od)" files (as suggested by JUERD) - fixed RT #24228 reported by THALJEF - t/99_critic.t now only runs if $ENV{AUTHOR_TEST} is set - resolved RT #25198 reported by bdfoy using his patch Module::CPANTS::Kwalitee::FindModules: do not check META.yml for "provides" because META.yml might list semi-garbage (eg according to META.yml, Siesta provides Apache::Constants, which it does not.) - skip very large test-files and only check *.t files (not everything in t/) as suggested by CASIANO - cpants_lint.pl: - switched from Getopt::Std to Getopt::Long - added "--no_capture" option for easier debugging - added "--verbose" options - hopefully fixed RT #25207 (test failures on Win32) reported (and patched…) by HEMINGWAY. This should also solve RT #26535 reported by Martin Thurn - applied doc patch submitted by MSTEVENS as RT #26379 0.69 2006-11-04 - split up "metayml_conforms_spec" to metayml_conforms_spec_1_0 and "metayml_conforms_spec_1_2" (which is optional) - added "metayml_error" and docu pointers to it. 0.68 2006-10-28 - fixed bug in Module::CPANTS::Kwalitee::FindModules reported by JDHEDDEN in RT #22081 (the module name of modules living in the top-level namespace (eg 'threads.pm') was not guessed correctly use META.yml "provides" (if it exists) instead of guessing module names in Module::CPANTS::Kwalitee::FindModules modifed changelog-regex in Module::CPANTS::Kwalitee::Files as suggested by CDOLAN in RT #21999 - added Module::CPANTS::Kwalitee::License - moved license checking to Module::CPANTS::Kwalitee::License - added checks for LICENSE file and "LICENSE" POD section - moved "meta_yml" parsing to Module::CPANTS::Kwalitee::MetaYML - changed "has_license|Module::CPANTS::Kwalitee::License" error text after Schwern (and Andreas Koenig) suggested that ExtUtils::MakeMaker now supports a "license" field 0.67 2006-09-13 - cpants_lint.pl now handles reporting of optional metrics better. - added t/99_critic.t (Gábor Szabó) - some code cleanups as reported by Test::Perl::Critic (Gábor Szabó) - new metric: "has_license|Module::CPANTS::Kwalitee::License"; - Module::CPANTS::Kwalitee::MetaYML (Gábor Szabó) - Module::CPANTS::Kwalitee::Pod now reports the error messages returned by Pod::Simple::Checker (suggested by Gábor Szabó) 0.66 2006-09-06 - added "optional_indicator_names utility" in Module::CPANTS::Kwalitee method 0.65 2006-09-05 (YAPC::Europe hackathon release) - updated test suite - added "has_example" to Module::CPANTS::Kwalitee::Files - added "buildtool_not_executable" to Module::CPANTS::Kwalitee::Files - added Module::CPANTS::Kwalitee::Manifest ("manifest_matches_dist") 0.64 2006-08-29 - updated Module::CPANTS::Kwalitee::BrokenInstaller submitted by Steffen Müller 0.63 2006-07-31 - we now also find README.txt - resolves RT #20633 reported by MBARBON (thanks for the patch!) 0.62 2006-07-20 - added Module::CPANTS::Kwalitee::BrokenInstaller submitted by Steffen Müller 0.61 2006-07-17 - Kwalitee metrics can now be marked as "is_extra" Such metrics do not count for available kwalitee - marked is_prereq as "is_extra" - cpants_lint now reports percentages additional to absolute values - cpants_lint won't list failed "is_extra" metrics - added some method caching to Module::CPANTS::Kwalitee - added Ctotal_kwalitee> to Module::CPANTS::Kwalitee. 0.60 2006-05-18 - activated is_prereq metric - added helper method ("available_kwalitee") - Module::CPANTS::Kwalitee::FindModules: skip stuff in inc (Module::Install) 0.52 2006-03-12 - added some dependencies to Build.PL/META.yml (thanks to Achim Grolms and BLBLACK (RT #17977)) - enhanced output of cpants_lint.pl (list failed tests) - Module::CPANTS::Kwalitee::FindModules: die if we cannot find a namespace - Module::CPANTS::Kwalitee::FindModules: remove stuff that doesn't seem to be namespace (eg lowercase) from module names - changed the name of some fields to work with the (upcoming) DB added some tests 0.51 2006-02-16 - adapted Module::CPANTS::Kwalitee::Prereq to work with newer versions of YAML (reported by Andreas Koenig as RT #17670) 0.50 2006-01-26 - first release to CPAN 0.01 - started rewrite Module-CPANTS-Analyse-0.96/Makefile.PL0000644000175000017500000000130612411273577017402 0ustar ishigakiishigakiuse 5.006; use strict; use warnings; use ExtUtils::MakeMaker::CPANfile; WriteMakefile( NAME => 'Module::CPANTS::Analyse', AUTHOR => [ 'Thomas Klausner ', 'Kenichi Ishigaki ', ], ABSTRACT_FROM => 'lib/Module/CPANTS/Analyse.pm', VERSION_FROM => 'lib/Module/CPANTS/Analyse.pm', LICENSE => 'perl', META_MERGE => { resources => { homepage => 'http://cpants.cpanauthors.org', repository => 'https://github.com/cpants/Module-CPANTS-Analyse', bugtracker => 'https://rt.cpan.org/Public/Dist/Display.html?Name=Module-CPANTS-Analyse', }, keywords => [ 'CPANTS','kwalitee', ], }, test => {TESTS => 't/*.t t/*/*.t'}, ); Module-CPANTS-Analyse-0.96/META.yml0000644000175000017500000000243112434531241016667 0ustar ishigakiishigaki--- abstract: 'Generate Kwalitee ratings for a distribution' author: - 'Thomas Klausner ' - 'Kenichi Ishigaki ' build_requires: Cwd: '0' ExtUtils::MakeMaker: '0' Test::FailWarnings: '0' Test::More: '0.88' configure_requires: ExtUtils::MakeMaker::CPANfile: '0.06' dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 6.98, CPAN::Meta::Converter version 2.142060' keywords: - CPANTS - kwalitee license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Module-CPANTS-Analyse no_index: directory: - t - inc requires: Archive::Any::Lite: '0.06' Archive::Tar: '1.48' Array::Diff: '0.04' CPAN::DistnameInfo: '0.06' CPAN::Meta::Validator: '2.133380' CPAN::Meta::YAML: '0.008' Class::Accessor: '0.19' File::Find::Object: v0.2.1 IO::Capture: '0.05' JSON::MaybeXS: '0' Module::ExtractUse: '0.33' Module::Pluggable: '2.96' Set::Scalar: '0' Software::License: '0.103008' Software::License::CC_BY_SA_3_0: '0' Text::Balanced: '0' version: '0.73' resources: bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Module-CPANTS-Analyse homepage: http://cpants.cpanauthors.org repository: https://github.com/cpants/Module-CPANTS-Analyse version: '0.96' Module-CPANTS-Analyse-0.96/cpanfile0000644000175000017500000000154712434527337017144 0ustar ishigakiishigakirequires 'Array::Diff' => '0.04'; requires 'Archive::Any::Lite' => '0.06'; requires 'Archive::Tar' => '1.48'; #depends on IO::Compress without memory leak requires 'Class::Accessor' => '0.19'; requires 'CPAN::DistnameInfo' => '0.06'; requires 'CPAN::Meta::YAML' => '0.008'; requires 'CPAN::Meta::Validator' => '2.133380'; requires 'File::Find::Object' => '0.2.1'; requires 'IO::Capture' => '0.05'; requires 'JSON::MaybeXS' => 0; requires 'Module::ExtractUse' => '0.33'; # for no support requires 'Module::Pluggable' => '2.96'; requires 'Set::Scalar' => 0; requires 'Software::License' => '0.103008'; requires 'Software::License::CC_BY_SA_3_0' => 0; # installs whole Software::License::CCpack requires 'Text::Balanced' => 0; requires 'version' => '0.73'; on test => sub { requires 'Cwd' => 0; requires 'Test::More' => '0.88'; requires 'Test::FailWarnings' => 0; }; Module-CPANTS-Analyse-0.96/MANIFEST0000644000175000017500000000426112434531241016552 0ustar ishigakiishigakiAUTHORS Changes cpanfile lib/Module/CPANTS/Analyse.pm lib/Module/CPANTS/Kwalitee.pm lib/Module/CPANTS/Kwalitee/BrokenInstaller.pm lib/Module/CPANTS/Kwalitee/CpantsErrors.pm lib/Module/CPANTS/Kwalitee/Distname.pm lib/Module/CPANTS/Kwalitee/Distros.pm lib/Module/CPANTS/Kwalitee/Files.pm lib/Module/CPANTS/Kwalitee/FindModules.pm lib/Module/CPANTS/Kwalitee/License.pm lib/Module/CPANTS/Kwalitee/Manifest.pm lib/Module/CPANTS/Kwalitee/MetaYML.pm lib/Module/CPANTS/Kwalitee/NeedsCompiler.pm lib/Module/CPANTS/Kwalitee/Pod.pm lib/Module/CPANTS/Kwalitee/Prereq.pm lib/Module/CPANTS/Kwalitee/Repackageable.pm lib/Module/CPANTS/Kwalitee/Signature.pm lib/Module/CPANTS/Kwalitee/Uses.pm lib/Module/CPANTS/Kwalitee/Version.pm Makefile.PL MANIFEST This list of files MANIFEST.SKIP README t/00_load.t t/05_testdir.t t/05_testfile.t t/analyse/manifest.t t/analyse/pod.t t/lib/Module/CPANTS/TestAnalyse.pm t/older_test_kwalitee.t t/x_cpants.t TODO xt/99_critic.t xt/99_pod.t xt/99_pod_coverage.t xt/kwalitee.t xt/kwalitee/has_abstract_in_pod.t xt/kwalitee/has_buildtool.t xt/kwalitee/has_changelog.t xt/kwalitee/has_human_readable_license.t xt/kwalitee/has_known_license_in_source_file.t xt/kwalitee/has_license_in_source_file.t xt/kwalitee/has_manifest.t xt/kwalitee/has_meta_yml.t xt/kwalitee/has_readme.t xt/kwalitee/has_separate_license_file.t xt/kwalitee/has_tests.t xt/kwalitee/has_tests_in_t_dir.t xt/kwalitee/manifest_matches_dist.t xt/kwalitee/meta_json_conforms_to_known_spec.t xt/kwalitee/meta_json_is_parsable.t xt/kwalitee/meta_yml_conforms_to_known_spec.t xt/kwalitee/meta_yml_declares_perl_version.t xt/kwalitee/meta_yml_has_license.t xt/kwalitee/meta_yml_has_provides.t xt/kwalitee/meta_yml_has_repository_resource.t xt/kwalitee/meta_yml_is_parsable.t xt/kwalitee/no_abstract_stub_in_pod.t xt/kwalitee/no_broken_auto_install.t xt/kwalitee/no_broken_module_install.t xt/kwalitee/no_stdin_for_prompting.t xt/kwalitee/no_symlinks.t xt/kwalitee/proper_libs.t xt/kwalitee/Test.pm xt/kwalitee/use_strict.t xt/kwalitee/use_warnings.t xt/strict_warnings_equiv.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Module-CPANTS-Analyse-0.96/MANIFEST.SKIP0000644000175000017500000000151712142374510017320 0ustar ishigakiishigaki# Avoid version control files. \bRCS\b \bCVS\b \bSCCS\b ,v$ \B\.svn\b \B\.git\b \B\.gitignore\b \b_darcs\b \B\.cvsignore$ # Avoid VMS specific MakeMaker generated files \bDescrip.MMS$ \bDESCRIP.MMS$ \bdescrip.mms$ # Avoid Makemaker generated and utility files. \bMANIFEST\.bak \bMakefile$ \bblib/ \bMakeMaker-\d \bpm_to_blib\.ts$ \bpm_to_blib$ \bblibdirs\.ts$ # 6.18 through 6.25 generated this # Avoid Module::Build generated and utility files. \bBuild$ \b_build/ \bBuild.bat$ \bBuild.COM$ \bBUILD.COM$ \bbuild.com$ # Avoid temp and backup files. ~$ \.old$ \#$ \b\.# \.bak$ \.tmp$ \.# \.rej$ # Avoid OS-specific files/dirs # Mac OSX metadata \B\.DS_Store # Mac OSX SMB mount metadata files \B\._ # Avoid Devel::Cover and Devel::CoverX::Covered files. \bcover_db\b \bcovered\b # Avoid MYMETA files ^MYMETA\. ^Module-CPANTS-Analyse Module-CPANTS-Analyse-0.96/xt/0000755000175000017500000000000012434531241016051 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/xt/kwalitee.t0000644000175000017500000000101612411273577020053 0ustar ishigakiishigakiuse strict; use warnings; use FindBin; use Test::More tests => 1; use Module::CPANTS::Kwalitee; my %names = map {$_ => 1} Module::CPANTS::Kwalitee->new->all_indicator_names; my %files = map {$_ => 1} glob "$FindBin::Bin/kwalitee/*.t"; my @errors; for (keys %names) { my $file = "$FindBin::Bin/kwalitee/$_.t"; if (exists $files{$file}) { delete $files{$file}; } else { push @errors, "$file is missing"; } } push @errors, "$_ is obsolete" for keys %files; ok !@errors, "no errors" or diag join "\n", @errors; Module-CPANTS-Analyse-0.96/xt/99_pod.t0000644000175000017500000000024612411273577017355 0ustar ishigakiishigaki#!perl -T use strict; use warnings; use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; all_pod_files_ok(); Module-CPANTS-Analyse-0.96/xt/kwalitee/0000755000175000017500000000000012434531241017656 5ustar ishigakiishigakiModule-CPANTS-Analyse-0.96/xt/kwalitee/meta_yml_has_provides.t0000644000175000017500000000101312411273600024410 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['TOBYINK/Platform-Windows-0.002.tar.gz', 0], # 2206 ['TOBYINK/Platform-Unix-0.002.tar.gz', 0], # 2264 ['COOLMEN/Test-More-Color-0.04.tar.gz', 0], # 2963 ['COOLMEN/Test-Mojo-More-0.04.tar.gz', 0], # 4301 ['SMUELLER/Math-SymbolicX-Complex-1.01.tar.gz', 0], # 4719 ['CHENRYN/Nagios-Plugin-ByGmond-0.01.tar.gz', 0], # 5159 ['SMUELLER/Math-Symbolic-Custom-CCompiler-1.03.tar.gz', 0], # 5244 ['LTP/Game-Life-0.05.tar.gz', 0], # 6535 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_yml_has_license.t0000644000175000017500000000120112411273600024176 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['CHENGANG/Log-Lite-0.05.tar.gz', 0], # 2739 ['SCILLEY/POE/Component/IRC/Plugin/IRCDHelp-0.02.tar.gz', 0], # 3243 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['HITHIM/Socket-Mmsg-0.02.tar.gz', 0], # 3946 ['FAYLAND/Acme-CPANAuthors-Chinese-0.26.tar.gz', 0], # 4474 ['BENNIE/ACME-KeyboardMarathon-1.15.tar.gz', 0], # 4479 ['ALEXP/Catalyst-Model-DBI-0.32.tar.gz', 0], # 4686 ['YTURTLE/Nephia-Plugin-Response-YAML-0.01.tar.gz', 0], # 4948 ['CHENRYN/Nagios-Plugin-ByGmond-0.01.tar.gz', 0], # 5159 ['IAMCAL/Flickr-API-1.06.tar.gz', 0], # 5172 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_meta_yml.t0000644000175000017500000000107512411273600022505 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['UNBIT/Net-uwsgi-1.1.tar.gz', 0], # 2409 ['ANANSI/Anansi-Singleton-0.02.tar.gz', 0], # 2664 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['DAVIEIRA/Data_Translate-0.3.tar.gz', 0], # 2970 ['ANANSI/Anansi-Class-0.03.tar.gz', 0], # 3028 ['ANANSI/Anansi-Actor-0.04.tar.gz', 0], # 3157 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['MANIGREW/SEG7-1.0.1.tar.gz', 0], # 3847 ['HITHIM/Socket-Mmsg-0.02.tar.gz', 0], # 3946 ['STEFANOS/Net-SMTP_auth-SSL-0.2.tar.gz', 0], # 4058 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_json_is_parsable.t0000644000175000017500000000104212411273600024360 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( # invalid control characters in abstract ['JOHND/Data-Properties-YAML-0.04.tar.gz', 0], # \r ['WINFINIT/Catalyst-Plugin-ModCluster-0.02.tar.gz', 0], # \t # '"' expected ['SHURD/DMTF-CIM-WSMan-v0.09.tar.gz', 0], ['RFREIMUTH/RandomJungle-0.05.tar.gz', 0], # VMS ['PFAUT/VMS-Time-0_1.zip', 0], # malformed JSON string ['MAXS/Palm-MaTirelire-1.12.tar.gz', 0], # \x{fffd} # illegal backslash escape sequence ['JHTHORSEN/Convos-0.6.tar.gz', 0], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/no_broken_auto_install.t0000644000175000017500000000120212411273600024565 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['GUGOD/WWW-Shorten-0rz-0.07.tar.gz', 0], # 14671 ['CLKAO/IPC-Run-SafeHandles-0.04.tar.gz', 0], # 19431 ['TBR/WKHTMLTOPDF-0.02.tar.gz', 0], # 19819 ['MONS/Test-More-UTF8-0.04.tar.gz', 0], # 19952 ['SKAUFMAN/Template-Plugin-Devel-StackTrace-0.02.tar.gz', 0], # 19960 ['LUKEC/Test-Mock-LWP-0.06.tar.gz', 0], # 20054 ['GAOU/Ubigraph-0.05.tar.gz', 0], # 20092 ['YVESAGO/Jifty-Plugin-Userpic-0.9.tar.gz', 0], # 20161 ['YVESAGO/Jifty-Plugin-SiteNews-0.9.tar.gz', 0], # 20249 ['BOLAV/DateTime-Format-Duration-DurationString-0.03.tar.gz', 0], # 20527 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/no_broken_module_install.t0000644000175000017500000000135612411273600025114 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['GUGOD/Kwiki-Session-0.01.tar.gz', 0], # 7880 ['GUGOD/Kwiki-Widgets-Links-0.01.tar.gz', 0], # 8214 ['CLSUNG/Lingua-ZH-Segment-0.02.tar.gz', 0], # 8236 ['RHUNDT/Catalyst-Model-Oryx-0.01.tar.gz', 0], # 8255 ['XERN/Template-Plugin-IO-All-0.01.tar.gz', 0], # 8462 ['IJLIAO/WWW-Scraper-ISBN-TWSrbook_Driver-0.01.tar.gz', 0], # 9139 ['IJLIAO/WWW-Scraper-ISBN-TWYlib_Driver-0.01.tar.gz', 0], # 9199 ['IJLIAO/WWW-Scraper-ISBN-TWTenlong_Driver-0.01.tar.gz', 0], # 9210 ['IJLIAO/WWW-Scraper-ISBN-TWPchome_Driver-0.01.tar.gz', 0], # 9308 ['IJLIAO/WWW-Scraper-ISBN-TWSoidea_Driver-0.01.tar.gz', 0], # 9348 # M::I 1.04 ['KARMAN/Dezi-UI-0.001000.tar.gz', 0], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/proper_libs.t0000644000175000017500000000136412411273600022364 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( # pm files not in the lib/base dir ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 (Google/TTS.pm) # didn't extract nicely (dot underscore files) ['AQUILINA/WWW-LaQuinta-Returns-0.02.tar.gz', 0], # 4055 # multiple pm files in the basedir ['DGRAHAM/simpleXMLParse/simplexmlparse_v1.4.tar.gz', 0], # 4336 # no modules ['LAWSONK/Gtk2-Ex-MPlayerEmbed-0.03.tar.gz', 1], # 465 ['WOLDRICH/App-epic-0.014.tar.gz', 1], # 812 ['TAG/AnyEvent-Peer39-0.32.tar.gz', 1], # 824 ['CASIANO/Git-Export-0.04.tar.gz', 1], # 2593 ['MILOVIDOV/APP-Yatranslate-0.02.tar.gz', 1], # 3773 ['DBR/pdoc-0.900.tar.gz', 1], # 3876 ['MUIR/modules/rinetd.pl-1.2.tar.gz', 1], # 4319 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/use_warnings.t0000644000175000017500000000134012411273600022542 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['TOBYINK/Platform-Windows-0.002.tar.gz', 0], # 2206 ['TOBYINK/Platform-Unix-0.002.tar.gz', 0], # 2264 ['BOOK/Acme-MetaSyntactic-errno-1.003.tar.gz', 0], # 2889 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['TXH/Template-Plugin-Filter-MinifyHTML-0.02.tar.gz', 0], # 3484 ['LTP/Game-Life-0.05.tar.gz', 0], # 6535 ['PJB/Speech-Speakup-1.04.tar.gz', 0], # 7410 ['JBAZIK/Archive-Ar-1.15.tar.gz', 0], # 7983 ['SULLR/Net-SSLGlue-1.03.tar.gz', 0], # 8720 ['SHARYANTO/Term-ProgressBar-Color-0.00.tar.gz', 0], # 9746 # no .pm files ['RCLAMP/cvn-0.02.tar.gz', 1], # .pod without package declaration ['ETHER/Moose-2.1209.tar.gz', 1], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/manifest_matches_dist.t0000644000175000017500000000120512411273600024373 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['UNBIT/Net-uwsgi-1.1.tar.gz', 0], # 2409 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['COOLMEN/Test-More-Color-0.04.tar.gz', 0], # 2963 ['APIOLI/YAMC-0.2.tar.gz', 0], # 3245 ['BENMEYER/Finance-btce-0.02.tar.gz', 0], # 3575 ['SJQUINNEY/MooseX-Types-EmailAddress-1.1.2.tar.gz', 0], # 4257 ['RSHADOW/libmojolicious-plugin-human-perl_0.6.orig.tar.gz', 0], # 4504 ['LEPREVOST/Math-SparseMatrix-Operations-0.06.tar.gz', 0], # 4593 ['SRPATT/Finance-Bank-CooperativeUKPersonal-0.02.tar.gz', 0], # 4991 ['SULLR/Net-PcapWriter-0.71.tar.gz', 0], # 5337 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_yml_declares_perl_version.t0000644000175000017500000000101512411273600026275 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['TOBYINK/Platform-Windows-0.002.tar.gz', 0], # 2206 ['TOBYINK/Platform-Unix-0.002.tar.gz', 0], # 2264 ['COOLMEN/Test-More-Color-0.04.tar.gz', 0], # 2963 ['TXH/Template-Plugin-Filter-MinifyHTML-0.02.tar.gz', 0], # 3484 ['SMUELLER/Math-SymbolicX-Complex-1.01.tar.gz', 0], # 4719 ['SMUELLER/Math-Symbolic-Custom-CCompiler-1.03.tar.gz', 0], # 5244 ['LTP/Game-Life-0.05.tar.gz', 0], # 6535 ['KPEE/Carp-Growl-0.0.3.tar.gz', 0], # 6682 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/no_stdin_for_prompting.t0000644000175000017500000000113512411273600024622 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['GMCCAR/Jabber-SimpleSend-0.03.tar.gz', 0], # 3455 ['SPEEVES/Apache-AuthenNIS-0.13.tar.gz', 0], # 4517 ['SPEEVES/Apache2-AuthenSmb-0.01.tar.gz', 0], # 5219 ['KROW/DBIx-Password-1.9.tar.gz', 0], # 5478 ['GEOTIGER/Data-Fax-0.02.tar.gz', 0], # 5944 ['GEOTIGER/CGI-Getopt-0.13.tar.gz', 0], # 6014 ['SPEEVES/Apache2-AuthNetLDAP-0.01.tar.gz', 0], # 6855 ['SPEEVES/Apache-AuthNetLDAP-0.29.tar.gz', 0], # 6952 ['AMALTSEV/XAO-MySQL-1.02.tar.gz', 0], # 7242 ['BHODGES/Mail-IMAPFolderSearch-0.03.tar.gz', 0], # 7326 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_readme.t0000644000175000017500000000120512411273600022126 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['SEVEAS/Term-Multiplexed-0.1.0.tar.gz', 0], # 1701 ['SROMANOV/App-Nopaste-Service-Dpaste-0.01.tar.gz', 0], # 2448 ['SROMANOV/Games-Chess-Position-Unicode-0.01.tar.gz', 0], # 2629 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['BOOK/Bundle-MetaSyntactic-1.026.tar.gz', 0], # 3178 ['BENMEYER/Finance-btce-0.02.tar.gz', 0], # 3575 ['SYSADM/Mojolicious-Plugin-DeCSRF-0.94.tar.gz', 0], # 3654 ['BKB/Lingua-EN-PluralToSingular-0.06.tar.gz', 0], # 3747 ['MANIGREW/SEG7-1.0.1.tar.gz', 0], # 3847 ['BKB/Lingua-JA-Gairaigo-Fuzzy-0.02.tar.gz', 0], # 4159 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_yml_is_parsable.t0000644000175000017500000000144112411273600024213 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( # No META.yml ['UNBIT/Net-uwsgi-1.1.tar.gz', 1], # 2409 # Stream does not end with newline character ['SCILLEY/POE/Component/IRC/Plugin/IRCDHelp-0.02.tar.gz', 0], # 3243 # Error reading from file: utf8 "\xB0" does not map to Unicode ['WINTRU/Mica-1.a.0.tar.gz', 0], # 1196 # CPAN::Meta::YAML does not support a feature in line ['STRO/Task-CPANAuthors-STRO-PPMCreator-2009.1018.tar.gz', 0], # 1555 # CPAN::Meta::YAML failed to classify line ' --- #YAML:1.0' ['XPANEL/XPanel-0.0.7.tar.gz', 0], # 2207 # CPAN::Meta::YAML found bad indenting ['NUFFIN/Devel-STDERR-Indent-0.01.tar.gz', 0], # 2594 # CPAN::Meta::YAML found illegal characters ['SOCK/WWW-Search-Feedster-0.02.tar.gz', 0], # 3220 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_json_conforms_to_known_spec.t0000644000175000017500000000166712411273600026667 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( # scalar license ['DMAKI/XML-RSS-Liberal-0.04.tar.gz', 0], # no abstract ['MLEHMANN/AnyEvent-DBus-0.31.tar.gz', 0], # resource -> license ['BARBIE/Template-Plugin-Lingua-EN-NameCase-0.01.tar.gz', 0], # invalid license ['TOMO/src/Net-SMTPS-0.03.tar.gz', 0], # perl ['RSAVAGE/DBIx-Admin-CreateTable-2.08.tgz', 0], # artistic_2_0 # 'origin' for 'repository' does not have a URL scheme ['RJBS/Sub-Import-0.092800.tar.gz', 0], ['MARCEL/Permute-Named-1.100980.tar.gz', 0], # '' for 'repository' is not a valid URL. ['KEEDI/Pod-Weaver-Section-Encoding-0.100830.tar.gz', 0], # git@github.com:... does not have a URL authority ['TIMB/PostgreSQL-PLPerl-Trace-1.001.tar.gz', 0], # Custom key must begin with 'x_' or 'X_'. ['AVAR/Bot-Twatterhose-0.04.tar.gz', 0], # value is an undefined string ['TOBYINK/Return-Type-0.004.tar.gz', 0], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/use_strict.t0000644000175000017500000000157512411273600022234 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['TOBYINK/Platform-Windows-0.002.tar.gz', 0], # 2206 ['TOBYINK/Platform-Unix-0.002.tar.gz', 0], # 2264 ['SCILLEY/POE/Component/IRC/Plugin/IRCDHelp-0.02.tar.gz', 0], # 3243 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['TXH/Template-Plugin-Filter-MinifyHTML-0.02.tar.gz', 0], # 3484 ['ANANSI/Anansi-ObjectManager-0.06.tar.gz', 0], # 5246 ['MARCEL/Web-Library-0.01.tar.gz', 0], # 7345 ['PJB/Speech-Speakup-1.04.tar.gz', 0], # 7410 ['TEMPIRE/Eponymous-Hash-0.01.tar.gz', 0], # 8503 ['SULLR/Net-SSLGlue-1.03.tar.gz', 0], # 8720 # use 5.012 and higher ['ZDM/Pharaoh-BootStrap-3.00.tar.gz', 1], # use 5.12.0 ['MALLEN/Acme-Github-Test-0.03.tar.gz', 1], # use 5.014 # no .pm files ['RCLAMP/cvn-0.02.tar.gz', 1], # .pod without package declaration ['ETHER/Moose-2.1209.tar.gz', 1], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/no_symlinks.t0000644000175000017500000000130612411273600022405 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; Test::More::plan skip_all => "This test doesn't work well under Windows" if $^O eq 'MSWin32'; xt::kwalitee::Test::run( ['CMORRIS/Parse-Extract-Net-MAC48-0.01.tar.gz', 0], # 3094 ['BRUMLEVE/autobless-1.0.1.tar.gz', 0], # 3318 ['BRUMLEVE/wildproto-1.0.1.tar.gz', 0], # 3617 ['BRUMLEVE/vm-1.0.1.tar.gz', 0], # 4236 ['CRUSOE/Template-Plugin-Filter-ANSIColor-0.0.3.tar.gz', 0], # 4963 ['GSLONDON/Devel-AutoProfiler-1.200.tar.gz', 0], # 6139 ['PHAM/Business-Stripe-0.04.tar.gz', 0], # 6412 ['GAVINC/Config-Directory-0.05.tar.gz', 0], # 8774 ['NETVARUN/Net-Semantics3-0.10.tar.gz', 0], # 8930 ['GAVINC/File-DirCompare-0.7.tar.gz', 0], # 9018 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_tests_in_t_dir.t0000644000175000017500000000112612411273600023704 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['SEVEAS/Term-Multiplexed-0.1.0.tar.gz', 0], # 1701 ['UNBIT/Net-uwsgi-1.1.tar.gz', 0], # 2409 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['MUIR/modules/rinetd.pl-1.2.tar.gz', 0], # 4319 ['SRPATT/Finance-Bank-CooperativeUKPersonal-0.02.tar.gz', 0], # 4991 ['IAMCAL/Flickr-API-1.06.tar.gz', 0], # 5172 ['PJB/Speech-Speakup-1.04.tar.gz', 0], # 7410 ['FIBO/Task-Viral-20130508.tar.gz', 0], # 8128 ['ADAMBA/Algorithm-MOS-0.001.tar.gz', 0], # 8570 ['FIBO/Task-BeLike-FIBO-20130508.tar.gz', 0], # 8922 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/no_abstract_stub_in_pod.t0000644000175000017500000000066512411273600024733 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( # h2xs ['ERICW/Roll-1.0.tar.gz', 0], # 2188 ['IEFREMOV/Statistics-CountAverage-0.02.tar.gz', 0], # 2839 ['HSLEE/Search-Equidistance-0.01.tar.gz', 0], # 3142 ['OPITZ/URL-Grab-1.4.tar.gz', 0], # 3210 # Module::Starter etc ['IKEBE/WebService-Livedoor-Auth-0.01.tar.gz', 0], # Minilla ['NNUTTER/Git-Repository-Plugin-Gerrit-0.03.tar.gz', 0], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_tests.t0000644000175000017500000000120712411273600022035 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['MSTROUT/pumpkin-pragma-placeholder-0.001.tar.gz', 0], # 961 ['SEVEAS/Term-Multiplexed-0.1.0.tar.gz', 0], # 1701 ['PBLAIR/Copy-From-Git-0.000302.tar.gz', 0], # 2235 ['UNBIT/Net-uwsgi-1.1.tar.gz', 0], # 2409 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['NKH/Devel-Depend-Cl-0.06.tar.gz', 0], # 3540 ['SEMUELF/WWW-Github-Files-0.02.tar.gz', 0], # 3634 ['MUIR/modules/rinetd.pl-1.2.tar.gz', 0], # 4319 ['SRPATT/Finance-Bank-CooperativeUKPersonal-0.02.tar.gz', 0], # 4991 ['NANARDON/RT-Interface-Email-Filter-CheckMessageId-0.1.tar.gz', 0], # 5398 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_buildtool.t0000644000175000017500000000114112411273600022665 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['LAWSONK/Gtk2-Ex-MPlayerEmbed-0.03.tar.gz', 0], # 465 ['HEDWIG/Template-Plugin-Duration-0.01.tar.gz', 0], # 474 ['WEBY/Mojolicious-Plugin-Mobi-0.02.tar.gz', 0], # 474 ['TIMA/Amazon-Bezos-0.001.tar.gz', 0], # 510 ['LEOCHARRE/LEOCHARRE-X11-WMCtrl-0.01.tar.gz', 0], # 514 ['WOLDRICH/Bundle-Woldrich-Term-0.02.tar.gz', 0], # 530 ['WOLDRICH/App-epic-0.014.tar.gz', 0], # 812 ['TAG/AnyEvent-Peer39-0.32.tar.gz', 0], # 824 ['ABCABC/CFTP_01.tar.gz', 0], # 897 ['DAMBAR/Catalyst-Plugin-Imager-0.01.tar.gz', 0], # 1026 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_manifest.t0000644000175000017500000000111412411273600022476 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['LAWSONK/Gtk2-Ex-MPlayerEmbed-0.03.tar.gz', 0], # 465 ['WEBY/Mojolicious-Plugin-Mobi-0.02.tar.gz', 0], # 474 ['WOLDRICH/Bundle-Woldrich-Term-0.02.tar.gz', 0], # 530 ['WOLDRICH/App-epic-0.014.tar.gz', 0], # 812 ['TAG/AnyEvent-Peer39-0.32.tar.gz', 0], # 824 ['ABCABC/CFTP_01.tar.gz', 0], # 897 ['SAULIUS/Date-Holidays-LT-0.01.tar.gz', 0], # 1532 ['RUFF/DJabberd-Authen-Dovecot-0.1.tar.gz', 0], # 2105 ['UNBIT/Net-uwsgi-1.1.tar.gz', 0], # 2409 ['GVENKAT/JSON-HPack-0.0.3.tar.gz', 0], # 2475 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_changelog.t0000644000175000017500000000120712411273600022622 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['UNBIT/Net-uwsgi-1.1.tar.gz', 0], # 2409 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['BENNING/Math-BaseMulti-1.00.tar.gz', 0], # 2942 ['HEYTRAV/Mojolicious-Plugin-Libravatar-1.08.tar.gz', 0], # 3415 ['TXH/Template-Plugin-Filter-MinifyHTML-0.02.tar.gz', 0], # 3484 ['MANIGREW/SEG7-1.0.1.tar.gz', 0], # 3847 ['MUIR/modules/rinetd.pl-1.2.tar.gz', 0], # 4319 ['GSB/WWW-Crab-Client-0.03.tar.gz', 0], # 4352 ['RSHADOW/libmojolicious-plugin-human-perl_0.6.orig.tar.gz', 0], # 4504 ['SRPATT/Finance-Bank-CooperativeUKPersonal-0.02.tar.gz', 0], # 4991 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_separate_license_file.t0000644000175000017500000000116012411273600025176 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['TOBYINK/Platform-Windows-0.002.tar.gz', 0], # 2206 ['TOBYINK/Platform-Unix-0.002.tar.gz', 0], # 2264 ['BOOK/Acme-MetaSyntactic-errno-1.003.tar.gz', 0], # 2889 ['COOLMEN/Test-More-Color-0.04.tar.gz', 0], # 2963 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['HITHIM/Socket-Mmsg-0.02.tar.gz', 0], # 3946 ['COOLMEN/Test-Mojo-More-0.04.tar.gz', 0], # 4301 ['MUGENKEN/Bundle-Unicheck-0.02.tar.gz', 0], # 4596 ['SMUELLER/Math-SymbolicX-Complex-1.01.tar.gz', 0], # 4719 ['CHENRYN/Nagios-Plugin-ByGmond-0.01.tar.gz', 0], # 5159 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_yml_has_repository_resource.t0000644000175000017500000000027412411273600026713 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['ISHIGAKI/Acme-CPANAuthors-Japanese-0.131002.tar.gz', 0], ['ISHIGAKI/Acme-CPANAuthors-0.23.tar.gz', 1], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/meta_yml_conforms_to_known_spec.t0000644000175000017500000000231412411273600026505 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( # '' for 'Carp' is not a valid version. ['MATIU/WWW-AfinimaKi-0.1.tar.gz', 0], # 518 # 'HASH(0xb8924f0)' for 'repository' does not have a URL scheme ['JBERGER/Alien-GSL-0.01.tar.gz', 0], # 556 # License 'Public domain' is invalid (license) ['SEVEAS/Term-Multiplexed-0.2.2.tar.gz', 0], # 1683 # Missing mandatory field, 'author' (author) ['ANDK/CPAN-Test-Dummy-Perl5-Make-CircDepeOne-1.00.tar.gz', 0], # 1893 # 'ExtUtils::MakeMaker version 6.17' for 'generated_by' is not a valid version. (requires -> generated_by) ['MITTI/PDF-Report-Table-1.00.tar.gz', 0], # 2300 # Expected a map structure from string or file. (requires) ['ANDK/CPAN-Test-Dummy-Perl5-Make-Expect-1.00.tar.gz', 0], # 2323 # 'DateTime::Event::Easter' for 'Time::Piece' is not a valid version. ['CLIFFORDJ/Date-Holidays-EnglandWales-0.01.tar.gz', 0], # 3085 # Key 'Acme::Unic<ö>de' is not a legal module name. ['SCHWIGON/acme-unicode/Acme-Uenicoede-0.0501.tar.gz', 0], # 3651 # 'meta-spec' => '1.1' is kind of broken, but it's not regarded # as a fatal error as of CPAN::Meta 2.132830. ['JOSEPHW/XML-Writer-0.545.tar.gz', 1], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_abstract_in_pod.t0000644000175000017500000000146612411273600024035 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['HACHI/MogileFS-Plugin-MetaData-0.01.tar.gz', 0], # 2059 ['URI/Acme-Madness-1.00.tar.gz', 0], # 2090 ['PJF/Payroll-AU-PAYG-0.01.tar.gz', 0], # 2097 ['LLAP/Plack-Middleware-OptionsOK-0.01.tar.gz', 0], # 2117 ['GMCCAR/Acme-ManekiNeko-0.03.tar.gz', 0], # 2161 ['KALEYCHEV/Math-Combination_out-0.21.tar.gz', 0], # 2163 ['LEOCHARRE/Getopt-Std-Strict-1.01.tar.gz', 0], # 2165 ['TJC/CGI-Untaint-telephone-0.03.tar.gz', 0], # 2178 ['STRZELEC/CGI-SpeedUp-0.11.tar.gz', 0], # 2187 # has a dash, though not in the same line as the package ['HODEL/Brasil-Checar-CGC-1.01a.tar.gz', 0], # 2018 # abstract in non-.pm file ['LEONT/App-find2perl-1.003.tar.gz', 1], # invalid =encoding (utf-8;) ['INGY/IO-All-0.40.tar.gz', 0], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/Test.pm0000644000175000017500000000217512411273577021152 0ustar ishigakiishigakipackage # xt::kwalitee::Test; use strict; use warnings; use FindBin; use Test::More; use JSON::MaybeXS; BEGIN { eval { require WorePAN }; plan skip_all => "requires WorePAN" if $@ or $WorePAN::VERSION < 0.09; } use Module::CPANTS::Analyse; sub run { my (@tests) = @_; my ($caller, $file) = caller; my ($name) = $file =~ /(\w+)\.t$/; for my $test (@tests) { my $worepan = WorePAN->new( root => "$FindBin::Bin/tmp", files => [$test->[0]], no_indices => 1, use_backpan => 1, no_network => 0, cleanup => 1, ); my $tarball = $worepan->file($test->[0]); my $analyzer = Module::CPANTS::Analyse->new({dist => $tarball}); $analyzer->unpack; $analyzer->analyse; my $metric = $analyzer->mck->get_indicators_hash->{$name}; my $result = $metric->{code}->($analyzer->d); is $result => $test->[1], "$test->[0] $name: $result"; if (!$result) { my $details = $metric->{details}->($analyzer->d) || ''; ok $details, ref $details ? encode_json($details) : $details; } if ($test->[2]) { note explain $analyzer->d; } } done_testing; } 1; Module-CPANTS-Analyse-0.96/xt/kwalitee/has_human_readable_license.t0000644000175000017500000000102412411273600025321 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['JJUDD/DBIx-Class-TimeStamp-HiRes-v1.0.0.tar.gz', 0], # 2596 ['NIELSD/Speech-Google-0.5.tar.gz', 0], # 2907 ['SCILLEY/POE/Component/IRC/Plugin/IRCDHelp-0.02.tar.gz', 0], # 3243 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['JEEN/WebService-Aladdin-0.08.tar.gz', 0], # 4287 ['SMUELLER/Math-SymbolicX-Complex-1.01.tar.gz', 0], # 4719 ['IAMCAL/Flickr-API-1.06.tar.gz', 0], # 5172 ['ANANSI/Anansi-ObjectManager-0.06.tar.gz', 0], # 5246 ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_license_in_source_file.t0000644000175000017500000000110312411273600025355 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['JJUDD/DBIx-Class-TimeStamp-HiRes-v1.0.0.tar.gz', 0], # 2596 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['SMUELLER/Math-SymbolicX-Complex-1.01.tar.gz', 0], # 4719 ['IAMCAL/Flickr-API-1.06.tar.gz', 0], # 5172 # =head1 AUTHOR / COPYRIGHT / LICENSE ['BJOERN/AI-CRM114-0.01.tar.gz', 1], # has =head1 COPYRIGHT AND LICENSE without closing =cut ['DAMI/DBIx-DataModel-2.39.tar.gz', 1], # has =head1 LICENSE followed by =head1 COPYRIGHT ['YSASAKI/App-pfswatch-0.08.tar.gz', 1], ); Module-CPANTS-Analyse-0.96/xt/kwalitee/has_known_license_in_source_file.t0000644000175000017500000000135112411273600026576 0ustar ishigakiishigakiuse strict; use warnings; use xt::kwalitee::Test; xt::kwalitee::Test::run( ['JJUDD/DBIx-Class-TimeStamp-HiRes-v1.0.0.tar.gz', 0], # 2596 ['ANANSI/Anansi-Library-0.02.tar.gz', 0], # 3365 ['SMUELLER/Math-SymbolicX-Complex-1.01.tar.gz', 0], # 4719 ['IAMCAL/Flickr-API-1.06.tar.gz', 0], # 5172 # =head1 AUTHOR / COPYRIGHT / LICENSE ['BJOERN/AI-CRM114-0.01.tar.gz', 1], # has =head1 COPYRIGHT AND LICENSE without closing =cut ['DAMI/DBIx-DataModel-2.39.tar.gz', 1], # has =head1 LICENSE followed by =head1 COPYRIGHT ['YSASAKI/App-pfswatch-0.08.tar.gz', 1], # ignore inc/Devel/CheckLib ['DJERIUS/Lua-API-0.02.tar.gz', 1], # https://github.com/cpants/www-cpants/issues/44 ['NEILB/Business-CCCheck-0.09.tar.gz', 1], ); Module-CPANTS-Analyse-0.96/xt/99_critic.t0000644000175000017500000000051412411273577020046 0ustar ishigakiishigakiuse strict; use warnings; use Test::More; eval { require Test::Perl::Critic; import Test::Perl::Critic; }; plan skip_all => 'Test::Perl::Critic only run for author tests' unless $ENV{AUTHOR_TEST}; plan skip_all => 'Test::Perl::Critic required to criticise code' if $@; all_critic_ok('blib'); #all_critic_ok('blib', 't'); Module-CPANTS-Analyse-0.96/xt/99_pod_coverage.t0000644000175000017500000000030312411273577021222 0ustar ishigakiishigaki#!perl use strict; use warnings; use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; all_pod_coverage_ok(); Module-CPANTS-Analyse-0.96/xt/strict_warnings_equiv.t0000644000175000017500000000537412411273600022675 0ustar ishigakiishigakiuse strict; use warnings; use FindBin; use File::Path; use Test::More; BEGIN { plan skip_all => "This is an author test" unless $ENV{AUTHOR_TESTING}; plan skip_all => "requires WorePAN" unless eval { require WorePAN; WorePAN->VERSION(0.04) }; plan skip_all => "This doesn't run well under Windows" if $^O eq 'MSWin32'; } use Module::CPANTS::Kwalitee::Uses; my $pid = $$; my $tempdir = "$FindBin::Bin/tmplib/"; mkpath $tempdir unless -d $tempdir; END { rmtree $tempdir if $pid eq $$ && -d $tempdir }; my %map = ( 'Catmandu::Sane' => 'Catmandu', 'Mojo::Base' => 'Mojolicious', 'perl5i::1' => 'perl5i', 'perl5i::2' => 'perl5i', 'perl5i::latest' => 'perl5i', ); my %flag_to_enable = ( 'Mojo::Base' => '-base', 'Spiffy' => '-Base', ); for my $module (@Module::CPANTS::Kwalitee::Uses::STRICT_EQUIV) { my $res = test($module); unless ($res) { note "SKIP $module"; next; } ok $res->{strict}, "$module enforces strict"; ok !$res->{warnings}, "$module does not enforce warnings"; note; } for my $module (@Module::CPANTS::Kwalitee::Uses::WARNINGS_EQUIV) { next if $module eq 'warnings::compat'; my $res = test($module); unless ($res) { note "SKIP $module"; next; } ok !$res->{strict}, "$module does not enforce strict"; ok $res->{warnings}, "$module enforces warnings"; note; } for my $module (@Module::CPANTS::Kwalitee::Uses::STRICT_WARNINGS_EQUIV) { my $res = test($module); unless ($res) { note "SKIP $module"; next; } ok $res->{strict}, "$module enforces strict"; ok $res->{warnings}, "$module enforce warnings"; note; } sub test { my $module = shift; my $dist = $map{$module} || $module; $dist =~ s|::|-|g; local $Parse::PMFile::ALLOW_DEV_VERSION = 1; my $worepan = WorePAN->new( root => "$FindBin::Bin/tmp/", dists => {$dist => 0}, use_backpan => 0, no_network => 0, verbose => 0, cleanup => 1, ); my ($version, $file) = $worepan->look_for($module); $file ||= $module; system("cpanm -nq -l $tempdir $file"); my $res = {}; { open my $fh, '>', 'strict_test.pl' or die $!; my $flag = $flag_to_enable{$module} || ''; print $fh <<"TEST_END"; package # Test::CPANTS::StrictWarningsEquiv; no warnings; my \$default_warning_bits; BEGIN { \$default_warning_bits = \${^WARNING_BITS}; } use local::lib "$tempdir"; use $module $flag; BEGIN { print "module: $module\n"; print "strict: ", (\$^H & (0x00000002|0x00000200|0x00000400)) ? 1 : 0, "\n"; print "warnings: ", (\${^WARNING_BITS} ne \$default_warning_bits ? 1 : 0), "\n"; } TEST_END close $fh; my $output = `$^X strict_test.pl`; return if $output =~ /Can't locate/; ($res->{strict}) = $output =~ /strict: ([01])/; ($res->{warnings}) = $output =~ /warnings: ([01])/; } $res; } done_testing;