@@ -20,7 +20,7 @@ my %module_build_args = (
"Mickey Nasriachi <mickey\@cpan.org>"
],
"dist_name" => "MetaCPAN-Client",
- "dist_version" => "1.003000",
+ "dist_version" => "1.006000",
"license" => "perl",
"module_name" => "MetaCPAN::Client",
"recommends" => {},
@@ -31,6 +31,7 @@ my %module_build_args = (
"JSON::MaybeXS" => 0,
"Moo" => 0,
"Moo::Role" => 0,
+ "Safe::Isa" => 0,
"Search::Elasticsearch" => "1.10",
"Search::Elasticsearch::Scroll" => 0,
"Try::Tiny" => 0,
@@ -44,6 +45,7 @@ my %module_build_args = (
"IPC::Open3" => 0,
"Test::Fatal" => 0,
"Test::More" => 0,
+ "base" => 0,
"perl" => "5.006"
}
);
@@ -56,6 +58,7 @@ my %fallback_build_requires = (
"Module::Build" => "0.3601",
"Test::Fatal" => 0,
"Test::More" => 0,
+ "base" => 0,
"perl" => "5.006"
);
@@ -1,5 +1,19 @@
Revision history for MetaCPAN-Client (previously MetaCPAN-API)
+1.006000 24.06.14
+ * Add 'recent' functionality (latest releases)
+
+1.005000 09.06.14
+ * Add Pod object to allow direct POD fetching (reneeb)
+ * Support single element without wrapping arrayref in structures
+ * Updated documents - basic/complex search links and wording (tsibley)
+
+1.004001 27.05.14
+ * correct rev_deps query
+
+1.004000 27.05.14
+ * reworked ResultSet to allow RS in non-scrolled searches.
+
1.003000 05.05.14
* Add proper POD fetching from module/file objects.
* GH #1: Switch from JSON.pm to JSON::MaybeXS.
@@ -22,7 +22,7 @@ This is free software, licensed under:
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
- 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -7,6 +7,7 @@ META.yml
Makefile.PL
README
dist.ini
+ex_complex.pl
examples/author-country.pl
examples/author.pl
examples/author_releases.pl
@@ -14,6 +15,10 @@ examples/complex-either-and.pl
examples/complex-either-not.pl
examples/complex.pl
examples/distribution.pl
+examples/module.pl
+examples/pod.pl
+examples/recent.pl
+examples/recent_today.pl
examples/release.pl
examples/rev_deps-recursive.pl
examples/rev_deps.pl
@@ -23,11 +28,13 @@ lib/MetaCPAN/Client/Distribution.pm
lib/MetaCPAN/Client/Favorite.pm
lib/MetaCPAN/Client/File.pm
lib/MetaCPAN/Client/Module.pm
+lib/MetaCPAN/Client/Pod.pm
lib/MetaCPAN/Client/Rating.pm
lib/MetaCPAN/Client/Release.pm
lib/MetaCPAN/Client/Request.pm
lib/MetaCPAN/Client/ResultSet.pm
lib/MetaCPAN/Client/Role/Entity.pm
+switching_to_filters
t/00-compile.t
t/api/_get.t
t/api/_get_or_search.t
@@ -37,6 +44,7 @@ t/api/distribution.t
t/api/favorite.t
t/api/file.t
t/api/module.t
+t/api/pod.t
t/api/rating.t
t/api/release.t
t/author-critic.t
@@ -46,3 +54,4 @@ t/release-pod-coverage.t
t/release-pod-syntax.t
t/request.t
t/resultset.t
+wishlist
@@ -10,12 +10,13 @@ build_requires:
Module::Build: 0.3601
Test::Fatal: 0
Test::More: 0
+ base: 0
perl: 5.006
configure_requires:
ExtUtils::MakeMaker: 6.30
Module::Build: 0.3601
dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.120921'
+generated_by: 'Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.131560'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -30,11 +31,12 @@ requires:
JSON::MaybeXS: 0
Moo: 0
Moo::Role: 0
+ Safe::Isa: 0
Search::Elasticsearch: 1.10
Search::Elasticsearch::Scroll: 0
Try::Tiny: 0
strict: 0
warnings: 0
resources:
- repository: git://github.com/CPAN-API/metacpan-client.git
-version: 1.003000
+ repository: https://github.com/CPAN-API/metacpan-client.git
+version: 1.006000
@@ -29,6 +29,7 @@ my %WriteMakefileArgs = (
"JSON::MaybeXS" => 0,
"Moo" => 0,
"Moo::Role" => 0,
+ "Safe::Isa" => 0,
"Search::Elasticsearch" => "1.10",
"Search::Elasticsearch::Scroll" => 0,
"Try::Tiny" => 0,
@@ -40,9 +41,10 @@ my %WriteMakefileArgs = (
"IO::Handle" => 0,
"IPC::Open3" => 0,
"Test::Fatal" => 0,
- "Test::More" => 0
+ "Test::More" => 0,
+ "base" => 0
},
- "VERSION" => "1.003000",
+ "VERSION" => "1.006000",
"test" => {
"TESTS" => "t/*.t t/api/*.t"
}
@@ -59,11 +61,13 @@ my %FallbackPrereqs = (
"Module::Build" => "0.3601",
"Moo" => 0,
"Moo::Role" => 0,
+ "Safe::Isa" => 0,
"Search::Elasticsearch" => "1.10",
"Search::Elasticsearch::Scroll" => 0,
"Test::Fatal" => 0,
"Test::More" => 0,
"Try::Tiny" => 0,
+ "base" => 0,
"strict" => 0,
"warnings" => 0
);
@@ -3,7 +3,7 @@ NAME
API
VERSION
- version 1.003000
+ version 1.006000
SYNOPSIS
# simple usage
@@ -76,8 +76,8 @@ METHODS
search.
distribution
- my $dist = $mcpan->dist('MetaCPAN-Client');
- my $dist = $mcpan->dist($search_spec);
+ my $dist = $mcpan->distribution('MetaCPAN-Client');
+ my $dist = $mcpan->distribution($search_spec);
Finds a distribution by either its distribution name or by a search spec
defined by a hash reference. Since it is common to many other searches,
@@ -113,12 +113,20 @@ METHODS
reverse_dependencies
my $deps = $mcpan->reverse_dependencies('ElasticSearch');
- Return an array (ref) of MetaCPAN::Client::Release matching all releases
- that are dependent on a given module.
+ all MetaCPAN::Client::Release objects of releases that are dependent on
+ a given module, returned as MetaCPAN::Client::ResultSet.
rev_deps
Alias to "reverse_dependencies" described above.
+ recent
+ my $recent = $mcpan->recent(10);
+ my $recent = $mcpan->recent('today');
+
+ return the latest N releases, or all releases from today.
+
+ returns a MetaCPAN::Client::ResultSet of MetaCPAN::Client::Release.
+
pod
Not implemented yet.
@@ -129,8 +137,7 @@ SEARCH SPEC
The hash-based search spec is common to many searches. It is quite
feature-rich and allows to disambiguate different types of searches.
- Simple
- Simple searches just contain keys and values:
+ Basic search specs just contain a hash of keys and values:
my $author = $mcpan->author( { name => 'Micha Nasriachi' } );
@@ -5,7 +5,7 @@ license = Perl_5
copyright_holder = Sawyer X
copyright_year = 2014
-version = 1.003000
+version = 1.006000
[@Basic]
[PodSyntaxTests]
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $authors =
+ MetaCPAN::Client->new->author({
+ either => [
+ { name => 'Dave *' },
+ { name => 'David *' },
+ ]
+ });
+
+my %output = (
+ TOTAL => $authors->total,
+ NAMES => [
+ map { my $x=$authors->next; [$x->name,$x->pauseid] }
+ 0 .. 9
+ ],
+);
+
+p %output;
@@ -1,3 +1,6 @@
+
+# examples/author-country.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -1,3 +1,7 @@
+
+
+# examples/author.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -15,3 +19,4 @@ my %output = (
);
p %output;
+
@@ -1,3 +1,6 @@
+
+# examples/complex-either-and.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -9,9 +12,7 @@ my $authors =
{ name => 'Dave *' },
{ name => 'David *' },
],
- all => [
- { email => '*gmail.com' }
- ],
+ all => { email => '*gmail.com' },
});
my %output = (
@@ -1,3 +1,6 @@
+
+# examples/complex-either-not.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -16,4 +19,5 @@ my $authors =
});
print "\n";
-p ( $authors->total );
+my %out = ( TOTAL => $authors->total );
+p %out;
@@ -1,3 +1,6 @@
+
+# examples/complex.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -1,3 +1,6 @@
+
+# examples/distribution.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -0,0 +1,23 @@
+
+# examples/module.pl
+
+use strict;
+use warnings;
+use DDP;
+
+use MetaCPAN::Client;
+
+my $module =
+ MetaCPAN::Client->new->module('Moo');
+
+my %output = (
+ NAME => $module->name,
+ ABSTRACT => $module->abstract,
+ DESCRIPTION => $module->description,
+ RELEASE => $module->release,
+ AUTHOR => $module->author,
+ VERSION => $module->version,
+);
+
+p %output;
+
@@ -0,0 +1,11 @@
+
+# examples/pod.pl
+
+use strict;
+use warnings;
+use MetaCPAN::Client;
+
+my $pod =
+ MetaCPAN::Client->new->pod('Moo');
+
+print $pod->html;
@@ -0,0 +1,22 @@
+
+# examples/recent.pl
+
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $recent =
+ MetaCPAN::Client->new->recent(3);
+
+while ( my $rel = $recent->next ) {
+ my %output = (
+ NAME => $rel->name,
+ AUTHOR => $rel->author,
+ DATE => $rel->date,
+ VERSION => $rel->version,
+ );
+
+ p %output;
+}
+
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $recent =
+ MetaCPAN::Client->new->recent('today');
+
+while ( my $rel = $recent->next ) {
+ my %output = (
+ NAME => $rel->name,
+ AUTHOR => $rel->author,
+ DATE => $rel->date,
+ VERSION => $rel->version,
+ );
+
+ p %output;
+}
+
@@ -1,3 +1,6 @@
+
+# examples/rev_deps-recursive.pl
+
use strict;
use warnings;
use Term::ANSIColor;
@@ -5,7 +8,7 @@ use MetaCPAN::Client;
$|=1;
-my $dist = 'Hijk';
+my $dist = shift || 'Hijk';
my $mcpan = MetaCPAN::Client->new;
print "\n\n", colored( "* $dist", 'green' ), "\n";
@@ -17,16 +20,16 @@ sub dig {
my $res = $mcpan->reverse_dependencies($dist);
- for ( @{$res} ) {
+ while ( my $item = $res->next ) {
if ( $level ) {
printf "%s%s\n",
colored( '....' x $level, 'yellow' ),
- $_->distribution;
+ $item->distribution;
} else {
printf "\n>> %s\n",
- colored( $_->distribution, 'blue' );
+ colored( $item->distribution, 'blue' );
}
- dig( $_->distribution, $level + 1 );
+ dig( $item->distribution, $level + 1 );
}
-};
+}
@@ -1,3 +1,6 @@
+
+# examples/rev_deps.pl
+
use strict;
use warnings;
use Data::Printer;
@@ -6,12 +9,16 @@ use MetaCPAN::Client;
my $deps =
MetaCPAN::Client->new->rev_deps('Hijk');
-my @output = (
- map +{
- name => $_->name,
- author => $_->author,
- },
- @{$deps},
-);
+my @output;
+
+while ( my $rel = $deps->next ) {
+ push @output => {
+ name => $rel->name,
+ author => $rel->author,
+ };
+}
+print "\n";
+my $title = "Reverse dependencies for 'Hijk':";
+p $title;
p @output;
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Author;
# ABSTRACT: An Author data object
-$MetaCPAN::Client::Author::VERSION = '1.003000';
+$MetaCPAN::Client::Author::VERSION = '1.006000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -46,13 +46,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Author - An Author data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Distribution;
# ABSTRACT: A Distribution data object
-$MetaCPAN::Client::Distribution::VERSION = '1.003000';
+$MetaCPAN::Client::Distribution::VERSION = '1.006000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -29,13 +29,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Distribution - A Distribution data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Favorite;
# ABSTRACT: A Favorite data object
-$MetaCPAN::Client::Favorite::VERSION = '1.003000';
+$MetaCPAN::Client::Favorite::VERSION = '1.006000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -29,13 +29,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Favorite - A Favorite data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::File;
# ABSTRACT: A File data object
-$MetaCPAN::Client::File::VERSION = '1.003000';
+$MetaCPAN::Client::File::VERSION = '1.006000';
use Moo;
use Carp;
@@ -52,13 +52,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::File - A File data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Module;
# ABSTRACT: A Module data object
-$MetaCPAN::Client::Module::VERSION = '1.003000';
+$MetaCPAN::Client::Module::VERSION = '1.006000';
use Moo;
extends 'MetaCPAN::Client::File';
@@ -12,13 +12,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Module - A Module data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -0,0 +1,108 @@
+use strict;
+use warnings;
+package MetaCPAN::Client::Pod;
+# ABSTRACT: A Pod object
+$MetaCPAN::Client::Pod::VERSION = '1.006000';
+use Moo;
+
+has name => ( is => 'ro', required => 1 );
+
+my @known_formats = qw<
+ html plain x_pod x_markdown
+>;
+
+foreach my $format (@known_formats) {
+ has $format => (
+ is => 'ro',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ return $self->_request( $format );
+ },
+ );
+}
+
+sub _request {
+ my $self = shift;
+ my $ctype = shift || "plain";
+
+ $ctype =~ s/_/-/;
+
+ my $name = $self->name;
+
+ require MetaCPAN::Client::Request;
+
+ return
+ MetaCPAN::Client::Request->new->fetch(
+ "pod/${name}?content-type=text/${ctype}"
+ );
+}
+
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+MetaCPAN::Client::Pod - A Pod object
+
+=head1 VERSION
+
+version 1.006000
+
+=head1 SYNOPSIS
+
+ use strict;
+ use warnings;
+ use MetaCPAN::Client;
+
+ my $pod = MetaCPAN::Client->new->pod('Moo');
+
+ print $pod->html;
+
+=head1 DESCRIPTION
+
+=head1 ATTRIBUTES
+
+=head2 name
+
+=head2 x_pod
+
+=head2 html
+
+=head2 x_markdown
+
+=head2 plain
+
+Get the plaintext version of the documentation
+
+ $pod = MetaCPAN::Client->new->pod( "MetaCPAN::Client" );
+ print $pod->plain;
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Sawyer X <xsawyerx@cpan.org>
+
+=item *
+
+Mickey Nasriachi <mickey@cpan.org>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2014 by Sawyer X.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Rating;
# ABSTRACT: A Rating data object
-$MetaCPAN::Client::Rating::VERSION = '1.003000';
+$MetaCPAN::Client::Rating::VERSION = '1.006000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -31,13 +31,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Rating - A Rating data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Release;
# ABSTRACT: A Release data object
-$MetaCPAN::Client::Release::VERSION = '1.003000';
+$MetaCPAN::Client::Release::VERSION = '1.006000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -32,13 +32,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Release - A Release data object
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Request;
# ABSTRACT: Object used for making requests to MetaCPAN
-$MetaCPAN::Client::Request::VERSION = '1.003000';
+$MetaCPAN::Client::Request::VERSION = '1.006000';
use Moo;
use Carp;
use JSON::MaybeXS qw<decode_json encode_json>;
@@ -140,6 +140,7 @@ sub _build_query_rec {
KEY: for my $k ( qw/ all either not / ) {
my $v = delete $args->{$k} || next KEY;
+ ref $v eq 'HASH' and $v = [ $v ];
ref $v eq 'ARRAY' or croak "invalid value for key $k";
undef $basic_element;
@@ -179,13 +180,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Request - Object used for making requests to MetaCPAN
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 ATTRIBUTES
@@ -2,20 +2,10 @@ use strict;
use warnings;
package MetaCPAN::Client::ResultSet;
# ABSTRACT: A Result Set
-$MetaCPAN::Client::ResultSet::VERSION = '1.003000';
+$MetaCPAN::Client::ResultSet::VERSION = '1.006000';
use Moo;
use Carp;
-has scroller => (
- is => 'ro',
- isa => sub {
- ref $_[0] eq 'Search::Elasticsearch::Scroll'
- or croak 'scroller must be an Search::Elasticsearch::Scroll object';
- },
- handles => ['total'],
- required => 1,
-);
-
has type => (
is => 'ro',
isa => sub {
@@ -26,31 +16,64 @@ has type => (
required => 1,
);
-has facets => (
+# in case we're returning from a scrolled search
+has scroller => (
+ is => 'ro',
+ isa => sub {
+ use Safe::Isa;
+ $_[0]->$_isa('Search::Elasticsearch::Scroll')
+ or croak 'scroller must be an Search::Elasticsearch::Scroll object';
+ },
+ predicate => 'has_scroller',
+);
+
+# in case we're returning from a fetch
+has items => (
+ is => 'ro',
+ isa => sub {
+ ref $_[0] eq 'ARRAY'
+ or croak 'items must be an array ref';
+ },
+);
+
+has total => (
is => 'ro',
- lazy => 1,
- builder => '_get_facets',
+ default => sub {
+ my $self = shift;
+
+ return $self->has_scroller ? $self->scroller->total
+ : scalar @{ $self->items };
+ },
);
-sub _get_facets {
- my $self = shift;
+sub BUILDARGS {
+ my ( $class, %args ) = @_;
- return $self->scroller->facets || {};
-}
+ exists $args{scroller} or exists $args{items}
+ or croak 'ResultSet must get either scroller or items';
+ exists $args{scroller} and exists $args{items}
+ and croak 'ResultSet must get either scroller or items, not both';
+
+ return \%args;
+}
sub next {
my $self = shift;
- my $result = $self->scroller->next;
+ my $result = $self->has_scroller ? $self->scroller->next
+ : shift @{ $self->items };
- defined $result
- or return;
+ defined $result or return;
my $class = 'MetaCPAN::Client::' . ucfirst $self->type;
-
return $class->new_from_request( $result->{'_source'} || $result->{'fields'} );
}
+sub facets {
+ my $self = shift;
+
+ return $self->has_scroller ? $self->scroller->facets : {};
+}
1;
@@ -58,25 +81,31 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::ResultSet - A Result Set
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
Object representing a result from Elastic Search. This is used for the complex
-(as in non-simple) queries to MetaCPAN. It provides easy access to the scroller
-and facets.
+(as in L<non-simple/MetaCPAN::Client/"SEARCH SPEC">) queries to MetaCPAN. It
+provides easy access to the scroller and facets.
=head1 ATTRIBUTES
=head2 scroller
-An L<Search::Elasticsearch::Scroll> object
+An L<Search::Elasticsearch::Scroll> object.
+
+=head2 items
+
+An arrayref of items to manually scroll over, instead of a scroller object.
=head2 type
@@ -112,6 +141,10 @@ Iterator call to fetch the next result set object.
Iterator call to fetch the total amount of objects available in result set.
+=head2 BUILDARGS
+
+Double checks construction of objects. You should never run this yourself.
+
=head1 AUTHORS
=over 4
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Role::Entity;
# ABSTRACT: A role for MetaCPAN entities
-$MetaCPAN::Client::Role::Entity::VERSION = '1.003000';
+$MetaCPAN::Client::Role::Entity::VERSION = '1.006000';
use Moo::Role;
has data => (
@@ -27,13 +27,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client::Role::Entity - A role for MetaCPAN entities
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client;
# ABSTRACT: A comprehensive, DWIM-featured client to the MetaCPAN API
-$MetaCPAN::Client::VERSION = '1.003000';
+$MetaCPAN::Client::VERSION = '1.006000';
use Moo;
use Carp;
@@ -12,6 +12,7 @@ use MetaCPAN::Client::Distribution;
use MetaCPAN::Client::Module;
use MetaCPAN::Client::File;
use MetaCPAN::Client::Favorite;
+use MetaCPAN::Client::Pod;
use MetaCPAN::Client::Rating;
use MetaCPAN::Client::Release;
use MetaCPAN::Client::ResultSet;
@@ -69,6 +70,13 @@ sub file {
return $self->_get( 'file', $path );
}
+sub pod {
+ my $self = shift;
+ my $name = shift;
+
+ return MetaCPAN::Client::Pod->new({ name => $name });
+}
+
#
# $api->rating({ dist => "Moose" })
# is equal to http://api.metacpan.org/v0/favorite/_search?q=distribution:Moose
@@ -128,6 +136,23 @@ sub reverse_dependencies {
*rev_deps = *reverse_dependencies;
+sub recent {
+ my $self = shift;
+ my $size = shift || 100;
+
+ $size eq 'today'
+ and return $self->_recent(
+ size => 1000,
+ filter => _filter_today()
+ );
+
+ $size =~ /^[0-9]+$/
+ and return $self->_recent( size => $size );
+
+ croak "recent: invalid size value";
+}
+
+
###
sub _get {
@@ -197,23 +222,70 @@ sub _reverse_deps {
$res = $self->fetch(
'/search/reverse_dependencies/'.$dist,
{
- query => { match_all => {} },
- filter => { term => { 'release.status' => 'latest' } },
size => 5000,
+ query => { match_all => {} },
+ filter => {
+ and => [
+ { term => { 'release.status' => 'latest' } },
+ { term => { 'authorized' => \1 } },
+ ]
+ },
+ }
+ );
+ 1;
+
+ } or do {
+ warn $@;
+ return _empty_result_set('release'),
+ };
+
+ return MetaCPAN::Client::ResultSet->new(
+ items => $res->{'hits'}{'hits'},
+ type => 'release',
+ );
+}
+
+sub _recent {
+ my $self = shift;
+ my @args = @_;
+
+ my $res;
+
+ eval {
+ $res = $self->fetch(
+ '/release/_search',
+ {
+ from => 0,
+ query => { match_all => {} },
+ @args,
+ sort => [ { 'date' => { order => "desc" } } ],
}
);
+ 1;
} or do {
warn $@;
- return [];
+ return _empty_result_set('release');
};
- return +[
- map { MetaCPAN::Client::Release->new_from_request($_->{'_source'}) }
- @{ $res->{'hits'}{'hits'} }
- ];
+ return MetaCPAN::Client::ResultSet->new(
+ items => $res->{'hits'}{'hits'},
+ type => 'release',
+ );
+}
+
+sub _filter_today {
+ return { range => { date => { from => "now/1d+0h" } } };
}
+sub _empty_result_set {
+ my $type = shift;
+
+ return MetaCPAN::Client::ResultSet->new(
+ items => [],
+ type => $type,
+ );
+}
1;
@@ -221,13 +293,15 @@ __END__
=pod
+=encoding UTF-8
+
=head1 NAME
MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN API
=head1 VERSION
-version 1.003000
+version 1.006000
=head1 SYNOPSIS
@@ -289,7 +363,7 @@ under C<SEARCH SPEC>.
Return a L<MetaCPAN::Client::Author> object on a simple search (PAUSE ID), or
a L<MetaCPAN::Client::ResultSet> object propagated with
-L<MetaCPAN::Client::Author> objects on a complex (search spec based) search.
+L<MetaCPAN::Client::Author> objects on a complex (L<search spec based|/"SEARCH SPEC">) search.
=head2 module
@@ -302,12 +376,12 @@ under C<SEARCH SPEC>.
Return a L<MetaCPAN::Client::Module> object on a simple search (module name), or
a L<MetaCPAN::Client::ResultSet> object propagated with
-L<MetaCPAN::Client::Module> objects on a complex (search spec based) search.
+L<MetaCPAN::Client::Module> objects on a complex (L<search spec based|/"SEARCH SPEC">) search.
=head2 distribution
- my $dist = $mcpan->dist('MetaCPAN-Client');
- my $dist = $mcpan->dist($search_spec);
+ my $dist = $mcpan->distribution('MetaCPAN-Client');
+ my $dist = $mcpan->distribution($search_spec);
Finds a distribution by either its distribution name or by a search spec
defined by a hash reference. Since it is common to many other searches, it is
@@ -315,7 +389,7 @@ explained below under C<SEARCH SPEC>.
Return a L<MetaCPAN::Client::Distribution> object on a simple search
(distribution name), or a L<MetaCPAN::Client::ResultSet> object propagated with
-L<MetaCPAN::Client::Distribution> objects on a complex (search spec based)
+L<MetaCPAN::Client::Distribution> objects on a complex (L<search spec based|/"SEARCH SPEC">)
search.
=head2 file
@@ -341,19 +415,28 @@ below under C<SEARCH SPEC>.
Return a L<MetaCPAN::Client::Release> object on a simple search (release name),
or a L<MetaCPAN::Client::ResultSet> object propagated with
-L<MetaCPAN::Client::Release> objects on a complex (search spec based) search.
+L<MetaCPAN::Client::Release> objects on a complex (L<search spec based|/"SEARCH SPEC">) search.
=head2 reverse_dependencies
my $deps = $mcpan->reverse_dependencies('ElasticSearch');
-Return an array (ref) of L<MetaCPAN::Client::Release> matching all
-releases that are dependent on a given module.
+all L<MetaCPAN::Client::Release> objects of releases that are dependent
+on a given module, returned as L<MetaCPAN::Client::ResultSet>.
=head2 rev_deps
Alias to C<reverse_dependencies> described above.
+=head2 recent
+
+ my $recent = $mcpan->recent(10);
+ my $recent = $mcpan->recent('today');
+
+return the latest N releases, or all releases from today.
+
+returns a L<MetaCPAN::Client::ResultSet> of L<MetaCPAN::Client::Release>.
+
=head2 pod
Not implemented yet.
@@ -367,9 +450,7 @@ Internal construction wrapper. Do not use.
The hash-based search spec is common to many searches. It is quite
feature-rich and allows to disambiguate different types of searches.
-=head2 Simple
-
-Simple searches just contain keys and values:
+Basic search specs just contain a hash of keys and values:
my $author = $mcpan->author( { name => 'Micha Nasriachi' } );
@@ -0,0 +1,52 @@
+works:
+
+{
+ query => { match_all => {} },
+ filter => {
+ or => [
+ { prefix => { name => "Dave " } },
+ { prefix => { name => "David " } },
+ ]
+ }
+}
+
+also:
+
+{
+ query => { match_all => {} },
+ filter => {
+ or => [
+ { prefix => { name => "Dave " } },
+ {
+ and => [
+ { prefix => { name => "David " } },
+ { not => { prefix => { pauseid => "D" } } },
+ ]
+ },
+ ]
+ }
+}
+
+logic:
+- and => []
+- or => []
+- not => {}
+
+wildcard replacements:
+- start ==> prefix
+- end ==> postfix
+- other ==> keep current query build
+
+
+
+_____________
+basic element
+all
+either
+not
+------------
+
+ { name => '' }
+ { all => [] }
+ { either => [] }
+ { not => [] }
@@ -2,9 +2,9 @@ use 5.006;
use strict;
use warnings;
-# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.040
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.039
-use Test::More tests => 11 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
+use Test::More tests => 12 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
@@ -15,6 +15,7 @@ my @module_files = (
'MetaCPAN/Client/Favorite.pm',
'MetaCPAN/Client/File.pm',
'MetaCPAN/Client/Module.pm',
+ 'MetaCPAN/Client/Pod.pm',
'MetaCPAN/Client/Rating.pm',
'MetaCPAN/Client/Release.pm',
'MetaCPAN/Client/Request.pm',
@@ -0,0 +1,16 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use t::lib::Functions;
+
+my $mc = mcpan();
+can_ok( $mc, 'pod' );
+
+my $pod = $mc->pod('MetaCPAN::API');
+isa_ok( $pod, 'MetaCPAN::Client::Pod' );
+can_ok( $pod, qw<html x_pod x_markdown plain name> );
+like( $pod->x_pod, qr/=head1/, 'got pod' );
+
@@ -7,11 +7,17 @@ use Test::More tests => 3;
use Test::Fatal;
use MetaCPAN::Client::ResultSet;
+{
+ package MetaCPAN::Client::Test::ScrollerZ;
+ use base 'Search::Elasticsearch::Scroll'; # < 5.10 FTW (except, no)
+ sub total {0}
+}
+
like(
exception {
MetaCPAN::Client::ResultSet->new(
type => 'failZZ',
- scroller => bless {}, 'Search::Elasticsearch::Scroll',
+ scroller => bless {}, 'MetaCPAN::Client::Test::ScrollerZ',
)
},
qr/Invalid type/,
@@ -0,0 +1 @@
+top uploaders