Module: Anthropic::Internal::Type::Converter Private

Extended by:
Util::SorbetRuntimeSupport
Included in:
ArrayOf, BaseModel, Boolean, Enum, FileInput, HashOf, Union, Unknown
Defined in:
lib/anthropic/internal/type/converter.rb

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util::SorbetRuntimeSupport

const_missing, define_sorbet_constant!, sorbet_constant_defined?, to_sorbet_type, to_sorbet_type

Class Method Details

.coerce(target, value, state: Anthropic::Internal::Type::Converter.new_coerce_state) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Based on ‘target`, transform `value` into `target`, to the extent possible:

  1. if the given ‘value` conforms to `target` already, return the given `value`

  2. if it’s possible and safe to convert the given ‘value` to `target`, then the converted value

  3. otherwise, the given ‘value` unaltered

The coercion process is subject to improvement between minor release versions. See docs.pydantic.dev/latest/concepts/unions/#smart-mode

when we have to decide between multiple possible conversion targets:

  • ‘true`: the conversion must be exact, with minimum coercion.

  • ‘false`: the conversion can be approximate, with some coercion.

The ‘exactness` is `Hash` with keys being one of `yes`, `no`, or `maybe`. For any given conversion attempt, the exactness will be updated based on how closely the value recursively matches the target type:

  • ‘yes`: the value can be converted to the target type with minimum coercion.

  • ‘maybe`: the value can be converted to the target type with some reasonable coercion.

  • ‘no`: the value cannot be converted to the target type.

See implementation below for more details.

@option state [Boolean] :translate_names

@option state [Boolean] :strictness

@option state [Hash{Symbol=>Object}] :exactness

@option state [Class<StandardError>] :error

@option state [Integer] :branched

