Spec-Zone.ru › Ruby 2.3

модуль Psych

Обзор

Psych — это парсер и генератор YAML. Psych использует libyaml [Главная страница: pyyaml.org/wiki/LibYAML] или [Репозиторий HG: bitbucket.org/xi/libyaml] для возможностей парсинга и генерации YAML. Помимо обертки над libyaml, Psych также умеет сериализовать и десериализовать большинство объектов Ruby в формат YAML и обратно.

МНЕ НУЖНО РАЗОБРАТЬ ИЛИ СГЕНЕРИРОВАТЬ YAML ПРЯМО СЕЙЧАС!

# Parse some YAML
Psych.load("--- foo") # => "foo"

# Emit some YAML
Psych.dump("foo")     # => "--- foo\n...\n"
{ :a => 'b'}.to_yaml  # => "---\n:a: b\n"

У вас есть больше времени? Продолжайте чтение!

Парсинг YAML

Psych предоставляет ряд интерфейсов для парсинга YAML-документа, от низкого до высокого уровня, в зависимости от ваших потребностей. На самом низком уровне — это парсер на основе событий. На среднем уровне — доступ к исходному AST YAML, а на самом высоком уровне — возможность распаковки YAML в объекты Ruby.

Генерация YAML

Psych предоставляет ряд интерфейсов для создания YAML-документов, от низкого до высокого уровня. Очень похоже на интерфейсы парсинга YAML, Psych предоставляет на самом низком уровне систему на основе событий, на среднем уровне — построение AST YAML, а на самом высоком уровне — преобразование объекта Ruby непосредственно в YAML-документ.

API высокого уровня

Парсинг

Парсер YAML высокого уровня, предоставляемый Psych, просто принимает YAML в качестве входных данных и возвращает структуру данных Ruby. Для получения информации об использовании парсера высокого уровня см. ::load

Чтение из строки

Psych.load("--- a")             # => 'a'
Psych.load("---\n - a\n - b")   # => ['a', 'b']

Чтение из файла

Psych.load_file("database.yml")

Обработка исключений

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

Генерация

У генератора высокого уровня самый простой интерфейс. Psych просто принимает структуру данных Ruby и преобразует ее в YAML-документ. См. ::dump для получения дополнительной информации о выгрузке структуры данных Ruby.

Запись в строку

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

Запись в файл

В настоящее время нет прямого API для выгрузки структуры Ruby в файл:

File.open('database.yml', 'w') do |file|
  file.write(Psych.dump(['a', 'b']))
end

API среднего уровня

Парсинг

Psych предоставляет доступ к AST, созданному из парсинга YAML-документа. Это дерево построено с использованием Psych::Parser и Psych::TreeBuilder. AST можно свободно исследовать и изменять. Обратитесь к ::parse_stream, Psych::Nodes и Psych::Nodes::Node для получения дополнительной информации о работе со синтаксическими деревьями YAML.

Чтение из строки

# Returns Psych::Nodes::Stream
Psych.parse_stream("---\n - a\n - b")

# Returns Psych::Nodes::Document
Psych.parse("---\n - a\n - b")

Чтение из файла

# Returns Psych::Nodes::Stream
Psych.parse_stream(File.read('database.yml'))

# Returns Psych::Nodes::Document
Psych.parse_file('database.yml')

Обработка исключений

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

Генерация

На среднем уровне происходит построение AST. Этот AST точно такой же, как AST, используемый при парсинге YAML-документа. Пользователи могут вручную построить AST, и AST знает, как сгенерировать себя как YAML-документ. См. Psych::Nodes, Psych::Nodes::Node и Psych::TreeBuilder для получения дополнительной информации о построении AST YAML.

Запись в строку

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

Запись в файл

# 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

API низкого уровня

Парсинг

Парсер самого низкого уровня следует использовать, когда входные данные YAML уже известны, и разработчик не хочет платить за создание AST или автоматическое обнаружение и преобразование в объекты Ruby. См. Psych::Parser для получения дополнительной информации об использовании парсера на основе событий.

Чтение в структуру

parser = Psych::Parser.new(TreeBuilder.new) # => #<Psych::Parser>
parser = Psych.parser                       # it's an alias for the above

parser.parse("---\n - a\n - b")             # => #<Psych::Parser>
parser.handler                              # => #<Psych::TreeBuilder>
parser.handler.root                         # => #<Psych::Nodes::Stream>

Получение потока событий

parser = Psych::Parser.new(Psych::Handlers::Recorder.new)

parser.parse("---\n - a\n - b")
parser.events # => [list of [event, args] lists]
              # event is one of: Psych::Handler::EVENTS
              # args are the arguments passed to the event

Генерация

Генератор самого низкого уровня — это система на основе событий. События отправляются объекту Psych::Emitter. Этот объект знает, как преобразовать события в YAML-документ. Этот интерфейс следует использовать, когда формат документа известен заранее или важна скорость. См. Psych::Emitter для получения дополнительной информации.

Запись в структуру Ruby

Psych.parser.parse("--- a")       # => #<Psych::Parser>

parser.handler.first              # => #<Psych::Nodes::Stream>
parser.handler.first.to_ruby      # => ["a"]

parser.handler.root.first         # => #<Psych::Nodes::Document>
parser.handler.root.first.to_ruby # => "a"

# You can instantiate an Emitter manually
Psych::Visitors::ToRuby.new.accept(parser.handler.root.first)
# => "a"

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

frozen_string_literal: false

Константы

DEFAULT_SNAKEYAML_VERSION
LIBYAML_VERSION

Версия libyaml, используемая Psych

VERSION

Версия Psych, которую вы используете

Методы публичного класса

