Hello all,
I've run into a behavior with autoload and $LOAD_PATH that is
inconsistent
across Ruby versions and implementations, and would like clarification
on what
the correct behavior should be.
Consider the two source files below:
(root)/foo.rb
-------------
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) +
'/./foo')
module Foo
autoload :Bar, 'bar'
end
Foo::Bar
(root)/foo/bar.rb
-----------------
module Foo; class Bar; end; end
An executable, expanded version of this example, along with some
annotations, is
available at https://github.com/yipdw/autoload-testcase.
The above code will unshift a path resembling /a/./foo into $LOAD_PATH.
This
path is absolute -- it addresses an unambiguous location in the
filesystem --
but it is not expanded.
This example is a bit silly, but this can happen in less contrived
situations,
such as loading libraries using
File.join(File.dirname(__FILE__), '../a/b')
.
(I know that File.join(File.dirname(__FILE__), ...) has issues, but that
doesn't
mean it's illegal Ruby code.)
Here are run results for the autoload-testcase example under a variety
of Ruby
implementations and versions[*]:
| Implementation | Result |
+--------------------------------------+-------------------+
| Ruby 1.8.7-p330 | resolves Foo::Bar |
| Ruby 1.9.2-p0 | raises NameError |
| Ruby 1.9.2-p136 | raises NameError |
| Rubinius 1.2.0 | resolves Foo::Bar |
| JRuby 1.5.6, 1.8 compatibility mode | resolves Foo::Bar |
| JRuby 1.5.6, 1.9 compatibility mode | resolves Foo::Bar |
A run log is available in the autoload-testcase repository.
So I guess my question can be stated as: does it make sense to permit
absolute
paths having . and .. in $LOAD_PATH?
$LOAD_PATH can already contain relative paths; additionally, . and ..
are
properly expanded for relative paths. Furthermore, most shells will
expand .
and .. in absolute paths. Therefore, I think the answer is "yes", but I
would
like input on this, especially as I haven't seen this issue raised
anywhere
else. (If it has been raised before, please let me know that, too.)
Thanks,
- David
---
[*] The exceptions thrown by Ruby 1.9.2-p0 and 1.9.2-p136 appear to be
triggered
in part by the algorithm of rb_get_expanded_load_path(void).
In r30603 (latest revision as of this writing) the following is present
in
rb_get_expanded_load_path at load.c:51-66:
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
VALUE str = rb_check_string_type(RARRAY_PTR(load_path)[i]);
if (NIL_P(str) || !rb_is_absolute_path(RSTRING_PTR(str)))
goto relative_path_found;
}
return load_path;
relative_path_found:
ary = rb_ary_new2(RARRAY_LEN(load_path));
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
VALUE path = rb_file_expand_path(RARRAY_PTR(load_path)[i],
Qnil);
rb_str_freeze(path);
rb_ary_push(ary, path);
}
rb_obj_freeze(ary);
return ary;
On non-DOSISH systems, rb_is_absolute_path expands to
int
rb_is_absolute_path(const char *path)
{
if (path[0] == '/') return 1;
return 0;
}
Therefore, if there are no paths present in $LOAD_PATH for which
rb_is_absolute_path returns false, paths such as /a/./b will not be
expanded to
/a/b by rb_get_expanded_load_path. I haven't yet studied the code long
enough
to precisely figure out how that behavior interacts with the autoload
mechanism
and produces the name resolution failure, but it does seem to play a
major role.
on 2011-01-19 10:21
on 2011-03-03 15:08
Ouch, ouch, ouch:
I was beginning to doubt my sanity until I stumbled across this post.
My Rspec (2.5.1) example was failing with
uninitialized constant B3::Bdd::Helpers (NameError)
Then, in spec_helper.rb I replaced
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
with
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__),
'..', 'lib')))
And things worked again.
Is this an acknowledged bug/issue or am I doing something illegal?
on 2011-03-10 00:32
> So I guess my question can be stated as: does it make sense to permit absolute > paths having . and .. in $LOAD_PATH? I think so. I'm thinking it's a bug, unless other disagree? -r
on 2011-03-10 06:04
On Wed, Mar 9, 2011 at 6:32 PM, Roger Pack <rogerdpack2@gmail.com>
wrote:
> I think so. I'm thinking it's a bug, unless other disagree?
This is in the backport queue. http://redmine.ruby-lang.org/issues/4446
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.