class Puppet::Pops::Types::PObjectTypeExtension

Base class for Parameterized Object implementations. The wrapper impersonates the base object and extends it with methods to filter assignable types and instances based on parameter values.

@api public

Attributes

base_type[R]
parameters[R]

Public Class Methods

create(base_type, init_parameters) click to toggle source

@api private

   # File lib/puppet/pops/types/p_object_type_extension.rb
26 def self.create(base_type, init_parameters)
27   impl_class = Loaders.implementation_registry.module_for_type("#{base_type.name}TypeExtension") || self
28   impl_class.new(base_type, init_parameters)
29 end
create_from_instance(base_type, instance) click to toggle source

Creates an array of type parameters from the attributes of the given instance that matches the type parameters by name. Type parameters for which there is no matching attribute will have `nil` in their corresponding position on the array. The array is then passed as the `init_parameters` argument in a call to `create`

@return [PObjectTypeExtension] the created extension @api private

   # File lib/puppet/pops/types/p_object_type_extension.rb
38 def self.create_from_instance(base_type, instance)
39   type_parameters = base_type.type_parameters(true)
40   attrs = base_type.attributes(true)
41   params = type_parameters.keys.map do |pn|
42     attr = attrs[pn]
43     attr.nil? ? nil : instance.send(pn)
44   end
45   create(base_type, params)
46 end
new(base_type, init_parameters) click to toggle source

@api private

   # File lib/puppet/pops/types/p_object_type_extension.rb
53 def initialize(base_type, init_parameters)
54   pts = base_type.type_parameters(true)
55   raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using []') % { label: base_type.label } if pts.empty?
56   @base_type = base_type
57 
58   named_args = init_parameters.size == 1 && init_parameters[0].is_a?(Hash)
59   if named_args
60     # Catch case when first parameter is an assignable Hash
61     named_args = pts.size >= 1 && !pts.values[0].type.instance?(init_parameters[0])
62   end
63 
64   by_name = {}
65   if named_args
66     hash = init_parameters[0]
67     hash.each_pair do |pn, pv|
68       tp = pts[pn]
69       if tp.nil?
70         raise Puppet::ParseError, _("'%{pn}' is not a known type parameter for %{label}-Type") % { pn: pn, label: base_type.label }
71       end
72       by_name[pn] = check_param(tp, pv) unless pv == :default
73     end
74   else
75     pts.values.each_with_index do |tp, idx|
76       if idx < init_parameters.size
77         pv = init_parameters[idx]
78         by_name[tp.name] = check_param(tp, pv) unless pv == :default
79       end
80     end
81   end
82   if by_name.empty?
83     raise Puppet::ParseError, _('The %{label}-Type cannot be parameterized using an empty parameter list') % { label: base_type.label }
84   end
85   @parameters = by_name
86 end
register_ptype(loader, ir) click to toggle source
   # File lib/puppet/pops/types/p_object_type_extension.rb
12 def self.register_ptype(loader, ir)
13   create_ptype(loader, ir, 'AnyType',
14     'base_type' => {
15       KEY_TYPE => PTypeType::DEFAULT
16     },
17     'init_parameters' => {
18       KEY_TYPE => PArrayType::DEFAULT
19     }
20   )
21 end

Public Instance Methods

[](name) click to toggle source
   # File lib/puppet/pops/types/p_object_type_extension.rb
48 def [](name)
49   @base_type[name]
50 end
check_param(type_param, v) click to toggle source
   # File lib/puppet/pops/types/p_object_type_extension.rb
88 def check_param(type_param, v)
89   TypeAsserter.assert_instance_of(nil, type_param.type, v) { type_param.label }
90 end
check_self_recursion(originator) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
132 def check_self_recursion(originator)
133   @base_type.check_self_recursion(originator)
134 end
create(*args) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
137 def create(*args)
138   @base_type.create(*args)
139 end
eql?(o) click to toggle source

