nestedtext 4.0.0 → 4.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +68 -6
- data/lib/nestedtext/errors_internal.rb +14 -12
- data/lib/nestedtext/version.rb +1 -1
- data/lib/nestedtext.rb +5 -2
- data/nestedtext.gemspec +18 -16
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56edadbc6c19a780acc64f2dc5e7b433a7a5086b9c2ff5d19837d18fa84ef1cb
|
4
|
+
data.tar.gz: 0b65feaf1d2cd866c1700c19bf2329c4c0a01db97b48c7c3b18dd91ae1620969
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa67ebde8e33b4e254f1ca484046113971141bb2fcd10e7b64aeb03cd4dab0912acfc465c521bf9a5647483536c478cc754c0602f79bf9a156c870c9e7d2974e
|
7
|
+
data.tar.gz: 9527268ebfae6a0646ce7f22f9af6f30bca4a70e8e65a233e94fd870054ebae374cc2a1aa58df4572d3128298ae8433fc8218633dcc2410665e8fd9ab895ff25
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [4.2.2] - 2022-02-12
|
10
|
+
### Fixed
|
11
|
+
- Better module documentation fix.
|
12
|
+
|
13
|
+
## [4.2.1] - 2022-02-12
|
14
|
+
### Fixed
|
15
|
+
- Better module documentation.
|
16
|
+
|
17
|
+
## [4.2.0] - 2022-02-08
|
18
|
+
### Fixed
|
19
|
+
- Proper Unicode character name lookup.
|
20
|
+
|
21
|
+
## [4.1.1] - 2022-01-28
|
22
|
+
### Fixed
|
23
|
+
- Don't trigger CI when CD will run all tests anyways.
|
24
|
+
|
25
|
+
## [4.1.0] - 2022-01-28
|
26
|
+
### Changed
|
27
|
+
- cd.yml now runs full tests before releasing new version, by using reusable workflows.
|
28
|
+
|
9
29
|
## [4.0.0] - 2022-01-28
|
10
30
|
### Changed
|
11
31
|
- **Breaking change**: Renamed `NTEncodeMixin` to `ToNTMixin`.
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[![Gem Downloads](https://ruby-gem-downloads-badge.herokuapp.com/nestedtext?color=brightgreen&type=total&label=gem%20downloads)](https://rubygems.org/gems/nestedtext)
|
4
4
|
[![Documentation](https://img.shields.io/badge/docs-API-informational?logo=readthedocs&logoColor=violet)](https://www.rubydoc.info/gems/nestedtext/NestedText)
|
5
5
|
[![Data Format Version Supported](https://img.shields.io/badge/%F0%9F%84%BD%F0%9F%85%83%20Version%20Supported-3.2.1-blueviolet)](https://nestedtext.org/en/v3.2/)
|
6
|
-
[![Official Tests](https://img.shields.io/badge/Official%20Tests-Passing-success?logo=cachet)](https://github.com/KenKundert/nestedtext_tests/
|
6
|
+
[![Official Tests](https://img.shields.io/badge/Official%20Tests-Passing-success?logo=cachet)](https://github.com/KenKundert/nestedtext_tests/)
|
7
7
|
[![GitHub Actions: Continuous Integration](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml)
|
8
8
|
[![GitHub Actions: Continuous Deployment](https://github.com/erikw/nestedtext-ruby/actions/workflows/cd.yml/badge.svg)](https://github.com/erikw/nestedtext-ruby/actions/workflows/cd.yml)
|
9
9
|
[![GitHub Actions: CodeQL Analysis](https://github.com/erikw/nestedtext-ruby/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/erikw/nestedtext-ruby/actions/workflows/codeql-analysis.yml)
|
@@ -23,6 +23,8 @@ Provided is support for decoding a NestedText file or string to Ruby data struct
|
|
23
23
|
|
24
24
|
This library is inspired Ruby stdlib modules `JSON` and `YAML` as well as the Python [reference implementation](https://github.com/KenKundert/nestedtext) of NestedText. Parsing is done with a LL(1) recursive descent parser and dumping with a recursive DFS traversal of the object references.
|
25
25
|
|
26
|
+
To make this library practically useful, you should pair it with a [schema validator](#schema).
|
27
|
+
|
26
28
|
# What is NestedText?
|
27
29
|
Citing from the official [introduction](https://nestedtext.org/en/latest/index.html) page:
|
28
30
|
> NestedText is a file format for holding structured data to be entered, edited, or viewed by people. It organizes the data into a nested collection of dictionaries, lists, and strings without the need for quoting or escaping. A unique feature of this file format is that it only supports one scalar type: strings. While the decision to eschew integer, real, date, etc. types may seem counter intuitive, it leads to simpler data files and applications that are more robust.
|
@@ -72,14 +74,14 @@ obj1 = NestedText::load(ntstr)
|
|
72
74
|
obj2 = NestedText::load_file("path/to/data.nt")
|
73
75
|
```
|
74
76
|
|
75
|
-
The type of the returned object depends on the top level type in the NestedText data and will be of corresponding native Ruby type. In the example above, `obj1` will be an `Array` and obj2 will be `Hash` if `data.nt` looks like e.g.
|
77
|
+
The type of the returned object depends on the top level type in the NestedText data and will be of corresponding native Ruby type. In the example above, `obj1` will be an `Array` and `obj2` will be `Hash` if `data.nt` looks like e.g.
|
76
78
|
|
77
79
|
```
|
78
80
|
key1: value1
|
79
81
|
key2: value2
|
80
82
|
```
|
81
83
|
|
82
|
-
Thus you must know what you're parsing, or test what you decoded.
|
84
|
+
Thus you must know what you're parsing, or test what you decoded after.
|
83
85
|
|
84
86
|
### Explicit Top Level Type
|
85
87
|
If you already know what you expect to have, you can guarantee that this is what you will get by telling either function what the expected top type is. If not, an error will be raised.
|
@@ -144,7 +146,7 @@ Ruby | [NestedText](https://nestedtext.org/en/latest/basic_syntax.html)
|
|
144
146
|
|
145
147
|
|
146
148
|
### Strict Mode
|
147
|
-
The strict mode determines how classes other than the basic types `String`, `Array` and `Hash` are handled during encoding and decoding. By **default** strict mode is
|
149
|
+
The strict mode determines how classes other than the basic types `String`, `Array` and `Hash` are handled during encoding and decoding. By **default** strict mode is **false**.
|
148
150
|
|
149
151
|
With `strict: true`
|
150
152
|
Ruby | NestedText | Comment
|
@@ -159,7 +161,7 @@ Ruby | NestedText | Comment
|
|
159
161
|
---|---|---
|
160
162
|
`nil` | *Custom Class Encoding* | (1.)
|
161
163
|
`Symbol` | `String` |
|
162
|
-
Custom Class | *Custom Class Encoding* | If the [Custom Class](#custom-classes-serialization) implements `#encode_nt_with`
|
164
|
+
Custom Class | *Custom Class Encoding* | If the [Custom Class](#custom-classes-serialization) implements `#encode_nt_with`
|
163
165
|
Other Class | String | `#to_s` will be called if there is no `#encode_nt_with`
|
164
166
|
|
165
167
|
|
@@ -172,7 +174,7 @@ Other Class | String | `#to_s` will be called if there is no `#encode_nt_with`
|
|
172
174
|
## Custom Classes Serialization
|
173
175
|
This library has support for serialization/deserialization of custom classes as well. This is done by letting the objects tell NestedText what data should be used to represent the object instance with the `#encode_nt_with` method (inspired by `YAML`'s `#encode_with` method). All objects being recursively referenced from a root object being serialized must either implement this method or be one of the core supported NestedText data types from the table above.
|
174
176
|
|
175
|
-
A class implementing `#encode_nt_with` is referred to as `Custom Class` in this document.
|
177
|
+
A class implementing `#encode_nt_with` is referred to as a `Custom Class` in this document.
|
176
178
|
|
177
179
|
```ruby
|
178
180
|
class Apple
|
@@ -245,6 +247,66 @@ Apple.new("granny smith", 12).to_nt
|
|
245
247
|
|
246
248
|
See [encode_custom_classes_test.rb](test/nestedtext/encode_custom_classes_test.rb) for more real working examples.
|
247
249
|
|
250
|
+
# Schema
|
251
|
+
The point of NestedText is to not get in to business of supporting ambiguous types. That's why all values are simple strings. Having only simple strings is not useful in practice though. This is why NestedText is intended to be paired with a [Schema Validator](https://nestedtext.org/en/latest/schemas.html)!
|
252
|
+
|
253
|
+
A schema validator can:
|
254
|
+
* assert that the parsed values are of the expected types
|
255
|
+
* automatically convert them to Ruby class instances like Integer, Float, etc.
|
256
|
+
|
257
|
+
The reference implementation in Python [lists](https://nestedtext.org/en/latest/examples.html) a few examples of Python validators. Here below is an example of how this Ruby implementation of NestedText can be paired it with [RSchema](https://github.com/tomdalling/rschema).
|
258
|
+
|
259
|
+
## Example with RSchema
|
260
|
+
The full and working example can be found at [erikw/nestedtext-ruby-test](https://github.com/erikw/nestedtext-ruby-test/blob/main/parse_validate.rb).
|
261
|
+
|
262
|
+
Let's say that you have a program that should connect to a few servers. The list of servers should be stored in a configuration file. With NestedText, a `conf.nt` file could look like:
|
263
|
+
```yaml
|
264
|
+
-
|
265
|
+
name: global-service
|
266
|
+
ip: 192.167.1.1
|
267
|
+
port: 8080
|
268
|
+
-
|
269
|
+
name: aux-service
|
270
|
+
ip: 17.245.14.2
|
271
|
+
port: 67
|
272
|
+
# Unstable server, don't use this
|
273
|
+
stable: false
|
274
|
+
```
|
275
|
+
|
276
|
+
After parsing this file with this NestedText library, the values for all keys will be string. But to make practical use of this, we would of course like the values for the `port` keys to be `Integer`, and `stable` should have a value of either `true` or `false`. RSchema can do this conversion for us!
|
277
|
+
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
# Define schema for our list of servers
|
281
|
+
schema = RSchema.define do
|
282
|
+
array(
|
283
|
+
hash(
|
284
|
+
'name' => _String,
|
285
|
+
'ip' => _String,
|
286
|
+
'port' => _Integer,
|
287
|
+
optional('stable') => boolean
|
288
|
+
)
|
289
|
+
)
|
290
|
+
end
|
291
|
+
|
292
|
+
# The coercer will automatially convert types
|
293
|
+
coercer = RSchema::CoercionWrapper::RACK_PARAMS.wrap(schema)
|
294
|
+
|
295
|
+
# Parse config file with NestedText
|
296
|
+
data = NestedText.load_file('conf.nt')
|
297
|
+
|
298
|
+
# Validate
|
299
|
+
result = coercer.validate(data)
|
300
|
+
raise result.error.to_s unless result.valid?
|
301
|
+
|
302
|
+
# Now we have validated data of the right type specified in the schema!
|
303
|
+
servers = result.value
|
304
|
+
|
305
|
+
# Let's use the values for something in our app
|
306
|
+
stable_servers = servers.select { |server| server['stable'] }
|
307
|
+
# Not a meaningful sum - just demonstrating that 'port' values are integers and not strings anymore!
|
308
|
+
port_sum = servers.map { |server| server['port'] }.sum
|
309
|
+
```
|
248
310
|
|
249
311
|
# Installation
|
250
312
|
1. Add this gem to your ruby project's Gemfile
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'word_wrap'
|
4
|
-
require 'word_wrap/core_ext'
|
3
|
+
# require 'word_wrap'
|
4
|
+
# require 'word_wrap/core_ext'
|
5
|
+
require 'unicode_utils'
|
5
6
|
|
6
7
|
require 'nestedtext/constants'
|
7
8
|
require 'nestedtext/error'
|
@@ -140,9 +141,10 @@ module NestedText
|
|
140
141
|
else
|
141
142
|
'invalid indentation.'
|
142
143
|
end
|
143
|
-
# Need to wrap like official tests. #wrap always add an extra \n we need to chop off.
|
144
|
-
|
145
|
-
|
144
|
+
# Official-tests kludge; Need to wrap like official tests. #wrap always add an extra \n we need to chop off.
|
145
|
+
# Seems not be needed anymore
|
146
|
+
# message_wrapped = message.wrap(70).chop
|
147
|
+
super(line, ind_exp, message)
|
146
148
|
end
|
147
149
|
end
|
148
150
|
|
@@ -162,14 +164,14 @@ module NestedText
|
|
162
164
|
|
163
165
|
class ParseInvalidIndentationCharError < ParseError
|
164
166
|
def initialize(line)
|
165
|
-
|
167
|
+
char = line.content[0]
|
168
|
+
# Official-tests kludge; Translate rubys \u00 to python's unicodedata.name \x format.
|
169
|
+
printable_char = char.dump.gsub(/"/, '').gsub(/\\u0*/, '\x').downcase
|
166
170
|
|
167
|
-
# Looking for non-breaking space is just to be compatible with official tests.
|
168
171
|
explanation = ''
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
172
|
+
# Official-tests kludge; ASCII chars have printable names too,
|
173
|
+
# but they are not used in reference implementation.
|
174
|
+
explanation = " (#{UnicodeUtils.char_name(char)})" unless char.ord < 128
|
173
175
|
|
174
176
|
message = "invalid character in indentation: '#{printable_char}'#{explanation}."
|
175
177
|
super(line, line.indentation, message)
|
@@ -225,7 +227,7 @@ module NestedText
|
|
225
227
|
|
226
228
|
class DumpUnsupportedTypeError < DumpError
|
227
229
|
def initialize(obj, culprit)
|
228
|
-
#
|
230
|
+
# Official-tests kludge; translate to Python names
|
229
231
|
class_name = obj.is_a?(Integer) ? 'int' : obj.class.name
|
230
232
|
super(culprit, "unsupported type (#{class_name}).")
|
231
233
|
end
|
data/lib/nestedtext/version.rb
CHANGED
data/lib/nestedtext.rb
CHANGED
@@ -7,9 +7,12 @@ require_relative 'nestedtext/encode_helpers'
|
|
7
7
|
require_relative 'nestedtext/error'
|
8
8
|
require_relative 'nestedtext/version'
|
9
9
|
|
10
|
-
##
|
11
10
|
# # NestedText
|
12
|
-
#
|
11
|
+
# A ruby library for the human friendly data format NestedText (https://nestedtext.org/).
|
12
|
+
#
|
13
|
+
# Provided is support for decoding a NestedText file or string to Ruby data structures,
|
14
|
+
# as well as encoding Ruby objects to a NestedText file or string. Furthermore there is
|
15
|
+
# support for serialization and deserialization of custom classes.
|
13
16
|
#
|
14
17
|
# See {file:README.md} for documentation on Types, Strict Mode and Custom Classes.
|
15
18
|
module NestedText
|
data/nestedtext.gemspec
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'lib/nestedtext/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
6
|
+
spec.name = 'nestedtext'
|
7
7
|
spec.version = NestedText::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
8
|
+
spec.authors = ['Erik Westrup']
|
9
|
+
spec.email = ['erik.westrup@gmail.com']
|
10
10
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
15
|
-
spec.required_ruby_version = [
|
11
|
+
spec.summary = 'A ruby library for the human friendly data format NestedText (https://nestedtext.org/)'
|
12
|
+
spec.description = 'A ruby library for the human friendly data format NestedText (https://nestedtext.org/). There is support for decoding a NestedText file or string to Ruby data structures, as well as encoding Ruby objects to a NestedText file or string. Furthermore there is support for serialization and deserialization of custom classes. Support for v3.2.1 of the data format will all official tests passing.'
|
13
|
+
spec.homepage = 'https://github.com/erikw/nestedtext-ruby/'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.required_ruby_version = ['>= 3.0', '< 4']
|
16
16
|
|
17
|
-
spec.metadata[
|
18
|
-
spec.metadata[
|
19
|
-
spec.metadata[
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/erikw/nestedtext-ruby/'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://github.com/erikw/nestedtext-ruby/blob/main/CHANGELOG.md'
|
20
20
|
|
21
21
|
# For push to GitHub packages to work.
|
22
22
|
# Reference: https://github.community/t/unable-to-push-rubygem-to-package-registry-the-expected-resource-was-not-found/14596/7
|
23
23
|
spec.metadata = {
|
24
|
-
|
24
|
+
'github_repo' => 'git@github.com:erikw/nestedtext-ruby.git',
|
25
|
+
'rubygems_mfa_required' => 'true'
|
25
26
|
}
|
26
27
|
|
27
28
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
@@ -29,8 +30,9 @@ Gem::Specification.new do |spec|
|
|
29
30
|
f.match(%r{\A(?:lib/|CHANGELOG.md|CONTRIBUTING.md|LICENSE.txt|README.md|SECURITY.md|nestedtext.gemspec)})
|
30
31
|
end
|
31
32
|
end
|
32
|
-
spec.require_paths = [
|
33
|
+
spec.require_paths = ['lib']
|
33
34
|
|
34
|
-
spec.add_runtime_dependency
|
35
|
-
spec.add_runtime_dependency
|
35
|
+
spec.add_runtime_dependency 'unicode_utils', '~> 1.4'
|
36
|
+
spec.add_runtime_dependency 'warning', '~> 1.2'
|
37
|
+
spec.add_runtime_dependency 'word_wrap', '~> 1.0'
|
36
38
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nestedtext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.2
|
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-
|
11
|
+
date: 2022-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: unicode_utils
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.4'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: warning
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,6 +88,7 @@ licenses:
|
|
74
88
|
- MIT
|
75
89
|
metadata:
|
76
90
|
github_repo: git@github.com:erikw/nestedtext-ruby.git
|
91
|
+
rubygems_mfa_required: 'true'
|
77
92
|
post_install_message:
|
78
93
|
rdoc_options: []
|
79
94
|
require_paths:
|