Module: Psych

Defined in:
lib/psych.rb,
lib/psych/set.rb,
lib/psych/omap.rb,
lib/psych/coder.rb,
lib/psych/nodes.rb,
lib/psych/parser.rb,
lib/psych/stream.rb,
lib/psych/handler.rb,
lib/psych/versions.rb,
lib/psych/streaming.rb,
lib/psych/exception.rb,
lib/psych/deprecated.rb,
lib/psych/nodes/node.rb,
lib/psych/json/stream.rb,
lib/psych/nodes/alias.rb,
lib/psych/class_loader.rb,
lib/psych/nodes/scalar.rb,
lib/psych/nodes/stream.rb,
lib/psych/tree_builder.rb,
lib/psych/syntax_error.rb,
lib/psych/nodes/mapping.rb,
lib/psych/scalar_scanner.rb,
lib/psych/nodes/document.rb,
lib/psych/nodes/sequence.rb,
lib/psych/json/yaml_events.rb,
lib/psych/json/ruby_events.rb,
lib/psych/visitors/visitor.rb,
lib/psych/visitors/to_ruby.rb,
lib/psych/visitors/emitter.rb,
lib/psych/handlers/recorder.rb,
lib/psych/json/tree_builder.rb,
lib/psych/visitors/json_tree.rb,
lib/psych/visitors/yaml_tree.rb,
lib/psych/visitors/depth_first.rb,
lib/psych/handlers/document_stream.rb,
psych.c,
psych_parser.c,
psych_emitter.c,
psych_to_ruby.c,
psych_yaml_tree.c

Overview

frozen_string_literal: false

Defined Under Namespace

Modules: DeprecatedMethods, Handlers, JSON, Nodes, Streaming, Visitors Classes: BadAlias, ClassLoader, Coder, DisallowedClass, Emitter, Exception, Handler, Omap, Parser, ScalarScanner, Set, Stream, SyntaxError, TreeBuilder

Constant Summary collapse

VERSION =

The version is Psych you’re using

'2.0.17'
LIBYAML_VERSION =

The version of libyaml Psych is using

Psych.libyaml_version.join '.'
DEFAULT_SNAKEYAML_VERSION =
'1.14'.freeze
DEPRECATED =

:nodoc:

__FILE__

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.domain_typesObject

Returns the value of attribute domain_types



502
503
504
# File 'lib/psych.rb', line 502

def domain_types
  @domain_types
end

.dump_tagsObject

Returns the value of attribute dump_tags



501
502
503
# File 'lib/psych.rb', line 501

def dump_tags
  @dump_tags
end

.load_tagsObject

Returns the value of attribute load_tags



500
501
502
# File 'lib/psych.rb', line 500

def load_tags
  @load_tags
end

Class Method Details

.add_builtin_type(type_tag, &block) ⇒ Object



482
483
484
485
486
# File 'lib/psych.rb', line 482

def self.add_builtin_type type_tag, &block
  domain = 'yaml.org,2002'
  key = ['tag', domain, type_tag].join ':'
  @domain_types[key] = [key, block]
end

.add_domain_type(domain, type_tag, &block) ⇒ Object



476
477
478
479
480
# File 'lib/psych.rb', line 476

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

.add_private_type(type_tag, &block) ⇒ Object



50
51
52
53
54
55
# File 'lib/psych/deprecated.rb', line 50

def self.add_private_type type_tag, &block
  warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE
  domain = 'x-private'
  key = [domain, type_tag].join ':'
  @domain_types[key] = [key, block]
end

.add_ruby_type(type_tag, &block) ⇒ Object



43
44
45
46
47
48
# File 'lib/psych/deprecated.rb', line 43

def self.add_ruby_type type_tag, &block
  warn "#{caller[0]}: add_ruby_type is deprecated, use add_domain_type" if $VERBOSE
  domain = 'ruby.yaml.org,2002'
  key = ['tag', domain, type_tag].join ':'
  @domain_types[key] = [key, block]
