psych 3.3.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 816fda8fc436476e4117450ad248554d12b2d41c25439e457c171583b0ad3e6a
4
- data.tar.gz: 83ce5b7ccd045a76f430d7a13b30c356d05be0014d753945f412ab0e939fe0da
3
+ metadata.gz: c1f28150eddba20d25bc0148ef02586e0c57defafab2fd085ff3838797ee0678
4
+ data.tar.gz: e7025e3b097c4b46a9a1cafb92441b362e3e85b909e70839eb7163881edc7d23
5
5
  SHA512:
6
- metadata.gz: 855d085016ed2c1f30bc3a3433247ad34ce06220d3871b7a92b922d89fde0a645471b8512f41b9d43812de407dcfaf01b23458475dfc1e0c37b9bbb6ff8d91f6
7
- data.tar.gz: 1191a34c8cf1c82687fbf94a25fdcce854c585718ef69aaedf97eb5a2cc1b07225ec44769a00b58124f67d58e33f138f657ea2233094f76bad1d2479d7a1b400
6
+ metadata.gz: 7eb5c82f61ba859be6207a1a1ecffc63ab4948437bbe8d380838b033324dfba165319fe65804a407742545e96e47eb7656c2299fd7805e9114387efedd959d8c
7
+ data.tar.gz: e83978ee6e12de207ae51985f00d0907e42c68d9960d4e6f4f89c5e9b5062d5d4c6f8851bc3289e18331cdf15eb31d59a5e9e63111a2625bc3aa238382d700f1
data/Rakefile CHANGED
@@ -33,7 +33,7 @@ end
33
33
 
34
34
  task :sync_tool do
35
35
  require 'fileutils'
36
- FileUtils.cp "../ruby/tool/lib/test/unit/core_assertions.rb", "./test/lib"
36
+ FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
37
37
  FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
38
38
  FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
39
39
  end
