nestedtext 0.6.0 → 1.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +30 -4
- data/lib/nestedtext/constants.rb +2 -0
- data/lib/nestedtext/core_ext.rb +6 -4
- data/lib/nestedtext/decode.rb +0 -5
- data/lib/nestedtext/dumper.rb +1 -0
- data/lib/nestedtext/encode_helpers.rb +3 -0
- data/lib/nestedtext/errors.rb +43 -35
- data/lib/nestedtext/parser.rb +9 -2
- data/lib/nestedtext/scanners.rb +3 -0
- data/lib/nestedtext/version.rb +1 -1
- metadata +2 -3
- data/lib/nestedtext/helpers.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74caf2136f95b24dc7b72d92e869c59992e7a573258d50c33762ade211f289fc
|
4
|
+
data.tar.gz: 9a185f16e4ecf87166fd90e47487a1bbff690713479049503b8b63594889c296
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49da0bd5404cc394f0ab0bf746da45fad947502bdb7c9a5017df44c5a7fff0bfc25a3b3baa3142574185fe8da727ddee388903f2cb0a3efbe683f952bdfd7a59
|
7
|
+
data.tar.gz: 66e5f06985d49b05702d6a569c1ac44f875726bd01ba7021b9e8ede0fb39e83aae9141e3c9e5e06c720e7dde207ac5b334c217473b0e36c390d3914c27eb5d83
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.0.0] - 2022-01-25
|
10
|
+
The library is now useful for clients!
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
- Hide all internals in the module from clients.
|
14
|
+
|
9
15
|
## [0.6.0] - 2022-01-24
|
10
16
|
### Fixed
|
11
17
|
- Move runtime dependencies from Gemfile to .gemspec.
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
# NestedText Ruby Library [](https://twitter.com/intent/tweet?text=
|
1
|
+
# NestedText Ruby Library [](https://twitter.com/intent/tweet?text=NestedText,%20the%20human%20friendly%20data%20format,%20has%20a%20now%20a%20ruby%20library%20for%20easy%20encoding%20and%20decoding&url=https://github.com/erikw/nestedtext-ruby&via=erik_westrup&hashtags=nestedtext,ruby,gem)
|
2
2
|
[](https://badge.fury.io/rb/nestedtext)
|
3
3
|
[](https://rubygems.org/gems/nestedtext)
|
4
4
|
[](https://nestedtext.org/en/v3.2/)
|
5
|
-
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml)
|
6
5
|
[](https://github.com/KenKundert/nestedtext_tests/tree/585e95a73d94ac1f48e71a154e2db0ab67cf30fa)
|
6
|
+
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml)
|
7
7
|
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/cd.yml)
|
8
8
|
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/codeql-analysis.yml)
|
9
9
|
[](https://codeclimate.com/github/erikw/nestedtext-ruby/maintainability)
|
@@ -37,6 +37,25 @@ TODO link to my test repo showin live usage. https://github.com/erikw/nestedtext
|
|
37
37
|
|
38
38
|
## Encoding (writing NT)
|
39
39
|
|
40
|
+
`#to_nt` method:
|
41
|
+
```irb
|
42
|
+
irb> require 'nestedtext'
|
43
|
+
irb> puts "a\nstring".to_nt
|
44
|
+
> a
|
45
|
+
> string
|
46
|
+
irb> puts ["i1", "i2", "i3"].to_nt
|
47
|
+
- i1
|
48
|
+
- i2
|
49
|
+
- i3
|
50
|
+
irb> puts({"k1" => "v1", "multiline\nkey" => "v2", "k3" => "multiline\nvalue"}.to_nt)
|
51
|
+
k1: v1
|
52
|
+
: multiline
|
53
|
+
: key
|
54
|
+
> v2
|
55
|
+
k3:
|
56
|
+
> multiline
|
57
|
+
> value
|
58
|
+
```
|
40
59
|
## Custom Classes Serialization
|
41
60
|
This library has support for serialization/deserialization of custom classes as well.
|
42
61
|
`strict: false` flag needed
|
@@ -72,9 +91,16 @@ See [encode_custom_classes_test.rb](test/nestedtext/encode_custom_classes_test.r
|
|
72
91
|
1. Install a supported ruby version (see .gemspec) with a ruby version manager e.g. [rbenv](https://github.com/rbenv/rbenv), [asdf](http://asdf-vm.com/) or [RVM](https://rvm.io/rvm/install)
|
73
92
|
1. run `$ script/setup` to install dependencies
|
74
93
|
1. run `$ script/test` to run the tests
|
75
|
-
1.
|
94
|
+
1. You can also run `$ script/console` for an interactive prompt that will allow you to experiment.
|
95
|
+
1. For local testing, install the gem on local machine with: `$ bundle exec rake install`.
|
96
|
+
* or manuall with `$ gem build *.gemscpec && gem install *.gem`
|
76
97
|
|
77
|
-
|
98
|
+
Make sure that only intended constants and methods are exposed from the module `NestedText`. Check with
|
99
|
+
```
|
100
|
+
irb> require 'nestedtext'
|
101
|
+
irb> NestedText.constants
|
102
|
+
irb> NestedText.methods(false)
|
103
|
+
```
|
78
104
|
|
79
105
|
## Releasing
|
80
106
|
Instructions for releasing on rubygems.org below. Optionally make a GitHub [release](https://github.com/erikw/nestedtext-ruby/releases) after this for the pushed git tag.
|
data/lib/nestedtext/constants.rb
CHANGED
data/lib/nestedtext/core_ext.rb
CHANGED
@@ -5,12 +5,14 @@ require "nestedtext/encode_helpers"
|
|
5
5
|
# Or both: add encoding/decoding of more native classes, and allow decoding + applying a schema with 3rd party.
|
6
6
|
# Or encourage using Marshal from core?
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
class
|
8
|
+
NT_MIXIN = NestedText.const_get(:NTEncodeStrictMixing)
|
9
|
+
|
10
|
+
class String include NT_MIXIN end
|
11
|
+
class Array include NT_MIXIN end
|
12
|
+
class Hash include NT_MIXIN end
|
11
13
|
|
12
14
|
class NilClass
|
13
|
-
include
|
15
|
+
include NT_MIXIN
|
14
16
|
|
15
17
|
def self.nt_create(_data) = nil
|
16
18
|
|
data/lib/nestedtext/decode.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "nestedtext/parser"
|
4
4
|
require "nestedtext/errors"
|
5
|
-
require "nestedtext/helpers"
|
6
5
|
|
7
6
|
require "logger"
|
8
7
|
require "stringio"
|
@@ -15,16 +14,12 @@ module NestedText
|
|
15
14
|
|
16
15
|
raise Errors::WrongInputTypeError.new([String], ntstring) unless ntstring.nil? || ntstring.is_a?(String)
|
17
16
|
|
18
|
-
assert_valid_top_level_type top_class
|
19
|
-
|
20
17
|
Parser.new(StringIO.new(ntstring), top_class, strict: strict).parse
|
21
18
|
end
|
22
19
|
|
23
20
|
def self.load_file(filename, top_class: Object, strict: true)
|
24
21
|
raise Errors::WrongInputTypeError.new([String], filename) unless !filename.nil? && filename.is_a?(String)
|
25
22
|
|
26
|
-
assert_valid_top_level_type top_class
|
27
|
-
|
28
23
|
# Open explicitly in text mode to detect \r as line ending.
|
29
24
|
File.open(filename, mode = "rt") do |file|
|
30
25
|
Parser.new(file, top_class, strict: strict).parse
|
data/lib/nestedtext/dumper.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require "nestedtext/dumper"
|
2
2
|
|
3
|
+
# TODO: s/Mixing/Mixin/g
|
3
4
|
module NestedText
|
4
5
|
module NTEncodeStrictMixing
|
5
6
|
def to_nt(indentation: 4, strict: true)
|
6
7
|
Dumper.new(EncodeOptions.new(indentation, strict)).dump self
|
7
8
|
end
|
8
9
|
end
|
10
|
+
private_constant :NTEncodeStrictMixing
|
9
11
|
|
10
12
|
module NTEncodeMixing
|
11
13
|
def to_nt(indentation: 4)
|
@@ -21,4 +23,5 @@ module NestedText
|
|
21
23
|
@strict = strict
|
22
24
|
end
|
23
25
|
end
|
26
|
+
private_constant :EncodeOptions
|
24
27
|
end
|
data/lib/nestedtext/errors.rb
CHANGED
@@ -6,12 +6,19 @@ require "word_wrap/core_ext"
|
|
6
6
|
require "nestedtext/constants"
|
7
7
|
|
8
8
|
module NestedText
|
9
|
-
# Top level
|
10
|
-
|
9
|
+
# Top level error for clients to rescue on.
|
10
|
+
# TODO hide #new so that client's cant create instance of it. Unit test this. https://ruby-doc.org/core-3.1.0/Module.html#private_class_method-method
|
11
|
+
class Error < StandardError
|
12
|
+
private_class_method :new
|
13
|
+
end
|
11
14
|
|
12
15
|
module Errors
|
16
|
+
class InternalError < Error
|
17
|
+
public_class_method :new # Prevent clients from instansiating.
|
18
|
+
end
|
19
|
+
|
13
20
|
# TODO: rename all Subclasses to ParseXError, just like for Dump
|
14
|
-
class ParseError <
|
21
|
+
class ParseError < InternalError
|
15
22
|
attr_reader :lineno, :colno, :message_raw
|
16
23
|
|
17
24
|
def initialize(line, colno, message)
|
@@ -177,25 +184,7 @@ module NestedText
|
|
177
184
|
end
|
178
185
|
end
|
179
186
|
|
180
|
-
class
|
181
|
-
def initialize(type_class)
|
182
|
-
super("The given top level type #{type_class&.name} is unsupported. Chose between #{TOP_LEVEL_TYPES.join(", ")}.")
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
class WrongInputTypeError < Error
|
187
|
-
def initialize(class_exps, class_act)
|
188
|
-
super("The given input type #{class_act.class.name} is unsupported. Expected to be of types #{class_exps.map(&:name).join(", ")}")
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
class TopLevelTypeMismatchParsedType < Error
|
193
|
-
def initialize(class_exp, class_act)
|
194
|
-
super("The requested top level class #{class_exp.name} is not the same as the actual parsed top level class #{class_act}.")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class AssertionError < Error; end
|
187
|
+
class AssertionError < InternalError; end
|
199
188
|
|
200
189
|
class LineScannerIsEmpty < AssertionError
|
201
190
|
def initialize
|
@@ -209,19 +198,7 @@ module NestedText
|
|
209
198
|
end
|
210
199
|
end
|
211
200
|
|
212
|
-
class
|
213
|
-
def initialize(io)
|
214
|
-
super("When giving the io argument, it must be of type IO (respond to #write, #fsync). Given: #{io.class.name}")
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
class DumpFileBadPath < Error
|
219
|
-
def initialize(path)
|
220
|
-
super("Must supply a string to a file path that can be written to. Given: #{path}")
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
class DumpError < Error
|
201
|
+
class DumpError < InternalError
|
225
202
|
attr_reader :culprit
|
226
203
|
|
227
204
|
def initialize(culprit, message)
|
@@ -258,5 +235,36 @@ module NestedText
|
|
258
235
|
|
259
236
|
raise LineTagNotDetected, line
|
260
237
|
end
|
238
|
+
|
239
|
+
class UnsupportedTopLevelTypeError < InternalError
|
240
|
+
def initialize(type_class)
|
241
|
+
super("The given top level type #{type_class&.name} is unsupported. Chose between #{TOP_LEVEL_TYPES.join(", ")}.")
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
class WrongInputTypeError < InternalError
|
246
|
+
def initialize(class_exps, class_act)
|
247
|
+
super("The given input type #{class_act.class.name} is unsupported. Expected to be of types #{class_exps.map(&:name).join(", ")}")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class TopLevelTypeMismatchParsedType < InternalError
|
252
|
+
def initialize(class_exp, class_act)
|
253
|
+
super("The requested top level class #{class_exp.name} is not the same as the actual parsed top level class #{class_act}.")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
class DumpBadIO < InternalError
|
258
|
+
def initialize(io)
|
259
|
+
super("When giving the io argument, it must be of type IO (respond to #write, #fsync). Given: #{io.class.name}")
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
class DumpFileBadPath < InternalError
|
264
|
+
def initialize(path)
|
265
|
+
super("Must supply a string to a file path that can be written to. Given: #{path}")
|
266
|
+
end
|
267
|
+
end
|
261
268
|
end
|
269
|
+
private_constant :Errors
|
262
270
|
end
|
data/lib/nestedtext/parser.rb
CHANGED
@@ -4,14 +4,20 @@ require "stringio"
|
|
4
4
|
|
5
5
|
require "nestedtext/errors"
|
6
6
|
require "nestedtext/scanners"
|
7
|
-
require "nestedtext/
|
7
|
+
require "nestedtext/constants"
|
8
8
|
|
9
9
|
module NestedText
|
10
10
|
class Parser
|
11
|
+
def self.assert_valid_top_level_type(top_class)
|
12
|
+
unless !top_class.nil? && top_class.is_a?(Class) && TOP_LEVEL_TYPES.map(&:object_id).include?(top_class.object_id)
|
13
|
+
raise Errors::UnsupportedTopLevelTypeError, top_class
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
11
17
|
# TODO: document that caller is responsible for closing IO after done with Parser.
|
12
18
|
def initialize(io, top_class, strict: true)
|
13
19
|
assert_valid_input_type io
|
14
|
-
|
20
|
+
Parser.assert_valid_top_level_type(top_class)
|
15
21
|
@top_class = top_class
|
16
22
|
@strict = strict
|
17
23
|
@line_scanner = LineScanner.new(io)
|
@@ -284,4 +290,5 @@ module NestedText
|
|
284
290
|
result
|
285
291
|
end
|
286
292
|
end
|
293
|
+
private_constant :Parser
|
287
294
|
end
|
data/lib/nestedtext/scanners.rb
CHANGED
@@ -40,6 +40,7 @@ module NestedText
|
|
40
40
|
@next_line = line
|
41
41
|
end
|
42
42
|
end
|
43
|
+
private_constant :LineScanner
|
43
44
|
|
44
45
|
class InlineScanner
|
45
46
|
attr_reader :line, :pos
|
@@ -68,6 +69,7 @@ module NestedText
|
|
68
69
|
empty? ? nil : @line.content[@pos]
|
69
70
|
end
|
70
71
|
end
|
72
|
+
private_constant :InlineScanner
|
71
73
|
|
72
74
|
class Line
|
73
75
|
# Reference: https://nestedtext.org/en/latest/file_format.html
|
@@ -158,4 +160,5 @@ module NestedText
|
|
158
160
|
end
|
159
161
|
end
|
160
162
|
end
|
163
|
+
private_constant :Line
|
161
164
|
end
|
data/lib/nestedtext/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nestedtext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Westrup
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: warning
|
@@ -68,7 +68,6 @@ files:
|
|
68
68
|
- lib/nestedtext/encode.rb
|
69
69
|
- lib/nestedtext/encode_helpers.rb
|
70
70
|
- lib/nestedtext/errors.rb
|
71
|
-
- lib/nestedtext/helpers.rb
|
72
71
|
- lib/nestedtext/parser.rb
|
73
72
|
- lib/nestedtext/scanners.rb
|
74
73
|
- lib/nestedtext/version.rb
|
data/lib/nestedtext/helpers.rb
DELETED