From 6ed90f144c592a5d744b1a03df42bf834f137416 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Sun, 15 Feb 2026 00:12:47 +0100 Subject: [PATCH 1/2] Add missing Psych methods and exception classes --- stdlib/psych/0/psych.rbs | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/stdlib/psych/0/psych.rbs b/stdlib/psych/0/psych.rbs index 808f0d41c..c085c2c0d 100644 --- a/stdlib/psych/0/psych.rbs +++ b/stdlib/psych/0/psych.rbs @@ -400,4 +400,56 @@ module Psych # %a{annotate:rdoc:copy:Psych.unsafe_load} def self.unsafe_load: (String yaml, ?filename: String | _ToStr | _ToS?, ?fallback: untyped, ?symbolize_names: bool, ?freeze: bool, ?strict_integer: bool) -> untyped + + # + # Safely loads the document contained in `filename`. Returns the yaml contained + # in `filename` as a Ruby object, or if the file is empty, it returns the + # specified `fallback` return value, which defaults to `nil`. See safe_load for + # options. + # + %a{annotate:rdoc:copy:Psych.safe_load_file} + def self.safe_load_file: (path, ?permitted_classes: Array[Class], ?permitted_symbols: Array[Symbol], ?aliases: bool, ?fallback: untyped, ?symbolize_names: bool, ?freeze: bool) -> untyped + + # + # Load the document contained in `filename`. Returns the yaml contained in + # `filename` as a Ruby object, or if the file is empty, it returns the specified + # `fallback` return value, which defaults to `false`. + # + # NOTE: This method *should not* be used to parse untrusted documents, such as + # YAML documents that are supplied via user input. Instead, please use the + # safe_load_file method. + # + %a{annotate:rdoc:copy:Psych.unsafe_load_file} + def self.unsafe_load_file: (path, ?fallback: untyped, ?symbolize_names: bool, ?freeze: bool) -> untyped + + class Exception < ::RuntimeError + end + + class SyntaxError < ::Psych::Exception + attr_reader file: String? + attr_reader line: Integer? + attr_reader column: Integer? + attr_reader offset: Integer? + attr_reader problem: String? + attr_reader context: String? + + # + # + def initialize: (?String? file, ?Integer? line, ?Integer? column, ?Integer? offset, ?String? problem, ?String? context) -> void + end + + class BadAlias < ::Psych::Exception + end + + class DisallowedClass < ::Psych::Exception + end end From 5995af3c96e8d4896dcf7c236b9989c09ef76617 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Mon, 16 Feb 2026 13:16:37 +0100 Subject: [PATCH 2/2] Add tests for `safe_load` and `unsafe_load_file` --- test/stdlib/psych_test.rb | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/stdlib/psych_test.rb b/test/stdlib/psych_test.rb index 8bb921e6e..4af1c990e 100644 --- a/test/stdlib/psych_test.rb +++ b/test/stdlib/psych_test.rb @@ -59,6 +59,42 @@ def test_safe_load ) end + def test_safe_load_file + Dir.mktmpdir do |dir| + (Pathname(dir) + "test.yaml").write(<<-YAML) +foo: 123 + YAML + + assert_send_type( + "(::String) -> untyped", + Psych, :safe_load_file, File.join(dir, "test.yaml") + ) + + assert_send_type( + "(::_ToPath, permitted_classes: ::Array[::Class], permitted_symbols: ::Array[::Symbol], aliases: bool, fallback: ::Symbol, symbolize_names: bool, freeze: bool) -> untyped", + Psych, :safe_load_file, Pathname(File.join(dir, "test.yaml")), permitted_classes: [Integer], permitted_symbols: [:foo], aliases: true, fallback: :foo, symbolize_names: true, freeze: false + ) + end + end + + def test_unsafe_load_file + Dir.mktmpdir do |dir| + (Pathname(dir) + "test.yaml").write(<<-YAML) +foo: 123 + YAML + + assert_send_type( + "(::String) -> untyped", + Psych, :unsafe_load_file, File.join(dir, "test.yaml") + ) + + assert_send_type( + "(::_ToPath, fallback: ::String, symbolize_names: bool, freeze: bool) -> untyped", + Psych, :unsafe_load_file, Pathname(File.join(dir, "test.yaml")), fallback: "foo", symbolize_names: false, freeze: false + ) + end + end + def test_dump assert_send_type( "(::Array[::Integer]) -> ::String",