summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/psych/lib/psych.rb59
-rw-r--r--ext/psych/lib/psych/syntax_error.rb5
-rw-r--r--test/psych/test_exception.rb78
4 files changed, 136 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 8521885b56..0f50e5f16c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
+
Tue Dec 6 18:26:33 2011 Tanaka Akira <akr@fsij.org>
* ext/dbm/dbm.c: use db_version() instead of DB_VERSION_STRING to
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index ebf2b35d14..3b7f9a34f2 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/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/ext/psych/lib/psych/syntax_error.rb b/ext/psych/lib/psych/syntax_error.rb
index 9fe3e0da30..f79743dba4 100644
--- a/ext/psych/lib/psych/syntax_error.rb
+++ b/ext/psych/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 5530a69626..c6d98d7a99 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