class Syskit::Actions::Profile

A representation of a set of dependency injections and definition of pre-instanciated models

Attributes

profiles[R]

Set of known profiles

definition_location[R]

The call trace at the time of the profile definition

definitions[R]

The definitions @return [Hash<String,InstanceRequirements>]

dependency_injection[R]

The DependencyInjection object that is being defined in this profile @return [DependencyInjection]

name[R]

The profile name @return [String]

tags[R]

The tags @return [Hash<String,InstanceRequirements>]

used_profiles[R]

The set of profiles that have been used in this profile with {use_profile} @return [Array<Profile>]

Public Class Methods

clear_model() click to toggle source
# File lib/syskit/actions/profile.rb, line 538
def self.clear_model
end
deregister_profile(profile) click to toggle source
# File lib/syskit/actions/profile.rb, line 532
def self.deregister_profile(profile)
    filter_submodels do |pr|
        pr == profile
    end
end
each_submodel() { |profile| ... } click to toggle source

Defined here to make profiles look like models w.r.t. Roby's #clear_model implementation

It enumerates the profiles created so far

# File lib/syskit/actions/profile.rb, line 520
def self.each_submodel
    return enum_for(__method__) if !block_given?
    filter_submodels do |profile|
        yield(profile)
        false
    end
end
filter_submodels() { |obj| ... } click to toggle source

Helper method that allows to iterate over the registered profiles and possibly delete some of them

@yieldparam [Profile] profile @yieldreturn [Boolean] true if this profile should be deleted,

false otherwise
# File lib/syskit/actions/profile.rb, line 505
def self.filter_submodels
    profiles.delete_if do |weakref|
        begin
            obj = weakref.__getobj__
            yield(obj)
        rescue WeakRef::RefError
            true
        end
    end
end
new(name = nil, register: false) click to toggle source
Calls superclass method
# File lib/syskit/actions/profile.rb, line 190
def initialize(name = nil, register: false)
    @name = name
    @permanent_model = false
    @definitions = Hash.new
    @tags = Hash.new
    @used_profiles = Array.new
    @dependency_injection = DependencyInjection.new
    @robot = RobotDefinition.new(self)
    @definition_location = caller_locations
    super()

    if register
        Profile.profiles << WeakRef.new(self)
    end
end
register_profile(profile) click to toggle source
# File lib/syskit/actions/profile.rb, line 528
def self.register_profile(profile)
    profiles << WeakRef.new(profile)
end

Public Instance Methods

all_used_profiles() click to toggle source
# File lib/syskit/actions/profile.rb, line 434
def all_used_profiles
    resolve_used_profiles(Array.new, Set.new)
end
basename() click to toggle source

The profile's basename

# File lib/syskit/actions/profile.rb, line 115
def basename; name.gsub(/.*::/, '') end
clear_model() click to toggle source

Clears this profile of all data, leaving it blank

This is mostly used in Roby's model-reloading procedures

Calls superclass method
# File lib/syskit/actions/profile.rb, line 485
def clear_model
    @robot = Robot::RobotDefinition.new
    definitions.clear
    @dependency_injection = DependencyInjection.new
    used_profiles.clear
    super if defined? super

    if MetaRuby::Registration.accessible_by_name?(self)
        MetaRuby::Registration.deregister_constant(self)
    end

    Profile.deregister_profile(self)
end
define(name, requirements) click to toggle source

Create a new definition based on a given instance requirement object

