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
         |