Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class::Struct, accessor overrides not called from constructor #7272

Closed
p5pRT opened this issue Apr 28, 2004 · 14 comments
Closed

Class::Struct, accessor overrides not called from constructor #7272

p5pRT opened this issue Apr 28, 2004 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 28, 2004

Migrated from rt.perl.org#29230 (status was 'resolved')

Searchable as RT29230$

@p5pRT
Copy link
Author

p5pRT commented Apr 28, 2004

From perl@rhesa.com

This is a bug report for perl from perl@​rhesa.com,
generated with the help of perlbug 1.34 running under perl v5.8.2.


Class​::Struct allows you to override the accessors it creates, but it
doesn't call them in its constructor.
In other words,

  $struct->field('blah');

calls my override, but

  $struct = structure->new('field' => 'blah');

doesn't. Class​::Struct simply does

  $r->{'field'} = $init{'field'}

but it would be more useful if it did

  $r->field($init{'field'})

See the sample code below for a demonstration.
I have also attached a diff with fixes to the code, and the results from
running Struct.t, the test script for Class​::Struct as found in the perl
5.8.4 distribution.

Thank you for your attention,
Rhesa Rozendaal

Demonstration script​:

#!/usr/bin/perl
use strict;
use warnings;
use Class​::Struct;
use Data​::Dumper;

### define struct
struct memory => {
  swap => '$',
  free => '$',
};

### override accessor for free
sub memory​::free {
  my $r = shift;
  die 'Too many args to free' if @​_ > 1;
  if(@​_) {
  my $id = shift;
  if( $id > 100 or $id < 0 ) {
  warn "free `$id` should be between 0 and 100";
  } else {
  $r->{'memory​::free'} = $id;
  }
  }

  $r->{'memory​::free'};
}

### create object and dump
my $m = memory->new(free=>110, swap => 100);
print Dumper($m); # free contains 110, but undef is expected

$m->free(120); # warns and doesn't update, as expected
print Dumper($m);

$m->free(25); # sets free to 25
print Dumper($m);

__END__;

diff of fixed code​:

Compare​: (<)D​:\APM\Perl\lib\Class\Struct.pm (20512 bytes)
  with​: (>)D​:\APM\Perl\lib\Class\Struct_new.pm (21188 bytes)

133a133,135

$out \.= "    bless \\$r\, \\$class;\\n\\n";

153c156
< $out .= " \$r->$elem = $init [];$cmt\n";


        $out \.= "    \\$r\->$name\( $init \[\] \);$cmt\\n";

159c162
< $out .= " \$r->$elem = $init {};$cmt\n";


        $out \.= "    \\$r\->$name\( $init \{\} \);$cmt\\n";

163c166
< $out .= " \$r->$elem = $init undef;$cmt\n";


        $out \.= "    \\$r\->$name\( $init undef \);$cmt\\n";

168c171
< $out .= " { \$r->$elem =
$type->new(\%{\$init{'$name'}}) } $cmt\n";


        $out \.= "            \{ \\$r\->$name\( 

$type->new(\%{\$init{'$name'}}) ) } $cmt\n";
170c173
< $out .= " { \$r->$elem = \$init{'$name'} } $cmt\n";


        $out \.= "            \{ \\$r\->$name\( \\$init\{'$name'\} \) \} 

$cmt\n";
181c184
< $out .= " bless \$r, \$class;\n }\n";


$out \.= "\\n    \\$r;\\n  \}\\n";

Test results​:

1..24
ok 1 - The object isa MyObj
ok 2
ok 3 - The object isa ARRAY
ok 4
ok 5
ok 6 - The object isa HASH
ok 7
ok 8
ok 9
ok 10 - The object isa aClass
ok 11
ok 12 - The object isa MyOther
ok 13
ok 14 - The object isa ARRAY
ok 15
ok 16
ok 17 - The object isa HASH
ok 18
ok 19
ok 20
ok 21 - The object isa aClass
ok 22
ok 23
ok 24 - The object isa RecClass



Flags​:
  category=library
  severity=low


Site configuration information for perl v5.8.2​:

Configured by rhesa at Wed Dec 31 09​:46​:19 2003.

