|
From: Mark Mackey on 26 Jan 2006 12:11 Hi all. I've got a simple problem that I can't work out an elegant way to solve. I have a simple Perl module which is basically a wrapper for some external binaries. I want the module to check for the existence of those binaries on import, but only for the binaries which are actually going to be used by the subroutines that are exported. For example, I have Thingy.pm: package Thingy; require Exporter; @ISA = qw(Exporter); # symbols to export on request @EXPORT_OK = qw(sub1 sub2 sub3); use strict; sub sub1 { print `/bin/ls`; } sub sub2 { print `/bin/true`; } sub sub3 { print `/bin/no_exist`; } BEGIN { my(@required)=qw( /bin/ls /bin/true /bin/no_exist ); my(%required)=( sub1=>"/bin/ls", sub2=>"/bin/true", sub3=>"/bin/no_exist" ); foreach (@required) { print "Checking $_\n"; die "Can't find required utility $_" if (! -x $_); } } 1; Sub1 will only work if "/bin/ls" is present, sub2 will only work if "/bin/true" is present, and sub3 will only work if "/bin/no_exist" is present. With the current structure, all 3 are checked on import, so use Thingy qw(); dies telling me that "bin/no_exist" doesn't exist :). What I want is to be able to check the relevant binaries' existence only for the methods that are imported, so in this case you could do use Thingy qw(sub1); and everything would be happy, but use Thingy qw(sub1 sub2 sub3); would bail out and inform me that 'sub3' depends on "/bin/no_exist" and hence it can't continue. The reason I'd like this check is that this module is used in lots of programs, each of which uses a different subset of its subroutines. Some of the programs have very long runtimes, so I don't really want them to run for hours and then suddenly bail out when sub3() finally gets called. I suspect the answer involves fiddling around with import() methods, but I don't completely understand the documentation for Exporter.pm about this. Help? -- Mark Mackey http://www.swallowtail.org/ code code code code code code code code code code code code code bug code co de code code code bug code code code code code code code code code code code code code code code code code code code code code code code code code code c
From: Uri Guttman on 26 Jan 2006 13:26 >>>>> "MM" == Mark Mackey <markm(a)chiark.greenend.org.uk> writes: MM> require Exporter; MM> @ISA = qw(Exporter); those two lines are better done as: use base 'Exporter' MM> # symbols to export on request MM> @EXPORT_OK = qw(sub1 sub2 sub3); MM> use strict; put the strict line before all the others. then use our before @EXPORT_OK. the use base line will still work correctly too. MM> What I want is to be able to check the relevant binaries' existence only MM> for the methods that are imported, so in this case you could do MM> The reason I'd like this check is that this module is used in lots of MM> programs, each of which uses a different subset of its subroutines. Some MM> of the programs have very long runtimes, so I don't really want them to MM> run for hours and then suddenly bail out when sub3() finally gets MM> called. I suspect the answer involves fiddling around with import() MM> methods, but I don't completely understand the documentation for MM> Exporter.pm about this. you just need to declare your own import() method. it is called with the class name and the arguments passed on the use line so you will get 'sub1', etc. do your checks then and die or whatever as needed. if all the requested features are supported, then you can pass the import request on to Exporter with: (untested) sub import { my( $class, @features ) = @_ ; # do your testing of the requested features in @features # and die as desired. # at this point everything wanted is found $class->SUPER::import( @features ) ; } since you are subclassing Exporter, it will get the same call as if it was handled directly without your intervening import method. uri -- Uri Guttman ------ uri(a)stemsystems.com -------- http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
From: Paul Lalli on 26 Jan 2006 13:55 Mark Mackey wrote: > I've got a simple problem that I can't work out an elegant way to solve. > I have a simple Perl module which is basically a wrapper for some > external binaries. I want the module to check for the existence of those > binaries on import, but only for the binaries which are actually going > to be used by the subroutines that are exported. <snip> > I suspect the answer involves fiddling around with import() > methods, You are correct. > but I don't completely understand the documentation for Exporter.pm about this. That's okay, because import() doesn't intrinsically have anything to do with Exporter; import() is not a built in. It is a method that you define in your package, that is automatically called when the user calles 'use Thingy;'. More specifically, if the user calls 'use Thingy qw/ls true/', then the import method is called with those two parameters. So, within your package, define your import() method. In it, retrieve what elements are being requested, via @_, like any other method or subroutine. Do whatever checks are necessary. And once you're done, you can then invoke Exporter's magic by following the "Exporting without using Exporter's import method" section of Exporter's documentation: use Carp; sub import { my $class = shift; my @subs_to_export = @_; my %required_for = ( sub1=>"/bin/ls", sub2=>"/bin/true", sub3=>"/bin/no_exist" ); foreach (@subs_to_export){ print "Checking $_\n"; croak "Can't find required utility for $_" unless -x $required_for{$_}; } #we got here, all the required checks passed. Export everything #the user wanted: $class->export_to_level(1, $class, @required); } > Help? Hope this helps. Paul Lalli
From: Mark Mackey on 27 Jan 2006 04:56 In article <1138297798.750898.238030(a)g43g2000cwa.googlegroups.com>, Paul Lalli <mritty(a)gmail.com> wrote: > >import() is not a built in. It is a method that you define in your >package, that is automatically called when the user calles 'use >Thingy;'. More specifically, if the user calls 'use Thingy qw/ls >true/', then the import method is called with those two parameters. Ah, that makes sense, and I now understand what the Exporter.pm docs were wittering about. Where is the fact that the import method is called on 'use' documented? I'd thought that I'd read all of the relevant bits of the man pages, but I missed that one. Thanks! -- Mark Mackey http://www.swallowtail.org/ code code code code code code code code code code code code code bug code co de code code code bug code code code code code code code code code code code code code code code code code code code code code code code code code code c
From: Paul Lalli on 27 Jan 2006 08:06 Mark Mackey wrote: > In article <1138297798.750898.238030(a)g43g2000cwa.googlegroups.com>, > Paul Lalli <mritty(a)gmail.com> wrote: > > > >import() is not a built in. It is a method that you define in your > >package, that is automatically called when the user calles 'use > >Thingy;'. More specifically, if the user calls 'use Thingy qw/ls > >true/', then the import method is called with those two parameters. > > Ah, that makes sense, and I now understand what the Exporter.pm docs > were wittering about. Where is the fact that the import method is called > on 'use' documented? I'd thought that I'd read all of the relevant bits > of the man pages, but I missed that one. perldoc -f import import There is no builtin "import" function. It is just an ordinary method (subroutine) defined (or inherited) by modules that wish to export names to another module. The "use" function calls the "import" method for the package used. perldoc -f use use Module LIST Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to BEGIN { require Module; import Module LIST; } except that Module must be a bareword. Paul Lalli
|
Next
|
Last
Pages: 1 2 Prev: FAQ 7.18 What's the difference between deep and shallow binding? Next: string manipulation |