toml-rb 1.1.2 → 2.0.0
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 +5 -5
- data/LICENSE +19 -0
- data/README.md +3 -3
- data/lib/toml-rb.rb +2 -1
- data/lib/toml-rb/array.rb +2 -8
- data/lib/toml-rb/datetime.rb +38 -0
- data/lib/toml-rb/dumper.rb +9 -1
- data/lib/toml-rb/grammars/array.citrus +16 -18
- data/lib/toml-rb/grammars/document.citrus +20 -8
- data/lib/toml-rb/grammars/primitive.citrus +80 -23
- data/lib/toml-rb/inline_table.rb +6 -52
- data/lib/toml-rb/keyvalue.rb +25 -17
- data/lib/toml-rb/parser.rb +6 -3
- data/lib/toml-rb/{keygroup.rb → table.rb} +15 -14
- data/lib/toml-rb/table_array.rb +17 -17
- metadata +12 -22
- data/Rakefile +0 -6
- data/test/dumper_test.rb +0 -94
- data/test/errors_test.rb +0 -88
- data/test/example-v0.4.0.toml +0 -244
- data/test/example.toml +0 -49
- data/test/grammar_test.rb +0 -239
- data/test/hard_example.toml +0 -46
- data/test/helper.rb +0 -2
- data/test/toml_examples.rb +0 -203
- data/test/toml_test.rb +0 -125
- data/toml-rb.gemspec +0 -23
data/lib/toml-rb/keyvalue.rb
CHANGED
@@ -1,31 +1,39 @@
|
|
1
|
+
require_relative "inline_table"
|
2
|
+
|
1
3
|
module TomlRB
|
2
4
|
class Keyvalue
|
3
|
-
attr_reader :value, :symbolize_keys
|
5
|
+
attr_reader :dotted_keys, :value, :symbolize_keys
|
4
6
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
+
def initialize(dotted_keys, value)
|
8
|
+
@dotted_keys = dotted_keys
|
7
9
|
@value = value
|
8
10
|
@symbolize_keys = false
|
9
11
|
end
|
10
12
|
|
11
|
-
def assign(hash, symbolize_keys = false)
|
13
|
+
def assign(hash, fully_defined_keys, symbolize_keys = false)
|
12
14
|
@symbolize_keys = symbolize_keys
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
dotted_keys_str = @dotted_keys.join(".")
|
16
|
+
keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys
|
17
|
+
update = keys.reverse.inject(visit_value @value) { |k1, k2| { k2 => k1 } }
|
18
|
+
|
19
|
+
if @value.is_a?(InlineTable)
|
20
|
+
fully_defined_keys << dotted_keys_str
|
21
|
+
hash.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) }
|
22
|
+
elsif fully_defined_keys.find{|k| update.dig(*k)}
|
23
|
+
hash.merge!(update) { |key, _, _| fail ValueOverwriteError.new(key) }
|
24
|
+
else
|
25
|
+
dotted_key_merge(hash, update)
|
22
26
|
end
|
23
|
-
|
24
|
-
result
|
25
27
|
end
|
26
28
|
|
27
|
-
def
|
28
|
-
|
29
|
+
def dotted_key_merge(hash, update)
|
30
|
+
hash.merge!(update) { |key, old, new|
|
31
|
+
if old.is_a?(Hash) && new.is_a?(Hash)
|
32
|
+
dotted_key_merge(old, new)
|
33
|
+
else
|
34
|
+
fail ValueOverwriteError.new(key)
|
35
|
+
end
|
36
|
+
}
|
29
37
|
end
|
30
38
|
|
31
39
|
def accept_visitor(parser)
|
data/lib/toml-rb/parser.rb
CHANGED
@@ -5,6 +5,7 @@ module TomlRB
|
|
5
5
|
def initialize(content, options = {})
|
6
6
|
@hash = {}
|
7
7
|
@visited_keys = []
|
8
|
+
@fully_defined_keys = []
|
8
9
|
@current = @hash
|
9
10
|
@symbolize_keys = options[:symbolize_keys]
|
10
11
|
|
@@ -19,18 +20,20 @@ module TomlRB
|
|
19
20
|
# Read about the Visitor pattern
|
20
21
|
# http://en.wikipedia.org/wiki/Visitor_pattern
|
21
22
|
def visit_table_array(table_array)
|
23
|
+
@fully_defined_keys = []
|
22
24
|
table_array_key = table_array.full_key
|
23
25
|
@visited_keys.reject! { |k| k.start_with? table_array_key }
|
24
26
|
|
25
27
|
@current = table_array.navigate_keys @hash, @symbolize_keys
|
26
28
|
end
|
27
29
|
|
28
|
-
def
|
29
|
-
@
|
30
|
+
def visit_table(table)
|
31
|
+
@fully_defined_keys = []
|
32
|
+
@current = table.navigate_keys @hash, @visited_keys, @symbolize_keys
|
30
33
|
end
|
31
34
|
|
32
35
|
def visit_keyvalue(keyvalue)
|
33
|
-
keyvalue.assign @current, @symbolize_keys
|
36
|
+
keyvalue.assign @current, @fully_defined_keys, @symbolize_keys
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
@@ -1,20 +1,21 @@
|
|
1
1
|
module TomlRB
|
2
|
-
class
|
3
|
-
def initialize(
|
4
|
-
@
|
2
|
+
class Table
|
3
|
+
def initialize(dotted_keys)
|
4
|
+
@dotted_keys = dotted_keys
|
5
5
|
end
|
6
6
|
|
7
7
|
def navigate_keys(hash, visited_keys, symbolize_keys = false)
|
8
8
|
ensure_key_not_defined(visited_keys)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
current = hash
|
10
|
+
keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys
|
11
|
+
keys.each do |key|
|
12
|
+
current[key] = {} unless current.key?(key)
|
13
|
+
element = current[key]
|
14
|
+
current = element.is_a?(Array) ? element.last : element
|
14
15
|
# check that key has not been defined before as a scalar value
|
15
|
-
fail ValueOverwriteError.new(key) unless
|
16
|
+
fail ValueOverwriteError.new(key) unless current.is_a?(Hash)
|
16
17
|
end
|
17
|
-
|
18
|
+
current
|
18
19
|
end
|
19
20
|
|
20
21
|
# Fail if the key was already defined with a ValueOverwriteError
|
@@ -24,18 +25,18 @@ module TomlRB
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def accept_visitor(parser)
|
27
|
-
parser.
|
28
|
+
parser.visit_table self
|
28
29
|
end
|
29
30
|
|
30
31
|
def full_key
|
31
|
-
@
|
32
|
+
@dotted_keys.join('.')
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
36
|
# Used in document.citrus
|
36
|
-
module
|
37
|
+
module TableParser
|
37
38
|
def value
|
38
|
-
TomlRB::
|
39
|
+
TomlRB::Table.new(captures[:stripped_key].map(&:value).first)
|
39
40
|
end
|
40
41
|
end
|
41
42
|
end
|
data/lib/toml-rb/table_array.rb
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
module TomlRB
|
2
2
|
class TableArray
|
3
|
-
def initialize(
|
4
|
-
@
|
3
|
+
def initialize(dotted_keys)
|
4
|
+
@dotted_keys = dotted_keys
|
5
5
|
end
|
6
6
|
|
7
7
|
def navigate_keys(hash, symbolize_keys = false)
|
8
|
-
|
9
|
-
|
8
|
+
current = hash
|
9
|
+
keys = symbolize_keys ? @dotted_keys.map(&:to_sym) : @dotted_keys
|
10
|
+
last_key = keys.pop
|
10
11
|
|
11
12
|
# Go over the parent keys
|
12
|
-
|
13
|
-
key =
|
14
|
-
hash[key] = {} unless hash[key]
|
13
|
+
keys.each do |key|
|
14
|
+
current[key] = {} unless current[key]
|
15
15
|
|
16
|
-
if
|
17
|
-
|
18
|
-
|
16
|
+
if current[key].is_a? Array
|
17
|
+
current[key] << {} if current[key].empty?
|
18
|
+
current = current[key].last
|
19
19
|
else
|
20
|
-
|
20
|
+
current = current[key]
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
# Define Table Array
|
25
|
-
if
|
25
|
+
if current[last_key].is_a? Hash
|
26
26
|
fail TomlRB::ParseError,
|
27
27
|
"#{last_key} was defined as hash but is now redefined as a table!"
|
28
28
|
end
|
29
|
-
|
30
|
-
|
29
|
+
current[last_key] = [] unless current[last_key]
|
30
|
+
current[last_key] << {}
|
31
31
|
|
32
|
-
|
32
|
+
current[last_key].last
|
33
33
|
end
|
34
34
|
|
35
35
|
def accept_visitor(parser)
|
@@ -37,14 +37,14 @@ module TomlRB
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def full_key
|
40
|
-
@
|
40
|
+
@dotted_keys.join('.')
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
# Used in document.citrus
|
45
45
|
module TableArrayParser
|
46
46
|
def value
|
47
|
-
TomlRB::TableArray.new(captures[:stripped_key].map(&:value))
|
47
|
+
TomlRB::TableArray.new(captures[:stripped_key].map(&:value).first)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
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:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emiliano Mancuso
|
@@ -9,26 +9,26 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-10-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: citrus
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
18
|
+
- - ">"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '3.0'
|
21
|
-
- - "
|
21
|
+
- - "~>"
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: '3.0'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - "
|
28
|
+
- - ">"
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '3.0'
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '3.0'
|
34
34
|
description: 'A Toml parser using Citrus parsing library. '
|
@@ -39,10 +39,11 @@ executables: []
|
|
39
39
|
extensions: []
|
40
40
|
extra_rdoc_files: []
|
41
41
|
files:
|
42
|
+
- LICENSE
|
42
43
|
- README.md
|
43
|
-
- Rakefile
|
44
44
|
- lib/toml-rb.rb
|
45
45
|
- lib/toml-rb/array.rb
|
46
|
+
- lib/toml-rb/datetime.rb
|
46
47
|
- lib/toml-rb/dumper.rb
|
47
48
|
- lib/toml-rb/errors.rb
|
48
49
|
- lib/toml-rb/grammars/array.citrus
|
@@ -50,22 +51,12 @@ files:
|
|
50
51
|
- lib/toml-rb/grammars/helper.citrus
|
51
52
|
- lib/toml-rb/grammars/primitive.citrus
|
52
53
|
- lib/toml-rb/inline_table.rb
|
53
|
-
- lib/toml-rb/keygroup.rb
|
54
54
|
- lib/toml-rb/keyvalue.rb
|
55
55
|
- lib/toml-rb/parser.rb
|
56
56
|
- lib/toml-rb/string.rb
|
57
|
+
- lib/toml-rb/table.rb
|
57
58
|
- lib/toml-rb/table_array.rb
|
58
|
-
|
59
|
-
- test/errors_test.rb
|
60
|
-
- test/example-v0.4.0.toml
|
61
|
-
- test/example.toml
|
62
|
-
- test/grammar_test.rb
|
63
|
-
- test/hard_example.toml
|
64
|
-
- test/helper.rb
|
65
|
-
- test/toml_examples.rb
|
66
|
-
- test/toml_test.rb
|
67
|
-
- toml-rb.gemspec
|
68
|
-
homepage: http://github.com/emancu/toml-rb
|
59
|
+
homepage: https://github.com/emancu/toml-rb
|
69
60
|
licenses:
|
70
61
|
- MIT
|
71
62
|
metadata: {}
|
@@ -77,15 +68,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
68
|
requirements:
|
78
69
|
- - ">="
|
79
70
|
- !ruby/object:Gem::Version
|
80
|
-
version: '
|
71
|
+
version: '2.3'
|
81
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
73
|
requirements:
|
83
74
|
- - ">="
|
84
75
|
- !ruby/object:Gem::Version
|
85
76
|
version: '0'
|
86
77
|
requirements: []
|
87
|
-
|
88
|
-
rubygems_version: 2.6.14.1
|
78
|
+
rubygems_version: 3.0.3
|
89
79
|
signing_key:
|
90
80
|
specification_version: 4
|
91
81
|
summary: Toml parser in ruby, for ruby.
|
data/Rakefile
DELETED
data/test/dumper_test.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require_relative 'helper'
|
2
|
-
|
3
|
-
class DumperTest < Minitest::Test
|
4
|
-
def test_dump_empty
|
5
|
-
dumped = TomlRB.dump({})
|
6
|
-
assert_equal('', dumped)
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_dump_types
|
10
|
-
dumped = TomlRB.dump(string: 'TomlRB "dump"')
|
11
|
-
assert_equal("string = \"TomlRB \\\"dump\\\"\"\n", dumped)
|
12
|
-
|
13
|
-
dumped = TomlRB.dump(float: -13.24)
|
14
|
-
assert_equal("float = -13.24\n", dumped)
|
15
|
-
|
16
|
-
dumped = TomlRB.dump(int: 1234)
|
17
|
-
assert_equal("int = 1234\n", dumped)
|
18
|
-
|
19
|
-
dumped = TomlRB.dump(true: true)
|
20
|
-
assert_equal("true = true\n", dumped)
|
21
|
-
|
22
|
-
dumped = TomlRB.dump(false: false)
|
23
|
-
assert_equal("false = false\n", dumped)
|
24
|
-
|
25
|
-
dumped = TomlRB.dump(array: [1, 2, 3])
|
26
|
-
assert_equal("array = [1, 2, 3]\n", dumped)
|
27
|
-
|
28
|
-
dumped = TomlRB.dump(array: [[1, 2], %w(weird one)])
|
29
|
-
assert_equal("array = [[1, 2], [\"weird\", \"one\"]]\n", dumped)
|
30
|
-
|
31
|
-
dumped = TomlRB.dump(datetime: Time.utc(1986, 8, 28, 15, 15))
|
32
|
-
assert_equal("datetime = 1986-08-28T15:15:00Z\n", dumped)
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_dump_nested_attributes
|
36
|
-
hash = { nested: { hash: { deep: true } } }
|
37
|
-
dumped = TomlRB.dump(hash)
|
38
|
-
assert_equal("[nested.hash]\ndeep = true\n", dumped)
|
39
|
-
|
40
|
-
hash[:nested].merge!(other: 12)
|
41
|
-
dumped = TomlRB.dump(hash)
|
42
|
-
assert_equal("[nested]\nother = 12\n[nested.hash]\ndeep = true\n", dumped)
|
43
|
-
|
44
|
-
hash[:nested].merge!(nest: { again: 'it never ends' })
|
45
|
-
dumped = TomlRB.dump(hash)
|
46
|
-
toml = <<-EOS.gsub(/^ {6}/, '')
|
47
|
-
[nested]
|
48
|
-
other = 12
|
49
|
-
[nested.hash]
|
50
|
-
deep = true
|
51
|
-
[nested.nest]
|
52
|
-
again = "it never ends"
|
53
|
-
EOS
|
54
|
-
|
55
|
-
assert_equal(toml, dumped)
|
56
|
-
|
57
|
-
hash = { non: { 'bare."keys"' => { "works" => true } } }
|
58
|
-
dumped = TomlRB.dump(hash)
|
59
|
-
assert_equal("[non.\"bare.\\\"keys\\\"\"]\nworks = true\n", dumped)
|
60
|
-
|
61
|
-
hash = { hola: [{ chau: 4 }, { chau: 3 }] }
|
62
|
-
dumped = TomlRB.dump(hash)
|
63
|
-
assert_equal("[[hola]]\nchau = 4\n[[hola]]\nchau = 3\n", dumped)
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_print_empty_tables
|
67
|
-
hash = { plugins: { cpu: { foo: "bar", baz: 1234 }, disk: {}, io: {} } }
|
68
|
-
dumped = TomlRB.dump(hash)
|
69
|
-
toml = <<-EOS.gsub(/^ {6}/, '')
|
70
|
-
[plugins.cpu]
|
71
|
-
baz = 1234
|
72
|
-
foo = "bar"
|
73
|
-
[plugins.disk]
|
74
|
-
[plugins.io]
|
75
|
-
EOS
|
76
|
-
|
77
|
-
assert_equal toml, dumped
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_dump_array_tables
|
81
|
-
hash = { fruit: [{ physical: { color: "red" } }, { physical: { color: "blue" } }] }
|
82
|
-
dumped = TomlRB.dump(hash)
|
83
|
-
toml = <<-EOS.gsub(/^ {6}/, '')
|
84
|
-
[[fruit]]
|
85
|
-
[fruit.physical]
|
86
|
-
color = "red"
|
87
|
-
[[fruit]]
|
88
|
-
[fruit.physical]
|
89
|
-
color = "blue"
|
90
|
-
EOS
|
91
|
-
|
92
|
-
assert_equal toml, dumped
|
93
|
-
end
|
94
|
-
end
|
data/test/errors_test.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require_relative 'helper'
|
2
|
-
|
3
|
-
class ErrorsTest < Minitest::Test
|
4
|
-
def test_text_after_keygroup
|
5
|
-
str = "[error] if you didn't catch this, your parser is broken"
|
6
|
-
assert_raises(TomlRB::ParseError) { TomlRB.parse(str) }
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_text_after_string
|
10
|
-
str = 'string = "Anything other than tabs, spaces and newline after a '
|
11
|
-
str += 'keygroup or key value pair has ended should produce an error '
|
12
|
-
str += 'unless it is a comment" like this'
|
13
|
-
|
14
|
-
assert_raises(TomlRB::ParseError) { TomlRB.parse(str) }
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_multiline_array_bad_string
|
18
|
-
str = <<-EOS
|
19
|
-
array = [
|
20
|
-
"This might most likely happen in multiline arrays",
|
21
|
-
Like here,
|
22
|
-
"or here,
|
23
|
-
and here"
|
24
|
-
] End of array comment, forgot the #
|
25
|
-
EOS
|
26
|
-
|
27
|
-
assert_raises(TomlRB::ParseError) { TomlRB.parse(str) }
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_multiline_array_string_not_ended
|
31
|
-
str = <<-EOS
|
32
|
-
array = [
|
33
|
-
"This might most likely happen in multiline arrays",
|
34
|
-
"or here,
|
35
|
-
and here"
|
36
|
-
] End of array comment, forgot the #
|
37
|
-
EOS
|
38
|
-
|
39
|
-
assert_raises(TomlRB::ParseError) { TomlRB.parse(str) }
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_text_after_multiline_array
|
43
|
-
str = <<-EOS
|
44
|
-
array = [
|
45
|
-
"This might most likely happen in multiline arrays",
|
46
|
-
"or here",
|
47
|
-
"and here"
|
48
|
-
] End of array comment, forgot the #
|
49
|
-
EOS
|
50
|
-
|
51
|
-
assert_raises(TomlRB::ParseError) { TomlRB.parse(str) }
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_text_after_number
|
55
|
-
str = 'number = 3.14 pi <--again forgot the #'
|
56
|
-
assert_raises(TomlRB::ParseError) { TomlRB.parse(str) }
|
57
|
-
end
|
58
|
-
|
59
|
-
def test_value_overwrite
|
60
|
-
str = "a = 1\na = 2"
|
61
|
-
e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) }
|
62
|
-
assert_equal "Key \"a\" is defined more than once", e.message
|
63
|
-
assert_equal "a", e.key
|
64
|
-
|
65
|
-
str = "a = false\na = true"
|
66
|
-
assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) }
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_table_overwrite
|
70
|
-
str = "[a]\nb=1\n[a]\nc=2"
|
71
|
-
e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) }
|
72
|
-
assert_equal "Key \"a\" is defined more than once", e.message
|
73
|
-
|
74
|
-
str = "[a]\nb=1\n[a]\nb=1"
|
75
|
-
e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) }
|
76
|
-
assert_equal "Key \"a\" is defined more than once", e.message
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_value_overwrite_with_table
|
80
|
-
str = "[a]\nb=1\n[a.b]\nc=2"
|
81
|
-
e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) }
|
82
|
-
assert_equal "Key \"b\" is defined more than once", e.message
|
83
|
-
|
84
|
-
str = "[a]\nb=1\n[a.b.c]\nd=3"
|
85
|
-
e = assert_raises(TomlRB::ValueOverwriteError) { TomlRB.parse(str) }
|
86
|
-
assert_equal "Key \"b\" is defined more than once", e.message
|
87
|
-
end
|
88
|
-
end
|