Hallo Benjamin,
On Tue Apr 24 15:52:09 2007, fagga@gmx.de wrote:
Show quoted text> I'm using the Curses::UI module and want to package it with my
> application in a PAR executable. Curses::UI makes use of the special
> literal __FILE__ which, without being in a PAR package, resolves into
> the full path of the module file name
> "/usr/share/perl5/Curses/UI/Language.pm". But inside a PAR package it
> resolves to "Curses/UI/Language.pm" and I get a "file not found"
> error. Because __FILE__ changes it's behaviour depending on being in
> PAR or not, I think this is a bug in PAR.
You're probably right, this could be considered a bug in PAR. At the
same time, however, I feel this is a bug in Curses::UI::Language. But
first things first:
As you may have guessed PAR does some heavy shuffling of files, file
names, and code to do its magic. The .par's or .exe's contents are
extracted to a temporary directory before being loaded. What exactly is
extracted and how and where it goes is determined by a myriad of
factors. Admitted, it should set __FILE__ right when loading a module.
But OTOH, it does *not* explicitly set __FILE__ wrong, so it is probably
a pretty hard-to-find bug which is most likely intimately related to how
a specific .pm file was loaded. My PAR maintenance time is severely
limited these days, so I can't take the time to search this.
I did, however, have a quick look at how Curses::UI uses the __FILE__
token because it seemed strange to me that a module would want to know
where it's physically (well, almost) located in the file system. It
turns out that Curses::UI::Language::loadlanguage() uses __FILE__ to
determine the location and file name of Curses::UI::Language::foo (i.e.
Curses/UI/Language/foo.pm) modules. That's certainly a bug since nobody
guarantees that various Curses::UI::Language::* modules are installed
into the same module search path. (On a side-note: As you're on debian,
you probably noticed debian has something like a hundred thousand paths
it likes to scatter its modules into.)
Now, there is a way to go about this which makes use of Perl's built-in
module (file) searching algorithm instead of doing all the file
searching by hand as Curses::UI does. That method should not be broken
by PAR mangling __FILE__:
- Instead of working with file names, the loadlanguage() sub would work
with namespaces. It would append ::langname to its own namespace
(__PACKAGE__).
- Then, it would eval("require $thatnamespace;") to make sure its loaded.
- Next, it would fetch the DATA file handle which is opened by perl for
it. That skips the opening of the module source code file by hand.
Admittedly, this approach also has some perils, but at least they're
hacks that stay within the Perl code and do not depend on file system
interaction.
I implemented the algorithm outlined above with PAR::StrippedPARL::Base,
::Static, and ::Dynamic. ::Base has all the heavy lifting and the other
classes inherit from it. PAR::StrippedPARL::Base would become
Curses::UI::Language::Base or so. Curses::UI::Language would load the
corresponding language class (which inherits from ::Base) and call
something like ->fetch_data_handle() or so on it. Of course, you could
make Curses::UI::Language the base class itself.
I don't know whether the Curses::UI maintainer would accept a patch to
do this, of course.
I'll keep this ticket open because even if Curses::UI::Language was
modified, the PAR bug would stay.
Show quoted text> Thank you very much for reading this and for this nevertheless great
> module. I was very happy when I found it. (:
Thanks for the praise!
Steffen