Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

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

Maintainer(s)' notes

I prefer that bugs & patches are filed on GitHub rather than on RT: https://github.com/kenahoo/Path-Class/issues. Thanks.

Report information
The Basics
Id: 27710
Status: resolved
Priority: 0/
Queue: Path-Class

People
Owner: Nobody in particular
Requestors: rt-cpan [...] trout.me.uk
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Would you be interested in a patch to make classes configurable to aid subclassing?
I'm rather fond of Path::Class but I occasionally find myself wanting to subclass it to provide some extra functionality - however, if I subclass I'll still get Path::Class::File / Path::Class::Dir objects back from some of the methods. Would you be willing to accept a patch to make those classes defaults that can be overidden by subclasses?
Looks like the big offenders are Path::Class::File->new(), Path::Class::File->dir(), and Path::Class::Dir->file(), right? Yeah, we should find a way to get those hard-coded class names out of there. There are probably lots of ways to accomplish it, want to suggest one? -Ken
Subject: Re: [rt.cpan.org #27710] Would you be interested in a patch to make classes configurable to aid subclassing?
Date: Tue, 17 Jul 2007 23:17:56 +0100
To: Ken_Williams via RT <bug-Path-Class [...] rt.cpan.org>
From: Matt S Trout <mst [...] shadowcatsystems.co.uk>
On Sun, Jun 24, 2007 at 11:27:45PM -0400, Ken_Williams via RT wrote: Show quoted text
> > <URL: http://rt.cpan.org/Ticket/Display.html?id=27710 > > > Looks like the big offenders are Path::Class::File->new(), > Path::Class::File->dir(), and Path::Class::Dir->file(), right? Yeah, we > should find a way to get those hard-coded class names out of there. > > There are probably lots of ways to accomplish it, want to suggest one?
sub _build_file_object { my ($self, $args) = @_; $self->_file_object_class->new($args); } sub _file_object_class { 'Path::Class::File' } etc. is roughly the way I tend to do it by default. I don't know if you'd prefer those methods to be non-_ though - I'm tending towards _ for 'protected' i.e. subclassable but not meant for external calling and "my $private = sub {" for "DO NOT SUBCLASS THIS", but it's your module so you get to pick the coding conventions :) -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Director Want a managed development or deployment platform? Shadowcat Systems Ltd. Contact mst (at) shadowcatsystems.co.uk for a quote http://chainsawblues.vox.com/ http://www.shadowcatsystems.co.uk/
From: jloverso [...] mathworks.com
Show quoted text
> sub _build_file_object { > my ($self, $args) = @_; > $self->_file_object_class->new($args); > } > > sub _file_object_class { 'Path::Class::File' }
I've looking at Path::Class to replace a homegrown equivalent, and this is one item I had (since I am subclassing the classes). This change is trivial - please consider incorporating it. (Presumably you'll just add file_object_class and dir_object_class to Path::Class::Entity, and then use that everywhere)
Subject: Re: [rt.cpan.org #27710] Would you be interested in a patch to make classes configurable to aid subclassing?
Date: Mon, 8 Dec 2008 17:32:13 +0000
To: John LoVerso via RT <bug-Path-Class [...] rt.cpan.org>
From: Matt S Trout <mst [...] shadowcat.co.uk>
On Sun, Dec 07, 2008 at 01:32:12PM -0500, John LoVerso via RT wrote: Show quoted text
> <URL: http://rt.cpan.org/Ticket/Display.html?id=27710 > >
> > sub _build_file_object { > > my ($self, $args) = @_; > > $self->_file_object_class->new($args); > > } > > > > sub _file_object_class { 'Path::Class::File' }
> > I've looking at Path::Class to replace a homegrown equivalent, and this > is one item I had (since I am subclassing the classes). This change is > trivial - please consider incorporating it. > > (Presumably you'll just add file_object_class and dir_object_class to > Path::Class::Entity, and then use that everywhere)
Well, I believe the author said he'd take the patch, it's just I never got time to write it. Maybe you could have a go? -- Matt S Trout Need help with your Catalyst or DBIx::Class project? Technical Director http://www.shadowcat.co.uk/catalyst/ Shadowcat Systems Ltd. Want a managed development or deployment platform? http://chainsawblues.vox.com/ http://www.shadowcat.co.uk/servers/
Attached is a simple patch to add dir_class() to Path::Class::File and file_class to Path::Class::Dir along with a simple test. I decided on a public method rather than messing around with "protected" because I never thought it was worth it. YMMV.
Subject: 0001-Make-Path-Class-subclassable.patch
From 522fba05005e901a29a95b4b5d84c97712399379 Mon Sep 17 00:00:00 2001 From: Michael G. Schwern <schwern@pobox.com> Date: Sat, 23 Jan 2010 18:50:36 -0800 Subject: [PATCH] Make Path::Class subclassable. --- lib/Path/Class/Dir.pm | 13 +++++++++++-- lib/Path/Class/File.pm | 15 ++++++++++++--- t/subclass.t | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 t/subclass.t diff --git a/lib/Path/Class/Dir.pm b/lib/Path/Class/Dir.pm index 6e365f1..ff90fa2 100644 --- a/lib/Path/Class/Dir.pm +++ b/lib/Path/Class/Dir.pm @@ -4,7 +4,6 @@ $VERSION = '0.18'; use strict; use Path::Class::File; -use Path::Class::Entity; use Carp(); use base qw(Path::Class::Entity); @@ -38,6 +37,10 @@ sub new { return $self; } +sub file_class { + return "Path::Class::File"; +} + sub is_dir { 1 } sub as_foreign { @@ -67,7 +70,7 @@ sub volume { shift()->{volume} } sub file { local $Path::Class::Foreign = $_[0]->{file_spec_class} if $_[0]->{file_spec_class}; - return Path::Class::File->new(@_); + return $_[0]->file_class->new(@_); } sub dir_list { @@ -633,6 +636,12 @@ C<File::stat> object representing the result. Same as C<stat()>, but if C<$file> is a symbolic link, C<lstat()> stats the link instead of the directory the link points to. +=item $class = $file->file_class() + +Returns the class which should be used to create file objects. + +Generally overriden by subclasses. + =back =head1 AUTHOR diff --git a/lib/Path/Class/File.pm b/lib/Path/Class/File.pm index 8c5bdd5..0750927 100644 --- a/lib/Path/Class/File.pm +++ b/lib/Path/Class/File.pm @@ -4,7 +4,6 @@ $VERSION = '0.18'; use strict; use Path::Class::Dir; -use Path::Class::Entity; use base qw(Path::Class::Entity); use IO::File (); @@ -20,12 +19,16 @@ sub new { push @dirs, $self->_spec->catpath($volume, $dirs, ''); } - $self->{dir} = @dirs ? Path::Class::Dir->new(@dirs) : undef; + $self->{dir} = @dirs ? $self->dir_class->new(@dirs) : undef; $self->{file} = $base; return $self; } +sub dir_class { + return "Path::Class::Dir"; +} + sub as_foreign { my ($self, $type) = @_; local $Path::Class::Foreign = $self->_spec_class($type); @@ -44,7 +47,7 @@ sub stringify { sub dir { my $self = shift; return $self->{dir} if defined $self->{dir}; - return Path::Class::Dir->new($self->_spec->curdir); + return $self->dir_class->new($self->_spec->curdir); } BEGIN { *parent = \&dir; } @@ -317,6 +320,12 @@ C<File::stat> object representing the result. Same as C<stat()>, but if C<$file> is a symbolic link, C<lstat()> stats the link instead of the file the link points to. +=item $class = $file->dir_class() + +Returns the class which should be used to create directory objects. + +Generally overriden by subclasses. + =back =head1 AUTHOR diff --git a/t/subclass.t b/t/subclass.t new file mode 100644 index 0000000..fcd3cc1 --- /dev/null +++ b/t/subclass.t @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +# Test subclassing of Path::Class + +use strict; +use warnings; + +use Test::More tests => 6; + +{ + package My::File; + use base qw(Path::Class::File); + + sub dir_class { return "My::Dir" } +} + +{ + package My::Dir; + use base qw(Path::Class::Dir); + + sub file_class { return "My::File" } +} + +{ + my $file = My::File->new("/path/to/some/file"); + isa_ok $file, "My::File"; + is $file->as_foreign("Unix"), "/path/to/some/file"; + + my $dir = $file->dir; + isa_ok $dir, "My::Dir"; + is $dir->as_foreign("Unix"), "/path/to/some"; + + my $file_again = $dir->file("bar"); + isa_ok $file_again, "My::File"; + is $file_again->as_foreign("Unix"), "/path/to/some/bar"; +} -- 1.6.6.1
Thanks, applied with a few style changes. -Ken