end

.add_tag(tag, klass) ⇒ Object



494
495
496
497
# File 'lib/psych.rb', line 494

def self.add_tag tag, klass
  @load_tags[tag] = klass.name
  @dump_tags[klass] = tag
end

.detect_implicit(thing) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/psych/deprecated.rb', line 35

def self.detect_implicit thing
  warn "#{caller[0]}: detect_implicit is deprecated" if $VERBOSE
  return '' unless String === thing
  return 'null' if '' == thing
  ss = ScalarScanner.new(ClassLoader.new)
  ss.tokenize(thing).class.name.downcase
end

.dump(o, io = nil, options = {}) ⇒ Object

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.

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)  # => #<StringIO:0x000001009d0890>

# 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)


409
410
411
412
413
414
415
416
417
418
# File 'lib/psych.rb', line 409

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

.dump_stream(*objects) ⇒ Object

Dump a list of objects as separate documents to a document stream.

Example:

Psych.dump_stream("foo\n  ", {}) # => "--- ! \"foo\\n  \"\n--- {}\n"


426
427
428
429
430
431
432
# File 'lib/psych.rb', line 426

def self.dump_stream *objects
  visitor = Psych::Visitors::YAMLTree.create({})
  objects.each do |o|
    visitor << o
  end
  visitor.tree.yaml
end

.libyaml_versionObject

Returns the version of libyaml being used



7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'psych.c', line 7

static VALUE libyaml_version(VALUE module)
{
    int major, minor, patch;
    VALUE list[3];

    yaml_get_version(&major, &minor, &patch);

    list[0] = INT2NUM((long)major);
    list[1] = INT2NUM((long)minor);
    list[2] = INT2NUM((long)patch);

    return rb_ary_new4((long)3, list);
}

.load(yaml, filename = nil) ⇒ Object

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.

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("--- `", "file.txt")
rescue Psych::SyntaxError => ex
  ex.file    # => 'file.txt'
  ex.message # => "(file.txt): found character that cannot start any token"
end


251
252
253
254
# File 'lib/psych.rb', line 251

def self.load yaml, filename = nil
  result = parse(yaml, filename)
  result ? result.to_ruby : result
end

.load_documents(yaml, &block) ⇒ Object

This method is deprecated, use Psych.load_stream instead.



26
27
28
29
30
31
32
33
# File 'lib/psych/deprecated.rb', line 26

def self.load_documents yaml, &block
  if $VERBOSE
    warn "#{caller[0]}: load_documents is deprecated, use load_stream"
  end
  list = load_stream yaml
  return list unless block_given?
  list.each(&block)
end

.load_file(filename) ⇒ Object

Load the document contained in filename. Returns the yaml contained in filename as a Ruby object



470
471
472
# File 'lib/psych.rb', line 470

def self.load_file filename
  File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename }
end

.load_stream(yaml, filename = nil) ⇒ Object

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']


457
458
459
460
461
462
463
464
465
# File 'lib/psych.rb', line 457

def self.load_stream yaml, filename = nil
  if block_given?
    parse_stream(yaml, filename) do |node|
      yield node.to_ruby
    end
  else
    parse_stream(yaml, filename).children.map { |child| child.to_ruby }
  end
end

.object_maker(klass, hash) ⇒ Object



73
74
75
76
77
78
# File 'lib/psych/deprecated.rb', line 73

def self.object_maker klass, hash
  warn "#{caller[0]}: object_maker is deprecated" if $VERBOSE
  klass.allocate.tap do |obj|
    hash.each { |k,v| obj.instance_variable_set(:"@#{k}", v) }
  end
end

.parse(yaml, filename = nil) ⇒ Object

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") # => #<Psych::Nodes::Document:0x00>

