Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add MetaCPAN::API::Distribution

Add MetaCPAN::API::Favorite
Add MetaCPAN::API::File (split from Module)
Add MetaCPAN::API::Rating
Add content-type docs to MetaCPAN::API::POD
Add README (for the sake of GitHub)
Bulk up .gitignore
  • Loading branch information...
commit e143225f00ba34e813e339f589cb2557c5915b3f 1 parent 591b48a
@SineSwiper authored
View
24 .gitignore
@@ -1 +1,23 @@
-*.swp
+LICENSE
+MANIFEST
+MANIFEST.bak
+Makefile
+Makefile.PL
+Makefile.old
+Build
+Build.PL
+Build.bat
+META.*
+MYMETA.*
+.build/
+_build/
+cover_db/
+blib/
+inc/
+.lwpcookies
+.last_cover_stats
+nytprof.out
+pod2htm*.tmp
+pm_to_blib
+metacpan-api-*
+metacpan-api-*.tar.gz
View
159 README
@@ -0,0 +1,159 @@
+NAME
+ MetaCPAN::API - A comprehensive, DWIM-featured API to MetaCPAN
+
+VERSION
+ version 0.43
+
+SYNOPSIS
+ # simple usage
+ my $mcpan = MetaCPAN::API->new();
+ my $author = $mcpan->author('XSAWYERX');
+ my $dist = $mcpan->release( distribution => 'MetaCPAN-API' );
+
+ # advanced usage with cache (contributed by Kent Fredric)
+ require CHI;
+ require WWW::Mechanize::Cached;
+ require HTTP::Tiny::Mech;
+ require MetaCPAN::API;
+
+ my $mcpan = MetaCPAN::API->new(
+ ua => HTTP::Tiny::Mech->new(
+ mechua => WWW::Mechanize::Cached->new(
+ cache => CHI->new(
+ driver => 'File',
+ root_dir => '/tmp/metacpan-cache',
+ ),
+ ),
+ ),
+ );
+
+DESCRIPTION
+ This is a hopefully-complete API-compliant interface to MetaCPAN
+ (<https://metacpan.org>) with DWIM capabilities, to make your life
+ easier.
+
+ This module has three purposes:
+
+ * Provide 100% of the beta 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 and
+ overall memory consumption.
+
+ 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 generic methods, which will
+ explain how their DWIMish nature works, and what searches they run.
+
+ATTRIBUTES
+ base_url
+ my $mcpan = MetaCPAN::API->new(
+ base_url => 'http://localhost:9999',
+ );
+
+ This attribute is used for REST requests. You should set it to where the
+ MetaCPAN is accessible. By default it's already set correctly, but if
+ you're running a local instance of MetaCPAN, or use a local mirror, or
+ tunnel it through a local port, or any of those stuff, you would want to
+ change this.
+
+ Default: *http://api.metacpan.org/v0*.
+
+ This attribute is read-only (immutable), meaning that once it's set on
+ initialize (via "new()"), you cannot change it. If you need to, create a
+ new instance of MetaCPAN::API. Why is it immutable? Because it's better.
+
+ ua
+ This attribute is used to contain the user agent used for running the
+ REST request to the server. It is specifically set to HTTP::Tiny, so if
+ you want to set it manually, make sure it's of HTTP::Tiny.
+
+ HTTP::Tiny is used as part of the philosophy of keeping it tiny.
+
+ This attribute is read-only (immutable), meaning that once it's set on
+ initialize (via "new()"), you cannot change it. If you need to, create a
+ new instance of MetaCPAN::API. Why is it immutable? Because it's better.
+
+ ua_args
+ my $mcpan = MetaCPAN::API->new(
+ ua_args => [ agent => 'MyAgent' ],
+ );
+
+ The arguments that will be given to the HTTP::Tiny user agent.
+
+ This attribute is read-only (immutable), meaning that once it's set on
+ initialize (via "new()"), you cannot change it. If you need to, create a
+ new instance of MetaCPAN::API. Why is it immutable? Because it's better.
+
+ The default is a user agent string: MetaCPAN::API/$version.
+
+METHODS
+ fetch
+ my $result = $mcpan->fetch('/release/distribution/Moose');
+
+ # with parameters
+ my $more = $mcpan->fetch(
+ '/release/distribution/Moose',
+ param => 'value',
+ );
+
+ This is a helper method for API implementations. It fetches a path from
+ MetaCPAN, decodes the JSON from the content variable and returns it.
+
+ You don't really need to use it, but you can in case you want to write
+ your own extension implementation to MetaCPAN::API.
+
+ It accepts an additional hash as "GET" parameters.
+
+ post
+ # /release&content={"query":{"match_all":{}},"filter":{"prefix":{"archive":"Cache-Cache-1.06"}}}
+ my $result = $mcpan->post(
+ 'release',
+ {
+ query => { match_all => {} },
+ filter => { prefix => { archive => 'Cache-Cache-1.06' } },
+ },
+ );
+
+ The POST equivalent of the "fetch()" method. It gets the path and JSON
+ request.
+
+AUTHOR
+ Sawyer X <xsawyerx@cpan.org>
+
+COPYRIGHT AND LICENSE
+ This software is copyright (c) 2011 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.
View
4 lib/MetaCPAN/API.pm
@@ -13,8 +13,12 @@ use URI::Escape 'uri_escape';
with qw/
MetaCPAN::API::Author
+ MetaCPAN::API::Distribution
+ MetaCPAN::API::Favorite
+ MetaCPAN::API::File
MetaCPAN::API::Module
MetaCPAN::API::POD
+ MetaCPAN::API::Rating
MetaCPAN::API::Release
MetaCPAN::API::Source
/;
View
66 lib/MetaCPAN/API/Distribution.pm
@@ -0,0 +1,66 @@
+use strict;
+use warnings;
+package MetaCPAN::API::Distribution;
+# ABSTRACT: Distribution information for MetaCPAN::API
+
+use Carp;
+use Any::Moose 'Role';
+
+# /distribution/{distribution}
+sub distribution {
+ my $self = shift;
+ my $url = '';
+ my $error = "Either provide a distribution or 'search'";
+
+ my %extra_opts = ();
+
+ if ( @_ == 1 ) {
+ $url = 'distribution/' . shift;
+ } elsif ( @_ ) {
+ my %opts = @_;
+
+ if ( defined ( my $dist = $opts{'distribution'} ) ) {
+ $url = "distribution/$dist";
+ } elsif ( defined ( my $search_opts = $opts{'search'} ) ) {
+ ref $search_opts && ref $search_opts eq 'HASH'
+ or croak $error;
+
+ %extra_opts = %{$search_opts};
+ $url = 'distribution/_search';
+ } else {
+ croak $error;
+ }
+ } else {
+ croak $error;
+ }
+
+ return $self->fetch( $url, %extra_opts );
+}
+
+1;
+
+__END__
+
+=head1 DESCRIPTION
+
+This role provides MetaCPAN::API with fetching information about distributions,
+returning information about the distribution which is not specific to a version
+(like RT bug counts).
+
+=head1 METHODS
+
+=head2 distibution
+
+ my $result = $mcpan->distibution('DBIx-Class');
+
+Searches MetaCPAN for a dist.
+
+You can do complex searches using 'search' parameter:
+
+ my $result = $mcpan->distribution(
+ search => {
+ filter => { exists => { field => 'bugs.source' } },
+ fields => ['name', 'bugs.source'],
+ size => 5,
+ },
+ );
View
57 lib/MetaCPAN/API/Favorite.pm
@@ -0,0 +1,57 @@
+use strict;
+use warnings;
+package MetaCPAN::API::Favorite;
+# ABSTRACT: Favorite ++ information for MetaCPAN::API
+
+use Carp;
+use Any::Moose 'Role';
+
+# /favorite/_search only
+sub favorite {
+ my $self = shift;
+ my %opts = @_ ? @_ : ();
+ my $url = '';
+ my $error = "Only 'search' can be used here";
+
+ %opts or croak $error;
+
+ my %extra_opts = ();
+
+ if ( defined ( my $search_opts = $opts{'search'} ) ) {
+ ref $search_opts && ref $search_opts eq 'HASH'
+ or croak $error;
+
+ %extra_opts = %{$search_opts};
+ $url = 'favorite/_search';
+ } else {
+ croak $error;
+ }
+
+ return $self->fetch( $url, %extra_opts );
+}
+
+1;
+
+__END__
+
+=head1 DESCRIPTION
+
+This role provides MetaCPAN::API with fetching information about favorite
+++ information.
+
+=head1 METHODS
+
+=head2 favorite
+
+ # example lifted from MetaCPAN docs
+ my $result = $mcpan->favorite(
+ search => {
+ user => "SZABGAB",
+ fields => "distribution",
+ size => 100,
+ },
+ );
+
+Searches MetaCPAN for favorite ++ information.
+
+Only complex searches are currently available.
View
73 lib/MetaCPAN/API/File.pm
@@ -0,0 +1,73 @@
+use strict;
+use warnings;
+package MetaCPAN::API::File;
+# ABSTRACT: File information for MetaCPAN::API
+
+use Carp;
+use Any::Moose 'Role';
+
+# /module/{module}
+# /file/{author}/{release}/{path}
+# /file/{author}/{release}
+# /file/{id}
+sub file {
+ my $self = shift;
+ my $url = '';
+ my $error = "Either provide a module name, 'id', or 'author and 'release' and an optional 'path'";
+
+ if ( @_ == 1 ) {
+ $url = 'module/' . shift;
+ } elsif ( @_ ) {
+ my %opts = @_;
+
+ if ( defined ( my $id = $opts{'id'} ) ) {
+ $url = "file/$id";
+ } elsif (
+ defined ( my $author = $opts{'author'} ) &&
+ defined ( my $release = $opts{'release'} )
+ ) {
+ my $path = $opts{'path'} || '';
+ $url = "file/$author/$release/$path";
+ } else {
+ croak $error;
+ }
+ } else {
+ croak $error;
+ }
+
+
+ return $self->fetch( $url );
+}
+
+1;
+
+__END__
+
+=head1 DESCRIPTION
+
+This role provides MetaCPAN::API with fetching file information about modules
+and distribution releases.
+
+=head1 METHODS
+
+=head2 pod
+
+ my $result = $mcpan->file(
+ author => 'DOY',
+ release => 'Moose-2.0201',
+ path => 'lib/Moose.pm',
+ );
+
+ # or
+ my $result = $mcpan->file(
+ author => 'DOY',
+ release => 'Moose-2.0201',
+ );
+
+ # or
+ my $result1 = $mcpan->file('MetaCPAN::API');
+ my $result2 = $mcpan->file( id => 'EMfoAvoYhHpUK8MVJSkm4KN5GmY' );
+
+Searches MetaCPAN for a module or a specific release and returns
+file/directory information. If path is omitted, it gets information
+on the root directory.
View
6 lib/MetaCPAN/API/Module.pm
@@ -16,9 +16,6 @@ sub module {
return $self->fetch("module/$name");
}
-# file() is a synonym of module
-sub file { goto &module }
-
1;
__END__
@@ -39,5 +36,6 @@ Searches MetaCPAN and returns a module's C<.pm> file.
=head2 file
-A synonym of C<module>.
+This used to be a synonym of C<module>, but the functionality has now
+moved to L<MetaCPAN::API::File>.
View
3  lib/MetaCPAN/API/POD.pm
@@ -70,3 +70,6 @@ and distribution releases.
Searches MetaCPAN for a module or a specific release and returns the POD.
+Content type can also be specified, like so:
+
+ my $result = $mcpan->pod( module => 'Moose', 'content-type' => 'x-pod' );
View
68 lib/MetaCPAN/API/Rating.pm
@@ -0,0 +1,68 @@
+use strict;
+use warnings;
+package MetaCPAN::API::Rating;
+# ABSTRACT: Rating information for MetaCPAN::API
+
+use Carp;
+use Any::Moose 'Role';
+
+# /rating/{id}
+# /rating/_search
+sub rating {
+ my $self = shift;
+ my $url = '';
+ my $error = "Either provide 'id' or 'search'";
+
+ my %extra_opts = ();
+
+ if ( @_ == 1 ) {
+ $url = 'rating/' . shift;
+ } elsif ( @_ ) {
+ my %opts = @_;
+
+ if ( defined ( my $id = $opts{'id'} ) ) {
+ $url = "rating/$id";
+ } elsif ( defined ( my $search_opts = $opts{'search'} ) ) {
+ ref $search_opts && ref $search_opts eq 'HASH'
+ or croak $error;
+
+ %extra_opts = %{$search_opts};
+ $url = 'rating/_search';
+ } else {
+ croak $error;
+ }
+ } else {
+ croak $error;
+ }
+
+ return $self->fetch( $url, %extra_opts );
+}
+
+1;
+
+__END__
+
+=head1 DESCRIPTION
+
+This role provides MetaCPAN::API with fetching information about CPAN
+ratings.
+
+=head1 METHODS
+
+=head2 rating
+
+ my $result = $mcpan->rating( id => 'UC6tqabqR-y3xxZk0tgVXQ' );
+
+Searches MetaCPAN for CPAN ratings.
+
+You can do complex searches using 'search' parameter:
+
+ my $result = $mcpan->rating(
+ search => {
+ filter => "distribution:Moose",
+ fields => [ "date", "rating" ],
+ },
+ );
+
+These searches will give you the right _id to use for more detailed
+information.
View
42 t/distribution.t
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+use Test::Fatal;
+use t::lib::Functions;
+
+my $mcpan = mcpan();
+
+isa_ok( $mcpan, 'MetaCPAN::API' );
+can_ok( $mcpan, 'distribution' );
+my $errmsg = qr/^Either provide a distribution or 'search'/;
+
+# missing input
+like(
+ exception { $mcpan->distribution },
+ $errmsg,
+ 'Missing any information',
+);
+
+# incorrect input
+like(
+ exception { $mcpan->distribution( ding => 'dong' ) },
+ $errmsg,
+ 'Incorrect input',
+);
+
+my $result = $mcpan->distribution('DBIx-Class');
+ok( $result, 'Got result' );
+
+$result = $mcpan->distribution( distribution => 'DBIx-Class' );
+ok( $result, 'Got result' );
+
+$result = $mcpan->distribution(
+ search => {
+ filter => { exists => { field => 'bugs.source' } },
+ fields => ['name', 'bugs.source'],
+ size => 5,
+ },
+);
+ok( $result, 'Got result' );
View
36 t/favorite.t
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 5;
+use Test::Fatal;
+use t::lib::Functions;
+
+my $mcpan = mcpan();
+
+isa_ok( $mcpan, 'MetaCPAN::API' );
+can_ok( $mcpan, 'favorite' );
+my $errmsg = qr/^Only 'search' can be used here/;
+
+# missing input
+like(
+ exception { $mcpan->favorite },
+ $errmsg,
+ 'Missing any information',
+);
+
+# incorrect input
+like(
+ exception { $mcpan->favorite( ding => 'dong' ) },
+ $errmsg,
+ 'Incorrect input',
+);
+
+my $result = $mcpan->favorite(
+ search => {
+ user => "SZABGAB",
+ fields => "distribution",
+ size => 100,
+ },
+);
+ok( $result, 'Got result' );
View
45 t/file.t
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 8;
+use Test::Fatal;
+use t::lib::Functions;
+
+my $mcpan = mcpan();
+
+isa_ok( $mcpan, 'MetaCPAN::API' );
+can_ok( $mcpan, 'file' );
+my $errmsg = qr/^Either provide a module name, 'id', or 'author and 'release' and an optional 'path'/;
+
+# missing input
+like(
+ exception { $mcpan->file },
+ $errmsg,
+ 'Missing any information',
+);
+
+# incorrect input
+like(
+ exception { $mcpan->file( ding => 'dong' ) },
+ $errmsg,
+ 'Incorrect input',
+);
+
+my $result = $mcpan->file(
+ author => 'DOY', release => 'Moose-2.0201', path => 'lib/Moose.pm',
+);
+ok( $result, 'Got result' );
+
+$result = $mcpan->file(
+ author => 'DOY', release => 'Moose-2.0201',
+);
+ok( $result, 'Got result' );
+
+$result = $mcpan->file(
+ id => 'ZdlTjiaxpvo9yRWUIB_V06SvRl4'
+);
+ok( $result, 'Got result' );
+
+$result = $mcpan->file('MetaCPAN::API');
+ok( $result, 'Got result' );
View
41 t/rating.t
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+use Test::Fatal;
+use t::lib::Functions;
+
+my $mcpan = mcpan();
+
+isa_ok( $mcpan, 'MetaCPAN::API' );
+can_ok( $mcpan, 'rating' );
+my $errmsg = qr/^Either provide 'id' or 'search'/;
+
+# missing input
+like(
+ exception { $mcpan->rating },
+ $errmsg,
+ 'Missing any information',
+);
+
+# incorrect input
+like(
+ exception { $mcpan->rating( ding => 'dong' ) },
+ $errmsg,
+ 'Incorrect input',
+);
+
+my $result = $mcpan->rating('UC6tqabqR-y3xxZk0tgVXQ');
+ok( $result, 'Got result' );
+
+$result = $mcpan->rating( id => 'UC6tqabqR-y3xxZk0tgVXQ' );
+ok( $result, 'Got result' );
+
+$result = $mcpan->rating(
+ search => {
+ filter => "distribution:Moose",
+ fields => [ "date", "rating" ],
+ },
+);
+ok( $result, 'Got result' );
Please sign in to comment.
Something went wrong with that request. Please try again.