lutaml-model 0.8.103 → 0.8.104

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02366b5cf16f9598e6eae1c391d7b21002fe9744cc4d617bf4bb9ffc785141a8
4
- data.tar.gz: b3e2928f228d2aa613e506c6b07ce70a765bb33d1574e61e871fd7f6d226ee43
3
+ metadata.gz: bd4d3ab0b184df92ad1d6ef04af5e1e1af9d483d34902f36d94b010477c54841
4
+ data.tar.gz: 6e5eee3bebcf1b9557b1cf635253b322a5dffc31fcbe1c7e3b07a76143a2100f
5
5
  SHA512:
6
- metadata.gz: '096e5a0302f14999f0f0c33c5c08455cdea460bee145d0a2cbb222d5bf19157f931a8aecd9e99a2232e176db0a7c546b62908a91f851c083aedf75a4cbfb5993'
7
- data.tar.gz: 79a62c6ce918c5ea416eec0a9343a9b52b65f5f9d7e234bcc94beaba817e2658d25ba680215ffaee282a8bfc4ba3f4d4fd2900ecfe5907c36f0ff317ec293028
6
+ metadata.gz: 761158fee8d42f919236179a76b90116183afde1cc7e8beb6921c958c27d03c96a6ada9a04abc0959417e34f1ca7677e99b33c00ef38326fe10cf196c0010e4f
7
+ data.tar.gz: 96f3e592216d1f0fe4bc6274ea92006e8db8fb67d77b31dbe79868175d1a42cfa17145ea9ac981d2ba6aaecf9cf9888260a1a33675f6aa7b735667d275270e23
@@ -59,14 +59,14 @@ module Lutaml
59
59
  # updates so recursive type resolution can populate related keys.
60
60
  #
61
61
  # @param name [Symbol, String, Class] The type name or class to resolve
62
- # @param context [TypeContext] The resolution context
62
+ # @param context [TypeContext, nil] The resolution context
63
63
  # @return [Class] The resolved type class
64
64
  # @raise [UnknownTypeError] If type cannot be resolved
65
65
  def resolve(name, context, materialize: true)
66
66
  return @delegate.resolve(name, context, materialize: false) unless materialize
67
67
 
68
68
  cache_key = if name.is_a?(Class)
69
- [context.id, name]
69
+ [context_id_for(context), name]
70
70
  else
71
71
  build_cache_key(name, context)
72
72
  end
@@ -79,11 +79,11 @@ module Lutaml
79
79
  # Check if a type can be resolved, using cache if available.
80
80
  #
81
81
  # @param name [Symbol, String, Class] The type name or class to check
82
- # @param context [TypeContext] The resolution context
82
+ # @param context [TypeContext, nil] The resolution context
83
83
  # @return [Boolean] true if type can be resolved
84
84
  def resolvable?(name, context)
85
85
  cache_key = if name.is_a?(Class)
86
- [context.id, name]
86
+ [context_id_for(context), name]
87
87
  else
88
88
  build_cache_key(name, context)
89
89
  end
@@ -137,10 +137,17 @@ module Lutaml
137
137
  # Uses array for faster comparison than string concatenation.
138
138
  #
139
139
  # @param name [Symbol, String] The type name
140
- # @param context [TypeContext] The resolution context
140
+ # @param context [TypeContext, nil] The resolution context
141
141
  # @return [Array] The cache key (faster than string)
142
142
  def build_cache_key(name, context)
143
- [context.id, name.to_sym]
143
+ [context_id_for(context), name.to_sym]
144
+ end
145
+
146
+ # A nil context (e.g. a register ID that has no registered type
147
+ # context) is a legitimate "no namespace" resolution; the cache
148
+ # key just forgoes the namespace slot.
149
+ def context_id_for(context)
150
+ context&.id
144
151
  end
145
152
  end
146
153
  end
@@ -44,7 +44,9 @@ module Lutaml
44
44
  # 5. Raise UnknownTypeError if not found anywhere
45
45
  #
46
46
  # @param name [Symbol, String, Class] The type name or class to resolve
47
- # @param context [TypeContext] The resolution context
47
+ # @param context [TypeContext, nil] The resolution context (nil means
48
+ # no primary registry and no fallbacks — an id registered in the
49
+ # Register namespace but not as a type context)
48
50
  # @return [Class] The resolved type class
49
51
  # @raise [UnknownTypeError] If type cannot be resolved
50
52
  #
@@ -66,11 +68,11 @@ module Lutaml
66
68
  type_name = name.to_sym
67
69
 
68
70
  # 1. Check primary registry
69
- type = context.lookup_local(type_name)
71
+ type = context&.lookup_local(type_name)
70
72
  return apply_substitutions(type, context) if type
71
73
 
72
74
  # 2. Check fallback contexts in order
73
- if context.has_fallbacks?
75
+ if context&.has_fallbacks?
74
76
  context.fallback_contexts.each do |fallback_context|
75
77
  type = resolve_from_fallback(type_name, fallback_context)
76
78
  return apply_substitutions(type, context) if type
@@ -97,8 +99,8 @@ module Lutaml
97
99
  # 5. Type not found - raise error
98
100
  raise UnknownTypeError.new(
99
101
  type_name,
100
- context_id: context.id,
101
- available_types: available_type_names(context),
102
+ context_id: context&.id,
103
+ available_types: context ? available_type_names(context) : [],
102
104
  )
103
105
  end
104
106
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Model
5
- VERSION = "0.8.103"
5
+ VERSION = "0.8.104"
6
6
  end
7
7
  end
