Class: Roby::TaskArguments

Inherits:
Object show all
Includes:
Enumerable, DRoby::V5::TaskArgumentsDumper
Defined in:
lib/roby/task_arguments.rb,
lib/roby/droby/enable.rb

Overview

Class that handles task arguments. They are handled specially as the arguments cannot be overwritten and can not be changed by a task that is not owned.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DRoby::V5::TaskArgumentsDumper

#droby_dump

Methods included from Enumerable

#empty?

Constructor Details

#initialize(task) ⇒ TaskArguments

Returns a new instance of TaskArguments.



9
10
11
12
13
14
# File 'lib/roby/task_arguments.rb', line 9

def initialize(task)
    @task   = task
    @static = true
    @values = Hash.new
    super()
end

Instance Attribute Details

#taskObject (readonly)

Returns the value of attribute task.



6
7
8
# File 'lib/roby/task_arguments.rb', line 6

def task
  @task
end

#valuesObject (readonly)

Returns the value of attribute values.



7
8
9
# File 'lib/roby/task_arguments.rb', line 7

def values
  @values
end

Class Method Details

.delayed_argument?(obj) ⇒ Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/roby/task_arguments.rb', line 16

def self.delayed_argument?(obj)
    obj.respond_to?(:evaluate_delayed_argument)
end

Instance Method Details

#==(hash) ⇒ Boolean

True if the arguments are equal

Both proper values and delayed values have to be equal

Returns:

  • (Boolean)


94
95
96
# File 'lib/roby/task_arguments.rb', line 94

def ==(hash)
    to_hash == hash.to_hash
end

#[](key) ⇒ Object



195
196
197
198
199
200
201
# File 'lib/roby/task_arguments.rb', line 195

def [](key)
    key = warn_deprecated_non_symbol_key(key)
    value = values[key]
    if !TaskArguments.delayed_argument?(value)
        value
    end
end

#[]=(key, value) ⇒ Object

Assigns a value to a given argument name

The method validates that writing this argument value is allowed

Raises:

  • OwnershipError if we don’t own the task

  • ArgumentError if the argument is already set



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/roby/task_arguments.rb', line 168

def []=(key, value)
    key = warn_deprecated_non_symbol_key(key)
    if writable?(key, value)
        if !value.droby_marshallable?
            raise NotMarshallable, "values used as task arguments must be marshallable, attempting to set #{key} to #{value} of class #{value.class}, which is not"
        elsif !task.read_write?
            raise OwnershipError, "cannot change the argument set of a task which is not owned #{task} is owned by #{task.owners} and #{task.plan} by #{task.plan.owners}"
        end

        if TaskArguments.delayed_argument?(value)
            @static = false
        elsif values.has_key?(key) && TaskArguments.delayed_argument?(values[key])
            update_static = true
        end

        values[key] = value
        task.plan.log(:task_arguments_updated, task, key, value)

        if update_static
            @static = values.all? { |k, v| !TaskArguments.delayed_argument?(v) }
        end
        value
    else
        raise ArgumentError, "cannot override task argument #{key} as it is already set to #{values[key]}"
    end
end

#assigned?(key) ⇒ Boolean

Tests if a given argument has been assigned, that is either has a static value or has a delayed value object

Returns:

  • (Boolean)


79
80
81
# File 'lib/roby/task_arguments.rb', line 79

def assigned?(key)
    has_key?(key)
end

#assigned_argumentsHash

Returns the set of arguments for which a proper value has been assigned

Returns:

  • (Hash)


115
116
117
118
119
120
121
# File 'lib/roby/task_arguments.rb', line 115

def assigned_arguments
    result = Hash.new
    each_assigned_argument do |k, v|
        result[k] = v
    end
    result
end

#dupObject



72
# File 'lib/roby/task_arguments.rb', line 72

def dup; self.to_hash end

#each(&block) ⇒ Object



133
134
135
# File 'lib/roby/task_arguments.rb', line 133

def each(&block)
    values.each(&block)
end

#each_assigned_argumentObject

Enumerates the arguments that have been explicitly assigned



124
125
126
127
128
129
130
131
# File 'lib/roby/task_arguments.rb', line 124

def each_assigned_argument
    return assigned_arguments if !block_given?
    each do |key, value|
        if !TaskArguments.delayed_argument?(value)
            yield(key, value)
        end
    end
end

#evaluate_delayed_argumentsHash

Returns this argument set, but with the delayed arguments evaluated

Returns:

  • (Hash)


206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/roby/task_arguments.rb', line 206

def evaluate_delayed_arguments
    result = Hash.new
    values.each do |key, val|
        if TaskArguments.delayed_argument?(val)
            catch(:no_value) do
                result[key] = val.evaluate_delayed_argument(task)
            end
        else
            result[key] = val
        end
    end
    result
end

#force_merge!(hash) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
# File 'lib/roby/task_arguments.rb', line 220

