diff --git a/CHANGES b/CHANGES index bde3c81..1cc9aae 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,13 @@ Changelog for Beam-Wire -1.014 2015-11-02T21:22:53 +1.015 2016-02-23T14:33:00 + - remove Build.PL + - Add META.json to the built dist + - Avoid using YAML::XS 0.61 where possible + - fix minimum test prereqs + - update travis config to test core, hide modules + +1.014 2015-11-02T21:22:53Z - allow empty hashref in service args - add exception class for config errors - upgrade perl in travis config diff --git a/Makefile.PL b/Makefile.PL index 5d3ea9f..f7e1529 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -35,12 +35,12 @@ my %WriteMakefileArgs = ( "IO::Handle" => 0, "IPC::Open3" => 0, "Test::Deep" => 0, - "Test::Differences" => 0, + "Test::Differences" => "0.64", "Test::Exception" => 0, "Test::Lib" => 0, - "Test::More" => 0 + "Test::More" => "1.001005" }, - "VERSION" => "1.014", + "VERSION" => "1.015", "test" => { "TESTS" => "t/*.t t/container/*.t t/dependency/*.t t/deprecated/*.t t/service/*.t" } @@ -49,20 +49,22 @@ my %WriteMakefileArgs = ( my %FallbackPrereqs = ( "Beam::Emitter" => 0, + "CPAN::Meta::Requirements" => "2.120620", "Config::Any" => "0.23", "Data::DPath" => "0.51", "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, + "Module::Metadata" => 0, "Module::Runtime" => 0, "Moo" => 0, "Path::Tiny" => "0.055", "Test::Deep" => 0, - "Test::Differences" => 0, + "Test::Differences" => "0.64", "Test::Exception" => 0, "Test::Lib" => 0, - "Test::More" => 0, + "Test::More" => "1.001005", "Throwable" => 0, "Types::Standard" => 0, "YAML" => 0 diff --git a/README b/README index 7b9629a..541abf6 100644 --- a/README +++ b/README @@ -1,546 +1,563 @@ -NAME - Beam::Wire - Lightweight Dependency Injection Container - -VERSION - version 1.013 - -SYNOPSIS - # wire.yml - - dbh: - class: 'DBI' - method: connect - args: - - 'dbi:mysql:dbname' - - { - PrintError: 1 - } - - # myscript.pl - - use Beam::Wire; - - my $wire = Beam::Wire->new( file => 'wire.yml' ); - my $dbh = $wire->get( 'dbh' ); - $wire->set( 'dbh' => DBI->new( 'dbi:pgsql:dbname' ) ); - -DESCRIPTION - Beam::Wire is a dependency injection (DI) container. A DI (dependency - injection) container is a framework/mechanism where dependency creation - and instantiation is handled automatically (e.g. creates instances of - classes that implement a given dependency interface on request). DI does - not require a container, in-fact, DI without a container is possible and - simply infers that dependency creation isn't automatically handled for - you (i.e. you have to write code to instantiate the dependencies - manually). - - Dependency injection (DI) at it's core is about creating loosely coupled - code by separating construction logic from application logic. This is - done by pushing the creation of services (dependencies) to the entry - point(s) and writing the application logic so that dependencies are - provided for its components. The application logic doesn't know or care - how it is supplied with its dependencies; it just requires them and - therefore receives them. - -OVERVIEW - Beam::Wire loads a configuration file and stores the specified - configuration in the config which is used to resolve it's services. This - section will give you an overview of how to declare dependencies and - services, and shape your configuration file. - - WHAT IS A DEPENDENCY? - A dependency is a declaration of a component requirement. In layman's - terms, a dependency is a class attribute (or any value required for - class construction) which will likely be used to define services. - - WHAT IS A SERVICE? - A service is a resolvable interface which may be selected and - implemented on behalf of a dependent component, or instantiated and - returned per request. In layman's terms, a service is a class - configuration which can be used independently or as a dependent of other - services. - - HOW ARE SERVICES CONFIGURED? - # databases.yml - - production_db: - class: 'DBI' - method: connect - args: - - 'dbi:mysql:master' - - { PrintError: 0, RaiseError: 0 } - production_cache: - class: 'CHI' - args: - driver: 'DBI' - dbh: { $ref: 'production_db' } - development_db: - class: 'DBI' - method: connect - args: - - 'dbi:mysql:slave' - - { PrintError: 1, RaiseError: 1 } - development_cache: - class: 'CHI' - args: - driver: 'DBI' - dbh: { $ref: 'development_db' } - - Service Attributes - class - The class to instantiate. The class will be loaded and the "method" - (below) method called. - - method - The class method to call to construct the object. Defaults to "new". - - If multiple methods are needed to initialize an object, "method" can be - an arrayref of hashrefs, like so: - - my_service: - class: My::Service - method: - - method: new - args: - foo: bar - - method: set_baz - args: - - Fizz - - In this example, first we call "My::Service-"new( foo => "bar" );> to - get our object, then we call "$obj-"set_baz( "Fizz" );> as a further - initialization step. - - To chain methods together, add "return: chain": - - my_service: - class: My::Service - method: - - method: new - args: - foo: bar - - method: set_baz - return: chain - args: - - Fizz - - method: set_buzz - return: chain - args: - - Bork - - This example is equivalent to the following code: - - my $service = My::Service->new( foo => "bar" )->set_baz( "Fizz" ) - ->set_buzz( "Bork" ); - - args - The arguments to the "method" method. This can be either an array or a - hash, like so: - - # array - dbh: - class: DBI - method: connect - args: - - 'dbi:mysql:dbname' - - # hash - cache: - class: CHI - args: - driver: Memory +=head1 SYNOPSIS + + # wire.yml + + dbh: + class: 'DBI' + method: connect + args: + - 'dbi:mysql:dbname' + - { + PrintError: 1 + } + + # myscript.pl + + use Beam::Wire; + + my $wire = Beam::Wire->new( file => 'wire.yml' ); + my $dbh = $wire->get( 'dbh' ); + $wire->set( 'dbh' => DBI->new( 'dbi:pgsql:dbname' ) ); + +=head1 DESCRIPTION + +Beam::Wire is a dependency injection (DI) container. A DI (dependency injection) +container is a framework/mechanism where dependency creation and instantiation is +handled automatically (e.g. creates instances of classes that implement a given +dependency interface on request). DI does not require a container, in-fact, DI +without a container is possible and simply infers that dependency creation isn't +automatically handled for you (i.e. you have to write code to instantiate the +dependencies manually). + +Dependency injection (DI) at it's core is about creating loosely coupled code by +separating construction logic from application logic. This is done by pushing +the creation of services (dependencies) to the entry point(s) and writing the +application logic so that dependencies are provided for its components. The +application logic doesn't know or care how it is supplied with its dependencies; +it just requires them and therefore receives them. + +=head1 OVERVIEW + +Beam::Wire loads a configuration L and stores the specified configuration +in the L which is used to resolve it's services. This section +will give you an overview of how to declare dependencies and services, and shape +your configuration file. + +=head2 WHAT IS A DEPENDENCY? + +A dependency is a declaration of a component requirement. In layman's terms, a +dependency is a class attribute (or any value required for class construction) +which will likely be used to define services. + +=head2 WHAT IS A SERVICE? + +A service is a resolvable interface which may be selected and implemented on +behalf of a dependent component, or instantiated and returned per request. In +layman's terms, a service is a class configuration which can be used +independently or as a dependent of other services. + +=head2 HOW ARE SERVICES CONFIGURED? + + # databases.yml + + production_db: + class: 'DBI' + method: connect + args: + - 'dbi:mysql:master' + - { PrintError: 0, RaiseError: 0 } + production_cache: + class: 'CHI' + args: + driver: 'DBI' + dbh: { $ref: 'production_db' } + development_db: + class: 'DBI' + method: connect + args: + - 'dbi:mysql:slave' + - { PrintError: 1, RaiseError: 1 } + development_cache: + class: 'CHI' + args: + driver: 'DBI' + dbh: { $ref: 'development_db' } + +=head3 Service Attributes + +=head4 class + +The class to instantiate. The class will be loaded and the C (below) +method called. + +=head4 method + +The class method to call to construct the object. Defaults to C. + +If multiple methods are needed to initialize an object, C can be an +arrayref of hashrefs, like so: + + my_service: + class: My::Service + method: + - method: new + args: + foo: bar + - method: set_baz + args: + - Fizz + +In this example, first we call Cnew( foo => "bar" );> to get our +object, then we call C<$obj->set_baz( "Fizz" );> as a further initialization +step. + +To chain methods together, add C: + + my_service: + class: My::Service + method: + - method: new + args: + foo: bar + - method: set_baz + return: chain + args: + - Fizz + - method: set_buzz + return: chain + args: + - Bork + +This example is equivalent to the following code: + + my $service = My::Service->new( foo => "bar" )->set_baz( "Fizz" ) + ->set_buzz( "Bork" ); + +=head4 args + +The arguments to the C method. This can be either an array or a hash, +like so: + + # array + dbh: + class: DBI + method: connect + args: + - 'dbi:mysql:dbname' + + # hash + cache: + class: CHI + args: + driver: Memory + max_size: 16MB + +Using the array of arguments, you can give arrayrefs or hashrefs: + + # arrayref of arrayrefs + names: + class: 'Set::CrossProduct' + args: + - + - [ 'Foo', 'Barkowictz' ] + - [ 'Bar', 'Foosmith' ] + - [ 'Baz', 'Bazleton' ] + + # arrayrefs of hashrefs + cache: + class: CHI + args: + - driver: Memory max_size: 16MB - Using the array of arguments, you can give arrayrefs or hashrefs: - - # arrayref of arrayrefs - names: - class: 'Set::CrossProduct' - args: - - - - [ 'Foo', 'Barkowictz' ] - - [ 'Bar', 'Foosmith' ] - - [ 'Baz', 'Bazleton' ] - - # arrayrefs of hashrefs - cache: - class: CHI - args: - - driver: Memory - max_size: 16MB - - extends - Inherit and override attributes from another service. - - dbh: - class: DBI - method: connect - args: - - 'dbi:mysql:dbname' - dbh_dev: - extends: 'dbh' - args: - - 'dbi:mysql:devdb' - - Hash "args" will be merged seperately, like so: - - activemq: - class: My::ActiveMQ - args: - host: example.com - port: 61312 - user: root - password: 12345 - activemq_dev: - extends: 'activemq' - args: - host: dev.example.com - - "activemq_dev" will get the "port", "user", and "password" arguments - from the base service "activemq". - - with - Compose roles into the service object. - - app: - class: My::App - with: My::FeatureRole - - otherapp: - class: My::App - with: - - My::FeatureRole - - My::OtherFeatureRole - - This lets you break features out into roles, and compose those roles a - la carte on the fly. If you have 20 different optional features, it is - difficult to create every possible combination of them. So, "with" - allows you to pick the features you want. - - lifecycle - Control how your service is created. The default value, "singleton", - will cache the resulting service and return it for every call to - "get()". The other value, "factory", will create a new instance of the - service every time: - - today: - class: DateTime - method: today - lifecycle: factory - args: - time_zone: US/Chicago - report_yesterday: - class: My::Report - args: - date: { $ref: today, $method: add, $args: [ "days", "-1" ] } - report_today: - class: My::Report - args: - date: { $ref: today } - - "DateTime-"add> modifies the object and returns the newly-modified - object (to allow for method chaining.) Without "lifecycle: factory", the - "today" service would become yesterday, making it hard to know what - "report_today" would report on. - - An "eager" value will be created as soon as the container is created. If - you have an object that registers itself upon instantiation, you can - make sure your object is created as soon as possible by doing - "lifecycle: eager". - - on - Attach event listeners using Beam::Emitter. - - emitter: - class: My::Emitter - on: - before_my_event: - $ref: listener - $sub: on_before_my_event - my_event: - - $ref: listener - $sub: on_my_event - - $ref: other_listener - $sub: on_my_event - listener: - class: My::Listener - other_listener: - class: My::Listener - - Now, when the "emitter" fires off its events, they are dispatched to the - appropriate listeners. - - In order to work around a bug in YAML.pm, you can also specify event - listeners as an array of hashes: - - emitter: - class: My::Emitter - on: - - before_my_event: - $ref: listener - $sub: on_before_my_event - - my_event: - $ref: listener - $sub: on_my_event - - my_event: - $ref: other_listener - $sub: on_my_event - - Config Services - A config service allows you to read a config file and use it as a - service, giving all or part of it to other objects in your container. - - To create a config service, use the "config" key. The value is the path - to the file to read. By default, YAML, JSON, XML, and Perl files are - supported (via Config::Any). - - # db_config.yml - dsn: 'dbi:mysql:dbname' - user: 'mysql' - pass: '12345' - - # container.yml - db_config: - config: db_config.yml - - You can pass in the entire config to an object using $ref: - - # container.yml - db_config: - config: db_config.yml - dbobj: - class: My::DB - args: - conf: - $ref: db_config - - If you only need the config file once, you can create an anonymous - config object. - - # container.yml - dbobj: - class: My::DB - args: - conf: - $config: db_config.yml - - The config file can be used as all the arguments to the service: - - # container.yml - dbobj: - class: My::DB - args: +=head4 extends + +Inherit and override attributes from another service. + + dbh: + class: DBI + method: connect + args: + - 'dbi:mysql:dbname' + dbh_dev: + extends: 'dbh' + args: + - 'dbi:mysql:devdb' + +Hash C will be merged seperately, like so: + + activemq: + class: My::ActiveMQ + args: + host: example.com + port: 61312 + user: root + password: 12345 + activemq_dev: + extends: 'activemq' + args: + host: dev.example.com + +C will get the C, C, and C arguments +from the base service C. + +=head4 with + +Compose roles into the service object. + + app: + class: My::App + with: My::FeatureRole + + otherapp: + class: My::App + with: + - My::FeatureRole + - My::OtherFeatureRole + +This lets you break features out into roles, and compose those roles a la carte +on the fly. If you have 20 different optional features, it is difficult to create +every possible combination of them. So, C allows you to pick the features +you want. + +=head4 lifecycle + +Control how your service is created. The default value, C, will cache +the resulting service and return it for every call to C. The other +value, C, will create a new instance of the service every time: + + today: + class: DateTime + method: today + lifecycle: factory + args: + time_zone: US/Chicago + report_yesterday: + class: My::Report + args: + date: { $ref: today, $method: add, $args: [ "days", "-1" ] } + report_today: + class: My::Report + args: + date: { $ref: today } + +Cadd> modifies the object and returns the newly-modified object (to +allow for method chaining.) Without C, the C service +would become yesterday, making it hard to know what C would +report on. + +An C value will be created as soon as the container is created. If you +have an object that registers itself upon instantiation, you can make sure your +object is created as soon as possible by doing C. + +=head4 on + +Attach event listeners using L. + + emitter: + class: My::Emitter + on: + before_my_event: + $ref: listener + $sub: on_before_my_event + my_event: + - $ref: listener + $sub: on_my_event + - $ref: other_listener + $sub: on_my_event + listener: + class: My::Listener + other_listener: + class: My::Listener + +Now, when the C fires off its events, they are dispatched to the +appropriate listeners. + +In order to work around a bug in YAML.pm, you can also specify event listeners +as an array of hashes: + + emitter: + class: My::Emitter + on: + - before_my_event: + $ref: listener + $sub: on_before_my_event + - my_event: + $ref: listener + $sub: on_my_event + - my_event: + $ref: other_listener + $sub: on_my_event + +=head3 Config Services + +A config service allows you to read a config file and use it as a service, giving +all or part of it to other objects in your container. + +To create a config service, use the C key. The value is the path to the +file to read. By default, YAML, JSON, XML, and Perl files are supported (via +L). + + # db_config.yml + dsn: 'dbi:mysql:dbname' + user: 'mysql' + pass: '12345' + + # container.yml + db_config: + config: db_config.yml + +You can pass in the entire config to an object using C<$ref>: + + # container.yml + db_config: + config: db_config.yml + dbobj: + class: My::DB + args: + conf: + $ref: db_config + +If you only need the config file once, you can create an anonymous config +object. + + # container.yml + dbobj: + class: My::DB + args: + conf: $config: db_config.yml - In this example, the constructor will be called like: - - my $dbobj = My::DB->new( - dsn => 'dbi:mysql:dbname', - user => 'mysql', - pass => '12345', - ); - - You can reference individual items in a configuration hash using $path - references: - - # container.yml - db_config: - config: db_config.yml - dbh: - class: DBI - method: connect - args: - - $ref: db_config - $path: /dsn - - $ref: db_config - $path: /user - - $ref: db_config - $path: /pass - - NOTE: You cannot use $path and anonymous config objects. - - Inner Containers - Beam::Wire objects can hold other Beam::Wire objects! - - inner: - class: Beam::Wire - args: - config: - dbh: - class: DBI - method: connect - args: - - 'dbi:mysql:dbname' - cache: - class: CHI - args: - driver: Memory - max_size: 16MB - - Inner containers' contents can be reached from outer containers by - separating the names with a slash character: - - my $dbh = $wire->get( 'inner/dbh' ); - - Inner Files - inner: - class: Beam::Wire - args: - file: inner.yml - - Inner containers can be created by reading files just like the main - container. If the "file" attribute is relative, the parent's "dir" - attribute will be added: - - # share/parent.yml - inner: - class: Beam::Wire - args: - file: inner.yml - - # share/inner.yml - dbh: - class: DBI - method: connect - args: - - 'dbi:sqlite:data.db' - - # myscript.pl - use Beam::Wire; - - my $container = Beam::Wire->new( - file => 'share/parent.yml', - ); - - my $dbh = $container->get( 'inner/dbh' ); - - If more control is needed, you can set the dir on the parent container. - If even more control is needed, you can make a subclass of Beam::Wire. - - Service/Configuration References - chi: - class: CHI - args: - driver: 'DBI' - dbh: { $ref: 'dbh' } - dbh: - class: DBI - method: connect - args: - - { $ref: dsn } - - { $ref: usr } - - { $ref: pwd } - dsn: - value: "dbi:SQLite:memory:" - usr: - value: "admin" - pwd: - value: "s3cret" - - The reuse of service and configuration containers as arguments for other - services is encouraged so we have provided a means of referencing those - objects within your configuration. A reference is an arugment (a service - argument) in the form of a hashref with a $ref key whose value is the - name of another service. Optionally, this hashref may contain a $path - key whose value is a Data::DPath search string which should return the - found data structure from within the referenced service. - - It is also possible to use raw-values as services, this is done by - configuring a service using a single key/value pair with a "value" key - whose value contains the raw-value you wish to reuse. - -ATTRIBUTES - file - The file attribute contains the file path of the file where Beam::Wire - container services are configured (typically a YAML file). The file's - contents should form a single hashref. The keys will become the service - names. - - dir - The dir attribute contains the directory path to use when searching for - inner container files. Defaults to the directory which contains the file - specified by the file. - - config - The config attribute contains a hashref of service configurations. This - data is loaded by Config::Any using the file specified by the file. - - services - A hashref of services. If you have any services already built, add them - here. - - meta_prefix - The character that begins a meta-property inside of a service's "args". - This includes $ref, $path, $method, and etc... - - The default value is '$'. The empty string is allowed. - -METHODS - get( name, [ overrides ] ) - The get method resolves and returns the service named "name". - - "overrides" may be a list of name-value pairs. If specified, get() will - create an anonymous service that extends the "name" service with the - given config overrides: - - # test.pl - use Beam::Wire; - my $wire = Beam::Wire->new( - config => { - foo => { - args => { - text => 'Hello, World!', - }, +The config file can be used as all the arguments to the service: + + # container.yml + dbobj: + class: My::DB + args: + $config: db_config.yml + +In this example, the constructor will be called like: + + my $dbobj = My::DB->new( + dsn => 'dbi:mysql:dbname', + user => 'mysql', + pass => '12345', + ); + +You can reference individual items in a configuration hash using C<$path> +references: + + # container.yml + db_config: + config: db_config.yml + dbh: + class: DBI + method: connect + args: + - $ref: db_config + $path: /dsn + - $ref: db_config + $path: /user + - $ref: db_config + $path: /pass + +B You cannot use C<$path> and anonymous config objects. + + +=head3 Inner Containers + +Beam::Wire objects can hold other Beam::Wire objects! + + inner: + class: Beam::Wire + args: + config: + dbh: + class: DBI + method: connect + args: + - 'dbi:mysql:dbname' + cache: + class: CHI + args: + driver: Memory + max_size: 16MB + +Inner containers' contents can be reached from outer containers by separating +the names with a slash character: + + my $dbh = $wire->get( 'inner/dbh' ); + +=head3 Inner Files + + inner: + class: Beam::Wire + args: + file: inner.yml + +Inner containers can be created by reading files just like the main container. +If the C attribute is relative, the parent's C attribute will be +added: + + # share/parent.yml + inner: + class: Beam::Wire + args: + file: inner.yml + + # share/inner.yml + dbh: + class: DBI + method: connect + args: + - 'dbi:sqlite:data.db' + + # myscript.pl + use Beam::Wire; + + my $container = Beam::Wire->new( + file => 'share/parent.yml', + ); + + my $dbh = $container->get( 'inner/dbh' ); + +If more control is needed, you can set the L on the parent +container. If even more control is needed, you can make a subclass of Beam::Wire. + +=head3 Service/Configuration References + + chi: + class: CHI + args: + driver: 'DBI' + dbh: { $ref: 'dbh' } + dbh: + class: DBI + method: connect + args: + - { $ref: dsn } + - { $ref: usr } + - { $ref: pwd } + dsn: + value: "dbi:SQLite:memory:" + usr: + value: "admin" + pwd: + value: "s3cret" + +The reuse of service and configuration containers as arguments for other +services is encouraged so we have provided a means of referencing those objects +within your configuration. A reference is an arugment (a service argument) in +the form of a hashref with a C<$ref> key whose value is the name of another +service. Optionally, this hashref may contain a C<$path> key whose value is a +L search string which should return the found data +structure from within the referenced service. + +It is also possible to use raw-values as services, this is done by configuring a +service using a single key/value pair with a C key whose value contains +the raw-value you wish to reuse. + +=attr file + +The file attribute contains the file path of the file where Beam::Wire container +services are configured (typically a YAML file). The file's contents should form +a single hashref. The keys will become the service names. + +=attr dir + +The dir attribute contains the directory path to use when searching for inner +container files. Defaults to the directory which contains the file specified by +the L. + +=attr config + +The config attribute contains a hashref of service configurations. This data is +loaded by L using the file specified by the +L. + +=attr services + +A hashref of services. If you have any services already built, add them here. + +=attr meta_prefix + +The character that begins a meta-property inside of a service's C. This +includes C<$ref>, C<$path>, C<$method>, and etc... + +The default value is '$'. The empty string is allowed. + +=method get( name, [ overrides ] ) + +The get method resolves and returns the service named C. + +C may be a list of name-value pairs. If specified, get() +will create an anonymous service that extends the C service +with the given config overrides: + + # test.pl + use Beam::Wire; + my $wire = Beam::Wire->new( + config => { + foo => { + args => { + text => 'Hello, World!', }, }, - ); - my $foo = $wire->get( 'foo', args => { text => 'Hello, Chicago!' } ); - print $foo; # prints "Hello, Chicago!" + }, + ); + my $foo = $wire->get( 'foo', args => { text => 'Hello, Chicago!' } ); + print $foo; # prints "Hello, Chicago!" + +This allows you to create factories out of any service, overriding service +configuration at run-time. + +=method set + +The set method configures and stores the specified service. + +=method get_config + +Get the config with the given name, searching inner containers if required + +=method new + +Create a new container. + +=head1 EXCEPTIONS + +If there is an error internal to Beam::Wire, an exception will be thrown. If there is an +error with creating a service or calling a method, the exception thrown will be passed- +through unaltered. + +=head2 Beam::Wire::Exception - This allows you to create factories out of any service, overriding - service configuration at run-time. +The base exception class - set - The set method configures and stores the specified service. +=head2 Beam::Wire::Exception::Constructor - get_config - Get the config with the given name, searching inner containers if - required +An exception creating a Beam::Wire object - new - Create a new container. +=head2 Beam::Wire::Exception::Config -EXCEPTIONS - If there is an error internal to Beam::Wire, an exception will be - thrown. If there is an error with creating a service or calling a - method, the exception thrown will be passed- through unaltered. +An exception loading the configuration file. - Beam::Wire::Exception - The base exception class +=head2 Beam::Wire::Exception::Service - Beam::Wire::Exception::Constructor - An exception creating a Beam::Wire object +An exception with service information inside - Beam::Wire::Exception::Service - An exception with service information inside +=head2 Beam::Wire::Exception::NotFound - Beam::Wire::Exception::NotFound - The requested service or configuration was not found. +The requested service or configuration was not found. - Beam::Wire::Exception::InvalidConfig - The configuration is invalid: +=head2 Beam::Wire::Exception::InvalidConfig - * Both "value" and "class" or "extends" are defined. These are - mutually-exclusive. +The configuration is invalid: -AUTHORS - * Doug Bell +=over 4 - * Al Newkirk +=item * -COPYRIGHT AND LICENSE - This software is copyright (c) 2015 by Doug Bell. +Both "value" and "class" or "extends" are defined. These are mutually-exclusive. - This is free software; you can redistribute it and/or modify it under - the same terms as the Perl 5 programming language system itself. +=back diff --git a/README.mkdn b/README.mkdn index cafcd4d..8821a20 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,7 +4,7 @@ Beam::Wire - Lightweight Dependency Injection Container # VERSION -version 1.014 +version 1.015 # STATUS @@ -579,7 +579,7 @@ The configuration is invalid: - Bruce Armstrong - Bruce Armstrong -- Kent Fredric <kentnl@cpan.org> +- Kent Fredric # COPYRIGHT AND LICENSE diff --git a/cpanfile b/cpanfile index 833fe76..6d69efc 100644 --- a/cpanfile +++ b/cpanfile @@ -15,10 +15,10 @@ on 'test' => sub { requires "IO::Handle" => "0"; requires "IPC::Open3" => "0"; requires "Test::Deep" => "0"; - requires "Test::Differences" => "0"; + requires "Test::Differences" => "0.64"; requires "Test::Exception" => "0"; requires "Test::Lib" => "0"; - requires "Test::More" => "0"; + requires "Test::More" => "1.001005"; }; on 'test' => sub {