@param [String] the definition name @param [#to_instance_requirements] requirements the IR object @return [Definition] the added instance requirement

# File lib/syskit/actions/profile.rb, line 345
def define(name, requirements)
    resolved = resolved_dependency_injection.
        direct_selection_for(requirements) || requirements
    doc = MetaRuby::DSLs.parse_documentation_block(
        ->(file) { Roby.app.app_file?(file) }, /^define$/)
    register_definition(name, resolved.to_instance_requirements, doc: doc)
end
definition(name) click to toggle source

Returns the instance requirement object that represents the given definition

@param (see find_definition_by_name) @raise [ArgumentError] if the definition does not exist @see #resolved_definition

# File lib/syskit/actions/profile.rb, line 391
def definition(name)
    if req = find_definition_by_name(name)
        req
    else
        raise ArgumentError, "profile #{self.name} has no definition called #{name}"
    end
end
each_action() { |action_model| ... } click to toggle source

Yield all actions that can be used to access this profile's definitions and devices

@yieldparam [Models::Action] action_model

# File lib/syskit/actions/profile.rb, line 545
def each_action
    return enum_for(__method__) if !block_given?

    robot.each_master_device do |dev|
        action_model = dev.to_action_model
        yield(action_model)
    end

    definitions.each do |name, req|
        action_model = req.to_action_model
        action_model.name = "#{name}_def"
        yield(action_model)
    end
end
each_definition() { |definition| ... } click to toggle source

Enumerate the definitions

@yieldparam [Definition] definition @return [void]

# File lib/syskit/actions/profile.rb, line 375
def each_definition
    return enum_for(__method__) if !block_given?

    definitions.each do |name, definition|
        definition = definition.dup
        definition.name = name
        yield(definition)
    end
end
each_submodel() click to toggle source

Defined here to make profiles look like models w.r.t. Roby's #clear_model implementation

It does nothing

# File lib/syskit/actions/profile.rb, line 106
def each_submodel
end
each_tag(&block) click to toggle source

Enumerate the tags declared on this profile

It never enumerates tags from used profiles

@yieldparam [Models::Tag]

# File lib/syskit/actions/profile.rb, line 220
def each_tag(&block)
    tags.each_value(&block)
end
find_definition_by_name(name) click to toggle source

Returns the instance requirement object that represents the given definition, if there is one

@param [String] name the definition name @return [nil,InstanceRequirements] the object matching the given

name, or nil if there is none

@see definition #resolved_definition

# File lib/syskit/actions/profile.rb, line 406
def find_definition_by_name(name)
    if req = definitions[name]
        req = req.dup
        req.name = name
        req
    end
end
find_device_requirements_by_name(name) click to toggle source

Returns the instance requirements that represent a certain device

@param [String] name @return [InstanceRequirements,nil]

# File lib/syskit/actions/profile.rb, line 581
def find_device_requirements_by_name(name)
    if dev = robot.devices[name]
        dev.to_instance_requirements.dup
    end
end
find_tag(name) click to toggle source

Returns a tag by its name

@param [String] name @return [Tag,nil]

# File lib/syskit/actions/profile.rb, line 569
def find_tag(name)
    tags[name]
end
find_through_method_missing(m, args) click to toggle source
# File lib/syskit/actions/profile.rb, line 595
def find_through_method_missing(m, args)
    MetaRuby::DSLs.find_through_method_missing(
        self, m, args,
        '_tag'.freeze => :find_tag,
        '_def'.freeze => :find_definition_by_name,
        '_dev'.freeze => :find_device_requirements_by_name) || super
end
from(accessor) click to toggle source

Get an argument from a task accessor

The common usage for this is to forward an argument from the task's parent:

define 'test', Composition.use(
  'some_child' => Model.with_arguments(test: from(:parent_task).test))
# File lib/syskit/actions/profile.rb, line 152
def from(accessor)
    Roby::Task.from(accessor)
end
from_state(state_object = State) click to toggle source

Get an argument from a state object

The common usage for this is to access a state variable

define 'test', Composition.use(
  'some_child' => Model.with_arguments(enabled: from_state.enabled?))
# File lib/syskit/actions/profile.rb, line 162
def from_state(state_object = State)
    Roby::Task.from_state(state_object)
end
has_definition?(name) click to toggle source

Test if this profile has a definition with the given name

# File lib/syskit/actions/profile.rb, line 367
def has_definition?(name)
    definitions.has_key?(name)
end
has_device?(name) click to toggle source
# File lib/syskit/actions/profile.rb, line 573
def has_device?(name)
    !!robot.devices[name]
end
has_tag?(name) click to toggle source

Whether a tag with this name exists

# File lib/syskit/actions/profile.rb, line 561
def has_tag?(name)
    !!tags[name]
end
has_through_method_missing?(m) click to toggle source
# File lib/syskit/actions/profile.rb, line 587
def has_through_method_missing?(m)
    MetaRuby::DSLs.has_through_method_missing?(
        self, m,
        '_tag'.freeze => :has_tag?,
        '_def'.freeze => :has_definition?,
        '_dev'.freeze => :has_device?) || super
end
initialize_copy(old) click to toggle source
Calls superclass method
# File lib/syskit/actions/profile.rb, line 461
def initialize_copy(old)
    super
    old.definitions.each do |name, req|
        definitions[name] = req.dup
    end
end
inject_di_context(req) click to toggle source

Injects the DI information registered in this profile in the given instance requirements

@param [InstanceRequirements] req the instance requirement object @return [void]

Calls superclass method
# File lib/syskit/actions/profile.rb, line 455
def inject_di_context(req)
    req.push_dependency_injection(resolved_dependency_injection)
    super if defined? super
    nil
end
invalidate_dependency_injection() click to toggle source

Invalidate the cached dependency inject object

@see #resolved_dependency_injection

# File lib/syskit/actions/profile.rb, line 234
def invalidate_dependency_injection
    @di = nil
end
nothing() click to toggle source

Dependency injection object that signifies “select nothing for this”

This is used to override more generic selections, or to make sure that a compositions' optional child is not present

@example disable the optional 'pose' child of Camera composition

Compositions::Camera.use('pose' => nothing)
# File lib/syskit/actions/profile.rb, line 142
def nothing
    DependencyInjection.nothing
end
promote_requirements(profile, req, tags = Hash.new) click to toggle source

Promote requirements taken from another profile to this profile

@param [Profile] profile the profile the requirements are

originating from

@param [InstanceRequirements] req the instance requirement object @param [{String=>Object}] tags selections for tags in profile,

from the tag name to the selected object

@return [InstanceRequirements] the promoted requirement object. It

might be the same than the req parameter (i.e. it is not
guaranteed to be a copy)
# File lib/syskit/actions/profile.rb, line 272
def promote_requirements(profile, req, tags = Hash.new)
    if req.composition_model?
        req = req.dup
        tags = resolve_tag_selection(profile, tags)
        req.push_selections
        req.use(tags)
    end
    req
end
register_definition(name, requirements, doc: nil) click to toggle source

@api private

Register requirements to a definition name

@return [Definition] the definition object

# File lib/syskit/actions/profile.rb, line 358
def register_definition(name, requirements, doc: nil)
    definition = Definition.new(self, name)
    definition.doc(doc) if doc
    definition.advanced = false
    definition.merge(requirements)
    definitions[name] = definition
end
resolve_tag_selection(profile, tags) click to toggle source

@api private

Resolves the names in the tags argument given to {#use_profile}

# File lib/syskit/actions/profile.rb, line 285
def resolve_tag_selection(profile, tags)
    tags.map_key do |key, _|
        if key.respond_to?(:to_str)
            profile.send("#{key.gsub(/_tag$/, '')}_tag")
        else key
        end
    end
end
resolve_used_profiles(list, set) click to toggle source
# File lib/syskit/actions/profile.rb, line 438
def resolve_used_profiles(list, set)
    new_profiles = used_profiles.find_all do |p, _|
        !set.include?(p)
    end
    list.concat(new_profiles)
    set |= new_profiles.map(&:first).to_set
    new_profiles.each do |p, _|
        p.resolve_used_profiles(list, set)
    end
    list
end
resolved_definition(name) click to toggle source

Returns the instance requirement object that represents the given definition, with all the dependency injection information contained in this profile applied

@param [String] name the definition name @return [InstanceRequirements] the instance requirement

representing the definition

@raise [ArgumentError] if the definition does not exist @see definition

# File lib/syskit/actions/profile.rb, line 423
def resolved_definition(name)
    req = definition(name)

    result = Definition.new(self, name, resolved: true)
    result.merge(req)
    inject_di_context(result)
    result.name = req.name
    result.doc(req.doc)
    result
end
resolved_dependency_injection() click to toggle source

@api private

Resolve the profile's global dependency injection object

This is an internal cache, and is updated as-needed

@see #invalidate_dependency_injection

# File lib/syskit/actions/profile.rb, line 245
def resolved_dependency_injection
    if !@di
        di = DependencyInjectionContext.new
        di.push(robot.to_dependency_injection)
        all_used_profiles.each do |prof, _|
            di.push(prof.dependency_injection)
        end
        di.push(dependency_injection)
        @di = di.current_state
    end
    @di
end
robot(&block) click to toggle source

@overload robot @overload robot { … }

Gets and/or modifies the robot definition of this profile

@return [Syskit::Robot::RobotDefinition] the robot definition

object
# File lib/syskit/actions/profile.rb, line 475
def robot(&block)
    if block_given?
        @robot.instance_eval(&block)
    end
    @robot
end
spacename() click to toggle source

The profile's namespace

# File lib/syskit/actions/profile.rb, line 117
def spacename; name.gsub(/::[^:]*$/, '') end
tag(name, *models) click to toggle source
# File lib/syskit/actions/profile.rb, line 206
def tag(name, *models)
    tags[name] = Syskit.create_proxy_task_model_for(models,
                                                    :extension => Tag,
                                                    :as => "#{self}.#{name}_tag")
    tags[name].tag_name = name
    tags[name].profile = self
    tags[name]
end
to_s() click to toggle source
# File lib/syskit/actions/profile.rb, line 258
def to_s
    "profile:#{name}"
end
use(*args) click to toggle source

Add some dependency injections for the definitions in this profile

# File lib/syskit/actions/profile.rb, line 225
def use(*args)
    invalidate_dependency_injection
    dependency_injection.add(*args)
    self
end
use_profile(profile, tags = Hash.new, transform_names: ->(k) { k }) click to toggle source

Adds the given profile DI information and registered definitions to this one.

If a definitions has the same name in self than in the given profile, the local definition takes precedence

@param [Profile] profile @return [void]

Calls superclass method
# File lib/syskit/actions/profile.rb, line 307
def use_profile(profile, tags = Hash.new, transform_names: ->(k) { k })
    invalidate_dependency_injection
    tags = resolve_tag_selection(profile, tags)
    used_profiles.push([profile, tags])

    # Register the definitions, but let the user override
    # definitions of the given profile locally
    new_definitions = Array.new
    profile.definitions.each do |name, req|
        name = transform_names.call(name)
        req = promote_requirements(profile, req, tags)
        definition = register_definition(name, req, doc: req.doc)
        new_definitions << definition
    end
    new_definitions.concat(robot.use_robot(profile.robot))

    # Now, map possible IR objects or IR-derived Action objects that
    # are present within the arguments
    new_definitions.each do |req|
        rebound_arguments = Hash.new
        req.arguments.each do |name, value|
            if value.respond_to?(:rebind_requirements)
                rebound_arguments[name] = value.rebind_requirements(self)
            end
        end
        req.with_arguments(**rebound_arguments)
    end

    super if defined? super
    new_definitions
end
uses_profile?(profile) click to toggle source

Whether self uses the given profile

# File lib/syskit/actions/profile.rb, line 295
def uses_profile?(profile)
    used_profiles.any? { |used_profile, _| used_profile == profile }
end