summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2011-12-06 15:14:27 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2011-12-06 15:14:27 -0800
commit40b1bc7cf72570f0645675b0e950de455566fe5e (patch)
tree3cda8d7d4e6308d62f97968af525c1227004ae92
parent7aad593c5e6e37e5b5f218b51a91cc005d10a3ac (diff)
downloadpsych-40b1bc7cf72570f0645675b0e950de455566fe5e.zip
* ext/psych/lib/psych.rb (module Psych): parse and load methods take
an optional file name that is used when raising Psych::SyntaxError exceptions * ext/psych/lib/psych/syntax_error.rb (module Psych): allow nil file names and handle nil file names in the exception message * test/psych/test_exception.rb (module Psych): Tests for changes.
-rw-r--r--CHANGELOG.rdoc9
-rw-r--r--lib/psych.rb59
-rw-r--r--lib/psych/syntax_error.rb5
-rw-r--r--test/psych/test_exception.rb78
4 files changed, 136 insertions, 15 deletions
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc
index d1184d4..6ea5d6f 100644
--- a/CHANGELOG.rdoc
+++ b/CHANGELOG.rdoc
@@ -1,3 +1,12 @@
+Wed Dec 7 08:04:31 2011 Aaron Patterson <aaron@tenderlovemaking.com>
+
+ * ext/psych/lib/psych.rb (module Psych): parse and load methods take
+ an optional file name that is used when raising Psych::SyntaxError
+ exceptions
+ * ext/psych/lib/psych/syntax_error.rb (module Psych): allow nil file
+ names and handle nil file names in the exception message
+ * test/psych/test_exception.rb (module Psych): Tests for changes.
+
Wed Nov 30 09:09:37 2011 Aaron Patterson <aaron@tenderlovemaking.com>
* ext/psych/parser.c (parse): parse method can take an option file
diff --git a/lib/psych.rb b/lib/psych.rb
index ebf2b35..3b7f9a3 100644
--- a/lib/psych.rb
+++ b/lib/psych.rb
@@ -106,34 +106,58 @@ module Psych
###
# 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']
- def self.load yaml
- result = parse(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 # => "(foo.txt): found character that cannot start any token"
+ # end
+ def self.load yaml, filename = nil
+ result = parse(yaml, filename)
result ? result.to_ruby : result
end
###
# Parse a YAML string in +yaml+. Returns the first object of a YAML AST.
+ # +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::Sequence:0x00>
#
+ # begin
+ # Psych.parse("--- `", "file.txt")
+ # rescue Psych::SyntaxError => ex
+ # ex.file # => 'file.txt'
+ # ex.message # => "(foo.txt): found character that cannot start any token"
+ # end
+ #
# See Psych::Nodes for more information about YAML AST.
- def self.parse yaml
- children = parse_stream(yaml).children
+ def self.parse yaml, filename = nil
+ children = parse_stream(yaml, filename).children
children.empty? ? false : children.first.children.first
end
###
# Parse a file at +filename+. Returns the YAML AST.
+ #
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
def self.parse_file filename
File.open filename do |f|
- parse f
+ parse f, filename
end
end
@@ -146,15 +170,26 @@ module Psych
###
# Parse a YAML string in +yaml+. Returns the full AST for the YAML document.
# This method can handle multiple YAML documents contained in +yaml+.
+ # +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_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
#
+ # begin
+ # Psych.parse_stream("--- `", "file.txt")
+ # rescue Psych::SyntaxError => ex
+ # ex.file # => 'file.txt'
+ # ex.message # => "(foo.txt): found character that cannot start any token"
+ # end
+ #
# See Psych::Nodes for more information about YAML AST.
- def self.parse_stream yaml
+ def self.parse_stream yaml, filename = nil
parser = self.parser
- parser.parse yaml
+ parser.parse yaml, filename
parser.handler.root
end
@@ -221,15 +256,15 @@ module Psych
#
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
#
- def self.load_stream yaml
- parse_stream(yaml).children.map { |child| child.to_ruby }
+ def self.load_stream yaml, filename = nil
+ parse_stream(yaml, filename).children.map { |child| child.to_ruby }
end
###
# Load the document contained in +filename+. Returns the yaml contained in
# +filename+ as a ruby object
def self.load_file filename
- File.open(filename) { |f| self.load f }
+ File.open(filename) { |f| self.load f, filename }
end
# :stopdoc:
diff --git a/lib/psych/syntax_error.rb b/lib/psych/syntax_error.rb
index 9fe3e0d..f79743d 100644
--- a/lib/psych/syntax_error.rb
+++ b/lib/psych/syntax_error.rb
@@ -3,8 +3,9 @@ module Psych
attr_reader :file, :line, :column, :offset, :problem, :context
def initialize file, line, col, offset, problem, context
- err = [problem, context].compact.join ' '
- message = "(%s): %s at line %d column %d" % [file, err, line, col]
+ err = [problem, context].compact.join ' '
+ filename = file || '<unknown>'
+ message = "(%s): %s at line %d column %d" % [filename, err, line, col]
@file = file
@line = line
diff --git a/test/psych/test_exception.rb b/test/psych/test_exception.rb
index 5530a69..c6d98d7 100644
--- a/test/psych/test_exception.rb
+++ b/test/psych/test_exception.rb
@@ -16,12 +16,88 @@ module Psych
@wups = Wups.new
end
+ def test_load_takes_file
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.load '--- `'
+ end
+ assert_nil ex.file
+
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.load '--- `', 'meow'
+ end
+ assert_equal 'meow', ex.file
+ end
+
+ def test_psych_parse_stream_takes_file
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.parse_stream '--- `'
+ end
+ assert_nil ex.file
+ assert_match '(<unknown>)', ex.message
+
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.parse_stream '--- `', 'omg!'
+ end
+ assert_equal 'omg!', ex.file
+ assert_match 'omg!', ex.message
+ end
+
+ def test_load_stream_takes_file
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.load_stream '--- `'
+ end
+ assert_nil ex.file
+ assert_match '(<unknown>)', ex.message
+
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.load_stream '--- `', 'omg!'
+ end
+ assert_equal 'omg!', ex.file
+ end
+
+ def test_parse_file_exception
+ t = Tempfile.new(['parsefile', 'yml'])
+ t.binmode
+ t.write '--- `'
+ t.close
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.parse_file t.path
+ end
+ assert_equal t.path, ex.file
+ t.close(true)
+ end
+
+ def test_load_file_exception
+ t = Tempfile.new(['loadfile', 'yml'])
+ t.binmode
+ t.write '--- `'
+ t.close
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.load_file t.path
+ end
+ assert_equal t.path, ex.file
+ t.close(true)
+ end
+
+ def test_psych_parse_takes_file
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.parse '--- `'
+ end
+ assert_match '(<unknown>)', ex.message
+ assert_nil ex.file
+
+ ex = assert_raises(Psych::SyntaxError) do
+ Psych.parse '--- `', 'omg!'
+ end
+ assert_match 'omg!', ex.message
+ end
+
def test_attributes
e = assert_raises(Psych::SyntaxError) {
Psych.load '--- `foo'
}
- assert_equal '<unknown>', e.file
+ assert_nil e.file
assert_equal 1, e.line
assert_equal 5, e.column
# FIXME: offset isn't being set correctly by libyaml