Commit 1a2a0f43 authored by Andy Yates's avatar Andy Yates
Browse files

Removing URIParser sub-package. It was nice in theory but I'd rather support...

Removing URIParser sub-package. It was nice in theory but I'd rather support different schemes using extensions to the URI package
parent 9972cdee
......@@ -20,36 +20,27 @@
=head1 NAME
Bio::EnsEMBL::Utils::URIParser::URI
Bio::EnsEMBL::Utils::URI
=head1 SYNOPSIS
use Bio::EnsEMBL::Utils::URIParser::URI;
#If it was a normal http URI
my $uri = Bio::EnsEMBL::Utils::URIParser::URI->new();
$uri->scheme('http');
$uri->host('www.google.co.uk');
$uri->port(80);
$uri->path('/search');
$uri->add_param('q', 'testing');
my $google_uri = $uri->generate_uri(); # produces 'http://www.google.co.uk:80/search?q=testing'
#Or if we had parsed a database URI
my $db_uri = get_my_db_uri();
my $dbc = Bio::EnsEMBL::DBSQL::DBConnection->new($db_uri->generate_dbsql_params());
use Bio::EnsEMBL::Utils::URI qw/parse_uri/;
my $up = Bio::EnsEMBL::Utils::URIParser->new();
my $db_uri = parse_uri('mysql://user@host:3157/db');
my $http_uri = parse_uri('http://www.google.co.uk:80/search?q=t');
=head1 DESCRIPTION
This is a module used for the storage of a parsed URI and the generation of
various formats of the data used by the Ensembl core infrastructure. The code
works in 2 modes;
This object is a generic URI parser which is primarily used in the
parsing of database URIs into a more managable data structure. We also provide
the resulting URI object
=head1 METHODS
=cut
package Bio::EnsEMBL::Utils::URIParser::URI;
package Bio::EnsEMBL::Utils::URI;
use strict;
use warnings;
......@@ -57,6 +48,78 @@ use warnings;
use Scalar::Util qw/looks_like_number/;
use Bio::EnsEMBL::Utils::Exception qw(throw);
use base qw/Exporter/;
our @EXPORT_OK;
@EXPORT_OK = qw/parse_uri/;
####URI Parsing
=head2 parse_uri
Arg[1] : Scalar; URI to parse
Example : my $uri = parse_uri('mysql://user:pass@host:415/db');
Description : A URL parser which attempts to convert many different types
of URL into a common data structure.
Returntype : Bio::EnsEMBL::Utils::URI
Caller : General
Status : Beta
=cut
sub parse_uri {
my ($url) = @_;
my $SCHEME = qr{ ([^:]+) :// }xms;
my $USER = qr{ ([^/:\@]+)? :? ([^/\@]+)? \@ }xms;
my $HOST = qr{ ([^/:]+)? :? ([^/]+)? }xms;
my $DB = qr{ / ([^/?]+)? /? ([^/?]+)? }xms;
my $PARAMS = qr{ \? (.+)}xms;
my $p;
if($url =~ qr{ $SCHEME ([^?]+) (?:$PARAMS)? }xms) {
my $scheme = $1;
$p = Bio::EnsEMBL::Utils::URI->new($scheme);
my ($locator, $params) = ($2, $3);
if($scheme eq 'file') {
$p->path($locator);
}
else {
if($locator =~ s/^$USER//) {
$p->user($1);
$p->pass($2);
}
if($locator =~ s/^$HOST//) {
$p->host($1);
$p->port($2);
}
if($p->is_db_scheme()) {
if($locator =~ $DB) {
$p->db_params()->{dbname} = $1;
$p->db_params()->{table} = $2;
}
}
else {
$p->path($locator);
}
}
if(defined $params) {
my @kv_pairs = split(/;|&/, $params);
foreach my $kv_string (@kv_pairs) {
my ($key, $value) = split(/=/, $kv_string);
$p->add_param($key, $value);
}
}
}
return $p;
}
####URI Object
=pod
=head2 new()
......@@ -73,14 +136,14 @@ sub new {
my ($class, $scheme) = @_;
$class = ref($class) || $class;
throw "No scheme given" unless $scheme;
my $self = bless ({
params => {},
param_keys => [],
db_params => {},
scheme => $scheme,
}, $class);
return $self;
}
......@@ -268,7 +331,7 @@ sub add_param {
=head2 get_params()
Arg[1] : String; key
Description : Returns the values which were found to be linked to the given
Description : Returns the values which were found to be linked to the given
key. Arrays are returned because one key can have many
values in a URI
Returntype : ArrayRef[Scalar]
......@@ -287,7 +350,7 @@ sub get_params {
Description : Storage of parameters used only for database URIs since
they require
Returntype : HashRef; Database name is keyed under C<dbname> and the
Returntype : HashRef; Database name is keyed under C<dbname> and the
table is keyed under C<table>
Exceptions : None
Status : Stable
......@@ -307,13 +370,13 @@ sub db_params {
which are deemed to be part of the C<db_params()> method
under C<-DBNAME> and C<-TABLE>. We also search for a number
of optional parameters which are lowercased equivalents
of the construction parameters available from a
L<Bio::EnsEMBL::DBSQL::DBAdaptor>,
L<Bio::EnsEMBL::DBSQL::DBConnection> as well as C<verbose>
of the construction parameters available from a
L<Bio::EnsEMBL::DBSQL::DBAdaptor>,
L<Bio::EnsEMBL::DBSQL::DBConnection> as well as C<verbose>
being supported.
We also convert the scheme type into the driver attribute
Returntype : Hash (not a reference). Output can be put into a C<DBConnection>
constructor.
Exceptions : None
......@@ -324,7 +387,7 @@ sub db_params {
sub generate_dbsql_params {
my ($self, $no_table) = @_;
my %db_params;
$db_params{-DRIVER} = $self->scheme();
$db_params{-HOST} = $self->host() if $self->host();
$db_params{-PORT} = $self->port() if $self->port();
......@@ -332,7 +395,7 @@ sub generate_dbsql_params {
$db_params{-PASS} = $self->pass() if $self->pass();
$db_params{-DBNAME} = $self->db_params()->{dbname} if $self->db_params()->{dbname};
$db_params{-TABLE} = $self->db_params()->{table} if ! $no_table && $self->db_params()->{table};
foreach my $boolean_param (qw/disconnect_when_inactive reconnect_when_connection_lost is_multispecies no_cache verbose/) {
if($self->param_exists_ci($boolean_param)) {
$db_params{q{-}.uc($boolean_param)} = 1;
......@@ -342,14 +405,14 @@ sub generate_dbsql_params {
if($self->param_exists_ci($value_param)) {
$db_params{q{-}.uc($value_param)} = $self->get_params($value_param)->[0];
}
}
}
return %db_params;
}
=head2 generate_uri()
Description : Generates a URI string from the paramaters in this object
Description : Generates a URI string from the paramaters in this object
Returntype : String
Exceptions : None
Status : Stable
......@@ -362,21 +425,21 @@ sub generate_uri {
my $user_credentials = q{};
my $host_credentials = q{};
my $location = q{};
if($self->user() || $self->pass()) {
$user_credentials = sprintf('%s%s@',
( $self->user() ? $self->user() : q{} ),
( $self->pass() ? q{:}.$self->pass() : q{} )
);
}
if($self->host() || $self->port()){
$host_credentials = sprintf('%s%s',
($self->host() ? $self->host() : q{}),
($self->port() ? q{:}.$self->port() : q{})
);
}
if($self->is_db_scheme()) {
if($self->db_params()->{dbname} || $self->db_params()->{table}) {
$location = sprintf('/%s%s',
......@@ -388,7 +451,7 @@ sub generate_uri {
else {
$location = $self->path() if $self->path();
}
my $param_string = q{};
if(@{$self->param_keys()}) {
$param_string = q{?};
......@@ -401,7 +464,7 @@ sub generate_uri {
}
$param_string .= join(q{;}, @params);
}
return join(q{}, $scheme, $user_credentials, $host_credentials, $location, $param_string);
}
......
=head1 LICENSE
Copyright (c) 1999-2011 The European Bioinformatics Institute and
Genome Research Limited. All rights reserved.
This software is distributed under a modified Apache license.
For license details, please see
http://www.ensembl.org/info/about/code_licence.html
=head1 CONTACT
Please email comments or questions to the public Ensembl
developers list at <dev@ensembl.org>.
Questions may also be sent to the Ensembl help desk at
<helpdesk@ensembl.org>.
=cut
=head1 NAME
Bio::EnsEMBL::Utils::URIParser
=head1 SYNOPSIS
#Using OO
use Bio::EnsEMBL::Utils::URIParser;
my $up = Bio::EnsEMBL::Utils::URIParser->new();
my $db_uri = $up->parse('mysql://user@host:3157/db');
my $http_uri = $up->parse('http://www.google.co.uk:80/search?q=t');
#Going functional
use Bio::EnsEMBL::Utils::URIParser qw/parse_uri/;
my $db_uri = parse_uri('mysql://user@host:3157/db');
my $http_uri = parse_uri('http://www.google.co.uk:80/search?q=t');
=head1 DESCRIPTION
This object is a generic URI parser which is primarily used in the
parsing of database URIs into a more managable data structure. It's aim
is this conversion and nothing else. The code produces URI objects
which contain more methods for introspection of the data points.
=head1 METHODS
=cut
package Bio::EnsEMBL::Utils::URIParser;
use strict;
use warnings;
use base qw/Exporter/;
our @EXPORT_OK;
@EXPORT_OK = qw/parse_uri/;
sub new {
my ($class) = @_;
return bless({}, ref($class) || $class);
}
=head2 parse_uri
Arg[1] : Scalar; URI to parse
Example : my $p = parse_uri('mysql://user:pass@host:415/db');
Description : Functional form of the C<parse()> call.
Returntype : Bio::EnsEMBL::Utils::URIParser::URI
Caller : General
Status : Stable
=cut
sub parse_uri {
my ($uri) = @_;
return __PACKAGE__->new()->parse($uri);
}
=head2 parse
Arg[1] : Scalar; URI to parse
Example : my $uri = $p->parse('mysql://user:pass@host:415/db');
Description : A URL parser which attempts to convert many different types
of URL into a common data structure.
Returntype : Bio::EnsEMBL::Utils::URIParser::URI
Caller : General
Status : Beta
=cut
sub parse {
my ($self, $url) = @_;
my $SCHEME = qr{ ([^:]+) :// }xms;
my $USER = qr{ ([^/:\@]+)? :? ([^/\@]+)? \@ }xms;
my $HOST = qr{ ([^/:]+)? :? ([^/]+)? }xms;
my $DB = qr{ / ([^/?]+)? /? ([^/?]+)? }xms;
my $PARAMS = qr{ \? (.+)}xms;
my $p;
if($url =~ qr{ $SCHEME ([^?]+) (?:$PARAMS)? }xms) {
my $scheme = $1;
$p = Bio::EnsEMBL::Utils::URIParser::URI->new($scheme);
my ($locator, $params) = ($2, $3);
if($scheme eq 'file') {
$p->path($locator);
}
else {
if($locator =~ s/^$USER//) {
$p->user($1);
$p->pass($2);
}
if($locator =~ s/^$HOST//) {
$p->host($1);
$p->port($2);
}
if($p->is_db_scheme()) {
if($locator =~ $DB) {
$p->db_params()->{dbname} = $1;
$p->db_params()->{table} = $2;
}
}
else {
$p->path($locator);
}
}
if(defined $params) {
my @kv_pairs = split(/;|&/, $params);
foreach my $kv_string (@kv_pairs) {
my ($key, $value) = split(/=/, $kv_string);
$p->add_param($key, $value);
}
}
}
return $p;
}
1;
\ No newline at end of file
use strict;
use warnings;
use Test::More;
use Test::Exception;
use Bio::EnsEMBL::Utils::URI qw/parse_uri/;
sub assert_parsing {
my ($msg, $url, $expected) = @_;
my $actual = parse_uri($url);
ok(! $actual->is_db_scheme(), 'Checking we do not have a DB scheme');
is_deeply($actual, $expected, $msg) or diag explain $actual;
return;
}
sub assert_db_parsing {
my ($msg, $url, $expected, $expected_params) = @_;
my $actual = parse_uri($url);
ok($actual->is_db_scheme(), 'Checking we have a DB scheme');
my $actual_dbsql_params = {$actual->generate_dbsql_params()};
if(! is_deeply($actual_dbsql_params, $expected, $msg)) {
diag explain $actual;
diag explain $actual_dbsql_params;
}
if($expected_params) {
is_deeply($actual->{params}, $expected_params, "Checking paramaters for $msg") or diag explain $actual->{params};
}
my $roundtrip_uri = $actual->generate_uri();
is($roundtrip_uri, $url, "Checking that '$msg' will roundtrip its URI");
return;
}
assert_db_parsing('Basic full URL','mysql://user:pass@host:51/dbname',{
-DRIVER => 'mysql',
-USER => 'user',
-PASS => 'pass',
-HOST => 'host',
-PORT => 51,
-DBNAME => 'dbname'
});
assert_db_parsing('Basic full URL with table','mysql://user:pass@host:51/dbname/table',{
-DRIVER => 'mysql',
-USER => 'user',
-PASS => 'pass',
-HOST => 'host',
-PORT => 51,
-DBNAME => 'dbname',
-TABLE => 'table'
});
assert_db_parsing('URL with no pass','mysql://user@host:51/dbname',{
-DRIVER => 'mysql',
-USER => 'user',
-HOST => 'host',
-PORT => 51,
-DBNAME => 'dbname'
});
assert_db_parsing('URL with no user but a password','mysql://:pass@host:51/dbname',{
-DRIVER => 'mysql',
-PASS => 'pass',
-HOST => 'host',
-PORT => 51,
-DBNAME => 'dbname'
});
assert_db_parsing('URL no user credentials with table','mysql://host:51/dbname/table',{
-DRIVER => 'mysql',
-HOST => 'host',
-PORT => 51,
-DBNAME => 'dbname',
-TABLE => 'table'
});
assert_db_parsing('URL no port','mysql://host/dbname',{
-DRIVER => 'mysql',
-HOST => 'host',
-DBNAME => 'dbname'
});
assert_db_parsing('URL no host','mysql:///dbname',{
-DRIVER => 'mysql',
-DBNAME => 'dbname'
});
assert_db_parsing('URL table only','mysql:////table',{
-DRIVER => 'mysql',
-TABLE => 'table',
});
assert_db_parsing('URL table with paramaters','mysql:////table?insert_scheme=INSERT_IGNORE',{
-DRIVER => 'mysql',
-TABLE => 'table',
}, {
insert_scheme => ['INSERT_IGNORE']
});
assert_db_parsing('URL params','mysql://host/db?param1=val1;param2',{
-DRIVER => 'mysql',
-HOST => 'host',
-DBNAME => 'db',
}, {
param1 => ['val1'],
param2 => [undef]
});
assert_parsing('http with params','http://host/path?param1=val1',{
scheme => 'http',
param_keys => [qw/param1/],
params => {param1 => ['val1']},
path => '/path',
host => 'host',
db_params => {}
});
assert_parsing('http real life params','http://www.google.co.uk:80/search?hl=en&source=hp&q=testing+%3D&hl=en',{
scheme => 'http',
param_keys => [qw/hl source q/],
params => {
hl => [qw/en en/],
source => ['hp'],
q => [qw/testing+%3D/]
},
path => '/search',
host => 'www.google.co.uk',
port => 80,
db_params => {}
});
assert_parsing('File path','file:///my/path',{
scheme => 'file',
params => {},
param_keys => [],
path => '/my/path',
db_params => {},
});
{
my $uri = Bio::EnsEMBL::Utils::URI->new('http');
$uri->host('www.google.co.uk');
$uri->port(80);
$uri->path('/search');
$uri->add_param('q', 'testing');
is($uri->generate_uri(), 'http://www.google.co.uk:80/search?q=testing', 'Checking URI generation for example usage');
}
{
my $u = Bio::EnsEMBL::Utils::URI->new('http');
dies_ok { $u->port(-1) } 'Checking we die if port is given an integer less than 1';
dies_ok { $u->port(80.265) } 'Checking we die if port is given a floating point number';
dies_ok { $u->port('my port') } 'Checking we die if port is given a string';
lives_ok { $u->port('80') } 'Checking we live if port is given a string which decodes to an integer';
lives_ok { $u->port(80) } 'Checking we live if port is given an integer';
}
done_testing();
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment