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.



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

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 &



283
284
285
286
287
# File 'src/ruby/yast/ops.rb', line 283

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 ~



350
351
352
353
354
# File 'src/ruby/yast/ops.rb', line 350

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

  ~value
end

.bitwise_or(first, second) ⇒ Object

Deprecated.

use ruby native operator |



290
291
292
293
294
# File 'src/ruby/yast/ops.rb', line 290

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 ^



297
298
299
300
301
# File 'src/ruby/yast/ops.rb', line 297

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



425
426
427
# File 'src/ruby/yast/ops.rb', line 425

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.



268
269
270
271
272
# File 'src/ruby/yast/ops.rb', line 268

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 ==



357
358
359
360
361
# File 'src/ruby/yast/ops.rb', line 357

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.



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
146
147
# File 'src/ruby/yast/ops.rb', line 114

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
73
74
# File 'src/ruby/yast/ops.rb', line 68

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_float(obj, idx) ⇒ Float?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_integer(obj, idx) ⇒ Integer?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_list(obj, idx) ⇒ Array?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_locale(obj, idx) ⇒ String?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_map(obj, idx) ⇒ Hash?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_path(obj, idx) ⇒ Path?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_string(obj, idx) ⇒ String?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_symbol(obj, idx) ⇒ Symbol?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.get_term(obj, idx) ⇒ Term?

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

Returns:



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

Ops::SHORTCUT_TYPES.each do |type|
  eval <<END, binding, __FILE__, __LINE__ + 1
    def self.get_#{type}(object, indexes, default=nil, &block)
      Yast::Convert.to_#{type} get(object, indexes, default, 1, &block)
    end
END
end

.greater_or_equal(first, second) ⇒ Object

Deprecated.

use ruby native operator >=



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

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 >



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

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_



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

def self.is(object, type)
  type = "function" if type =~ /\(.*\)/ # reference to function
  type.gsub!(/<.*>/, "")
  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 <=



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

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 <



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

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 &&



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

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



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

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



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

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.



276
277
278
279
280
# File 'src/ruby/yast/ops.rb', line 276

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.



259
260
261
262
263
# File 'src/ruby/yast/ops.rb', line 259

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 !=



364
365
366
367
368
# File 'src/ruby/yast/ops.rb', line 364

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)


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

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



304
305
306
307
308
# File 'src/ruby/yast/ops.rb', line 304

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



311
312
313
314
315
# File 'src/ruby/yast/ops.rb', line 311

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.



251
252
253
254
255
# File 'src/ruby/yast/ops.rb', line 251

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

  first - second
end

.unary_minus(value) ⇒ Object

Deprecated.

use ruby native operator -



334
335
336
337
338
# File 'src/ruby/yast/ops.rb', line 334

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

  -value
end