2021/05/20 今週の気になった bugs.ruby のチケット
今週は Psych の非互換な変更に対するチケットできていました。
かなり影響範囲が広いのでどうなるか今後どうなっていくのか気になる。
[Bug #17866] Incompatible changes with Psych 4.0.0
- 先週話していた
Psych.load
をPsych.safe_load
に置き換える PR がマージされて Psych 4.0.0 がリリースされた - このチケットは Psych 4.0.0 が非互換になるのでそれの対応をするチケット
- 大まかに2つの問題があり、1つはデフォルトだとエイリアスが許可されていない問題
- デフォルトだと
&default
みたいなエイリアスが許可されておらずにいろんな場所で問題になっている - これの影響でいくつかの gem が対応を行っている
- エイリアスがデフォルトで不許可なのは再帰的なエイリアスになった場合に安全ではないケースがあるのが理由
- 以下のようなデータの場合にクラッシュしてしまう
require "psych" def process thing thing.each do |item| case item when Array process item when Hash # ... when String # ... end end end user_input = <<~EOS --- &1 - *1 EOS # error: stack level too deep (SystemStackError) process Psych.load(user_input)
- エイリアスは許可したいが再帰的なエイリアスは不許可にできれば…
- また
Psych.load
は『キーにSymbol
を定義できることを許容している』がYAML.load_file
に反映されていないバグがあるっぽい
# :text: という書き方が許可されてほしいが許可されていない require "psych" require "tempfile" require "yaml" Tempfile.open "example" do |file| file.write %(:text: "Hello.") file.rewind # load は OK puts "YAML Contents: #{YAML.load file}" # load_file は NG puts "YAML Contents: #{YAML.load_file file}" end
- かなり影響範囲が大きそうなので Psych のリリースは様子を見たほうがよかったんじゃないのかなあ、と思う一方でリリースしないとこういう問題はわからないので難しいところ
[PR 4414] Fix some typos by spell checker
$ cat test.txt currrent # スペルミスがある位置を出力してくれる $ codespell test.txt test.txt:1: currrent ==> current # -w を付けると修正してくれる $ codespell test.txt -w FIXED: test.txt $ cat test.txt current
- 普通に便利そう
[Feature #11747] "bury" feature, similar to 'dig' but opposite
- 少し前のチケット
Hash#dig
のように複数のキーを渡してネストしてデータ構造を生成できるようにするHash#bury
というメソッドの提案
data = { users: [{ name: "homu" }] } # data[:users][0][:name] を以下のようにしてアクセスできる pp data.dig(:users, 0, :name) # => "homu" # dig のようにネストしたデータ構造を1回で代入する data.bury(:users, 0, :name, 'mami')
- ただし、空のデータに対してネストした構造を定義する場合にどのクラスで定義すべきなのか、という課題がある
# こう定義した時にどうなってほしい? # struct なども考慮する必要がある {}.bury(0, 1, 2, :foo) # => {0 => {1 => {2 => :foo}}} # or # => [[nil, [nil, nil, :foo]]]
- これが理由でチケットは Reject されている
- 一応以下のように書くこともできるが…
# これでネストしたデータを定義できるがうーん root = {} [:a, :b, :c].reduce(root) { _1[_2] ||= {} }[:d] = 'E' pp root # => {:a=>{:b=>{:c=>{:d=>"E"}}}}