New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #37065 - report_row now explicitly accepts args and kwargs #10047
Fixes #37065 - report_row now explicitly accepts args and kwargs #10047
Conversation
7e1baa7
to
3794fa5
Compare
'Name': host.name, | ||
'Global': machine_readable ? host.global_status : host.global_status_label |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may say, "But these hash keys look like strings!" Which is what I thought too. But Ruby always makes it a Symbol if you use the more modern Hash syntax. To get true string keys you'd have to use =>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK this has always been the case. Only =>
leaves the keys untouched, :
there has always converted it to symbols.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think JavaScript object syntax has ruined my brain 🙈
'Name': host.name, | ||
'Global': machine_readable ? host.global_status : host.global_status_label |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK this has always been the case. Only =>
leaves the keys untouched, :
there has always converted it to symbols.
and then there are |
I think all of those will still work fine, because to break it you must use both |
🤯 This whole kwargs handling melts my brain every day slightly more. Halp. |
I still haven't figured out exactly why this fixes it. thoughts welcome |
[test Redmine issues] |
3794fa5
to
6f67663
Compare
Maybe a dead end, but wouldn't a third option be to pass |
Can confirm that this works too! 🤯 |
[test katello] |
One possibility I was thinking about was that in addition to calling def report_row(args) but this would change it to def report_row(**args) This would make things a bit more safe because there'd be no confusion as to whether we're sending positional or keyword arguments, but
Thoughts? |
@jeremylenz mind setting the target version in Redmine to 3.10? This is a blocker for GA |
done |
I've noticed that it works on Ruby 3.0 though... So as a different solution we could bump here safemode to I think there is a place where due to Ruby 2.7 "feature" a hash is being unpacked into a series of keyword arguments automatically. I'm trying to find a way how to fix that and don't break templates or force users to update their own :/ |
6f67663
to
c22caa1
Compare
This seems like a better solution to me. Updated the PR. 👍
That certainly seems like what's happening! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I din't think we can both support Ruby 3 and safemode < 1.4. You will also need to revert the changes to use the safe operator, but I expect the tests to fail with this.
@ekohl I don't understand what changes you are requesting? Should I change it back to what it was before? |
If (and that's a big if) you're pinning to an older version you must revert 93ac254. As you can see, the tests are broken on Ruby 2.7. On Ruby 3.0 you also see test failures and we want to support Ruby 3.0 for EL9. So yes, I am requesting to revert to the previous patch or implement a fix in safemode itself. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a test that failed prior to this and is now solved? I'd like to have some regression testing for this.
I also fail to understand why this is an issue. In plain Ruby:
def meth(row_data)
puts row_data.inspect
end
data = { x: 'y' }
meth(data)
meth(data.merge('a' => 'b'))
$ ruby --version
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
$ ruby kwargs.rb
{:x=>"y"}
{:x=>"y", "a"=>"b"}
# ruby --version
ruby 2.7.8p225 (2023-03-30 revision 1f4d455848) [x86_64-linux]
# ruby kwargs.rb
{:x=>"y"}
{:x=>"y", "a"=>"b"}
So could this be something that safemode does? Have you tried to run the report with safemode turned off?
Yes. In safemode every method is removed and every call must go through Here's what's going on in safemode def method_missing(method, *args, **kwargs, &block)
# ...
@delegate.send :report_row, *[{ "Build"=>"Installed", ... }], **{:Name=>"foreman.kutak.com", :Global=>"OK"}, &block
# ...
end And here's what on Ruby 3.0: def method_missing(method, *args, **kwargs, &block)
# ...
@delegate.send :report_row, *[{ :Name=>"foreman.kutak.com", :Global=>"OK", "Build"=>"Installed", ... }], **{}, &block
# ...
end Honestly, I've spent so much time on similar stuff, that it's not even fun anymore... Also, plain Ruby tests won't show you almost anything since it lacks the broken context of our "corner cases". |
But we can write a test that renders the report using safemode, right? It would be more of an integration test, but I always find those to be useful for cases like this. |
Sure, it should be possible, and I'm all for such tests. Just to be clear, what I meant by plain Ruby tests is going to irb and test some trivial stuff to see how it works. It doesn't always show the whole picture :/ |
98b7339
to
af14a6d
Compare
@ofedoren @ekohl Updated with a test. Confirmed that it fails on develop:
and passes here:
|
af14a6d
to
88a383a
Compare
@ekohl updated to also assert output. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @jeremylenz, LGTM!
also adds a test which fails without the fix
88a383a
to
4ec55cd
Compare
@ofedoren API docs updated per your comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot, @jeremylenz! @ekohl, any concerns?
With Ruby 3-related changes in
safemode
1.4 (maybe?), theHost - Statuses
report breaks withThe issue does not occur when using safemode 1.3.8.
In my testing, to trigger this requires both of the following conditions:
report_row
is called with the result ofHash#merge
To work around this, we can either (a) make sure none of our Hash keys are symbols; or (b) call
report_row
with kwargs rather than positional arguments, by adding**
to the call.With this change, we make
report_row
explicitly accept both args and kwargs. This makes it so you don't have to do either of these workarounds.Update: Added a test that fails without the
report_row
change.