data/ext/psych/depend CHANGED
@@ -1,4 +1,16 @@
1
- $(OBJS): $(YAML_H)
1
+ $(TARGET_SO): $(LIBYAML)
2
+
3
+ libyaml $(LIBYAML):
4
+ cd libyaml && $(MAKE)
5
+ $(AR) $(ARFLAGS) $(LIBYAML) $(LIBYAML_OBJDIR)/*.$(OBJEXT)
6
+ $(RANLIB) $(LIBYAML)
7
+
8
+ clean-so::
9
+ -cd libyaml && $(MAKE) clean
10
+
11
+ distclean-so::
12
+ -cd libyaml && $(MAKE) distclean
13
+ -$(Q)$(RMDIRS) libyaml/* libyaml
2
14
 
3
15
  $(OBJS): $(HDRS) $(ruby_headers) \
4
16
  $(hdrdir)/ruby/encoding.h \
data/ext/psych/extconf.rb CHANGED
@@ -1,43 +1,53 @@
1
1
  # -*- coding: us-ascii -*-
2
2
  # frozen_string_literal: true
3
3
  require 'mkmf'
4
- require 'fileutils'
5
4
 
6
- # :stopdoc:
7
-
8
- dir_config 'libyaml'
9
-
10
- if enable_config("bundled-libyaml", false) || !(find_header('yaml.h') && find_library('yaml', 'yaml_get_version'))
11
- # Embed libyaml since we could not find it.
12
-
13
- $VPATH << "$(srcdir)/yaml"
14
- $INCFLAGS << " -I$(srcdir)/yaml"
15
-
16
- $srcs = Dir.glob("#{$srcdir}/{,yaml/}*.c").map {|n| File.basename(n)}.sort
5
+ if $mswin or $mingw or $cygwin
6
+ $CPPFLAGS << " -DYAML_DECLARE_STATIC"
7
+ end
17
8
 
18
- header = 'yaml/yaml.h'
19
- header = "{$(VPATH)}#{header}" if $nmake
20
- if have_macro("_WIN32")
21
- $CPPFLAGS << " -DYAML_DECLARE_STATIC -DHAVE_CONFIG_H"
9
+ yaml_source = with_config("libyaml-source-dir")
10
+ if yaml_source
11
+ yaml_source = yaml_source.gsub(/\$\((\w+)\)|\$\{(\w+)\}/) {ENV[$1||$2]}
12
+ yaml_source = yaml_source.chomp("/")
13
+ yaml_configure = "#{File.expand_path(yaml_source)}/configure"
14
+ unless File.exist?(yaml_configure)
15
+ raise "Configure script not found in #{yaml_source.quote}"
22
16
  end
23
17
 
24
- have_header 'dlfcn.h'
25
- have_header 'inttypes.h'
26
- have_header 'memory.h'
27
- have_header 'stdint.h'
28
- have_header 'stdlib.h'
29
- have_header 'strings.h'
30
- have_header 'string.h'
31
- have_header 'sys/stat.h'
32
- have_header 'sys/types.h'
33
- have_header 'unistd.h'
34
-
35
- find_header 'yaml.h'
36
- have_header 'config.h'
18
+ puts("Configuring libyaml source in #{yaml_source.quote}")
19
+ yaml = "libyaml"
20
+ Dir.mkdir(yaml) unless File.directory?(yaml)
21
+ shared = $enable_shared || !$static
22
+ args = [
23
+ yaml_configure,
24
+ "--enable-#{shared ? 'shared' : 'static'}",
25
+ "--host=#{RbConfig::CONFIG['host'].sub(/-unknown-/, '-')}",
26
+ "CC=#{RbConfig::CONFIG['CC']}",
27
+ *(["CFLAGS=-w"] if RbConfig::CONFIG["GCC"] == "yes"),
28
+ ]
29
+ puts(args.quote.join(' '))
30
+ unless system(*args, chdir: yaml)
31
+ raise "failed to configure libyaml"
32
+ end
33
+ inc = yaml_source.start_with?("#$srcdir/") ? "$(srcdir)#{yaml_source[$srcdir.size..-1]}" : yaml_source
34
+ $INCFLAGS << " -I#{yaml}/include -I#{inc}/include"
35
+ puts("INCFLAGS=#$INCFLAGS")
36
+ libyaml = "libyaml.#$LIBEXT"
37
+ $cleanfiles << libyaml
38
+ $LOCAL_LIBS.prepend("$(LIBYAML) ")
39
+ else # default to pre-installed libyaml
40
+ pkg_config('yaml-0.1')
41
+ dir_config('libyaml')
42
+ find_header('yaml.h') or abort "yaml.h not found"
43
+ find_library('yaml', 'yaml_get_version') or abort "libyaml not found"
37
44
  end
38
45
 
39
46
  create_makefile 'psych' do |mk|
40
- mk << "YAML_H = #{header}".strip << "\n"
47
+ mk << "LIBYAML = #{libyaml}".strip << "\n"
48
+ mk << "LIBYAML_OBJDIR = libyaml/src#{shared ? '/.libs' : ''}\n"
49
+ mk << "OBJEXT = #$OBJEXT"
50
+ mk << "RANLIB = #{config_string('RANLIB') || config_string('NULLCMD')}\n"
41
51
  end
42
52
 
43
53
  # :startdoc:
@@ -79,21 +79,25 @@ static VALUE allocate(VALUE klass)
79
79
 
80
80
  static VALUE make_exception(yaml_parser_t * parser, VALUE path)
81
81
  {
82
- size_t line, column;
83
- VALUE ePsychSyntaxError;
82
+ if (parser->error == YAML_MEMORY_ERROR) {
83
+ return rb_eNoMemError;
84
+ } else {
85
+ size_t line, column;
86
+ VALUE ePsychSyntaxError;
84
87
 
85
- line = parser->context_mark.line + 1;
86
- column = parser->context_mark.column + 1;
88
+ line = parser->context_mark.line + 1;
89
+ column = parser->context_mark.column + 1;
87
90
 
88
- ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
91
+ ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
89
92
 
90
- return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
91
- path,
92
- SIZET2NUM(line),
93
- SIZET2NUM(column),
94
- SIZET2NUM(parser->problem_offset),
95
- parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
96
- parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
93
+ return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
94
+ path,
95
+ SIZET2NUM(line),
96
+ SIZET2NUM(column),
97
+ SIZET2NUM(parser->problem_offset),
98
+ parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
99
+ parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
100
+ }
97
101
  }
98
102
 
99
103
  static VALUE transcode_string(VALUE src, int * parser_encoding)
@@ -241,18 +245,8 @@ static VALUE protected_event_location(VALUE pointer)
241
245
  return rb_funcall3(args[0], id_event_location, 4, args + 1);
242
246
  }
243
247
 
244
- /*
245
- * call-seq:
246
- * parser.parse(yaml)
247
- *
248
- * Parse the YAML document contained in +yaml+. Events will be called on
249
- * the handler set on the parser instance.
250
- *
251
- * See Psych::Parser and Psych::Parser#handler
252
- */
253
- static VALUE parse(int argc, VALUE *argv, VALUE self)
248
+ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
254
249
  {
255
- VALUE yaml, path;
256
250
  yaml_parser_t * parser;
257
251
  yaml_event_t event;
258
252
  int done = 0;
@@ -260,14 +254,6 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
260
254
  int parser_encoding = YAML_ANY_ENCODING;
261
255
  int encoding = rb_utf8_encindex();
262
256
  rb_encoding * internal_enc = rb_default_internal_encoding();
263
- VALUE handler = rb_iv_get(self, "@handler");
264
-
265
- if (rb_scan_args(argc, argv, "11", &yaml, &path) == 1) {
266
- if(rb_respond_to(yaml, id_path))
267
- path = rb_funcall(yaml, id_path, 0);
268
- else
269
- path = rb_str_new2("<unknown>");
270
- }
271
257
 
272
258
  TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
273
259
 
@@ -293,7 +279,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
293
279
  VALUE event_args[5];
294
280
  VALUE start_line, start_column, end_line, end_column;
295
281
 
296
- if(!yaml_parser_parse(parser, &event)) {
282
+ if(parser->error || !yaml_parser_parse(parser, &event)) {
297
283
  VALUE exception;
298
284
 
299
285
  exception = make_exception(parser, path);
@@ -558,7 +544,7 @@ void Init_psych_parser(void)
558
544
 
559
545
  rb_require("psych/syntax_error");
560
546
 
561
- rb_define_method(cPsychParser, "parse", parse, -1);
547
+ rb_define_private_method(cPsychParser, "_native_parse", parse, 3);
562
548
  rb_define_method(cPsychParser, "mark", mark, 0);
563
549
 
564
550
  id_read = rb_intern("read");
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/omap'
3
- require 'psych/set'
2
+ require_relative 'omap'
3
+ require_relative 'set'
4
4
 
5
5
  module Psych
6
6
  class ClassLoader # :nodoc:
@@ -86,7 +86,7 @@ module Psych
86
86
  if @symbols.include? sym
87
87
  super
88
88
  else
89
- raise DisallowedClass, 'Symbol'
89
+ raise DisallowedClass.new('load', 'Symbol')
90
90
  end
91
91
  end
92
92
 
@@ -96,7 +96,7 @@ module Psych
96
96
  if @classes.include? klassname
97
97
  super
98
98
  else
99
- raise DisallowedClass, klassname
99
+ raise DisallowedClass.new('load', klassname)
100
100
  end
101
101
  end
102
102
  end
@@ -15,5 +15,5 @@ class Object
15
15
  end
16
16
 
17
17
  if defined?(::IRB)
18
- require 'psych/y'
18
+ require_relative 'y'
19
19
  end
@@ -6,9 +6,23 @@ module Psych
6
6
  class BadAlias < Exception
7
7
  end
8
8
 
9
+ # Subclasses `BadAlias` for backwards compatibility
10
+ class AliasesNotEnabled < BadAlias
11
+ def initialize
12
+ super "Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`."
13
+ end
14
+ end
15
+
16
+ # Subclasses `BadAlias` for backwards compatibility
17
+ class AnchorNotDefined < BadAlias
18
+ def initialize anchor_name
19
+ super "An alias referenced an unknown anchor: #{anchor_name}"
20
+ end
21
+ end
22
+
9
23
  class DisallowedClass < Exception
10
- def initialize klass_name
11
- super "Tried to load unspecified class: #{klass_name}"
24
+ def initialize action, klass_name
25
+ super "Tried to #{action} unspecified class: #{klass_name}"
12
26
  end
13
27
  end
14
28
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/tree_builder'
2
+ require_relative '../tree_builder'
3
3
 
4
4
  module Psych
5
5
  module Handlers
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/handler'
2
+ require_relative '../handler'
3
3
 
4
4
  module Psych
5
5
  module Handlers
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/json/ruby_events'
3
- require 'psych/json/yaml_events'
2
+ require_relative 'ruby_events'
3
+ require_relative 'yaml_events'
4
4
 
5
5
  module Psych
6
6
  module JSON
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/json/yaml_events'
2
+ require_relative 'yaml_events'
3
3
 
4
4
  module Psych
5
5
  module JSON
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'stringio'
3
- require 'psych/class_loader'
4
- require 'psych/scalar_scanner'
3
+ require_relative '../class_loader'
4
+ require_relative '../scalar_scanner'
5
5
 
6
6
  module Psych
7
7
  module Nodes
@@ -46,8 +46,8 @@ module Psych
46
46
  # Convert this node to Ruby.
47
47
  #
48
48
  # See also Psych::Visitors::ToRuby
49
- def to_ruby(symbolize_names: false, freeze: false)
50
- Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze).accept(self)
49
+ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
50
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self)
51
51
  end
52
52
  alias :transform :to_ruby
53
53
 
data/lib/psych/nodes.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/nodes/node'
3
- require 'psych/nodes/stream'
4
- require 'psych/nodes/document'
5
- require 'psych/nodes/sequence'
6
- require 'psych/nodes/scalar'
7
- require 'psych/nodes/mapping'
8
- require 'psych/nodes/alias'
2
+ require_relative 'nodes/node'
3
+ require_relative 'nodes/stream'
4
+ require_relative 'nodes/document'
5
+ require_relative 'nodes/sequence'
6
+ require_relative 'nodes/scalar'
7
+ require_relative 'nodes/mapping'
8
+ require_relative 'nodes/alias'
9
9
 
10
10
  module Psych
11
11
  ###
data/lib/psych/parser.rb CHANGED
@@ -48,5 +48,18 @@ module Psych
48
48
  @handler = handler
49
49
  @external_encoding = ANY
50
50
  end
51
+
52
+ ###
53
+ # call-seq:
54
+ # parser.parse(yaml)
55
+ #
56
+ # Parse the YAML document contained in +yaml+. Events will be called on
57
+ # the handler set on the parser instance.
58
+ #
59
+ # See Psych::Parser and Psych::Parser#handler
60
+
61
+ def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>"
62
+ _native_parse @handler, yaml, path
63
+ end
51
64
  end
52
65
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'strscan'
3
2
 
4
3
  module Psych
5
4
  ###
@@ -9,32 +8,39 @@ module Psych
9
8
  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)?))?$/
