toml-rb 0.3.6 → 0.3.7
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 +4 -4
- data/Rakefile +4 -3
- data/init.rb +1 -0
- data/lib/toml/errors.rb +17 -0
- data/lib/toml/grammars/document.citrus +2 -2
- data/lib/toml/grammars/primitive.citrus +2 -2
- data/lib/toml/keygroup.rb +13 -8
- data/lib/toml/keyvalue.rb +0 -9
- data/lib/toml/parser.rb +3 -4
- data/lib/toml/string.rb +20 -2
- data/lib/toml/table_array.rb +4 -0
- data/test/dumper_test.rb +1 -1
- data/test/errors_test.rb +2 -2
- data/test/grammar_test.rb +15 -4
- data/test/helper.rb +1 -1
- data/test/toml_test.rb +32 -1
- data/toml-rb.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 404c0a6fb64ad42ecd9de6e9569e072c5d2d68e8
|
4
|
+
data.tar.gz: 7ccfabbb8c4014867a8bc3d309363e6d1bb10eb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afebe6d9de4b0eaaa913829c2fc35be18d2ac30339a6a158638612ed93f15196681624df0b164fd6baae3da5b7236fba1d6f46e79b7343bba1d7b6e51eb8db2f
|
7
|
+
data.tar.gz: 1c7b0380404eca6e933f45a28a7fa14c7bab52024879b4bf11c7c8f68bcb59f4c86edd35946575c960215e17d6af5fc85390228d3e409d64360680549574ef6d
|
data/Rakefile
CHANGED
data/init.rb
CHANGED
data/lib/toml/errors.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module TOML
|
2
|
+
# Parent class for all TOML errors
|
3
|
+
Error = Class.new(StandardError)
|
4
|
+
|
5
|
+
# Error related to parsing.
|
6
|
+
ParseError = Class.new(Error)
|
7
|
+
|
8
|
+
# Overwrite error
|
9
|
+
class ValueOverwriteError < Error
|
10
|
+
attr_accessor :key
|
11
|
+
|
12
|
+
def initialize(key)
|
13
|
+
self.key = key
|
14
|
+
super "Key #{key.inspect} is defined more than once"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -7,11 +7,11 @@ grammar TOML::Document
|
|
7
7
|
end
|
8
8
|
|
9
9
|
rule table_array
|
10
|
-
(space? '[[' (space? key space? "."?)+ ']]' space? comment?) <TOML::TableArrayParser>
|
10
|
+
(space? '[[' ((key "."?)+|'"'(space? key space? "."?)+'"') ']]' space? comment?) <TOML::TableArrayParser>
|
11
11
|
end
|
12
12
|
|
13
13
|
rule keygroup
|
14
|
-
(space? '[' (space? key space? "."?)+ ']' space? comment?) <TOML::KeygroupParser>
|
14
|
+
(space? '[' ((key "."?)+|'"'(space? key space? "."?)+'"') ']' space? comment?) <TOML::KeygroupParser>
|
15
15
|
end
|
16
16
|
|
17
17
|
rule keyvalue
|
@@ -22,11 +22,11 @@ grammar TOML::Primitive
|
|
22
22
|
end
|
23
23
|
|
24
24
|
rule multiline_string
|
25
|
-
('"""' line_break* text:~'"""' '"""' space) <TOML::MultilineString>
|
25
|
+
('"""' line_break* (text:~'"""'|'') '"""' space) <TOML::MultilineString>
|
26
26
|
end
|
27
27
|
|
28
28
|
rule multiline_literal
|
29
|
-
("'''" line_break* text:~"'''" "'''" space) <TOML::MultilineLiteral>
|
29
|
+
("'''" line_break* (text:~"'''"|'') "'''" space) <TOML::MultilineLiteral>
|
30
30
|
end
|
31
31
|
|
32
32
|
##
|
data/lib/toml/keygroup.rb
CHANGED
@@ -4,27 +4,32 @@ module TOML
|
|
4
4
|
@nested_keys = nested_keys
|
5
5
|
end
|
6
6
|
|
7
|
-
def navigate_keys(hash, symbolize_keys = false)
|
8
|
-
|
9
|
-
@nested_keys.
|
7
|
+
def navigate_keys(hash, visited_keys, symbolize_keys = false)
|
8
|
+
ensure_key_not_defined(visited_keys)
|
9
|
+
@nested_keys.each do |key|
|
10
10
|
key = symbolize_keys ? key.to_sym : key
|
11
|
-
# do not allow to define more than once just the last key
|
12
|
-
if i == last_index && hash.key?(key)
|
13
|
-
fail ValueOverwriteError.new(key)
|
14
|
-
end
|
15
11
|
hash[key] = {} unless hash.key?(key)
|
16
12
|
element = hash[key]
|
17
13
|
hash = element.is_a?(Array) ? element.last : element
|
18
14
|
# check that key has not been defined before as a scalar value
|
19
15
|
fail ValueOverwriteError.new(key) unless hash.is_a?(Hash)
|
20
16
|
end
|
21
|
-
|
22
17
|
hash
|
23
18
|
end
|
24
19
|
|
20
|
+
# Fail if the key was already defined with a ValueOverwriteError
|
21
|
+
def ensure_key_not_defined(visited_keys)
|
22
|
+
fail ValueOverwriteError.new(full_key) if visited_keys.include?(full_key)
|
23
|
+
visited_keys << full_key
|
24
|
+
end
|
25
|
+
|
25
26
|
def accept_visitor(parser)
|
26
27
|
parser.visit_keygroup self
|
27
28
|
end
|
29
|
+
|
30
|
+
def full_key
|
31
|
+
@nested_keys.join('.')
|
32
|
+
end
|
28
33
|
end
|
29
34
|
# Used in document.citrus
|
30
35
|
module KeygroupParser
|
data/lib/toml/keyvalue.rb
CHANGED
data/lib/toml/parser.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
module TOML
|
2
|
-
class ParseError < StandardError; end
|
3
|
-
|
4
2
|
class Parser
|
5
3
|
attr_reader :hash
|
6
4
|
|
7
5
|
def initialize(content, options = {})
|
8
6
|
@hash = {}
|
7
|
+
@visited_keys = Set.new
|
9
8
|
@current = @hash
|
10
9
|
@symbolize_keys = options[:symbolize_keys]
|
11
10
|
|
@@ -13,7 +12,7 @@ module TOML
|
|
13
12
|
parsed = TOML::Document.parse(content)
|
14
13
|
parsed.matches.map(&:value).compact.each { |m| m.accept_visitor(self) }
|
15
14
|
rescue Citrus::ParseError => e
|
16
|
-
raise ParseError.new(e.message)
|
15
|
+
raise TOML::ParseError.new(e.message)
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
@@ -24,7 +23,7 @@ module TOML
|
|
24
23
|
end
|
25
24
|
|
26
25
|
def visit_keygroup(keygroup)
|
27
|
-
@current = keygroup.navigate_keys @hash, @symbolize_keys
|
26
|
+
@current = keygroup.navigate_keys @hash, @visited_keys, @symbolize_keys
|
28
27
|
end
|
29
28
|
|
30
29
|
def visit_keyvalue(keyvalue)
|
data/lib/toml/string.rb
CHANGED
@@ -7,13 +7,29 @@ module TOML
|
|
7
7
|
aux[1...-1]
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
# Replace the unicode escaped characters with the corresponding character
|
11
|
+
# e.g. \u03B4 => ?
|
12
|
+
def self.decode_unicode(str)
|
13
|
+
str.gsub(/([^\\](?:\\\\)*\\u[\da-f]{4})/i) do |m|
|
14
|
+
m[0...-6] + [m[-4..-1].to_i(16)].pack('U')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Replace special characters such as line feed and tabs.
|
19
|
+
def self.decode_special_char(str)
|
11
20
|
str.gsub(/\\0/, "\0")
|
12
21
|
.gsub(/\\t/, "\t")
|
22
|
+
.gsub(/\\b/, "\b")
|
23
|
+
.gsub(/\\f/, "\f")
|
13
24
|
.gsub(/\\n/, "\n")
|
14
25
|
.gsub(/\\\"/, '"')
|
15
26
|
.gsub(/\\r/, "\r")
|
16
|
-
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.transform_escaped_chars(str)
|
30
|
+
str = decode_special_char(str)
|
31
|
+
str = decode_unicode(str)
|
32
|
+
str.gsub(/\\\\/, '\\').encode('utf-8')
|
17
33
|
end
|
18
34
|
end
|
19
35
|
|
@@ -25,6 +41,7 @@ module TOML
|
|
25
41
|
|
26
42
|
module MultilineString
|
27
43
|
def value
|
44
|
+
return '' if captures[:text].empty?
|
28
45
|
aux = captures[:text].first.value
|
29
46
|
|
30
47
|
# Remove spaces on multilined Singleline strings
|
@@ -36,6 +53,7 @@ module TOML
|
|
36
53
|
|
37
54
|
module MultilineLiteral
|
38
55
|
def value
|
56
|
+
return '' if captures[:text].empty?
|
39
57
|
aux = captures[:text].first.value
|
40
58
|
|
41
59
|
aux.gsub(/\\\r?\n[\n\t\r ]*/, '')
|
data/lib/toml/table_array.rb
CHANGED
data/test/dumper_test.rb
CHANGED
data/test/errors_test.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require_relative 'helper'
|
2
2
|
|
3
|
-
class ErrorsTest < Test
|
3
|
+
class ErrorsTest < Minitest::Test
|
4
4
|
def test_text_after_keygroup
|
5
5
|
str = "[error] if you didn't catch this, your parser is broken"
|
6
6
|
assert_raises(TOML::ParseError) { TOML.parse(str) }
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_text_after_string
|
10
|
-
str =
|
10
|
+
str = 'string = "Anything other than tabs, spaces and newline after a '
|
11
11
|
str += 'keygroup or key value pair has ended should produce an error '
|
12
12
|
str += 'unless it is a comment" like this'
|
13
13
|
|
data/test/grammar_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require_relative 'helper'
|
3
3
|
|
4
|
-
class GrammarTest < Test
|
4
|
+
class GrammarTest < Minitest::Test
|
5
5
|
def test_comment
|
6
6
|
match = TOML::Document.parse(' # A comment', root: :comment)
|
7
7
|
assert_equal(nil, match.value)
|
@@ -30,9 +30,13 @@ class GrammarTest < Test::Unit::TestCase
|
|
30
30
|
assert_equal(%w(owner.emancu),
|
31
31
|
match.value.instance_variable_get('@nested_keys'))
|
32
32
|
|
33
|
-
match = TOML::Document.parse('[
|
34
|
-
assert_equal(
|
33
|
+
match = TOML::Document.parse('["first key"."second key"]', root: :keygroup)
|
34
|
+
assert_equal(['first key', 'second key'],
|
35
35
|
match.value.instance_variable_get('@nested_keys'))
|
36
|
+
|
37
|
+
assert_raises Citrus::ParseError do
|
38
|
+
TOML::Document.parse('[ owner . emancu ]', root: :keygroup)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
def test_keyvalue
|
@@ -64,6 +68,13 @@ class GrammarTest < Test::Unit::TestCase
|
|
64
68
|
assert_equal "One Two", match.value
|
65
69
|
end
|
66
70
|
|
71
|
+
def test_empty_multiline_string
|
72
|
+
to_parse = '""""""'
|
73
|
+
|
74
|
+
match = TOML::Document.parse(to_parse, root: :multiline_string)
|
75
|
+
assert_equal '', match.value
|
76
|
+
end
|
77
|
+
|
67
78
|
def test_special_characters
|
68
79
|
match = TOML::Document.parse('"\0 \" \t \n \r"', root: :string)
|
69
80
|
assert_equal("\0 \" \t \n \r", match.value)
|
@@ -146,7 +157,7 @@ class GrammarTest < Test::Unit::TestCase
|
|
146
157
|
assert_equal([%w(hey TOML), [2, 4]], match.value)
|
147
158
|
|
148
159
|
match = TOML::Document.parse('[ { one = 1 }, { two = 2, three = 3} ]',
|
149
|
-
|
160
|
+
root: :inline_table_array)
|
150
161
|
assert_equal([{ 'one' => 1 }, { 'two' => 2, 'three' => 3 }], match.value)
|
151
162
|
end
|
152
163
|
|
data/test/helper.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require '
|
1
|
+
require 'minitest/autorun'
|
2
2
|
require_relative '../lib/toml'
|
data/test/toml_test.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require_relative 'helper'
|
2
2
|
require_relative 'toml_examples'
|
3
|
+
require 'json'
|
3
4
|
|
4
|
-
class TomlTest < Test
|
5
|
+
class TomlTest < Minitest::Test
|
5
6
|
def test_file_v_0_4_0
|
6
7
|
path = File.join(File.dirname(__FILE__), 'example-v0.4.0.toml')
|
7
8
|
parsed = TOML.load_file(path)
|
@@ -84,4 +85,34 @@ class TomlTest < Test::Unit::TestCase
|
|
84
85
|
parsed = TOML.parse("hello = 'world'\r\nline_break = true")
|
85
86
|
assert_equal({ 'hello' => 'world', 'line_break' => true }, parsed)
|
86
87
|
end
|
88
|
+
|
89
|
+
def compare_toml_files(folder, file = nil, &block)
|
90
|
+
file ||= '*'
|
91
|
+
Dir["test/examples/#{folder}/#{file}.json"].each do |json_file|
|
92
|
+
toml_file = File.join(File.dirname(json_file),
|
93
|
+
File.basename(json_file, '.json')) + '.toml'
|
94
|
+
begin
|
95
|
+
toml = TOML.load_file(toml_file)
|
96
|
+
rescue TOML::Error => e
|
97
|
+
assert false, "Error: #{e} in #{toml_file}"
|
98
|
+
end
|
99
|
+
json = JSON.parse(File.read(json_file))
|
100
|
+
block.call(json, toml, toml_file)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_valid_cases
|
105
|
+
compare_toml_files 'valid' do |json, toml, file|
|
106
|
+
assert_equal json, toml, "In file '#{file}'"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_invalid_cases
|
111
|
+
file = '*'
|
112
|
+
Dir["test/examples/invalid/#{file}.toml"].each do |toml_file|
|
113
|
+
assert_raises(TOML::Error, "For file #{toml_file}") do
|
114
|
+
TOML.load_file(toml_file)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
87
118
|
end
|
data/toml-rb.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toml-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emiliano Mancuso
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-06-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: citrus
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- init.rb
|
45
45
|
- lib/toml.rb
|
46
46
|
- lib/toml/dumper.rb
|
47
|
+
- lib/toml/errors.rb
|
47
48
|
- lib/toml/grammars/array.citrus
|
48
49
|
- lib/toml/grammars/document.citrus
|
49
50
|
- lib/toml/grammars/helper.citrus
|