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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 195cf273687c9cf4af35eaea661eef6086bdb8b1f47578092e7473a4cb56a418
4
- data.tar.gz: 32ca43c2433eea7065cd56e2809c85accd1165a3bf734e5ba0525fe3a256f56a
3
+ metadata.gz: 56edadbc6c19a780acc64f2dc5e7b433a7a5086b9c2ff5d19837d18fa84ef1cb
4
+ data.tar.gz: 0b65feaf1d2cd866c1700c19bf2329c4c0a01db97b48c7c3b18dd91ae1620969
5
5
  SHA512:
6
- metadata.gz: 8869b326141ccf9e56653bade9795f5a110f45d628df8eb1c372763a7cf5bfe7cb8a1077ff0fb36e5b0ec466f5f9f286fe877e1aaf1a4af3271c4ce5f8f718ed
7
- data.tar.gz: ac63098b99b0d5d4f2060ecae53d8f325ca64af240e7250e07f3757088d7aee9ef81f495f8b4969b7a139f373b2c77d8c0711d947421ef41075f6671b2d9c453
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/tree/585e95a73d94ac1f48e71a154e2db0ab67cf30fa)
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 turned **off**.
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` (2.)
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
- message_wrapped = message.wrap(70).chop
145
- super(line, ind_exp, message_wrapped)
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
- printable_char = line.content[0].dump.gsub(/"/, '')
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
- if printable_char == '\\u00A0'
170
- printable_char = '\\xa0'
171
- explanation = ' (NO-BREAK SPACE)'
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
- # Needed to pass official test.
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module NestedText
4
4
  # The version of this library.
5
- VERSION = '4.0.0'
5
+ VERSION = '4.2.2'
6
6
  end
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
- # The main module in this library to use.
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 "lib/nestedtext/version"
3
+ require_relative 'lib/nestedtext/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "nestedtext"
6
+ spec.name = 'nestedtext'
7
7
  spec.version = NestedText::VERSION
8
- spec.authors = ["Erik Westrup"]
9
- spec.email = ["erik.westrup@gmail.com"]
8
+ spec.authors = ['Erik Westrup']
9
+ spec.email = ['erik.westrup@gmail.com']
10
10
 
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"]
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["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"
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
- "github_repo" => "git@github.com:erikw/nestedtext-ruby.git"
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 = ["lib"]
33
+ spec.require_paths = ['lib']
33
34
 
34
- spec.add_runtime_dependency "warning", "~> 1.2"
35
- spec.add_runtime_dependency "word_wrap", "~> 1.0"
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.0.0
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-01-28 00:00:00.000000000 Z
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: