Skip to content

Commit

Permalink
Introduce IO.new(..., path:) and promote File#path to IO#path. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Dec 8, 2022
1 parent b276475 commit 6fd5d2d
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 90 deletions.
1 change: 1 addition & 0 deletions defs/id.def
Expand Up @@ -58,6 +58,7 @@ firstline, predefined = __LINE__+1, %[\
quo
name
nil
path
_ UScore
Expand Down
6 changes: 2 additions & 4 deletions error.c
Expand Up @@ -3024,14 +3024,12 @@ Init_Exception(void)
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
rb_define_method(rb_eSyntaxError, "initialize", syntax_error_initialize, -1);

ID id_path = rb_intern_const("path");

/* the path failed to parse */
rb_attr(rb_eSyntaxError, id_path, TRUE, FALSE, FALSE);
rb_attr(rb_eSyntaxError, idPath, TRUE, FALSE, FALSE);

rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
/* the path failed to load */
rb_attr(rb_eLoadError, id_path, TRUE, FALSE, FALSE);
rb_attr(rb_eLoadError, idPath, TRUE, FALSE, FALSE);

rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);

Expand Down
37 changes: 0 additions & 37 deletions file.c
Expand Up @@ -484,41 +484,6 @@ apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg)
return LONG2FIX(argc);
}

/*
* call-seq:
* path -> filepath
*
* Returns the string filepath used to create +self+:
*
* f = File.new('t.txt') # => #<File:t.txt>
f.path # => "t.txt"
*
* Does not normalize the returned filepath:
*
* f = File.new('../files/t.txt') # => #<File:../files/t.txt>
f.path # => "../files/t.txt"
*
* Raises IOError for a file created using File::Constants::TMPFILE, because it has no filename.
*
* File#to_path is an alias for File#path.
*
*/

static VALUE
rb_file_path(VALUE obj)
{
rb_io_t *fptr;

fptr = RFILE(rb_io_taint_check(obj))->fptr;
rb_io_check_initialized(fptr);

if (NIL_P(fptr->pathv)) {
rb_raise(rb_eIOError, "File is unnamed (TMPFILE?)");
}

return rb_str_dup(fptr->pathv);
}

static size_t
stat_memsize(const void *p)
{
Expand Down Expand Up @@ -7555,8 +7520,6 @@ Init_File(void)
/* Name of the null device */
rb_define_const(rb_mFConst, "NULL", rb_fstring_cstr(ruby_null_device));

rb_define_method(rb_cFile, "path", rb_file_path, 0);
rb_define_method(rb_cFile, "to_path", rb_file_path, 0);
rb_define_global_function("test", rb_f_test, -1);

rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject);
Expand Down
43 changes: 41 additions & 2 deletions io.c
Expand Up @@ -2908,6 +2908,29 @@ rb_io_pid(VALUE io)
return PIDT2NUM(fptr->pid);
}

/*
* call-seq:
* path -> string or nil
*
* Returns the path associated with the IO, or +nil+ if there is no path
* associated with the IO. It is not guaranteed that the path exists on
* the filesystem.
*
* $stdin.path # => "<STDIN>"
*
* File.open("testfile") {|f| f.path} # => "testfile"
*/

static VALUE
rb_io_path(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;

if (!fptr)
return Qnil;

return rb_obj_dup(fptr->pathv);
}