Summary of my perl5 (revision 5 version 8 subversion 2) configuration​:
  Platform​:
  osname=MSWin32, osvers=4.0, archname=MSWin32-x86-multi-thread
  uname=''
  config_args='undef'
  hint=recommended, useposix=true, d_sigaction=undef
  usethreads=undef use5005threads=undef useithreads=define
usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=undef use64bitall=undef uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cl', ccflags ='-nologo -Gf -W3 -MD -DNDEBUG -O1 -DWIN32
-D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT -DNO_HASH_SEED
-DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO
-DPERL_MSVCRT_READFIX',
  optimize='-MD -DNDEBUG -O1',
  cppflags='-DWIN32'
  ccversion='', gccversion='', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
  d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10
  ivtype='long', ivsize=4, nvtype='double', nvsize=8,
Off_t='__int64', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='link', ldflags ='-nologo -nodefaultlib -release
-libpath​:"d​:\apm\Perl\lib\CORE" -machine​:x86'
  libpth=\lib
  libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib
  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib
netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib
odbc32.lib odbccp32.lib msvcrt.lib
  perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib
winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib
oleaut32.lib netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib
version.lib odbc32.lib odbccp32.lib msvcrt.lib
  libc=msvcrt.lib, so=dll, useshrplib=yes, libperl=perl58.lib
  gnulibc_version='undef'
  Dynamic Linking​:
  dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
  cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -release
-libpath​:"d​:\apm\Perl\lib\CORE" -machine​:x86'

