summaryrefslogtreecommitdiff
path: root/ext/psych/lib/psych
diff options
context:
space:
mode:
Diffstat (limited to 'ext/psych/lib/psych')
-rw-r--r--ext/psych/lib/psych/class_loader.rb6
-rw-r--r--ext/psych/lib/psych/core_ext.rb2
-rw-r--r--ext/psych/lib/psych/exception.rb14
-rw-r--r--ext/psych/lib/psych/handlers/document_stream.rb2
-rw-r--r--ext/psych/lib/psych/handlers/recorder.rb2
-rw-r--r--ext/psych/lib/psych/json/stream.rb4
-rw-r--r--ext/psych/lib/psych/json/tree_builder.rb2
-rw-r--r--ext/psych/lib/psych/nodes.rb14
-rw-r--r--ext/psych/lib/psych/nodes/node.rb8
-rw-r--r--ext/psych/lib/psych/parser.rb13
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb38
-rw-r--r--ext/psych/lib/psych/syntax_error.rb2
-rw-r--r--ext/psych/lib/psych/tree_builder.rb6
-rw-r--r--ext/psych/lib/psych/versions.rb4
-rw-r--r--ext/psych/lib/psych/visitors.rb12
-rw-r--r--ext/psych/lib/psych/visitors/json_tree.rb2
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb20
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb50
18 files changed, 117 insertions, 84 deletions
diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb
index 088373cd66..50efc35ee2 100644
--- a/ext/psych/lib/psych/class_loader.rb
+++ b/ext/psych/lib/psych/class_loader.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'psych/omap'
-require 'psych/set'
+require_relative 'omap'
+require_relative 'set'
module Psych
class ClassLoader # :nodoc:
@@ -35,7 +35,7 @@ module Psych
constants.each do |const|
konst = const_get const
- class_eval <<~RUBY
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{const.to_s.downcase}
load #{konst.inspect}
end
diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb
index 81055cc501..0721a133c3 100644
--- a/ext/psych/lib/psych/core_ext.rb
+++ b/ext/psych/lib/psych/core_ext.rb
@@ -15,5 +15,5 @@ class Object
end
if defined?(::IRB)
- require 'psych/y'
+ require_relative 'y'
end
diff --git a/ext/psych/lib/psych/exception.rb b/ext/psych/lib/psych/exception.rb
index f473b95a3b..d7469a4b30 100644
--- a/ext/psych/lib/psych/exception.rb
+++ b/ext/psych/lib/psych/exception.rb
@@ -6,6 +6,20 @@ module Psych
class BadAlias < Exception
end
+ # Subclasses `BadAlias` for backwards compatibility
+ class AliasesNotEnabled < BadAlias
+ def initialize
+ super "Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`."
+ end
+ end
+
+ # Subclasses `BadAlias` for backwards compatibility
+ class AnchorNotDefined < BadAlias
+ def initialize anchor_name
+ super "An alias referenced an unknown anchor: #{anchor_name}"
+ end
+ end
+
class DisallowedClass < Exception
def initialize action, klass_name
super "Tried to #{action} unspecified class: #{klass_name}"
diff --git a/ext/psych/lib/psych/handlers/document_stream.rb b/ext/psych/lib/psych/handlers/document_stream.rb
index 67da794093..b77115d074 100644
--- a/ext/psych/lib/psych/handlers/document_stream.rb
+++ b/ext/psych/lib/psych/handlers/document_stream.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/tree_builder'
+require_relative '../tree_builder'
module Psych
module Handlers
diff --git a/ext/psych/lib/psych/handlers/recorder.rb b/ext/psych/lib/psych/handlers/recorder.rb
index a8fc7b1144..c98724cb76 100644
--- a/ext/psych/lib/psych/handlers/recorder.rb
+++ b/ext/psych/lib/psych/handlers/recorder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/handler'
+require_relative '../handler'
module Psych
module Handlers
diff --git a/ext/psych/lib/psych/json/stream.rb b/ext/psych/lib/psych/json/stream.rb
index 2ebd3d7a66..24dd4b9baf 100644
--- a/ext/psych/lib/psych/json/stream.rb
+++ b/ext/psych/lib/psych/json/stream.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'psych/json/ruby_events'
-require 'psych/json/yaml_events'
+require_relative 'ruby_events'
+require_relative 'yaml_events'
module Psych
module JSON
diff --git a/ext/psych/lib/psych/json/tree_builder.rb b/ext/psych/lib/psych/json/tree_builder.rb
index 5c2ee8ca25..9a45f6b94c 100644
--- a/ext/psych/lib/psych/json/tree_builder.rb
+++ b/ext/psych/lib/psych/json/tree_builder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/json/yaml_events'
+require_relative 'yaml_events'
module Psych
module JSON
diff --git a/ext/psych/lib/psych/nodes.rb b/ext/psych/lib/psych/nodes.rb
index 5842c2e3e5..2fa52e0055 100644
--- a/ext/psych/lib/psych/nodes.rb
+++ b/ext/psych/lib/psych/nodes.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
-require 'psych/nodes/node'
-require 'psych/nodes/stream'
-require 'psych/nodes/document'
-require 'psych/nodes/sequence'
-require 'psych/nodes/scalar'
-require 'psych/nodes/mapping'
-require 'psych/nodes/alias'
+require_relative 'nodes/node'
+require_relative 'nodes/stream'
+require_relative 'nodes/document'
+require_relative 'nodes/sequence'
+require_relative 'nodes/scalar'
+require_relative 'nodes/mapping'
+require_relative 'nodes/alias'
module Psych
###
diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb
index 05cb08dac0..f44fce5f05 100644
--- a/ext/psych/lib/psych/nodes/node.rb
+++ b/ext/psych/lib/psych/nodes/node.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'stringio'
-require 'psych/class_loader'
-require 'psych/scalar_scanner'
+require_relative '../class_loader'
+require_relative '../scalar_scanner'
module Psych
module Nodes
@@ -46,8 +46,8 @@ module Psych
# Convert this node to Ruby.
#
# See also Psych::Visitors::ToRuby
- def to_ruby(symbolize_names: false, freeze: false)
- Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze).accept(self)
+ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self)
end
alias :transform :to_ruby
diff --git a/ext/psych/lib/psych/parser.rb b/ext/psych/lib/psych/parser.rb
index 39bc8289be..2181c730e5 100644
--- a/ext/psych/lib/psych/parser.rb
+++ b/ext/psych/lib/psych/parser.rb
@@ -48,5 +48,18 @@ module Psych
@handler = handler
@external_encoding = ANY
end
+
+ ###
+ # call-seq:
+ # parser.parse(yaml)
+ #
+ # Parse the YAML document contained in +yaml+. Events will be called on
+ # the handler set on the parser instance.
+ #
+ # See Psych::Parser and Psych::Parser#handler
+
+ def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>"
+ _native_parse @handler, yaml, path
+ end
end
end
diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb
index d565a336e8..3cb4bf3c7e 100644
--- a/ext/psych/lib/psych/scalar_scanner.rb
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'strscan'
module Psych
###
@@ -9,32 +8,39 @@ module Psych
TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/
# Taken from http://yaml.org/type/float.html
- FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
- |[-+]?\.(inf|Inf|INF)(?# infinity)
- |\.(nan|NaN|NAN)(?# not a number))$/x
+ # Base 60, [-+]inf and NaN are handled separately
+ FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
# Taken from http://yaml.org/type/int.html
- INTEGER = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
- |[-+]?0[0-7_,]+ (?# base 8)
- |[-+]?(?:0|[1-9][0-9_,]*) (?# base 10)
- |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
+ INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2)
+ |[-+]?0[0-7_]+ (?# base 8)
+ |[-+]?(0|[1-9][0-9_]*) (?# base 10)
+ |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
+
+ # Same as above, but allows commas.
+ # Not to YML spec, but kept for backwards compatibility
+ INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
+ |[-+]?0[0-7_,]+ (?# base 8)
+ |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
+ |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
attr_reader :class_loader
# Create a new scanner
- def initialize class_loader
+ def initialize class_loader, strict_integer: false
@symbol_cache = {}
@class_loader = class_loader
+ @strict_integer = strict_integer
end
# Tokenize +string+ returning the Ruby object
def tokenize string
return nil if string.empty?
return @symbol_cache[string] if @symbol_cache.key?(string)
-
+ integer_regex = @strict_integer ? INTEGER_STRICT : INTEGER_LEGACY
# Check for a String type, being careful not to get caught by hash keys, hex values, and
# special floats (e.g., -.inf).
- if string.match?(/^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/) || string.match?(/\n/)
+ if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
return string if string.length > 5
if string.match?(/^[^ytonf~]/i)
@@ -57,11 +63,11 @@ module Psych
elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
require 'date'
begin
- class_loader.date.strptime(string, '%Y-%m-%d')
+ class_loader.date.strptime(string, '%F', Date::GREGORIAN)
rescue ArgumentError
string
end
- elsif string.match?(/^\.inf$/i)
+ elsif string.match?(/^\+?\.inf$/i)
Float::INFINITY
elsif string.match?(/^-\.inf$/i)
-Float::INFINITY
@@ -89,9 +95,9 @@ module Psych
if string.match?(/\A[-+]?\.\Z/)
string
else
- Float(string.gsub(/[,_]|\.([Ee]|$)/, '\1'))
+ Float(string.delete(',_').gsub(/\.([Ee]|$)/, '\1'))
end
- elsif string.match?(INTEGER)
+ elsif string.match?(integer_regex)
parse_int string
else
string
@@ -101,7 +107,7 @@ module Psych
###
# Parse and return an int from +string+
def parse_int string
- Integer(string.gsub(/[,_]/, ''))
+ Integer(string.delete(',_'))
end
###
diff --git a/ext/psych/lib/psych/syntax_error.rb b/ext/psych/lib/psych/syntax_error.rb
index 1598e6ff36..a4c9c4a376 100644
--- a/ext/psych/lib/psych/syntax_error.rb
+++ b/ext/psych/lib/psych/syntax_error.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/exception'
+require_relative 'exception'
module Psych
class SyntaxError < Psych::Exception
diff --git a/ext/psych/lib/psych/tree_builder.rb b/ext/psych/lib/psych/tree_builder.rb
index 47a1695643..83115bd721 100644
--- a/ext/psych/lib/psych/tree_builder.rb
+++ b/ext/psych/lib/psych/tree_builder.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/handler'
+require_relative 'handler'
module Psych
###
@@ -41,7 +41,7 @@ module Psych
Sequence
Mapping
}.each do |node|
- class_eval %{
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
def start_#{node.downcase}(anchor, tag, implicit, style)
n = Nodes::#{node}.new(anchor, tag, implicit, style)
set_start_location(n)
@@ -54,7 +54,7 @@ module Psych
set_end_location(n)
n
end
- }
+ RUBY
end
###
diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb
index 513d010903..b9e8d9ef11 100644
--- a/ext/psych/lib/psych/versions.rb
+++ b/ext/psych/lib/psych/versions.rb
@@ -2,9 +2,9 @@
module Psych
# The version of Psych you are using
- VERSION = '4.0.1'
+ VERSION = '5.1.2'
if RUBY_ENGINE == 'jruby'
- DEFAULT_SNAKEYAML_VERSION = '1.28'.freeze
+ DEFAULT_SNAKEYAML_VERSION = '2.7'.freeze
end
end
diff --git a/ext/psych/lib/psych/visitors.rb b/ext/psych/lib/psych/visitors.rb
index e2b084daee..508290d862 100644
--- a/ext/psych/lib/psych/visitors.rb
+++ b/ext/psych/lib/psych/visitors.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'psych/visitors/visitor'
-require 'psych/visitors/to_ruby'
-require 'psych/visitors/emitter'
-require 'psych/visitors/yaml_tree'
-require 'psych/visitors/json_tree'
-require 'psych/visitors/depth_first'
+require_relative 'visitors/visitor'
+require_relative 'visitors/to_ruby'
+require_relative 'visitors/emitter'
+require_relative 'visitors/yaml_tree'
+require_relative 'visitors/json_tree'
+require_relative 'visitors/depth_first'
diff --git a/ext/psych/lib/psych/visitors/json_tree.rb b/ext/psych/lib/psych/visitors/json_tree.rb
index 9912cb1362..979fc100bd 100644
--- a/ext/psych/lib/psych/visitors/json_tree.rb
+++ b/ext/psych/lib/psych/visitors/json_tree.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'psych/json/ruby_events'
+require_relative '../json/ruby_events'
module Psych
module Visitors
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 4de7f80d33..f0fda9bdbc 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'psych/scalar_scanner'
-require 'psych/class_loader'
-require 'psych/exception'
+require_relative '../scalar_scanner'
+require_relative '../class_loader'
+require_relative '../exception'
unless defined?(Regexp::NOENCODING)
Regexp::NOENCODING = 32
@@ -12,9 +12,9 @@ module Psych
###
# This class walks a YAML AST, converting each node to Ruby
class ToRuby < Psych::Visitors::Visitor
- def self.create(symbolize_names: false, freeze: false)
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false)
class_loader = ClassLoader.new
- scanner = ScalarScanner.new class_loader
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
end
@@ -80,7 +80,9 @@ module Psych
when "!ruby/object:DateTime"
class_loader.date_time
require 'date' unless defined? DateTime
- @ss.parse_time(o.value).to_datetime
+ t = @ss.parse_time(o.value)
+ DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
+ (t.subsec/86400)
when '!ruby/encoding'
::Encoding.find o.value
when "!ruby/object:Complex"
@@ -99,7 +101,7 @@ module Psych
source = $1
options = 0
lang = nil
- ($2 || '').split('').each do |option|
+ $2&.each_char do |option|
case option
when 'x' then options |= Regexp::EXTENDED
when 'i' then options |= Regexp::IGNORECASE
@@ -323,7 +325,7 @@ module Psych
end
def visit_Psych_Nodes_Alias o
- @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
+ @st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
end
private
@@ -427,7 +429,7 @@ module Psych
class NoAliasRuby < ToRuby
def visit_Psych_Nodes_Alias o
- raise BadAlias, "Unknown alias: #{o.anchor}"
+ raise AliasesNotEnabled
end
end
end
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
index 05748dd81c..a2ebc4d781 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'psych/tree_builder'
-require 'psych/scalar_scanner'
-require 'psych/class_loader'
+require_relative '../tree_builder'
+require_relative '../scalar_scanner'
+require_relative '../class_loader'
module Psych
module Visitors
@@ -15,30 +15,25 @@ module Psych
class YAMLTree < Psych::Visitors::Visitor
class Registrar # :nodoc:
def initialize
- @obj_to_id = {}
- @obj_to_node = {}
- @targets = []
+ @obj_to_id = {}.compare_by_identity
+ @obj_to_node = {}.compare_by_identity
@counter = 0
end
def register target, node
- return unless target.respond_to? :object_id
- @targets << target
- @obj_to_node[target.object_id] = node
+ @obj_to_node[target] = node
end
def key? target
- @obj_to_node.key? target.object_id
- rescue NoMethodError
- false
+ @obj_to_node.key? target
end
def id_for target
- @obj_to_id[target.object_id] ||= (@counter += 1)
+ @obj_to_id[target] ||= (@counter += 1)
end
def node_for target
- @obj_to_node[target.object_id]
+ @obj_to_node[target]
end
end
@@ -70,6 +65,7 @@ module Psych
fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.")
end
end
+ @stringify_names = options[:stringify_names]
@coders = []
@dispatch_cache = Hash.new do |h,klass|
@@ -192,12 +188,13 @@ module Psych
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
end
+ def visit_Date o
+ register o, visit_Integer(o.gregorian)
+ end
+
def visit_DateTime o
- formatted = if o.offset.zero?
- o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
- else
- o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
- end
+ t = o.italy
+ formatted = format_time t, t.offset.zero?
tag = '!ruby/object:DateTime'
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
end
@@ -235,7 +232,6 @@ module Psych
end
alias :visit_TrueClass :visit_Integer
alias :visit_FalseClass :visit_Integer
- alias :visit_Date :visit_Integer
def visit_Float o
if o.nan?
@@ -272,6 +268,8 @@ module Psych
tag = 'tag:yaml.org,2002:str'
plain = false
quote = false
+ elsif o == 'y' || o == 'Y' || o == 'n' || o == 'N'
+ style = Nodes::Scalar::DOUBLE_QUOTED
elsif @line_width && o.length > @line_width
style = Nodes::Scalar::FOLDED
elsif o =~ /^[^[:word:]][^"]*$/
@@ -326,7 +324,7 @@ module Psych
if o.class == ::Hash
register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
- accept k
+ accept(@stringify_names && Symbol === k ? k.to_s : k)
accept v
end
@emitter.end_mapping
@@ -339,7 +337,7 @@ module Psych
register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
- accept k
+ accept(@stringify_names && Symbol === k ? k.to_s : k)
accept v
end
@@ -480,8 +478,8 @@ module Psych
@emitter.end_mapping
end
- def format_time time
- if time.utc?
+ def format_time time, utc = time.utc?
+ if utc
time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
else
time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
@@ -566,7 +564,7 @@ module Psych
raise BadAlias, "Tried to dump an aliased object"
end
- unless @permitted_classes[target.class]
+ unless Symbol === target || @permitted_classes[target.class]
raise DisallowedClass.new('dump', target.class.name || target.class.inspect)
end
@@ -574,7 +572,7 @@ module Psych
end
def visit_Symbol sym
- unless @permitted_symbols[sym]
+ unless @permitted_classes[Symbol] || @permitted_symbols[sym]
raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})")
end