Re: Is it ever legitimate to override $^O ?
by kcott (Archbishop) on Aug 02, 2022 at 07:43 UTC
|
G'day Rob,
I was curious about this, so I did a little digging.
I don't have a v5.34.0 on MSWin available so I can't do any direct testing.
"Try building Path::Class on Windows and watch it pass ..."
In the "mswin32" column of the "CPAN Testers Matrix: Path-Class 0.37",
there are only passes from v5.12.2 to v5.29.3 then, a lone test for v5.34.0 which failed
(see "Report for Path-Class-0.37").
The problem here is very similar to what you report for 'make test':
Output from 'C:\perl-5.34.0\bin\perl.exe ./Build test':
Can't call method "relative" on an undefined value at C:\Users\jndt\Ap
+pData\Local\.cpan\build\Path-Class-0.37-0\blib\lib/Path/Class/Entity.
+pm line 71.
t/01-basic.t ..........
Dubious, test returned 22 (wstat 5632, 0x1600)
Failed 28/78 subtests
The line numbers are different: 71 (here) vs. 76 (yours) — I don't know if that's significant.
The distribution provides both a Makefile.PL and a Build.PL.
The INSTALL file only references
perl Build.PL followed by various ./Build commands (no make anywhere).
I had a look at a few reports, all had ./Build test — again, I don't know if that's significant.
The last update to Path-Class was six years ago (2016).
So, it would seem more likely the "bug" is due to a Perl change
(v5.34.0 was released in 2021, a little over a year ago)
or something in Strawberry/ActivePerl/etc.
I don't know if any of that helps.
Maybe some avenues for further investigation.
I've no idea if overriding $^O is legitimate.
I had a think about it but drew a blank.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
The problem here is very similar to what you report for 'make test'
Yes - that's the issue.
On MS Windows, be it Windows 7 & mingw-built perl-5.34.0 (as in my case), or Windows 10 & MSVC-built (as in the testers matrix), the overriding of $^O generates that error.
The line numbers are different: 71 (here) vs. 76 (yours) — I don't know if that's significant.
In earlier attempts to work out what was going on, I had inserted some debug statements into Entity.pm.
I then commented out those statements - thereby leaving the code in its original state, but altering the line numbers.
So it's not significant, and I'm sorry for the confusion.
I believe it's only Windows that's being affected by this.
The distribution provides both a Makefile.PL and a Build.PL. The INSTALL file only references perl Build.PL followed by various ./Build commands (no make anywhere). I had a look at a few reports, all had ./Build test — again, I don't know if that's significant.
I don't think there's anything significant in that.
It makes no difference whether the module is built using Module::Build or ExtUtils::MakeMaker. The behaviour is still the same.
If cpan/cpanm/cpanp is invoked to do the building, then I think M::B will be used.
When I build manually from source, I use EU::MM as that's my preference.
Because Strawberry Perl have not yet released a perl later than 5.32.1, there aren't many Windows perls in the wild that are at version 5.34 or later.
I build my own perls and test them regularly, but I haven't been testing their capabilities to build Path::Class because that module has never interested me.
Having recently become aware of this problem, I'm unsure as to where it should be reported.
Maybe I should just open a perl Issue and ask there - but I wanted to first draw on any wisdom that exists here.
Cheers, Rob
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
Re: Is it ever legitimate to override $^O ?
by Discipulus (Canon) on Aug 02, 2022 at 07:47 UTC
|
Hello syphilis,
no clues by me, only other doubts..
In the very first place I dont understand why a module aimed to help with path and filenames plays so dirty on testing, faking a Unix mode
Second, as I dont have any strawberry available newer than 5.32 I played a bit with the t/01-basic.t and I discovered it fails in the same way even with this modified part:
use Config;
BEGIN {
#$^O = 'Unix'; # Test in Unix mode
$Config{'osname'} = 'Unix';
warn "DEBUG: config: ",$Config{'osname'}," -- \$^O: $^O\n";
}
So $Config{'osname'} and $^O are indipendent and the above code is only influenced by $^O.
In perlvar I read: $^O .. The value is identical to $Config{'osname'}. They are identical but not bound.
Infact the module you are talking about rely on the core module File::Spec (..yes, boring to use but works very well) and it simply inspect $^O as you can see. And yes you can also try $^O = ''; to fake the Unix mode.
With my poor understanding I can find nothing in perldelta about osname nor about $^O
As last doubt I have noting at Entity.pm line 76. ..merely a blank line after the sub resolve ending.
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
So $Config{'osname'} and $^O are independent and the above code is only influenced by $^O.
Yes - initially $Config{osname} and $^O are identical. But $^O can be altered (is writeable) whereas $Config{osname} is permanently set in stone and attempting to assign a value to it should be a fatal compile-time error.
And yes you can also try $^O = ''; to fake the Unix mode.
I didn't know that. So I tried specifying $^O = ''; in t/01-basic.t but it didn't help wrt perl-5.34.0 and later :-(
As last doubt I have noting at Entity.pm line 76. ..merely a blank line after the sub resolve ending
Yeah - it should be line 71 (I think).
As I've (now) noted elsewhere in this thread, I made changes (comments) in Entity.pm that did not alter the code but did bugger up the line numbering. Sorry 'bout that.
Cheers, Rob
| [reply] [Watch: Dir/Any] [d/l] |
|
perl -MConfig -wE "say $Config{'osname'}; $Config{'osname'} = 'Unix';
+say $Config{'osname'}"
MSWin32
Unix
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [Watch: Dir/Any] [d/l] |
|
Re: Is it ever legitimate to override $^O ?
by kcott (Archbishop) on Aug 02, 2022 at 22:44 UTC
|
| [reply] [Watch: Dir/Any] |
Re: Is it ever legitimate to override $^O ? -- Cwd and File::Spec
by Discipulus (Canon) on Aug 03, 2022 at 07:59 UTC
|
Hello again syphilis,
some steps backward? Can this $^O be only some smoke in our eyes? t/01-basic.t .......... 1/78 Can't call method "relative" on an undefined value ...lets start again from this point:
# https://metacpan.org/release/KWILLIAMS/Path-Class-0.37/source/lib/Pa
+th/Class/Entity.pm#L65
sub resolve {
my $self = shift;
Carp::croak($! . " $self") unless -e $self; # No such file or direc
+tory
my $cleaned = $self->new( scalar Cwd::realpath($self->stringify) );
# realpath() always returns absolute path, kind of annoying
$cleaned = $cleaned->relative if $self->is_relative;
+ # line 71 (76 in your modified version)
%$self = %$cleaned;
return $self;
}
So $cleaned is undefined at line 71 and it should be initialized in the line my $cleaned = $self->new( scalar Cwd::realpath($self->stringify) ); so going backward I'd verify:
- $self->stringify
- Cwd::realpath($self->stringify) ) # first charged in my opinion
- $self->new( scalar Cwd::realpath($self->stringify) );
So, maybe, the problem is not at all with Path::Class nor with (or maybe yes..) with assignement to $0 but within Cwd or File::Spec as they are heavily used in the background.
I mean: I tried to track back Cwd::realpath and this module also use $^O to decide what to do.
I'd also investigate which version of Cwd and File::Spec come with your testing distros of Perl.
As last point (maybe due to a dumb moment): the failing test is the first one: there are 78 tests and I checked them... the first one is.... ok(1) O_O is this one failing?!?
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Yes - I had started off by checking most of those things. (That was how line 71 became line 76 ;-)
Everything looked fine, except that $cleaned was not defined.
It was actually quite some time before I looked at the test script itself and noticed the $^O override.
File/Spec.pm contains very little code - and it certainly seems to be inviting this override that t/01-basic.t uses.
So I decided to investigate some basic behaviour of File::Spec, without any reference to Path::Class. I used this script:
# fake_os.pl
BEGIN {
$^O = 'Unix';
}
use strict;
use warnings;
use File::Spec;
my $x = File::Spec->catfile('a', 'b', 'c');
print $x;
I find that on both perl-5.32 and 5.34, this script outputs 'a/b/c' as expected.
If I comment out the BEGIN block, then the script outputs 'a\b\c' as expected - on both perl-5.32 and perl-5.34.
What is odd is that if I simply load Test::Harness, then on both perl-5.32 and 5.34 I always get 'a\b\c' even when the BEGIN block is included:
C:\_32\pscrpt\file-spec>perl fake_os.pl
a/b/c
C:\_32\pscrpt\file-spec>perl -MTest::Harness fake_os.pl
a\b\c
I think that demonstrates that there might be some fragility around overriding $^O, though it doesn't really explain much about the behaviour of t/01-basic.t.
I think it's a pity that File::Spec invites users to mess with the path formatting by fiddling with $^O.
Surely it would be better if there was a function to call or an environment variable to set ... or something else that doesn't involve fiddling with $^O.
I think I might just file bug reports against both perl (based on the demo of the Test::Harness interference) and Path::Class ... and see where it all ends up.
I've just tried my fake_os.pl on Ubuntu with $^O = 'Win32'; and it just ignores that and gives the Unix style 'a/b/c' (on both perl-5.32 and 5.36).(I think that's intended behaviour.)
I totally buggered that up. I can get Win32 path formatting with fake_os.pl on Ubuntu if I specify $^O = 'MSWin32' .
Again, it doesn't work if the Test::Harness is loaded.
I think I'm just fiddling about with a heap of rubbish ...
Update: Forgot to mention that I did hack File::Spec on Windows perl-5.34 such that 'Unix' was hard coded in, and $^O didn't need to be altered. In that case the t/01-basic.t script ran fine and passed all tests.
To me, that shows that the problem with t/01-basic.t is not that 'Unix' formatting is being selected - it's because $^O is being messed with.
I'll post again with links to relevant bug reports once they have been filed.
Thanks for the interest that has been shown.
Cheers, Rob
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
C:>cat fakeOS.pl
BEGIN {
$^O = 'Unix';
}
use strict;
use warnings;
use Cwd 'abs_path';
my $abs_path = abs_path('.');
print $abs_path;
C:>perl fakeOS.pl
C:\EX_D\ulisseDUE
C:>perl -MTest::Harness fakeOS.pl
C:/EX_D/ulisseDUE
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
Re: Is it ever legitimate to override $^O ?
by Anonymous Monk on Aug 02, 2022 at 07:44 UTC
|
| [reply] [Watch: Dir/Any] |
|
It's a terrible hack.
I think that was my reaction, too.
The question is "Having worked in perl-5.32.x and earlier, should this hack be expected to continue working in 5.34.x and onwards ?"
I don't know the answer ... but maybe we should just work on rewriting t/01-basic.t such that the hack is not needed.
BTW, thanks for pointing out the part that File::Spec plays in this.
Cheers, Rob
| [reply] [Watch: Dir/Any] |
Re: Is it ever legitimate to override $^O ?
by davies (Prior) on Aug 08, 2022 at 22:18 UTC
|
If it's not legitimate, how should I have written the test & code below?
use strict;
use warnings;
use Test::More;
use FindBin qw( $RealBin );
use lib $RealBin;
use MyModule;
if (connected()) {
pass("\"connected\" works with defaults ($^O)");
} else {
plan skip_all => 'Internet inaccessible';
}
my $careto = $^O;
if ($careto =~ /win/gmsi) {
$^O = 'linux';
} else {
$^O = 'win';
}
ok !connected(), "\"connected\" fails with defaults overwritten ($^O)"
or diag("\"connected\" returns true regardless (OS = $^O)");
$^O = $careto;
done_testing;
SSCCE (I hope!) from the module:
Package MyModule;
use strict;
use warnings;
sub connected {
my $pingcmd = 'ping -c 1 8.8.8.8';
my $pingworks = ' 0% packet loss';
if ($^O =~ /win/gmsi) {
$pingcmd =~ s/-c/\/n/;
$pingworks = 'bytes=32';
}
my $pingrtn = qx($pingcmd);
return $pingrtn =~ /$pingworks/msi;
}
1;
I accept this may be an ugly hack, but it tests what I want in a way that seems obvious to me. But I will gladly accept improvements, advice and explanations.
Regards,
John Davies
Almost immediate update: deleted a couple of relic lines | [reply] [Watch: Dir/Any] [d/l] [select] |
|
sub connected_win32 { ... }
sub connected_linux { ... }
Poking at global vars is no api | [reply] [Watch: Dir/Any] [d/l] |