Skip Menu |

This queue is for tickets about the Class-Accessor CPAN distribution.

Report information
The Basics
Id: 17856
Status: resolved
Priority: 0/
Queue: Class-Accessor

People
Owner: Nobody in particular
Requestors: rrwo [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.22
Fixed in: (no value)



Subject: Accessors have the Class::Accessor namespace according to caller() function
Since the accessors are compiled in Class::Accessor (or Class::Accessor::Fast), the caller() function thinks that the accessors are in Class::Accessor, rather than the class they are in. For normal circumstances, this does not matter. But when the hash used by the class is actually a tied hash uses the namespace for encapsulation restrictions (for example, Class::Tie::InsideOut), then it's broken. The attached patch fixes the problem (though it does not include tests for it). For Class::Accessor::Fast, it sets the local *__ANON__ to refer to the class it's created in. For Class::Accessor, it creates a local version of the set and get methods, unless one is defined in that class. (There are still get/set methods in Class::Accessor for compatability.) The patch also fixes a minor bug where one can use fields named "get" or "set".
Subject: Class-Accessor-0.22.diff
diff -r Class-Accessor-0.22/Changes Class-Accessor-0.22.orig/Changes 1,9d0 < < < - checks for get and set fields < - accessor appears to the caller function that it is in the namespace < that it is defined it, rather than Class::Accessor < < 0.22 < - ? < diff -r Class-Accessor-0.22/lib/Class/Accessor/Fast.pm Class-Accessor-0.22.orig/lib/Class/Accessor/Fast.pm 4c4 < $Class::Accessor::Fast::VERSION = '0.2201'; --- > $Class::Accessor::Fast::VERSION = '0.22'; 38d37 < local *__ANON__ = "${class}::${field}"; 50d48 < local *__ANON__ = "${class}::${field}"; 63d60 < local *__ANON__ = "${class}::${field}"; diff -r Class-Accessor-0.22/lib/Class/Accessor.pm Class-Accessor-0.22.orig/lib/Class/Accessor.pm 4c4 < $Class::Accessor::VERSION = '0.2201'; --- > $Class::Accessor::VERSION = '0.22'; 143a144 > 159,160c160,161 < if( $field =~ m/(DESTROY|get|set)/ ) { < $self->carp("Having a data accessor named '$1' in '$class' is unwise."); --- > if( $field eq 'DESTROY' ) { > $self->carp("Having a data accessor named DESTROY in '$class' is unwise."); 167,170d167 < < *{"${class}::set"} = _make_set($class) unless defined &{"${class}::set"}; < *{"${class}::get"} = _make_get($class) unless defined &{"${class}::get"}; < 269,272c266 < sub _make_set { < my $class = shift; < return sub { < local *__ANON__ = "${class}::set"; --- > sub set { 284d277 < } 298,301c291 < sub _make_get { < my $class = shift; < return sub { < local *__ANON__ = "${class}::get"; --- > sub get { 313,318d302 < } < } < < BEGIN { < *set = _make_set(__PACKAGE__); < *get = _make_get(__PACKAGE__); 338d321 < local *__ANON__ = "${class}::${field}"; 365d347 < local *__ANON__ = "${class}::${field}"; 393d374 < local *__ANON__ = "${class}::${field}";
From: rrwo [...] cpan.org
I forgot to mention that advice how to fix this problem cames from Ovid (Perl Hacks) via Chromatic.
From: rrwo [...] cpan.org
Actually, here's a revised patch. It eliminates the garbage for set/get methods. Those can be defined in class that needs them for encapsulation issues.
diff -r Class-Accessor-0.22/Changes Class-Accessor-0.22.orig/Changes 1,9d0 < < < - checks for get and set fields < - accessor appears to the caller function that it is in the namespace < that it is defined it, rather than Class::Accessor < < 0.22 < - ? < diff -r Class-Accessor-0.22/lib/Class/Accessor/Fast.pm Class-Accessor-0.22.orig/lib/Class/Accessor/Fast.pm 4c4 < $Class::Accessor::Fast::VERSION = '0.2201'; --- > $Class::Accessor::Fast::VERSION = '0.22'; 38d37 < local *__ANON__ = "${class}::${field}"; 50d48 < local *__ANON__ = "${class}::${field}"; 63d60 < local *__ANON__ = "${class}::${field}"; diff -r Class-Accessor-0.22/lib/Class/Accessor.pm Class-Accessor-0.22.orig/lib/Class/Accessor.pm 4c4 < $Class::Accessor::VERSION = '0.2202'; --- > $Class::Accessor::VERSION = '0.22'; 143a144 > 159,160c160,161 < if( $field =~ m/(DESTROY|get|set)/ ) { < $self->carp("Having a data accessor named '$1' in '$class' is unwise."); --- > if( $field eq 'DESTROY' ) { > $self->carp("Having a data accessor named DESTROY in '$class' is unwise."); 338d321 < local *__ANON__ = "${class}::${field}"; 365d347 < local *__ANON__ = "${class}::${field}"; 393d374 < local *__ANON__ = "${class}::${field}";
As of version 0.33, if you have the Sub::Name module installed then this problem is fixed. -- Marty