@@ -1,5 +1,5 @@
-# This file was automatically generated by Dist::Zilla::Plugin::ModuleBuild v5.025.
+# This file was automatically generated by Dist::Zilla::Plugin::ModuleBuild v5.035.
use strict;
use warnings;
@@ -20,7 +20,7 @@ my %module_build_args = (
"Mickey Nasriachi <mickey\@cpan.org>"
],
"dist_name" => "MetaCPAN-Client",
- "dist_version" => "1.008001",
+ "dist_version" => "1.013000",
"license" => "perl",
"module_name" => "MetaCPAN::Client",
"recommends" => {},
@@ -35,6 +35,7 @@ my %module_build_args = (
"Search::Elasticsearch" => "1.10",
"Search::Elasticsearch::Scroll" => 0,
"Try::Tiny" => 0,
+ "perl" => "5.008",
"strict" => 0,
"warnings" => 0
},
@@ -47,7 +48,7 @@ my %module_build_args = (
"Test::More" => 0,
"Test::Requires" => 0,
"base" => 0,
- "perl" => "5.006"
+ "perl" => "5.008"
}
);
@@ -61,7 +62,7 @@ my %fallback_build_requires = (
"Test::More" => 0,
"Test::Requires" => 0,
"base" => 0,
- "perl" => "5.006"
+ "perl" => "5.008"
);
@@ -1,5 +1,25 @@
Revision history for MetaCPAN-Client (previously MetaCPAN-API)
+1.013000 25.04.15
+ * GH #34 Use Travis for CI (oalders)
+ * GH #35 Improve Kwalitee + test improvements (oalders)
+
+1.012000 09.04.15
+ * GH #33 added Mirror type and support for mirrors search in 'all' queries (mickeyn)
+ * GH #33 support 'ratings' search in 'all' queries (mickeyn)
+ * more example scripts: facets, top favorites, all authors blogs (mickeyn)
+ * cleanup & doc updates (Gabor Szabo, mickeyn)
+
+1.011000 27.01.15
+ * support 'favorites' type and 'facets' key param in 'all' queries (mickeyn)
+
+1.010000 23.01.15
+ * support wildcard-only value in complex search (mickeyn)
+ * support raw ElasticSearch filters in 'all' queries (mickeyn)
+
+1.009000 11.01.15
+ * GH #25 (RT #99499): added support for 'fields' filtering (mickeyn, oalders)
+
1.008001 01.01.15
* Happy new year!
* Correct Meta resources for the repo.
@@ -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.
@@ -1,33 +1,43 @@
-# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.025.
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.035.
Build.PL
Changes
LICENSE
MANIFEST
+MANIFEST.SKIP
+META.json
META.yml
Makefile.PL
-README
+cpanfile
dist.ini
+examples/all_favorite_counts_per_dist.pl
examples/author-country.pl
examples/author.pl
examples/author_releases.pl
+examples/authors_blogs.pl
examples/complex-either-and.pl
examples/complex-either-not.pl
examples/complex-nested-either-and.pl
examples/complex.pl
examples/distribution.pl
+examples/es_filter.pl
+examples/fields-filter.pl
+examples/mirror.pl
examples/module.pl
examples/pod.pl
+examples/rating.pl
examples/recent.pl
examples/recent_today.pl
examples/release.pl
examples/rev_deps-recursive.pl
examples/rev_deps.pl
+examples/top20_favorite_distributions.pl
examples/totals.pl
lib/MetaCPAN/Client.pm
lib/MetaCPAN/Client/Author.pm
lib/MetaCPAN/Client/Distribution.pm
lib/MetaCPAN/Client/Favorite.pm
lib/MetaCPAN/Client/File.pm
+lib/MetaCPAN/Client/Mirror.pm
lib/MetaCPAN/Client/Module.pm
lib/MetaCPAN/Client/Pod.pm
lib/MetaCPAN/Client/Rating.pm
@@ -0,0 +1,3 @@
+cpanfile.snapshot
+local
+MetaCPAN-Client*
@@ -0,0 +1,91 @@
+{
+ "abstract" : "A comprehensive, DWIM-featured client to the MetaCPAN API",
+ "author" : [
+ "Sawyer X <xsawyerx@cpan.org>",
+ "Mickey Nasriachi <mickey@cpan.org>"
+ ],
+ "dynamic_config" : 0,
+ "generated_by" : "Dist::Zilla version 5.035, CPAN::Meta::Converter version 2.142060",
+ "license" : [
+ "perl_5"
+ ],
+ "meta-spec" : {
+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+ "version" : "2"
+ },
+ "name" : "MetaCPAN-Client",
+ "no_index" : {
+ "file" : [
+ "README.pod"
+ ]
+ },
+ "prereqs" : {
+ "build" : {
+ "requires" : {
+ "Module::Build" : "0.28"
+ }
+ },
+ "configure" : {
+ "requires" : {
+ "ExtUtils::MakeMaker" : "0",
+ "Module::Build" : "0.28"
+ }
+ },
+ "develop" : {
+ "requires" : {
+ "HTTP::Tiny::Mech" : "0",
+ "Pod::Coverage::TrustPod" : "0",
+ "Test::Pod" : "1.41",
+ "Test::Pod::Coverage" : "1.08",
+ "WWW::Mechanize::Cached" : "1.48"
+ }
+ },
+ "runtime" : {
+ "requires" : {
+ "Carp" : "0",
+ "HTTP::Tiny" : "0",
+ "JSON::MaybeXS" : "0",
+ "Moo" : "0",
+ "Moo::Role" : "0",
+ "Safe::Isa" : "0",
+ "Search::Elasticsearch" : "1.10",
+ "Search::Elasticsearch::Scroll" : "0",
+ "Try::Tiny" : "0",
+ "perl" : "5.008",
+ "strict" : "0",
+ "warnings" : "0"
+ }
+ },
+ "test" : {
+ "recommends" : {
+ "HTTP::Tiny::Mech" : "0",
+ "WWW::Mechanize::Cached" : "1.48"
+ },
+ "requires" : {
+ "File::Spec" : "0",
+ "IO::Handle" : "0",
+ "IPC::Open3" : "0",
+ "Test::Fatal" : "0",
+ "Test::More" : "0",
+ "Test::Requires" : "0",
+ "base" : "0",
+ "perl" : "5.008"
+ }
+ }
+ },
+ "release_status" : "stable",
+ "resources" : {
+ "bugtracker" : {
+ "web" : "https://github.com/CPAN-API/metacpan-client/issues"
+ },
+ "repository" : {
+ "type" : "git",
+ "url" : "git://github.com/CPAN-API/metacpan-client.git",
+ "web" : "https://github.com/CPAN-API/metacpan-client"
+ },
+ "x_IRC" : "irc://irc.perl.org/#metacpan",
+ "x_WebIRC" : "https://chat.mibbit.com/#metacpan@irc.perl.org"
+ },
+ "version" : "1.013000"
+}
+
@@ -12,12 +12,12 @@ build_requires:
Test::More: 0
Test::Requires: 0
base: 0
- perl: 5.006
+ perl: 5.008
configure_requires:
ExtUtils::MakeMaker: 0
Module::Build: 0.28
dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.025, CPAN::Meta::Converter version 2.142690'
+generated_by: 'Dist::Zilla version 5.035, CPAN::Meta::Converter version 2.142060'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -36,6 +36,7 @@ requires:
Search::Elasticsearch: 1.10
Search::Elasticsearch::Scroll: 0
Try::Tiny: 0
+ perl: 5.008
strict: 0
warnings: 0
resources:
@@ -43,4 +44,4 @@ resources:
WebIRC: https://chat.mibbit.com/#metacpan@irc.perl.org
bugtracker: https://github.com/CPAN-API/metacpan-client/issues
repository: git://github.com/CPAN-API/metacpan-client.git
-version: 1.008001
+version: 1.013000
@@ -1,14 +1,11 @@
-
-# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.025.
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.035.
use strict;
use warnings;
-use 5.006;
+use 5.008;
use ExtUtils::MakeMaker;
-
-
my %WriteMakefileArgs = (
"ABSTRACT" => "A comprehensive, DWIM-featured client to the MetaCPAN API",
"AUTHOR" => "Sawyer X <xsawyerx\@cpan.org>, Mickey Nasriachi <mickey\@cpan.org>",
@@ -22,7 +19,7 @@ my %WriteMakefileArgs = (
"DISTNAME" => "MetaCPAN-Client",
"EXE_FILES" => [],
"LICENSE" => "perl",
- "MIN_PERL_VERSION" => "5.006",
+ "MIN_PERL_VERSION" => "5.008",
"NAME" => "MetaCPAN::Client",
"PREREQ_PM" => {
"Carp" => 0,
@@ -46,7 +43,7 @@ my %WriteMakefileArgs = (
"Test::Requires" => 0,
"base" => 0
},
- "VERSION" => "1.008001",
+ "VERSION" => "1.013000",
"test" => {
"TESTS" => "t/*.t t/api/*.t"
}
@@ -87,6 +84,3 @@ delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
WriteMakefile(%WriteMakefileArgs);
-
-
-
@@ -1,271 +0,0 @@
-NAME
- MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN
- API
-
-VERSION
- version 1.008001
-
-SYNOPSIS
- # simple usage
- my $mcpan = MetaCPAN::Client->new();
- my $author = $mcpan->author('XSAWYERX');
- my $dist = $mcpan->distribution('MetaCPAN-Client');
-
- # advanced usage with cache (contributed by Kent Fredric)
- use CHI;
- use WWW::Mechanize::Cached;
- use HTTP::Tiny::Mech;
- use MetaCPAN::Client;
-
- my $mcpan = MetaCPAN::Client->new(
- ua => HTTP::Tiny::Mech->new(
- mechua => WWW::Mechanize::Cached->new(
- cache => CHI->new(
- driver => 'File',
- root_dir => '/tmp/metacpan-cache',
- ),
- ),
- ),
- );
-
- # now $mcpan caches results
-
-DESCRIPTION
- This is a hopefully-complete API-compliant client to MetaCPAN
- (<https://metacpan.org>) with DWIM capabilities, to make your life
- easier.
-
-ATTRIBUTES
- request
- Internal attribute representing the request object making the request to
- MetaCPAN and analyzing the results. You probably don't want to set this,
- nor should you have any usage of it.
-
- ua
- If provided, MetaCPAN::Client::Request will use the user agent object
- instead of the default, which is HTTP::Tiny.
-
- Then it can be used to fetch the user agent object used by
- MetaCPAN::Client::Request.
-
-METHODS
- author
- my $author = $mcpan->author('XSAWYERX');
- my $author = $mcpan->author($search_spec);
-
- Finds an author by either its PAUSE ID or by a search spec defined by a
- hash reference. Since it is common to many other searches, it is
- explained below under "SEARCH SPEC".
-
- Return a MetaCPAN::Client::Author object on a simple search (PAUSE ID),
- or a MetaCPAN::Client::ResultSet object propagated with
- MetaCPAN::Client::Author objects on a complex (search spec based)
- search.
-
- module
- my $module = $mcpan->module('MetaCPAN::Client');
- my $module = $mcpan->module($search_spec);
-
- Finds a module by either its module name or by a search spec defined by
- a hash reference. Since it is common to many other searches, it is
- explained below under "SEARCH SPEC".
-
- Return a MetaCPAN::Client::Module object on a simple search (module
- name), or a MetaCPAN::Client::ResultSet object propagated with
- MetaCPAN::Client::Module objects on a complex (search spec based)
- search.
-
- distribution
- 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 explained below under "SEARCH SPEC".
-
- Return a MetaCPAN::Client::Distribution object on a simple search
- (distribution name), or a MetaCPAN::Client::ResultSet object propagated
- with MetaCPAN::Client::Distribution objects on a complex (search spec
- based) search.
-
- file
- Return a MetaCPAN::Client::File object.
-
- favorite
- Return a MetaCPAN::Client::Favorite object.
-
- rating
- Return a MetaCPAN::Client::Rating object.
-
- release
- my $release = $mcpan->release('MetaCPAN-Client');
- my $release = $mcpan->release($search_spec);
-
- Finds a release 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 explained below under "SEARCH SPEC".
-
- Return a MetaCPAN::Client::Release object on a simple search (release
- name), or a MetaCPAN::Client::ResultSet object propagated with
- MetaCPAN::Client::Release objects on a complex (search spec based)
- search.
-
- reverse_dependencies
- my $deps = $mcpan->reverse_dependencies('ElasticSearch');
-
- 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
- Get POD for given file/module name. returns a MetaCPAN::Client::Pod
- object, which supports various output formats (html, plain, x_pod &
- x_markdown).
-
- my $pod = $mcpan->pod('Moo')->html;
-
- all
- Retrieve all matches for authors/modules/distributions or releases.
-
- my $all_releases = $mcpan->all('releases')
-
- BUILDARGS
- Internal construction wrapper. Do not use.
-
-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.
-
- Basic search specs just contain a hash of keys and values:
-
- my $author = $mcpan->author( { name => 'Micha Nasriachi' } );
-
- # the following is the same as ->author('MICKEY')
- my $author = $mcpan->author( { pauseid => 'MICKEY' } );
-
- # find all people named Dave, not covering Davids
- # will return a resultset
- my $daves = $mcpan->author( { name => 'Dave *' } );
-
- OR
- If you want to do a more complicated query that has an *OR* condition,
- such as "this or that", you can use the following syntax with the
- "either" key:
-
- # any author named "Dave" or "David"
- my $daves = $mcpan->author( {
- either => [
- { name => 'Dave *' },
- { name => 'David *' },
- ]
- } );
-
- AND
- If you want to do a more complicated query that has an *AND* condition,
- such as "this and that", you can use the following syntax with the "all"
- key:
-
- # any users named 'John' with a Gmail account
- my $johns = $mcpan->author( {
- all => [
- { name => 'John *' },
- { email => '*gmail.com' },
- ]
- } );
-
- If you want to do something even more complicated, You can also nest
- your queries, e.g.:
-
- my $gmail_daves_or_cpan_sams = $mcpan->author( {
- either => [
- { all => [ { name => 'Dave *' },
- { email => '*gmail.com' } ]
- },
- { all => [ { name => 'Sam *' },
- { email => '*cpan.org' } ]
- },
- ],
- } );
-
- NOT
- If you want to filter out some of the results of an either/all query
- adding a *NOT* filter condition, such as "not these", you can use the
- following syntax with the "not" key:
-
- # any author named "Dave" or "David"
- my $daves = $mcpan->author( {
- either => [
- { name => 'Dave *' },
- { name => 'David *' },
- ],
- not => [
- { email => '*gmail.com' },
- ],
- } );
-
-DESIGN
- This module has three purposes:
-
- * Provide 100% of the MetaCPAN API
-
- This module will be updated regularly on every MetaCPAN API change,
- and intends to provide the user with as much of the API as possible,
- no shortcuts. If it's documented in the API, you should be able to
- do it.
-
- Because of this design decision, this module has an official
- MetaCPAN namespace with the blessing of the MetaCPAN developers.
-
- Notice this module currently only provides the beta API, not the old
- soon-to-be-deprecated API.
-
- * Be lightweight, to allow flexible usage
-
- While many modules would help make writing easier, it's important to
- take into account how they affect your compile-time, run-time,
- overall memory consumption, and CPU usage.
-
- By providing a slim interface implementation, more users are able to
- use this module, such as long-running processes (like daemons), CLI
- or GUI applications, cron jobs, and more.
-
- * DWIM
-
- While it's possible to access the methods defined by the API spec,
- there's still a matter of what you're really trying to achieve. For
- example, when searching for *"Dave"*, you want to find both *Dave
- Cross* and *Dave Rolsky* (and any other *Dave*), but you also want
- to search for a PAUSE ID of *DAVE*, if one exists.
-
- This is where DWIM comes in. This module provides you with
- additional generic methods which will try to do what they think you
- want.
-
- Of course, this does not prevent you from manually using the API
- methods. You still have full control over that, if that's what you
- wish.
-
- You can (and should) read up on the general methods, which will
- explain how their DWIMish nature works, and what searches they run.
-
-AUTHORS
- * Sawyer X <xsawyerx@cpan.org>
-
- * Mickey Nasriachi <mickey@cpan.org>
-
-COPYRIGHT AND LICENSE
- This software is copyright (c) 2015 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.
-
@@ -0,0 +1,45 @@
+requires "Carp" => "0";
+requires "HTTP::Tiny" => "0";
+requires "JSON::MaybeXS" => "0";
+requires "Moo" => "0";
+requires "Moo::Role" => "0";
+requires "Safe::Isa" => "0";
+requires "Search::Elasticsearch" => "1.10";
+requires "Search::Elasticsearch::Scroll" => "0";
+requires "Try::Tiny" => "0";
+requires "perl" => "5.008";
+requires "strict" => "0";
+requires "warnings" => "0";
+
+on 'build' => sub {
+ requires "Module::Build" => "0.28";
+};
+
+on 'test' => sub {
+ requires "File::Spec" => "0";
+ requires "IO::Handle" => "0";
+ requires "IPC::Open3" => "0";
+ requires "Test::Fatal" => "0";
+ requires "Test::More" => "0";
+ requires "Test::Requires" => "0";
+ requires "base" => "0";
+ requires "perl" => "5.008";
+};
+
+on 'test' => sub {
+ recommends "HTTP::Tiny::Mech" => "0";
+ recommends "WWW::Mechanize::Cached" => "1.48";
+};
+
+on 'configure' => sub {
+ requires "ExtUtils::MakeMaker" => "0";
+ requires "Module::Build" => "0.28";
+};
+
+on 'develop' => sub {
+ requires "HTTP::Tiny::Mech" => "0";
+ requires "Pod::Coverage::TrustPod" => "0";
+ requires "Test::Pod" => "1.41";
+ requires "Test::Pod::Coverage" => "1.08";
+ requires "WWW::Mechanize::Cached" => "1.48";
+};
@@ -5,20 +5,30 @@ license = Perl_5
copyright_holder = Sawyer X
copyright_year = 2015
-version = 1.008001
+version = 1.013000
+
+
+[@Filter]
+-bundle = @Basic
+-remove = GatherDir
-[@Basic]
[PodSyntaxTests]
[PodCoverageTests]
[Test::Perl::Critic]
[Test::Compile]
+[Git::GatherDir]
+exclude_filename = cpanfile
+
[Prereqs]
Search::Elasticsearch = 1.10
[AutoPrereqs]
skip = ^t::lib::Functions$
+[Prereqs / TestRequires]
+WWW::Mechanize::Cached = 1.48
+
[Prereqs::Soften]
module = HTTP::Tiny::Mech
module = WWW::Mechanize::Cached
@@ -27,14 +37,21 @@ copy_to = develop.requires
[ModuleBuild]
[PodWeaver]
[ReadmeFromPod]
+[MetaJSON]
+[MinimumPerlFast]
[MetaNoIndex]
file = README.pod
+
[ReadmeAnyFromPod / pod.root ]
filename = README.pod
type = pod
location = root
+[CPANFile]
+[CopyFilesFromBuild]
+copy = cpanfile
+
[CheckChangeLog]
[PkgVersion]
[MetaResources]
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+use Data::Printer;
+
+use MetaCPAN::Client;
+
+# All 1+ favorite counts per distributions
+# -- done inefficiently :)
+
+my $mcpan = MetaCPAN::Client->new();
+my $size = $mcpan->all('favorites')->total;
+my $favs = $mcpan->all('favorites', {
+ facets => {
+ distribution => {
+ terms => {
+ field => "distribution",
+ size => $size,
+ order => "reverse_count",
+# all_terms => "true",
+ }
+ },
+ }
+});
+
+p $favs->facets->{distribution}{terms};
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+
+use MetaCPAN::Client;
+
+my $mcpan = MetaCPAN::Client->new;
+
+my $all_authors = $mcpan->all('authors');
+
+AUTHOR: while ( my $author = $all_authors->next ) {
+
+ BLOG: for my $blog ( @{ $author->blog || [] } ) {
+ $blog and exists $blog->{url} or next BLOG;
+ my $url = $blog->{url};
+
+ my $blogs_csv = ref $url eq 'ARRAY'
+ ? join q{,} => @$url
+ : $url;
+
+ printf "%-10s: %s\n", $author->pauseid, $blogs_csv;
+ }
+}
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+
+use MetaCPAN::Client;
+
+# use raw ES filter on a { match_all => {} } query
+
+# find 'latest' status releases with at least 700 failing tests
+# which consist at least 50% of their overall number of tests.
+
+my $release = MetaCPAN::Client->new->all(
+ 'releases',
+ {
+ es_filter => {
+ and => [
+ { range => { 'tests.fail' => { gte => 700 } } },
+ { term => { 'status' => 'latest' } }
+ ]
+ },
+
+ fields => [qw/ name tests /],
+ }
+);
+
+while ( my $r = $release->next ) {
+ my $fail = $r->tests->{fail};
+ my $all = 0; $all += $_ for @{ $r->tests }{qw/pass fail na unknown/};
+ ($fail / $all) >= 0.5 and printf "%4d/%4d: %s\n", $fail, $all, $r->name;
+}
@@ -0,0 +1,14 @@
+
+# examples/fields-filter.pl
+
+use strict;
+use warnings;
+use DDP;
+
+use MetaCPAN::Client;
+
+my $module =
+ MetaCPAN::Client->new->module('Moose',
+ { fields => [ qw/ author version / ] });
+
+p $module;
@@ -0,0 +1,14 @@
+
+
+# examples/mirror.pl
+
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $mirrors =
+ MetaCPAN::Client->new->mirror('eutelia.it');
+
+p $mirrors;
+
@@ -0,0 +1,14 @@
+
+# examples/rating.pl
+
+use strict;
+use warnings;
+use DDP;
+
+use MetaCPAN::Client;
+
+my $rating =
+ MetaCPAN::Client->new->rating({ distribution => "Moose" });
+
+p $rating->next;
+
@@ -0,0 +1,27 @@
+use strict;
+use warnings;
+use Data::Printer;
+
+use MetaCPAN::Client;
+
+# TOP 20 FAVORITE DISTRIBUTIONS
+
+my $mcpan = MetaCPAN::Client->new();
+my $favs = $mcpan->all('favorites', {
+ facets => {
+ distribution => {
+ terms => {
+ field => "distribution",
+ size => 20,
+ order => "count",
+ }
+ },
+ }
+});
+
+print "TOP 20 FAVORITE DISTRIBUTIONS:\n";
+
+my $count = 1;
+for ( @{ $favs->facets->{distribution}{terms} } ) {
+ printf "%3d) %5d %-20s\n", $count++, @{$_}{qw/count term/};
+}
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Author;
# ABSTRACT: An Author data object
-$MetaCPAN::Client::Author::VERSION = '1.008001';
+$MetaCPAN::Client::Author::VERSION = '1.013000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -51,7 +51,7 @@ MetaCPAN::Client::Author - An Author data object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Distribution;
# ABSTRACT: A Distribution data object
-$MetaCPAN::Client::Distribution::VERSION = '1.008001';
+$MetaCPAN::Client::Distribution::VERSION = '1.013000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -37,7 +37,7 @@ MetaCPAN::Client::Distribution - A Distribution data object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Favorite;
# ABSTRACT: A Favorite data object
-$MetaCPAN::Client::Favorite::VERSION = '1.008001';
+$MetaCPAN::Client::Favorite::VERSION = '1.013000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -37,7 +37,7 @@ MetaCPAN::Client::Favorite - A Favorite data object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::File;
# ABSTRACT: A File data object
-$MetaCPAN::Client::File::VERSION = '1.008001';
+$MetaCPAN::Client::File::VERSION = '1.013000';
use Moo;
use Carp;
@@ -60,7 +60,7 @@ MetaCPAN::Client::File - A File data object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -0,0 +1,117 @@
+use strict;
+use warnings;
+package MetaCPAN::Client::Mirror;
+# ABSTRACT: A Mirror data object
+$MetaCPAN::Client::Mirror::VERSION = '1.013000';
+use Moo;
+use Carp;
+
+with 'MetaCPAN::Client::Role::Entity';
+
+my @known_fields = qw< name org ftp contact city rsync src ccode
+ aka_name tz note dnsrr region inceptdate
+ country location freq continent http
+ reitredate A_or_CNAME >;
+
+foreach my $field (@known_fields) {
+ has $field => (
+ is => 'ro',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ return $self->data->{$field};
+ },
+ );
+}
+
+sub _known_fields { return \@known_fields }
+
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+MetaCPAN::Client::Mirror - A Mirror data object
+
+=head1 VERSION
+
+version 1.013000
+
+=head1
+DESCRIPTION
+
+=head1
+ATTRIBUTES
+
+=head2 name
+
+=head2 org
+
+=head2 ftp
+
+=head2 contact
+
+=head2 city
+
+=head2 rsync
+
+=head2 src
+
+=head2 ccode
+
+=head2 aka_name
+
+=head2 tz
+
+=head2 note
+
+=head2 dnsrr
+
+=head2 region
+
+=head2 inceptdate
+
+=head2 country
+
+=head2 location
+
+=head2 freq
+
+=head2 continent
+
+=head2 http
+
+=head2 reitredate
+
+=head2 A_or_CNAME
+
+=head1 METHODS
+
+=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) 2015 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::Module;
# ABSTRACT: A Module data object
-$MetaCPAN::Client::Module::VERSION = '1.008001';
+$MetaCPAN::Client::Module::VERSION = '1.013000';
use Moo;
extends 'MetaCPAN::Client::File';
@@ -20,7 +20,7 @@ MetaCPAN::Client::Module - A Module data object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Pod;
# ABSTRACT: A Pod object
-$MetaCPAN::Client::Pod::VERSION = '1.008001';
+$MetaCPAN::Client::Pod::VERSION = '1.013000';
use Moo;
has name => ( is => 'ro', required => 1 );
@@ -53,7 +53,7 @@ MetaCPAN::Client::Pod - A Pod object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 SYNOPSIS
@@ -71,14 +71,24 @@ version 1.008001
=head2 name
+The name of the module (probably always the value passed to the pod() method)
+
=head2 x_pod
+The raw pod extracted from the file.
+
=head2 html
+Formatted as an HTML chunk (No <html>...<body>)
+
=head2 x_markdown
+Converted to Markdown.
+
=head2 plain
+Formatted as plain text.
+
Get the plaintext version of the documentation
$pod = MetaCPAN::Client->new->pod( "MetaCPAN::Client" );
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Rating;
# ABSTRACT: A Rating data object
-$MetaCPAN::Client::Rating::VERSION = '1.008001';
+$MetaCPAN::Client::Rating::VERSION = '1.013000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -39,7 +39,7 @@ MetaCPAN::Client::Rating - A Rating data object
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::Release;
# ABSTRACT: A Release data object
-$MetaCPAN::Client::Release::VERSION = '1.008001';
+$MetaCPAN::Client::Release::VERSION = '1.013000';
use Moo;
with 'MetaCPAN::Client::Role::Entity';
@@ -40,7 +40,7 @@ MetaCPAN::Client::Release - A Release data object
=head1 VERSION
-version 1.008001
+version 1.013000
=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.008001';
+$MetaCPAN::Client::Request::VERSION = '1.013000';
use Moo;
use Carp;
use JSON::MaybeXS qw<decode_json encode_json>;
@@ -89,6 +89,8 @@ sub ssearch {
( $self->_has_user_ua ? ( handle => $self->_user_ua ) : () )
);
+ my $body = $self->_build_body($args, $params);
+
my $scroller = Search::Elasticsearch::Scroll->new(
es => $es,
search_type => 'scan',
@@ -96,7 +98,7 @@ sub ssearch {
index => $self->version,
type => $type,
size => 1000,
- body => $self->_build_body($args),
+ body => $body,
%{ $params },
);
@@ -132,14 +134,19 @@ sub _decode_result {
}
sub _build_body {
- my $self = shift;
- my $args = shift;
+ my $self = shift;
+ my $args = shift;
+ my $params = shift;
my $query = $args->{__MATCH_ALL__}
? { match_all => {} }
: _build_query_rec($args);
- return +{ query => $query };
+ return +{
+ query => $query,
+ _read_filters($params),
+ _read_facets($params)
+ };
}
my %key2es = (
@@ -148,6 +155,24 @@ my %key2es = (
not => 'must_not',
);
+sub _read_facets {
+ my $params = shift;
+
+ my $facets = delete $params->{facets};
+ ref($facets) or return ();
+
+ return ( facets => $facets );
+}
+
+sub _read_filters {
+ my $params = shift;
+
+ my $filter = delete $params->{es_filter};
+ ref($filter) or return ();
+
+ return ( filter => $filter );
+}
+
sub _build_query_rec {
my $args = shift;
ref $args eq 'HASH' or croak 'query args must be a hash';
@@ -180,11 +205,12 @@ sub _build_query_element {
or croak 'Wrong number of keys in query element';
my ($key) = keys %{$args};
+ my $val = $args->{$key};
- ! ref( $args->{$key} ) and $args->{$key} =~ /\w/
+ !ref($val) and $val =~ /[\w\*]/
or croak 'Wrong type of query arguments';
- my $wildcard = $args->{$key} =~ /[*?]/;
+ my $wildcard = $val =~ /[*?]/;
my $qtype = $wildcard ? 'wildcard' : 'term';
return +{ $qtype => $args };
@@ -205,7 +231,7 @@ MetaCPAN::Client::Request - Object used for making requests to MetaCPAN
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 ATTRIBUTES
@@ -2,7 +2,7 @@ use strict;
use warnings;
package MetaCPAN::Client::ResultSet;
# ABSTRACT: A Result Set
-$MetaCPAN::Client::ResultSet::VERSION = '1.008001';
+$MetaCPAN::Client::ResultSet::VERSION = '1.013000';
use Moo;
use Carp;
@@ -11,7 +11,7 @@ has type => (
isa => sub {
croak 'Invalid type' unless
grep { $_ eq $_[0] } qw<author distribution favorite
- file module rating release>;
+ file module rating release mirror>;
},
required => 1,
);
@@ -89,7 +89,7 @@ MetaCPAN::Client::ResultSet - A Result Set
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 DESCRIPTION
@@ -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.008001';
+$MetaCPAN::Client::Role::Entity::VERSION = '1.013000';
use Moo::Role;
has data => (
@@ -47,7 +47,7 @@ MetaCPAN::Client::Role::Entity - A role for MetaCPAN entities
=head1 VERSION
-version 1.008001
+version 1.013000
=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.008001';
+$MetaCPAN::Client::VERSION = '1.013000';
use Moo;
use Carp;
@@ -15,6 +15,7 @@ use MetaCPAN::Client::Favorite;
use MetaCPAN::Client::Pod;
use MetaCPAN::Client::Rating;
use MetaCPAN::Client::Release;
+use MetaCPAN::Client::Mirror;
use MetaCPAN::Client::ResultSet;
has request => (
@@ -23,16 +24,16 @@ has request => (
);
my @supported_searches = qw<
- author distribution favorite module rating release
+ author distribution favorite module rating release mirror
>;
sub BUILDARGS {
my ( $class, %args ) = @_;
$args{'request'} ||= MetaCPAN::Client::Request->new(
- ( ua => $args{'ua'} ) x !! $args{'ua'},
- $args{domain} ? ( domain => $args{domain} ) : (),
- $args{version} ? ( version => $args{version} ) : (),
+ ( ua => $args{ua} )x!! $args{ua},
+ ( domain => $args{domain} )x!! $args{domain},
+ ( version => $args{version} )x!! $args{version},
);
return \%args;
@@ -79,13 +80,6 @@ sub pod {
return MetaCPAN::Client::Pod->new({ name => $name });
}
-#
-# $api->rating({ dist => "Moose" })
-# is equal to http://api.metacpan.org/v0/favorite/_search?q=distribution:Moose
-#
-# $api->rating({ author => "DOY" })
-# is equal to http://api.metacpan.org/v0/favorite/_search?q=author:DOY
-#
sub favorite {
my $self = shift;
my $args = shift;
@@ -97,13 +91,6 @@ sub favorite {
return $self->_search( 'favorite', $args, $params );
}
-#
-# $api->rating({ rating => "4.0" })
-# is equal to http://api.metacpan.org/v0/rating/_search?q=rating:4.0
-#
-# $api->rating({ distribution => "Moose" })
-# is equal to http://api.metacpan.org/v0/rating/_search?q=distribution:Moose
-#
sub rating {
my $self = shift;
my $args = shift;
@@ -115,10 +102,6 @@ sub rating {
return $self->_search( 'rating', $args, $params );
}
-#
-# $api->release({ author => "XSAWYERX" })
-# is equal to http://api.metacpan.org/v0/release/_search?q=author:XSAWYERX
-#
sub release {
my $self = shift;
my $arg = shift;
@@ -127,6 +110,14 @@ sub release {
return $self->_get_or_search( 'release', $arg, $params );
}
+sub mirror {
+ my $self = shift;
+ my $arg = shift;
+ my $params = shift;
+
+ return $self->_get_or_search( 'mirror', $arg, $params );
+}
+
sub reverse_dependencies {
my $self = shift;
my $dist = shift;
@@ -155,17 +146,19 @@ sub recent {
}
sub all {
- my $self = shift;
- my $type = shift;
+ my $self = shift;
+ my $type = shift;
+ my $params = shift;
- my $match_all = { __MATCH_ALL__ => 1 };
+ grep { $type eq $_ } qw/ authors distributions modules releases
+ favorites ratings mirrors /
+ or croak "all: unsupported type";
+ $type =~ s/s$//;
- $type eq 'authors' and return $self->author( $match_all );
- $type eq 'distributions' and return $self->distribution( $match_all );
- $type eq 'modules' and return $self->module( $match_all );
- $type eq 'releases' and return $self->release( $match_all );
+ $params and ref($params) ne 'HASH'
+ and croak "all: params must be a hashref";
- croak "all: unsupported type";
+ return $self->$type( { __MATCH_ALL__ => 1 }, $params );
}
###
@@ -173,13 +166,19 @@ sub all {
sub _get {
my $self = shift;
- scalar(@_) == 2
- or croak '_get takes type and search string as parameters';
+ ( scalar(@_) == 2
+ or ( scalar(@_) == 3 and ( !defined $_[2] or ref $_[2] eq 'HASH' ) ) )
+ or croak '_get takes type and search string as parameters (and an optional params hash)';
- my $type = shift;
- my $arg = shift;
+ my $type = shift;
+ my $arg = shift;
+ my $params = shift;
- my $response = $self->fetch("$type/$arg");
+ my $fields_filter = $self->_read_fields( $params );
+
+ my $response = $self->fetch(
+ sprintf("%s/%s%s", $type ,$arg, $fields_filter)
+ );
ref $response eq 'HASH'
or croak sprintf( 'Failed to fetch %s (%s)', ucfirst($type), $arg );
@@ -187,6 +186,27 @@ sub _get {
return $class->new_from_request($response, $self);
}
+sub _read_fields {
+ my $self = shift;
+ my $params = shift;
+ $params or return '';
+
+ my $fields = delete $params->{fields};
+
+ if ( ref $fields eq 'ARRAY' ) {
+ grep { ref $_ } @$fields
+ and croak "fields array should not contain any refs.";
+
+ return sprintf( "?fields=%s", join q{,} => @$fields );
+
+ } elsif ( !ref $fields ) {
+
+ return "?fields=$fields";
+ }
+
+ croak "invalid param: fields";
+}
+
sub _search {
my $self = shift;
my $type = shift;
@@ -222,7 +242,7 @@ sub _get_or_search {
return $self->_search( $type, $arg, $params );
defined $arg and ! ref($arg)
- and return $self->_get($type, $arg);
+ and return $self->_get($type, $arg, $params);
croak "$type: invalid args (takes scalar value or search parameters hashref)";
}
@@ -316,7 +336,7 @@ MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN API
=head1 VERSION
-version 1.008001
+version 1.013000
=head1 SYNOPSIS
@@ -413,10 +433,14 @@ Return a L<MetaCPAN::Client::File> object.
=head2 favorite
+ my $favorite = $mcpan->favorite({ distribution => 'Moose' });
+
Return a L<MetaCPAN::Client::Favorite> object.
=head2 rating
+ my $rating = $mcpan->rating({ distribution => 'Moose' });
+
Return a L<MetaCPAN::Client::Rating> object.
=head2 release
@@ -432,6 +456,12 @@ 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 (L<search spec based|/"SEARCH SPEC">) search.
+=head2 mirror
+
+ my $mirror = $mcpan->mirror('kr.freebsd.org');
+
+Returns a L<MetaCPAN::Client::Mirror> object.
+
=head2 reverse_dependencies
my $deps = $mcpan->reverse_dependencies('ElasticSearch');
@@ -462,14 +492,46 @@ formats (html, plain, x_pod & x_markdown).
=head2 all
-Retrieve all matches for authors/modules/distributions or releases.
+Retrieve all matches for authors/modules/distributions/favorites or releases.
my $all_releases = $mcpan->all('releases')
+When called with a second parameter containing a hash ref,
+will support the following keys:
+
+=head3 fields
+
+See SEARCH PARAMS.
+
+ my $all_releases = $mcpan->all('releases', { fields => [...] })
+
+=head3 es_filter
+
+Pass a raw ElasticSearch filter structure to reduce the number
+of elements returned by the query.
+
+ my $some_releases = $mcpan->all('releases', { es_filter => {...} })
+
=head2 BUILDARGS
Internal construction wrapper. Do not use.
+=head1 SEARCH PARAMS
+
+Most searches take params as an optional hash-ref argument.
+these params will be passed to the search action.
+
+In non-scrolled searches, 'fields' filter is the only supported
+parameter ATM.
+
+=head2 fields
+
+Filter the fields to reduce the amount of data pulled from MetaCPAN.
+can be passed as a csv list or an array ref.
+
+ my $module = $mcpan->module('Moose', { fields => "version,author" });
+ my $module = $mcpan->module('Moose', { fields => [qw/version author/] });
+
=head1 SEARCH SPEC
The hash-based search spec is common to many searches. It is quite
@@ -2,11 +2,11 @@ use 5.006;
use strict;
use warnings;
-# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.051
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.052
use Test::More;
-plan tests => 12 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
+plan tests => 13 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
my @module_files = (
'MetaCPAN/Client.pm',
@@ -14,6 +14,7 @@ my @module_files = (
'MetaCPAN/Client/Distribution.pm',
'MetaCPAN/Client/Favorite.pm',
'MetaCPAN/Client/File.pm',
+ 'MetaCPAN/Client/Mirror.pm',
'MetaCPAN/Client/Module.pm',
'MetaCPAN/Client/Pod.pm',
'MetaCPAN/Client/Rating.pm',