Module: Yast::Ops

Defined in:
src/ruby/yast/ops.rb

Defined Under Namespace

Classes: GenericComparable, HashComparator, ListComparator

Constant Summary

TYPES_MAP =

map of YCPTypes to ruby types

{
  "any"       => ::Object,
  "nil"       => ::NilClass,
  "void"      => ::NilClass,
  "boolean"   => [::TrueClass, ::FalseClass],
  "string"    => ::String,
  "symbol"    => ::Symbol,
  "integer"   => ::Integer,
  "float"     => ::Float,
  "list"      => ::Array,
  "map"       => ::Hash,
  "term"      => Yast::Term,
  "path"      => Yast::Path,
  "locale"    => ::String,
  "function"  => [Yast::FunRef, Yast::YReference],
  "byteblock" => Yast::Byteblock
}.freeze
SHORTCUT_TYPES =

Types for which we generate shortcut methods, e.g. get_string or Convert.to_string.

[
  "boolean",
  "string",
  "symbol",
  "integer",
  "float",
  "list",
  "map",
  "term",
  "path",
  "locale"
].freeze
OUTER_LOOP_FRAME =

To log the caller frame we need to skip 3 frames as 1 is method itself and each block contributes 2 frames (outer: called, inner: defined) Try for yourself: def a puts caller.inspect [0].each { |i| puts caller.inspect } end a

3

Class Method Summary collapse

Class Method Details

.add(first, second) ⇒ Object

Deprecated.

use ruby native operator +

Adds second to first.



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'src/ruby/yast/ops.rb', line 230

def self.add(first, second)
  return nil if first.nil? || second.nil?

  case first
  when ::Array
    return Yast.deep_copy(first + second) if second.is_a?(::Array)

    Yast.deep_copy(first).push(Yast.deep_copy(second))
  when ::Hash
    Yast.deep_copy(first).merge(Yast.deep_copy(second))
  when ::String
    first + second.to_s
  else
    first + second
  end
end

.bitwise_and(first, second) ⇒ Object

Deprecated.

use ruby native operator &



281
282
283
284
285
# File 'src/ruby/yast/ops.rb', line 281

def self.bitwise_and(first, second)
  return nil if first.nil? || second.nil?

  first & second
end

.bitwise_not(value) ⇒ Object

Deprecated.

use ruby native operator ~



348
349
350
351
352
# File 'src/ruby/yast/ops.rb', line 348

def self.bitwise_not(value)
  return nil if value.nil?

  ~value
end

.bitwise_or(first, second) ⇒ Object

Deprecated.

use ruby native operator |



288
289
290
291
292
# File 'src/ruby/yast/ops.rb', line 288

def self.bitwise_or(first, second)
  return nil if first.nil? || second.nil?

  first | second
end

.bitwise_xor(first, second) ⇒ Object

Deprecated.

use ruby native operator ^



295
296
297
298
299
# File 'src/ruby/yast/ops.rb', line 295

def self.bitwise_xor(first, second)
  return nil if first.nil? || second.nil?

  first ^ second
end

.comparable_object(object, localized = false) ⇒ Object

Creates comparable wrapper that makes ycp compatible comparison



423
424
425
# File 'src/ruby/yast/ops.rb', line 423

def self.comparable_object(object, localized = false)
  GenericComparable.new(object, localized)
end

.divide(first, second) ⇒ Object

Deprecated.

use ruby native operator /

Note:

allows division with zero and in such case return nil

Divides first with second.



266
267
268
269
270
# File 'src/ruby/yast/ops.rb', line 266

def self.divide(first, second)
  return nil if first.nil? || second.nil? || second == 0

  first / second
end

.equal(first, second) ⇒ Object

Deprecated.

use ruby native operator ==



355
356
357
358
359
# File 'src/ruby/yast/ops.rb', line 355

def self.equal(first, second)
  first = comparable_object(first)

  first == second
end

.get(object, indexes, default = nil, skip_frames = 0) ⇒ Object

Deprecated.

Use the native Ruby operator []

Gets value from object at indexes. Eager to return default at slightest provocation.

Replacement

Consider using

  • object[index]
  • object[i1][i2]
  • object[index] || default if the value cannot be false or nil
  • object.fetch(index, default)
  • object.fetch(index) if you want an exception when index is absent

Parameters:

  • object (Array, Hash, Yast::Term)
  • indexes

    Usually a scalar, but also an array of scalars to recursively descend into object

  • default (defaults to: nil)

    the default value returned (via Yast.deep_copy) for any error; if a block is given, it is called to provide the default value (only when the default is needed, so it is useful for values that are expensive to compute).

  • skip_frames (Integer) (defaults to: 0)

    private, how many caller frames to skip when reporting warnings or exceptions

