This is an automated email from the git hooks/post-receive script. myon pushed a commit to branch master in repository libgeo-coder-osm-perl.
commit e9c7a84ea87d884f3369c3888cfed08534aadfc2 Author: Christoph Berg <[email protected]> Date: Mon Mar 23 13:22:12 2015 +0100 Import original source of Geo-Coder-OSM 0.03 --- Changes | 11 ++ MANIFEST | 18 +++ META.json | 52 ++++++++ META.yml | 29 +++++ Makefile.PL | 53 ++++++++ README | 30 +++++ ex/custom-useragent.pl | 23 ++++ lib/Geo/Coder/OSM.pm | 312 +++++++++++++++++++++++++++++++++++++++++++++ t/00_compile.t | 5 + t/01_new.t | 9 ++ xt/kwalitee.t | 7 + xt/live.t | 65 ++++++++++ xt/perlcritic.t | 10 ++ xt/perlcriticrc | 22 ++++ xt/pod.t | 9 ++ xt/pod_coverage.t | 9 ++ xt/portability_filenames.t | 9 ++ xt/vars.t | 9 ++ 18 files changed, 682 insertions(+) diff --git a/Changes b/Changes new file mode 100644 index 0000000..e1f94d4 --- /dev/null +++ b/Changes @@ -0,0 +1,11 @@ +Revision history for Geo-Coder-OSM + +0.03 Wed Nov 13 22:40:07 UTC 2013 + - Added reverse_geocode method. + - Allowed for additional sources to be defined. + +0.02 Tue Mar 22 00:15:25 UTC 2011 + - Added support for the Mapquest mirror of the Nominatim service. + +0.01 Sun Jun 27 00:33:44 UTC 2010 + - Initial distribution. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..ead8518 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,18 @@ +Changes +ex/custom-useragent.pl +lib/Geo/Coder/OSM.pm +Makefile.PL +MANIFEST This list of files +README +t/00_compile.t +t/01_new.t +xt/kwalitee.t +xt/live.t +xt/perlcritic.t +xt/perlcriticrc +xt/pod.t +xt/pod_coverage.t +xt/portability_filenames.t +xt/vars.t +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/META.json b/META.json new file mode 100644 index 0000000..44e5876 --- /dev/null +++ b/META.json @@ -0,0 +1,52 @@ +{ + "abstract" : "Geocode addresses with the OpenStreetMap Nominatim API", + "author" : [ + "gray <[email protected]>" + ], + "dynamic_config" : 1, + "generated_by" : "ExtUtils::MakeMaker version 6.82, CPAN::Meta::Converter version 2.132830", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Geo-Coder-OSM", + "no_index" : { + "directory" : [ + "t", + "inc" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "Test::More" : "0.82" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "runtime" : { + "recommends" : { + "JSON::XS" : "2" + }, + "requires" : { + "Encode" : "0", + "JSON" : "2", + "LWP::UserAgent" : "0", + "URI" : "1.36" + } + } + }, + "release_status" : "stable", + "resources" : { + "repository" : { + "url" : "http://github.com/gray/geo-coder-osm" + } + }, + "version" : "0.03" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..c800493 --- /dev/null +++ b/META.yml @@ -0,0 +1,29 @@ +--- +abstract: 'Geocode addresses with the OpenStreetMap Nominatim API' +author: + - 'gray <[email protected]>' +build_requires: + Test::More: 0.82 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 1 +generated_by: 'ExtUtils::MakeMaker version 6.82, CPAN::Meta::Converter version 2.132830' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: Geo-Coder-OSM +no_index: + directory: + - t + - inc +recommends: + JSON::XS: 2 +requires: + Encode: 0 + JSON: 2 + LWP::UserAgent: 0 + URI: 1.36 +resources: + repository: http://github.com/gray/geo-coder-osm +version: 0.03 diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..2faa66c --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,53 @@ +use strict; +use warnings; +use ExtUtils::MakeMaker; + +my %conf = ( + NAME => 'Geo::Coder::OSM', + AUTHOR => 'gray <[email protected]>', + LICENSE => 'perl', + VERSION_FROM => 'lib/Geo/Coder/OSM.pm', + ABSTRACT_FROM => 'lib/Geo/Coder/OSM.pm', + PREREQ_PM => { + 'Encode' => 0, + 'JSON' => 2.0, + 'LWP::UserAgent' => 0, + 'URI' => 1.36, + }, + BUILD_REQUIRES => { + 'Test::More' => 0.82, + }, + META_MERGE => { + resources => { + repository => 'http://github.com/gray/geo-coder-osm', + }, + recommends => { + 'JSON::XS' => 2.0, + }, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Geo-Coder-OSM-*' }, +); + +my $eumm_version=$ExtUtils::MakeMaker::VERSION; +delete $conf{META_MERGE} if $eumm_version < 6.46; +$conf{PREREQ_PM} = { + %{ $conf{PREREQ_PM} || {} }, %{ delete $conf{BUILD_REQUIRES} }, +} if ($conf{BUILD_REQUIRES} and $eumm_version < 6.5503); + +WriteMakefile(%conf); + + +sub MY::postamble { + return <<" MAKE_FRAG"; +authortest: +\t\$(MAKE) -e \$(TEST_TYPE) TEST_FILES="xt/*.t" + MAKE_FRAG +} + +sub MY::dist_test { + my $self = shift; + return $self->MM::dist_test . <<" MAKE_FRAG"; +\tcd \$(DISTVNAME) && \$(MAKE) authortest \$(PASTHRU) + MAKE_FRAG +} diff --git a/README b/README new file mode 100644 index 0000000..4a377dd --- /dev/null +++ b/README @@ -0,0 +1,30 @@ +Geo-Coder-OSM +============= + +This module provides an interface to the OpenStreetMap Nominatim API + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + + Encode + JSON + LWP::UserAgent + Test::More + URI + +COPYRIGHT AND LICENCE + +Copyright (C) 2010-2013 by gray <[email protected]> + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. diff --git a/ex/custom-useragent.pl b/ex/custom-useragent.pl new file mode 100755 index 0000000..deff913 --- /dev/null +++ b/ex/custom-useragent.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use Data::Dumper; +use Geo::Coder::OSM; + +my $location = join(' ', @ARGV) || die "Usage: $0 \$location_string"; + +# Custom useragent identifier. +my $ua = LWP::UserAgent->new(agent => 'My Geocoder'); + +# Load any proxy settings from environment variables. +$ua->env_proxy; + +my $geocoder = Geo::Coder::OSM->new( + ua => $ua, + debug => 1, +); +my $result = $geocoder->geocode(location => $location); + +local $Data::Dumper::Indent = 1; +print Dumper($result); diff --git a/lib/Geo/Coder/OSM.pm b/lib/Geo/Coder/OSM.pm new file mode 100644 index 0000000..24b90d6 --- /dev/null +++ b/lib/Geo/Coder/OSM.pm @@ -0,0 +1,312 @@ +package Geo::Coder::OSM; + +use strict; +use warnings; + +use Carp qw(croak); +use Encode (); +use JSON; +use LWP::UserAgent; +use URI; + +our $VERSION = '0.03'; +$VERSION = eval $VERSION; + +our %SOURCES = ( + osm => 'http://nominatim.openstreetmap.org', + mapquest => 'http://open.mapquestapi.com/nominatim/v1', +); + +sub new { + my ($class, @params) = @_; + my %params = (@params % 2) ? (key => @params) : @params; + + my $self = bless \ %params, $class; + + $self->ua( + $params{ua} || LWP::UserAgent->new(agent => "$class/$VERSION") + ); + + if (exists $self->{sources}) { + my $sources = $self->{sources}; + $self->{sources} = $sources = [$sources] unless ref $sources; + for my $source (@$sources) { + croak qq(unknown source '$source') + unless exists $SOURCES{$source}; + } + } + else { + $self->{sources} = ['osm']; + } + + $self->{source_idx} = 0; + + if ($self->{debug}) { + my $dump_sub = sub { $_[0]->dump(maxlength => 0); return }; + $self->ua->set_my_handler(request_send => $dump_sub); + $self->ua->set_my_handler(response_done => $dump_sub); + } + elsif (exists $self->{compress} ? $self->{compress} : 1) { + $self->ua->default_header(accept_encoding => 'gzip,deflate'); + } + + return $self; +} + +sub response { $_[0]->{response} } + +sub ua { + my ($self, $ua) = @_; + if ($ua) { + croak q('ua' must be (or derived from) an LWP::UserAgent') + unless ref $ua and $ua->isa(q(LWP::UserAgent)); + $self->{ua} = $ua; + } + return $self->{ua}; +} + +sub geocode { + my ($self, @params) = @_; + my %params = (@params % 2) ? (location => @params) : @params; + + my $location = delete $params{location} or return; + $location = Encode::encode('utf-8', $location); + + # Cycle throught the list of sources. + my $idx = ($self->{source_idx} %= @{ $self->{sources} })++; + + my $uri = URI->new($SOURCES{ $self->{sources}[$idx] } . '/search'); + $uri->query_form( + q => $location, + format => 'json', + addressdetails => 1, + 'accept-language' => 'en', + %params, + ); + + return $self->_request($uri); +} + +sub reverse_geocode { + my ($self, @params) = @_; + my %params = (@params % 2) ? (latlng => @params) : @params; + + # Maintain api compatibility with other geocoders. + my ($lat, $lon); + if (my $latlon = delete $params{latlng}) { + ($lat, $lon) = split '\s*,\s*', $latlon; + } + else { + $lat = delete $params{lat}; + ($lon) = grep defined, delete @params{qw(lon lng)}; + } + return unless 2 == grep defined, $lat, $lon; + + # Cycle throught the list of sources. + my $idx = ($self->{source_idx} %= @{ $self->{sources} })++; + + my $uri = URI->new($SOURCES{ $self->{sources}[$idx] } . '/reverse'); + $uri->query_form( + lat => $lat, + lon => $lon, + format => 'json', + addressdetails => 1, + 'accept-language' => 'en', + %params, + ); + + return $self->_request($uri); +} + +sub _request { + my ($self, $uri) = @_; + + return unless $uri; + + my $res = $self->{response} = $self->ua->get($uri); + return unless $res->is_success; + + # Change the content type of the response (if necessary) so + # HTTP::Message will decode the character encoding. + $res->content_type('text/plain') + unless $res->content_type =~ /^text/; + + my $content = $res->decoded_content; + return unless $content; + + my $data = eval { from_json($content) }; + return unless $data; + + my @results = 'ARRAY' eq ref $data ? @$data : ($data); + return wantarray ? @results : $results[0]; +} + + +1; + +__END__ + +=head1 NAME + +Geo::Coder::OSM - Geocode addresses with the OpenStreetMap Nominatim API + +=head1 SYNOPSIS + + use Geo::Coder::OSM; + + my $geocoder = Geo::Coder::OSM->new; + my $location = $geocoder->geocode( + location => 'Hollywood and Highland, Los Angeles, CA' + ); + +=head1 DESCRIPTION + +The C<Geo::Coder::OSM> module provides an interface to the OpenStreet +Nominatim geocoding service. + +=head1 METHODS + +=head2 new + + $geocoder = Geo::Coder::OSM->new() + $geocoder = Geo::Coder::OSM->new( + ua => $ua, + sources => [ 'osm', 'mapquest' ], + debug => 1, + ) + +Creates a new geocoding object. + +Accepts an optional B<ua> parameter for passing in a custom LWP::UserAgent +object. + +Accepts an optional B<sources> parameter for specifying the data sources. +Current valid values are B<osm> and B<mapquest>. The default value is B<osm>. +To cycle between different sources, specify an array reference for the +B<sources> value. To define additional sources, see L</SOURCES> below. + +=head2 geocode + + $location = $geocoder->geocode(location => $location) + @locations = $geocoder->geocode(location => $location) + +In scalar context, this method returns the first location result; and in +list context it returns all location results. + +Each location result is a hashref; a typical example looks like: + + { + address => { + city => "Los Angeles", + country => "United States of America", + country_code => "us", + hamlet => "Hollywood", + road => "Hollywood Boulevard", + station => "Hollywood/Highland", + suburb => "Little Armenia", + }, + boundingbox => [ + "34.101634979248", "34.1018371582031", + "-118.339317321777", "-118.33910369873", + ], + class => "railway", + display_name => + "Hollywood/Highland, Hollywood Boulevard, Little Armenia, Hollywood, Los Angeles, United States of America", + icon => + "http://nominatim.openstreetmap.org/images/mapicons/transport_train_station2.p.20.png", + lat => "34.101736", + licence => + "Data Copyright OpenStreetMap Contributors, Some Rights Reserved. CC-BY-SA 2.0.", + lon => "-118.33921", + osm_id => 472413621, + osm_type => "node", + place_id => 9071654, + type => "station", + } + +=head2 reverse_geocode + + $location = $geocoder->reverse_geocode(lat => $lat, lon => $lon) + $location = $geocoder->reverse_geocode(latlng => "$lat,$lon") + +Returns a location result for the given lat/lon pair. + +=head2 response + + $response = $geocoder->response() + +Returns an L<HTTP::Response> object for the last submitted request. Can be +used to determine the details of an error. + +=head2 ua + + $ua = $geocoder->ua() + $ua = $geocoder->ua($ua) + +Accessor for the UserAgent object. + +=head2 SOURCES + +To define additional sources add them to the B<%SOURCES> package variable like +so: + + $Geo::Coder::OSM::SOURCES{local} = 'http://127.0.0.1/api_base_path'; + $Geo::Coder::OSM::SOURCES{internal} = 'http://internal.corp/api_base_path'; + +=head1 SEE ALSO + +L<http://wiki.openstreetmap.org/wiki/Nominatim> + +L<http://open.mapquestapi.com/nominatim/> + +=head1 REQUESTS AND BUGS + +Please report any bugs or feature requests to +L<http://rt.cpan.org/Public/Bug/Report.html?Queue=Geo-Coder-OSM>. I will be +notified, and then you'll automatically be notified of progress on your bug +as I make changes. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Geo::Coder::OSM + +You can also look for information at: + +=over + +=item * GitHub Source Repository + +L<http://github.com/gray/geo-coder-osm> + +=item * AnnoCPAN: Annotated CPAN documentation + +L<http://annocpan.org/dist/Geo-Coder-OSM> + +=item * CPAN Ratings + +L<http://cpanratings.perl.org/d/Geo-Coder-OSM> + +=item * RT: CPAN's request tracker + +L<http://rt.cpan.org/Public/Dist/Display.html?Name=Geo-Coder-OSM> + +=item * Search CPAN + +L<http://search.cpan.org/dist/Geo-Coder-OSM/> + +=back + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2010-2013 gray <gray at cpan.org>, all rights reserved. + +This library is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=head1 AUTHOR + +gray, <gray at cpan.org> + +=cut diff --git a/t/00_compile.t b/t/00_compile.t new file mode 100644 index 0000000..0b4e475 --- /dev/null +++ b/t/00_compile.t @@ -0,0 +1,5 @@ +use strict; +use warnings; +use Test::More tests => 1; + +BEGIN { use_ok 'Geo::Coder::OSM' } diff --git a/t/01_new.t b/t/01_new.t new file mode 100644 index 0000000..ebef748 --- /dev/null +++ b/t/01_new.t @@ -0,0 +1,9 @@ +use strict; +use warnings; +use Test::More tests => 3; +use Geo::Coder::OSM; + +new_ok('Geo::Coder::OSM' => []); +new_ok('Geo::Coder::OSM' => [debug => 1]); + +can_ok('Geo::Coder::OSM', qw(geocode response ua)); diff --git a/xt/kwalitee.t b/xt/kwalitee.t new file mode 100644 index 0000000..7b704ce --- /dev/null +++ b/xt/kwalitee.t @@ -0,0 +1,7 @@ +use strict; +use warnings; +use Test::More; + +eval { require Test::Kwalitee; Test::Kwalitee->import(); 1 } or do { + plan skip_all => 'Test::Kwalitee not installed; skipping'; +}; diff --git a/xt/live.t b/xt/live.t new file mode 100644 index 0000000..702b314 --- /dev/null +++ b/xt/live.t @@ -0,0 +1,65 @@ +use strict; +use warnings; +use Encode; +use Geo::Coder::OSM; +use LWP::UserAgent; +use Test::More; + +my $debug = $ENV{GEO_CODER_OSM_DEBUG}; +diag "Set GEO_CODER_OSM_DEBUG to see request/response data" + unless $debug; + +for my $source (qw(osm mapquest)) { + my $geocoder = Geo::Coder::OSM->new( + debug => $debug, + sources => $source, + ); + { + my $address = '132 Maney Hill Road, West Midlands, UK'; + my $forward = $geocoder->geocode($address); + is( + $forward->{address}{town}, + 'Sutton Coldfield', + "correct town for $address" + ); + my $road = $forward->{address}{road}; + + my ($lat, $lon) = @$forward{qw(lat lon)}; + my $reverse = $geocoder->reverse_geocode(lat => $lat, lon => $lon); + is( + $reverse->{address}{road}, + $forward->{address}{road}, + 'correct street for lat/lon', + ); + } + { + my $address = qq(Champs-\xC9lys\xE9es, 75008); + + my $location = $geocoder->geocode($address); + ok($location, 'latin1 bytes'); + is($location->{address}{country}, 'France', 'latin1 bytes'); + + $location = $geocoder->geocode(decode('latin1', $address)); + ok($location, 'UTF-8 characters'); + is($location->{address}{country}, 'France', 'UTF-8 characters'); + + TODO: { + local $TODO = 'UTF-8 bytes'; + $location = $geocoder->geocode( + encode('utf-8', decode('latin1', $address)) + ); + ok($location, 'UTF-8 bytes'); + is($location->{address}{country}, 'France', 'UTF-8 bytes'); + } + } + { + my $city = decode('latin1', qq(Schm\xF6ckwitz)); + my $location = $geocoder->geocode("$city, Berlin, Germany"); + is( + $location->{address}{suburb}, $city, + 'decoded character encoding of response' + ); + } +} + +done_testing; diff --git a/xt/perlcritic.t b/xt/perlcritic.t new file mode 100644 index 0000000..e4cfc15 --- /dev/null +++ b/xt/perlcritic.t @@ -0,0 +1,10 @@ +use strict; +use warnings; +use Test::More; + +eval { require Test::Perl::Critic; 1 } or do { + plan skip_all => "Test::Perl::Critic is not installed."; +}; +Test::Perl::Critic->import( -profile => 'xt/perlcriticrc' ); + +all_critic_ok(qw( ex lib t xt )); diff --git a/xt/perlcriticrc b/xt/perlcriticrc new file mode 100644 index 0000000..aa03514 --- /dev/null +++ b/xt/perlcriticrc @@ -0,0 +1,22 @@ +verbose = 8 + +[CodeLayout::ProhibitHardTabs] +allow_leading_tabs = 0 +severity = 5 + +[CodeLayout::ProhibitTrailingWhitespace] +severity = 5 + +# requires Perl::Critic::More +[CodeLayout::RequireASCII] +severity = 5 + +[TestingAndDebugging::RequireUseWarnings] +severity = 5 + +[-TestingAndDebugging::ProhibitNoStrict] +[-BuiltinFunctions::ProhibitStringyEval] + +# requires Regexp::Parser +[RegularExpressions::ProhibitUnusedCapture] +severity = 5 diff --git a/xt/pod.t b/xt/pod.t new file mode 100644 index 0000000..4ed8308 --- /dev/null +++ b/xt/pod.t @@ -0,0 +1,9 @@ +use strict; +use warnings; +use Test::More; + +eval "use Test::Pod 1.00; 1" or do { + plan skip_all => 'Test::Pod 1.00 required for testing POD'; +}; + +all_pod_files_ok(); diff --git a/xt/pod_coverage.t b/xt/pod_coverage.t new file mode 100644 index 0000000..a345856 --- /dev/null +++ b/xt/pod_coverage.t @@ -0,0 +1,9 @@ +use strict; +use warnings; +use Test::More; + +eval "use Test::Pod::Coverage 1.00; 1" or do { + plan skip_all => 'Test::Pod::Coverage 1.00 is not installed.'; +}; + +all_pod_coverage_ok(); diff --git a/xt/portability_filenames.t b/xt/portability_filenames.t new file mode 100644 index 0000000..6b94873 --- /dev/null +++ b/xt/portability_filenames.t @@ -0,0 +1,9 @@ +use strict; +use warnings; +use Test::More; + +eval "use Test::Portability::Files; 1" or do { + plan skip_all => 'Test::Portability::Files is not installed.'; +}; + +run_tests(); diff --git a/xt/vars.t b/xt/vars.t new file mode 100644 index 0000000..39b57ae --- /dev/null +++ b/xt/vars.t @@ -0,0 +1,9 @@ +use strict; +use warnings; +use Test::More; + +eval "use Test::Vars; 1" or do { + plan skip_all => 'Test::Vars is not installed.'; +}; + +all_vars_ok(); -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libgeo-coder-osm-perl.git _______________________________________________ Pkg-perl-cvs-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits
