Module: XTwitterScraper::Internal::Type::Converter Private

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

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: XTwitterScraper::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 https://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 (XTwitterScraper::Internal::Type::Converter, Class)
  • value (Object)
  • state (Hash{Symbol=>Object}) (defaults to: XTwitterScraper::Internal::Type::Converter.new_coerce_state)

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

Returns:

  • (Object)


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
270
271
272
273
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 191

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

  case target
  in XTwitterScraper::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)


286
287
288
289
290
291
292
293
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 286

def dump(target, value, state: {can_retry: true})
  case target
  in XTwitterScraper::Internal::Type::Converter
    target.dump(value, state: state)
  else
    XTwitterScraper::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)
  • depth: (Integer)

Returns:

  • (String)


301
302
303
304
305
306
307
308
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 301

def inspect(target, depth:)
  case target
  in XTwitterScraper::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, XTwitterScraper::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, XTwitterScraper::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})


128
129
130
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 128

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})


137
138
139
140
141
142
143
144
145
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 137

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, XTwitterScraper::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)


90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 90

def type_info(spec)
  case spec
  in Proc
    spec
  in Hash
    type_info(spec.slice(:const, :enum, :union).first&.last)
  in true | false
    -> { XTwitterScraper::Internal::Type::Boolean }
  in XTwitterScraper::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] :error

    @option state [Integer] :branched

Returns:

  • (Object)


33
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 33

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)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 44

def dump(value, state:)
  case value
  in Array
    value.map { XTwitterScraper::Internal::Type::Unknown.dump(_1, state: state) }
  in Hash
    value.transform_values { XTwitterScraper::Internal::Type::Unknown.dump(_1, state: state) }
  in XTwitterScraper::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)
    XTwitterScraper::FilePart.new(value)
  in XTwitterScraper::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)
  • depth: (Integer) (defaults to: 0)

Returns:

  • (String)


70
71
72
# File 'lib/x_twitter_scraper/internal/type/converter.rb', line 70

def inspect(depth: 0)
  super()
end