ml.ruby-lang.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

ruby-core

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
ruby-core@ml.ruby-lang.org

October 2024

  • 6 participants
  • 205 discussions
[ruby-core:119451] [Ruby master Feature#15554] warn/error passing a block to a method which never use a block
by byroot (Jean Boussier) 04 Oct '24

04 Oct '24
Issue #15554 has been updated by byroot (Jean Boussier). "strict" works I suppose. What we really want to convey is that this group of warnings is more likely to have false positives. ---------------------------------------- Feature #15554: warn/error passing a block to a method which never use a block https://bugs.ruby-lang.org/issues/15554#change-110071 * Author: ko1 (Koichi Sasada) * Status: Assigned * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- # Abstract Warn or raise an ArgumentError if block is passed to a method which does not use a block. In other words, detect "block user methods" implicitly and only "block user methods" can accept a block. # Background Sometimes, we pass a block to a method which ignores the passed block accidentally. ``` def my_open(name) open(name) end # user hopes it works as Kernel#open which invokes a block with opened file. my_open(name){|f| important_work_with f } # but simply ignored... ``` To solve this issue, this feature request propose showing warnings or raising an exception on such case. Last developer's meeting, matz proposed `&nil` which declares this method never receive a block. It is explicit, but it is tough to add this `&nil` parameter declaration to all of methods (do you want to add it to `def []=(i, e, &nil)`?). (I agree `&nil` is valuable on some situations) # Spec ## Define "use a block" methods We need to define which method accepts a block and which method does not. * (1) method has a block parameter (`&b`) * (2) method body has `yield' * (3) method body has `super` (ZSUPER in internal terminology) or `super(...)` * (4) method body has singleton method (optional) (1) and (2) is very clear. I need to explain about (3) and (4). (3). `super` (ZSUPER) passes all parameters as arguments. So there is no surprise that which can accept `block`. However `super(...)` also passes a block if no explicit block passing (like `super(){}` or `super(&b)`) are written. I'm not sure we need to continue this strange specification, but to keep compatibility depending this spec, I add this rule. (4). surprisingly, the following code invoke a block: ``` def foo class << Object.new yield end end foo{ p :ok } #=> :ok ``` I'm also not sure we need to keep this spec, but to allow this spec, I added (4) rule. Strictly speaking, it is not required, but we don't keep the link from singleton class ISeq to lexical parent iseq now, so I added it. ## Exceptional cases A method called by `super` doesn`t warn warning even if this method doesn't use a block. The rule (3) can pass blocks easily and there are many methods don`t use a block. So my patch ignores callings by `super`. ## corner cases There are several cases to use block without (1)-(4) rules. ### `Proc.new/proc/lambda` without a block Now it was deprecated in r66772 (commit:9f1fb0a17febc59356d58cef5e98db61a3c03550). Related discussion: [Bug #15539] ### `block_given?` `block_given?` expects block, but I believe we use it with `yield` or a block parameter. If you know the usecase without them, please tell us. ### `yield` in `eval` We can't know `yield` (or (3), (4) rule) in an `eval` evaluating string at calling time. ``` def foo eval('yield`) end foo{} # at calling time, # we can't know the method foo can accept a block or not. ``` So I added a warning to use `yield` in `eval` like that: `test.rb:4: warning: use yield in eval will not be supported in Ruby 3.` Workaround is use a block parameter explicitly. ``` def foo &b eval('b.call') end foo{ p :ok } ``` # Implementation Strategy is: * [compile time] introduce `iseq::has_yield` field and check it if the iseq (or child iseq) contains `yield` (or something) * [calling time] if block is given, check `iseq::has_yield` flag and show warning (or raise an exception) https://gist.github.com/ko1/c9148ad0224bf5befa3cc76ed2220c0b On this patch, now it raises an error to make it easy to detect. It is easy to switch to show the warning. # Evaluation and discussion I tried to avoid ruby's tests. https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786 Here is a patch. There are several patterns to avoid warnings. ## tests for `block_given?`, `Proc.new` (and similar) without block Add a dummy block parameter. It is test-specific issue. ## empty `each` Some tests add `each` methods do not `yield`, like: `def each; end`. Maybe test-specific issue, and adding a dummy block parameter. ## Subtyping / duck typing https://github.com/ruby/ruby/blob/c01a5ee85e2d6a7128cccafb143bfa694284ca87/… This `parse` method doesn't use `yield`, but other sub-type's `parse` methods use. ## `super` with `new` method https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-pat… This method override `Class#new` method and introduce a hook with block (yield a block in this hook code). https://github.com/ruby/ruby/blob/trunk/lib/rubygems/package/tar_writer.rb#… In this method, call `super` and it also passing a block. However, called `initialize` doesn't use a block. ## Change robustness This change reduce robustness for API change. `Delegator` requires to support `__getobj__` for client classes. Now `__getobj__` should accept block but most of `__getobj__` clients do not call given block. https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L80 This is because of delegator.rb's API change. https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-pat… Nobu says calling block is not required (ignoring a block is no problem) so it is not a bug for delegator client classes. ## Found issues. ``` [ 2945/20449] Rinda::TestRingServer#test_do_reply = 0.00 s 1) Error: Rinda::TestRingServer#test_do_reply: ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used. /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:635:in `test_do_reply' [ 2946/20449] Rinda::TestRingServer#test_do_reply_local = 0.00 s 2) Error: Rinda::TestRingServer#test_do_reply_local: ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used. /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:657:in `test_do_reply_local' [10024/20449] TestGemRequestSetGemDependencyAPI#test_platform_mswin = 0.01 s 3) Error: TestGemRequestSetGemDependencyAPI#test_platform_mswin: ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used. /home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:655:in `test_platform_mswin' [10025/20449] TestGemRequestSetGemDependencyAPI#test_platforms = 0.01 s 4) Error: TestGemRequestSetGemDependencyAPI#test_platforms: ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used. /home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:711:in `test_platforms' ``` These 4 detection show the problem. `with_timeout` method (used in Rinda test) and `util_set_arch` method (used in Rubygems test) simply ignore the given block. So these tests are simply ignored. I reported them. (https://github.com/rubygems/rubygems/issues/2601) ## raise an error or show a warning? At least, Ruby 2.7 should show warning for this kind of violation with `-w`. How about for Ruby3? -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:119449] [Ruby master Feature#15554] warn/error passing a block to a method which never use a block
by matz (Yukihiro Matsumoto) 04 Oct '24

04 Oct '24
Issue #15554 has been updated by matz (Yukihiro Matsumoto). I don' like the term "pedantic" either. How about "strict"? I mean `--warn-strict-unused-block` or `Waning[:strict_unused_block]`. Matz. ---------------------------------------- Feature #15554: warn/error passing a block to a method which never use a block https://bugs.ruby-lang.org/issues/15554#change-110069 * Author: ko1 (Koichi Sasada) * Status: Assigned * Assignee: matz (Yukihiro Matsumoto) ---------------------------------------- # Abstract Warn or raise an ArgumentError if block is passed to a method which does not use a block. In other words, detect "block user methods" implicitly and only "block user methods" can accept a block. # Background Sometimes, we pass a block to a method which ignores the passed block accidentally. ``` def my_open(name) open(name) end # user hopes it works as Kernel#open which invokes a block with opened file. my_open(name){|f| important_work_with f } # but simply ignored... ``` To solve this issue, this feature request propose showing warnings or raising an exception on such case. Last developer's meeting, matz proposed `&nil` which declares this method never receive a block. It is explicit, but it is tough to add this `&nil` parameter declaration to all of methods (do you want to add it to `def []=(i, e, &nil)`?). (I agree `&nil` is valuable on some situations) # Spec ## Define "use a block" methods We need to define which method accepts a block and which method does not. * (1) method has a block parameter (`&b`) * (2) method body has `yield' * (3) method body has `super` (ZSUPER in internal terminology) or `super(...)` * (4) method body has singleton method (optional) (1) and (2) is very clear. I need to explain about (3) and (4). (3). `super` (ZSUPER) passes all parameters as arguments. So there is no surprise that which can accept `block`. However `super(...)` also passes a block if no explicit block passing (like `super(){}` or `super(&b)`) are written. I'm not sure we need to continue this strange specification, but to keep compatibility depending this spec, I add this rule. (4). surprisingly, the following code invoke a block: ``` def foo class << Object.new yield end end foo{ p :ok } #=> :ok ``` I'm also not sure we need to keep this spec, but to allow this spec, I added (4) rule. Strictly speaking, it is not required, but we don't keep the link from singleton class ISeq to lexical parent iseq now, so I added it. ## Exceptional cases A method called by `super` doesn`t warn warning even if this method doesn't use a block. The rule (3) can pass blocks easily and there are many methods don`t use a block. So my patch ignores callings by `super`. ## corner cases There are several cases to use block without (1)-(4) rules. ### `Proc.new/proc/lambda` without a block Now it was deprecated in r66772 (commit:9f1fb0a17febc59356d58cef5e98db61a3c03550). Related discussion: [Bug #15539] ### `block_given?` `block_given?` expects block, but I believe we use it with `yield` or a block parameter. If you know the usecase without them, please tell us. ### `yield` in `eval` We can't know `yield` (or (3), (4) rule) in an `eval` evaluating string at calling time. ``` def foo eval('yield`) end foo{} # at calling time, # we can't know the method foo can accept a block or not. ``` So I added a warning to use `yield` in `eval` like that: `test.rb:4: warning: use yield in eval will not be supported in Ruby 3.` Workaround is use a block parameter explicitly. ``` def foo &b eval('b.call') end foo{ p :ok } ``` # Implementation Strategy is: * [compile time] introduce `iseq::has_yield` field and check it if the iseq (or child iseq) contains `yield` (or something) * [calling time] if block is given, check `iseq::has_yield` flag and show warning (or raise an exception) https://gist.github.com/ko1/c9148ad0224bf5befa3cc76ed2220c0b On this patch, now it raises an error to make it easy to detect. It is easy to switch to show the warning. # Evaluation and discussion I tried to avoid ruby's tests. https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786 Here is a patch. There are several patterns to avoid warnings. ## tests for `block_given?`, `Proc.new` (and similar) without block Add a dummy block parameter. It is test-specific issue. ## empty `each` Some tests add `each` methods do not `yield`, like: `def each; end`. Maybe test-specific issue, and adding a dummy block parameter. ## Subtyping / duck typing https://github.com/ruby/ruby/blob/c01a5ee85e2d6a7128cccafb143bfa694284ca87/… This `parse` method doesn't use `yield`, but other sub-type's `parse` methods use. ## `super` with `new` method https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-pat… This method override `Class#new` method and introduce a hook with block (yield a block in this hook code). https://github.com/ruby/ruby/blob/trunk/lib/rubygems/package/tar_writer.rb#… In this method, call `super` and it also passing a block. However, called `initialize` doesn't use a block. ## Change robustness This change reduce robustness for API change. `Delegator` requires to support `__getobj__` for client classes. Now `__getobj__` should accept block but most of `__getobj__` clients do not call given block. https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L80 This is because of delegator.rb's API change. https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-pat… Nobu says calling block is not required (ignoring a block is no problem) so it is not a bug for delegator client classes. ## Found issues. ``` [ 2945/20449] Rinda::TestRingServer#test_do_reply = 0.00 s 1) Error: Rinda::TestRingServer#test_do_reply: ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used. /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:635:in `test_do_reply' [ 2946/20449] Rinda::TestRingServer#test_do_reply_local = 0.00 s 2) Error: Rinda::TestRingServer#test_do_reply_local: ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used. /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:657:in `test_do_reply_local' [10024/20449] TestGemRequestSetGemDependencyAPI#test_platform_mswin = 0.01 s 3) Error: TestGemRequestSetGemDependencyAPI#test_platform_mswin: ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used. /home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:655:in `test_platform_mswin' [10025/20449] TestGemRequestSetGemDependencyAPI#test_platforms = 0.01 s 4) Error: TestGemRequestSetGemDependencyAPI#test_platforms: ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used. /home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:711:in `test_platforms' ``` These 4 detection show the problem. `with_timeout` method (used in Rinda test) and `util_set_arch` method (used in Rubygems test) simply ignore the given block. So these tests are simply ignored. I reported them. (https://github.com/rubygems/rubygems/issues/2601) ## raise an error or show a warning? At least, Ruby 2.7 should show warning for this kind of violation with `-w`. How about for Ruby3? -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:119440] [Ruby master Feature#17294] Feature: Allow method chaining with Pathname#mkpath Pathname#rmtree
by hsbt (Hiroshi SHIBATA) 03 Oct '24

03 Oct '24
Issue #17294 has been updated by hsbt (Hiroshi SHIBATA). Status changed from Assigned to Closed This proposal has been approved by @akr. I merged https://github.com/ruby/ruby/pull/3705 now. ---------------------------------------- Feature #17294: Feature: Allow method chaining with Pathname#mkpath Pathname#rmtree https://bugs.ruby-lang.org/issues/17294#change-110060 * Author: schneems (Richard Schneeman) * Status: Closed * Assignee: akr (Akira Tanaka) ---------------------------------------- Currently in my code when I want to create a pathname object and create a path at the same time I must use tap ``` path = Pathname.new("/tmp/new").tap(&:mkpath) ``` I think it would be cleaner to be able to chain on the results of these methods instead: ``` path = Pathname.new("/tmp/new").mkpath ``` This is a change in return value but after research on github I do not believe many (if any) are relying on the current behavior to return nil https://github.com/search?l=&p=1&q=.mkpath+language%3ARuby&ref=advsearch&ty…. Here is my diff: ``` $ git diff master schneems/return-self-pathname diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb index e6fb90277d..f1eb1e00ae 100644 --- a/ext/pathname/lib/pathname.rb +++ b/ext/pathname/lib/pathname.rb @@ -582,7 +582,7 @@ class Pathname # * FileUtils * def mkpath require 'fileutils' FileUtils.mkpath(@path) - nil + self end # Recursively deletes a directory, including all directories beneath it. @@ -593,7 +593,7 @@ def rmtree # File::Path provides "mkpath" and "rmtree". require 'fileutils' FileUtils.rm_r(@path) - nil + self end end diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb index 43cef4849f..149fe15c3a 100644 --- a/test/pathname/test_pathname.rb +++ b/test/pathname/test_pathname.rb @@ -1389,7 +1389,8 @@ def test_find def test_mkpath with_tmpchdir('rubytest-pathname') {|dir| - Pathname("a/b/c/d").mkpath + path = Pathname("a/b/c/d") + assert_equal(path, path.mkpath) assert_file.directory?("a/b/c/d") } end @@ -1398,7 +1399,8 @@ def test_rmtree with_tmpchdir('rubytest-pathname') {|dir| Pathname("a/b/c/d").mkpath assert_file.exist?("a/b/c/d") - Pathname("a").rmtree + path = Pathname("a") + assert_equal(path, path.rmtree) assert_file.not_exist?("a") } end ``` Github PR: https://github.com/ruby/ruby/pull/3705. If accepted I will make a pr to update the tests here as well https://github.com/ruby/rbs/blob/b0dee64fdd00cc41c0729fa2c239fc2dcb9c3b18/t…. -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:119439] [Ruby master Feature#17297] Feature: Introduce Pathname.mktmpdir
by hsbt (Hiroshi SHIBATA) 03 Oct '24

03 Oct '24
Issue #17297 has been updated by hsbt (Hiroshi SHIBATA). Status changed from Assigned to Closed This feature request has been approved by @akr. I merged https://github.com/ruby/ruby/pull/3709 now. ---------------------------------------- Feature #17297: Feature: Introduce Pathname.mktmpdir https://bugs.ruby-lang.org/issues/17297#change-110059 * Author: schneems (Richard Schneeman) * Status: Closed * Assignee: akr (Akira Tanaka) ---------------------------------------- When I want to create a tmpdir I often want to manipulate it as a pathname. By introducing Pathname.mktmpdir I can get this behavior. Currently I must: ```ruby Dir.mktmpdir do |dir| dir = Pathname(dir) # ... code end ``` I would like to be able to instead: ```ruby Pathname.mktmpdir do |dir| # ... code end ``` Diff: ``` $ git diff master diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb index e6fb90277d..ec32e7d611 100644 --- a/ext/pathname/lib/pathname.rb +++ b/ext/pathname/lib/pathname.rb @@ -597,3 +597,20 @@ def rmtree end end +class Pathname # * tmpdir * + # Creates a tmp directory and wraps the returned path in a Pathname object. + # + # See Dir.mktmpdir + def self.mktmpdir + require 'tmpdir' unless defined?(Dir.mktmpdir) + if block_given? + Dir.mktmpdir do |dir| + dir = self.new(dir) + yield dir + end + else + self.new(Dir.mktmpdir) + end + end +end + diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb index 43cef4849f..8edcccf666 100644 --- a/test/pathname/test_pathname.rb +++ b/test/pathname/test_pathname.rb @@ -1272,6 +1272,14 @@ def test_s_glob_3args } end + def test_mktmpdir + Pathname.mktmpdir do |dir| + assert_equal Pathname(dir), dir + assert dir.directory? + assert dir.exist? + end + end + def test_s_getwd wd = Pathname.getwd assert_kind_of(Pathname, wd) ``` Github link: https://github.com/ruby/ruby/pull/3709 -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:119438] [Ruby master Feature#17295] Feature: Create a directory and file with Pathname#touch
by hsbt (Hiroshi SHIBATA) 03 Oct '24

03 Oct '24
Issue #17295 has been updated by hsbt (Hiroshi SHIBATA). Status changed from Assigned to Rejected `Pathname#touch` is rejected at [this reason](https://bugs.ruby-lang.org/issues/7361#note-5). I asked this proposal to @akr again, he is still negative for `Pathname#touch`. ---------------------------------------- Feature #17295: Feature: Create a directory and file with Pathname#touch https://bugs.ruby-lang.org/issues/17295#change-110058 * Author: schneems (Richard Schneeman) * Status: Rejected * Assignee: akr (Akira Tanaka) ---------------------------------------- Right now if a developer wants to create a file and is not sure if the path exists yet or not they must: ```ruby Pathname.new("/a/b/c/d.txt").tap {|p| p.dirname.mkpath; FileUtils.touch(p)} ``` After this patch a developer can instead call: ```ruby Pathname.new("/a/b/c/d.txt").touch ``` An alternative name for this behavior could be `mkfile` but I think it is confusing to have a `mkfile` and a `mkpath` where one creates a directory and one creates a file. Diff: ``` $ git diff master diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb index e6fb90277d..2ed02a6633 100644 --- a/ext/pathname/lib/pathname.rb +++ b/ext/pathname/lib/pathname.rb @@ -585,6 +585,27 @@ def mkpath nil end + # Creates a file and the full path to the file including any intermediate directories that don't yet + # exist. + # + # Example: + # + # Dir.exist?("/a/b/c") # => false + # + # p = Pathname.new("/a/b/c/d.txt") + # p.file? => false + # p.touch + # p.file? => true + # + # Dir.exist?("/a/b/c") # => true + def touch + require 'fileutils' + dirname.mkpath + + FileUtils.touch(self) + self + end + # Recursively deletes a directory, including all directories beneath it. # # See FileUtils.rm_r diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb index 43cef4849f..3c518cc3da 100644 --- a/test/pathname/test_pathname.rb +++ b/test/pathname/test_pathname.rb @@ -1394,6 +1394,14 @@ def test_mkpath } end + def test_touch + with_tmpchdir('rubytest-pathname') {|dir| + Pathname("a/b/c/d.txt").touch + assert_file.directory?("a/b/c") + assert_file.file?("a/b/c/d.txt") + } + end + def test_rmtree with_tmpchdir('rubytest-pathname') {|dir| Pathname("a/b/c/d").mkpath ``` Github link: https://github.com/ruby/ruby/pull/3706 -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:119410] [Ruby master Feature#20778] ruby/repl_type_completor as a bundled gem
by tompng (tomoya ishida) 03 Oct '24

03 Oct '24
Issue #20778 has been reported by tompng (tomoya ishida). ---------------------------------------- Feature #20778: ruby/repl_type_completor as a bundled gem https://bugs.ruby-lang.org/issues/20778 * Author: tompng (tomoya ishida) * Status: Open ---------------------------------------- When gem repl_type_completor is installed, `irb --type-completor` will provide better completion in IRB. ~~~ irb(main):001* [1, 2, 3].map(&:ch█ |:chr| ~~~ ~~~ irb(main):001* [1, 2, 3].map(&:chr).each do |c| irb(main):002* puts c.ch█ irb(main):003> end |c.chars | |c.chomp | |c.chomp!| |c.chop | |c.chop! | |c.chr | ~~~ I believe this feature will provide powerful support especially to beginners, but it requires installation and setup. And what is important, you cannot activate this feature unless you know it exists. If repl_type_completor is a bundled gem, and if IRB uses type-completor as default (https://github.com/ruby/irb/pull/1010) Ruby 3.4's IRB will provide great experience by default. ## With bundler When `repl_type_completor` is not added to Gemfile, fallback to regexp-based completion. Force require: consider later. ## Dependency `prism` and `rbs` -- https://bugs.ruby-lang.org/
3 6
0 0
[ruby-core:118811] [Ruby master Feature#20669] Add error classes to differentiate Marshal ArgumentErrors
by olleolleolle (Olle Jonsson) 03 Oct '24

03 Oct '24
Issue #20669 has been reported by olleolleolle (Olle Jonsson). ---------------------------------------- Feature #20669: Add error classes to differentiate Marshal ArgumentErrors https://bugs.ruby-lang.org/issues/20669 * Author: olleolleolle (Olle Jonsson) * Status: Open ---------------------------------------- Currently, Marshal.load raises ArgumentErrors on failure. In the memcache client Dalli, there is [a regular expression to check for a few of the ArgumentErrors that can be raised during Marshal.load](https://github.com/petergoldstein/dalli/blob/v3.2.8/lib/dalli…. In order to make it easier to work with, perhaps new individual error classes deriving from ArgumentError could be introduced in Marshal? Perhaps a MarshalError base class deriving from ArgumentError? Something backwards-compatible. [Dalli PR where another error message would be added](https://github.com/petergoldstein/dalli/pull/1008) -- https://bugs.ruby-lang.org/
4 6
0 0
[ruby-core:119430] [Ruby master Feature#17296] Feature: Pathname#chmod use FileUtils.chmod instead of File
by mame (Yusuke Endoh) 03 Oct '24

03 Oct '24
Issue #17296 has been updated by mame (Yusuke Endoh). Status changed from Assigned to Feedback It was discussed at the dev meeting. `File.chmod` and `FileUtils.chmod` have an incompatibility in their handling of symbolic links: `File.chmod` changes the permissions on the target of the symbolic link, while `FileUtils.chmod` changes the permissions on the symbolic link itself in environments with `lchmod `itself, and no-op in environments without `lchmod`. Therefore, it seems better to have `File.chmod` support `"+x"`, etc., rather than using `FileUtils.chmod`. ---------------------------------------- Feature #17296: Feature: Pathname#chmod use FileUtils.chmod instead of File https://bugs.ruby-lang.org/issues/17296#change-110045 * Author: schneems (Richard Schneeman) * Status: Feedback * Assignee: akr (Akira Tanaka) ---------------------------------------- The `FileUtils.chmod` provides the same numerical interface as `File.chmod` and it also includes a "symbolic mode" interface. With this patch you'll be able to run this code: ```ruby Pathname.new("bin/compile").chmod("+x") ``` I believe that this is backwards compatible with the existing implementation and all changes are an extension. The only difference between File.chmod and FileUtils.chmod I could find is they have different return values and the previous implementation of `Pathname#chmod` returned the result of the `File.chmod` call. From the docs `File.chmod` returns the number of files modified, since we're only ever able to pass in a maximum of one file through this interface, the return value will always be a `1` or an exception if the file does not exist. I checked and the exceptions when the file does not exist match: ``` irb(main):004:0> File.chmod(0444, "doesnotexist.txt") Traceback (most recent call last): 6: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `<main>' 5: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `load' 4: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>' 3: from (irb):3 2: from (irb):4:in `rescue in irb_binding' 1: from (irb):4:in `chmod' Errno::ENOENT (No such file or directory @ apply2files - doesnotexist.txt) irb(main):005:0> FileUtils.chmod(0444, "doesnotexist.txt") Traceback (most recent call last): 10: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `<main>' 9: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `load' 8: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>' 7: from (irb):4 6: from (irb):5:in `rescue in irb_binding' 5: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1016:in `chmod' 4: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1016:in `each' 3: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1017:in `block in chmod' 2: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1346:in `chmod' 1: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1346:in `chmod' Errno::ENOENT (No such file or directory @ apply2files - doesnotexist.txt) ``` If you're open to changing the interface of the return value my preference would be to return `self` from this method so that it can be chained. Otherwise this current patch is a smaller change. Diff: ``` $ git diff master diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb index e6fb90277d..cb6e32d9ac 100644 --- a/ext/pathname/lib/pathname.rb +++ b/ext/pathname/lib/pathname.rb @@ -585,6 +585,15 @@ def mkpath nil end + # Changes file permissions. + # + # See FileUtils.chmod + def chmod(mode) + require 'fileutils' + FileUtils.chmod(mode, self) + return 1 + end + # Recursively deletes a directory, including all directories beneath it. # # See FileUtils.rm_r diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c index f71cec1b25..6778d4f102 100644 --- a/ext/pathname/pathname.c +++ b/ext/pathname/pathname.c @@ -12,7 +12,6 @@ static ID id_binwrite; static ID id_birthtime; static ID id_blockdev_p; static ID id_chardev_p; -static ID id_chmod; static ID id_chown; static ID id_ctime; static ID id_directory_p; @@ -552,20 +551,6 @@ path_mtime(VALUE self) return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self)); } -/* - * call-seq: - * pathname.chmod(mode_int) -> integer - * - * Changes file permissions. - * - * See File.chmod. - */ -static VALUE -path_chmod(VALUE self, VALUE mode) -{ - return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self)); -} - /* * call-seq: * pathname.lchmod(mode_int) -> integer @@ -1448,7 +1433,6 @@ path_f_pathname(VALUE self, VALUE str) * - #birthtime * - #ctime * - #mtime - * - #chmod(mode) * - #lchmod(mode) * - #chown(owner, group) * - #lchown(owner, group) @@ -1495,6 +1479,7 @@ path_f_pathname(VALUE self, VALUE str) * === Utilities * * These methods are a mixture of Find, FileUtils, and others: + * - #chmod(mode) * - #find(&block) * - #mkpath * - #rmtree @@ -1542,7 +1527,6 @@ Init_pathname(void) rb_define_method(rb_cPathname, "birthtime", path_birthtime, 0); rb_define_method(rb_cPathname, "ctime", path_ctime, 0); rb_define_method(rb_cPathname, "mtime", path_mtime, 0); - rb_define_method(rb_cPathname, "chmod", path_chmod, 1); rb_define_method(rb_cPathname, "lchmod", path_lchmod, 1); rb_define_method(rb_cPathname, "chown", path_chown, 2); rb_define_method(rb_cPathname, "lchown", path_lchown, 2); @@ -1618,7 +1602,6 @@ InitVM_pathname(void) id_birthtime = rb_intern("birthtime"); id_blockdev_p = rb_intern("blockdev?"); id_chardev_p = rb_intern("chardev?"); - id_chmod = rb_intern("chmod"); id_chown = rb_intern("chown"); id_ctime = rb_intern("ctime"); id_directory_p = rb_intern("directory?"); diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb index 43cef4849f..5673691231 100644 --- a/test/pathname/test_pathname.rb +++ b/test/pathname/test_pathname.rb @@ -823,6 +823,11 @@ def test_chmod path.chmod(0444) assert_equal(0444, path.stat.mode & 0777) path.chmod(old) + + skip "Windows has different symbolic mode" if /mswin|mingw/ =~ RUBY_PLATFORM + path.chmod("u=wrx,g=rx,o=x") + assert_equal(0751, path.stat.mode & 0777) + path.chmod(old) } end ``` Github link: https://github.com/ruby/ruby/pull/3708 -- https://bugs.ruby-lang.org/
1 0
0 0
[ruby-core:118514] [Ruby master Bug#20620] singleton_method undefined for module using "extend self"
by dentarg (Patrik Ragnarsson) 02 Oct '24

02 Oct '24
Issue #20620 has been reported by dentarg (Patrik Ragnarsson). ---------------------------------------- Bug #20620: singleton_method undefined for module using "extend self" https://bugs.ruby-lang.org/issues/20620 * Author: dentarg (Patrik Ragnarsson) * Status: Open * ruby -v: ruby 3.4.0dev (2024-07-08T21:43:28Z master e500222de1) [x86_64-linux] * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- Is this a bug? I expected `ExtendSelf.singleton_method(:foo)` to work when `ExtendSelf.singleton_methods` worked and `:foo` was in the list returned. ```ruby # singleton_method.rb class Klass def self.foo end end module ExtendSelf extend self def foo end end p RUBY_DESCRIPTION p "Klass" p Klass.singleton_methods # => [:foo] p Klass.singleton_method(:foo) # => #<Method: Klass.foo() singleton_method.rb:2> p "ExtendSelf" p ExtendSelf.singleton_methods # => [:foo] p ExtendSelf.singleton_method(:foo) # => singleton_method.rb:19:in `singleton_method': undefined singleton method `foo' for `ExtendSelf' (NameError) ``` ```shell $ docker run --rm -it -v $(pwd):/app -w /app rubylang/ruby:master-nightly-jammy Unable to find image 'rubylang/ruby:master-nightly-jammy' locally master-nightly-jammy: Pulling from rubylang/ruby ... Digest: sha256:922037b184b897786a26b2460f70a66139f87dce67f20ddf760cd4186790ed9f root@9807305c322a:/app# ruby -v ruby 3.4.0dev (2024-07-08T21:43:28Z master e500222de1) [x86_64-linux] root@9807305c322a:/app# ruby singleton_method.rb "ruby 3.4.0dev (2024-07-08T21:43:28Z master e500222de1) [x86_64-linux]" "Klass" [:foo] #<Method: Klass.foo() singleton_method.rb:2> "ExtendSelf" [:foo] singleton_method.rb:21:in 'Kernel#singleton_method': undefined singleton method 'foo' for 'ExtendSelf' (NameError) ``` -- https://bugs.ruby-lang.org/
3 4
0 0
[ruby-core:119420] [Ruby master Feature#18127] Ractor-local version of Singleton
by hsbt (Hiroshi SHIBATA) 02 Oct '24

02 Oct '24
Issue #18127 has been updated by hsbt (Hiroshi SHIBATA). Status changed from Open to Closed I have been merged https://github.com/ruby/singleton/pull/4 ---------------------------------------- Feature #18127: Ractor-local version of Singleton https://bugs.ruby-lang.org/issues/18127#change-110034 * Author: rm155 (Rohit Menon) * Status: Closed ---------------------------------------- **Background** When the Singleton module (from the Singleton library) is included in a class, that class will have only one instance. Since the instance can only be in one Ractor at once, Singleton is not Ractor-compatible. For example, the following code would fail upon trying to access Example.instance in the Ractor: ``` ruby class Example def initialize @value = 1 end end Example.include Singleton Ractor.new do Example.instance end.take #=> can not access instance variables of classes/modules from non-main Ractors (Ractor::IsolationError) ``` In some cases, this may be the desired behavior, as it may be important that the class truly have only one instance. However, in many other cases, it would be more convenient for the class to have one instance per Ractor. **Proposal** The proposal is to create a RactorLocalSingleton module that can be included instead of Singleton to make the instance Ractor-local. Here is how RactorLocalSingleton might be used in the situation above: ``` ruby class Example def initialize @value = 1 end end Example.include RactorLocalSingleton Ractor.new do Example.instance end.take ``` **Discussion** The advantage of creating RactorLocalSingleton is that classes could have Singleton-like behavior while being usable in Ractors. Since some libraries, such as Prime, currently rely on the Singleton module, this would enable those libraries to have more flexibility with Ractors. The disadvantage of creating this module is that it supports the continued use of the Singleton design pattern, which is sometimes considered harmful. An alternative to RactorLocalSingleton might be to simply use Thread-local variables as Singleton instances. Here is how Thread-local variables might be used in the given situation: ``` ruby class Example def initialize @value = 1 end end Ractor.new do Thread.current[:Example] = Example.new Thread.current[:Example] end.take ``` **Summary** Classes that include Singleton are currently incompatible with Ractors. By instead including a new module RactorLocalSingleton, classes can have Singleton-like properties while being used in Ractors. However, this may perpetuate the use of the Singleton design pattern, and using Thread-local variables may be a preferable solution. -- https://bugs.ruby-lang.org/
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 17
  • 18
  • 19
  • 20
  • 21
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.