230230module Psych
231231 # The version of libyaml Psych is using
232232 LIBYAML_VERSION = Psych . libyaml_version . join '.'
233-
234- FALLBACK = Struct . new :to_ruby # :nodoc:
233+ # Deprecation guard
234+ NOT_GIVEN = Object . new
235+ private_constant :NOT_GIVEN
235236
236237 ###
237238 # Load +yaml+ in to a Ruby data structure. If multiple documents are
@@ -248,7 +249,7 @@ module Psych
248249 # Psych.load("---\n - a\n - b") # => ['a', 'b']
249250 #
250251 # begin
251- # Psych.load("--- `", "file.txt")
252+ # Psych.load("--- `", filename: "file.txt")
252253 # rescue Psych::SyntaxError => ex
253254 # ex.file # => 'file.txt'
254255 # ex.message # => "(file.txt): found character that cannot start any token"
@@ -260,8 +261,15 @@ module Psych
260261 # Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
261262 # Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
262263 #
263- def self . load yaml , filename = nil , fallback : false , symbolize_names : false
264- result = parse ( yaml , filename , fallback : FALLBACK . new ( fallback ) )
264+ # Raises a TypeError when `yaml` parameter is NilClass
265+ #
266+ def self . load yaml , legacy_filename = NOT_GIVEN , filename : nil , fallback : false , symbolize_names : false
267+ if legacy_filename != NOT_GIVEN
268+ filename = legacy_filename
269+ end
270+
271+ result = parse ( yaml , filename : filename )
272+ return fallback unless result
265273 result = result . to_ruby if result
266274 symbolize_names! ( result ) if symbolize_names
267275 result
@@ -280,27 +288,27 @@ def self.load yaml, filename = nil, fallback: false, symbolize_names: false
280288 # * Hash
281289 #
282290 # Recursive data structures are not allowed by default. Arbitrary classes
283- # can be allowed by adding those classes to the +whitelist+ . They are
291+ # can be allowed by adding those classes to the +whitelist_classes+ keyword argument . They are
284292 # additive. For example, to allow Date deserialization:
285293 #
286- # Psych.safe_load(yaml, [Date])
294+ # Psych.safe_load(yaml, whitelist_classes: [Date])
287295 #
288296 # Now the Date class can be loaded in addition to the classes listed above.
289297 #
290- # Aliases can be explicitly allowed by changing the +aliases+ parameter .
298+ # Aliases can be explicitly allowed by changing the +aliases+ keyword argument .
291299 # For example:
292300 #
293301 # x = []
294302 # x << x
295303 # yaml = Psych.dump x
296304 # Psych.safe_load yaml # => raises an exception
297- # Psych.safe_load yaml, [], [], true # => loads the aliases
305+ # Psych.safe_load yaml, aliases: true # => loads the aliases
298306 #
299307 # A Psych::DisallowedClass exception will be raised if the yaml contains a
300308 # class that isn't in the whitelist.
301309 #
302310 # A Psych::BadAlias exception will be raised if the yaml contains aliases
303- # but the +aliases+ parameter is set to false.
311+ # but the +aliases+ keyword argument is set to false.
304312 #
305313 # +filename+ will be used in the exception message if any exception is raised
306314 # while parsing.
@@ -311,18 +319,34 @@ def self.load yaml, filename = nil, fallback: false, symbolize_names: false
311319 # Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
312320 # Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
313321 #
314- def self . safe_load yaml , whitelist_classes = [ ] , whitelist_symbols = [ ] , aliases = false , filename = nil , symbolize_names : false
315- result = parse ( yaml , filename )
316- return unless result
322+ def self . safe_load yaml , legacy_whitelist_classes = NOT_GIVEN , legacy_whitelist_symbols = NOT_GIVEN , legacy_aliases = NOT_GIVEN , legacy_filename = NOT_GIVEN , whitelist_classes : [ ] , whitelist_symbols : [ ] , aliases : false , filename : nil , fallback : nil , symbolize_names : false
323+ if legacy_whitelist_classes != NOT_GIVEN
324+ whitelist_classes = legacy_whitelist_classes
325+ end
326+
327+ if legacy_whitelist_symbols != NOT_GIVEN
328+ whitelist_symbols = legacy_whitelist_symbols
329+ end
330+
331+ if legacy_aliases != NOT_GIVEN
332+ aliases = legacy_aliases
333+ end
334+
335+ if legacy_filename != NOT_GIVEN
336+ filename = legacy_filename
337+ end
338+
339+ result = parse ( yaml , filename : filename )
340+ return fallback unless result
317341
318342 class_loader = ClassLoader ::Restricted . new ( whitelist_classes . map ( &:to_s ) ,
319343 whitelist_symbols . map ( &:to_s ) )
320344 scanner = ScalarScanner . new class_loader
321- if aliases
322- visitor = Visitors ::ToRuby . new scanner , class_loader
323- else
324- visitor = Visitors ::NoAliasRuby . new scanner , class_loader
325- end
345+ visitor = if aliases
346+ Visitors ::ToRuby . new scanner , class_loader
347+ else
348+ Visitors ::NoAliasRuby . new scanner , class_loader
349+ end
326350 result = visitor . accept result
327351 symbolize_names! ( result ) if symbolize_names
328352 result
@@ -340,28 +364,38 @@ def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases
340364 # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00>
341365 #
342366 # begin
343- # Psych.parse("--- `", "file.txt")
367+ # Psych.parse("--- `", filename: "file.txt")
344368 # rescue Psych::SyntaxError => ex
345369 # ex.file # => 'file.txt'
346370 # ex.message # => "(file.txt): found character that cannot start any token"
347371 # end
348372 #
349373 # See Psych::Nodes for more information about YAML AST.
350- def self . parse yaml , filename = nil , fallback : false
351- parse_stream ( yaml , filename ) do |node |
374+ def self . parse yaml , legacy_filename = NOT_GIVEN , filename : nil , fallback : NOT_GIVEN
375+ if legacy_filename != NOT_GIVEN
376+ filename = legacy_filename
377+ end
378+
379+ parse_stream ( yaml , filename : filename ) do |node |
352380 return node
353381 end
354- fallback
382+
383+ if fallback != NOT_GIVEN
384+ fallback
385+ else
386+ false
387+ end
355388 end
356389
357390 ###
358391 # Parse a file at +filename+. Returns the Psych::Nodes::Document.
359392 #
360393 # Raises a Psych::SyntaxError when a YAML syntax error is detected.
361- def self . parse_file filename
362- File . open filename , 'r:bom|utf-8' do |f |
363- parse f , filename
394+ def self . parse_file filename , fallback : false
395+ result = File . open filename , 'r:bom|utf-8' do |f |
396+ parse f , filename : filename
364397 end
398+ result || fallback
365399 end
366400
367401 ###
@@ -390,14 +424,20 @@ def self.parser
390424 # end
391425 #
392426 # begin
393- # Psych.parse_stream("--- `", "file.txt")
427+ # Psych.parse_stream("--- `", filename: "file.txt")
394428 # rescue Psych::SyntaxError => ex
395429 # ex.file # => 'file.txt'
396430 # ex.message # => "(file.txt): found character that cannot start any token"
397431 # end
398432 #
433+ # Raises a TypeError when NilClass is passed.
434+ #
399435 # See Psych::Nodes for more information about YAML AST.
400- def self . parse_stream yaml , filename = nil , &block
436+ def self . parse_stream yaml , legacy_filename = NOT_GIVEN , filename : nil , &block
437+ if legacy_filename != NOT_GIVEN
438+ filename = legacy_filename
439+ end
440+
401441 if block_given?
402442 parser = Psych ::Parser . new ( Handlers ::DocumentStream . new ( &block ) )
403443 parser . parse yaml , filename
@@ -498,14 +538,21 @@ def self.to_json object
498538 # end
499539 # list # => ['foo', 'bar']
500540 #
501- def self . load_stream yaml , filename = nil
502- if block_given?
503- parse_stream ( yaml , filename ) do |node |
504- yield node . to_ruby
505- end
506- else
507- parse_stream ( yaml , filename ) . children . map { |child | child . to_ruby }
541+ def self . load_stream yaml , legacy_filename = NOT_GIVEN , filename : nil , fallback : [ ]
542+ if legacy_filename != NOT_GIVEN
543+ filename = legacy_filename
508544 end
545+
546+ result = if block_given?
547+ parse_stream ( yaml , filename : filename ) do |node |
548+ yield node . to_ruby
549+ end
550+ else
551+ parse_stream ( yaml , filename : filename ) . children . map ( &:to_ruby )
552+ end
553+
554+ return fallback if result . is_a? ( Array ) && result . empty?
555+ result
509556 end
510557
511558 ###
@@ -514,7 +561,7 @@ def self.load_stream yaml, filename = nil
514561 # the specified +fallback+ return value, which defaults to +false+.
515562 def self . load_file filename , fallback : false
516563 File . open ( filename , 'r:bom|utf-8' ) { |f |
517- self . load f , filename , fallback : fallback
564+ self . load f , filename : filename , fallback : fallback
518565 }
519566 end
520567
0 commit comments