toml-rb 0.3.6 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|