[ruby-talk:444215] Is this the correct behaviour of `super`

I have been investigating a test failure triggered by upgrading selenium-webdriver from v4.9.0 to v4.9.1. This has lead me to produce the following test code that demonstrates the problem which occurs as an interaction between capybara and selenium. The test produces the following error
wrong number of arguments (given 2, expected 0..1) (ArgumentError)
Here is some code that reproduces the error -----8<-----8<-----8<-----8<-----8<-----8<------8<-----8<-----8<----- require 'selenium/webdriver/atoms' require 'selenium/webdriver/common' require 'selenium/webdriver/version' module DeprecationSuppressor def initialize(*) puts 'in DeprecationSuppressor::initialize' super end end Selenium::WebDriver::Logger.prepend DeprecationSuppressor class Demo def initialize @logger = Selenium::WebDriver::Logger.new('Selenium', ignored: true) puts @logger.class end end Demo.new -----8<-----8<-----8<-----8<-----8<-----8<------8<-----8<-----8<----- Here is it failing ➜ ruby -v ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22] ➜ ruby demo.rb in DeprecationSuppressor::initialize /Users/my/.rvm/gems/ruby-3.2.2@test/gems/selenium-webdriver-4.9.1/lib/selenium/webdriver/common/logger.rb:51:in `initialize': wrong number of arguments (given 2, expected 0..1) (ArgumentError) The error is raised by the `super` call in the initialize method of the DeprecationSuppressor module. Naming the arguments in the initialize method fixes the problem e.g. -----8<-----8<-----8<-----8<-----8<-----8<------8<-----8<-----8<----- module DeprecationSuppressor def initialize(*args) puts 'in DeprecationSuppressor::initialize' super args end end Selenium::WebDriver::Logger.prepend DeprecationSuppressor -----8<-----8<-----8<-----8<-----8<-----8<------8<-----8<-----8<----- ➜ ruby demo.rb in DeprecationSuppressor::initialize Selenium::WebDriver::Logger I have also found that using `initialize(...)` works too. I've tested this on Ruby 3.2.2 and 3.1.4 For further context of the wider problem, here is the initialize method in selenium-webdriver 4.9.0 and 4.9.1 4.9.0: https://github.com/SeleniumHQ/selenium/blob/selenium-4.9.0/rb/lib/selenium/w... 4.9.1: https://github.com/SeleniumHQ/selenium/blob/selenium-4.9.1/rb/lib/selenium/w... The difference being that two more named arguments have been added Finally it looks to me as though the Capybara team are preparing to fix this in v3.9.1 (https://github.com/teamcapybara/capybara/issues/2666) My question is whether Ruby is behaving correctly? It seems to me that the `super` call in the initialize(*) method should work.

wrong number of arguments (given 2, expected 0..1) (ArgumentError)
Here is some code that reproduces the error
module DeprecationSuppressor def initialize(*) puts 'in DeprecationSuppressor::initialize' super end end Selenium::WebDriver::Logger.prepend DeprecationSuppressor
'In Ruby 3.0, positional arguments and keyword arguments will be separated. ... In Ruby 3, a method delegating all arguments must explicitly delegate keyword arguments in addition to positional arguments. ... So when you want to pass keyword arguments, you should always use foo(k: expr) or foo(**expr). If you want to accept keyword arguments, in principle you should always use def foo(k: default) or def foo(k:) or def foo(**kwargs). ... Alternatively, if you do not need compatibility with Ruby 2.6 or prior and you don’t alter any arguments, you can use the new delegation syntax (...) that is introduced in Ruby 2.7." https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-ke...

""" So when you want to pass keyword arguments, you should always use foo(k: expr) or foo(**expr). If you want to accept keyword arguments, in principle you should always use def foo(k: default) or def foo(k:) or def foo(**kwargs). """ Isn't `**expr` same with `**kwargs`? https://ismailarilik.com On Mon, May 15, 2023, 01:57 Frank J. Cameron via ruby-talk < ruby-talk@ml.ruby-lang.org> wrote:
wrong number of arguments (given 2, expected 0..1) (ArgumentError)
Here is some code that reproduces the error
module DeprecationSuppressor def initialize(*) puts 'in DeprecationSuppressor::initialize' super end end Selenium::WebDriver::Logger.prepend DeprecationSuppressor
'In Ruby 3.0, positional arguments and keyword arguments will be separated. ... In Ruby 3, a method delegating all arguments must explicitly delegate keyword arguments in addition to positional arguments. ... So when you want to pass keyword arguments, you should always use foo(k: expr) or foo(**expr). If you want to accept keyword arguments, in principle you should always use def foo(k: default) or def foo(k:) or def foo(**kwargs). ... Alternatively, if you do not need compatibility with Ruby 2.6 or prior and you don’t alter any arguments, you can use the new delegation syntax (...) that is introduced in Ruby 2.7."
https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-ke...
______________________________________________ ruby-talk mailing list -- ruby-talk@ml.ruby-lang.org To unsubscribe send an email to ruby-talk-leave@ml.ruby-lang.org ruby-talk info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-talk.ml.ruby-lang.org...
participants (3)
-
Frank J. Cameron
-
İsmail Arılık
-
mark_young@hotmail.com