From 806f14ea2c0edd8c1db92f734c70c054dc6fe856 Mon Sep 17 00:00:00 2001 From: Diab Jerius Date: Fri, 21 Oct 2016 17:12:20 -0400 Subject: [PATCH] initial import --- Changes | 6 ++ MANIFEST.SKIP | 11 ++ Makefile.PL | 28 +++++ README | 146 +++++++++++++++++++++++++ README.md | 159 ++++++++++++++++++++++++++++ cpanfile | 32 ++++++ lib/PDLx/DetachedObject.pm | 212 +++++++++++++++++++++++++++++++++++++ t/00-load.t | 9 ++ t/classes.t | 120 +++++++++++++++++++++ xt/cpan-changes.t | 4 + xt/cpan-meta-json.t | 4 + xt/cpan-meta.t | 4 + xt/nobreakpoints.t | 7 ++ xt/perlcritic.t | 11 ++ xt/pod.t | 6 ++ xt/test-fixme.t | 2 + 16 files changed, 761 insertions(+) create mode 100644 Changes create mode 100644 MANIFEST.SKIP create mode 100644 Makefile.PL create mode 100644 README create mode 100644 README.md create mode 100644 cpanfile create mode 100644 lib/PDLx/DetachedObject.pm create mode 100644 t/00-load.t create mode 100644 t/classes.t create mode 100644 xt/cpan-changes.t create mode 100644 xt/cpan-meta-json.t create mode 100644 xt/cpan-meta.t create mode 100644 xt/nobreakpoints.t create mode 100644 xt/perlcritic.t create mode 100644 xt/pod.t create mode 100644 xt/test-fixme.t diff --git a/Changes b/Changes new file mode 100644 index 0000000..c3b4d5f --- /dev/null +++ b/Changes @@ -0,0 +1,6 @@ +Revision history for PDLx-DetachedObject + +0.01 2016-10-21T17:04:06-0400 + + * Initial release. + diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..00b08ba --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,11 @@ +^.hg +.old$ +.bak$ +Makefile$ +blib/ +~$ +pm_to_blib +blibdirs +^[^/]+\.gz$ +^MYMETA[.].*$ +_build/ diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..d4d8214 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,28 @@ +#! perl + +use strict; +use warnings; +use inc::Module::Install; + +name 'PDLx-DetachedObject'; +license 'gpl3'; +auto_license( holder => 'Smithsonian Astrophysical Observatory' ); +all_from 'lib/PDLx/DetachedObject.pm'; + +readme_from; +readme_from '', { format => 'md' };; + +resources ( + license => 'http://www.gnu.org/licenses/gpl-3.0.html', + repository => 'https://github.com/djerius/PDLx-DetachedObject', + bugtracker => 'https://rt.cpan.org/Public/Dist/Display.html?Name=PDLx-DetachedObject', +); + + +author_tests( 'xt' ); + +tests_recursive; + +cpanfile; + +WriteAll; diff --git a/README b/README new file mode 100644 index 0000000..15d9fa9 --- /dev/null +++ b/README @@ -0,0 +1,146 @@ +NAME + PDLx::DetachedObject - parent class for subclassing PDL from class + frameworks + +SYNTAX + Moo + package MyPDL; + + use Moo; + use PDL::Lite; + + extends 'PDLx::DetachedObject'; + + has PDL => ( is => 'rw' ); + + Class::Tiny + package MyPDL; + + use Class::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + + Object::Tiny + package MyPDL; + + use Object::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + + Class::Accessor + package MyPDL; + + use parent 'Class::Accessor', 'PDLx::DetachedObject'; + __PACKAGE__->follow_best_practice; + __PACKAGE__->mk_accessors( 'PDL' ); + + or with Antlers: + + package MyPDL; + use Class::Accessor "antlers"; + use parent 'PDLx::DetachedObject'; + + has PDL => ( is => 'ro' ); + +DESCRIPTION + PDL has a non-standard way of handling subclasses. Because a PDL object + is a blessed scalar, outside of using inside-out classes as the + subclass, there is no easy means of adding extra attributes to the + object. + + To work around this, PDL will treat any hash blessed into a subclass of + PDL which has an entry with key "PDL" whose value is a real PDL object + as a PDL object. + + So far, here's a Moo version of the class + + package MyPDL; + + use Moo; + + extends 'PDL'; + + # don't pass any constructor arguments to PDL->new; it confuses it + sub FOREIGNBUILDARGS {} + + has PDL => ( is => 'rw' ); + has required_attr => ( is => 'ro', required =>1 ); + + When PDL needs to instantiate an object from the subclass, it doesn't + call the subclass's constructor, rather it calls the initialize class + method, which is expected to return a hash, blessed into the subclass, + containing the "PDL" key as well as any other attributes. + + sub initialize { + my $class = shift; + bless { PDL => PDL->null }, $class; + } + + The initialize method is invoked in a variety of places. For instance, + it's called in PDL::new, which due to Moo's inheritance scheme will be + called by MyPDL's constructor: + + $mypdl = MyPDL->new( required_attr => 2 ); + + It's also called when PDL needs to create an object to recieve the + results of a PDL operation on a MyPDL object: + + $newpdl = $mypdl + 1; + + There's one wrinkle, however. PDL *must* create an object without any + extra attributes (it cannot know which values to give them) so + initialize() is called with a *single* argument, the class name. This + means that $newpdl will be an *incomplete* MyPDL object, i.e. + "required_attr" is uninitiailzed. This can *really* confuse polymorphic + code which operates differently when handed a PDL or MyPDL object. + + One way out of this dilemma is to have PDL create a *normal* piddle + instead of a MyPDL object. MyPDL has explicitly indicated it wants to be + treated as a normal piddle in PDL operations (by subclassing from PDL) + so this doesn't break that contract. + + $newpdl = $mypdl + 1; + + would result in $newpdl being a normal PDL object, not a MyPDL object. + + Subclassing from PDLx::DetachedObject effects this behavior. + PDLx::DetachedObject provides a wrapper constructor and an initialize + class method. The constructor ensures returns a properly subclassed hash + with the "PDL" key, keeping PDL happy. When PDL calls the initialize + function it gets a normal PDL. + + Using with Class Frameworks + The "SYNOPSIS" shows how to use PDLx::DetachedObject with various class + frameworks. The key differentiation between frameworks is whether or not + they will call a superclass's constructor. Moo always calls it, + Class::Tiny calls it only if it inherits from Class::Tiny::Object, and + Object::Tiny and Class::Accessor never will call the superclass' + constructor. + +BUGS AND LIMITATIONS + Please report any bugs or feature requests to + "bug-pdlx-mask@rt.cpan.org", or through the web interface at + . + +VERSION + Version 0.01 + +LICENSE AND COPYRIGHT + Copyright (c) 2016 The Smithsonian Astrophysical Observatory + + PDLx::DetachedObject is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see . + +AUTHOR + Diab Jerius + diff --git a/README.md b/README.md new file mode 100644 index 0000000..eecee0c --- /dev/null +++ b/README.md @@ -0,0 +1,159 @@ +# NAME + +PDLx::DetachedObject - parent class for subclassing PDL from class frameworks + +# SYNTAX + +### Moo + + package MyPDL; + + use Moo; + use PDL::Lite; + + extends 'PDLx::DetachedObject'; + + has PDL => ( is => 'rw' ); + +### Class::Tiny + + package MyPDL; + + use Class::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + +### Object::Tiny + + package MyPDL; + + use Object::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + +### Class::Accessor + + package MyPDL; + + use parent 'Class::Accessor', 'PDLx::DetachedObject'; + __PACKAGE__->follow_best_practice; + __PACKAGE__->mk_accessors( 'PDL' ); + +or with Antlers: + + package MyPDL; + use Class::Accessor "antlers"; + use parent 'PDLx::DetachedObject'; + + has PDL => ( is => 'ro' ); + +# DESCRIPTION + +[PDL](https://metacpan.org/pod/PDL) has a [non-standard way of handling +subclasses](https://metacpan.org/pod/PDL::Objects). Because a **PDL** object is a blessed scalar, +outside of using inside-out classes as the subclass, there is no easy +means of adding extra attributes to the object. + +To work around this, **PDL** will treat any hash blessed into a +subclass of PDL which has an entry with key `PDL` whose value is a +real **PDL** object as a **PDL** object. + +So far, here's a [**Moo**](https://metacpan.org/pod/Moo) version of the class + + package MyPDL; + + use Moo; + + extends 'PDL'; + + # don't pass any constructor arguments to PDL->new; it confuses it + sub FOREIGNBUILDARGS {} + + has PDL => ( is => 'rw' ); + has required_attr => ( is => 'ro', required =>1 ); + +When **PDL** needs to instantiate an object from the subclass, +it doesn't call the subclass's constructor, rather it calls the +**initialize** class method, which is expected to return a hash, +blessed into the subclass, containing the `PDL` key as well as any +other attributes. + + sub initialize { + my $class = shift; + bless { PDL => PDL->null }, $class; + } + +The **initialize** method is invoked in a variety of places. For +instance, it's called in **PDL::new**, which due to **Moo**'s +inheritance scheme will be called by **MyPDL**'s constructor: + + $mypdl = MyPDL->new( required_attr => 2 ); + +It's also called when **PDL** needs to create an object to recieve +the results of a **PDL** operation on a **MyPDL** object: + + $newpdl = $mypdl + 1; + +There's one wrinkle, however. **PDL** _must_ create an object without +any extra attributes (it cannot know which values to give them) so +**initialize()** is called with a _single_ argument, the class name. +This means that `$newpdl` will be an _incomplete_ **MyPDL** object, +i.e. `required_attr` is uninitiailzed. This can _really_ confuse +polymorphic code which operates differently when handed a **PDL** or +**MyPDL** object. + +One way out of this dilemma is to have **PDL** create a _normal_ piddle +instead of a **MyPDL** object. **MyPDL** has explicitly indicated it wants to be +treated as a normal piddle in **PDL** operations (by subclassing from **PDL**) so +this doesn't break that contract. + + $newpdl = $mypdl + 1; + +would result in `$newpdl` being a normal **PDL** object, not a **MyPDL** +object. + +Subclassing from **PDLx::DetachedObject** effects this +behavior. **PDLx::DetachedObject** provides a wrapper constructor and +an **initialize** class method. The constructor ensures returns a +properly subclassed hash with the `PDL` key, keeping **PDL** happy. +When **PDL** calls the **initialize** function it gets a normal **PDL**. + +## Using with Class Frameworks + +The ["SYNOPSIS"](#synopsis) shows how to use **PDLx::DetachedObject** with various +class frameworks. The key differentiation between frameworks is +whether or not they will call a superclass's constructor. **Moo** +always calls it, **Class::Tiny** calls it only if it inherits from +**Class::Tiny::Object**, and **Object::Tiny** and **Class::Accessor** +never will call the superclass' constructor. + +# BUGS AND LIMITATIONS + +Please report any bugs or feature requests to +`bug-pdlx-mask@rt.cpan.org`, or through the web interface at +[http://rt.cpan.org/Public/Dist/Display.html?Name=PDLx-DetachedObject](http://rt.cpan.org/Public/Dist/Display.html?Name=PDLx-DetachedObject). + +# VERSION + +Version 0.01 + +# LICENSE AND COPYRIGHT + +Copyright (c) 2016 The Smithsonian Astrophysical Observatory + +PDLx::DetachedObject is free software: you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +# AUTHOR + +Diab Jerius diff --git a/cpanfile b/cpanfile new file mode 100644 index 0000000..89db43c --- /dev/null +++ b/cpanfile @@ -0,0 +1,32 @@ +#! perl + +requires 'PDL'; + +on test => sub { + + requires 'Test::More'; + requires 'Test::Deep'; + requires 'Moo'; + requires 'Class::Tiny'; + requires 'Object::Tiny'; + requires 'Class::Accessor'; + +}; + +on develop => sub { + + requires 'Module::Install'; + requires 'Module::Install::AuthorRequires'; + requires 'Module::Install::AuthorTests'; + requires 'Module::Install::AutoLicense'; + requires 'Module::Install::CPANfile'; + requires 'Module::Install::ReadmeFromPod'; + + requires 'Test::Fixme'; + requires 'Test::NoBreakpoints'; + requires 'Test::Pod'; + requires 'Test::Perl::Critic'; + requires 'Test::CPAN::Changes'; + requires 'Test::CPAN::Meta'; + requires 'Test::CPAN::Meta::JSON'; +}; diff --git a/lib/PDLx/DetachedObject.pm b/lib/PDLx/DetachedObject.pm new file mode 100644 index 0000000..7721ed7 --- /dev/null +++ b/lib/PDLx/DetachedObject.pm @@ -0,0 +1,212 @@ +# --8<--8<--8<--8<-- +# +# Copyright (C) 2016 Smithsonian Astrophysical Observatory +# +# This file is part of PDLx-DetachedObject +# +# PDLx-DetachedObject is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# -->8-->8-->8-->8-- + +package PDLx::DetachedObject; + +use strict; +use warnings; + +our $VERSION = 0.01; + +use parent 'PDL'; + +use PDL::Core ''; + +sub initialize { return PDL->null } + +sub new { + my $class = shift; + bless { PDL => PDL->null }, $class; +} + +1; + +__END__ + + +=pod + +=head1 NAME + +PDLx::DetachedObject - parent class for subclassing PDL from class frameworks + +=head1 SYNTAX + +=head3 Moo + + package MyPDL; + + use Moo; + use PDL::Lite; + + extends 'PDLx::DetachedObject'; + + has PDL => ( is => 'rw' ); + + +=head3 Class::Tiny + + package MyPDL; + + use Class::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + +=head3 Object::Tiny + + package MyPDL; + + use Object::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + +=head3 Class::Accessor + + package MyPDL; + + use parent 'Class::Accessor', 'PDLx::DetachedObject'; + __PACKAGE__->follow_best_practice; + __PACKAGE__->mk_accessors( 'PDL' ); + +or with Antlers: + + package MyPDL; + use Class::Accessor "antlers"; + use parent 'PDLx::DetachedObject'; + + has PDL => ( is => 'ro' ); + + + +=head1 DESCRIPTION + +L has a L. Because a B object is a blessed scalar, +outside of using inside-out classes as the subclass, there is no easy +means of adding extra attributes to the object. + +To work around this, B will treat any hash blessed into a +subclass of PDL which has an entry with key C whose value is a +real B object as a B object. + +So far, here's a L<< B >> version of the class + + package MyPDL; + + use Moo; + + extends 'PDL'; + + # don't pass any constructor arguments to PDL->new; it confuses it + sub FOREIGNBUILDARGS {} + + has PDL => ( is => 'rw' ); + has required_attr => ( is => 'ro', required =>1 ); + +When B needs to instantiate an object from the subclass, +it doesn't call the subclass's constructor, rather it calls the +B class method, which is expected to return a hash, +blessed into the subclass, containing the C key as well as any +other attributes. + + sub initialize { + my $class = shift; + bless { PDL => PDL->null }, $class; + } + +The B method is invoked in a variety of places. For +instance, it's called in B, which due to B's +inheritance scheme will be called by B's constructor: + + $mypdl = MyPDL->new( required_attr => 2 ); + +It's also called when B needs to create an object to recieve +the results of a B operation on a B object: + + $newpdl = $mypdl + 1; + +There's one wrinkle, however. B I create an object without +any extra attributes (it cannot know which values to give them) so +B is called with a I argument, the class name. +This means that C<$newpdl> will be an I B object, +i.e. C is uninitiailzed. This can I confuse +polymorphic code which operates differently when handed a B or +B object. + +One way out of this dilemma is to have B create a I piddle +instead of a B object. B has explicitly indicated it wants to be +treated as a normal piddle in B operations (by subclassing from B) so +this doesn't break that contract. + + $newpdl = $mypdl + 1; + +would result in C<$newpdl> being a normal B object, not a B +object. + +Subclassing from B effects this +behavior. B provides a wrapper constructor and +an B class method. The constructor ensures returns a +properly subclassed hash with the C key, keeping B happy. +When B calls the B function it gets a normal B. + +=head2 Using with Class Frameworks + +The L shows how to use B with various +class frameworks. The key differentiation between frameworks is +whether or not they will call a superclass's constructor. B +always calls it, B calls it only if it inherits from +B, and B and B +never will call the superclass' constructor. + +=head1 BUGS AND LIMITATIONS + + +Please report any bugs or feature requests to +C, or through the web interface at +L. + +=head1 VERSION + +Version 0.01 + +=head1 LICENSE AND COPYRIGHT + +Copyright (c) 2016 The Smithsonian Astrophysical Observatory + +PDLx::DetachedObject is free software: you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +=head1 AUTHOR + +Diab Jerius Edjerius@cpan.orgE + + +=cut diff --git a/t/00-load.t b/t/00-load.t new file mode 100644 index 0000000..695bf06 --- /dev/null +++ b/t/00-load.t @@ -0,0 +1,9 @@ +#!perl + +use Test::More tests => 1; + +BEGIN { + use_ok('PDLx::DetachedObject'); +} + +diag( "Testing PDLx::DetachedObject $PDLx::DetachedObject::VERSION, Perl $], $^X" ); diff --git a/t/classes.t b/t/classes.t new file mode 100644 index 0000000..90b6921 --- /dev/null +++ b/t/classes.t @@ -0,0 +1,120 @@ +#!perl + +use strict; +use warnings; + +use Test::More; +use Test::Deep; +use PDL; + + +{ + package Moo::PDL; + + use PDL::Lite; + + use Moo; + extends 'PDLx::DetachedObject'; + + has PDL => ( is => 'rw' ); + + sub requires_hash { 0 }; +} + +{ + package Class::Tiny::PDL; + + use Class::Tiny qw[ PDL ]; + + use parent 'PDLx::DetachedObject'; + + sub requires_hash { 0 }; +} + +{ + package Object::Tiny::PDL; + + use Object::Tiny qw[ PDL ]; + use parent 'PDLx::DetachedObject'; + + sub requires_hash { 0 }; + +} + +{ + package Class::Accessor::PDL; + + use parent 'Class::Accessor', 'PDLx::DetachedObject'; + __PACKAGE__->follow_best_practice; + __PACKAGE__->mk_accessors( 'PDL' ); + + sub requires_hash { 1 }; +} + +{ + package Class::Accessor::Antlers::PDL; + + use Class::Accessor "antlers"; + use parent 'PDLx::DetachedObject'; + + has PDL => ( is => 'ro' ); + + sub requires_hash { 1 }; +} + + +for my $Class ( qw[ + Object::Tiny::PDL + Moo::PDL + Class::Tiny::PDL + Class::Accessor::PDL + Class::Accessor::Antlers::PDL + ] ) +{ + + subtest $Class => sub { + + my @args = ( PDL => pdl( 0, 1 ) ); + + my $mpdl = $Class->new( $Class->requires_hash ? { @args } : @args ); + + isa_ok( $mpdl, $Class ); + isa_ok( $mpdl, 'PDL' ); + + cmp_deeply( $mpdl->unpdl, [ 0, 1 ], 'constructor initialization' ); + + { + # copy constructor is just a pass through + my $pdl = $mpdl; + isa_ok( $pdl, $Class ); + isa_ok( $pdl, 'PDL' ); + cmp_deeply( $pdl->unpdl, [ 0, 1 ], 'copy' ); + } + + { + # operations! + my $pdl = $mpdl + 2; + + ok( $pdl->isa( 'PDL' ) && !$pdl->isa( $Class ), + "result is normal piddle" ); + + cmp_deeply( $mpdl->unpdl, [ 0, 1 ], 'mpdl untouched' ); + cmp_deeply( $pdl->unpdl, [ 2, 3 ], 'result' ); + } + + { + # operations! + $mpdl *= 2; + + isa_ok( $mpdl, $Class ); + isa_ok( $mpdl, 'PDL' ); + + cmp_deeply( $mpdl->unpdl, [ 0, 2 ], 'mpdl * 2' ); + } + + }; + +} + +done_testing; + diff --git a/xt/cpan-changes.t b/xt/cpan-changes.t new file mode 100644 index 0000000..a9831b3 --- /dev/null +++ b/xt/cpan-changes.t @@ -0,0 +1,4 @@ +use Test::More; +eval 'use Test::CPAN::Changes'; +plan skip_all => 'Test::CPAN::Changes required for this test' if $@; +changes_ok(); diff --git a/xt/cpan-meta-json.t b/xt/cpan-meta-json.t new file mode 100644 index 0000000..3873897 --- /dev/null +++ b/xt/cpan-meta-json.t @@ -0,0 +1,4 @@ +use Test::More; +eval "use Test::CPAN::Meta::JSON"; +plan skip_all => "Test::CPAN::Meta::JSON required for testing META.json" if $@; +meta_json_ok(); diff --git a/xt/cpan-meta.t b/xt/cpan-meta.t new file mode 100644 index 0000000..924aea2 --- /dev/null +++ b/xt/cpan-meta.t @@ -0,0 +1,4 @@ +use Test::More; +eval "use Test::CPAN::Meta"; +plan skip_all => "Test::CPAN::Meta required for testing META.yml" if $@; +meta_yaml_ok(); diff --git a/xt/nobreakpoints.t b/xt/nobreakpoints.t new file mode 100644 index 0000000..b6dc2e8 --- /dev/null +++ b/xt/nobreakpoints.t @@ -0,0 +1,7 @@ + +use Test::More; +eval "use Test::NoBreakpoints 0.10"; +plan skip_all => "Test::NoBreakpoints 0.10 required for testing" if $@; +all_files_no_breakpoints_ok(); + +done_testing; diff --git a/xt/perlcritic.t b/xt/perlcritic.t new file mode 100644 index 0000000..e87ca82 --- /dev/null +++ b/xt/perlcritic.t @@ -0,0 +1,11 @@ +#!perl + +use Test::More; + +if (! eval{ require Test::Perl::Critic }) { + Test::More::plan( + skip_all => "Test::Perl::Critic required for testing PBP compliance" + ); +} + +Test::Perl::Critic::all_critic_ok(); diff --git a/xt/pod.t b/xt/pod.t new file mode 100644 index 0000000..976d7cd --- /dev/null +++ b/xt/pod.t @@ -0,0 +1,6 @@ +#!perl -T + +use Test::More; +eval "use Test::Pod 1.14"; +plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; +all_pod_files_ok(); diff --git a/xt/test-fixme.t b/xt/test-fixme.t new file mode 100644 index 0000000..eabda34 --- /dev/null +++ b/xt/test-fixme.t @@ -0,0 +1,2 @@ +use Test::Fixme; +run_tests();