lutaml-model 0.8.144 → 0.8.146
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/lib/lutaml/key_value/adapter/yamls/standard_adapter.rb +1 -1
- data/lib/lutaml/model/serialize/value_mapping.rb +15 -0
- data/lib/lutaml/model/utils.rb +11 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/yamls/adapter/standard_adapter.rb +2 -2
- data/spec/lutaml/model/polymorphic_spec.rb +28 -0
- data/spec/lutaml/model/yamls_spec.rb +32 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c23c8811a30181e0ed6ca3987a23ab7fadf4c4354ca143d28e84114218f80af
|
|
4
|
+
data.tar.gz: aa89d32438cae623a9e0dd37bd8e614bcdd76bf53759e164b47f44eb957f7a96
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3dd2402033dbecea612e3bb32903d041d466d71408cbda93159dedc5af884f24a0b49e6501874481bc92184b6179d996f388bcee0811f9b7758c9361a593f68c
|
|
7
|
+
data.tar.gz: 5109ea9359e823c2ace26967168222d01d0da81390e838b77c0445cc29ee295aa173fbdb938067eacd4353a457080e78df13c88df568cb0118e28da6ada77563
|
|
@@ -67,6 +67,21 @@ module Lutaml
|
|
|
67
67
|
klass = Object.const_get(klass_name)
|
|
68
68
|
|
|
69
69
|
propagated = options.slice(*Lutaml::Model::Attribute::CHILD_PROPAGATION_KEYS)
|
|
70
|
+
|
|
71
|
+
# A map entry that resolves to the deserializing class itself
|
|
72
|
+
# (a subclass inheriting its base's map, or an apply_mappings
|
|
73
|
+
# override delegating back to super for its own concrete class)
|
|
74
|
+
# must fall through to this class's real deserialization:
|
|
75
|
+
# re-dispatching apply_mappings would resolve the same entry
|
|
76
|
+
# again and never make progress.
|
|
77
|
+
if klass == model
|
|
78
|
+
transformer = Lutaml::Model::Config.transformer_for(format)
|
|
79
|
+
return transformer.data_to_model(
|
|
80
|
+
self, doc, format,
|
|
81
|
+
propagated.merge(register: instance.lutaml_register)
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
|
|
70
85
|
klass.apply_mappings(doc, format,
|
|
71
86
|
propagated.merge(register: instance.lutaml_register))
|
|
72
87
|
end
|
data/lib/lutaml/model/utils.rb
CHANGED
|
@@ -34,6 +34,17 @@ module Lutaml
|
|
|
34
34
|
false
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# Parse-error classes of every YAML engine that may be answering
|
|
38
|
+
# ::YAML in this process. A host bundle can rebind ::YAML (a
|
|
39
|
+
# Psych drop-in), so the multi-document skip-rescues must cover
|
|
40
|
+
# each loaded engine's parse error, not only Psych's (#1053: a
|
|
41
|
+
# raw Yeptris::ParseError escaped from_yamls).
|
|
42
|
+
def yaml_parse_errors
|
|
43
|
+
errors = [Psych::SyntaxError]
|
|
44
|
+
errors << Yeptris::ParseError if defined?(Yeptris::ParseError)
|
|
45
|
+
errors
|
|
46
|
+
end
|
|
47
|
+
|
|
37
48
|
# Convert string to camel case (cached)
|
|
38
49
|
def camel_case(str)
|
|
39
50
|
return "" if str.nil? || str.empty?
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Lutaml
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
results
|
|
25
|
-
rescue
|
|
25
|
+
rescue *Lutaml::Model::Utils.yaml_parse_errors => e
|
|
26
26
|
warn "Skipping invalid yaml: #{e.message}"
|
|
27
27
|
parse_with_split(yamls)
|
|
28
28
|
end
|
|
@@ -36,7 +36,7 @@ module Lutaml
|
|
|
36
36
|
begin
|
|
37
37
|
doc = YAML.safe_load(yaml, aliases: true)
|
|
38
38
|
results << doc unless doc.nil?
|
|
39
|
-
rescue
|
|
39
|
+
rescue *Lutaml::Model::Utils.yaml_parse_errors => e
|
|
40
40
|
warn "Skipping invalid yaml: #{e.message}"
|
|
41
41
|
end
|
|
42
42
|
end
|
|
@@ -125,6 +125,21 @@ module PolymorphicSpec
|
|
|
125
125
|
}
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
|
+
|
|
129
|
+
# A polymorphic map whose entry resolves to the class carrying it
|
|
130
|
+
# (e.g. a subclass inheriting its base's map, or an apply_mappings
|
|
131
|
+
# override delegating back to super for its own concrete class).
|
|
132
|
+
class SelfResolving < Lutaml::Model::Serializable
|
|
133
|
+
attribute :_type, :string
|
|
134
|
+
attribute :name, :string
|
|
135
|
+
|
|
136
|
+
key_value do
|
|
137
|
+
map "_type", to: :_type, polymorphic_map: {
|
|
138
|
+
"self_resolving" => "PolymorphicSpec::Base::SelfResolving",
|
|
139
|
+
}
|
|
140
|
+
map "name", to: :name
|
|
141
|
+
end
|
|
142
|
+
end
|
|
128
143
|
end
|
|
129
144
|
|
|
130
145
|
module Child
|
|
@@ -546,4 +561,17 @@ RSpec.describe "Polymorphic" do
|
|
|
546
561
|
end
|
|
547
562
|
end
|
|
548
563
|
end
|
|
564
|
+
|
|
565
|
+
# A polymorphic map that resolves a document to the very class that is
|
|
566
|
+
# deserializing it must fall through to the model's own
|
|
567
|
+
# deserialization, not re-dispatch apply_mappings forever.
|
|
568
|
+
context "when the polymorphic map resolves to the deserializing class" do
|
|
569
|
+
it "deserializes without recursing" do
|
|
570
|
+
model = PolymorphicSpec::Base::SelfResolving.apply_mappings(
|
|
571
|
+
{ "_type" => "self_resolving", "name" => "x" }, :hash
|
|
572
|
+
)
|
|
573
|
+
expect(model).to be_a(PolymorphicSpec::Base::SelfResolving)
|
|
574
|
+
expect(model.name).to eq("x")
|
|
575
|
+
end
|
|
576
|
+
end
|
|
549
577
|
end
|
|
@@ -154,6 +154,38 @@ RSpec.describe "Yamls" do
|
|
|
154
154
|
end.to output(/Skipping invalid yaml: /).to_stderr
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
+
# #1053: a host bundle can rebind ::YAML to another engine (a Psych
|
|
158
|
+
# drop-in), so the multi-doc lane must treat every loaded engine's
|
|
159
|
+
# parse error as a skippable document error — never let a raw engine
|
|
160
|
+
# error escape.
|
|
161
|
+
describe "engine parse errors" do
|
|
162
|
+
it "rescues every loaded YAML engine's parse errors" do
|
|
163
|
+
errors = Lutaml::Model::Utils.yaml_parse_errors
|
|
164
|
+
|
|
165
|
+
expect(errors).to include(Psych::SyntaxError)
|
|
166
|
+
if defined?(Yeptris::ParseError)
|
|
167
|
+
expect(errors).to include(Yeptris::ParseError)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "skips an invalid document when the active engine raises its own parse error" do
|
|
172
|
+
skip "yeptris not loadable in this process" unless Lutaml::Model::Utils.safe_load("yeptris", :Yeptris)
|
|
173
|
+
|
|
174
|
+
allow(YAML).to receive(:load_stream).and_raise(
|
|
175
|
+
Yeptris::ParseError.new("parse failed: unexpected parser state at line 11, column 26"),
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
expect do
|
|
179
|
+
expect(Lutaml::Yamls::Adapter::StandardAdapter.parse(invalid_yamls_content)).to eq(
|
|
180
|
+
[
|
|
181
|
+
{ "full_name" => "John", "age" => 30, "address" => { "city" => "New York" } },
|
|
182
|
+
{ "full_name" => "Bob", "age" => 35, "address" => { "city" => "Paris" } },
|
|
183
|
+
],
|
|
184
|
+
)
|
|
185
|
+
end.to output(/Skipping invalid yaml: /).to_stderr
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
157
189
|
describe "parsing" do
|
|
158
190
|
it "handles empty documents" do
|
|
159
191
|
yamls_with_empty_docs = <<~YAMLS
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lutaml-model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.146
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|