Locally applied patches​:
  ACTIVEPERL_LOCAL_PATCHES_ENTRY
  21846 Configure gets d_u32align wrong
  21739 [perl #24493] install.html not working
  21737 Ooops. left an XXX comment in, and worse still it's a // comment
  21735 utf8 keys now work for tied hashes
  21734 Accessing unicode keys in tie hashes via hv_exists was broken
  21733 ext/threads/t/problem.t
  21732 Config​::myconfig() fails under ithreads
  21728 Update perlhist with 5.6.2
  21723 Include 'SCCS' in the list of dir names ignored by installperl
  21718 Empty subroutine as object method segfaults in 5.8.2 (sometimes)
  21714 Fix bug #24380​: assigning list with duplicated keys to a hash
  21706 [perl #24460] [DOC PATCH] the begincheck program
  21693 must copy changes from win32/makeifle.mk to wince/makefile.ce
  21691 Update the list of pumpkings in perlhist.pod
  21687 [PATCH 5.6.2-RC1 pod/perlhist.pod] Updated
  21677 OS/2 docu
  21676 Bug #24407​: key for shared hash got stringified into wrong pool
  21673 Be sure to use -fPIC not -fpic on Linux/SPARC
  21672 extending the hash attack test
  21671 Benchmark.pm cmpthese segfault
  21662 'make minitest' fails for op/cproto and op/pat
  21586 Comment that this 'optimisation' is actually a necessary fixup
  21548 Sync with Pod​::Perldoc 3.12
  21540 Fix backward-compatibility issues in if.pm


@​INC for perl v5.8.2​:
  D​:/APM/Perl/lib
  D​:/APM/Perl/site/lib
  .


Environment for perl v5.8.2​:
  HOME=c​:/
  LANG=NL
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=c​:\program
files\imagemagick-5.5.7-q8;C​:\Cygwin\bin;C​:\PerlForDotNet\bin\;C​:\Program
Files\Microsoft.Net\FrameworkSDK\Bin\;C​:\WINNT\Microsoft.NET\Framework\v1.0.2204\;C​:\Perl\bin\;C​:\WINNT\system32;C​:\WINNT;C​:\WINNT\System32\Wbem;C​:\Program
Files\Microsoft SDK for Java 4.0\Bin;C​:\Program
Files\InstallShield\InstallShield 5.5 Professional
Edition\Program;C​:\MSSQL7\BINN;C​:\Program
Files\cvsnt;c​:\data\rrdtool\bin;c​:\program
files\kevterm;C​:\GnuPG;C​:\Program Files\ImageMagick-5.5.6-Q8;C​:\Program
Files\Microsoft Visual Studio\Common\Tools\WinNT;C​:\Program
Files\Microsoft Visual Studio\Common\MSDev98\Bin;C​:\Program
Files\Microsoft Visual Studio\Common\Tools;C​:\Program Files\Microsoft
Visual Studio\VC98\bin;C​:\Program Files\deskwin\shortcuts
  PERLDB_OPTS=RemotePort=127.0.0.1​:2000
  PERL_BADLANG (unset)
  SHELL (unset)

@p5pRT
Copy link
Author

p5pRT commented Jul 18, 2005

From @schwern

[rhesa - Wed Apr 28 11​:12​:56 2004]​:

Class​::Struct allows you to override the accessors it creates, but it
doesn't call them in its constructor.
In other words,

 $struct\->field\('blah'\);

calls my override, but

 $struct = structure\->new\('field' => 'blah'\);

doesn't. Class​::Struct simply does

 $r\->\{'field'\} = $init\{'field'\}

but it would be more useful if it did

 $r\->field\($init\{'field'\}\)

Sounds like a valid complaint to me. Example 2 in the docs demonstrates
overriding Class​::Struct accessors and the constructor should follow suit.

Pumpkings, there's a patch with this ticket to fix this.

@p5pRT
Copy link
Author

p5pRT commented Jul 18, 2005

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Aug 31, 2008

From renee.baecker@smart-websolutions.de

Hi,

I've tested the patch by Rhesa Rozendaal and made a unified diff (that
is attached)...

Cheers,
Renee

@p5pRT
Copy link
Author

p5pRT commented Aug 31, 2008

From renee.baecker@smart-websolutions.de

Struct.patch
--- lib/Class/Struct.pm.orig	2008-08-31 11:03:38.000000000 +0200
+++ lib/Class/Struct.pm	2008-08-31 11:11:36.000000000 +0200
@@ -130,6 +130,9 @@
     elsif( $base_type eq 'ARRAY' ){
         $out .= "    my(\$r) = [];\n";
     }
+
+    $out .= " bless \$r, \$class;\n\n";
+
     while( $idx < @decls ){
         $name = $decls[$idx];
         $type = $decls[$idx+1];
@@ -150,24 +153,24 @@
         if( $type eq '@' ){
             $out .= "    croak 'Initializer for $name must be array reference'\n"; 
             $out .= "        if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'ARRAY';\n";
-            $out .= "    \$r->$elem = $init [];$cmt\n"; 
+            $out .= "    \$r->$name( $init [] );$cmt\n"; 
             $arrays{$name}++;
         }
         elsif( $type eq '%' ){
             $out .= "    croak 'Initializer for $name must be hash reference'\n";
             $out .= "        if defined(\$init{'$name'}) && ref(\$init{'$name'}) ne 'HASH';\n";
-            $out .= "    \$r->$elem = $init {};$cmt\n";
+            $out .= "    \$r->$name( $init {} );$cmt\n";
             $hashes{$name}++;
         }
         elsif ( $type eq '$') {
-            $out .= "    \$r->$elem = $init undef;$cmt\n";
+            $out .= "    \$r->$name( $init undef );$cmt\n";
         }
         elsif( $type =~ /^\w+(?:::\w+)*$/ ){
             $out .= "    if (defined(\$init{'$name'})) {\n";
            $out .= "       if (ref \$init{'$name'} eq 'HASH')\n";
-            $out .= "            { \$r->$elem = $type->new(\%{\$init{'$name'}}) } $cmt\n";
+            $out .= "            { \$r->$name( $type->new(\%{\$init{'$name'}}) ) } $cmt\n";
            $out .= "       elsif (UNIVERSAL::isa(\$init{'$name'}, '$type'))\n";
-            $out .= "            { \$r->$elem = \$init{'$name'} } $cmt\n";
+            $out .= "            { \$r->$name( \$init{'$name'} ) } $cmt\n";
             $out .= "       else { croak 'Initializer for $name must be hash or $type reference' }\n";
             $out .= "    }\n";
             $classes{$name} = $type;
@@ -178,7 +181,8 @@
         }
         $idx += 2;
     }
-    $out .= "    bless \$r, \$class;\n  }\n";
+
+    $out .= "\n \$r;\n}\n";
 
     # Create accessor methods.
 

@p5pRT
Copy link
Author

p5pRT commented May 27, 2012

From @Hugmeir

On Sun Aug 31 02​:16​:51 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

I've tested the patch by Rhesa Rozendaal and made a unified diff (that
is attached)...

Cheers,
Renee