@@ -23,7 +23,7 @@ module Lutaml
23
23
  assert_no_truncated_recovered_parse!(parsed)
24
24
  root_element = parsed.root
25
25
 
26
- raise_empty_document_error if root_element.nil?
26
+ raise_empty_document_error(parsed.parse_errors) if root_element.nil?
27
27
 
28
28
  root = self::PARSED_ELEMENT_CLASS.new(root_element)
29
29
  doc_pis = extract_document_processing_instructions(parsed)
@@ -112,8 +112,11 @@ module Lutaml
112
112
  }
113
113
  end
114
114
 
115
- def raise_empty_document_error
115
+ def raise_empty_document_error(parse_errors = nil)
116
116
  message = self::EMPTY_DOCUMENT_ERROR_MESSAGE
117
+ if parse_errors && !parse_errors.empty?
118
+ message += " (the XML engine reported: #{parse_errors.join('; ')})"
119
+ end
117
120
 
118
121
  case self::EMPTY_DOCUMENT_ERROR_TYPE
119
122
  when :parse_exception
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ # Register ids and type-context ids are two namespaces that
6
+ # GlobalContext#resolve_type bridges implicitly: an id present only in the
7
+ # Register namespace (a flavor's `lutaml_default_register`) resolves to a
8
+ # nil type context, and every resolution shape must treat that as a
9
+ # legitimate "no namespace" input instead of crashing (metanorma-jis#531).
10
+ RSpec.describe "type resolution through a register id with no registered type context" do
11
+ let(:collection_class) do
12
+ Class.new(Lutaml::Model::Collection) do
13
+ instances :entries, :string
14
+ end
15
+ end
16
+
17
+ it "resolves collection instance types under a nil context" do
18
+ collection = collection_class.new(["a"], lutaml_register: :jis_document)
19
+
20
+ expect(collection.entries).to eq(["a"])
21
+ end
22
+
23
+ it "resolves built-in symbol names under a nil context" do
24
+ resolved = Lutaml::Model::GlobalContext.resolve_type(:string, :jis_document)
25
+
26
+ expect(resolved).to eq(Lutaml::Model::Type::String)
27
+ end
28
+
29
+ it "raises UnknownTypeError for unknown names under a nil context" do
30
+ expect do
31
+ Lutaml::Model::GlobalContext.resolve_type(:no_such_type, :jis_document)
32
+ end.to raise_error(Lutaml::Model::UnknownTypeError)
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "lutaml/xml/adapter/leptris_adapter"
5
+ require "lutaml/xml/adapter/nokogiri_adapter"
6
+
7
+ # A failed parse reaches the empty-document guard as a document with no
8
+ # root, indistinguishable from genuinely empty input. The engine's parse
9
+ # diagnostics ride the document (moxml attachments :parse_errors) and
10
+ # must surface in the raised message — otherwise the error names the
11
+ # input's emptiness while the input is neither empty nor the problem
12
+ # (lutaml-model#956).
13
+ RSpec.describe "empty-document errors surface engine parse diagnostics" do
14
+ describe Lutaml::Xml::Adapter::LeptrisAdapter do
15
+ it "appends the engine diagnostic when the parse failed" do
16
+ expect do
17
+ described_class.parse("<root><a>x</b></root>")
18
+ end.to raise_error(Lutaml::Model::InvalidFormatError) do |error|
19
+ expect(error.message).to include("the XML engine reported:")
20
+ expect(error.message).to include("XML parse error at byte 14")
21
+ end
22
+ end
23
+
24
+ it "reports the engine diagnostic for whitespace-only input" do
25
+ expect do
26
+ described_class.parse(" ")
27
+ end.to raise_error(Lutaml::Model::InvalidFormatError, /the XML engine reported:/)
28
+ end
29
+ end
30
+
31
+ describe Lutaml::Xml::Adapter::NokogiriAdapter do
32
+ it "keeps the plain empty-document message when the engine reported nothing" do
33
+ expect do
34
+ described_class.parse("")
35
+ end.to raise_error(Lutaml::Model::InvalidFormatError) do |error|
36
+ expect(error.message).to include("The XML may be empty")
37
+ expect(error.message).not_to include("the XML engine reported:")
38
+ end
39
+ end
40
+ end
41
+ end
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.103
4
+ version: 0.8.104
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 00:00:00.000000000 Z
11
+ date: 2026-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -1863,6 +1863,7 @@ files:
1863
1863
  - spec/lutaml/model/uninitialized_class_spec.rb
1864
1864
  - spec/lutaml/model/union_attribute_spec.rb
1865
1865
  - spec/lutaml/model/union_spec.rb
1866
+ - spec/lutaml/model/unregistered_context_resolution_spec.rb
1866
1867
  - spec/lutaml/model/utils_spec.rb
1867
1868
  - spec/lutaml/model/validation/concerns/has_issues_spec.rb
1868
1869
  - spec/lutaml/model/validation/context_spec.rb
@@ -1913,6 +1914,7 @@ files:
1913
1914
  - spec/lutaml/turtle/mapping_spec.rb
1914
1915
  - spec/lutaml/turtle/transform_spec.rb
1915
1916
  - spec/lutaml/xml/adapter/base_adapter_regression_spec.rb
1917
+ - spec/lutaml/xml/adapter/empty_document_diagnostics_spec.rb
1916
1918
  - spec/lutaml/xml/adapter/nokogiri_adapter_spec.rb
1917
1919
  - spec/lutaml/xml/adapter/oga_adapter_spec.rb
1918
1920
  - spec/lutaml/xml/adapter/order_spec.rb