diff --git a/Changes b/Changes new file mode 100644 index 0000000..651fa7b --- /dev/null +++ b/Changes @@ -0,0 +1,5 @@ +Revision history for {{$dist->name}} + +{{$NEXT}} + + Pre-release version. Released as a proof of concept. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..424ec00 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +test: + dzil test + diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..37cc16f --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,73 @@ +# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.012. +use strict; +use warnings; + +use 5.014000; + +use ExtUtils::MakeMaker 6.48; + +my %WriteMakefileArgs = ( + "ABSTRACT" => "Access SmartyStreet API", + "AUTHOR" => "binary.com ", + "CONFIGURE_REQUIRES" => { + "ExtUtils::MakeMaker" => "6.64" + }, + "DISTNAME" => "WebService-Async-SmartyStreets", + "LICENSE" => "perl", + "MIN_PERL_VERSION" => "5.014000", + "NAME" => "WebService::Async::SmartyStreets", + "PREREQ_PM" => { + "Future::AsyncAwait" => "0.21", + "IO::Async::SSL" => 0, + "Net::Async::HTTP" => "0.44", + "indirect" => 0, + "mro" => 0, + "parent" => 0 + }, + "TEST_REQUIRES" => { + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Test::CheckDeps" => "0.010", + "Test::FailWarnings" => 0, + "Test::Fatal" => 0, + "Test::More" => "0.94", + "Test::Warn" => 0 + }, + "VERSION" => "0.001", + "test" => { + "TESTS" => "t/*.t" + } +); + + +my %FallbackPrereqs = ( + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "Future::AsyncAwait" => "0.21", + "IO::Async::SSL" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Net::Async::HTTP" => "0.44", + "Test::CheckDeps" => "0.010", + "Test::FailWarnings" => 0, + "Test::Fatal" => 0, + "Test::More" => "0.94", + "Test::Warn" => 0, + "indirect" => 0, + "mro" => 0, + "parent" => 0 +); + + +unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { + delete $WriteMakefileArgs{TEST_REQUIRES}; + delete $WriteMakefileArgs{BUILD_REQUIRES}; + $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; +} + +delete $WriteMakefileArgs{CONFIGURE_REQUIRES} + unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; + +WriteMakefile(%WriteMakefileArgs); diff --git a/README.md b/README.md index a09ba1c..c170323 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,235 @@ -# perl-WebService-Async-SmartyStreets -Address lookup and verification API +# NAME + +WebService::Async::SmartyStreets::Address - parses the response from SmartyStreets API + +# VERSION + +version 0.001 + +# SYNOPSIS + + use WebService::Async::SmartyStreets::Address; + # Mocking a simple response from SmartyStreets API and parses it with WebService::Async::SmartyStreets::Address + my $response = WebService::Async::SmartyStreets::Address->new( + metadata => { + latitude => 101.2131, + longitude => 180.1223, + geocode_precision => "Premise", + }, + analysis => { + verification_status => "Partial", + address_precision => "Premise", + }); + # Accessing the attributes + print ($response->status); + +# DESCRIPTION + +This module parses the response by SmartyStreets API into an object to access them. + +## Construction + + WebService::Async::SmartyStreets::Address->new( + input_id => 12345, + organization => 'Beenary', + metadata => { + latitude => 101.2131, + longitude => 180.1223, + geocode_precision => "Premise", + }, + analysis => { + verification_status => "Partial", + address_precision => "Premise", + }); + +## Sample SmartyStreets API response + + [ + { + "address1": "Hainichener Str. 64", + "address2": "09599 Freiberg", + "components": { + "administrative_area": "Sachsen", + "sub_administrative_area": "Früher: Direktionsbezirk Chemnitz", + "country_iso_3": "DEU", + "locality": "Freiberg", + "postal_code": "09599", + "postal_code_short": "09599", + "premise": "64", + "premise_number": "64", + "thoroughfare": "Hainichener Str.", + "thoroughfare_name": "Hainichenerstr.", + "thoroughfare_trailing_type": "Str." + }, + "metadata": { + "latitude": 50.92221, + "longitude": 13.32259, + "geocode_precision": "Premise", + "max_geocode_precision": "DeliveryPoint", + "address_format": "thoroughfare premise|postal_code locality" + }, + "analysis": { + "verification_status": "Verified", + "address_precision": "Premise", + "max_address_precision": "DeliveryPoint" + } + } + ] + +# Attributes + +All attributes that is parsed includes: + +- input_id +- organization +- latitude +- longitude +- geocode_precision +- max_geocode_precision +- address_format +- verification_status +- address_precision +- max_address_precision + +For more information about the attributes, click [here](https://smartystreets.com/docs/cloud/international-street-api) + +# Methods + +## status_at_least + +Checks if the returned response at least hits a certain level (in terms of score). + +## accuracy_at_least + +Checks if the returned response at least hits a certain accuracy (in terms of score). +Instantly returns 0 if the status is lower than 'partial'. + +# Attributes + +## input_id + +Returns the input_id parsed. + +## organization + +Returns the organization parsed. + +## latitude + +Returns the latitude parsed. + +## longitude + +Returns the latitude parsed. + +## geocode_precision + +Returns the geocode_precision parsed. + +## max_geocode_precision + +Returns the max_geocode_precision parsed. + +## address_format + +Returns the value of address_format parsed. + +## status + +Returns the value of verification_status parsed. + +The value returned should be either: + +- none +- ambiguous +- partial +- verified + +## address_precision + +Returns the value of address_precision parsed. + +## max_address_precision + +Returns the value of max_address_precision parsed. + +--- + +# NAME + +WebService::Async::SmartyStreets; + +# SYNOPSIS + + my $loop = IO::Async::Loop->new; + $loop->add( + my $ss = WebService::Async::SmartyStreets->new( + # International token + auth_id => '...', + token => '...', + api_choice => '...', + ) + ); + async sub { + my $addr = await $ss->verify( + # insert address here + ); + }->get; + +# DESCRIPTION + +This class calls the SmartyStreets API and parse the response to `WebService::Async::SmartyStreets::Address` + +# METHODS + +## verify + +Makes connection to SmartyStreets API and parses the response into `WebService::Async::SmartyStreets::Address`. + +Takes the following named parameters: +- args - address parameters in hash (See `WebService::Async::SmartyStreets/verify_international`) + +args consists of the following parameters: + +- country - country _[COMPULSORY]_ +- address1 - address line 1 +- address2 - address line 2 +- organization - name of organization (usually building names) +- locality - city +- administrative_area - state +- postal_code - post code +- geocode - true or false +- api\_choice - _[OPTIONAL]_ will overide the api_choice in config + +## get_decoded_data + +Parses the response give by SmartyStreets + +More information of the resposne can be seen in [SmartyStreets Documentation](https://smartystreets.com/docs/cloud/international-street-api) + +Returns an arrayref of hashrefs which the keys corresponds to `WebService::Async::SmartyStreets::Address` + +## configure + +configures the class with auth_id and token. + +## auth_id + +Returns auth_id. + +## token + +Returns token. + +## api_choice + +Returns api_choice. + +## ua + +Accessor for the `Net::Async::HTTP` instance which will be used for SmartyStreets API requests. + +# AUTHOR + +Binary.com + diff --git a/cpanfile b/cpanfile new file mode 100644 index 0000000..d9703de --- /dev/null +++ b/cpanfile @@ -0,0 +1,17 @@ +requires 'mro', 0; +requires 'indirect', 0; +requires 'parent', 0; +requires 'Net::Async::HTTP', '>= 0.44'; +requires 'IO::Async::SSL', 0; +requires 'Future::AsyncAwait', '>= 0.21'; + +on configure => sub { + requires 'ExtUtils::MakeMaker', '6.64'; +}; + +on test => sub { + requires 'Test::More'; + requires 'Test::Warn'; + requires 'Test::FailWarnings'; + requires 'Test::Fatal'; +}; \ No newline at end of file diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..1df65a7 --- /dev/null +++ b/dist.ini @@ -0,0 +1,67 @@ +name = WebService-Async-SmartyStreets +author = binary.com +license = Perl_5 +copyright_holder = binary.com +copyright_year = 2019 +main_module = lib/WebService/Async/SmartyStreets.pm + +[Git::GatherDir] +exclude_filename = Makefile.PL +include_dotfiles = 1 +[PruneCruft] +except = t/rc/\.perl*rc$ +[ManifestSkip] +[MetaYAML] +[License] +[Readme] +[MakeMaker] +eumm_version = 6.48 +prereq_fatal = 1 +[ExecDir] +[ShareDir] +dir = share +[Manifest] +[TestRelease] +[ConfirmRelease] +[UploadToCPAN] +[Prereqs::FromCPANfile] +[Prereqs / BuildRequires] +perl = 5.014000 +[CheckPrereqsIndexed] +[CheckExtraTests] +[VersionFromModule] +[PodVersion] +[PkgVersion] +[GitHub::Meta] +repo = binary-com/perl-WebService-Async-SmartyStreets +[InstallGuide] +[MetaJSON] +[InsertExample] +[PodSyntaxTests] +[MojibakeTests] +[Test::CheckDeps] +[Test::Compile] +[Test::Synopsis] +[Test::EOL] +[Test::Version] +[Test::Pod::LinkCheck] +[PodCoverageTests] +[Test::UnusedVars] +[Test::ReportPrereqs] +[SpellingCommonMistakesTests] +[CopyFilesFromBuild] +copy = Makefile.PL +;[Git::Check] +;allow_dirty = dist.ini +;changelog = Changes +[Git::Commit] +allow_dirty = dist.ini +allow_dirty = cpanfile +allow_dirty = Changes +allow_dirty = Makefile.PL +[Git::Tag] +tag_format = v%v +tag_message = Tag v%v for CPAN release +[ReversionOnRelease] +[NextRelease] +[InstallRelease] \ No newline at end of file diff --git a/lib/WebService/Async/SmartyStreets.pm b/lib/WebService/Async/SmartyStreets.pm new file mode 100644 index 0000000..3f60ec9 --- /dev/null +++ b/lib/WebService/Async/SmartyStreets.pm @@ -0,0 +1,241 @@ +package WebService::Async::SmartyStreets; +# ABSTRACT: Access SmartyStreet API + +use strict; +use warnings; + +our $VERSION = '0.001'; + +=head1 NAME + +WebService::Async::SmartyStreets - calls the SmartyStreets API and checks for the validity of the address + +=head1 SYNOPSIS + + my $ss = WebService::Async::SmartyStreets->new( + # Obtain these from your SmartyStreets account page. + # These will be used for US lookups + us_auth_id => '...', + us_token => '...', + # For non-US address lookups, you would also need an international token + international_auth_id => '...', + international_token => '...', + ); + IO::Async::Loop->new->add($ss); + + print $ss->verify( + city => 'Atlanta', + country => 'US', + geocode => 1 + )->get->status; + +=head1 DESCRIPTION + +This module provides basic support for the L. + +Note that this module uses L. + +=cut + +use parent qw(IO::Async::Notifier); + +use mro; +no indirect; + +use URI; +use URI::QueryParam; + +use Future::AsyncAwait; +use Net::Async::HTTP; +use JSON::MaybeUTF8 qw(:v1); +use Syntax::Keyword::Try; + +use WebService::Async::SmartyStreets::Address; + +use Log::Any qw($log); + +=head2 verify + +Makes connection to SmartyStreets API and parses the response into WebService::Async::SmartyStreets::Address. + + my $addr = $ss->verify(%address_to_check)->get; + +Takes the following named parameters: + +=over 4 + +=item * C - country (required) + +=item * C - address line 1 + +=item * C - address line 2 + +=item * C - name of organization (usually building names) + +=item * C - city + +=item * C - state + +=item * C - post code + +=item * C - true or false + +=back + +Returns a L which should resolve to a valid L instance. + +=cut + +async sub verify { + my ($self, %args) = @_; + + my $uri = $self->country_endpoint($args{country})->clone; + + $uri->query_param($_ => $args{$_}) for keys %args; + $uri->query_param( + 'auth-id' => ($self->auth_id($args{country}) // die 'need an auth ID'), + ); + $uri->query_param( + 'auth-token' => ($self->token($args{country}) // die 'need an auth token'), + ); + $uri->query_param( + 'input-id' => $self->next_id, + ); + $log->tracef('GET %s', '' . $uri); + + my $decoded = await get_decoded_data($self, $uri); + + $log->tracef('=> %s', $decoded); + + return map { WebService::Async::SmartyStreets::Address->new(%$_) } @$decoded; +} + +=head2 METHODS - Accessors + +=cut + +sub country_endpoint { + my ($self, $country) = @_; + return $self->us_endpoint if uc($country) eq 'US'; + return $self->international_endpoint; +} + +sub us_endpoint { + shift->{us_endpoint} //= URI->new('https://us-street.api.smartystreets.com/street-address'); +} + +sub international_endpoint { + shift->{international_endpoint} //= URI->new('https://international-street.api.smartystreets.com/verify'); +} + +sub auth_id { + my ($self, $country) = @_; + return $self->{us_auth_id} if uc($country) eq 'US'; + return $self->{international_auth_id}; +} + +sub token { + my ($self, $country) = @_; + return $self->{us_token} if uc($country) eq 'US'; + return $self->{international_token}; +} + + +=head1 METHODS - Internal + +=head2 get_decoded_data + +Calls the SmartyStreets API then decode and parses the response give by SmartyStreets + + my $decoded = await get_decoded_data($self, $uri) + +Takes the following parameters: + +=over 4 + +=item * C<$uri> - URI for endpoint + +=back + +More information on the response can be seen in L. + +Returns a L which resolves to an arrayref of L instances. + +=cut + +async sub get_decoded_data { + my $self = shift; + my $uri = shift; + + my $res; + try { + $res = await $self->ua->GET($uri); + } + catch { + die "Unable to retrieve response."; + }; + + my $response = decode_json_utf8($res->decoded_content); + + return $response->[0]; +} + +=head2 configure + +Configures the instance. + +Takes the following named parameters: + +=over 4 + +=item * C - auth_id obtained from SmartyStreet + +=item * C - token obtained from SmartyStreet + +=item * C - auth_id obtained from SmartyStreet + +=item * C - token obtained from SmartyStreet + +=back + +Note that you can provide US, international or both API tokens - if an API token +is not available for a L call, then it will return a failed L. + +=cut + +sub configure { + my ($self, %args) = @_; + for my $k (qw(international_auth_id international_token us_auth_id us_token)) { + $self->{$k} = delete $args{$k} if exists $args{$k}; + } + $self->next::method(%args); +} + +sub next_id { + ++(shift->{id} //= 'AA00000000'); +} + +=head2 ua + +Accessor for the L instance which will be used for SmartyStreets API requests. + +=cut + +sub ua { + my ($self) = @_; + $self->{ua} //= do { + $self->add_child( + my $ua = Net::Async::HTTP->new( + fail_on_error => 1, + decode_content => 1, + pipeline => 0, + max_connections_per_host => 4, + user_agent => + 'Mozilla/4.0 (WebService::Async::SmartyStreets; BINARY@cpan.org; https://metacpan.org/pod/WebService::Async::SmartyStreets)', + )); + $ua; + } +} + +1; + diff --git a/lib/WebService/Async/SmartyStreets/Address.pm b/lib/WebService/Async/SmartyStreets/Address.pm new file mode 100644 index 0000000..f7eeb79 --- /dev/null +++ b/lib/WebService/Async/SmartyStreets/Address.pm @@ -0,0 +1,179 @@ +package WebService::Async::SmartyStreets::Address; + +use strict; +use warnings; + +# VERSION + +=head1 NAME + +WebService::Async::SmartyStreets::Address - object that contains the response from SmartyStreets API + +=head1 SYNOPSIS + + # Mocking a simple response from SmartyStreets API and parses it with WebService::Async::SmartyStreets::Address + my $response = WebService::Async::SmartyStreets::Address->new( + metadata => { + latitude => 101.2131, + longitude => 180.1223, + geocode_precision => "Premise", + }, + analysis => { + verification_status => "Partial", + address_precision => "Premise", + }); + # Accessing the attributes + print ($response->status); + +=head1 DESCRIPTION + +Represents (parses) the return response from SmartyStreets API in an object + +=head2 Construction + + WebService::Async::SmartyStreets::Address->new( + input_id => 12345, + organization => 'Beenary', + metadata => { + latitude => 101.2131, + longitude => 180.1223, + geocode_precision => "Premise", + }, + analysis => { + verification_status => "Partial", + address_precision => "Premise", + }); + +=cut + +sub new { + my ($class, %args) = @_; + bless \%args, $class +} + +=head2 METHODS - Accessors + +=head2 input_id + +=cut + +sub input_id { shift->{input_id} } + +=head2 organization + +=cut + +sub organization { shift->{organization} } + +=head2 latitude + +=cut + +sub latitude { shift->{metadata}{latitude} } + +=head2 longitude + +=cut + +sub longitude { shift->{metadata}{longitude} } + +=head2 geocode_precision + +=cut + +sub geocode_precision { shift->{metadata}{geocode_precision} } + +=head2 max_geocode_precision + +=cut + +sub max_geocode_precision { shift->{metadata}{max_geocode_precision} } + +=head2 address_format + +=cut + +sub address_format { shift->{metadata}{address_format} } + +=head2 status + +=cut + +sub status { lc shift->{analysis}{verification_status} // ''} + +=head2 address_precision + +=cut + +sub address_precision { lc shift->{analysis}{address_precision} // ''} + +=head2 max_address_precision + +=cut + +sub max_address_precision { lc shift->{analysis}{max_address_precision} // ''} + +# Maps each verification response into a score +my %status_level = ( + none => 0, + partial => 1, + ambiguous => 2, + verified => 3 +); + +=head2 status_at_least + +Checks if the returned response at least hits a certain level (in terms of score) + +Example Usage: + + $obj->status_at_least("partial"); + +Takes L which consists of verification status ("verified", "partial", "ambiguous", "none") + +Returns 1 or 0 + +=cut + +sub status_at_least { + my ($self, $target) = @_; + my $target_level = $status_level{$target} // die 'unknown target status ' . $target; + my $actual_level = $status_level{$self->status} // die 'unknown status ' . $self->status; + return $actual_level >= $target_level; +} + +my %accuracy_level = ( + none => 0, + administrative_area => 1, + locality => 2, + thoroughfare => 3, + premise => 4, + delivery_point => 5, +); + +=head2 accuracy_at_least + +Similar with status at least, checks if the returned response is at least hits a certain accuracy (in terms of score) + +Example Usage: + + $obj->accuracy_at_least("premise"); + +Takes L which consists of address accuracy ("none", "administrative_area", "locality", "thoroughfare", "premise", "delivery_point") + +Returns 0 if the status is lower than 'partial' + +Returns 1 or 0 + +=cut + +sub accuracy_at_least { + my ($self, $target) = @_; + return 0 unless $self->status_at_least('partial'); + my $target_level = $accuracy_level{$target} // die 'unknown target accuracy ' . $target; + my $actual_level = $accuracy_level{$self->address_precision} // die 'unknown accuracy ' . $self->address_precision; + return $actual_level >= $target_level; +} + +1; + diff --git a/t/01_unit_test.t b/t/01_unit_test.t new file mode 100644 index 0000000..7657d0c --- /dev/null +++ b/t/01_unit_test.t @@ -0,0 +1,42 @@ +use strict; +use warnings; +use Test::More; +use WebService::Async::SmartyStreets::Address; + +subtest 'Parsing test' => sub { + my %dummy_data = ( + input_id => 12345, + organization => 'Beenary', + metadata => { + latitude => 101.2131, + longitude => 180.1223, + geocode_precision => "Premise", + }, + analysis => { + verification_status => "Partial", + address_precision => "Premise", + }); + + my $parsed_data = WebService::Async::SmartyStreets::Address->new(%dummy_data); + + # Checks if the data is correctly parsed + is ($parsed_data->input_id, 12345, "input_id is correctly parsed"); + is ($parsed_data->organization, 'Beenary', "Organization is correctly parsed"); + is ($parsed_data->latitude, 101.2131, "latitude is correctly parsed"); + is ($parsed_data->longitude, 180.1223, "longitude is correctly parsed"); + is ($parsed_data->geocode_precision, "Premise", "geocode_precision is correctly parsed"); + is ($parsed_data->status, "partial", "status is correctly parsed"); + # Checks if data can be retrieved if it is not passed in + is ($parsed_data->address_format, undef, "address_format is undef"); + + # Check if status check is correct + is ($parsed_data->status_at_least('none'), 1, "Verification score is correct"); + is ($parsed_data->status_at_least('verified'), '', "Verification score is correct"); + + # Check if address accuracy level check is correct + is ($parsed_data->accuracy_at_least('locality'), 1, "Accuracy checking is correct"); + is ($parsed_data->accuracy_at_least('delivery_point'), '', "Accuracy checking is correct"); + +}; + +done_testing; \ No newline at end of file diff --git a/t/02_smarty_test.t b/t/02_smarty_test.t new file mode 100644 index 0000000..a46f0b6 --- /dev/null +++ b/t/02_smarty_test.t @@ -0,0 +1,74 @@ +use strict; +use warnings; +use Future; +use Test::More; +use Test::MockModule; +use Test::Fatal; +use WebService::Async::SmartyStreets; +use Future::AsyncAwait; + +my $user_agent = Test::MockModule->new('Net::Async::HTTP'); +$user_agent->mock( + GET => sub { + return Future->done(); + }); + +my $mock_ss = Test::MockModule->new('WebService::Async::SmartyStreets'); +$mock_ss->mock( + international_auth_id => sub { + return 1; + }, + + international_token => sub { + return 1; + }, + + get_decoded_data => sub{ + my $data = [{ + input_id => 12345, + organization => 'Beenary', + metadata => { + latitude => 101.2131, + longitude => 180.1223, + geocode_precision => "Premise", + }, + analysis => { + verification_status => "Partial", + address_precision => "Premise", + }, + } + ]; + return Future->done($data); + }); + + +subtest "Call SmartyStreets" => sub { + my $ss = WebService::Async::SmartyStreets->new( + # this function is mocked, so the values are irrelevant + international_auth_id => '...', + international_token => '...', + ); + + my %data = ( + api_choice => 'international', + address1 => 'Jalan 1223 Jamse Bndo 012', + address2 => '03/03', + locality => 'Sukabumi', + administrative_area => 'JB', + postal_code => '43145', + country => 'Indonesia', + geocode => 'true', + ); + + my $addr = $ss->verify(%data)->get(); + + # Check if status check is correct + is ($addr->status_at_least('none'), 1, "Verification score is correct"); + is ($addr->status_at_least('verified'), '', "Verification score is correct"); + + # Check if address accuracy level check is correct + is ($addr->accuracy_at_least('locality'), 1, "Accuracy checking is correct"); + is ($addr->accuracy_at_least('delivery_point'), '', "Accuracy checking is correct"); +}; + +done_testing(); diff --git a/t/rc/.perlcriticrc b/t/rc/.perlcriticrc new file mode 100644 index 0000000..dba5c2e --- /dev/null +++ b/t/rc/.perlcriticrc @@ -0,0 +1,23 @@ +severity = 4 +criticism-fatal = 1 +color = 1 +include = TestingAndDebugging::RequireUseWarnings Subroutines::RequireArgUnpacking TestingAndDebugging::ProhibitNoStrict CodeLayout::RequireTidyCode ErrorHandling::RequireCheckingReturnValueOfEval TestingAndDebugging::RequireUseStrict Freenode::Each Freenode::IndirectObjectNotation Freenode::DollarAB Freenode::DeprecatedFeatures BuiltinFunctions::ProhibitReturnOr Dynamic::NoIndirect ProhibitSmartmatch Subroutines::ProhibitAmbiguousFunctionCalls Modules::ProhibitPOSIXimport +exclude = ValuesAndExpressions::ProhibitConstantPragma Subroutines::ProhibitExplicitReturnUndef Freenode::PackageMatchesFilename Freenode::DiscouragedModules + +[TestingAndDebugging::RequireUseWarnings] +equivalent_modules=MooseX::Singleton Mojo::Base + +[Subroutines::RequireArgUnpacking] +short_subroutine_statements=3 + +[TestingAndDebugging::ProhibitNoStrict] +allow=refs + +[CodeLayout::RequireTidyCode] +perltidyrc=/home/git/regentmarkets/cpan/rc/.perltidyrc + +[ErrorHandling::RequireCheckingReturnValueOfEval] +severity=4 + +[TestingAndDebugging::RequireUseStrict] +equivalent_modules=MooseX::Singleton Mojo::Base diff --git a/t/rc/.perltidyrc b/t/rc/.perltidyrc new file mode 100644 index 0000000..3a6cfa1 --- /dev/null +++ b/t/rc/.perltidyrc @@ -0,0 +1,63 @@ +#line length; keep it quite short so that lists of arguments to subs +#are wrapped +--maximum-line-length=150 + +#Cuddled else +-ce + +#Stack Closing Tokens +#http://perltidy.sourceforge.net/stylekey.html#stack_closing_tokens +#"The manual shows how all of these vertical tightness controls may be +#applied independently to each type of non-block opening and opening token." +--stack-closing-tokens + +## Similarly for opening. +--stack-opening-tokens + +#4 char wide tabs instead of spaces for indentation. +-i=4 + +#Horizontal Tightness +#http://perltidy.sourceforge.net/stylekey.html#define_horizontal_tightness +#parentheses if ((my $len_tab = length($tabstr)) > 0) +-pt=2 + +#square brackets $width = $col[$j + $k] - $col[$j]; +-sbt=2 + +#braces $width = $col[$j + $k] - $col[$j]; +-bt=2 + +#block braces map { $_ => -M $_ } grep { /\.deb$/ } +-bbt=0 + +#no space in front of semi-colons in a for loop +--nospace-for-semicolon + +#no outdenting of long quotes +#http://perltidy.sourceforge.net/stylekey.html#outdenting_long_quotes +--no-outdent-long-quotes + +--add-semicolons + +#always break a new line after a semi-colon +--want-break-after=";" + +#all hash key/values on a separate line +--comma-arrow-breakpoints=0 + +#No newlines before comments +-nbbc + +--no-outdent-long-lines + +#do not outdent labels +--no-outdent-labels + +--check-syntax + +--indent-spaced-block-comments + +#4 charachter if its breaks the line +--continuation-indentation=4 +