Could someone review/apply the patch in this ticket?

--hugmeir

@p5pRT
Copy link
Author

p5pRT commented Jun 9, 2012

From @cpansprout

On Sun May 27 04​:21​:46 2012, Hugmeir wrote​:

On Sun Aug 31 02​:16​:51 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

I've tested the patch by Rhesa Rozendaal and made a unified diff (that
is attached)...

Cheers,
Renee

Could someone review/apply the patch in this ticket?

--hugmeir

It’s not only committers who can review patches. :-)

I’ve never used Class​::Struct before.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jun 9, 2012

From @cpansprout

On Fri Jun 08 20​:34​:30 2012, sprout wrote​:

On Sun May 27 04​:21​:46 2012, Hugmeir wrote​:

On Sun Aug 31 02​:16​:51 2008, renee.baecker@​smart-websolutions.de wrote​:

Hi,

I've tested the patch by Rhesa Rozendaal and made a unified diff (that
is attached)...

Cheers,
Renee

Could someone review/apply the patch in this ticket?

--hugmeir

It’s not only committers who can review patches. :-)

I’ve never used Class​::Struct before.

But I’ve just had a look at the patch anyway, and it looks good, except
it lacks tests.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jun 9, 2012

From mailinglisten@renee-baecker.de

On 09.06.2012 05​:41, Father Chrysostomos via RT wrote​:

But I’ve just had a look at the patch anyway, and it looks good, except
it lacks tests.

Attached is a patch that add two tests...

- Renee

@p5pRT
Copy link
Author

p5pRT commented Jun 9, 2012

From mailinglisten@renee-baecker.de

0001-add-tests-for-overridden-Class-Struct-accessors.patch
From a06895e8db0e5e1a0de2ee2715e5fc1fd5d56de1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renee=20B=C3=A4cker?= <perl@renee-baecker.de>
Date: Sat, 9 Jun 2012 04:17:18 -0700
Subject: [PATCH] add tests for overridden Class::Struct accessors

---
 lib/Class/Struct.t |   26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/lib/Class/Struct.t b/lib/Class/Struct.t
index 694d622..71cdaa3 100644
--- a/lib/Class/Struct.t
+++ b/lib/Class/Struct.t
@@ -33,11 +33,29 @@ package MyOther;
 use Class::Struct s => '$', a => '@', h => '%', c => 'aClass';
 
 #
+# test overriden accessors
+#
+package OverrideAccessor;
+use Class::Struct;
+
+struct( 'OverrideAccessor', { count => '$' } );
+
+sub count {
+  my ($self,$count) = @_;
+
+  if ( @_ >= 2 ) {
+    $self->{'OverrideAccessor::count'} = $count + 9;
+  }
+
+  return $self->{'OverrideAccessor::count'};
+}
+
+#
 # back to main...
 #
 package main;
 
-use Test::More tests => 24;
+use Test::More tests => 26;
 
 my $obj = MyObj->new;
 isa_ok $obj, 'MyObj';
@@ -101,3 +119,9 @@ is $obk->SomeElem(), 123;
 my $recobj = RecClass->new();
 isa_ok $recobj, 'RecClass';
 
+my $override_obj = OverrideAccessor->new( count => 3 );
+is $override_obj->count, 12;
+
+$override_obj->count( 1 );
+is $override_obj->count, 10;
+
-- 
1.7.5.4

@p5pRT
Copy link
Author

p5pRT commented Jun 15, 2012

From @cpansprout

On Sat Jun 09 04​:22​:47 2012, mailinglisten@​renee-baecker.de wrote​:

On 09.06.2012 05​:41, Father Chrysostomos via RT wrote​:

But I’ve just had a look at the patch anyway, and it looks good, except
it lacks tests.

Attached is a patch that add two tests...

Thank you. I have applied the original patch as a79a48c and the tests
as 61dc4ab.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jun 15, 2012

@cpansprout - Status changed from 'open' to 'resolved'

@freonpsandoz
Copy link

I'm using ActiveState Perl 5.20 built 20 July 2015. It has Class::Struct 0.65 and it doesn't seem to have this fix. What version of Class::Struct has this fix, and where can I get it? CPAN shows version 0.66 with no changes since 2001. Thanks.

@iabyn
Copy link
Contributor

iabyn commented May 18, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants