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!·ÏAAlib/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!«›{>QQlib/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ÿç(rr!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!ö©GGlib/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ø6lib/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!*JJlib/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!ú–â§KKlib/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ê>22lib/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õçLLlib/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!ÒÐ¥cclib/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!€;JFFlib/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€xflib/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!Ýê ï2h2h 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!Ϧ[tlib/psych/nodes/stream.rbnu„[µü¤PK!·ÏAA¾ lib/psych/nodes/document.rbnu„[µü¤PK!¨Ìׄ„Jlib/psych/nodes/scalar.rbnu„[µü¤PK!‚ɉ  lib/psych/nodes/alias.rbnu„[µü¤PK!ªë¯!!jlib/psych/nodes/sequence.rbnu„[µü¤PK!+‡í=ÿÿÖ$lib/psych/nodes/node.rbnu„[µü¤PK!©Ø'K¾¾-lib/psych/y.rbnu„[µü¤PK!‚=nH??.lib/psych/class_loader.rbnu„[µü¤PK!ÔµüÖÖ 6lib/psych/exception.rbnu„[µü¤PK!MA+¾¾¼9lib/psych/visitors/visitor.rbnu„[µü¤PK!«›{>QQÇ<lib/psych/visitors/json_tree.rbnu„[µü¤PK!¿ÛÚZÊÊg?lib/psych/visitors/emitter.rbnu„[µü¤PK!Rÿç(rr!~Elib/psych/visitors/depth_first.rbnu„[µü¤PK!ö©GGAHlib/psych/visitors/yaml_tree.rbnu„[µü¤PK!,Nk˜ø6ø6–lib/psych/visitors/to_ruby.rbnu„[µü¤PK!r¸››ÛÆlib/psych/stream.rbnu„[µü¤PK!¬,ÉɹÊlib/psych/handler.rbnu„[µü¤PK!*JJÆçlib/psych/set.rbnu„[µü¤PK!:æýŽ  %Pèlib/psych/handlers/document_stream.rbnu„[µü¤PK!.ä^{{±êlib/psych/handlers/recorder.rbnu„[µü¤PK!ú–â§KKzîlib/psych/omap.rbnu„[µü¤PK!/Ô€ € ïlib/psych/nodes.rbnu„[µü¤PK!uê>22Èølib/psych/coder.rbnu„[µü¤PK!¢L   <lib/psych/tree_builder.rbnu„[µü¤PK!¢#D::™ lib/psych/core_ext.rbnu„[µü¤PK!åy2K››lib/psych/streaming.rbnu„[µü¤PK!HõçLLùlib/psych/syntax_error.rbnu„[µü¤PK!¢‹  Žlib/psych/json/yaml_events.rbnu„[µü¤PK!Ëð:¾’’ælib/psych/json/stream.rbnu„[µü¤PK!…ËéœèèÀlib/psych/json/ruby_events.rbnu„[µü¤PK!ÒÐ¥ccõlib/psych/json/tree_builder.rbnu„[µü¤PK!ãR:þþ¦lib/psych/visitors.rbnu„[µü¤PK!€;JFFé lib/psych/scalar_scanner.rbnu„[µü¤PK!O€xfz4lib/psych/parser.rbnu„[µü¤PK!Ýê ï2h2h Ù<lib/psych.rbnu„[µü¤PK%%Ä G¥