begin
  Psych.parse("--- `", "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.



324
325
326
327
328
329
# File 'lib/psych.rb', line 324

def self.parse yaml, filename = nil
  parse_stream(yaml, filename) do |node|
    return node
  end
  false
end

.parse_file(filename) ⇒ Object

Parse a file at filename. Returns the Psych::Nodes::Document.

Raises a Psych::SyntaxError when a YAML syntax error is detected.



335
336
337
338
339
# File 'lib/psych.rb', line 335

def self.parse_file filename
  File.open filename, 'r:bom|utf-8' do |f|
    parse f, filename
  end
end

.parse_stream(yaml, filename = nil, &block) ⇒ Object

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::Nodes::Stream:0x00>

Psych.parse_stream("--- a\n--- b") do |node|
  node # => #<Psych::Nodes::Document:0x00>
end

begin
  Psych.parse_stream("--- `", "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.



374
375
376
377
378
379
380
381
382
383
# File 'lib/psych.rb', line 374

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

.parserObject

Returns a default parser



343
344
345
# File 'lib/psych.rb', line 343

def self.parser
  Psych::Parser.new(TreeBuilder.new)
end

.quick_emit(thing, opts = {}, &block) ⇒ Object

:nodoc:



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/psych/deprecated.rb', line 12

def self.quick_emit thing, opts = {}, &block # :nodoc:
  warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
  target = eval 'self', block.binding
  target.extend DeprecatedMethods
  metaclass = class << target; self; end
  metaclass.send(:define_method, :encode_with) do |coder|
    target.taguri        = coder.tag
    target.to_yaml_style = coder.style
    block.call coder
  end
  target.psych_to_yaml unless opts[:nodump]
end

.read_type_class(type, reference) ⇒ Object



63
64
65
66
67
68
69
70
71
# File 'lib/psych/deprecated.rb', line 63

def self.read_type_class type, reference
  warn "#{caller[0]}: read_type_class is deprecated" if $VERBOSE
  _, _, type, name = type.split ':', 4

  reference = name.split('::').inject(reference) do |k,n|
    k.const_get(n.to_sym)
  end if name
  [type, reference]
end

.remove_type(type_tag) ⇒ Object



488
489
490
# File 'lib/psych.rb', line 488

def self.remove_type type_tag
  @domain_types.delete type_tag
end

.safe_load(yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil) ⇒ Object

Safely load the yaml string in yaml. By default, only the following classes are allowed to be deserialized:

  • TrueClass

  • FalseClass

  • NilClass

  • Numeric

  • String

  • Array

  • Hash

Recursive data structures are not allowed by default. Arbitrary classes can be allowed by adding those classes to the whitelist. They are additive. For example, to allow Date deserialization:

Psych.safe_load(yaml, [Date])

Now the Date class can be loaded in addition to the classes listed above.

Aliases can be explicitly allowed by changing the aliases parameter. For example:

x = []
x << x
yaml = Psych.dump x
Psych.safe_load yaml               # => raises an exception
Psych.safe_load yaml, [], [], true # => loads the aliases

A Psych::DisallowedClass exception will be raised if the yaml contains a class that isn’t in the whitelist.

A Psych::BadAlias exception will be raised if the yaml contains aliases but the aliases parameter is set to false.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/psych.rb', line 290

def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil
  result = parse(yaml, filename)
  return unless result

  class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s),
                                             whitelist_symbols.map(&:to_s))
  scanner      = ScalarScanner.new class_loader
  if aliases
    visitor = Visitors::ToRuby.new scanner, class_loader
  else
    visitor = Visitors::NoAliasRuby.new scanner, class_loader
  end
  visitor.accept result
end

.tagurize(thing) ⇒ Object



57
58
59
60
61
# File 'lib/psych/deprecated.rb', line 57

def self.tagurize thing
  warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE
  return thing unless String === thing
  "tag:yaml.org,2002:#{thing}"
end

.to_json(object) ⇒ Object

Dump Ruby object to a JSON string.



436
437
438
439
440
# File 'lib/psych.rb', line 436

def self.to_json object
  visitor = Psych::Visitors::JSONTree.create
  visitor << object
  visitor.tree.yaml
end