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