lutaml-model 0.8.142 → 0.8.144
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/model/serialize/initialization.rb +6 -4
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/xml/schema/xsd/all.rb +2 -2
- data/spec/lutaml/model/cow_fork_public_spec.rb +60 -0
- data/spec/lutaml/xml/schema/xsd/all_occurrence_attributes_spec.rb +60 -0
- data/spec/lutaml/xml/schema/xsd/mapping_integrity_spec.rb +37 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff4c24c792fe315c6798bf64b67dbc4924fc919fc447e4a0264467d169a80315
|
|
4
|
+
data.tar.gz: 15621c39ad1d06dddbca3c9b0ef809b1a87d13222ef850c0cdb557da3317ca1d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21de2545ba67ce8357cd0216e70a085648ea24153cff022a805005b677d7d90ab51af50869cfc6335d6aad5404f4bb4fde30ed9f6389a31ff9b7ac51580646b4
|
|
7
|
+
data.tar.gz: d46faf8a708c88622abb2d560bf2f533da86815553c81049b8d432f71d60cfad67a65e567858454a7ecad721b2d2e02c2c3d6bd8bc173416903dc5d4faab7065
|
|
@@ -184,12 +184,16 @@ module Lutaml
|
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
186
|
|
|
187
|
-
private
|
|
188
|
-
|
|
189
187
|
# Replace a shared structure with a class-owned copy. The copy
|
|
190
188
|
# becomes the snapshot for every existing subclass, which is what
|
|
191
189
|
# keeps post-fork mutations invisible to them (the eager-copy
|
|
192
190
|
# semantics).
|
|
191
|
+
#
|
|
192
|
+
# Public on purpose: code that mutates `mappings`, `attributes`,
|
|
193
|
+
# `choices` or `registers` outside the DSL — sibling classes pruning
|
|
194
|
+
# inherited elements (relaton's Item-header prunes) or importing
|
|
195
|
+
# models — must fork the structure first, or the mutation lands on
|
|
196
|
+
# the object shared with the superclass and every sibling class.
|
|
193
197
|
def lutaml_cow_fork!(structure)
|
|
194
198
|
return if lutaml_cow_status(structure) == 1
|
|
195
199
|
|
|
@@ -220,8 +224,6 @@ module Lutaml
|
|
|
220
224
|
lutaml_cow_set_status!(structure, 1)
|
|
221
225
|
end
|
|
222
226
|
|
|
223
|
-
public
|
|
224
|
-
|
|
225
227
|
# Return the mapping object a format DSL may mutate. Forking
|
|
226
228
|
# the mappings structure copies every entry, so the object
|
|
227
229
|
# returned here is this class's own.
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -17,8 +17,8 @@ module Lutaml
|
|
|
17
17
|
namespace Lutaml::Xml::Schema::XsdNamespace
|
|
18
18
|
|
|
19
19
|
map_attribute :id, to: :id
|
|
20
|
-
map_attribute :
|
|
21
|
-
map_attribute :
|
|
20
|
+
map_attribute :maxOccurs, to: :max_occurs
|
|
21
|
+
map_attribute :minOccurs, to: :min_occurs
|
|
22
22
|
map_element :annotation, to: :annotation
|
|
23
23
|
map_element :element, to: :element
|
|
24
24
|
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
# Copy-on-write inheritance shares a subclass's structures with its
|
|
6
|
+
# superclass until the class's own DSL forks them. External mutators — a
|
|
7
|
+
# library pruning an inherited attribute on one subclass (relaton's
|
|
8
|
+
# Item-header prunes) — need a supported way to claim ownership first, or
|
|
9
|
+
# the mutation erases the attribute for every sibling class.
|
|
10
|
+
RSpec.describe "Lutaml::Model::Serializable#lutaml_cow_fork!" do
|
|
11
|
+
let(:parent_class) do
|
|
12
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
13
|
+
attribute :id, :string
|
|
14
|
+
attribute :shared, :string
|
|
15
|
+
|
|
16
|
+
xml do
|
|
17
|
+
root "parent"
|
|
18
|
+
map_attribute "id", to: :id
|
|
19
|
+
map_element "shared", to: :shared
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:child_class) do
|
|
25
|
+
Class.new(parent_class)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "is callable from outside the DSL" do
|
|
29
|
+
expect(child_class).to respond_to(:lutaml_cow_fork!)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "gives the class a private copy without touching the superclass" do
|
|
33
|
+
parent_attributes = parent_class.class_attributes
|
|
34
|
+
child_class.lutaml_cow_fork!(:attributes)
|
|
35
|
+
|
|
36
|
+
expect(child_class.class_attributes).not_to equal(parent_attributes)
|
|
37
|
+
expect(parent_class.class_attributes).to equal(parent_attributes)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "keeps post-fork mutations private to the forking class" do
|
|
41
|
+
child_class.lutaml_cow_fork!(:attributes)
|
|
42
|
+
child_class.lutaml_cow_fork!(:mappings)
|
|
43
|
+
child_class.class_attributes.delete(:id)
|
|
44
|
+
xml_attrs = child_class.mappings[:xml].instance_variable_get(:@attributes)
|
|
45
|
+
xml_attrs.delete("id")
|
|
46
|
+
|
|
47
|
+
expect(parent_class.class_attributes).to be_key(:id)
|
|
48
|
+
expect(parent_class.mappings[:xml]
|
|
49
|
+
.instance_variable_get(:@attributes)).to be_key("id")
|
|
50
|
+
expect(child_class.class_attributes).not_to be_key(:id)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "does not fork an already-owned structure into a new object" do
|
|
54
|
+
child_class.lutaml_cow_fork!(:attributes)
|
|
55
|
+
owned = child_class.class_attributes
|
|
56
|
+
child_class.lutaml_cow_fork!(:attributes)
|
|
57
|
+
|
|
58
|
+
expect(child_class.class_attributes).to equal(owned)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../../../spec_helper"
|
|
4
|
+
require "lutaml/xml/schema/xsd"
|
|
5
|
+
|
|
6
|
+
# #1046: xs:all carried its occurrence bounds mapped by their Ruby names
|
|
7
|
+
# (min_occurs/max_occurs), so minOccurs="0" was silently dropped at parse
|
|
8
|
+
# and never re-emitted. Sequence, choice and group already map the XML
|
|
9
|
+
# names; all now does too.
|
|
10
|
+
RSpec.describe "Xsd::All occurrence attributes" do
|
|
11
|
+
let(:xsd) do
|
|
12
|
+
<<~XSD
|
|
13
|
+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
|
14
|
+
<xsd:element name="elt1">
|
|
15
|
+
<xsd:complexType>
|
|
16
|
+
<xsd:all minOccurs="0" maxOccurs="1">
|
|
17
|
+
<xsd:element name="elt2"/>
|
|
18
|
+
</xsd:all>
|
|
19
|
+
</xsd:complexType>
|
|
20
|
+
</xsd:element>
|
|
21
|
+
</xsd:schema>
|
|
22
|
+
XSD
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "reads the occurrence bounds" do
|
|
26
|
+
doc = Lutaml::Xml::Schema::Xsd.parse(xsd)
|
|
27
|
+
all = doc.element.first.complex_type.all
|
|
28
|
+
|
|
29
|
+
expect(all.min_occurs).to eq("0")
|
|
30
|
+
expect(all.max_occurs).to eq("1")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "round-trips them as the XML attribute names" do
|
|
34
|
+
xml = Lutaml::Xml::Schema::Xsd.parse(xsd).to_xml
|
|
35
|
+
|
|
36
|
+
expect(xml).to include('minOccurs="0"')
|
|
37
|
+
expect(xml).to include('maxOccurs="1"')
|
|
38
|
+
expect(xml).not_to include("min_occurs")
|
|
39
|
+
expect(xml).not_to include("max_occurs")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "keeps an xs:all without bounds boundless" do
|
|
43
|
+
doc = Lutaml::Xml::Schema::Xsd.parse(
|
|
44
|
+
<<~XSD,
|
|
45
|
+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
|
46
|
+
<xsd:element name="elt1">
|
|
47
|
+
<xsd:complexType>
|
|
48
|
+
<xsd:all><xsd:element name="elt2"/></xsd:all>
|
|
49
|
+
</xsd:complexType>
|
|
50
|
+
</xsd:element>
|
|
51
|
+
</xsd:schema>
|
|
52
|
+
XSD
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
all = doc.element.first.complex_type.all
|
|
56
|
+
|
|
57
|
+
expect(all.min_occurs).to be_nil
|
|
58
|
+
expect(all.max_occurs).to be_nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -14,6 +14,15 @@ require "lutaml/xml/schema/xsd"
|
|
|
14
14
|
# registered model's element and attribute rules to declared attributes
|
|
15
15
|
# so the whole typo family fails here, at spec time.
|
|
16
16
|
RSpec.describe "XSD schema model mapping integrity" do
|
|
17
|
+
# The registry fills at class-definition time and Xsd.parse is what
|
|
18
|
+
# force-loads the classes; without this hook the sweeps below see an
|
|
19
|
+
# empty register whenever they run before any parsing spec.
|
|
20
|
+
before do
|
|
21
|
+
Lutaml::Xml::Schema::Xsd::XSD_AUTOLOAD_CLASSES.each do |name|
|
|
22
|
+
Lutaml::Xml::Schema::Xsd.const_get(name) unless name == :VERSION
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
17
26
|
it "maps every element rule of every registered model to a declared attribute" do
|
|
18
27
|
broken = []
|
|
19
28
|
|
|
@@ -60,6 +69,34 @@ RSpec.describe "XSD schema model mapping integrity" do
|
|
|
60
69
|
MSG
|
|
61
70
|
end
|
|
62
71
|
|
|
72
|
+
# #1046 family: xs:all mapped its occurrence bounds by their Ruby names
|
|
73
|
+
# (min_occurs/max_occurs), so minOccurs="0" was dropped at parse. The
|
|
74
|
+
# XSD vocabulary has no snake_case attribute names — every multi-word
|
|
75
|
+
# XML attribute is camelCase — so a snake_case rule name is always a
|
|
76
|
+
# Ruby name that leaked into the wire.
|
|
77
|
+
it "spells every multi-word XML attribute name in camelCase" do
|
|
78
|
+
broken = []
|
|
79
|
+
|
|
80
|
+
Lutaml::Xml::Schema::Xsd.register.models.each_value do |klass|
|
|
81
|
+
next unless klass.is_a?(Class) && klass.include?(Lutaml::Model::Serialize)
|
|
82
|
+
|
|
83
|
+
mapping = klass.mappings_for(:xml)
|
|
84
|
+
mapping.mapping_attributes_hash.each_value do |rule_or_array|
|
|
85
|
+
Array(rule_or_array).each do |rule|
|
|
86
|
+
next unless rule.name.to_s.include?("_")
|
|
87
|
+
|
|
88
|
+
broken << "#{klass.name}: map_attribute #{rule.name.inspect} -> " \
|
|
89
|
+
"#{rule.to.inspect}"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
expect(broken).to be_empty, <<~MSG
|
|
95
|
+
attribute rules spelled with snake_case wire names:
|
|
96
|
+
#{broken.join("\n")}
|
|
97
|
+
MSG
|
|
98
|
+
end
|
|
99
|
+
|
|
63
100
|
# #1025: the regression that motivated the sweep — a redefine with a
|
|
64
101
|
# group child parses, and each redefined member kind lands on its
|
|
65
102
|
# declared attribute.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.144
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -1753,6 +1753,7 @@ files:
|
|
|
1753
1753
|
- spec/lutaml/model/consolidation_spec.rb
|
|
1754
1754
|
- spec/lutaml/model/context_registry_spec.rb
|
|
1755
1755
|
- spec/lutaml/model/conversion_caching_spec.rb
|
|
1756
|
+
- spec/lutaml/model/cow_fork_public_spec.rb
|
|
1756
1757
|
- spec/lutaml/model/custom_bibtex_adapter_spec.rb
|
|
1757
1758
|
- spec/lutaml/model/custom_collection_spec.rb
|
|
1758
1759
|
- spec/lutaml/model/custom_from_empty_values_spec.rb
|
|
@@ -2047,6 +2048,7 @@ files:
|
|
|
2047
2048
|
- spec/lutaml/xml/schema/facet_round_trip_spec.rb
|
|
2048
2049
|
- spec/lutaml/xml/schema/rnc_compiler_spec.rb
|
|
2049
2050
|
- spec/lutaml/xml/schema/rng_compiler_spec.rb
|
|
2051
|
+
- spec/lutaml/xml/schema/xsd/all_occurrence_attributes_spec.rb
|
|
2050
2052
|
- spec/lutaml/xml/schema/xsd/any_attribute_spec.rb
|
|
2051
2053
|
- spec/lutaml/xml/schema/xsd/errors/error_context_spec.rb
|
|
2052
2054
|
- spec/lutaml/xml/schema/xsd/errors/suggestion_spec.rb
|