Parameters:

  • target (Anthropic::Internal::Type::Converter, Class)
  • value (Object)
  • state (Hash{Symbol=>Object}) (defaults to: Anthropic::Internal::Type::Converter.new_coerce_state)

    The ‘strictness` is one of `true`, `false`. This informs the coercion strategy

Returns:

  • (Object)


187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
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
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/anthropic/internal/type/converter.rb', line 187

def coerce(target, value, state: Anthropic::Internal::Type::Converter.new_coerce_state)
  # rubocop:disable Metrics/BlockNesting
  exactness = state.fetch(:exactness)

  case target
  in Anthropic::Internal::Type::Converter
    return target.coerce(value, state: state)
  in Class
    if value.is_a?(target)
      exactness[:yes] += 1
      return value
    end

    case target
    in -> { _1 <= NilClass }
      exactness[value.nil? ? :yes : :maybe] += 1
      return nil
    in -> { _1 <= Integer }
      case value
      in Integer
        exactness[:yes] += 1
        return value
      else
        Kernel.then do
          return Integer(value).tap { exactness[:maybe] += 1 }
        rescue ArgumentError, TypeError => e
          state[:error] = e
        end
      end
    in -> { _1 <= Float }
      if value.is_a?(Numeric)
        exactness[:yes] += 1
        return Float(value)
      else
        Kernel.then do
          return Float(value).tap { exactness[:maybe] += 1 }
        rescue ArgumentError, TypeError => e
          state[:error] = e
        end
      end
    in -> { _1 <= String }
      case value
      in String | Symbol | Numeric
        exactness[value.is_a?(Numeric) ? :maybe : :yes] += 1
        return value.to_s
      in StringIO
        exactness[:yes] += 1
        return value.string
      else
        state[:error] = TypeError.new("#{value.class} can't be coerced into #{String}")
      end
    in -> { _1 <= Date || _1 <= Time }
      Kernel.then do
        return target.parse(value).tap { exactness[:yes] += 1 }
      rescue ArgumentError, TypeError => e
        state[:error] = e
      end
    in -> { _1 <= StringIO } if value.is_a?(String)
      exactness[:yes] += 1
      return StringIO.new(value.b)
    else
    end
  in Symbol
    case value
    in Symbol | String
      if value.to_sym == target
        exactness[:yes] += 1
        return target
      else
        exactness[:maybe] += 1
        return value
      end
    else
      message = "cannot convert non-matching #{value.class} into #{target.inspect}"
      state[:error] = ArgumentError.new(message)
    end
  else
  end

  exactness[:no] += 1
  value
  # rubocop:enable Metrics/BlockNesting
end

.dump(target, value, state: {can_retry: true}) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

Returns:

  • (Object)


282
283
284
285
286
287
288
289
# File 'lib/anthropic/internal/type/converter.rb', line 282

def dump(target, value, state: {can_retry: true})
  case target
  in Anthropic::Internal::Type::Converter
    target.dump(value, state: state)
  else
    Anthropic::Internal::Type::Unknown.dump(value, state: state)
  end
end

.inspect(target, depth:) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • target (Object)
  • depth (Integer)

Returns:

  • (String)


297
298
299
300
301
302
303
304
# File 'lib/anthropic/internal/type/converter.rb', line 297

def inspect(target, depth:)
  case target
  in Anthropic::Internal::Type::Converter
    target.inspect(depth: depth.succ)
  else
    target.inspect
  end
end

.meta_info(type_info, spec) ⇒ Hash{Symbol=>Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • type_info (Hash{Symbol=>Object}, Proc, Anthropic::Internal::Type::Converter, Class)

    .

    @option type_info [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const

    @option type_info [Proc] :enum

    @option type_info [Proc] :union

    @option type_info [Boolean] :“nil?”

  • spec (Hash{Symbol=>Object}, Proc, Anthropic::Internal::Type::Converter, Class)

    .

    @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const

    @option spec [Proc] :enum

    @option spec [Proc] :union

    @option spec [Boolean] :“nil?”

Returns:

  • (Hash{Symbol=>Object})


124
125
126
# File 'lib/anthropic/internal/type/converter.rb', line 124

def meta_info(type_info, spec)
  [spec, type_info].grep(Hash).first.to_h.except(:const, :enum, :union, :nil?)
end

.new_coerce_state(translate_names: true) ⇒ Hash{Symbol=>Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • translate_names (Boolean) (defaults to: true)

Returns:

  • (Hash{Symbol=>Object})


133
134
135
136
137
138
139
140
141
# File 'lib/anthropic/internal/type/converter.rb', line 133

def new_coerce_state(translate_names: true)
  {
    translate_names: translate_names,
    strictness: true,
    exactness: {yes: 0, no: 0, maybe: 0},
    error: nil,
    branched: 0
  }
end

.type_info(spec) ⇒ Proc

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • spec (Hash{Symbol=>Object}, Proc, Anthropic::Internal::Type::Converter, Class)

    .

    @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const

    @option spec [Proc] :enum

    @option spec [Proc] :union

    @option spec [Boolean] :“nil?”

Returns:

  • (Proc)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/anthropic/internal/type/converter.rb', line 86

def type_info(spec)
  case spec
  in Proc
    spec
  in Hash
    type_info(spec.slice(:const, :enum, :union).first&.last)
  in true | false
    -> { Anthropic::Internal::Type::Boolean }
  in Anthropic::Internal::Type::Converter | Class | Symbol
    -> { spec }
  in NilClass | Integer | Float
    -> { spec.class }
  end
end

Instance Method Details

#coerce(value, state:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • value (Object)
  • state (Hash{Symbol=>Object})

    .

    @option state [Boolean] :translate_names

    @option state [Boolean] :strictness

    @option state [HashSymbol=>Object] :exactness

    @option state [Class<StandardError>] :error

    @option state [Integer] :branched

Returns:

  • (Object)


29
# File 'lib/anthropic/internal/type/converter.rb', line 29

def coerce(value, state:) = (raise NotImplementedError)

#dump(value, state:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • value (Object)
  • state (Hash{Symbol=>Object})

    .

    @option state [Boolean] :can_retry

Returns:

  • (Object)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/anthropic/internal/type/converter.rb', line 40

def dump(value, state:)
  case value
  in Array
    value.map { Anthropic::Internal::Type::Unknown.dump(_1, state: state) }
  in Hash
    value.transform_values { Anthropic::Internal::Type::Unknown.dump(_1, state: state) }
  in Anthropic::Internal::Type::BaseModel
    value.class.dump(value, state: state)
  in StringIO
    value.string
  in Pathname | IO
    state[:can_retry] = false if value.is_a?(IO)
    Anthropic::FilePart.new(value)
  in Anthropic::FilePart
    state[:can_retry] = false if value.content.is_a?(IO)
    value
  else
    value
  end
end

#inspect(depth: 0) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • depth (Integer) (defaults to: 0)

Returns:

  • (String)


66
67
68
# File 'lib/anthropic/internal/type/converter.rb', line 66

def inspect(depth: 0)
  super()
end