@api private

Calls superclass method
    # File lib/puppet/pops/types/p_object_type_extension.rb
112 def eql?(o)
113   super(o) && @base_type.eql?(o.base_type) && @parameters.eql?(o.parameters)
114 end
generalize() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
117 def generalize
118   @base_type
119 end
hash() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
122 def hash
123   @base_type.hash ^ @parameters.hash
124 end
implementation_class(create = true) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
157 def implementation_class(create = true)
158   @base_type.implementation_class(create)
159 end
init_parameters() click to toggle source

Return the parameter values as positional arguments with unset values as :default. The array is stripped from trailing :default values @return [Array] the parameter values @api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
 96 def init_parameters
 97   pts = @base_type.type_parameters(true)
 98   if pts.size > 2
 99     @parameters
100   else
101     result = pts.values.map do |tp|
102       pn = tp.name
103       @parameters.include?(pn) ? @parameters[pn] : :default
104     end
105     # Remove trailing defaults
106     result.pop while result.last == :default
107     result
108   end
109 end
instance?(o, guard = nil) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
142 def instance?(o, guard = nil)
143   @base_type.instance?(o, guard) && test_instance?(o, guard)
144 end
loader() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
127 def loader
128   @base_type.loader
129 end
new_function() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
147 def new_function
148   @base_type.new_function
149 end
parameter_info(impl_class) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
162 def parameter_info(impl_class)
163   @base_type.parameter_info(impl_class)
164 end
simple_name() click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
152 def simple_name
153   @base_type.simple_name
154 end

Protected Instance Methods

_assignable?(o, guard = nil) click to toggle source

@api private

    # File lib/puppet/pops/types/p_object_type_extension.rb
219 def _assignable?(o, guard = nil)
220   if o.is_a?(PObjectTypeExtension)
221     @base_type.assignable?(o.base_type, guard) && test_assignable?(o.parameters, guard)
222   else
223     @base_type.assignable?(o, guard) && test_assignable?(EMPTY_HASH, guard)
224   end
225 end
test_assignable?(param_values, guard) click to toggle source

Checks that the given `param_values` hash contains all keys present in the `parameters` of this instance and that each keyed value is a match for the given parameter. The match is done using case expression semantics.

This method is only called when a given type is found to be assignable to the base type of this extension.

@param param_values the parameter values of the assignable type @param guard guard against endless recursion @return [Boolean] true or false to indicate assignability @api public

    # File lib/puppet/pops/types/p_object_type_extension.rb
179 def test_assignable?(param_values, guard)
180   # Default implementation performs case expression style matching of all parameter values
181   # provided that the value exist (this should always be the case, since all defaults have
182   # been assigned at this point)
183   eval = Parser::EvaluatingParser.singleton.evaluator
184   @parameters.keys.all? do |pn|
185     if param_values.include?(pn)
186       a = param_values[pn]
187       b = @parameters[pn]
188       eval.match?(a, b) || a.is_a?(PAnyType) && b.is_a?(PAnyType) && b.assignable?(a)
189     else
190       false
191     end
192   end
193 end
test_instance?(o, guard) click to toggle source

Checks that the given instance `o` has one attribute for each key present in the `parameters` of this instance and that each attribute value is a match for the given parameter. The match is done using case expression semantics.

This method is only called when the given value is found to be an instance of the base type of this extension.

@param o [Object] the instance to test @param guard guard against endless recursion @return [Boolean] true or false to indicate if the value is an instance or not @api public

    # File lib/puppet/pops/types/p_object_type_extension.rb
206 def test_instance?(o, guard)
207   eval = Parser::EvaluatingParser.singleton.evaluator
208   @parameters.keys.all? do |pn|
209     begin
210       m = o.public_method(pn)
211       m.arity == 0 ? eval.match?(m.call, @parameters[pn]) : false
212     rescue NameError
213       false
214     end
215   end
216 end