Returns:

  • The value in object at indexes, if it exists. The default value if object, indexes are nil, have wrong type, or indexes does not exist in object.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'src/ruby/yast/ops.rb', line 112

def self.get(object, indexes, default = nil, skip_frames = 0)
  res = object
  default = Yast.deep_copy(default)
  skip_frames += OUTER_LOOP_FRAME
  indexes = [indexes] unless indexes.is_a? ::Array

  indexes.each do |i|
    case res
    when ::Array, Yast::Term
      if i.is_a?(::Integer)
        if (0..res.size - 1).cover? i
          res = res[i]
        else
          Yast.y2milestone skip_frames, "Index #{i} is out of array size"
          return block_given? ? yield : default
        end
      else
        Yast.y2warning skip_frames, "Passed #{i.inspect} as index key for array."
        return block_given? ? yield : default
      end
    when ::Hash
      return block_given? ? yield : default unless res.key?(i)

      res = res[i]
    when ::NilClass
      Yast.y2milestone skip_frames, "Ops.get called on nil."
      return block_given? ? yield : default
    else
      Yast.y2warning skip_frames, "Ops.get called on wrong type #{res.class}"
      return block_given? ? yield : default
    end
  end
  Yast.deep_copy(res)
end

.get_boolean(obj, idx) ⇒ Boolean?

