Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK ! áõQb¼ ¼ lib/psych/versions.rbnu „[µü¤ # frozen_string_literal: true
module Psych
# The version of Psych you are using
VERSION = '5.3.1'
if RUBY_ENGINE == 'jruby'
DEFAULT_SNAKEYAML_VERSION = '2.10'.freeze
end
end
PK ! )£´) ) lib/psych/nodes/mapping.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Nodes
###
# This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping].
#
# A Psych::Nodes::Mapping node may have 0 or more children, but must have
# an even number of children. Here are the valid children a
# Psych::Nodes::Mapping node may have:
#
# * Psych::Nodes::Sequence
# * Psych::Nodes::Mapping
# * Psych::Nodes::Scalar
# * Psych::Nodes::Alias
class Mapping < Psych::Nodes::Node
# Any Map Style
ANY = 0
# Block Map Style
BLOCK = 1
# Flow Map Style
FLOW = 2
# The optional anchor for this mapping
attr_accessor :anchor
# The optional tag for this mapping
attr_accessor :tag
# Is this an implicit mapping?
attr_accessor :implicit
# The style of this mapping
attr_accessor :style
###
# Create a new Psych::Nodes::Mapping object.
#
# +anchor+ is the anchor associated with the map or +nil+.
# +tag+ is the tag associated with the map or +nil+.
# +implicit+ is a boolean indicating whether or not the map was implicitly
# started.
# +style+ is an integer indicating the mapping style.
#
# == See Also
# See also Psych::Handler#start_mapping
def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
super()
@anchor = anchor
@tag = tag
@implicit = implicit
@style = style
end
def mapping?; true; end
end
end
end
PK ! Ϧ[ lib/psych/nodes/stream.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Nodes
###
# Represents a YAML stream. This is the root node for any YAML parse
# tree. This node must have one or more child nodes. The only valid
# child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
class Stream < Psych::Nodes::Node
# Encodings supported by Psych (and libyaml)
# Any encoding
ANY = Psych::Parser::ANY
# UTF-8 encoding
UTF8 = Psych::Parser::UTF8
# UTF-16LE encoding
UTF16LE = Psych::Parser::UTF16LE
# UTF-16BE encoding
UTF16BE = Psych::Parser::UTF16BE
# The encoding used for this stream
attr_accessor :encoding
###
# Create a new Psych::Nodes::Stream node with an +encoding+ that
# defaults to Psych::Nodes::Stream::UTF8.
#
# See also Psych::Handler#start_stream
def initialize encoding = UTF8
super()
@encoding = encoding
end
def stream?; true; end
end
end
end
PK ! ·ÏA A lib/psych/nodes/document.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Nodes
###
# This represents a YAML Document. This node must be a child of
# Psych::Nodes::Stream. A Psych::Nodes::Document must have one child,
# and that child may be one of the following:
#
# * Psych::Nodes::Sequence
# * Psych::Nodes::Mapping
# * Psych::Nodes::Scalar
class Document < Psych::Nodes::Node
# The version of the YAML document
attr_accessor :version
# A list of tag directives for this document
attr_accessor :tag_directives
# Was this document implicitly created?
attr_accessor :implicit
# Is the end of the document implicit?
attr_accessor :implicit_end
###
# Create a new Psych::Nodes::Document object.
#
# +version+ is a list indicating the YAML version.
# +tags_directives+ is a list of tag directive declarations
# +implicit+ is a flag indicating whether the document will be implicitly
# started.
#
# == Example:
# This creates a YAML document object that represents a YAML 1.1 document
# with one tag directive, and has an implicit start:
#
# Psych::Nodes::Document.new(
# [1,1],
# [["!", "tag:tenderlovemaking.com,2009:"]],
# true
# )
#
# == See Also
# See also Psych::Handler#start_document
def initialize version = [], tag_directives = [], implicit = false
super()
@version = version
@tag_directives = tag_directives
@implicit = implicit
@implicit_end = true
end
###
# Returns the root node. A Document may only have one root node:
# http://yaml.org/spec/1.1/#id898031
def root
children.first
end
def document?; true; end
end
end
end
PK ! ¨Ìׄ „ lib/psych/nodes/scalar.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Nodes
###
# This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081].
#
# This node type is a terminal node and should not have any children.
class Scalar < Psych::Nodes::Node
# Any style scalar, the emitter chooses
ANY = 0
# Plain scalar style
PLAIN = 1
# Single quoted style
SINGLE_QUOTED = 2
# Double quoted style
DOUBLE_QUOTED = 3
# Literal style
LITERAL = 4
# Folded style
FOLDED = 5
# The scalar value
attr_accessor :value
# The anchor value (if there is one)
attr_accessor :anchor
# The tag value (if there is one)
attr_accessor :tag
# Is this a plain scalar?
attr_accessor :plain
# Is this scalar quoted?
attr_accessor :quoted
# The style of this scalar
attr_accessor :style
###
# Create a new Psych::Nodes::Scalar object.
#
# +value+ is the string value of the scalar
# +anchor+ is an associated anchor or nil
# +tag+ is an associated tag or nil
# +plain+ is a boolean value
# +quoted+ is a boolean value
# +style+ is an integer indicating the string style
#
# == See Also
#
# See also Psych::Handler#scalar
def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY
@value = value
@anchor = anchor
@tag = tag
@plain = plain
@quoted = quoted
@style = style
end
def scalar?; true; end
end
end
end
PK ! ‚ɉ lib/psych/nodes/alias.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Nodes
###
# This class represents a {YAML Alias}[http://yaml.org/spec/1.1/#alias].
# It points to an +anchor+.
#
# A Psych::Nodes::Alias is a terminal node and may have no children.
class Alias < Psych::Nodes::Node
# The anchor this alias links to
attr_accessor :anchor
# Create a new Alias that points to an +anchor+
def initialize anchor
@anchor = anchor
end
def alias?; true; end
end
end
end
PK ! ªë¯! ! lib/psych/nodes/sequence.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Nodes
###
# This class represents a
# {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax].
#
# A YAML sequence is basically a list, and looks like this:
#
# %YAML 1.1
# ---
# - I am
# - a Sequence
#
# A YAML sequence may have an anchor like this:
#
# %YAML 1.1
# ---
# &A [
# "This sequence",
# "has an anchor"
# ]
#
# A YAML sequence may also have a tag like this:
#
# %YAML 1.1
# ---
# !!seq [
# "This sequence",
# "has a tag"
# ]
#
# This class represents a sequence in a YAML document. A
# Psych::Nodes::Sequence node may have 0 or more children. Valid children
# for this node are:
#
# * Psych::Nodes::Sequence
# * Psych::Nodes::Mapping
# * Psych::Nodes::Scalar
# * Psych::Nodes::Alias
class Sequence < Psych::Nodes::Node
# Any Styles, emitter chooses
ANY = 0
# Block style sequence
BLOCK = 1
# Flow style sequence
FLOW = 2
# The anchor for this sequence (if any)
attr_accessor :anchor
# The tag name for this sequence (if any)
attr_accessor :tag
# Is this sequence started implicitly?
attr_accessor :implicit
# The sequence style used
attr_accessor :style
###
# Create a new object representing a YAML sequence.
#
# +anchor+ is the anchor associated with the sequence or nil.
# +tag+ is the tag associated with the sequence or nil.
# +implicit+ a boolean indicating whether or not the sequence was
# implicitly started.
# +style+ is an integer indicating the list style.
#
# See Psych::Handler#start_sequence
def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
super()
@anchor = anchor
@tag = tag
@implicit = implicit
@style = style
end
def sequence?; true; end
end
end
end
PK ! +‡í=ÿ ÿ lib/psych/nodes/node.rbnu „[µü¤ # frozen_string_literal: true
require_relative '../class_loader'
require_relative '../scalar_scanner'
module Psych
module Nodes
###
# The base class for any Node in a YAML parse tree. This class should
# never be instantiated.
class Node
include Enumerable
# The children of this node
attr_reader :children
# An associated tag
attr_reader :tag
# The line number where this node start
attr_accessor :start_line
# The column number where this node start
attr_accessor :start_column
# The line number where this node ends
attr_accessor :end_line
# The column number where this node ends
attr_accessor :end_column
# Create a new Psych::Nodes::Node
def initialize
@children = []
end
###
# Iterate over each node in the tree. Yields each node to +block+ depth
# first.
def each &block
return enum_for :each unless block_given?
Visitors::DepthFirst.new(block).accept self
end
###
# Convert this node to Ruby.
#
# See also Psych::Visitors::ToRuby
def to_ruby(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true)
Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols).accept(self)
end
alias :transform :to_ruby
###
# Convert this node to YAML.
#
# See also Psych::Visitors::Emitter
def yaml io = nil, options = {}
require "stringio" unless defined?(StringIO)
real_io = io || StringIO.new(''.encode('utf-8'))
Visitors::Emitter.new(real_io, options).accept self
return real_io.string unless io
io
end
alias :to_yaml :yaml
def alias?; false; end
def document?; false; end
def mapping?; false; end
def scalar?; false; end
def sequence?; false; end
def stream?; false; end
end
end
end
PK ! ©Ø'K¾ ¾ lib/psych/y.rbnu „[µü¤ # frozen_string_literal: true
module Kernel
###
# An alias for Psych.dump_stream meant to be used with IRB.
def y *objects
puts Psych.dump_stream(*objects)
end
private :y
end
PK ! ‚=nH? ? lib/psych/class_loader.rbnu „[µü¤ # frozen_string_literal: true
require_relative 'omap'
require_relative 'set'
module Psych
class ClassLoader # :nodoc:
BIG_DECIMAL = 'BigDecimal'
COMPLEX = 'Complex'
DATA = 'Data' unless RUBY_VERSION < "3.2"
DATE = 'Date'
DATE_TIME = 'DateTime'
EXCEPTION = 'Exception'
OBJECT = 'Object'
PSYCH_OMAP = 'Psych::Omap'
PSYCH_SET = 'Psych::Set'
RANGE = 'Range'
RATIONAL = 'Rational'
REGEXP = 'Regexp'
STRUCT = 'Struct'
SYMBOL = 'Symbol'
def initialize
@cache = CACHE.dup
end
def load klassname
return nil if !klassname || klassname.empty?
find klassname
end
def symbolize sym
symbol
sym.to_sym
end
constants.each do |const|
konst = const_get const
class_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{const.to_s.downcase}
load #{konst.inspect}
end
RUBY
end
private
def find klassname
@cache[klassname] ||= resolve(klassname)
end
def resolve klassname
name = klassname
retried = false
begin
path2class(name)
rescue ArgumentError, NameError => ex
unless retried
name = "Struct::#{name}"
retried = ex
retry
end
raise retried
end
end
CACHE = Hash[constants.map { |const|
val = const_get const
begin
[val, ::Object.const_get(val)]
rescue
nil
end
}.compact].freeze
class Restricted < ClassLoader
def initialize classes, symbols
@classes = classes
@symbols = symbols
super()
end
def symbolize sym
return super if @symbols.empty?
if @symbols.include? sym
super
else
raise DisallowedClass.new('load', 'Symbol')
end
end
private
def find klassname
if @classes.include? klassname
super
else
raise DisallowedClass.new('load', klassname)
end
end
end
end
end
PK ! ÔµüÖ Ö lib/psych/exception.rbnu „[µü¤ # frozen_string_literal: true
module Psych
class Exception < RuntimeError
end
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}"
end
end
end
PK ! MA+¾ ¾ lib/psych/visitors/visitor.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Visitors
class Visitor
def accept target
visit target
end
private
# @api private
def self.dispatch_cache
Hash.new do |hash, klass|
hash[klass] = :"visit_#{klass.name.gsub('::', '_')}"
end.compare_by_identity
end
if defined?(Ractor)
def dispatch
@dispatch_cache ||= (Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache)
end
else
DISPATCH = dispatch_cache
def dispatch
DISPATCH
end
end
def visit target
send dispatch[target.class], target
end
end
end
end
PK ! «›{>Q Q lib/psych/visitors/json_tree.rbnu „[µü¤ # frozen_string_literal: true
require_relative '../json/ruby_events'
module Psych
module Visitors
class JSONTree < YAMLTree
include Psych::JSON::RubyEvents
def self.create options = {}
emitter = Psych::JSON::TreeBuilder.new
class_loader = ClassLoader.new
ss = ScalarScanner.new class_loader
new(emitter, ss, options)
end
def accept target
if target.respond_to?(:encode_with)
dump_coder target
else
send(@dispatch_cache[target.class], target)
end
end
end
end
end
PK ! ¿ÛÚZÊ Ê lib/psych/visitors/emitter.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Visitors
class Emitter < Psych::Visitors::Visitor
def initialize io, options = {}
opts = [:indentation, :canonical, :line_width].find_all { |opt|
options.key?(opt)
}
if opts.empty?
@handler = Psych::Emitter.new io
else
du = Handler::DumperOptions.new
opts.each { |option| du.send :"#{option}=", options[option] }
@handler = Psych::Emitter.new io, du
end
end
def visit_Psych_Nodes_Stream o
@handler.start_stream o.encoding
o.children.each { |c| accept c }
@handler.end_stream
end
def visit_Psych_Nodes_Document o
@handler.start_document o.version, o.tag_directives, o.implicit
o.children.each { |c| accept c }
@handler.end_document o.implicit_end
end
def visit_Psych_Nodes_Scalar o
@handler.scalar o.value, o.anchor, o.tag, o.plain, o.quoted, o.style
end
def visit_Psych_Nodes_Sequence o
@handler.start_sequence o.anchor, o.tag, o.implicit, o.style
o.children.each { |c| accept c }
@handler.end_sequence
end
def visit_Psych_Nodes_Mapping o
@handler.start_mapping o.anchor, o.tag, o.implicit, o.style
o.children.each { |c| accept c }
@handler.end_mapping
end
def visit_Psych_Nodes_Alias o
@handler.alias o.anchor
end
end
end
end
PK ! Rÿç(r r ! lib/psych/visitors/depth_first.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Visitors
class DepthFirst < Psych::Visitors::Visitor
def initialize block
@block = block
end
private
def nary o
o.children.each { |x| visit x }
@block.call o
end
alias :visit_Psych_Nodes_Stream :nary
alias :visit_Psych_Nodes_Document :nary
alias :visit_Psych_Nodes_Sequence :nary
alias :visit_Psych_Nodes_Mapping :nary
def terminal o
@block.call o
end
alias :visit_Psych_Nodes_Scalar :terminal
alias :visit_Psych_Nodes_Alias :terminal
end
end
end
PK ! ö©G G lib/psych/visitors/yaml_tree.rbnu „[µü¤ # frozen_string_literal: true
require_relative '../tree_builder'
require_relative '../scalar_scanner'
require_relative '../class_loader'
module Psych
module Visitors
###
# YAMLTree builds a YAML ast given a Ruby object. For example:
#
# builder = Psych::Visitors::YAMLTree.new
# builder << { :foo => 'bar' }
# builder.tree # => # v }
@emitter.end_sequence
end
def visit_Encoding o
tag = "!ruby/encoding"
@emitter.scalar o.name, nil, tag, false, false, Nodes::Scalar::ANY
end
def visit_Object o
tag = Psych.dump_tags[o.class]
unless tag
klass = o.class == Object ? nil : o.class.name
tag = ['!ruby/object', klass].compact.join(':')
end
map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
register(o, map)
dump_ivars o
@emitter.end_mapping
end
alias :visit_Delegator :visit_Object
def visit_Data o
ivars = o.instance_variables
if ivars.empty?
tag = ['!ruby/data', o.class.name].compact.join(':')
register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
o.members.each do |member|
@emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
accept o.send member
end
@emitter.end_mapping
else
tag = ['!ruby/data-with-ivars', o.class.name].compact.join(':')
node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
register(o, node)
# Dump the members
accept 'members'
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
o.members.each do |member|
@emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
accept o.send member
end
@emitter.end_mapping
# Dump the ivars
accept 'ivars'
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
ivars.each do |ivar|
accept ivar.to_s
accept o.instance_variable_get ivar
end
@emitter.end_mapping
@emitter.end_mapping
end
end unless RUBY_VERSION < "3.2"
def visit_Struct o
tag = ['!ruby/struct', o.class.name].compact.join(':')
register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
o.members.each do |member|
@emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
accept o[member]
end
dump_ivars o
@emitter.end_mapping
end
def visit_Exception o
dump_exception o, o.message.to_s
end
def visit_NameError o
dump_exception o, o.message.to_s
end
def visit_Regexp o
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
end
def visit_Date o
formatted = format_date o
register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
end
def visit_DateTime o
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
def visit_Time o
formatted = format_time o
register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
end
def visit_Rational o
register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
[
'denominator', o.denominator.to_s,
'numerator', o.numerator.to_s
].each do |m|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
end
@emitter.end_mapping
end
def visit_Complex o
register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
end
@emitter.end_mapping
end
def visit_Integer o
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
end
alias :visit_TrueClass :visit_Integer
alias :visit_FalseClass :visit_Integer
def visit_Float o
if o.nan?
@emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
elsif o.infinite?
@emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
nil, nil, true, false, Nodes::Scalar::ANY)
else
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
end
end
def visit_BigDecimal o
@emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
end
def visit_String o
plain = true
quote = true
style = Nodes::Scalar::PLAIN
tag = nil
if binary?(o)
o = [o].pack('m0')
tag = '!binary' # FIXME: change to below when syck is removed
#tag = 'tag:yaml.org,2002:binary'
style = Nodes::Scalar::LITERAL
plain = false
quote = false
elsif o.match?(/\n(?!\Z)/) # match \n except blank line at the end of string
style = Nodes::Scalar::LITERAL
elsif o == '<<'
style = Nodes::Scalar::SINGLE_QUOTED
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.match?(/^[^[:word:]][^"]*$/)
style = Nodes::Scalar::DOUBLE_QUOTED
elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/.match?(o)
style = Nodes::Scalar::SINGLE_QUOTED
end
is_primitive = o.class == ::String
ivars = is_primitive ? [] : o.instance_variables
if ivars.empty?
unless is_primitive
tag = "!ruby/string:#{o.class}"
plain = false
quote = false
end
@emitter.scalar o, nil, tag, plain, quote, style
else
maptag = '!ruby/string'.dup
maptag << ":#{o.class}" unless o.class == ::String
register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK)
@emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
@emitter.scalar o, nil, tag, plain, quote, style
dump_ivars o
@emitter.end_mapping
end
end
def visit_Module o
raise TypeError, "can't dump anonymous module: #{o}" unless o.name
register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
end
def visit_Class o
raise TypeError, "can't dump anonymous class: #{o}" unless o.name
register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
end
def visit_Range o
register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
accept m
end
@emitter.end_mapping
end
def visit_Hash o
if o.class == ::Hash
register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
accept(@stringify_names && Symbol === k ? k.to_s : k)
accept v
end
@emitter.end_mapping
else
visit_hash_subclass o
end
end
def visit_Psych_Set o
register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
o.each do |k,v|
accept(@stringify_names && Symbol === k ? k.to_s : k)
accept v
end
@emitter.end_mapping
end
def visit_Array o
if o.class == ::Array
visit_Enumerator o
else
visit_array_subclass o
end
end
def visit_Enumerator o
register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
o.each { |c| accept c }
@emitter.end_sequence
end
def visit_NilClass o
@emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY)
end
def visit_Symbol o
if o.empty?
@emitter.scalar "", nil, '!ruby/symbol', false, false, Nodes::Scalar::ANY
else
@emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
end
end
def visit_BasicObject o
tag = Psych.dump_tags[o.class]
tag ||= "!ruby/marshalable:#{o.class.name}"
map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
register(o, map)
o.marshal_dump.each(&method(:accept))
@emitter.end_mapping
end
private
def binary? string
string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?
end
def visit_array_subclass o
tag = "!ruby/array:#{o.class}"
ivars = o.instance_variables
if ivars.empty?
node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
register o, node
o.each { |c| accept c }
@emitter.end_sequence
else
node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
register o, node
# Dump the internal list
accept 'internal'
@emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
o.each { |c| accept c }
@emitter.end_sequence
# Dump the ivars
accept 'ivars'
@emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
ivars.each do |ivar|
accept ivar
accept o.instance_variable_get ivar
end
@emitter.end_mapping
@emitter.end_mapping
end
end
def visit_hash_subclass o
ivars = o.instance_variables
if ivars.any?
tag = "!ruby/hash-with-ivars:#{o.class}"
node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
register(o, node)
# Dump the ivars
accept 'ivars'
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
o.instance_variables.each do |ivar|
accept ivar
accept o.instance_variable_get ivar
end
@emitter.end_mapping
# Dump the elements
accept 'elements'
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
o.each do |k,v|
accept k
accept v
end
@emitter.end_mapping
@emitter.end_mapping
else
tag = "!ruby/hash:#{o.class}"
node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
register(o, node)
o.each do |k,v|
accept k
accept v
end
@emitter.end_mapping
end
end
def dump_list o
end
def dump_exception o, msg
tag = ['!ruby/exception', o.class.name].join ':'
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
if msg
@emitter.scalar 'message', nil, nil, true, false, Nodes::Scalar::ANY
accept msg
end
@emitter.scalar 'backtrace', nil, nil, true, false, Nodes::Scalar::ANY
accept o.backtrace
dump_ivars o
@emitter.end_mapping
end
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")
end
end
def format_date date
date.strftime("%Y-%m-%d")
end
def register target, yaml_obj
@st.register target, yaml_obj
yaml_obj
end
def dump_coder o
@coders << o
tag = Psych.dump_tags[o.class]
unless tag
klass = o.class == Object ? nil : o.class.name
tag = ['!ruby/object', klass].compact.join(':')
end
c = Psych::Coder.new(tag)
o.encode_with(c)
emit_coder c, o
end
def emit_coder c, o
case c.type
when :scalar
@emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, c.style
when :seq
@emitter.start_sequence nil, c.tag, c.tag.nil?, c.style
c.seq.each do |thing|
accept thing
end
@emitter.end_sequence
when :map
register o, @emitter.start_mapping(nil, c.tag, c.implicit, c.style)
c.map.each do |k,v|
accept k
accept v
end
@emitter.end_mapping
when :object
accept c.object
end
end
def dump_ivars target
target.instance_variables.each do |iv|
@emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY)
accept target.instance_variable_get(iv)
end
end
end
class RestrictedYAMLTree < YAMLTree
DEFAULT_PERMITTED_CLASSES = {
TrueClass => true,
FalseClass => true,
NilClass => true,
Integer => true,
Float => true,
String => true,
Array => true,
Hash => true,
}.compare_by_identity.freeze
def initialize emitter, ss, options
super
@permitted_classes = DEFAULT_PERMITTED_CLASSES.dup
Array(options[:permitted_classes]).each do |klass|
@permitted_classes[klass] = true
end
@permitted_symbols = {}.compare_by_identity
Array(options[:permitted_symbols]).each do |symbol|
@permitted_symbols[symbol] = true
end
@aliases = options.fetch(:aliases, false)
end
def accept target
if !@aliases && @st.key?(target)
raise BadAlias, "Tried to dump an aliased object"
end
unless Symbol === target || @permitted_classes[target.class]
raise DisallowedClass.new('dump', target.class.name || target.class.inspect)
end
super
end
def visit_Symbol sym
unless @permitted_classes[Symbol] || @permitted_symbols[sym]
raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})")
end
super
end
end
end
end
PK ! ,Nk˜ø6 ø6 lib/psych/visitors/to_ruby.rbnu „[µü¤ # frozen_string_literal: true
require_relative '../scalar_scanner'
require_relative '../class_loader'
require_relative '../exception'
unless defined?(Regexp::NOENCODING)
Regexp::NOENCODING = 32
end
module Psych
module Visitors
###
# This class walks a YAML AST, converting each node to Ruby
class ToRuby < Psych::Visitors::Visitor
unless RUBY_VERSION < "3.2"
DATA_INITIALIZE = Data.instance_method(:initialize)
end
def self.create(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true)
class_loader = ClassLoader.new
scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
end
attr_reader :class_loader
def initialize ss, class_loader, symbolize_names: false, freeze: false
super()
@st = {}
@ss = ss
@load_tags = Psych.load_tags
@domain_types = Psych.domain_types
@class_loader = class_loader
@symbolize_names = symbolize_names
@freeze = freeze
end
def accept target
result = super
unless @domain_types.empty? || !target.tag
key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
key = "tag:#{key}" unless key.match?(/^(?:tag:|x-private)/)
if @domain_types.key? key
value, block = @domain_types[key]
result = block.call value, result
end
end
result = deduplicate(result).freeze if @freeze
result
end
def deserialize o
if klass = resolve_class(@load_tags[o.tag])
instance = klass.allocate
if instance.respond_to?(:init_with)
coder = Psych::Coder.new(o.tag)
coder.scalar = o.value
instance.init_with coder
end
return instance
end
return o.value if o.quoted
return @ss.tokenize(o.value) unless o.tag
case o.tag
when '!binary', 'tag:yaml.org,2002:binary'
o.value.unpack('m').first
when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
klass = resolve_class($1)
if klass
klass.allocate.replace o.value
else
o.value
end
when '!ruby/object:BigDecimal'
require 'bigdecimal' unless defined? BigDecimal
class_loader.big_decimal._load o.value
when "!ruby/object:DateTime"
class_loader.date_time
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"
class_loader.complex
Complex(o.value)
when "!ruby/object:Rational"
class_loader.rational
Rational(o.value)
when "!ruby/class", "!ruby/module"
resolve_class o.value
when "tag:yaml.org,2002:float", "!float"
Float(@ss.tokenize(o.value))
when "!ruby/regexp"
klass = class_loader.regexp
matches = /^\/(?.*)\/(?[mixn]*)$/m.match(o.value)
source = matches[:string].gsub('\/', '/')
options = 0
lang = nil
matches[:options].each_char do |option|
case option
when 'x' then options |= Regexp::EXTENDED
when 'i' then options |= Regexp::IGNORECASE
when 'm' then options |= Regexp::MULTILINE
when 'n' then options |= Regexp::NOENCODING
else lang = option
end
end
klass.new(*[source, options, lang].compact)
when "!ruby/range"
klass = class_loader.range
args = o.value.split(/([.]{2,3})/, 2).map { |s|
accept Nodes::Scalar.new(s)
}
args.push(args.delete_at(1) == '...')
klass.new(*args)
when /^!ruby\/sym(bol)?:?(.*)?$/
class_loader.symbolize o.value
else
@ss.tokenize o.value
end
end
private :deserialize
def visit_Psych_Nodes_Scalar o
register o, deserialize(o)
end
def visit_Psych_Nodes_Sequence o
if klass = resolve_class(@load_tags[o.tag])
instance = klass.allocate
if instance.respond_to?(:init_with)
coder = Psych::Coder.new(o.tag)
coder.seq = o.children.map { |c| accept c }
instance.init_with coder
end
return instance
end
case o.tag
when nil
register_empty(o)
when '!omap', 'tag:yaml.org,2002:omap'
map = register(o, Psych::Omap.new)
o.children.each { |a|
map[accept(a.children.first)] = accept a.children.last
}
map
when /^!(?:seq|ruby\/array):(.*)$/
klass = resolve_class($1)
list = register(o, klass.allocate)
o.children.each { |c| list.push accept c }
list
else
register_empty(o)
end
end
def visit_Psych_Nodes_Mapping o
if @load_tags[o.tag]
return revive(resolve_class(@load_tags[o.tag]), o)
end
return revive_hash(register(o, {}), o) unless o.tag
case o.tag
when /^!ruby\/struct:?(.*)?$/
klass = resolve_class($1) if $1
if klass
s = register(o, klass.allocate)
members = {}
struct_members = s.members.map { |x| class_loader.symbolize x }
o.children.each_slice(2) do |k,v|
member = accept(k)
value = accept(v)
if struct_members.include?(class_loader.symbolize(member))
s.send("#{member}=", value)
else
members[member.to_s.sub(/^@/, '')] = value
end
end
init_with(s, members, o)
else
klass = class_loader.struct
members = o.children.map { |c| accept c }
h = Hash[*members]
s = klass.new(*h.map { |k,v|
class_loader.symbolize k
}).new(*h.map { |k,v| v })
register(o, s)
s
end
when /^!ruby\/data(-with-ivars)?(?::(.*))?$/
data = register(o, resolve_class($2).allocate) if $2
members = {}
if $1 # data-with-ivars
ivars = {}
o.children.each_slice(2) do |type, vars|
case accept(type)
when 'members'
revive_data_members(members, vars)
data ||= allocate_anon_data(o, members)
when 'ivars'
revive_hash(ivars, vars)
end
end
ivars.each do |ivar, v|
data.instance_variable_set ivar, v
end
else
revive_data_members(members, o)
end
data ||= allocate_anon_data(o, members)
DATA_INITIALIZE.bind_call(data, **members)
data.freeze
data
when /^!ruby\/object:?(.*)?$/
name = $1 || 'Object'
if name == 'Complex'
class_loader.complex
h = Hash[*o.children.map { |c| accept c }]
register o, Complex(h['real'], h['image'])
elsif name == 'Rational'
class_loader.rational
h = Hash[*o.children.map { |c| accept c }]
register o, Rational(h['numerator'], h['denominator'])
elsif name == 'Hash'
revive_hash(register(o, {}), o)
else
obj = revive((resolve_class(name) || class_loader.object), o)
obj
end
when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
klass = resolve_class($1)
members = {}
string = nil
o.children.each_slice(2) do |k,v|
key = accept k
value = accept v
if key == 'str'
if klass
string = klass.allocate.replace value
else
string = value
end
register(o, string)
else
members[key] = value
end
end
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
when /^!ruby\/array:(.*)$/
klass = resolve_class($1)
list = register(o, klass.allocate)
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
list.replace members['internal']
members['ivars'].each do |ivar, v|
list.instance_variable_set ivar, v
end
list
when '!ruby/range'
klass = class_loader.range
h = Hash[*o.children.map { |c| accept c }]
register o, klass.new(h['begin'], h['end'], h['excl'])
when /^!ruby\/exception:?(.*)?$/
h = Hash[*o.children.map { |c| accept c }]
e = build_exception((resolve_class($1) || class_loader.exception),
h.delete('message'))
e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
init_with(e, h, o)
when '!set', 'tag:yaml.org,2002:set'
set = class_loader.psych_set.new
@st[o.anchor] = set if o.anchor
o.children.each_slice(2) do |k,v|
set[accept(k)] = accept(v)
end
set
when /^!ruby\/hash-with-ivars(?::(.*))?$/
hash = $1 ? resolve_class($1).allocate : {}
register o, hash
o.children.each_slice(2) do |key, value|
case key.value
when 'elements'
revive_hash hash, value
when 'ivars'
value.children.each_slice(2) do |k,v|
hash.instance_variable_set accept(k), accept(v)
end
end
end
hash
when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/
revive_hash register(o, resolve_class($1).allocate), o
when '!omap', 'tag:yaml.org,2002:omap'
map = register(o, class_loader.psych_omap.new)
o.children.each_slice(2) do |l,r|
map[accept(l)] = accept r
end
map
when /^!ruby\/marshalable:(.*)$/
name = $1
klass = resolve_class(name)
obj = register(o, klass.allocate)
if obj.respond_to?(:init_with)
init_with(obj, revive_hash({}, o), o)
elsif obj.respond_to?(:marshal_load)
marshal_data = o.children.map(&method(:accept))
obj.marshal_load(marshal_data)
obj
else
raise ArgumentError, "Cannot deserialize #{name}"
end
else
revive_hash(register(o, {}), o)
end
end
def visit_Psych_Nodes_Document o
accept o.root
end
def visit_Psych_Nodes_Stream o
o.children.map { |c| accept c }
end
def visit_Psych_Nodes_Alias o
@st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
end
private
def register node, object
@st[node.anchor] = object if node.anchor
object
end
def register_empty object
list = register(object, [])
object.children.each { |c| list.push accept c }
list
end
def allocate_anon_data node, members
klass = class_loader.data.define(*members.keys)
register(node, klass.allocate)
end
def revive_data_members hash, o
o.children.each_slice(2) do |k,v|
name = accept(k)
value = accept(v)
hash[class_loader.symbolize(name)] = value
end
hash
end
def revive_hash hash, o, tagged= false
o.children.each_slice(2) { |k,v|
key = accept(k)
val = accept(v)
if key == '<<' && k.tag != "tag:yaml.org,2002:str"
case v
when Nodes::Alias, Nodes::Mapping
begin
hash.merge! val
rescue TypeError
hash[key] = val
end
when Nodes::Sequence
begin
h = {}
val.reverse_each do |value|
h.merge! value
end
hash.merge! h
rescue TypeError
hash[key] = val
end
else
hash[key] = val
end
else
if !tagged && @symbolize_names && key.is_a?(String)
key = key.to_sym
elsif !@freeze
key = deduplicate(key)
end
hash[key] = val
end
}
hash
end
if RUBY_VERSION < '2.7'
def deduplicate key
if key.is_a?(String)
# It is important to untaint the string, otherwise it won't
# be deduplicated into an fstring, but simply frozen.
-(key.untaint)
else
key
end
end
else
def deduplicate key
if key.is_a?(String)
-key
else
key
end
end
end
def merge_key hash, key, val
end
def revive klass, node
s = register(node, klass.allocate)
init_with(s, revive_hash({}, node, true), node)
end
def init_with o, h, node
c = Psych::Coder.new(node.tag)
c.map = h
if o.respond_to?(:init_with)
o.init_with c
else
h.each { |k,v| o.instance_variable_set(:"@#{k}", v) }
end
o
end
# Convert +klassname+ to a Class
def resolve_class klassname
class_loader.load klassname
end
end
class NoAliasRuby < ToRuby
def visit_Psych_Nodes_Alias o
raise AliasesNotEnabled
end
end
end
end
PK ! r¸› › lib/psych/stream.rbnu „[µü¤ # frozen_string_literal: true
module Psych
###
# Psych::Stream is a streaming YAML emitter. It will not buffer your YAML,
# but send it straight to an IO.
#
# Here is an example use:
#
# stream = Psych::Stream.new($stdout)
# stream.start
# stream.push({:foo => 'bar'})
# stream.finish
#
# YAML will be immediately emitted to $stdout with no buffering.
#
# Psych::Stream#start will take a block and ensure that Psych::Stream#finish
# is called, so you can do this form:
#
# stream = Psych::Stream.new($stdout)
# stream.start do |em|
# em.push(:foo => 'bar')
# end
#
class Stream < Psych::Visitors::YAMLTree
class Emitter < Psych::Emitter # :nodoc:
def end_document implicit_end = !streaming?
super
end
def streaming?
true
end
end
include Psych::Streaming
extend Psych::Streaming::ClassMethods
end
end
PK ! ¬,É É lib/psych/handler.rbnu „[µü¤ # frozen_string_literal: true
module Psych
###
# Psych::Handler is an abstract base class that defines the events used
# when dealing with Psych::Parser. Clients who want to use Psych::Parser
# should implement a class that inherits from Psych::Handler and define
# events that they can handle.
#
# Psych::Handler defines all events that Psych::Parser can possibly send to
# event handlers.
#
# See Psych::Parser for more details
class Handler
###
# Configuration options for dumping YAML.
class DumperOptions
attr_accessor :line_width, :indentation, :canonical
def initialize
@line_width = 0
@indentation = 2
@canonical = false
end
end
# Default dumping options
OPTIONS = DumperOptions.new
# Events that a Handler should respond to.
EVENTS = [ :alias,
:empty,
:end_document,
:end_mapping,
:end_sequence,
:end_stream,
:scalar,
:start_document,
:start_mapping,
:start_sequence,
:start_stream ]
###
# Called with +encoding+ when the YAML stream starts. This method is
# called once per stream. A stream may contain multiple documents.
#
# See the constants in Psych::Parser for the possible values of +encoding+.
def start_stream encoding
end
###
# Called when the document starts with the declared +version+,
# +tag_directives+, if the document is +implicit+.
#
# +version+ will be an array of integers indicating the YAML version being
# dealt with, +tag_directives+ is a list of tuples indicating the prefix
# and suffix of each tag, and +implicit+ is a boolean indicating whether
# the document is started implicitly.
#
# === Example
#
# Given the following YAML:
#
# %YAML 1.1
# %TAG ! tag:tenderlovemaking.com,2009:
# --- !squee
#
# The parameters for start_document must be this:
#
# version # => [1, 1]
# tag_directives # => [["!", "tag:tenderlovemaking.com,2009:"]]
# implicit # => false
def start_document version, tag_directives, implicit
end
###
# Called with the document ends. +implicit+ is a boolean value indicating
# whether or not the document has an implicit ending.
#
# === Example
#
# Given the following YAML:
#
# ---
# hello world
#
# +implicit+ will be true. Given this YAML:
#
# ---
# hello world
# ...
#
# +implicit+ will be false.
def end_document implicit
end
###
# Called when an alias is found to +anchor+. +anchor+ will be the name
# of the anchor found.
#
# === Example
#
# Here we have an example of an array that references itself in YAML:
#
# --- &ponies
# - first element
# - *ponies
#
# &ponies is the anchor, *ponies is the alias. In this case, alias is
# called with "ponies".
def alias anchor
end
###
# Called when a scalar +value+ is found. The scalar may have an
# +anchor+, a +tag+, be implicitly +plain+ or implicitly +quoted+
#
# +value+ is the string value of the scalar
# +anchor+ is an associated anchor or nil
# +tag+ is an associated tag or nil
# +plain+ is a boolean value
# +quoted+ is a boolean value
# +style+ is an integer indicating the string style
#
# See the constants in Psych::Nodes::Scalar for the possible values of
# +style+
#
# === Example
#
# Here is a YAML document that exercises most of the possible ways this
# method can be called:
#
# ---
# - !str "foo"
# - &anchor fun
# - many
# lines
# - |
# many
# newlines
#
# The above YAML document contains a list with four strings. Here are
# the parameters sent to this method in the same order:
#
# # value anchor tag plain quoted style
# ["foo", nil, "!str", false, false, 3 ]
# ["fun", "anchor", nil, true, false, 1 ]
# ["many lines", nil, nil, true, false, 1 ]
# ["many\nnewlines\n", nil, nil, false, true, 4 ]
#
def scalar value, anchor, tag, plain, quoted, style
end
###
# Called when a sequence is started.
#
# +anchor+ is the anchor associated with the sequence or nil.
# +tag+ is the tag associated with the sequence or nil.
# +implicit+ a boolean indicating whether or not the sequence was implicitly
# started.
# +style+ is an integer indicating the list style.
#
# See the constants in Psych::Nodes::Sequence for the possible values of
# +style+.
#
# === Example
#
# Here is a YAML document that exercises most of the possible ways this
# method can be called:
#
# ---
# - !!seq [
# a
# ]
# - &pewpew
# - b
#
# The above YAML document consists of three lists, an outer list that
# contains two inner lists. Here is a matrix of the parameters sent
# to represent these lists:
#
# # anchor tag implicit style
# [nil, nil, true, 1 ]
# [nil, "tag:yaml.org,2002:seq", false, 2 ]
# ["pewpew", nil, true, 1 ]
def start_sequence anchor, tag, implicit, style
end
###
# Called when a sequence ends.
def end_sequence
end
###
# Called when a map starts.
#
# +anchor+ is the anchor associated with the map or +nil+.
# +tag+ is the tag associated with the map or +nil+.
# +implicit+ is a boolean indicating whether or not the map was implicitly
# started.
# +style+ is an integer indicating the mapping style.
#
# See the constants in Psych::Nodes::Mapping for the possible values of
# +style+.
#
# === Example
#
# Here is a YAML document that exercises most of the possible ways this
# method can be called:
#
# ---
# k: !!map { hello: world }
# v: &pewpew
# hello: world
#
# The above YAML document consists of three maps, an outer map that contains
# two inner maps. Below is a matrix of the parameters sent in order to
# represent these three maps:
#
# # anchor tag implicit style
# [nil, nil, true, 1 ]
# [nil, "tag:yaml.org,2002:map", false, 2 ]
# ["pewpew", nil, true, 1 ]
def start_mapping anchor, tag, implicit, style
end
###
# Called when a map ends
def end_mapping
end
###
# Called when an empty event happens. (Which, as far as I can tell, is
# never).
def empty
end
###
# Called when the YAML stream ends
def end_stream
end
###
# Called before each event with line/column information.
def event_location(start_line, start_column, end_line, end_column)
end
###
# Is this handler a streaming handler?
def streaming?
false
end
end
end
PK ! *J J lib/psych/set.rbnu „[µü¤ # frozen_string_literal: true
module Psych
class Set < ::Hash
end
end
PK ! :æýŽ % lib/psych/handlers/document_stream.rbnu „[µü¤ # frozen_string_literal: true
require_relative '../tree_builder'
module Psych
module Handlers
class DocumentStream < Psych::TreeBuilder # :nodoc:
def initialize &block
super
@block = block
end
def start_document version, tag_directives, implicit
n = Nodes::Document.new version, tag_directives, implicit
push n
end
def end_document implicit_end = !streaming?
@last.implicit_end = implicit_end
@block.call pop
end
end
end
end
PK ! .ä^{ { lib/psych/handlers/recorder.rbnu „[µü¤ # frozen_string_literal: true
require_relative '../handler'
module Psych
module Handlers
###
# This handler will capture an event and record the event. Recorder events
# are available vial Psych::Handlers::Recorder#events.
#
# For example:
#
# recorder = Psych::Handlers::Recorder.new
# parser = Psych::Parser.new recorder
# parser.parse '--- foo'
#
# recorder.events # => [list of events]
#
# # Replay the events
#
# emitter = Psych::Emitter.new $stdout
# recorder.events.each do |m, args|
# emitter.send m, *args
# end
class Recorder < Psych::Handler
attr_reader :events
def initialize
@events = []
super
end
EVENTS.each do |event|
define_method event do |*args|
@events << [event, args]
end
end
end
end
end
PK ! ú–â§K K lib/psych/omap.rbnu „[µü¤ # frozen_string_literal: true
module Psych
class Omap < ::Hash
end
end
PK ! / Ô€ € lib/psych/nodes.rbnu „[µü¤ # frozen_string_literal: true
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
###
# = Overview
#
# When using Psych.load to deserialize a YAML document, the document is
# translated to an intermediary AST. That intermediary AST is then
# translated in to a Ruby object graph.
#
# In the opposite direction, when using Psych.dump, the Ruby object graph is
# translated to an intermediary AST which is then converted to a YAML
# document.
#
# Psych::Nodes contains all of the classes that make up the nodes of a YAML
# AST. You can manually build an AST and use one of the visitors (see
# Psych::Visitors) to convert that AST to either a YAML document or to a
# Ruby object graph.
#
# Here is an example of building an AST that represents a list with one
# scalar:
#
# # Create our nodes
# stream = Psych::Nodes::Stream.new
# doc = Psych::Nodes::Document.new
# seq = Psych::Nodes::Sequence.new
# scalar = Psych::Nodes::Scalar.new('foo')
#
# # Build up our tree
# stream.children << doc
# doc.children << seq
# seq.children << scalar
#
# The stream is the root of the tree. We can then convert the tree to YAML:
#
# stream.to_yaml => "---\n- foo\n"
#
# Or convert it to Ruby:
#
# stream.to_ruby => [["foo"]]
#
# == YAML AST Requirements
#
# A valid YAML AST *must* have one Psych::Nodes::Stream at the root. A
# Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes
# as children.
#
# Psych::Nodes::Document nodes must have one and *only* one child. That child
# may be one of:
#
# * Psych::Nodes::Sequence
# * Psych::Nodes::Mapping
# * Psych::Nodes::Scalar
#
# Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many
# children, but Psych::Nodes::Mapping nodes should have an even number of
# children.
#
# All of these are valid children for Psych::Nodes::Sequence and
# Psych::Nodes::Mapping nodes:
#
# * Psych::Nodes::Sequence
# * Psych::Nodes::Mapping
# * Psych::Nodes::Scalar
# * Psych::Nodes::Alias
#
# Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and
# should not have any children.
module Nodes
end
end
PK ! uê>2 2 lib/psych/coder.rbnu „[µü¤ # frozen_string_literal: true
module Psych
###
# If an object defines +encode_with+, then an instance of Psych::Coder will
# be passed to the method when the object is being serialized. The Coder
# automatically assumes a Psych::Nodes::Mapping is being emitted. Other
# objects like Sequence and Scalar may be emitted if +seq=+ or +scalar=+ are
# called, respectively.
class Coder
attr_accessor :tag, :style, :implicit, :object
attr_reader :type, :seq
def initialize tag
@map = {}
@seq = []
@implicit = false
@type = :map
@tag = tag
@style = Psych::Nodes::Mapping::BLOCK
@scalar = nil
@object = nil
end
def scalar *args
if args.length > 0
warn "#{caller[0]}: Coder#scalar(a,b,c) is deprecated" if $VERBOSE
@tag, @scalar, _ = args
@type = :scalar
end
@scalar
end
# Emit a map. The coder will be yielded to the block.
def map tag = @tag, style = @style
@tag = tag
@style = style
yield self if block_given?
@map
end
# Emit a scalar with +value+ and +tag+
def represent_scalar tag, value
self.tag = tag
self.scalar = value
end
# Emit a sequence with +list+ and +tag+
def represent_seq tag, list
@tag = tag
self.seq = list
end
# Emit a sequence with +map+ and +tag+
def represent_map tag, map
@tag = tag
self.map = map
end
# Emit an arbitrary object +obj+ and +tag+
def represent_object tag, obj
@tag = tag
@type = :object
@object = obj
end
# Emit a scalar with +value+
def scalar= value
@type = :scalar
@scalar = value
end
# Emit a map with +value+
def map= map
@type = :map
@map = map
end
def []= k, v
@type = :map
@map[k] = v
end
alias :add :[]=
def [] k
@type = :map
@map[k]
end
# Emit a sequence of +list+
def seq= list
@type = :seq
@seq = list
end
end
end
PK ! ¢L lib/psych/tree_builder.rbnu „[µü¤ # frozen_string_literal: true
require_relative 'handler'
module Psych
###
# This class works in conjunction with Psych::Parser to build an in-memory
# parse tree that represents a YAML document.
#
# == Example
#
# parser = Psych::Parser.new Psych::TreeBuilder.new
# parser.parse('--- foo')
# tree = parser.handler.root
#
# See Psych::Handler for documentation on the event methods used in this
# class.
class TreeBuilder < Psych::Handler
# Returns the root node for the built tree
attr_reader :root
# Create a new TreeBuilder instance
def initialize
@stack = []
@last = nil
@root = nil
@start_line = nil
@start_column = nil
@end_line = nil
@end_column = nil
end
def event_location(start_line, start_column, end_line, end_column)
@start_line = start_line
@start_column = start_column
@end_line = end_line
@end_column = end_column
end
%w{
Sequence
Mapping
}.each do |node|
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)
@last.children << n
push n
end
def end_#{node.downcase}
n = pop
set_end_location(n)
n
end
RUBY
end
###
# Handles start_document events with +version+, +tag_directives+,
# and +implicit+ styling.
#
# See Psych::Handler#start_document
def start_document version, tag_directives, implicit
n = Nodes::Document.new version, tag_directives, implicit
set_start_location(n)
@last.children << n
push n
end
###
# Handles end_document events with +version+, +tag_directives+,
# and +implicit+ styling.
#
# See Psych::Handler#start_document
def end_document implicit_end = !streaming?
@last.implicit_end = implicit_end
n = pop
set_end_location(n)
n
end
def start_stream encoding
@root = Nodes::Stream.new(encoding)
set_start_location(@root)
push @root
end
def end_stream
n = pop
set_end_location(n)
n
end
def scalar value, anchor, tag, plain, quoted, style
s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
set_location(s)
@last.children << s
s
end
def alias anchor
a = Nodes::Alias.new(anchor)
set_location(a)
@last.children << a
a
end
private
def push value
@stack.push value
@last = value
end
def pop
x = @stack.pop
@last = @stack.last
x
end
def set_location(node)
set_start_location(node)
set_end_location(node)
end
def set_start_location(node)
node.start_line = @start_line
node.start_column = @start_column
end
def set_end_location(node)
node.end_line = @end_line
node.end_column = @end_column
end
end
end
PK ! ¢#D: : lib/psych/core_ext.rbnu „[µü¤ # frozen_string_literal: true
class Object
def self.yaml_tag url
Psych.add_tag(url, self)
end
###
# call-seq: to_yaml(options = {})
#
# Convert an object to YAML. See Psych.dump for more information on the
# available +options+.
def to_yaml options = {}
Psych.dump self, options
end
end
# Up to Ruby 3.4, Set was a regular object and was dumped as such
# by Pysch.
# Starting from Ruby 4.0 it's a core class written in C, so we have to implement
# #encode_with / #init_with to preserve backward compatibility.
if defined?(::Set) && Set.new.instance_variables.empty?
class Set
def encode_with(coder)
hash = {}
each do |m|
hash[m] = true
end
coder["hash"] = hash
coder
end
def init_with(coder)
replace(coder["hash"].keys)
end
end
end
PK ! åy2K› › lib/psych/streaming.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module Streaming
module ClassMethods
###
# Create a new streaming emitter. Emitter will print to +io+. See
# Psych::Stream for an example.
def new io
emitter = const_get(:Emitter).new(io)
class_loader = ClassLoader.new
ss = ScalarScanner.new class_loader
super(emitter, ss, {})
end
end
###
# Start streaming using +encoding+
def start encoding = Nodes::Stream::UTF8
super.tap { yield self if block_given? }
ensure
finish if block_given?
end
private
def register target, obj
end
end
end
PK ! HõçL L lib/psych/syntax_error.rbnu „[µü¤ # frozen_string_literal: true
require_relative 'exception'
module Psych
class SyntaxError < Psych::Exception
attr_reader :file, :line, :column, :offset, :problem, :context
def initialize file, line, col, offset, problem, context
err = [problem, context].compact.join ' '
filename = file || ''
message = "(%s): %s at line %d column %d" % [filename, err, line, col]
@file = file
@line = line
@column = col
@offset = offset
@problem = problem
@context = context
super(message)
end
end
end
PK ! ¢‹ lib/psych/json/yaml_events.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module JSON
module YAMLEvents # :nodoc:
def start_document version, tag_directives, implicit
super(version, tag_directives, !streaming?)
end
def end_document implicit_end = !streaming?
super(implicit_end)
end
def start_mapping anchor, tag, implicit, style
super(anchor, nil, true, Nodes::Mapping::FLOW)
end
def start_sequence anchor, tag, implicit, style
super(anchor, nil, true, Nodes::Sequence::FLOW)
end
def scalar value, anchor, tag, plain, quoted, style
if "tag:yaml.org,2002:null" == tag
super('null', nil, nil, true, false, Nodes::Scalar::PLAIN)
else
super
end
end
end
end
end
PK ! Ëð:¾’ ’ lib/psych/json/stream.rbnu „[µü¤ # frozen_string_literal: true
require_relative 'ruby_events'
require_relative 'yaml_events'
module Psych
module JSON
class Stream < Psych::Visitors::JSONTree
include Psych::JSON::RubyEvents
include Psych::Streaming
extend Psych::Streaming::ClassMethods
class Emitter < Psych::Stream::Emitter # :nodoc:
include Psych::JSON::YAMLEvents
end
end
end
end
PK ! …Ëéœè è lib/psych/json/ruby_events.rbnu „[µü¤ # frozen_string_literal: true
module Psych
module JSON
module RubyEvents # :nodoc:
def visit_Time o
formatted = format_time o
@emitter.scalar formatted, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED
end
def visit_DateTime o
visit_Time o.to_time
end
def visit_String o
@emitter.scalar o.to_s, nil, nil, false, true, Nodes::Scalar::DOUBLE_QUOTED
end
alias :visit_Symbol :visit_String
end
end
end
PK ! ÒÐ¥c c lib/psych/json/tree_builder.rbnu „[µü¤ # frozen_string_literal: true
require_relative 'yaml_events'
module Psych
module JSON
###
# Psych::JSON::TreeBuilder is an event based AST builder. Events are sent
# to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed.
class TreeBuilder < Psych::TreeBuilder
include Psych::JSON::YAMLEvents
end
end
end
PK ! ãR:þ þ lib/psych/visitors.rbnu „[µü¤ # frozen_string_literal: true
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'
PK ! €;JF F lib/psych/scalar_scanner.rbnu „[µü¤ # frozen_string_literal: true
module Psych
###
# Scan scalars for built in types
class ScalarScanner
# Taken from http://yaml.org/type/timestamp.html
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
# 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 and modified to ensure at least one numerical symbol exists
INTEGER_STRICT = /^(?:[-+]?0b[_]*[0-1][0-1_]* (?# base 2)
|[-+]?0[_]*[0-7][0-7_]* (?# base 8)
|[-+]?(0|[1-9][0-9_]*) (?# base 10)
|[-+]?0x[_]*[0-9a-fA-F][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][0-1_,]* (?# base 2)
|[-+]?0[_,]*[0-7][0-7_,]* (?# base 8)
|[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
|[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x
attr_reader :class_loader
# Create a new scanner
def initialize class_loader, strict_integer: false, parse_symbols: true
@symbol_cache = {}
@class_loader = class_loader
@strict_integer = strict_integer
@parse_symbols = parse_symbols
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?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
return string if string.length > 5
if string.match?(/^[^ytonf~]/i)
string
elsif string == '~' || string.match?(/^null$/i)
nil
elsif string.match?(/^(yes|true|on)$/i)
true
elsif string.match?(/^(no|false|off)$/i)
false
else
string
end
elsif string.match?(TIME)
begin
parse_time string
rescue ArgumentError
string
end
elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
begin
class_loader.date.strptime(string, '%F', Date::GREGORIAN)
rescue ArgumentError
string
end
elsif string.match?(/^\+?\.inf$/i)
Float::INFINITY
elsif string.match?(/^-\.inf$/i)
-Float::INFINITY
elsif string.match?(/^\.nan$/i)
Float::NAN
elsif @parse_symbols && string.match?(/^:./)
if string =~ /^:(["'])(.*)\1/
@symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
else
@symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
end
elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/)
i = 0
string.split(':').each_with_index do |n,e|
i += (n.to_i * 60 ** (e - 2).abs)
end
i
elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/)
i = 0
string.split(':').each_with_index do |n,e|
i += (n.to_f * 60 ** (e - 2).abs)
end
i
elsif string.match?(FLOAT)
if string.match?(/\A[-+]?\.\Z/)
string
else
Float(string.delete(',_').gsub(/\.([Ee]|$)/, '\1'))
end
elsif string.match?(integer_regex)
parse_int string
else
string
end
end
###
# Parse and return an int from +string+
def parse_int string
Integer(string.delete(',_'))
end
###
# Parse and return a Time from +string+
def parse_time string
klass = class_loader.load 'Time'
date, time = *(string.split(/[ tT]/, 2))
(yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i }
md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)
(hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000
time = klass.utc(yy, m, dd, hh, mm, ss, us)
return time if 'Z' == md[3]
return klass.at(time.to_i, us) unless md[3]
tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) }
offset = tz.first * 3600
if offset < 0
offset -= ((tz[1] || 0) * 60)
else
offset += ((tz[1] || 0) * 60)
end
klass.new(yy, m, dd, hh, mm, ss+us/(1_000_000r), offset)
end
end
end
PK ! O€xf lib/psych/parser.rbnu „[µü¤ # frozen_string_literal: true
module Psych
###
# YAML event parser class. This class parses a YAML document and calls
# events on the handler that is passed to the constructor. The events can
# be used for things such as constructing a YAML AST or deserializing YAML
# documents. It can even be fed back to Psych::Emitter to emit the same
# document that was parsed.
#
# See Psych::Handler for documentation on the events that Psych::Parser emits.
#
# Here is an example that prints out ever scalar found in a YAML document:
#
# # Handler for detecting scalar values
# class ScalarHandler < Psych::Handler
# def scalar value, anchor, tag, plain, quoted, style
# puts value
# end
# end
#
# parser = Psych::Parser.new(ScalarHandler.new)
# parser.parse(yaml_document)
#
# Here is an example that feeds the parser back in to Psych::Emitter. The
# YAML document is read from STDIN and written back out to STDERR:
#
# parser = Psych::Parser.new(Psych::Emitter.new($stderr))
# parser.parse($stdin)
#
# Psych uses Psych::Parser in combination with Psych::TreeBuilder to
# construct an AST of the parsed YAML document.
class Parser
class Mark < Struct.new(:index, :line, :column)
end
# The handler on which events will be called
attr_accessor :handler
# Set the encoding for this parser to +encoding+
attr_writer :external_encoding
###
# Creates a new Psych::Parser instance with +handler+. YAML events will
# be called on +handler+. See Psych::Parser for more details.
def initialize handler = Handler.new
@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 : ""
_native_parse @handler, yaml, path
end
end
end
PK ! Ýê
ï2h 2h lib/psych.rbnu „[µü¤ # frozen_string_literal: true
require 'date'
require_relative 'psych/versions'
case RUBY_ENGINE
when 'jruby'
require_relative 'psych_jars'
if JRuby::Util.respond_to?(:load_ext)
JRuby::Util.load_ext('org.jruby.ext.psych.PsychLibrary')
else
require 'java'; require 'jruby'
org.jruby.ext.psych.PsychLibrary.new.load(JRuby.runtime, false)
end
else
require 'psych.so'
end
require_relative 'psych/nodes'
require_relative 'psych/streaming'
require_relative 'psych/visitors'
require_relative 'psych/handler'
require_relative 'psych/tree_builder'
require_relative 'psych/parser'
require_relative 'psych/omap'
require_relative 'psych/set'
require_relative 'psych/coder'
require_relative 'psych/stream'
require_relative 'psych/json/tree_builder'
require_relative 'psych/json/stream'
require_relative 'psych/handlers/document_stream'
require_relative 'psych/class_loader'
###
# = Overview
#
# Psych is a YAML parser and emitter.
# Psych leverages libyaml [Home page: https://pyyaml.org/wiki/LibYAML]
# or [git repo: https://github.com/yaml/libyaml] for its YAML parsing
# and emitting capabilities. In addition to wrapping libyaml, Psych also
# knows how to serialize and de-serialize most Ruby objects to and from
# the YAML format.
#
# = I NEED TO PARSE OR EMIT YAML RIGHT NOW!
#
# # Parse some YAML
# Psych.load("--- foo") # => "foo"
#
# # Emit some YAML
# Psych.dump("foo") # => "--- foo\n...\n"
# { :a => 'b'}.to_yaml # => "---\n:a: b\n"
#
# Got more time on your hands? Keep on reading!
#
# == YAML Parsing
#
# Psych provides a range of interfaces for parsing a YAML document ranging from
# low level to high level, depending on your parsing needs. At the lowest
# level, is an event based parser. Mid level is access to the raw YAML AST,
# and at the highest level is the ability to unmarshal YAML to Ruby objects.
#
# == YAML Emitting
#
# Psych provides a range of interfaces ranging from low to high level for
# producing YAML documents. Very similar to the YAML parsing interfaces, Psych
# provides at the lowest level, an event based system, mid-level is building
# a YAML AST, and the highest level is converting a Ruby object straight to
# a YAML document.
#
# == High-level API
#
# === Parsing
#
# The high level YAML parser provided by Psych simply takes YAML as input and
# returns a Ruby data structure. For information on using the high level parser
# see Psych.load
#
# ==== Reading from a string
#
# Psych.safe_load("--- a") # => 'a'
# Psych.safe_load("---\n - a\n - b") # => ['a', 'b']
# # From a trusted string:
# Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
#
# ==== Reading from a file
#
# Psych.safe_load_file("data.yml", permitted_classes: [Date])
# Psych.load_file("trusted_database.yml")
#
# ==== \Exception handling
#
# begin
# # The second argument changes only the exception contents
# Psych.parse("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# === Emitting
#
# The high level emitter has the easiest interface. Psych simply takes a Ruby
# data structure and converts it to a YAML document. See Psych.dump for more
# information on dumping a Ruby data structure.
#
# ==== Writing to a string
#
# # Dump an array, get back a YAML string
# Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
#
# # Dump an array to an IO object
# Psych.dump(['a', 'b'], StringIO.new) # => #
#
# # Dump an array with indentation set
# Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n"
#
# # Dump an array to an IO with indentation set
# Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
#
# ==== Writing to a file
#
# Currently there is no direct API for dumping Ruby structure to file:
#
# File.open('database.yml', 'w') do |file|
# file.write(Psych.dump(['a', 'b']))
# end
#
# == Mid-level API
#
# === Parsing
#
# Psych provides access to an AST produced from parsing a YAML document. This
# tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can
# be examined and manipulated freely. Please see Psych::parse_stream,
# Psych::Nodes, and Psych::Nodes::Node for more information on dealing with
# YAML syntax trees.
#
# ==== Reading from a string
#
# # Returns Psych::Nodes::Stream
# Psych.parse_stream("---\n - a\n - b")
#
# # Returns Psych::Nodes::Document
# Psych.parse("---\n - a\n - b")
#
# ==== Reading from a file
#
# # Returns Psych::Nodes::Stream
# Psych.parse_stream(File.read('database.yml'))
#
# # Returns Psych::Nodes::Document
# Psych.parse_file('database.yml')
#
# ==== \Exception handling
#
# begin
# # The second argument changes only the exception contents
# Psych.parse("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# === Emitting
#
# At the mid level is building an AST. This AST is exactly the same as the AST
# used when parsing a YAML document. Users can build an AST by hand and the
# AST knows how to emit itself as a YAML document. See Psych::Nodes,
# Psych::Nodes::Node, and Psych::TreeBuilder for more information on building
# a YAML AST.
#
# ==== Writing to a string
#
# # We need Psych::Nodes::Stream (not Psych::Nodes::Document)
# stream = Psych.parse_stream("---\n - a\n - b")
#
# stream.to_yaml # => "---\n- a\n- b\n"
#
# ==== Writing to a file
#
# # We need Psych::Nodes::Stream (not Psych::Nodes::Document)
# stream = Psych.parse_stream(File.read('database.yml'))
#
# File.open('database.yml', 'w') do |file|
# file.write(stream.to_yaml)
# end
#
# == Low-level API
#
# === Parsing
#
# The lowest level parser should be used when the YAML input is already known,
# and the developer does not want to pay the price of building an AST or
# automatic detection and conversion to Ruby objects. See Psych::Parser for
# more information on using the event based parser.
#
# ==== Reading to Psych::Nodes::Stream structure
#
# parser = Psych::Parser.new(TreeBuilder.new) # => #
# parser = Psych.parser # it's an alias for the above
#
# parser.parse("---\n - a\n - b") # => #
# parser.handler # => #
# parser.handler.root # => #
#
# ==== Receiving an events stream
#
# recorder = Psych::Handlers::Recorder.new
# parser = Psych::Parser.new(recorder)
#
# parser.parse("---\n - a\n - b")
# recorder.events # => [list of [event, args] lists]
# # event is one of: Psych::Handler::EVENTS
# # args are the arguments passed to the event
#
# === Emitting
#
# The lowest level emitter is an event based system. Events are sent to a
# Psych::Emitter object. That object knows how to convert the events to a YAML
# document. This interface should be used when document format is known in
# advance or speed is a concern. See Psych::Emitter for more information.
#
# ==== Writing to a Ruby structure
#
# Psych.parser.parse("--- a") # => #
#
# parser.handler.first # => #
# parser.handler.first.to_ruby # => ["a"]
#
# parser.handler.root.first # => #
# parser.handler.root.first.to_ruby # => "a"
#
# # You can instantiate an Emitter manually
# Psych::Visitors::ToRuby.new.accept(parser.handler.root.first)
# # => "a"
module Psych
# The version of libyaml Psych is using
LIBYAML_VERSION = Psych.libyaml_version.join('.').freeze
###
# Load +yaml+ in to a Ruby data structure. If multiple documents are
# provided, the object contained in the first document will be returned.
# +filename+ will be used in the exception message if any exception
# is raised while parsing. If +yaml+ is empty, it returns
# the specified +fallback+ return value, which defaults to +false+.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.unsafe_load("--- a") # => 'a'
# Psych.unsafe_load("---\n - a\n - b") # => ['a', 'b']
#
# begin
# Psych.unsafe_load("--- `", filename: "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# When the optional +symbolize_names+ keyword argument is set to a
# true value, returns symbols for keys in Hash objects (default: strings).
#
# Psych.unsafe_load("---\n foo: bar") # => {"foo"=>"bar"}
# Psych.unsafe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
#
# Raises a TypeError when `yaml` parameter is NilClass
#
# 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
# load method or the safe_load method.
#
def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
result = parse(yaml, filename: filename)
return fallback unless result
result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols)
end
###
# Safely load the yaml string in +yaml+. By default, only the following
# classes are allowed to be deserialized:
#
# * TrueClass
# * FalseClass
# * NilClass
# * Integer
# * Float
# * String
# * Array
# * Hash
#
# Recursive data structures are not allowed by default. Arbitrary classes
# can be allowed by adding those classes to the +permitted_classes+ keyword argument. They are
# additive. For example, to allow Date deserialization:
#
# Psych.safe_load(yaml, permitted_classes: [Date])
#
# Now the Date class can be loaded in addition to the classes listed above.
#
# Aliases can be explicitly allowed by changing the +aliases+ keyword argument.
# For example:
#
# x = []
# x << x
# yaml = Psych.dump x
# Psych.safe_load yaml # => raises an exception
# Psych.safe_load yaml, aliases: true # => loads the aliases
#
# A Psych::DisallowedClass exception will be raised if the yaml contains a
# class that isn't in the +permitted_classes+ list.
#
# A Psych::AliasesNotEnabled exception will be raised if the yaml contains aliases
# but the +aliases+ keyword argument is set to false.
#
# +filename+ will be used in the exception message if any exception is raised
# while parsing.
#
# When the optional +symbolize_names+ keyword argument is set to a
# true value, returns symbols for keys in Hash objects (default: strings).
#
# Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
# Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
#
def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
result = parse(yaml, filename: filename)
return fallback unless result
class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
permitted_symbols.map(&:to_s))
scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols
visitor = if aliases
Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
else
Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
end
result = visitor.accept result
result
end
###
# Load +yaml+ in to a Ruby data structure. If multiple documents are
# provided, the object contained in the first document will be returned.
# +filename+ will be used in the exception message if any exception
# is raised while parsing. If +yaml+ is empty, it returns
# the specified +fallback+ return value, which defaults to +nil+.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.load("--- a") # => 'a'
# Psych.load("---\n - a\n - b") # => ['a', 'b']
#
# begin
# Psych.load("--- `", filename: "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# When the optional +symbolize_names+ keyword argument is set to a
# true value, returns symbols for keys in Hash objects (default: strings).
#
# Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
# Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
#
# Raises a TypeError when `yaml` parameter is NilClass. This method is
# similar to `safe_load` except that `Symbol` objects are allowed by default.
#
def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
safe_load yaml, permitted_classes: permitted_classes,
permitted_symbols: permitted_symbols,
aliases: aliases,
filename: filename,
fallback: fallback,
symbolize_names: symbolize_names,
freeze: freeze,
strict_integer: strict_integer,
parse_symbols: parse_symbols
end
###
# Parse a YAML string in +yaml+. Returns the Psych::Nodes::Document.
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.parse("---\n - a\n - b") # => #
#
# begin
# Psych.parse("--- `", filename: "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# See Psych::Nodes for more information about YAML AST.
def self.parse yaml, filename: nil
parse_stream(yaml, filename: filename) do |node|
return node
end
false
end
###
# Parse a file at +filename+. Returns the Psych::Nodes::Document.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
def self.parse_file filename, fallback: false
result = File.open filename, 'r:bom|utf-8' do |f|
parse f, filename: filename
end
result || fallback
end
###
# Returns a default parser
def self.parser
Psych::Parser.new(TreeBuilder.new)
end
###
# Parse a YAML string in +yaml+. Returns the Psych::Nodes::Stream.
# This method can handle multiple YAML documents contained in +yaml+.
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
#
# If a block is given, a Psych::Nodes::Document node will be yielded to the
# block as it's being parsed.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.parse_stream("---\n - a\n - b") # => #
#
# Psych.parse_stream("--- a\n--- b") do |node|
# node # => #
# end
#
# begin
# Psych.parse_stream("--- `", filename: "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# Raises a TypeError when NilClass is passed.
#
# See Psych::Nodes for more information about YAML AST.
def self.parse_stream yaml, filename: nil, &block
if block_given?
parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
parser.parse yaml, filename
else
parser = self.parser
parser.parse yaml, filename
parser.handler.root
end
end
###
# call-seq:
# Psych.dump(o) -> string of yaml
# Psych.dump(o, options) -> string of yaml
# Psych.dump(o, io) -> io object passed in
# Psych.dump(o, io, options) -> io object passed in
#
# Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
# to control the output format. If an IO object is passed in, the YAML will
# be dumped to that IO object.
#
# Currently supported options are:
#
# [:indentation] Number of space characters used to indent.
# Acceptable value should be in 0..9 range,
# otherwise option is ignored.
#
# Default: 2.
# [:line_width] Max character to wrap line at.
# For unlimited line width use -1.
#
# Default: 0 (meaning "wrap at 81").
# [:canonical] Write "canonical" YAML form (very verbose, yet
# strictly formal).
#
# Default: false.
# [:header] Write %YAML [version] at the beginning of document.
#
# Default: false.
#
# [:stringify_names] Dump symbol keys in Hash objects as string.
#
# Default: false.
#
# Example:
#
# # Dump an array, get back a YAML string
# Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
#
# # Dump an array to an IO object
# Psych.dump(['a', 'b'], StringIO.new) # => #
#
# # Dump an array with indentation set
# Psych.dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n"
#
# # Dump an array to an IO with indentation set
# Psych.dump(['a', ['b']], StringIO.new, indentation: 3)
#
# # Dump hash with symbol keys as string
# Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
def self.dump o, io = nil, options = {}
if Hash === io
options = io
io = nil
end
visitor = Psych::Visitors::YAMLTree.create options
visitor << o
visitor.tree.yaml io, options
end
###
# call-seq:
# Psych.safe_dump(o) -> string of yaml
# Psych.safe_dump(o, options) -> string of yaml
# Psych.safe_dump(o, io) -> io object passed in
# Psych.safe_dump(o, io, options) -> io object passed in
#
# Safely dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
# to control the output format. If an IO object is passed in, the YAML will
# be dumped to that IO object. By default, only the following
# classes are allowed to be serialized:
#
# * TrueClass
# * FalseClass
# * NilClass
# * Integer
# * Float
# * String
# * Array
# * Hash
#
# Arbitrary classes can be allowed by adding those classes to the +permitted_classes+
# keyword argument. They are additive. For example, to allow Date serialization:
#
# Psych.safe_dump(yaml, permitted_classes: [Date])
#
# Now the Date class can be dumped in addition to the classes listed above.
#
# A Psych::DisallowedClass exception will be raised if the object contains a
# class that isn't in the +permitted_classes+ list.
#
# Currently supported options are:
#
# [:indentation] Number of space characters used to indent.
# Acceptable value should be in 0..9 range,
# otherwise option is ignored.
#
# Default: 2.
# [:line_width] Max character to wrap line at.
# For unlimited line width use -1.
#
# Default: 0 (meaning "wrap at 81").
# [:canonical] Write "canonical" YAML form (very verbose, yet
# strictly formal).
#
# Default: false.
# [:header] Write %YAML [version] at the beginning of document.
#
# Default: false.
#
# [:stringify_names] Dump symbol keys in Hash objects as string.
#
# Default: false.
#
# Example:
#
# # Dump an array, get back a YAML string
# Psych.safe_dump(['a', 'b']) # => "---\n- a\n- b\n"
#
# # Dump an array to an IO object
# Psych.safe_dump(['a', 'b'], StringIO.new) # => #
#
# # Dump an array with indentation set
# Psych.safe_dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n"
#
# # Dump an array to an IO with indentation set
# Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3)
#
# # Dump hash with symbol keys as string
# Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
def self.safe_dump o, io = nil, options = {}
if Hash === io
options = io
io = nil
end
visitor = Psych::Visitors::RestrictedYAMLTree.create options
visitor << o
visitor.tree.yaml io, options
end
###
# Dump a list of objects as separate documents to a document stream.
#
# Example:
#
# Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
def self.dump_stream *objects
visitor = Psych::Visitors::YAMLTree.create({})
objects.each do |o|
visitor << o
end
visitor.tree.yaml
end
###
# Dump Ruby +object+ to a JSON string.
def self.to_json object
visitor = Psych::Visitors::JSONTree.create
visitor << object
visitor.tree.yaml
end
###
# Load multiple documents given in +yaml+. Returns the parsed documents
# as a list. If a block is given, each document will be converted to Ruby
# and passed to the block during parsing
#
# Example:
#
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
#
# list = []
# Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
# list << ruby
# end
# list # => ['foo', 'bar']
#
def self.load_stream yaml, filename: nil, fallback: [], **kwargs
result = if block_given?
parse_stream(yaml, filename: filename) do |node|
yield node.to_ruby(**kwargs)
end
else
parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) }
end
return fallback if result.is_a?(Array) && result.empty?
result
end
###
# Load multiple documents given in +yaml+. Returns the parsed documents
# as a list.
#
# Example:
#
# Psych.safe_load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
#
# list = []
# Psych.safe_load_stream("--- foo\n...\n--- bar\n...") do |ruby|
# list << ruby
# end
# list # => ['foo', 'bar']
#
def self.safe_load_stream yaml, filename: nil, permitted_classes: [], aliases: false
documents = parse_stream(yaml, filename: filename).children.map do |child|
stream = Psych::Nodes::Stream.new
stream.children << child
safe_load(stream.to_yaml, permitted_classes: permitted_classes, aliases: aliases)
end
if block_given?
documents.each { |doc| yield doc }
nil
else
documents
end
end
###
# 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.
def self.unsafe_load_file filename, **kwargs
File.open(filename, 'r:bom|utf-8') { |f|
self.unsafe_load f, filename: filename, **kwargs
}
end
###
# 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.
def self.safe_load_file filename, **kwargs
File.open(filename, 'r:bom|utf-8') { |f|
self.safe_load f, filename: filename, **kwargs
}
end
###
# 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 load for options.
def self.load_file filename, **kwargs
File.open(filename, 'r:bom|utf-8') { |f|
self.load f, filename: filename, **kwargs
}
end
# :stopdoc:
def self.add_domain_type domain, type_tag, &block
key = ['tag', domain, type_tag].join ':'
domain_types[key] = [key, block]
domain_types["tag:#{type_tag}"] = [key, block]
end
def self.add_builtin_type type_tag, &block
domain = 'yaml.org,2002'
key = ['tag', domain, type_tag].join ':'
domain_types[key] = [key, block]
end
def self.remove_type type_tag
domain_types.delete type_tag
end
def self.add_tag tag, klass
load_tags[tag] = klass.name
dump_tags[klass] = tag
end
class << self
if defined?(Ractor)
class Config
attr_accessor :load_tags, :dump_tags, :domain_types
def initialize
@load_tags = {}
@dump_tags = {}
@domain_types = {}
end
end
def config
Ractor.current[:PsychConfig] ||= Config.new
end
def load_tags
config.load_tags
end
def dump_tags
config.dump_tags
end
def domain_types
config.domain_types
end
def load_tags=(value)
config.load_tags = value
end
def dump_tags=(value)
config.dump_tags = value
end
def domain_types=(value)
config.domain_types = value
end
else
attr_accessor :load_tags
attr_accessor :dump_tags
attr_accessor :domain_types
end
end
self.load_tags = {}
self.dump_tags = {}
self.domain_types = {}
# :startdoc:
end
require_relative 'psych/core_ext'
PK ! áõQb¼ ¼ lib/psych/versions.rbnu „[µü¤ PK ! )£´) ) lib/psych/nodes/mapping.rbnu „[µü¤ PK ! Ϧ[ t lib/psych/nodes/stream.rbnu „[µü¤ PK ! ·ÏA A ¾ lib/psych/nodes/document.rbnu „[µü¤ PK ! ¨Ìׄ „ J lib/psych/nodes/scalar.rbnu „[µü¤ PK ! ‚ɉ lib/psych/nodes/alias.rbnu „[µü¤ PK ! ªë¯! ! j lib/psych/nodes/sequence.rbnu „[µü¤ PK ! +‡í=ÿ ÿ Ö$ lib/psych/nodes/node.rbnu „[µü¤ PK ! ©Ø'K¾ ¾ - lib/psych/y.rbnu „[µü¤ PK ! ‚=nH? ? . lib/psych/class_loader.rbnu „[µü¤ PK ! ÔµüÖ Ö 6 lib/psych/exception.rbnu „[µü¤ PK ! MA+¾ ¾ ¼9 lib/psych/visitors/visitor.rbnu „[µü¤ PK ! «›{>Q Q Ç<