Spec-Zone.ru › Ruby 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. Для получения информации о том, как использовать парсер высокого уровня, см. Psych.load

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

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

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

Psych.safe_load_file("data.yml", permitted_classes: [Date])
Psych.load_file("trusted_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. См. Psych.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 можно свободно исследовать и изменять. См. Psych::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>

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

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

Генерация

Генератор самого низкого уровня — это система на основе событий. События отправляются в объект 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"

Константы

DEFAULT_SNAKEYAML_VERSION
LIBYAML_VERSION

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

NOT_GIVEN

Защита от устаревания

VERSION

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

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

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

В настоящее время поддерживаются следующие параметры:

:indentation

Количество пробелов, используемых для отступа. Допустимое значение должно быть в диапазоне 0..9, в противном случае параметр игнорируется.

По умолчанию: 2.

:line_width

Максимальная длина строки для перевода строки.

По умолчанию: 0 (означает «перевод строки при 81»).

:canonical

Запись «канонической» формы YAML (очень подробной, но строго формальной).

По умолчанию: false.

:header

Запись «%YAML [version]» в начале документа.

По умолчанию: false.

Пример:

# 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 523
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(major);
    list[1] = INT2NUM(minor);
    list[2] = INT2NUM(patch);

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

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

load(yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false, freeze: false) Показать исходный код
# File ext/psych/lib/psych.rb, line 274
def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false, freeze: false
  if legacy_filename != NOT_GIVEN
    warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load is deprecated. Use keyword argument like Psych.load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
    filename = legacy_filename
  end

  result = parse(yaml, filename: filename)
  return fallback unless result
  result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
end

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

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

Пример:

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

Если необязательный параметр symbolize_names имеет значение true, возвращает символы для ключей в объектах Hash (по умолчанию — строки).

Psych.load("---\n foo: bar")                         # => {"foo"=>"bar"}
Psych.load("---\n foo: bar", symbolize_names: true)  # => {:foo=>"bar"}

Вызывает TypeError, если параметр `yaml` равен NilClass

ПРИМЕЧАНИЕ: Этот метод *не следует* использовать для разбора ненадежных документов, таких как документы YAML, предоставленные пользователем. Вместо этого используйте метод safe_load.

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

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

ПРИМЕЧАНИЕ: Этот метод *не следует* использовать для разбора ненадежных документов, таких как документы YAML, предоставленные пользователем. Вместо этого используйте метод safe_load_file.

load_stream(yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [], **kwargs) { |to_ruby(**kwargs)| ... } Показать исходный код
# File ext/psych/lib/psych.rb, line 554
def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [], **kwargs
  if legacy_filename != NOT_GIVEN
    warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load_stream is deprecated. Use keyword argument like Psych.load_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
    filename = legacy_filename
  end

  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

Загружает несколько документов, заданных в 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']
parse(yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: NOT_GIVEN) Показать исходный код
# File ext/psych/lib/psych.rb, line 384
def self.parse yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: NOT_GIVEN
  if legacy_filename != NOT_GIVEN
    warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse is deprecated. Use keyword argument like Psych.parse(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
    filename = legacy_filename
  end

  parse_stream(yaml, filename: filename) do |node|
    return node
  end

  if fallback != NOT_GIVEN
    warn_with_uplevel 'Passing the `fallback` keyword argument of Psych.parse is deprecated.', uplevel: 1 if $VERBOSE
    fallback
  else
    false
  end
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("--- `", filename: "file.txt")
rescue Psych::SyntaxError => ex
  ex.file    # => 'file.txt'
  ex.message # => "(file.txt): found character that cannot start any token"
end

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

parse_file(filename, fallback: false) Показать исходный код
# File ext/psych/lib/psych.rb, line 406
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

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

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

parse_stream(yaml, legacy_filename = NOT_GIVEN, filename: nil, &block) Показать исходный код
# File ext/psych/lib/psych.rb, line 448
def self.parse_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, &block
  if legacy_filename != NOT_GIVEN
    warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse_stream is deprecated. Use keyword argument like Psych.parse_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
    filename = legacy_filename
  end

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

Вызывает TypeError, если передан NilClass.

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

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

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

safe_load(yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false) Показать исходный код
# File ext/psych/lib/psych.rb, line 329
def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
  if legacy_permitted_classes != NOT_GIVEN
    warn_with_uplevel 'Passing permitted_classes with the 2nd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_classes: ...) instead.', uplevel: 1 if $VERBOSE
    permitted_classes = legacy_permitted_classes
  end

  if legacy_permitted_symbols != NOT_GIVEN
    warn_with_uplevel 'Passing permitted_symbols with the 3rd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_symbols: ...) instead.', uplevel: 1 if $VERBOSE
    permitted_symbols = legacy_permitted_symbols
  end

  if legacy_aliases != NOT_GIVEN
    warn_with_uplevel 'Passing aliases with the 4th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, aliases: ...) instead.', uplevel: 1 if $VERBOSE
    aliases = legacy_aliases
  end

  if legacy_filename != NOT_GIVEN
    warn_with_uplevel 'Passing filename with the 5th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
    filename = legacy_filename
  end

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

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

  • TrueClass

  • FalseClass

  • NilClass

  • Numeric

  • String

  • Array

  • Hash

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

Psych.safe_load(yaml, permitted_classes: [Date])

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

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

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

Psych::DisallowedClass будет вызван, если YAML содержит класс, который отсутствует в списке permitted_classes.

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

filename будет использоваться в сообщении об ошибке, если при разборе возникнет какая-либо ошибка.

Если необязательный параметр symbolize_names имеет значение true, возвращает символы для ключей в объектах Hash (по умолчанию — строки).

Psych.safe_load("---\n foo: bar")                         # => {"foo"=>"bar"}
Psych.safe_load("---\n foo: bar", symbolize_names: true)  # => {:foo=>"bar"}
safe_load_file(filename, **kwargs) Показать исходный код
# File ext/psych/lib/psych.rb, line 591
def self.safe_load_file filename, **kwargs
  File.open(filename, 'r:bom|utf-8') { |f|
    self.safe_load f, filename: filename, **kwargs
  }
end

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

to_json(object) Показать исходный код
# File ext/psych/lib/psych.rb, line 533
def self.to_json object
  visitor = Psych::Visitors::JSONTree.create
  visitor << object
  visitor.tree.yaml
end

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

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

Spec-Zone.ru

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