def force_merge!(hash)
    if task.plan && task.plan.executable?
        values.merge!(hash) do |k, _, v|
            task.plan.log(:task_arguments_updated, task, k, v)
            v
        end
    else
        values.merge!(hash)
    end
    @static = values.all? { |k, v| !TaskArguments.delayed_argument?(v) }
end

#has_key?(key) ⇒ Boolean

True if an argument with that name is assigned, be it a proper value or a delayed value object

Returns:

  • (Boolean)


40
41
42
# File 'lib/roby/task_arguments.rb', line 40

def has_key?(key)
    values.has_key?(key)
end

#keysObject

The set of argument names that have been assigned so far, either with a proper object or a delayed value object



46
47
48
# File 'lib/roby/task_arguments.rb', line 46

def keys
    values.keys
end

#merge!(**hash) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/roby/task_arguments.rb', line 232

def merge!(**hash)
    hash.each do |key, value|
        if !value.droby_marshallable?
            raise NotMarshallable, "values used as task arguments must be marshallable, attempting to set #{key} to #{value}, which is not"
        end
    end

    values.merge!(hash) do |key, old, new|
        if old == new then old
        elsif writable?(key, new)
            task.plan.log(:task_arguments_updated, task, key, new)
            new
        else
            raise ArgumentError, "cannot override task argument #{key}: trying to replace #{old} by #{new}"
        end
    end
    @static = values.all? { |k, v| !TaskArguments.delayed_argument?(v) }
    self
end

#pretty_print(pp) ⇒ Object

Pretty-prints this argument set



99
100
101
102
103
104
105
# File 'lib/roby/task_arguments.rb', line 99

def pretty_print(pp)
    pp.seplist(values) do |keyvalue|
        key, value = *keyvalue
        pp.text "#{key}: "
        value.pretty_print(pp)
    end
end

#raw_get(key) ⇒ Object

Return the value stored for the given key as-is



34
35
36
# File 'lib/roby/task_arguments.rb', line 34

def raw_get(key)
    values[key]
end

#set?(key) ⇒ Boolean

Tests if a given argument has been set with a proper value (not a delayed value object)

Returns:

  • (Boolean)


85
86
87
# File 'lib/roby/task_arguments.rb', line 85

def set?(key)
    has_key?(key) && !TaskArguments.delayed_argument?(values.fetch(key))
end

#slice(*args) ⇒ Object

Returns the listed set of arguments

Delayed arguments are evaluated before it is sliced

Parameters:

  • args (Array<Symbol>)

    the argument names



68
69
70
# File 'lib/roby/task_arguments.rb', line 68

def slice(*args)
    evaluate_delayed_arguments.slice(*args)
end

#static?Boolean

True if none of the argument values are delayed objects

Returns:

  • (Boolean)


21
22
23
# File 'lib/roby/task_arguments.rb', line 21

def static?
    @static
end

#to_hashObject



73
74
75
# File 'lib/roby/task_arguments.rb', line 73

def to_hash
    values.dup
end

#to_sObject



107
108
109
# File 'lib/roby/task_arguments.rb', line 107

def to_s
    values.sort_by(&:first).map { |k, v| "#{k}: #{v}" }.join(", ")
end

#update!(key, value) ⇒ Object

Updates the given argument, regardless of whether it is allowed or not

Parameters:

  • key (Symbol)

    the argument name

  • value (Object)

    the new argument value

Returns:

See Also:

  • Roby::TaskArguments.{{#writable?}


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/roby/task_arguments.rb', line 143

def update!(key, value)
    if values.has_key?(key)
        current_value = values[key]
        is_updated    = (current_value != value)
        update_static = TaskArguments.delayed_argument?(current_value)
    else is_updated = true
    end

    values[key] = value
    if is_updated
        task.plan.log(:task_arguments_updated, task, key, value)
    end
    if TaskArguments.delayed_argument?(value)
        @static = false
    elsif update_static
        @static = values.all? { |k, v| !TaskArguments.delayed_argument?(v) }
    end
end

#warn_deprecated_non_symbol_key(key) ⇒ Object



25
26
27
28
29
30
31
# File 'lib/roby/task_arguments.rb', line 25

def warn_deprecated_non_symbol_key(key)
    if !key.kind_of?(Symbol)
        Roby.warn_deprecated "accessing arguments using anything else than a symbol is deprecated", 2
        key.to_sym
    else key
    end
end

#writable?(key, value) ⇒ Boolean

True if it is possible to write the given value to the given argument

Parameters:

  • key (Symbol)

    the argument name

  • value (Object)

    the new argument value

Returns:

  • (Boolean)


54
55
56
57
58
59
60
61
# File 'lib/roby/task_arguments.rb', line 54

def writable?(key, value)
    if has_key?(key)
        !task.model.arguments.include?(key) ||
            TaskArguments.delayed_argument?(values[key])
    else
        true
    end
end