in reply to (tye)Re: Unconfuse filehandles and classes
in thread Unconfuse filehandles and classes

Here is the new monster:

package IO::patch; # The following code: # use CGI; my $q= CGI->new(); open CGI, "< $0"; # gives: # Can't locate object method "new" via package "IO::Handle" # # But download this code and put it into lib/IO/patch.pm and # either add "use IO::patch;" to your script or add # PERL5OPT=-MIO::patch to your environment, and this problem # goes away. # # Only class methods are subject to this problem. This version # of IO::patch even handles class methods that are AUTOLOADed, # but doesn't trap class methods that have the same name as # methods (or routines) in IO::Handle except for new(). require IO::Handle; use vars qw( $AUTOLOAD ); my $oldNew= \&IO::Handle::new; *IO::Handle::new= \&newNew; *IO::Handle::AUTOLOAD= \&AUTOLOAD; sub newNew { my $pkg= $_[0]; if( UNIVERSAL::isa( $pkg, "GLOB" ) ) { my $name= *{$pkg}{NAME}; my $can= UNIVERSAL::can( $name, "new" ); require Carp if $^W; if( $can ) { Carp::carp( "File handle vs. package name conflict ($name)" ) if $^W; $_[0]= $name; goto &$can; } Carp::carp( qq(Called new() on an open IO::Handle or can't locate) . qq( object method "new" via package "$name") ) if $^W; } goto &$oldNew; } sub AUTOLOAD { my $pkg= $_[0]; my $meth= $AUTOLOAD; require Carp; if( UNIVERSAL::isa( $pkg, "GLOB" ) ) { my $name= *{$pkg}{NAME}; $meth =~ s/^IO::Handle:://; my $can= UNIVERSAL::can( $name, $meth ); if( $can ) { Carp::carp( "File handle vs. package name conflict ($name)" ) if $^W; $_[0]= $name; goto &$can; } $can= UNIVERSAL::can( $name, "AUTOLOAD" ); if( $can ) { eval { require Devel::Peek } or Carp::croak( qq(Can't AUTOLOAD method "$meth" via package "$nam +e") . qq( unless you install Devel::Peek\n) . $@ ); my $gv= Devel::Peek::CvGV( $can ); { my $alPkg= *{$gv}{PACKAGE}; no strict 'refs'; ${$alPkg."::AUTOLOAD"}= $name . "::" . $meth; } Carp::carp( "File handle vs. package name conflict ($name)" ) if $^W; $_[0]= $name; goto &$can; } Carp::croak( qq(Can't locate object method "$meth" via package "$name") ); } Carp::croak( qq(Can't locate object method "$meth" via package "IO::Handle" +) ); }
I've tested it and it works well in lots of situations. The code could probably be drastically cleaned up, but that is less important than getting this out there.

Update: Thanks, bbfu, fixed.

        - tye (but my friends call me "Tye")

Replies are listed 'Best First'.
(bbfu) Re: (tye)Re2: Unconfuse filehandles and classes
by bbfu (Curate) on Sep 07, 2001 at 00:07 UTC

    Hrm. Unless I'm missing something, if warnings are off and Devel::Peek is not installed, the calls to Carp::croak are going to fail since you only require in Carp if warnings are on, and you croak regardless.

    bbfu
    Seasons don't fear The Reaper.
    Nor do the wind, the sun, and the rain.
    We can be like they are.