verse-schema 1.1.0 → 1.1.1
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/Gemfile.lock +1 -1
- data/lib/tasks/readme_doc_extractor.rb +1 -1
- data/lib/verse/schema/base.rb +1 -1
- data/lib/verse/schema/coalescer.rb +1 -1
- data/lib/verse/schema/collection.rb +24 -5
- data/lib/verse/schema/dictionary.rb +1 -2
- data/lib/verse/schema/field.rb +3 -3
- data/lib/verse/schema/scalar.rb +36 -11
- data/lib/verse/schema/struct.rb +39 -40
- data/lib/verse/schema/version.rb +1 -1
- 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: 6608dcff00a7bef2d8313866053ac7d37d82933d9b597052a222f0bcad693f91
|
4
|
+
data.tar.gz: dfcecf7d576b599b3c39d552cfbbf082ceda4707f0ec532d94d4a0db3dbfa620
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3bc6f97bf7b683d4e45ee578af5a1cd57375d56f54161a93ed3b725c2f783cbfedb2583fa9dc6470e68243bdaa3cda93f703dc82df4a63bd912d386695933bc
|
7
|
+
data.tar.gz: 49c7ae54ea24d5a4e7a8304e1361f70feb81f68a4993beddc153fabd1c88fa1d63e5eb5bd5bbcb41eea83bd863f7188bcfc73cdf31d98c9a0b08b32d749c0ecc
|
data/Gemfile.lock
CHANGED
@@ -109,7 +109,7 @@ class ReadmeDocExtractor
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
|
112
|
+
# Extract code from an example
|
113
113
|
def extract_code_from_example(example)
|
114
114
|
# Get the example block directly using instance_variable_get
|
115
115
|
example_block = example.instance_variable_get(:@example_block)
|
data/lib/verse/schema/base.rb
CHANGED
@@ -57,10 +57,30 @@ module Verse
|
|
57
57
|
@values.all? do |child_type|
|
58
58
|
# ...is a subtype (`<=`) of *at least one* type allowed by the parent collection.
|
59
59
|
parent_schema.values.any? do |parent_type|
|
60
|
-
#
|
61
|
-
#
|
62
|
-
|
63
|
-
|
60
|
+
# Special handling for when child_type is a primitive class (like Integer)
|
61
|
+
# and parent_type is a Scalar
|
62
|
+
if !child_type.is_a?(Base) && parent_type.is_a?(Scalar)
|
63
|
+
# Check if the primitive class is compatible with any of the Scalar's values
|
64
|
+
parent_type.values.any? do |scalar_value|
|
65
|
+
begin
|
66
|
+
# Use standard Ruby `<=` for comparison
|
67
|
+
child_type <= scalar_value
|
68
|
+
rescue TypeError
|
69
|
+
# Handle cases where <= is not defined between types
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
# Use the existing `<=` operator defined on schema types (Scalar, Struct, etc.)
|
75
|
+
# This assumes the `<=` operator correctly handles class inheritance (e.g., Integer <= Object)
|
76
|
+
# and schema type compatibility.
|
77
|
+
begin
|
78
|
+
child_type <= parent_type
|
79
|
+
rescue TypeError
|
80
|
+
# Handle cases where <= is not defined between types
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
64
84
|
end
|
65
85
|
end
|
66
86
|
end
|
@@ -170,7 +190,6 @@ module Verse
|
|
170
190
|
|
171
191
|
Result.new(output, error_builder.errors)
|
172
192
|
end
|
173
|
-
|
174
193
|
end
|
175
194
|
end
|
176
195
|
end
|
@@ -14,7 +14,7 @@ module Verse
|
|
14
14
|
def initialize(values:, post_processors: nil)
|
15
15
|
super(post_processors:)
|
16
16
|
|
17
|
-
@values
|
17
|
+
@values = values
|
18
18
|
end
|
19
19
|
|
20
20
|
def validate(input, error_builder: nil, locals: {}, strict: false)
|
@@ -155,7 +155,6 @@ module Verse
|
|
155
155
|
|
156
156
|
Result.new(output, error_builder.errors)
|
157
157
|
end
|
158
|
-
|
159
158
|
end
|
160
159
|
end
|
161
160
|
end
|
data/lib/verse/schema/field.rb
CHANGED
@@ -8,7 +8,7 @@ module Verse
|
|
8
8
|
module Schema
|
9
9
|
# A field in a schema
|
10
10
|
class Field
|
11
|
-
attr_reader :opts, :post_processors, :name
|
11
|
+
attr_reader :opts, :post_processors, :name
|
12
12
|
|
13
13
|
def initialize(name, type, opts, post_processors: nil, &block)
|
14
14
|
@name = name
|
@@ -53,7 +53,7 @@ module Verse
|
|
53
53
|
of_arg = @opts[:of] # For array and dictionary
|
54
54
|
of_arg = [of_arg] unless of_arg.nil? || of_arg.is_a?(Array)
|
55
55
|
|
56
|
-
if
|
56
|
+
if [Hash, Object].include?(type)
|
57
57
|
type = Schema.dictionary(*of_arg) if of_arg # dictionary
|
58
58
|
elsif type == Array
|
59
59
|
type = Schema.array(*of_arg) if of_arg
|
@@ -269,7 +269,7 @@ module Verse
|
|
269
269
|
elsif c.is_a?(Class) && p.is_a?(Verse::Schema::Scalar)
|
270
270
|
p.values.any? { |p_val| c <= p_val }
|
271
271
|
elsif c.is_a?(Verse::Schema::Base) && p.is_a?(Verse::Schema::Base)
|
272
|
-
|
272
|
+
c <= p
|
273
273
|
elsif c.is_a?(Class) && p.is_a?(Class)
|
274
274
|
c <= p
|
275
275
|
else
|
data/lib/verse/schema/scalar.rb
CHANGED
@@ -64,19 +64,45 @@ module Verse
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
|
67
|
+
def <=(other)
|
68
|
+
# 1. Identical check: Is it the exact same object?
|
69
|
+
return true if other == self
|
70
|
+
|
71
|
+
# 2. Check if inheriting from another Scalar:
|
72
|
+
# Use the existing inherit? method which correctly handles Scalar-to-Scalar inheritance.
|
73
|
+
# (inherit? implicitly checks `other.is_a?(Scalar)`)
|
74
|
+
return true if inherit?(other)
|
75
|
+
|
76
|
+
# 3. NEW: Check compatibility with non-Scalar types:
|
77
|
+
# If 'other' is not a Scalar, check if any type *wrapped* by this Scalar
|
78
|
+
# is a subtype of 'other'. This handles `Scalar<Integer> <= Integer`.
|
79
|
+
# We rely on the `<=` operator of the wrapped types themselves.
|
80
|
+
@values.any? do |wrapped_type|
|
81
|
+
begin
|
82
|
+
# Use standard Ruby `<=` for comparison.
|
83
|
+
# This works for Class <= Class (e.g., Integer <= Integer, Integer <= Numeric)
|
84
|
+
# and potentially for SchemaType <= SchemaType if defined.
|
85
|
+
wrapped_type <= other
|
86
|
+
rescue TypeError
|
87
|
+
# Handle cases where <= is not defined between wrapped_type and other
|
88
|
+
false
|
69
89
|
end
|
90
|
+
end
|
91
|
+
end
|
70
92
|
|
71
|
-
|
72
|
-
|
73
|
-
|
93
|
+
def <(other)
|
94
|
+
other != self && self <= other
|
95
|
+
end
|
74
96
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
97
|
+
# rubocop:disable Style/InverseMethods
|
98
|
+
def >(other)
|
99
|
+
!(self <= other)
|
100
|
+
end
|
101
|
+
|
102
|
+
def >=(other)
|
103
|
+
other <= self
|
104
|
+
end
|
105
|
+
# rubocop:enable Style/InverseMethods
|
80
106
|
|
81
107
|
# Aggregation of two schemas.
|
82
108
|
def +(other)
|
@@ -149,7 +175,6 @@ module Verse
|
|
149
175
|
|
150
176
|
Result.new(coalesced_value, error_builder.errors)
|
151
177
|
end
|
152
|
-
|
153
178
|
end
|
154
179
|
end
|
155
180
|
end
|
data/lib/verse/schema/struct.rb
CHANGED
@@ -221,49 +221,49 @@ module Verse
|
|
221
221
|
fields << :extra_fields if extra_fields?
|
222
222
|
|
223
223
|
# Special case for empty schema (yeah, I know, it happens in my production code...)
|
224
|
-
if fields.empty?
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
224
|
+
@dataclass = if fields.empty?
|
225
|
+
Class.new do
|
226
|
+
def self.from_raw(*)=new
|
227
|
+
def self.schema = dataclass_schema
|
228
|
+
|
229
|
+
class_eval(&block) if block
|
230
|
+
end
|
231
|
+
else
|
232
|
+
::Struct.new(*fields, keyword_init: true) do
|
233
|
+
# Redefine new method
|
234
|
+
define_singleton_method(:from_raw, &method(:new))
|
235
|
+
|
236
|
+
define_singleton_method(:new) do |*args, **kwargs|
|
237
|
+
# Use the schema to generate the hash for our record
|
238
|
+
if args.size > 1
|
239
|
+
raise ArgumentError, "You cannot pass more than one argument"
|
240
|
+
end
|
241
|
+
|
242
|
+
if args.size == 1
|
243
|
+
if kwargs.any?
|
244
|
+
raise ArgumentError, "You cannot pass both a hash and keyword arguments"
|
245
|
+
end
|
246
|
+
|
247
|
+
kwargs = args.first
|
248
|
+
end
|
249
|
+
|
250
|
+
dataclass_schema.new(kwargs)
|
251
|
+
end
|
252
|
+
|
253
|
+
define_singleton_method(:schema){ dataclass_schema }
|
254
|
+
|
255
|
+
class_eval(&block) if block
|
256
|
+
end
|
257
|
+
end
|
258
258
|
end
|
259
259
|
|
260
260
|
def inspect
|
261
261
|
fields_string = @fields.map do |field|
|
262
|
-
if field.type.is_a?(Array)
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
262
|
+
type_str = if field.type.is_a?(Array)
|
263
|
+
field.type.map(&:inspect).join("|")
|
264
|
+
else
|
265
|
+
field.type.inspect
|
266
|
+
end
|
267
267
|
|
268
268
|
optional_marker = field.optional? ? "?" : ""
|
269
269
|
"#{field.name}#{optional_marker}: #{type_str}"
|
@@ -320,7 +320,6 @@ module Verse
|
|
320
320
|
|
321
321
|
Result.new(output, error_builder.errors)
|
322
322
|
end
|
323
|
-
|
324
323
|
end
|
325
324
|
end
|
326
325
|
end
|
data/lib/verse/schema/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: verse-schema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yacine Petitprez
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-25 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: attr_chainable
|