Skip Menu |

This queue is for tickets about the Geo-Coder-Google CPAN distribution.

Report information
The Basics
Id: 79007
Status: resolved
Priority: 0/
Queue: Geo-Coder-Google

People
Owner: Nobody in particular
Requestors: MRDVT [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.11
Fixed in: (no value)



Subject: geocode method randomly returns undef
The geocode method randomly returns undef but the method does not store any of the data to triage at the higher application levels. I guess since I don't have enough tools. I'd like to see this... $self->{"last_res"} = $self->{"last_json"} = $self->{"last_data"} = undef; $self->{"last_res"} = $self->{ua}->get($url); if ($self->{"last_res"}->is_error) { Carp::croak("Google Maps API returned error: " . $self-> {"last_res"}->status_line); } $self->{"last_json"} = JSON->new->utf8; $self->{"last_data"} = $self->{"last_json"}->decode($res->content); my @results = @{ $self->{"last_data"}->{results} || [] }; wantarray ? @results : $results[0]; I don't really see a need to limit the scope on this data to inside the method. What do you think? Mike mrdvt92
I prototyped it up and I found out this... 'last_data' => { 'status' => 'OVER_QUERY_LIMIT', 'results' => [] }, and 'client' => '', Oh the little bugs... package XXX::Geo::Coder::Google::V3; use strict; use warnings; use base qw{Geo::Coder::Google::V3}; =head1 LICENSE Copyright 2012 Tatsuhiko Miyagawa <miyagawa@bulknews.net>, Justin Hunter <justin.d.hunter@gmail.com> and Michael R. Davis <mrdvt92> This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut sub geocode { my $self = shift; my %param; if (@_ % 2 == 0) { %param = @_; } else { $param{location} = shift; } my $location = $param{location} or Carp::croak("Usage: geocode(location => \$location)"); if (Encode::is_utf8($location)) { $location = Encode::encode_utf8($location); } my $uri = URI->new("http://$self->{host}/maps/api/geocode/json"); my %query_parameters = (address => $location); $query_parameters{language} = $self->{language} if defined $self-> {language}; $query_parameters{region} = $self->{region} if defined $self-> {region}; $query_parameters{oe} = $self->{oe}; $query_parameters{sensor} = $self->{sensor} ? 'true' : 'false'; $uri->query_form(%query_parameters); my $url = $uri->as_string; # Process Maps Premier account info if ($self->{client} and $self->{key}) { $query_parameters{client} = $self->{client}; $uri->query_form(%query_parameters); my $signature = $self->make_signature($uri); # signature must be last parameter in query string or you get 403's $url = $uri->as_string; $url .= '&signature='.$signature if $signature; } $self->{"last_res"} = $self->{"last_json"} = $self->{"last_data"} = undef; $self->{"last_res"} = $self->{ua}->get($url); if ($self->{"last_res"}->is_error) { Carp::croak("Google Maps API returned error: " . $self-> {"last_res"}->status_line); } $self->{"last_json"} = JSON->new->utf8; $self->{"last_data"} = $self->{"last_json"}->decode($self-> {"last_res"}->content); my @results = @{ $self->{"last_data"}->{results} || [] }; wantarray ? @results : $results[0]; } 1;
can you make a diff against git master or a pull request? (https://github.com/arcanez/geo-coder-google) On Wed Aug 15 23:56:45 2012, MRDVT wrote: Show quoted text
> I prototyped it up and I found out this... > > 'last_data' => { > 'status' => 'OVER_QUERY_LIMIT', > 'results' => [] > }, > > and > > 'client' => '', > > Oh the little bugs... > > > package XXX::Geo::Coder::Google::V3; > use strict; > use warnings; > use base qw{Geo::Coder::Google::V3}; > > =head1 LICENSE > > Copyright 2012 Tatsuhiko Miyagawa <miyagawa@bulknews.net>, Justin > Hunter <justin.d.hunter@gmail.com> and Michael R. Davis <mrdvt92> > > This library is free software; you can redistribute it and/or modify
it Show quoted text
> under the same terms as Perl itself. > > =cut > > sub geocode { > my $self = shift; > > my %param; > if (@_ % 2 == 0) { > %param = @_; > } else { > $param{location} = shift; > } > > my $location = $param{location} > or Carp::croak("Usage: geocode(location => \$location)"); > > if (Encode::is_utf8($location)) { > $location = Encode::encode_utf8($location); > } > > my $uri = URI->new("http://$self->{host}/maps/api/geocode/json"); > my %query_parameters = (address => $location); > $query_parameters{language} = $self->{language} if defined $self-> > {language}; > $query_parameters{region} = $self->{region} if defined $self-> > {region}; > $query_parameters{oe} = $self->{oe}; > $query_parameters{sensor} = $self->{sensor} ? 'true' : 'false'; > $uri->query_form(%query_parameters); > my $url = $uri->as_string; > > # Process Maps Premier account info > if ($self->{client} and $self->{key}) { > $query_parameters{client} = $self->{client}; > $uri->query_form(%query_parameters); > > my $signature = $self->make_signature($uri); > # signature must be last parameter in query string or you get > 403's > $url = $uri->as_string; > $url .= '&signature='.$signature if $signature; > } > > $self->{"last_res"} = $self->{"last_json"} = $self->{"last_data"}
= Show quoted text
> undef; > > $self->{"last_res"} = $self->{ua}->get($url); > > if ($self->{"last_res"}->is_error) { > Carp::croak("Google Maps API returned error: " . $self-> > {"last_res"}->status_line); > } > > $self->{"last_json"} = JSON->new->utf8; > $self->{"last_data"} = $self->{"last_json"}->decode($self-> > {"last_res"}->content); > > my @results = @{ $self->{"last_data"}->{results} || [] }; > wantarray ? @results : $results[0]; > } > > 1;
Show quoted text
> can you make a diff against git master or a pull request?
The method was simply copied, pasted and tweaked. I also got this error so we need a little more tweaking. 'last_data' => { 'status' => 'ZERO_RESULTS', 'results' => [] }, We need to expose the JSON status in the object as well and we should be cacheing the JSON object construction. I'd like to see the ua lazy loaded too. Thanks, Mike mrdvt92
Patch attached... Show quoted text
> can you make a diff against git master or a pull request? > (https://github.com/arcanez/geo-coder-google)
Subject: 0001-Changes-Michael-R.-Davis-mrdvt92.patch
From 6e1c5fa83c77bca4fcb844c816331443d8947886 Mon Sep 17 00:00:00 2001 From: Michael R. Davis <mrdvt@cpan.org> Date: Sat, 18 Aug 2012 04:46:51 +0000 Subject: [PATCH] Changes Michael R. Davis <mrdvt92> 0.12 Fri Aug 18 23:59:59 EDT 2012 - Updated pod to pass tests - Lazy load LWP::UserAgent and JSON - Cache JSON object - Stash data in variables last_data, last_res, last_status --- Changes | 7 +++++ lib/Geo/Coder/Google.pm | 7 ++++- lib/Geo/Coder/Google/V3.pm | 60 ++++++++++++++++++++++++------------------- t/02_v3_live.t | 6 +++- t/kwalitee.t | 7 +++++ t/pod-coverage.t | 4 +++ t/pod.t | 4 +++ 7 files changed, 66 insertions(+), 29 deletions(-) create mode 100644 t/kwalitee.t create mode 100644 t/pod-coverage.t create mode 100644 t/pod.t diff --git a/Changes b/Changes index 8ecb216..d7abbb6 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,11 @@ Revision history for Perl extension Geo::Coder::Google + +0.12 Fri Aug 18 23:59:59 EDT 2012 + - Updated pod to pass tests + - Lazy load LWP::UserAgent and JSON + - Cache JSON object + - Stash data in variables last_data, last_res, last_status + 0.11 Wed Jul 25 11:50:34 EDT 2012 - fix live test data - skip live tests by default, providing an $ENV var to enable them diff --git a/lib/Geo/Coder/Google.pm b/lib/Geo/Coder/Google.pm index 94cbaa6..c658f88 100644 --- a/lib/Geo/Coder/Google.pm +++ b/lib/Geo/Coder/Google.pm @@ -2,7 +2,7 @@ package Geo::Coder::Google; use strict; use warnings; -our $VERSION = '0.11'; +our $VERSION = '0.12'; sub new { my ($self, %param) = @_; @@ -28,4 +28,9 @@ See L<Geo::Coder::Google::V2> for V2 API usage. See L<Geo::Coder::Google::V3> for V3 API usage. +=head2 new + + my $geocoder=Geo::Coder::Google->new(apiver=>2); + my $geocoder=Geo::Coder::Google->new(apiver=>3); + =cut diff --git a/lib/Geo/Coder/Google/V3.pm b/lib/Geo/Coder/Google/V3.pm index f9cd0ed..0a2eee6 100644 --- a/lib/Geo/Coder/Google/V3.pm +++ b/lib/Geo/Coder/Google/V3.pm @@ -2,7 +2,7 @@ package Geo::Coder::Google::V3; use strict; use warnings; -our $VERSION = '0.11'; +our $VERSION = '0.12'; use Carp; use Encode; @@ -14,7 +14,6 @@ use URI; sub new { my($class, %param) = @_; - my $ua = delete $param{ua} || LWP::UserAgent->new(agent => __PACKAGE__ . "/$VERSION"); my $host = delete $param{host} || 'maps.googleapis.com'; my $language = delete $param{language} || delete $param{hl}; @@ -25,23 +24,27 @@ sub new { my $key = delete $param{key} || ''; bless { - ua => $ua, host => $host, language => $language, + host => $host, language => $language, region => $region, oe => $oe, sensor => $sensor, client => $client, key => $key, }, $class; } sub ua { - my $self = shift; - if (@_) { - $self->{ua} = shift; - } - $self->{ua}; + my $self = shift; + $self->{ua} = shift if @_; + $self->{ua} = LWP::UserAgent->new(agent => __PACKAGE__ . "/$VERSION") + unless defined $self->{ua}; + return $self->{ua}; } sub geocode { my $self = shift; + $self->{"last_res"} = undef; + $self->{"last_data"} = undef; + $self->{"last_status"} = undef; + my %param; if (@_ % 2 == 0) { %param = @_; @@ -70,28 +73,35 @@ sub geocode { $query_parameters{client} = $self->{client}; $uri->query_form(%query_parameters); - my $signature = $self->make_signature($uri); + my $signature = $self->_make_signature($uri); # signature must be last parameter in query string or you get 403's $url = $uri->as_string; $url .= '&signature='.$signature if $signature; } - my $res = $self->{ua}->get($url); + $self->{"last_res"} = $self->ua->get($url); - if ($res->is_error) { - Carp::croak("Google Maps API returned error: " . $res->status_line); + if ($self->{"last_res"}->is_error) { + Carp::croak("Google Maps API returned error: " . $self->{"last_res"}->status_line); } - my $json = JSON->new->utf8; - my $data = $json->decode($res->content); + $self->{"last_data"} = $self->_json->decode($self->{"last_res"}->content); + $self->{"last_status"} = $self->{"last_data"}->{"status"}; - my @results = @{ $data->{results} || [] }; + my @results = @{ $self->{"last_data"}->{results} || [] }; wantarray ? @results : $results[0]; } +sub _json { + my $self=shift; + $self->{"json"}=JSON->new->utf8 + unless defined $self->{"json"}; + return $self->{"json"}; +} + # methods below adapted from # http://gmaps-samples.googlecode.com/svn/trunk/urlsigning/urlsigner.pl -sub decode_urlsafe_base64 { +sub _decode_urlsafe_base64 { my ($self, $content) = @_; $content =~ tr/-/\+/; @@ -100,7 +110,7 @@ sub decode_urlsafe_base64 { return MIME::Base64::decode_base64($content); } -sub encode_urlsafe{ +sub _encode_urlsafe{ my ($self, $content) = @_; $content =~ tr/\+/\-/; $content =~ tr/\//\_/; @@ -108,20 +118,20 @@ sub encode_urlsafe{ return $content; } -sub make_signature { +sub _make_signature { my ($self, $uri) = @_; require Digest::HMAC_SHA1; require MIME::Base64; - my $key = $self->decode_urlsafe_base64($self->{key}); + my $key = $self->_decode_urlsafe_base64($self->{key}); my $to_sign = $uri->path_query; my $digest = Digest::HMAC_SHA1->new($key); $digest->add($to_sign); my $signature = $digest->b64digest; - return $self->encode_urlsafe($signature); + return $self->_encode_urlsafe($signature); } @@ -145,9 +155,7 @@ Geo::Coder::Google::V3 provides a geocoding functionality using Google Maps API =head1 METHODS -=over 4 - -=item new +=head2 new $geocoder = Geo::Coder::Google->new(apiver => 3); $geocoder = Geo::Coder::Google->new(apiver => 3, language => 'ru'); @@ -171,7 +179,7 @@ variables GMAP_CLIENT and GMAP_KEY before running 02_v3_live.t GMAP_CLIENT=your_id GMAP_KEY='your_key' make test -=item geocode +=head2 geocode $location = $geocoder->geocode(location => $location); @location = $geocoder->geocode(location => $location); @@ -184,7 +192,7 @@ returns the 1st one in a scalar context. When you'd like to pass non-ascii string as a location, you should pass it as either UTF-8 bytes or Unicode flagged string. -=item ua +=head2 ua Accessor method to get and set UserAgent object used internally. You can call I<env_proxy> for example, to get the proxy information from @@ -196,8 +204,6 @@ You can also set your own User-Agent object: $coder->ua( LWPx::ParanoidAgent->new ); -=back - =head1 AUTHOR Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt> diff --git a/t/02_v3_live.t b/t/02_v3_live.t index ffd1e3e..914290b 100644 --- a/t/02_v3_live.t +++ b/t/02_v3_live.t @@ -6,7 +6,7 @@ use Encode (); use Geo::Coder::Google; if ($ENV{TEST_GEOCODER_GOOGLE_LIVE}) { - plan tests => 8; + plan tests => 12; } else { plan skip_all => 'Not running live tests. Set $ENV{TEST_GEOCODER_GOOGLE_LIVE} = 1 to enable'; } @@ -16,6 +16,10 @@ if ($ENV{TEST_GEOCODER_GOOGLE_LIVE}) { my $location = $geocoder->geocode('548 4th Street, San Francisco, CA'); delta_ok($location->{geometry}{location}{lat}, 37.778907); delta_ok($location->{geometry}{location}{lng}, -122.39732); + is($geocoder->{"last_status"}, "OK", "last_staus"); + isa_ok($geocoder->_json, "JSON"); + isa_ok($geocoder->{"last_res"}, "HTTP::Response", "last_res"); + isa_ok($geocoder->{"last_data"}, "HASH", "last_data"); } SKIP: { diff --git a/t/kwalitee.t b/t/kwalitee.t new file mode 100644 index 0000000..fac1f57 --- /dev/null +++ b/t/kwalitee.t @@ -0,0 +1,7 @@ +use Test::More; + +eval { require Test::Kwalitee; Test::Kwalitee->import(tests => [qw{ -has_meta_yml }]) }; + +plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@; + +unlink($_) foreach (<Debian_CPANTS.*>); diff --git a/t/pod-coverage.t b/t/pod-coverage.t new file mode 100644 index 0000000..2c5ca56 --- /dev/null +++ b/t/pod-coverage.t @@ -0,0 +1,4 @@ +use Test::More; +eval "use Test::Pod::Coverage 1.00"; +plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage" if $@; +all_pod_coverage_ok(); diff --git a/t/pod.t b/t/pod.t new file mode 100644 index 0000000..437887a --- /dev/null +++ b/t/pod.t @@ -0,0 +1,4 @@ +use Test::More; +eval "use Test::Pod 1.00"; +plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; +all_pod_files_ok(); -- 1.7.2.3
Are you planning to work this issue or should I fork the package? I'd rather not have to maintain yet another package. The limitations are probably too much not to have a return object that has status and data. Let me know, Thanks, Mike mrdvt92
I have applied the patch to a 'status-object' branch (https://github.com/arcanez/geo-coder-google/tree/status-object) and shipped 0.11_01 to CPAN for you to test On Tue Sep 11 22:06:17 2012, MRDVT wrote: Show quoted text
> Are you planning to work this issue or should I fork the package? I'd > rather not have to maintain yet another package. > > The limitations are probably too much not to have a return object that > has status and data. > > Let me know, > Thanks, > Mike > > > mrdvt92
On Wed Sep 12 10:35:53 2012, arcanez wrote: Show quoted text
> I have applied the patch ... and > shipped 0.11_01 to CPAN for you to test
I noticed that 0.11_02 does not support ZERO_RESULTS Status Code. •"ZERO_RESULTS" indicates that the geocode was successful but returned no results. This may occur if the geocode was passed a non-existent address or a latlng in a remote location. •"OVER_QUERY_LIMIT" indicates that you are over your quota. •"REQUEST_DENIED" indicates that your request was denied, generally because of lack of a sensor parameter. •"INVALID_REQUEST" generally indicates that the query (address or latlng) is missing. I'd prefer the other option. Carp::croak(sprintf(qq{Google Maps API returned status "%s"}, $data-> {status})) unless $data->{status} eq 'OK';
I have uploaded 0.11_03 with this change. POSTing upload for Geo-Coder-Google-0.11_03.tar.gz to https://pause.perl.org/pause/authenquery PAUSE add message sent ok [200] On Sun Jan 20 21:30:12 2013, MRDVT wrote: Show quoted text
> On Wed Sep 12 10:35:53 2012, arcanez wrote:
> > I have applied the patch ... and > > shipped 0.11_01 to CPAN for you to test
> > I noticed that 0.11_02 does not support ZERO_RESULTS Status Code. > > •"ZERO_RESULTS" indicates that the geocode was successful but
returned Show quoted text
> no results. This may occur if the geocode was passed a non-existent > address or a latlng in a remote location. > •"OVER_QUERY_LIMIT" indicates that you are over your quota. > •"REQUEST_DENIED" indicates that your request was denied, generally > because of lack of a sensor parameter. > •"INVALID_REQUEST" generally indicates that the query (address or > latlng) is missing. > > I'd prefer the other option. > > Carp::croak(sprintf(qq{Google Maps API returned status "%s"}, $data-> > {status})) > unless $data->{status} eq 'OK'; >
registering upload with PAUSE web server POSTing upload for Geo-Coder-Google-0.12.tar.gz to https://pause.perl.org/pause/authenquery PAUSE add message sent ok [200] On Fri Mar 15 09:12:45 2013, arcanez wrote: Show quoted text
> I have uploaded 0.11_03 with this change. > > POSTing upload for Geo-Coder-Google-0.11_03.tar.gz to > https://pause.perl.org/pause/authenquery > PAUSE add message sent ok [200] > > > On Sun Jan 20 21:30:12 2013, MRDVT wrote:
> > On Wed Sep 12 10:35:53 2012, arcanez wrote:
> > > I have applied the patch ... and > > > shipped 0.11_01 to CPAN for you to test
> > > > I noticed that 0.11_02 does not support ZERO_RESULTS Status Code. > > > > •"ZERO_RESULTS" indicates that the geocode was successful but
> returned
> > no results. This may occur if the geocode was passed a non-existent > > address or a latlng in a remote location. > > •"OVER_QUERY_LIMIT" indicates that you are over your quota. > > •"REQUEST_DENIED" indicates that your request was denied, generally > > because of lack of a sensor parameter. > > •"INVALID_REQUEST" generally indicates that the query (address or > > latlng) is missing. > > > > I'd prefer the other option. > > > > Carp::croak(sprintf(qq{Google Maps API returned status "%s"}, $data-> > > {status})) > > unless $data->{status} eq 'OK'; > >
> >