On Fri, 5 Sep 2003 [EMAIL PROTECTED] wrote:

> Installing one of these plugin modules will also maintain a small
> "database" of installed plugins and their capabilities (where a capability
> is osmething like "reads oggs" or "writes ID3 tags"). This is a bit like
> how XML::SAX works.

For comparison XML::SAX's interface looks like this (stolen directly from
the synopsis)

         # get a list of known parsers
         my $parsers = XML::SAX->parsers();

         # add/update a parser
         XML::SAX->add_parser(q(XML::SAX::PurePerl));

         # remove parser
         XML::SAX->remove_parser(q(XML::SAX::Foodelberry));

         # save parsers
         XML::SAX->save_parsers();

It does it's magic by storing a ParserDetails.ini file in the same
directory as SAX.pm is located.  They look like this:

  [XML::SAX::PurePerl]
  http://xml.org/sax/features/namespaces = 1
  http://xml.org/sax/features/validation = 0
  # a comment

  # blank lines ignored

  [XML::SAX::AnotherParser]
  http://xml.org/sax/features/namespaces = 0
  http://xml.org/sax/features/validation = 1

So that's fairly straight forward.  As Dave pointed out the problems I
identified are:

1) How does this work with PAR?

 Internally XML::SAX's doing something like this to get at the file:

   # get directory XML::SAX is in.
   $dir = dirname($INC{'XML/SAX.pm'});

   # get the ParserDetails.ini file
   open($fh, File::Spec->catfile($dir, "SAX", "ParserDetails.ini");

This of course works terribly with PAR.  PAR (the module that allows you
to create ZIP files of distributions and then use them directly without
having to unzip their contents) works by putting a magic coderef in @INC.
Normally when you load a module perl looks though each of the directories
in @INC until it finds the file.  However, if rather than putting a
directory in @INC you put in a coderef, perl will execute the code and
expect it to return the source of the module you were looking for.  This
is how PAR works - the subroutine gets the module out of the zip file and
presents it to perl.  The problem is, it doesn't set the %INC to be the
right thing for our uses.  For example:

lib/Foo/Bar.pm
--------------
package Foo::Bar;
use File::Slurp;
use File::Spec::Functions;
use File::Basename qw(dirname);
sub get_contents {
  read_file(catfile(dirname($INC{'Foo/Bar.pm'}),'details'))
}
1;

lib/Foo/details
---------------
these are the details

Running this normally works fine:
bash-2.05b$ perl -Ilib -MFoo::Bar -e 'print Foo::Bar->get_contents'
these are the details
bash-2.05b$

However, if we make this a PAR file, it all goes horribly wrong:
bash-2.05b$ rm lib.par
bash-2.05b$ zip -r lib lib
  adding: lib/ (stored 0%)
  adding: lib/Foo/ (stored 0%)
  adding: lib/Foo/details (stored 0%)
  adding: lib/Foo/Bar.pm (deflated 21%)
bash-2.05b$ perl -MPAR=./lib.zip -MFoo::Bar -e 'print Foo::Bar->get_contents'
open ./details: No such file or directory at /loader/0x81a984c/Foo/Bar.pm
line 6

Darn!

One possibility around this is that rather than have a ini file, we
actually use a simple perl module to hold the file, somewhat like
Config.pm does, and when you add things you rewrite the perl module. This
wouldn't allow you to add things when you're working from a PAR file, but
it would allow you to bundle up extensions.

Does this make sense?  Can anyone spot a flaw in this strategy?

2) More than one place

The big problem I see is where you have local plugins.  Imagine that you
have global plugins installed in /usr/local/lib/perl/5.8.0 and you
want to install some local plugins in /home/mark/perllib.  This is a
problem as you can't write to the global plugin registry.

I guess you could have two versions of the module, a local one that is
attempted to be loaded that adds it's data to the global one.  This is
only one layer of kludge though.  What happens if I have global, an
application level, and a truly local set of plugins?  Where do you draw
the line?

The problem is compounded by it'd be really nice to do something like

  perl -MPAR=./pluginone.par,./plugintwo.par script.pl

And have it get all the plugins in there that are registered inside those
modules.

Shucks, this is getting complicated.  Ideas?

Mark.

-- 
#!/usr/bin/perl -T
use strict;
use warnings;
print q{Mark Fowler, [EMAIL PROTECTED], http://twoshortplanks.com/};

Reply via email to