10
9
 
11
10
  # Taken from http://yaml.org/type/float.html
12
- FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
13
- |[-+]?\.(inf|Inf|INF)(?# infinity)
14
- |\.(nan|NaN|NAN)(?# not a number))$/x
11
+ # Base 60, [-+]inf and NaN are handled separately
12
+ FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
15
13
 
16
14
  # Taken from http://yaml.org/type/int.html
17
- INTEGER = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
18
- |[-+]?0[0-7_,]+ (?# base 8)
19
- |[-+]?(?:0|[1-9][0-9_,]*) (?# base 10)
20
- |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
15
+ INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2)
16
+ |[-+]?0[0-7_]+ (?# base 8)
17
+ |[-+]?(0|[1-9][0-9_]*) (?# base 10)
18
+ |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
19
+
20
+ # Same as above, but allows commas.
21
+ # Not to YML spec, but kept for backwards compatibility
22
+ INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
23
+ |[-+]?0[0-7_,]+ (?# base 8)
24
+ |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
25
+ |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
21
26
 
22
27
  attr_reader :class_loader
23
28
 
24
29
  # Create a new scanner
25
- def initialize class_loader
30
+ def initialize class_loader, strict_integer: false
26
31
  @symbol_cache = {}
27
32
  @class_loader = class_loader
33
+ @strict_integer = strict_integer
28
34
  end
29
35
 
30
36
  # Tokenize +string+ returning the Ruby object
31
37
  def tokenize string
32
38
  return nil if string.empty?
33
39
  return @symbol_cache[string] if @symbol_cache.key?(string)
34
-
40
+ integer_regex = @strict_integer ? INTEGER_STRICT : INTEGER_LEGACY
35
41
  # Check for a String type, being careful not to get caught by hash keys, hex values, and
36
42
  # special floats (e.g., -.inf).
37
- if string.match?(/^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/) || string.match?(/\n/)
43
+ if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
38
44
  return string if string.length > 5
39
45
 
40
46
  if string.match?(/^[^ytonf~]/i)
@@ -57,11 +63,11 @@ module Psych
57
63
  elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
58
64
  require 'date'
59
65
  begin
60
- class_loader.date.strptime(string, '%Y-%m-%d')
66
+ class_loader.date.strptime(string, '%F', Date::GREGORIAN)
61
67
  rescue ArgumentError
62
68
  string
63
69
  end
64
- elsif string.match?(/^\.inf$/i)
70
+ elsif string.match?(/^\+?\.inf$/i)
65
71
  Float::INFINITY
66
72
  elsif string.match?(/^-\.inf$/i)
67
73
  -Float::INFINITY
@@ -89,9 +95,9 @@ module Psych
89
95
  if string.match?(/\A[-+]?\.\Z/)
90
96
  string
91
97
  else
92
- Float(string.gsub(/[,_]|\.([Ee]|$)/, '\1'))
98
+ Float(string.delete(',_').gsub(/\.([Ee]|$)/, '\1'))
93
99
  end
94
- elsif string.match?(INTEGER)
100
+ elsif string.match?(integer_regex)
95
101
  parse_int string
96
102
  else
97
103
  string
@@ -101,7 +107,7 @@ module Psych
101
107
  ###
102
108
  # Parse and return an int from +string+
103
109
  def parse_int string
104
- Integer(string.gsub(/[,_]/, ''))
110
+ Integer(string.delete(',_'))
105
111
  end
106
112
 
107
113
  ###
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/exception'
2
+ require_relative 'exception'
3
3
 
4
4
  module Psych
5
5
  class SyntaxError < Psych::Exception
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/handler'
2
+ require_relative 'handler'
3
3
 
4
4
  module Psych
5
5
  ###
@@ -2,9 +2,9 @@
2
2
 
3
3
  module Psych
4
4
  # The version of Psych you are using
5
- VERSION = '3.3.2'
5
+ VERSION = '5.0.0'
6
6
 
7
7
  if RUBY_ENGINE == 'jruby'
8
- DEFAULT_SNAKEYAML_VERSION = '1.28'.freeze
8
+ DEFAULT_SNAKEYAML_VERSION = '1.33'.freeze
9
9
  end
10
10
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/json/ruby_events'
2
+ require_relative '../json/ruby_events'
3
3
 
4
4
  module Psych
5
5
  module Visitors
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/scalar_scanner'
3
- require 'psych/class_loader'
4
- require 'psych/exception'
2
+ require_relative '../scalar_scanner'
3
+ require_relative '../class_loader'
4
+ require_relative '../exception'
5
5
 
6
6
  unless defined?(Regexp::NOENCODING)
7
7
  Regexp::NOENCODING = 32
@@ -12,9 +12,9 @@ module Psych
12
12
  ###
13
13
  # This class walks a YAML AST, converting each node to Ruby
14
14
  class ToRuby < Psych::Visitors::Visitor
15
- def self.create(symbolize_names: false, freeze: false)
15
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false)
16
16
  class_loader = ClassLoader.new
17
- scanner = ScalarScanner.new class_loader
17
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
18
18
  new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
19
19
  end
20
20
 
@@ -80,7 +80,9 @@ module Psych
80
80
  when "!ruby/object:DateTime"
81
81
  class_loader.date_time
82
82
  require 'date' unless defined? DateTime
83
- @ss.parse_time(o.value).to_datetime
83
+ t = @ss.parse_time(o.value)
84
+ DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
85
+ (t.subsec/86400)
84
86
  when '!ruby/encoding'
85
87
  ::Encoding.find o.value
86
88
  when "!ruby/object:Complex"
@@ -323,7 +325,7 @@ module Psych
323
325
  end
324
326
 
325
327
  def visit_Psych_Nodes_Alias o
326
- @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
328
+ @st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
327
329
  end
328
330
 
329
331
  private
@@ -427,7 +429,7 @@ module Psych
427
429
 
428
430
  class NoAliasRuby < ToRuby
429
431
  def visit_Psych_Nodes_Alias o
430
- raise BadAlias, "Unknown alias: #{o.anchor}"
432
+ raise AliasesNotEnabled
431
433
  end
432
434
  end
433
435
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/tree_builder'
3
- require 'psych/scalar_scanner'
4
- require 'psych/class_loader'
2
+ require_relative '../tree_builder'
3
+ require_relative '../scalar_scanner'
4
+ require_relative '../class_loader'
5
5
 
6
6
  module Psych
7
7
  module Visitors
@@ -192,12 +192,13 @@ module Psych
192
192
  register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
193
193
  end
194
194
 
195
+ def visit_Date o
196
+ register o, visit_Integer(o.gregorian)
197
+ end
198
+
195
199
  def visit_DateTime o
196
- formatted = if o.offset.zero?
197
- o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
198
- else
199
- o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
200
- end
200
+ t = o.italy
201
+ formatted = format_time t, t.offset.zero?
201
202
  tag = '!ruby/object:DateTime'
202
203
  register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
203
204
  end
@@ -235,7 +236,6 @@ module Psych
235
236
  end
236
237
  alias :visit_TrueClass :visit_Integer
237
238
  alias :visit_FalseClass :visit_Integer
238
- alias :visit_Date :visit_Integer
239
239
 
240
240
  def visit_Float o
241
241
  if o.nan?
@@ -272,6 +272,8 @@ module Psych
272
272
  tag = 'tag:yaml.org,2002:str'
273
273
  plain = false
274
274
  quote = false
275
+ elsif o == 'y' || o == 'n'
276
+ style = Nodes::Scalar::DOUBLE_QUOTED
275
277
  elsif @line_width && o.length > @line_width
276
278
  style = Nodes::Scalar::FOLDED
277
279
  elsif o =~ /^[^[:word:]][^"]*$/
@@ -480,8 +482,8 @@ module Psych
480
482
  @emitter.end_mapping
481
483
  end
482
484
 
483
- def format_time time
484
- if time.utc?
485
+ def format_time time, utc = time.utc?
486
+ if utc
485
487
  time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
486
488
  else
487
489
  time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
@@ -535,5 +537,51 @@ module Psych
535
537
  end
536
538
  end
537
539
  end
540
+
541
+ class RestrictedYAMLTree < YAMLTree
542
+ DEFAULT_PERMITTED_CLASSES = {
543
+ TrueClass => true,
544
+ FalseClass => true,
545
+ NilClass => true,
546
+ Integer => true,
547
+ Float => true,
548
+ String => true,
549
+ Array => true,
550
+ Hash => true,
551
+ }.compare_by_identity.freeze
552
+
553
+ def initialize emitter, ss, options
554
+ super
555
+ @permitted_classes = DEFAULT_PERMITTED_CLASSES.dup
556
+ Array(options[:permitted_classes]).each do |klass|
557
+ @permitted_classes[klass] = true
558
+ end
559
+ @permitted_symbols = {}.compare_by_identity
560
+ Array(options[:permitted_symbols]).each do |symbol|
561
+ @permitted_symbols[symbol] = true
562
+ end
563
+ @aliases = options.fetch(:aliases, false)
564
+ end
565
+
566
+ def accept target
567
+ if !@aliases && @st.key?(target)
568
+ raise BadAlias, "Tried to dump an aliased object"
569
+ end
570
+
571
+ unless @permitted_classes[target.class]
572
+ raise DisallowedClass.new('dump', target.class.name || target.class.inspect)
573
+ end
574
+
575
+ super
576
+ end
577
+
578
+ def visit_Symbol sym
579
+ unless @permitted_symbols[sym]
580
+ raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})")
581
+ end
582
+
583
+ super
584
+ end
585
+ end
538
586
  end
539
587
  end