class Puppet::Pops::Types::ClassLoader
The ClassLoader provides a Class instance given a class name or a meta-type. If the class is not already loaded, it is loaded using the Puppet Autoloader. This means it can load a class from a gem, or from puppet modules.
Public Class Methods
provide(name)
click to toggle source
Returns a Class given a fully qualified class name. Lookup of class is never relative to the calling namespace. @param name [String, Array<String>, Array<Symbol>, PAnyType] A fully qualified
class name String (e.g. '::Foo::Bar', 'Foo::Bar'), a PAnyType, or a fully qualified name in Array form where each part
is either a String or a Symbol, e.g. `%w{Puppetx Puppetlabs SomeExtension}`.
@return [Class, nil] the looked up class or nil if no such class is loaded @raise ArgumentError If the given argument has the wrong type @api public
# File lib/puppet/pops/types/class_loader.rb 20 def self.provide(name) 21 case name 22 when String 23 provide_from_string(name) 24 25 when Array 26 provide_from_name_path(name.join('::'), name) 27 28 when PAnyType, PTypeType 29 provide_from_type(name) 30 31 else 32 raise ArgumentError, "Cannot provide a class from a '#{name.class.name}'" 33 end 34 end
provide_from_name_path(name, name_path)
click to toggle source
# File lib/puppet/pops/types/class_loader.rb 83 def self.provide_from_name_path(name, name_path) 84 # If class is already loaded, try this first 85 result = find_class(name_path) 86 87 unless result.is_a?(Module) 88 # Attempt to load it using the auto loader 89 loaded_path = nil 90 if paths_for_name(name_path).find {|path| loaded_path = path; @autoloader.load(path, Puppet.lookup(:current_environment)) } 91 result = find_class(name_path) 92 unless result.is_a?(Module) 93 raise RuntimeError, "Loading of #{name} using relative path: '#{loaded_path}' did not create expected class" 94 end 95 end 96 end 97 return nil unless result.is_a?(Module) 98 result 99 end
Private Class Methods
de_camel(fq_name)
click to toggle source
# File lib/puppet/pops/types/class_loader.rb 122 def self.de_camel(fq_name) 123 fq_name.to_s.gsub(/::/, '/'). 124 gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 125 gsub(/([a-z\d])([A-Z])/,'\1_\2'). 126 tr("-", "_"). 127 downcase 128 end
find_class(name_path)
click to toggle source
# File lib/puppet/pops/types/class_loader.rb 102 def self.find_class(name_path) 103 name_path.reduce(Object) do |ns, name| 104 begin 105 ns.const_get(name, false) # don't search ancestors 106 rescue NameError 107 return nil 108 end 109 end 110 end
paths_for_name(fq_named_parts)
click to toggle source
# File lib/puppet/pops/types/class_loader.rb 113 def self.paths_for_name(fq_named_parts) 114 # search two entries, one where all parts are decamelized, and one with names just downcased 115 # TODO:this is not perfect - it will not produce the correct mix if a mix of styles are used 116 # The alternative is to test many additional paths. 117 # 118 [fq_named_parts.map {|part| de_camel(part)}.join('/'), fq_named_parts.join('/').downcase ] 119 end
provide_from_string(name)
click to toggle source
# File lib/puppet/pops/types/class_loader.rb 76 def self.provide_from_string(name) 77 name_path = name.split(TypeFormatter::NAME_SEGMENT_SEPARATOR) 78 # always from the root, so remove an empty first segment 79 name_path.shift if name_path[0].empty? 80 provide_from_name_path(name, name_path) 81 end
provide_from_type(type)
click to toggle source
# File lib/puppet/pops/types/class_loader.rb 36 def self.provide_from_type(type) 37 case type 38 when PRuntimeType 39 raise ArgumentError.new("Only Runtime type 'ruby' is supported, got #{type.runtime}") unless type.runtime == :ruby 40 provide_from_string(type.runtime_type_name) 41 42 when PBooleanType 43 # There is no other thing to load except this Enum meta type 44 RGen::MetamodelBuilder::MMBase::Boolean 45 46 when PTypeType 47 # TODO: PTypeType should have a type argument (a PAnyType) so the Class' class could be returned 48 # (but this only matters in special circumstances when meta programming has been used). 49 Class 50 51 when POptionalType 52 # cannot make a distinction between optional and its type 53 provide_from_type(type.optional_type) 54 55 # Although not expected to be the first choice for getting a concrete class for these 56 # types, these are of value if the calling logic just has a reference to type. 57 # 58 when PArrayType ; Array 59 when PTupleType ; Array 60 when PHashType ; Hash 61 when PStructType ; Hash 62 when PRegexpType ; Regexp 63 when PIntegerType ; Integer 64 when PStringType ; String 65 when PPatternType ; String 66 when PEnumType ; String 67 when PFloatType ; Float 68 when PUndefType ; NilClass 69 when PCallableType ; Proc 70 else 71 nil 72 end 73 end