Returns Convert.to_boolean(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_float(obj, idx) ⇒ Float?

Returns Convert.to_float(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_integer(obj, idx) ⇒ Integer?

Returns Convert.to_integer(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_list(obj, idx) ⇒ Array?

Returns Convert.to_list(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_locale(obj, idx) ⇒ String?

Returns Convert.to_locale(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_map(obj, idx) ⇒ Hash?

Returns Convert.to_map(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_path(obj, idx) ⇒ Path?

Returns Convert.to_path(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_string(obj, idx) ⇒ String?

Returns Convert.to_string(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_symbol(obj, idx) ⇒ Symbol?

Returns Convert.to_symbol(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.get_term(obj, idx) ⇒ Term?

Returns Convert.to_term(get(obj, idx, def))

Returns:



68
69
70
71
72
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  define_singleton_method("get_#{type}") do |object, indexes, default=nil, &block|
    Yast::Convert.public_send("to_#{type}", get(object, indexes, default, 1, &block))
  end
end

.greater_or_equal(first, second) ⇒ Object

Deprecated.

use ruby native operator >=



396
397
398
399
400
401
402
# File 'src/ruby/yast/ops.rb', line 396

def self.greater_or_equal(first, second)
  return nil if first.nil? || second.nil?

  first = comparable_object(first)

  first >= second
end

.greater_than(first, second) ⇒ Object

Deprecated.

use ruby native operator >



387
388
389
390
391
392
393
# File 'src/ruby/yast/ops.rb', line 387

def self.greater_than(first, second)
  return nil if first.nil? || second.nil?

  first = comparable_object(first)

  first > second
end

.is(object, type) ⇒ Object

Checks if object is given YCP type. There is also shorfcuts for most of types in format is_



412
413
414
415
416
417
418
419
420
# File 'src/ruby/yast/ops.rb', line 412

def self.is(object, type)
  type = "function" if type =~ /\(.*\)/ # reference to function
  type = type.gsub(/<.*>/, "")
  type = type.gsub(/\s+/, "")
  classes = TYPES_MAP[type]
  raise "Invalid type to detect in is '#{type}'" unless classes
  classes = [classes] unless classes.is_a? ::Array
  classes.any? { |cl| object.is_a? cl }
end

.less_or_equal(first, second) ⇒ Object

Deprecated.

use ruby native operator <=



378
379
380
381
382
383
384
# File 'src/ruby/yast/ops.rb', line 378

def self.less_or_equal(first, second)
  return nil if first.nil? || second.nil?

  first = comparable_object(first)

  first <= second
end

.less_than(first, second) ⇒ Object

Deprecated.

use ruby native operator <



369
370
371
372
373
374
375
# File 'src/ruby/yast/ops.rb', line 369

def self.less_than(first, second)
  return nil if first.nil? || second.nil?

  first = comparable_object(first)

  first < second
end

.logical_and(first, second) ⇒ Object

Deprecated.

use ruby native operator &&



316
317
318
319
320
321
# File 'src/ruby/yast/ops.rb', line 316

def self.logical_and(first, second)
  first = false if first.nil?
  second = false if second.nil?

  first && second
end

.logical_not(value) ⇒ Object

Deprecated.

use ruby native operator !

Note:

for nil returns nil to be compatible with ycp implementation



340
341
342
343
344
345
# File 'src/ruby/yast/ops.rb', line 340

def self.logical_not(value)
  # Yast really do it!!!
  return nil if value.nil?

  !value
end

.logical_or(first, second) ⇒ Object

Deprecated.

use ruby native operator ||



324
325
326
327
328
329
# File 'src/ruby/yast/ops.rb', line 324

def self.logical_or(first, second)
  first = false if first.nil?
  second = false if second.nil?

  first || second
end

.modulo(first, second) ⇒ Object

Deprecated.

use ruby native operator %

Computes module after division of first with second.



274
275
276
277
278
# File 'src/ruby/yast/ops.rb', line 274

def self.modulo(first, second)
  return nil if first.nil? || second.nil?

  first % second
end

.multiply(first, second) ⇒ Object

Deprecated.

use ruby native operator *

Multiplies first with second.



257
258
259
260
261
# File 'src/ruby/yast/ops.rb', line 257

def self.multiply(first, second)
  return nil if first.nil? || second.nil?

  first * second
end

.not_equal(first, second) ⇒ Object

Deprecated.

use ruby native operator !=



362
363
364
365
366
# File 'src/ruby/yast/ops.rb', line 362

def self.not_equal(first, second)
  first = comparable_object(first)

  first != second
end

.set(object, indexes, value) ⇒ void

Deprecated.

Use the native Ruby operator []=

This method returns an undefined value.

Sets value to object at given indexes.

If object or indexes is nil, set does nothing.

If indexes is an Array, set recursively descends through all but last indexes to find the destination container. As expected, if the last index does not exist, object is assigned. However, if an intermediate index does not exist, object is not asigned (no Perl-like autovivification).

Replacement

Ops.set(object, indexes, value) can be mechanically replaced by object[indexes] = value if all conditions below are met

  • object is a non-nil Array, Hash, Term
  • indexes is a non-nil scalar
  • value does not need Yast.deep_copy

Idiomatic Replacement

If you want cleaner code and are ready to rescue exceptions, this applies:

  • object will simply raise an error if it cannot handle []=; that works as expected.
  • If indexes is an Array of the form [i, j, k], use object[i][j][k] = value. Missing indexes will become nil and raise an exception on the next index.
  • value may need a deep copy: object[indexes] = deep_copy(value)


184
185
186
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
# File 'src/ruby/yast/ops.rb', line 184

def self.set(object, indexes, value)
  return if indexes.nil? || object.nil?

  indexes = [indexes] unless indexes.is_a? ::Array
  last = indexes.pop
  res = object

  # return here is needed for quick exit of method and workaround with any or
  # all is nasty and decrease readability
  # rubocop:disable Lint/NonLocalExitFromIterator
  indexes.each do |i|
    case res
    when ::Array, Yast::Term
      if !i.is_a?(::Integer)
        Yast.y2warning OUTER_LOOP_FRAME, "Passed #{i.inspect} as index key for array."
        return
      end

      if !(0..res.size - 1).cover?(i)
        Yast.y2warning OUTER_LOOP_FRAME, "Index #{i} is out of array size"
        return
      end

      res = res[i]
    when ::Hash
      return unless res.key? i

      res = res[i]
    else
      Yast.y2warning OUTER_LOOP_FRAME, "Builtin assign called on wrong type #{res.class}"
      return
    end
  end
  # rubocop:enable Lint/NonLocalExitFromIterator

  case res
  when ::Array, Yast::Term, ::Hash
    res[last] = Yast.deep_copy(value)
  else
    # log is not in loop, so use simple 1 to get outside of method
    Yast.y2warning 1, "Builtin assign called on wrong type #{res.class}"
  end
end

.shift_left(first, second) ⇒ Object

Deprecated.

use ruby native operator <<



302
303
304
305
306
# File 'src/ruby/yast/ops.rb', line 302

def self.shift_left(first, second)
  return nil if first.nil? || second.nil?

  first << second
end

.shift_right(first, second) ⇒ Object

Deprecated.

use ruby native operator >>



309
310
311
312
313
# File 'src/ruby/yast/ops.rb', line 309

def self.shift_right(first, second)
  return nil if first.nil? || second.nil?

  first >> second
end

.subtract(first, second) ⇒ Object

Deprecated.

use ruby native operator -

Subtracts second from first.



249
250
251
252
253
# File 'src/ruby/yast/ops.rb', line 249

def self.subtract(first, second)
  return nil if first.nil? || second.nil?

  first - second
end

.unary_minus(value) ⇒ Object

Deprecated.

use ruby native operator -



332
333
334
335
336
# File 'src/ruby/yast/ops.rb', line 332

def self.unary_minus(value)
  return nil if value.nil?

  -value
end