add_private_type(type_tag, &block) Показать исходный код
# File ext/psych/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) Показать исходный код
# File ext/psych/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
detect_implicit(thing) Показать исходный код
# File ext/psych/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) → строка yaml Показать исходный код
dump(o, options) → строка yaml
dump(o, io) → объект io
dump(o, io, options) → объект io
# File ext/psych/lib/psych.rb, line 411
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

Преобразует объект Ruby o в строку YAML. Дополнительные options могут быть переданы для управления форматом вывода. Если передается объект IO, YAML будет выведен в этот объект IO.

Пример:

# 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)
dump_stream(*objects) Показать исходный код
# File ext/psych/lib/psych.rb, line 428
def self.dump_stream *objects
  visitor = Psych::Visitors::YAMLTree.create({})
  objects.each do |o|
    visitor << o
  end
  visitor.tree.yaml
end

Выводит список объектов как отдельные документы в поток документа.

Пример:

Psych.dump_stream("foo\n  ", {}) # => "--- ! \"foo\\n  \"\n--- {}\n"
libyaml_version Показать исходный код
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);
}

Возвращает используемую версию libyaml

load(yaml, filename = nil, fallback = false) Показать исходный код
# File ext/psych/lib/psych.rb, line 253
def self.load yaml, filename = nil, fallback = false
  result = parse(yaml, filename, fallback)
  result ? result.to_ruby : result
end

Загружает yaml в структуру данных Ruby. Если предоставлено несколько документов, возвращается объект, содержащийся в первом документе. filename будет использоваться в сообщении об ошибке, если во время разбора возникнет какая-либо ошибка.

Вызывает Psych::SyntaxError при обнаружении синтаксической ошибки YAML.

Пример:

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
load_documents(yaml, &block) Показать исходный код
# File ext/psych/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_stream вместо него.

load_file(filename, fallback = false) Показать исходный код
# File ext/psych/lib/psych.rb, line 473
def self.load_file filename, fallback = false
  File.open(filename, 'r:bom|utf-8') { |f|
    self.load f, filename, FALLBACK.new(fallback)
  }
end

Загружает документ, содержащийся в filename. Возвращает yaml, содержащийся в filename, как объект Ruby, или, если файл пустой, возвращает указанное значение по умолчанию, которое по умолчанию является пустым словарём.

load_stream(yaml, filename = nil) { |to_ruby| ... } Показать исходный код
# File ext/psych/lib/psych.rb, line 459
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

Загружает несколько документов, указанных в yaml. Возвращает список проанализированных документов. Если задан блок, каждый документ будет преобразован в Ruby и передан в блок во время разбора

Пример:

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']
object_maker(klass, hash) Показать исходный код
# File ext/psych/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, fallback = false) Показать исходный код
# File ext/psych/lib/psych.rb, line 326
def self.parse yaml, filename = nil, fallback = false
  parse_stream(yaml, filename) do |node|
    return node
  end
  fallback
end

Разбор строки YAML в yaml. Возвращает Psych::Nodes::Document. filename используется в сообщении об ошибке, если возникает Psych::SyntaxError.

Вызывает Psych::SyntaxError при обнаружении синтаксической ошибки YAML.

Пример:

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

См. Psych::Nodes для получения дополнительной информации о YAML AST.

parse_file(filename) Показать исходный код
# File ext/psych/lib/psych.rb, line 337
def self.parse_file filename
  File.open filename, 'r:bom|utf-8' do |f|
    parse f, filename
  end
end

Парсинг файла по адресу filename. Возвращает Psych::Nodes::Document.

Вызывает Psych::SyntaxError при обнаружении синтаксической ошибки YAML.

parse_stream(yaml, filename = nil, &block) Показать исходный код
# File ext/psych/lib/psych.rb, line 376
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

Парсинг строки YAML в yaml. Возвращает Psych::Nodes::Stream. Этот метод может обрабатывать несколько документов YAML, содержащихся в yaml. filename используется в сообщении об ошибке, если возникает Psych::SyntaxError.

Если задан блок, узел Psych::Nodes::Document будет передан в блок по мере его разбора.

Вызывает Psych::SyntaxError при обнаружении синтаксической ошибки YAML.

Пример:

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

См. Psych::Nodes для получения дополнительной информации о YAML AST.

parser() Показать исходный код
# File ext/psych/lib/psych.rb, line 345
def self.parser
  Psych::Parser.new(TreeBuilder.new)
end

Возвращает парсер по умолчанию

read_type_class(type, reference) Показать исходный код
# File ext/psych/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
safe_load(yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil) Показать исходный код
# File ext/psych/lib/psych.rb, line 292
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

Безопасно загружает строку yaml в yaml. По умолчанию разрешены только следующие классы:

  • TrueClass

  • FalseClass

  • NilClass

  • Numeric

  • Строка

  • Массив

  • Словарь

Вложенные структуры данных по умолчанию не разрешены. Произвольные классы могут быть разрешены путем добавления этих классов в whitelist. Они являются аддитивными. Например, для разрешения разбора Date:

Psych.safe_load(yaml, [Date])

Теперь класс Date может загружаться дополнительно к перечисленным выше классам.

Псевдонимы могут быть явно разрешены путем изменения параметра aliases. Например:

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

Исключение Psych::DisallowedClass будет вызвано, если yaml содержит класс, который не указан в списке разрешенных.

Исключение Psych::BadAlias будет вызвано, если yaml содержит псевдонимы, но параметр aliases установлен в false.

tagurize(thing) Показать исходный код
# File ext/psych/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) Показать исходный код
# File ext/psych/lib/psych.rb, line 438
def self.to_json object
  visitor = Psych::Visitors::JSONTree.create
  visitor << object
  visitor.tree.yaml
end

Преобразует Ruby object в строку JSON.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API