/*
* call-seq:
Expand Down Expand Up @@ -9361,14 +9384,26 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
}
#endif
if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
fmode |= FMODE_PREP;
VALUE path = Qnil;

if (!NIL_P(opt)) {
if (rb_hash_aref(opt, sym_autoclose) == Qfalse) {
fmode |= FMODE_PREP;
}

path = rb_hash_aref(opt, RB_ID2SYM(idPath));
if (!NIL_P(path)) {
StringValue(path);
path = rb_str_new_frozen(path);
}
}

MakeOpenFile(io, fp);
fp->self = io;
fp->fd = fd;
fp->mode = fmode;
fp->encs = convconfig;
fp->pathv = path;
fp->timeout = Qnil;
clear_codeconv(fp);
io_check_tty(fp);
Expand Down Expand Up @@ -15436,6 +15471,10 @@ Init_IO(void)
rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
rb_define_method(rb_cIO, "pid", rb_io_pid, 0);

rb_define_method(rb_cIO, "path", rb_io_path, 0);
rb_define_method(rb_cIO, "to_path", rb_io_path, 0);

rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);

rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
Expand Down
14 changes: 8 additions & 6 deletions spec/ruby/core/file/shared/path.rb
Expand Up @@ -78,13 +78,15 @@
rm_r @dir
end

it "raises IOError if file was opened with File::TMPFILE" do
begin
File.open(@dir, File::RDWR | File::TMPFILE) do |f|
-> { f.send(@method) }.should raise_error(IOError)
ruby_version_is ""..."3.1" do
it "raises IOError if file was opened with File::TMPFILE" do
begin
File.open(@dir, File::RDWR | File::TMPFILE) do |f|
-> { f.send(@method) }.should raise_error(IOError)
end
rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
skip "no support from the filesystem"
end
rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
skip "no support from the filesystem"
end
end
end
Expand Down
11 changes: 11 additions & 0 deletions spec/ruby/core/io/path_spec.rb
@@ -0,0 +1,11 @@
require_relative '../../spec_helper'

describe "IO#path" do
ruby_version_is "3.2" do
it "returns the path of the file associated with the IO object" do
File.open(tmp("io_path.txt"), "w") do |file|
IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path
end
end
end
end
2 changes: 1 addition & 1 deletion test/ruby/test_file.rb
Expand Up @@ -527,7 +527,7 @@ def test_open_tempfile_path
io.write "foo"
io.flush
assert_equal 3, io.size
assert_raise(IOError) { io.path }
assert_nil io.path
ensure
io&.close
end
Expand Down
6 changes: 6 additions & 0 deletions test/ruby/test_io.rb
Expand Up @@ -1639,6 +1639,12 @@ def test_write_nonblock_file
end
end

def test_explicit_path
io = IO.for_fd(0, path: "Fake Path", autoclose: false)
assert_match %r"Fake Path", io.inspect
assert_equal "Fake Path", io.path
end

def test_write_nonblock_simple_no_exceptions
pipe(proc do |w|
w.write_nonblock('1', exception: false)
Expand Down
4 changes: 2 additions & 2 deletions test/zlib/test_zlib.rb
Expand Up @@ -804,10 +804,10 @@ def test_path_tmpfile
io.rewind

gz0 = Zlib::GzipWriter.new(io)
assert_raise(NoMethodError) { gz0.path }
assert_nil gz0.path

gz1 = Zlib::GzipReader.new(io)
assert_raise(NoMethodError) { gz1.path }
assert_nil gz1.path
gz0.close
gz1.close
end
Expand Down
78 changes: 40 additions & 38 deletions yjit/src/cruby_bindings.inc.rs
Expand Up @@ -579,31 +579,32 @@ pub const tFdiv: ruby_method_ids = 223;
pub const tQuo: ruby_method_ids = 224;
pub const tName: ruby_method_ids = 225;
pub const tNil: ruby_method_ids = 226;
pub const tUScore: ruby_method_ids = 227;
pub const tNUMPARAM_1: ruby_method_ids = 228;
pub const tNUMPARAM_2: ruby_method_ids = 229;
pub const tNUMPARAM_3: ruby_method_ids = 230;
pub const tNUMPARAM_4: ruby_method_ids = 231;
pub const tNUMPARAM_5: ruby_method_ids = 232;
pub const tNUMPARAM_6: ruby_method_ids = 233;
pub const tNUMPARAM_7: ruby_method_ids = 234;
pub const tNUMPARAM_8: ruby_method_ids = 235;
pub const tNUMPARAM_9: ruby_method_ids = 236;
pub const tTOKEN_LOCAL_END: ruby_method_ids = 237;
pub const tTOKEN_INSTANCE_BEGIN: ruby_method_ids = 236;
pub const tTOKEN_INSTANCE_END: ruby_method_ids = 237;
pub const tTOKEN_GLOBAL_BEGIN: ruby_method_ids = 236;
pub const tLASTLINE: ruby_method_ids = 237;
pub const tBACKREF: ruby_method_ids = 238;
pub const tERROR_INFO: ruby_method_ids = 239;
pub const tTOKEN_GLOBAL_END: ruby_method_ids = 240;
pub const tTOKEN_CONST_BEGIN: ruby_method_ids = 239;
pub const tTOKEN_CONST_END: ruby_method_ids = 240;
pub const tTOKEN_CLASS_BEGIN: ruby_method_ids = 239;
pub const tTOKEN_CLASS_END: ruby_method_ids = 240;
pub const tTOKEN_ATTRSET_BEGIN: ruby_method_ids = 239;
pub const tTOKEN_ATTRSET_END: ruby_method_ids = 240;
pub const tNEXT_ID: ruby_method_ids = 240;
pub const tPath: ruby_method_ids = 227;
pub const tUScore: ruby_method_ids = 228;
pub const tNUMPARAM_1: ruby_method_ids = 229;
pub const tNUMPARAM_2: ruby_method_ids = 230;
pub const tNUMPARAM_3: ruby_method_ids = 231;
pub const tNUMPARAM_4: ruby_method_ids = 232;
pub const tNUMPARAM_5: ruby_method_ids = 233;
pub const tNUMPARAM_6: ruby_method_ids = 234;
pub const tNUMPARAM_7: ruby_method_ids = 235;
pub const tNUMPARAM_8: ruby_method_ids = 236;
pub const tNUMPARAM_9: ruby_method_ids = 237;
pub const tTOKEN_LOCAL_END: ruby_method_ids = 238;
pub const tTOKEN_INSTANCE_BEGIN: ruby_method_ids = 237;
pub const tTOKEN_INSTANCE_END: ruby_method_ids = 238;
pub const tTOKEN_GLOBAL_BEGIN: ruby_method_ids = 237;
pub const tLASTLINE: ruby_method_ids = 238;
pub const tBACKREF: ruby_method_ids = 239;
pub const tERROR_INFO: ruby_method_ids = 240;
pub const tTOKEN_GLOBAL_END: ruby_method_ids = 241;
pub const tTOKEN_CONST_BEGIN: ruby_method_ids = 240;
pub const tTOKEN_CONST_END: ruby_method_ids = 241;
pub const tTOKEN_CLASS_BEGIN: ruby_method_ids = 240;
pub const tTOKEN_CLASS_END: ruby_method_ids = 241;
pub const tTOKEN_ATTRSET_BEGIN: ruby_method_ids = 240;
pub const tTOKEN_ATTRSET_END: ruby_method_ids = 241;
pub const tNEXT_ID: ruby_method_ids = 241;
pub const idMax: ruby_method_ids = 2721;
pub const idMin: ruby_method_ids = 2737;
pub const idFreeze: ruby_method_ids = 2753;
Expand Down Expand Up @@ -661,19 +662,20 @@ pub const idFdiv: ruby_method_ids = 3569;
pub const idQuo: ruby_method_ids = 3585;
pub const idName: ruby_method_ids = 3601;
pub const idNil: ruby_method_ids = 3617;
pub const idUScore: ruby_method_ids = 3633;
pub const idNUMPARAM_1: ruby_method_ids = 3649;
pub const idNUMPARAM_2: ruby_method_ids = 3665;
pub const idNUMPARAM_3: ruby_method_ids = 3681;
pub const idNUMPARAM_4: ruby_method_ids = 3697;
pub const idNUMPARAM_5: ruby_method_ids = 3713;
pub const idNUMPARAM_6: ruby_method_ids = 3729;
pub const idNUMPARAM_7: ruby_method_ids = 3745;
pub const idNUMPARAM_8: ruby_method_ids = 3761;
pub const idNUMPARAM_9: ruby_method_ids = 3777;
pub const idLASTLINE: ruby_method_ids = 3799;
pub const idBACKREF: ruby_method_ids = 3815;
pub const idERROR_INFO: ruby_method_ids = 3831;
pub const idPath: ruby_method_ids = 3633;
pub const idUScore: ruby_method_ids = 3649;
pub const idNUMPARAM_1: ruby_method_ids = 3665;
pub const idNUMPARAM_2: ruby_method_ids = 3681;
pub const idNUMPARAM_3: ruby_method_ids = 3697;
pub const idNUMPARAM_4: ruby_method_ids = 3713;
pub const idNUMPARAM_5: ruby_method_ids = 3729;
pub const idNUMPARAM_6: ruby_method_ids = 3745;
pub const idNUMPARAM_7: ruby_method_ids = 3761;
pub const idNUMPARAM_8: ruby_method_ids = 3777;
pub const idNUMPARAM_9: ruby_method_ids = 3793;
pub const idLASTLINE: ruby_method_ids = 3815;
pub const idBACKREF: ruby_method_ids = 3831;
pub const idERROR_INFO: ruby_method_ids = 3847;
pub const tLAST_OP_ID: ruby_method_ids = 169;
pub const idLAST_OP_ID: ruby_method_ids = 10;
pub type ruby_method_ids = u32;
Expand Down

0 comments on commit 6fd5d2d

Please sign in to comment.