Subclassing CGI::Pretty dies instantly in ->new , bug?

Discussion in 'Perl Misc' started by Jeremy Henty, Feb 21, 2007.

  1. Jeremy Henty

    Jeremy Henty Guest

    I created a subclass of CGI::pretty and it instantly dies:

    $ /data/www-jeremy/cgi-bin/cgi-jeremy
    Undefined subroutine Jeremy::CGI::delete
    at /data/www-jeremy/cgi-bin/cgi-jeremy line 9

    Line 9 is:

    my $query = Jeremy::CGI->new;

    If I modify the class to inherit from CGI then it works.

    Is this a bug or a feature?

    Is there a workaround?

    Are there any other pitfalls if I inherit from CGI instead of
    CGI::pretty ? (I plan to use object-oriented style exclusively.)


    Details:

    Perl 5.8.7 on Linux 2.6.17.14 , gcc 3.4.3 .

    The CGI subclass (works as given but fails if I replace CGI with
    CGI::pretty):

    use strict;
    use warnings;

    package Jeremy::CGI;
    use CGI;
    our @ISA;
    @ISA = qw( CGI );

    1; # success

    The CGI script:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use lib qw( /home/jeremy/Personal/Geeky/Perl/Lib );
    use Jeremy::CGI;

    my $query = Jeremy::CGI->new;

    print
    $query->header,
    $query->start_html("Hi!"),
    $query->p("boink"),
    $query->ul($query->li("foo"),
    $query->li("bar"),);
    $query->end_html,
    ;

    Full output of "perl -V":

    Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
    Platform:
    osname=linux, osvers=2.6.9, archname=i686-linux
    uname='linux knoppix 2.6.9 #2 smp tue oct 19 23:51:10 cest 2004 i686 athlon-4 i386 gnulinux '
    config_args='-ds -e -Dprefix=/usr -Dpager=/bin/less -isR'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
    Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='3.4.3', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
    Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.3.4.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.3.4'
    Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'


    Characteristics of this binary (from libperl):
    Compile-time options: USE_LARGE_FILES
    Built under linux
    Compiled at Dec 5 2005 05:39:47
    @INC:
    /usr/lib/perl5/5.8.7/i686-linux
    /usr/lib/perl5/5.8.7
    /usr/lib/perl5/site_perl/5.8.7/i686-linux
    /usr/lib/perl5/site_perl/5.8.7
    /usr/lib/perl5/site_perl
     
    Jeremy Henty, Feb 21, 2007
    #1
    1. Advertising

  2. Jeremy Henty

    Uri Guttman Guest

    >>>>> "JH" == Jeremy Henty <> writes:

    JH> I created a subclass of CGI::pretty and it instantly dies:
    JH> $ /data/www-jeremy/cgi-bin/cgi-jeremy
    JH> Undefined subroutine Jeremy::CGI::delete
    JH> at /data/www-jeremy/cgi-bin/cgi-jeremy line 9

    JH> Line 9 is:

    JH> my $query = Jeremy::CGI->new;

    JH> If I modify the class to inherit from CGI then it works.

    you are contradicting yourself. you can't subclass without
    inheriting. the namespace of a module HAS NOTHING to do with subclassing
    or inheritance. it is an arbitrary namespace and you can call it Foo and
    subclass Bar.

    JH> Is this a bug or a feature?

    JH> Is there a workaround?

    you found the fix (not a workaround).

    JH> Are there any other pitfalls if I inherit from CGI instead of
    JH> CGI::pretty ? (I plan to use object-oriented style exclusively.)

    JH> use CGI;
    JH> our @ISA;
    JH> @ISA = qw( CGI );

    replace all that with:

    use base 'CGI' ;

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Feb 21, 2007
    #2
    1. Advertising

  3. Jeremy Henty

    Jeremy Henty Guest

    On 2007-02-21, Uri Guttman <> wrote:
    >>>>>> "JH" == Jeremy Henty <> writes:

    >
    > JH> I created a subclass of CGI::pretty and it instantly dies:
    > JH> $ /data/www-jeremy/cgi-bin/cgi-jeremy
    > JH> Undefined subroutine Jeremy::CGI::delete
    > JH> at /data/www-jeremy/cgi-bin/cgi-jeremy line 9
    >
    > JH> Line 9 is:
    >
    > JH> my $query = Jeremy::CGI->new;
    >
    > JH> If I modify the class to inherit from CGI then it works.
    >
    > you are contradicting yourself. you can't subclass without
    > inheriting.


    I don't see how this comment relates to my problem. I'm not claiming
    you can subclass without inheriting. What I have is two modules,
    identical except that one subclasses CGI and the other subclasses
    CGI::pretty , and the first works and the second breaks. What is
    wrong with trying to subclass CGI::pretty ?

    > ...the namespace of a module HAS NOTHING to do with subclassing or
    > inheritance. it is an arbitrary namespace and you can call it Foo
    > and subclass Bar.


    I'm aware of that. I've actually written code that does that without
    problems. It doesn't explain why my module breaks if I replace "use
    CGI;" with "use CGI::pretty;" and "@ISA = qw( CGI );" with "@ISA = qw(
    CGI::pretty );". I've read the CGI and CGI::pretty perldocs, Googled
    and searched perl.doc and found nothing that explains this.

    > JH> use CGI;
    > JH> our @ISA;
    > JH> @ISA = qw( CGI );
    >
    > replace all that with:
    >
    > use base 'CGI' ;


    Thanks for the tip but it doesn't help the original problem, "use base
    'CGI';" works fine and "use base 'CGI::pretty';" dies exactly as
    before. So I'm still mystified.

    Regards,

    Jeremy Henty
     
    Jeremy Henty, Feb 21, 2007
    #3
  4. Jeremy Henty

    Jeremy Henty Guest

    On 2007-02-21, Jeremy Henty <> wrote:

    > ... What I have is two modules, identical except that one
    > subclasses CGI and the other subclasses CGI::pretty , and the first
    > works and the second breaks. What is wrong with trying to subclass
    > CGI::pretty ?


    I'm following up to myself to explain further: the reason why this is
    so surprising is that CGI::pretty is just a subclass of CGI that
    modifies a few methods to produce nicer HTML output. If I rewrite my
    CGI script to use CGI::pretty directly then it works.

    So the *real* puzzle is this: why does replacing CGI::pretty with a
    module that does nothing except inherit from CGI::pretty break things?

    In fact "perldoc perltoot" says:

    Setting up an empty class like this is called the "empty subclass
    test"; that is, making a derived class that does nothing but
    inherit from a base class. If the original base class has been
    designed properly, then the new derived class can be used as a
    drop-in replacement for the old one.

    which suggests that CGI::pretty is actually broken since it fails the
    empty subclass test. If that's so then at the very least the docs
    should say so.

    Hope this clarifies my question.

    Regards,

    Jeremy Henty
     
    Jeremy Henty, Feb 21, 2007
    #4
  5. Jeremy Henty

    Uri Guttman Guest

    >>>>> "JH" == Jeremy Henty <> writes:

    JH> On 2007-02-21, Jeremy Henty <> wrote:
    >> ... What I have is two modules, identical except that one
    >> subclasses CGI and the other subclasses CGI::pretty , and the first
    >> works and the second breaks. What is wrong with trying to subclass
    >> CGI::pretty ?


    JH> I'm following up to myself to explain further: the reason why this is
    JH> so surprising is that CGI::pretty is just a subclass of CGI that
    JH> modifies a few methods to produce nicer HTML output. If I rewrite my
    JH> CGI script to use CGI::pretty directly then it works.

    well, for one thing since you don't seem to do anything special in
    Jeremy::CGI why do you need that module?

    the error you get seems to imply a broken inheritance path as your new
    method is calling a delete method up the @ISA tree. when you changed
    your module to use CGI::pretty did you change all the CGI to
    CGI::pretty? you didn't show that version.


    JH> So the *real* puzzle is this: why does replacing CGI::pretty with a
    JH> module that does nothing except inherit from CGI::pretty break things?

    i looked at the code and it seems it should work so i will bet it is
    your code that is somehow broken. nothing personal but that is a good
    bet when someone complains about modules by certain authors such as
    lincoln stein.

    try using the use base idea i mentioned. it does exactly what you want
    and it means only one place needs to be changed from CGI to
    CGI::pretty. maybe that will fix it or help isolate the problem.

    also to make your life easier for testing you can run this directly and
    not under a web server. this is much better for debugging many cgi
    scripts in general.

    if you think (and can prove) this is a real error in CGI::pretty then
    you should report it to the author (but not until you can show serious
    evidence on your side).

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Feb 21, 2007
    #5
  6. Jeremy Henty

    Jeremy Henty Guest

    On 2007-02-21, Uri Guttman <> wrote:
    >>>>>> "JH" == Jeremy Henty <> writes:


    > JH> I'm following up to myself to explain further: the reason why
    > JH> this is so surprising is that CGI::pretty is just a subclass
    > JH> of CGI that modifies a few methods to produce nicer HTML output.
    > JH> If I rewrite my CGI script to use CGI::pretty directly then it
    > JH> works.
    >
    > well, for one thing since you don't seem to do anything special in
    > Jeremy::CGI why do you need that module?


    I wanted to inherit from CGI::pretty to refactor some code and when I
    did so it promptly broke. I'm giving you a stripped-down example to
    spare you the irrelevant details. (That's good practice, right?)

    > ... try using the use base idea i mentioned. it does exactly what
    > you want and it means only one place needs to be changed from CGI to
    > CGI::pretty. maybe that will fix it or help isolate the problem.


    It did not fix it (though I appreciate you telling me about it)! Here
    are the *exact* files I am now using (modulo indentation for clarity)

    The CGI script:

    #!/usr/bin/perl

    use strict;
    use warnings;

    use lib qw( /home/jeremy/Personal/Geeky/Perl/Lib );
    use Jeremy::CGI;

    my $query = Jeremy::CGI->new;

    print
    $query->header,
    $query->start_html("Hi!"),
    $query->p("boink"),
    $query->ul($query->li("foo"),
    $query->li("bar"),);
    $query->end_html,
    ;

    Jeremy/CGI.pm :

    use strict;
    use warnings;

    package Jeremy::CGI;
    use base 'CGI::pretty';

    1; # success

    And the result is:

    Undefined subroutine Jeremy::CGI::delete
    at /data/www-jeremy/cgi-bin/cgi-jeremy line 9

    If I replace "my $query = Jeremy::CGI->new;" with "my $query =
    CGI::pretty->new;", it works. If I replace "use base 'CGI::pretty';"
    with "use base 'CGI';", it works. But as it stands, it's broken. It
    seems clear that subclassing CGI::pretty just doesn't work.

    > ... to make your life easier for testing you can run this directly
    > and not under a web server.


    I am running it directly. (Believe me, I do read the docs and I am
    trying not to waste your time or mine.)

    > ... if you think (and can prove) this is a real error in CGI::pretty
    > then you should report it to the author


    I was hoping someone could tell me whether subclassing CGI::pretty was
    supported before I hassled the author.

    > ... (but not until you can show serious evidence on your side).


    I've given you the exact files and output, and a quote from "perldoc
    perltoot" that says a properly written module should not do this. If
    that's not serious evidence I don't know what is!

    Regards,

    Jeremy Henty
     
    Jeremy Henty, Feb 21, 2007
    #6
  7. Jeremy Henty

    Uri Guttman Guest

    >>>>> "JH" == Jeremy Henty <> writes:

    JH> On 2007-02-21, Uri Guttman <> wrote:

    JH> The CGI script:

    JH> use lib qw( /home/jeremy/Personal/Geeky/Perl/Lib );
    JH> use Jeremy::CGI;

    JH> my $query = Jeremy::CGI->new;

    JH> Jeremy/CGI.pm :

    JH> use strict;
    JH> use warnings;

    JH> package Jeremy::CGI;
    JH> use base 'CGI::pretty';

    JH> And the result is:

    JH> Undefined subroutine Jeremy::CGI::delete
    JH> at /data/www-jeremy/cgi-bin/cgi-jeremy line 9

    JH> If I replace "my $query = Jeremy::CGI->new;" with "my $query =
    JH> CGI::pretty->new;", it works. If I replace "use base 'CGI::pretty';"
    JH> with "use base 'CGI';", it works. But as it stands, it's broken. It
    JH> seems clear that subclassing CGI::pretty just doesn't work.

    i would call that pretty good evidence. not much you can do but write
    the author and send him all of this.

    JH> I was hoping someone could tell me whether subclassing CGI::pretty was
    JH> supported before I hassled the author.

    well, no one seems to have tried it before you did (i don't use ::pretty
    and don't do much CGI in general).

    >> ... (but not until you can show serious evidence on your side).


    JH> I've given you the exact files and output, and a quote from "perldoc
    JH> perltoot" that says a properly written module should not do this. If
    JH> that's not serious evidence I don't know what is!

    like i said, now you have to write to lincoln stein and show him
    this. if you were to even find the fix (something in CGI::pretty) he
    would likely update it quickly. he is know for reasonable response
    times. also you can try reporting the bug with rt.cpan.org which may be
    more effective. he should get all bug reports from that on his modules.

    as i said, i looked at the CGI::pretty code and couldn't see anything
    obvious as to why it wouldn't work. there is one possible issue i can
    think of. CGI is noted for doing dynamic loading of many of its
    functions/methods and it does its own wierd way. maybe GGI::pretty is
    doing something that needs to be done in your module too to force
    loading of the delete method? i see this line in CGI::pretty and maybe
    it will be a clue for you.

    $CGI::pretty::AutoloadClass = 'CGI';

    also look into calling SUPER::new() instead of new() in your
    module. CGI::pretty does that and it might also help. calling SUPER:: is
    common when inheriting constructors.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Feb 21, 2007
    #7
  8. Jeremy Henty

    Jeremy Henty Guest

    > ... you can try reporting the bug with rt.cpan.org which may be more
    > effective.


    I will. Thanks for the pointer.

    > I see this line in CGI::pretty and maybe it will be a clue for you.
    >
    > $CGI::pretty::AutoloadClass = 'CGI';
    >
    > also look into calling SUPER::new() instead of new() in your
    > module. CGI::pretty does that and it might also help. calling
    > SUPER:: is common when inheriting constructors.


    I did actually try copying stuff from the CGI::pretty constructor into
    mine but nothing I tried worked. Eventually I decided to stop
    tinkering and ask for help. Maybe the author can tell me the right
    combination of magic.

    Thanks again for your comments,

    Jeremy Henty
     
    Jeremy Henty, Feb 21, 2007
    #8
  9. Jeremy Henty

    -berlin.de Guest

    Uri Guttman <> wrote in comp.lang.perl.misc:
    > >>>>> "JH" == Jeremy Henty <> writes:

    >
    > JH> On 2007-02-21, Uri Guttman <> wrote:
    >
    > JH> The CGI script:
    >
    > JH> use lib qw( /home/jeremy/Personal/Geeky/Perl/Lib );
    > JH> use Jeremy::CGI;
    >
    > JH> my $query = Jeremy::CGI->new;
    >
    > JH> Jeremy/CGI.pm :
    >
    > JH> use strict;
    > JH> use warnings;
    >
    > JH> package Jeremy::CGI;
    > JH> use base 'CGI::pretty';
    >
    > JH> And the result is:
    >
    > JH> Undefined subroutine Jeremy::CGI::delete
    > JH> at /data/www-jeremy/cgi-bin/cgi-jeremy line 9
    >
    > JH> If I replace "my $query = Jeremy::CGI->new;" with "my $query =
    > JH> CGI::pretty->new;", it works. If I replace "use base 'CGI::pretty';"
    > JH> with "use base 'CGI';", it works. But as it stands, it's broken. It
    > JH> seems clear that subclassing CGI::pretty just doesn't work.
    >
    > i would call that pretty good evidence. not much you can do but write
    > the author and send him all of this.
    >
    > JH> I was hoping someone could tell me whether subclassing CGI::pretty was
    > JH> supported before I hassled the author.
    >
    > well, no one seems to have tried it before you did (i don't use ::pretty
    > and don't do much CGI in general).
    >
    > >> ... (but not until you can show serious evidence on your side).

    >
    > JH> I've given you the exact files and output, and a quote from "perldoc
    > JH> perltoot" that says a properly written module should not do this. If
    > JH> that's not serious evidence I don't know what is!
    >
    > like i said, now you have to write to lincoln stein and show him
    > this. if you were to even find the fix (something in CGI::pretty) he
    > would likely update it quickly. he is know for reasonable response
    > times. also you can try reporting the bug with rt.cpan.org which may be
    > more effective. he should get all bug reports from that on his modules.
    >
    > as i said, i looked at the CGI::pretty code and couldn't see anything
    > obvious as to why it wouldn't work. there is one possible issue i can
    > think of. CGI is noted for doing dynamic loading of many of its
    > functions/methods and it does its own wierd way. maybe GGI::pretty is
    > doing something that needs to be done in your module too to force
    > loading of the delete method? i see this line in CGI::pretty and maybe
    > it will be a clue for you.


    Your hunch is right about helping a class along to load its methods.
    This is a workaround: In .../Jeremy/CLI.pm do

    package Jeremy::CGI;
    use base 'CGI::pretty';

    CGI::pretty->can( $_) for qw( delete header cache);

    1; # success

    The ->can query has the effect that later calls to the methods
    actually succeed. I don't know what exactly happens, just
    noticed the effect while looking into this.

    > $CGI::pretty::AutoloadClass = 'CGI';


    > also look into calling SUPER::new() instead of new() in your
    > module. CGI::pretty does that and it might also help. calling SUPER:: is
    > common when inheriting constructors.


    No, it's common when you override the constructor with your own. If
    you inherit the constructor, there's no need (and no way) to use
    SUPER::.

    Anno
     
    -berlin.de, Feb 21, 2007
    #9
  10. Jeremy Henty

    Jeremy Henty Guest

    This is another auto-followup to thank everyone who posted
    workarounds. I'll still send in a bug report, but first, sleep
    beckons.

    Jeremy Henty
     
    Jeremy Henty, Feb 21, 2007
    #10
  11. Jeremy Henty

    Uri Guttman Guest

    >>>>> "a" == anno4000 <-berlin.de> writes:

    a> Uri Guttman <> wrote in comp.lang.perl.misc:
    >>
    >> as i said, i looked at the CGI::pretty code and couldn't see anything
    >> obvious as to why it wouldn't work. there is one possible issue i can
    >> think of. CGI is noted for doing dynamic loading of many of its
    >> functions/methods and it does its own wierd way. maybe GGI::pretty is
    >> doing something that needs to be done in your module too to force
    >> loading of the delete method? i see this line in CGI::pretty and maybe
    >> it will be a clue for you.


    a> Your hunch is right about helping a class along to load its methods.
    a> This is a workaround: In .../Jeremy/CLI.pm do

    a> package Jeremy::CGI;
    a> use base 'CGI::pretty';

    a> CGI::pretty->can( $_) for qw( delete header cache);

    a> 1; # success

    a> The ->can query has the effect that later calls to the methods
    a> actually succeed. I don't know what exactly happens, just
    a> noticed the effect while looking into this.

    >> $CGI::pretty::AutoloadClass = 'CGI';


    interesting. why his call to new() doesn't trigger the autoload of
    delete but CGI::pretty's new call does is the mystery.

    >> also look into calling SUPER::new() instead of new() in your
    >> module. CGI::pretty does that and it might also help. calling SUPER:: is
    >> common when inheriting constructors.


    a> No, it's common when you override the constructor with your own. If
    a> you inherit the constructor, there's no need (and no way) to use
    a> SUPER::.

    SUPER:: is normally used to call the parent class's initializer which
    may not be called by its constructor. or some such variation. i thought
    it might be a way to force autoloading of the missing methods in this
    case. your call to can() seems to force it but again, why it is needed
    is unknown. the OP should still ask stein about this IMO.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Feb 22, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ceri
    Replies:
    2
    Views:
    422
    Ceri Locke
    Dec 17, 2003
  2. Dot net work
    Replies:
    11
    Views:
    13,489
    Dot net work
    May 9, 2004
  3. xamman
    Replies:
    1
    Views:
    285
    xamman
    Dec 29, 2006
  4. Darren

    Instantly Download Software

    Darren, Oct 1, 2005, in forum: C Programming
    Replies:
    2
    Views:
    264
    Skarmander
    Oct 2, 2005
  5. Christopher M. Lusardi
    Replies:
    3
    Views:
    193
    Alan J. Flavell
    Oct 19, 2003
Loading...

Share This Page