Bug #19238
closedURI.open fails for file path when second argument is a hash
Description
I upgraded one of my projects to ruby 3.1.3 and I found that URI.open
now throws an error when passed a second argument when the first argument is a file path.
When the first argument is a URL, then URI.open will work as expected.
I was able to replicate this issue in all 3.x versions including the latest so it's an issue that was introduce with the release of 3.0
I found it convenient that URI.open(uri, {})
, worked regardless of wether uri was a file path or a URL because it meant I did not have to add logic for varying cases. When the uri argument was a file path URI.open would simply open up the file and disregard the hash options params. But now I have to add that logic myself which is not as clean looking.
Below is an example of the error. It's quite easy to reproduce on any version of ruby 3.x
URI.open("spec/fixtures/blogs.json", {})
/Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/open-uri.rb:31:in `initialize': no implicit conversion of Hash into String (TypeError)
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/open-uri.rb:31:in `open'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/open-uri.rb:31:in `open'
from (irb):9:in `<main>'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
from /Users/dkinzer/.rbenv/versions/3.1.3/bin/irb:25:in `load'
from /Users/dkinzer/.rbenv/versions/3.1.3/bin/irb:25:in `<top (required)>'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/cli/exec.rb:58:in `load'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/cli/exec.rb:58:in `kernel_load'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/cli/exec.rb:23:in `run'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/cli.rb:486:in `exec'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/cli.rb:31:in `dispatch'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
from /Users/dkinzer/.rbenv/versions/3.1.3/lib/ruby/3.1.0/bundler/cli.rb:25:in `start'
... 5 levels...
Updated by alanwu (Alan Wu) over 2 years ago
With a path, URI.open
delegates to Kernel#open
and in turn to
File#open
, who has keyword parameters. URI.open
only has rest parameters
and this mismatch along with the recent change to use super
for delegation
seems to be the source of the error.
In 2.7, open-uri
used a splat to delegate and it issued a deprecation message:
/opt/wandbox/ruby-2.7.3/lib/ruby/2.7.0/open-uri.rb:52: warning: Using the last argument as keyword parameters is deprecated
/opt/wandbox/ruby-2.7.3/lib/ruby/2.7.0/open-uri.rb:52:in `initialize': No such file or directory @ rb_sysopen - spec/fixtures/blogs.json (Errno::ENOENT)
from /opt/wandbox/ruby-2.7.3/lib/ruby/2.7.0/open-uri.rb:52:in `open'
from /opt/wandbox/ruby-2.7.3/lib/ruby/2.7.0/open-uri.rb:52:in `open'
from prog.rb:2:in `<main>'
Maybe URI.open(path_or_uri, **{})
is a viable workaround? Seems to work
fine for both paths and URIs on 3.1.
We can consider tweaking the delegation on the open-uri
side.
Updated by jeremyevans0 (Jeremy Evans) almost 2 years ago
This is a bug in URI.open
. It can be fixed by using ruby2_keywords
. I submitted a pull request to fix it: https://github.com/ruby/open-uri/pull/24
Updated by jeremyevans (Jeremy Evans) over 1 year ago
- Status changed from Open to Closed
Applied in changeset git|43c2c1ed4814c6e1f0d0d0ec88641e12bf5aa290.
[ruby/open-uri] Make URI.open pass keywords
Fixes [Bug #19238]