The base class for all Puppet types.
A type describes:
@todo Don’t know if this is a name, or a reference to a Provider instance (now marked up as an instance
of Provider.
@return [Puppet::Provider, nil] The default provider for this type, or nil if non is defines
The reference to a parent type for the parameter `:provider` used to get a list of providers for documentation purposes.
@return [Array<Puppet::Property>] The list of declared properties for the resource type. The returned lists contains instances if Puppet::Property or its subclasses.
The loader of providers to use when loading providers from disk. Although it looks like this attribute provides a way to operate with different loaders of providers that is not the case; the attribute is written when a new type is created, and should not be changed thereafter. @api private
@todo what does this mean “this resource” (sounds like this if for an instance of the type, not the meta Type),
but not sure if this is about the catalog where the meta Type is included)
@return [??? TODO] The catalog that this resource is stored in.
The noop attribute of WHAT ??? does WHAT??? @todo Figure out what this is the noop attribute of (it appears on line 1931 currently). @return [???] the noop WHAT ??? (mode? if so of what, or noop for an instance of the type, or for all
instances of a type, or for what???
The provider that has been selected for the instance of the resource type. @return [Puppet::Provider,nil] the selected provider or nil, if none has been selected
Returns all the attribute names of the type in the appropriate order. The {key_attributes} come first, then the {provider}, then the {properties}, and finally the {parameters} and {metaparams}, all in the order they were specified in the respective files. @return [Array<String>] all type attribute names in a defined order.
# File lib/puppet/type.rb, line 117 def self.allattrs key_attributes | (parameters & [:provider]) | properties.collect { |property| property.name } | parameters | metaparams end
Makes this type apply to `:host` if not already applied to something else. @return [Symbol] a `:device`, `:host`, or `:both` enumeration @api private
# File lib/puppet/type.rb, line 245 def self.apply_to @apply_to ||= :host end
Makes this type applicable to `:both` (i.e. `:host` and `:device`). @return [Symbol] Returns `:both` @api private
# File lib/puppet/type.rb, line 238 def self.apply_to_all @apply_to = :both end
@comment These `apply_to` methods are horrible. They should really be implemented
as part of the usual system of constraints that apply to a type and provider pair, but were implemented as a separate shadow system.
@comment We should rip them out in favour of a real constraint pattern around the
target device - whatever that looks like - and not have this additional magic here. --daniel 2012-03-08
Makes this type applicable to `:device`. @return [Symbol] Returns `:device` @api private
# File lib/puppet/type.rb, line 222 def self.apply_to_device @apply_to = :device end
Makes this type applicable to `:host`. @return [Symbol] Returns `:host` @api private
# File lib/puppet/type.rb, line 230 def self.apply_to_host @apply_to = :host end
Returns the class associated with the given attribute name. @param name [String] the name of the attribute to obtain the class for @return [Class, nil] the class for the given attribute, or nil if the name does not refer to an existing attribute
# File lib/puppet/type.rb, line 125 def self.attrclass(name) @attrclasses ||= {} # We cache the value, since this method gets called such a huge number # of times (as in, hundreds of thousands in a given run). unless @attrclasses.include?(name) @attrclasses[name] = case self.attrtype(name) when :property; @validproperties[name] when :meta; @@metaparamhash[name] when :param; @paramhash[name] end end @attrclasses[name] end
Returns the attribute type (`:property`, `;param`, `:meta`). @comment What type of parameter are we dealing with? Cache the results, because
this method gets called so many times.
@return [Symbol] a symbol describing the type of attribute (`:property`, `;param`, `:meta`)
# File lib/puppet/type.rb, line 145 def self.attrtype(attr) @attrtypes ||= {} unless @attrtypes.include?(attr) @attrtypes[attr] = case when @validproperties.include?(attr); :property when @paramhash.include?(attr); :param when @@metaparamhash.include?(attr); :meta end end @attrtypes[attr] end
Adds a block producing a single name (or list of names) of the given resource type name to autorequire. @example Autorequire the files File[‘foo’, ‘bar’]
autorequire( 'file', {|| ['foo', 'bar'] })
@todo original = _“Specify a block for generating a list of objects to autorequire.
This makes it so that you don't have to manually specify things that you clearly require."_
@param name [String] the name of a type of which one or several resources should be autorequired e.g. “file” @yield [ ] a block returning list of names of given type to auto require @yieldreturn [String, Array<String>] one or several resource names for the named type @return [void] @dsl type @api public
# File lib/puppet/type.rb, line 1926 def self.autorequire(name, &block) @autorequires ||= {} @autorequires[name] = block end
Returns true if this type is applicable to the given target. @param target [Symbol] should be :device, :host or :target, if anything else, :host is enforced @return [Boolean] true @api private
# File lib/puppet/type.rb, line 254 def self.can_apply_to(target) [ target == :device ? :device : :host, :both ].include?(apply_to) end
The default provider, or the most suitable provider if no default provider was set. @note a warning will be issued if no default provider has been configured and a search for the most
suitable provider returns more than one equally suitable provider.
@return [Puppet::Provider, nil] the default or most suitable provider, or nil if no provider was found
# File lib/puppet/type.rb, line 1646 def self.defaultprovider return @defaultprovider if @defaultprovider suitable = suitableprovider # Find which providers are a default for this system. defaults = suitable.find_all { |provider| provider.default? } # If we don't have any default we use suitable providers defaults = suitable if defaults.empty? max = defaults.collect { |provider| provider.specificity }.max defaults = defaults.find_all { |provider| provider.specificity == max } if defaults.length > 1 Puppet.warning( "Found multiple default providers for #{self.name}: #{defaults.collect { |i| i.name.to_s }.join(", ")}; using #{defaults[0].name}" ) end @defaultprovider = defaults.shift unless defaults.empty? end
Provides the ability to add documentation to a provider.
# File lib/puppet/type.rb, line 1800 def self.doc # Since we're mixing @doc with text from other sources, we must normalize # its indentation with scrub. But we don't need to manually scrub the # provider's doc string, since markdown_definitionlist sanitizes its inputs. scrub(@doc) + "Available providers are:\n\n" + parenttype.providers.sort { |a,b| a.to_s <=> b.to_s }.collect { |i| markdown_definitionlist( i, scrub(parenttype().provider(i).doc) ) }.join end
Provides iteration over added auto-requirements (see {autorequire}). @yieldparam type [String] the name of the type to autoriquire an instance of @yieldparam block [Proc] a block producing one or several dependencies to auto require (see {autorequire}). @yieldreturn [void] @return [void]
# File lib/puppet/type.rb, line 1936 def self.eachautorequire @autorequires ||= {} @autorequires.each { |type, block| yield(type, block) } end
Provides iteration over meta-parameters. @yieldparam p [Puppet::Parameter] each meta parameter @return [void]
# File lib/puppet/type.rb, line 162 def self.eachmetaparam @@metaparams.each { |p| yield p.name } end
Creates a new `ensure` property with configured default values or with configuration by an optional block. This method is a convenience method for creating a property `ensure` with default accepted values. If no block is specified, the new `ensure` property will accept the default symbolic values `:present`, and `:absent` - see {Puppet::Property::Ensure}. If something else is wanted, pass a block and make calls to {Puppet::Property.newvalue} from this block to define each possible value. If a block is passed, the defaults are not automatically added to the set of valid values.
@note This method will be automatically called without a block if the type implements the methods
specified by {ensurable?}. It is recommended to always call this method and not rely on this automatic specification to clearly state that the type is ensurable.
@overload ensurable() @overload ensurable({|| … }) @yield [ ] A block evaluated in scope of the new Parameter @yieldreturn [void] @return [void] @dsl type @api public
# File lib/puppet/type.rb, line 186 def self.ensurable(&block) if block_given? self.newproperty(:ensure, :parent => Puppet::Property::Ensure, &block) else self.newproperty(:ensure, :parent => Puppet::Property::Ensure) do self.defaultvalues end end end
Returns true if the type implements the default behavior expected by being ensurable “by default”. A type is ensurable by default if it responds to `:exists`, `:create`, and `:destroy`. If a type implements these methods and have not already specified that it is ensurable, it will be made so with the defaults specified in {ensurable}. @return [Boolean] whether the type is ensurable or not.
# File lib/puppet/type.rb, line 202 def self.ensurable? # If the class has all three of these methods defined, then it's # ensurable. [:exists?, :create, :destroy].all? { |method| self.public_method_defined?(method) } end
Processes the options for a named parameter. @param name [String] the name of a parameter @param options [Hash] a hash of options @option options [Boolean] :boolean if option set to true, an access method on the form name? is added for the param @return [void]
# File lib/puppet/type.rb, line 264 def self.handle_param_options(name, options) # If it's a boolean parameter, create a method to test the value easily if options[:boolean] define_method(name.to_s + "?") do val = self[name] if val == :true or val == true return true end end end end
Converts a simple hash into a Resource instance. @todo as opposed to a complex hash? Other raised exceptions? @param [Hash{Symbol, String => Object}] resource attribute to value map to initialize the created resource from @return [Puppet::Resource] the resource created from the hash @raise [Puppet::Error] if a title is missing in the given hash
# File lib/puppet/type.rb, line 1144 def self.hash2resource(hash) hash = hash.inject({}) { |result, ary| result[ary[0].to_sym] = ary[1]; result } title = hash.delete(:title) title ||= hash[:name] title ||= hash[key_attributes.first] if key_attributes.length == 1 raise Puppet::Error, "Title or name must be provided" unless title # Now create our resource. resource = Puppet::Resource.new(self.name, title) [:catalog].each do |attribute| if value = hash[attribute] hash.delete(attribute) resource.send(attribute.to_s + "=", value) end end hash.each do |param, value| resource[param] = value end resource end
Initializes all of the variables that must be initialized for each subclass. @todo Does the explanation make sense? @return [void]
# File lib/puppet/type.rb, line 2056 def self.initvars # all of the instances of this class @objects = Hash.new @aliases = Hash.new @defaults = {} @parameters ||= [] @validproperties = {} @properties = [] @parameters = [] @paramhash = {} @paramdoc = Hash.new { |hash,key| key = key.intern if key.is_a?(String) if hash.include?(key) hash[key] else "Param Documentation for #{key} not found" end } @doc ||= "" end
Retrieves all known instances. @todo Retrieves them from where? Known to whom? Either requires providers or must be overridden. @raise [Puppet::DevError] when there are no providers and the implementation has not overridded this method.
# File lib/puppet/type.rb, line 1094 def self.instances raise Puppet::DevError, "#{self.name} has no providers and has not overridden 'instances'" if provider_hash.empty? # Put the default provider first, then the rest of the suitable providers. provider_instances = {} providers_by_source.collect do |provider| all_properties = self.properties.find_all do |property| provider.supports_parameter?(property) end.collect do |property| property.name end provider.instances.collect do |instance| # We always want to use the "first" provider instance we find, unless the resource # is already managed and has a different provider set if other = provider_instances[instance.name] Puppet.debug "%s %s found in both %s and %s; skipping the %s version" % [self.name.to_s.capitalize, instance.name, other.class.name, instance.class.name, instance.class.name] next end provider_instances[instance.name] = instance result = new(:name => instance.name, :provider => instance) properties.each { |name| result.newattr(name) } result end end.flatten.compact end
Returns true if the type’s notion of name is the identity of a resource. See the overview of this class for a longer explanation of the concept isomorphism. Defaults to true.
@return [Boolan] true, if this type’s name is isomorphic with the object
# File lib/puppet/type.rb, line 862 def self.isomorphic? if defined?(@isomorphic) return @isomorphic else return true end end
Returns parameters that act as a key. All parameters that return true from isnamevar? or is named `:name` are included in the returned result. @todo would like a better explanation @return Array<??? Puppet::Parameter>
# File lib/puppet/type.rb, line 359 def self.key_attribute_parameters @key_attribute_parameters ||= ( params = @parameters.find_all { |param| param.isnamevar? or param.name == :name } ) end
Returns cached {key_attribute_parameters} names @todo what is a ‘key_attribute’ ? @return [Array<String>] cached key_attribute names
# File lib/puppet/type.rb, line 371 def self.key_attributes # This is a cache miss around 0.05 percent of the time. --daniel 2012-07-17 @key_attributes_cache ||= key_attribute_parameters.collect { |p| p.name } end
Is the given parameter a meta-parameter? @return [Boolean] true if the given parameter is a meta-parameter.
# File lib/puppet/type.rb, line 279 def self.metaparam?(param) @@metaparamhash.include?(param.intern) end
Returns the meta-parameter class associated with the given meta-parameter name. Accepts a `nil` name, and return nil. @param name [String, nil] the name of a meta-parameter @return [Class,nil] the class for the given meta-parameter, or `nil` if no such meta-parameter exists, (or if
the given meta-parameter name is `nil`.
# File lib/puppet/type.rb, line 289 def self.metaparamclass(name) return nil if name.nil? @@metaparamhash[name.intern] end
Returns the documentation for a given meta-parameter of this type. @todo the type for the param metaparam @param metaparam [??? Puppet::Parameter] the meta-parameter to get documentation for. @return [String] the documentation associated with the given meta-parameter, or nil of not such documentation
exists.
@raises [?] if the given metaparam is not a meta-parameter in this type
# File lib/puppet/type.rb, line 308 def self.metaparamdoc(metaparam) @@metaparamhash[metaparam].doc end
Returns all meta-parameter names. @return [Array<String>] all meta-parameter names
# File lib/puppet/type.rb, line 297 def self.metaparams @@metaparams.collect { |param| param.name } end
Creates an instance of Type from a hash or a {Puppet::Resource}. @todo Unclear if this is a new Type or a new instance of a given type (the initialization ends
with calling validate - which seems like validation of an instance of a given type, not a new meta type.
@todo Explain what the Hash and Resource are. There seems to be two different types of
resources; one that causes the title to be set to resource.title, and one that causes the title to be resource.ref ("for components") - what is a component?
@overaload initialize(hsh)
@param hsh [Hash]
@overload initialize(resource)
@param resource [Puppet:Resource]
# File lib/puppet/type.rb, line 2167 def initialize(resource) resource = self.class.hash2resource(resource) unless resource.is_a?(Puppet::Resource) # The list of parameter/property instances. @parameters = {} # Set the title first, so any failures print correctly. if resource.type.to_s.downcase.to_sym == self.class.name self.title = resource.title else # This should only ever happen for components self.title = resource.ref end [:file, :line, :catalog, :exported, :virtual].each do |getter| setter = getter.to_s + "=" if val = resource.send(getter) self.send(setter, val) end end @tags = resource.tags @original_parameters = resource.to_hash set_name(@original_parameters) set_default(:provider) set_parameters(@original_parameters) self.validate if self.respond_to?(:validate) end
Creates a new meta-parameter. This creates a new meta-parameter that is added to all types. @param name [Symbol] the name of the parameter @param options [Hash] a hash with options. @option options [Class<inherits Puppet::Parameter>] :parent (Puppet::Parameter) the super class of this parameter @option options [Hash{String => Object}] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Boolean] :boolean (false) specifies if this is a boolean parameter @option options [Boolean] :namevar (false) specifies if this parameter is the namevar @option options [Symbol, Array<Symbol>] :required_features specifies required provider features by name @return [Class<inherits Puppet::Parameter>] the created parameter @yield [ ] a required block that is evaluated in the scope of the new meta-parameter @api public @dsl type @todo Verify that this description is ok
# File lib/puppet/type.rb, line 329 def self.newmetaparam(name, options = {}, &block) @@metaparams ||= [] @@metaparamhash ||= {} name = name.intern param = genclass( name, :parent => options[:parent] || Puppet::Parameter, :prefix => "MetaParam", :hash => @@metaparamhash, :array => @@metaparams, :attributes => options[:attributes], &block ) # Grr. param.required_features = options[:required_features] if options[:required_features] handle_param_options(name, options) param.metaparam = true param end
Creates a new parameter. @param name [Symbol] the name of the parameter @param options [Hash] a hash with options. @option options [Class<inherits Puppet::Parameter>] :parent (Puppet::Parameter) the super class of this parameter @option options [Hash{String => Object}] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Boolean] :boolean (false) specifies if this is a boolean parameter @option options [Boolean] :namevar (false) specifies if this parameter is the namevar @option options [Symbol, Array<Symbol>] :required_features specifies required provider features by name @return [Class<inherits Puppet::Parameter>] the created parameter @yield [ ] a required block that is evaluated in the scope of the new parameter @api public @dsl type
# File lib/puppet/type.rb, line 437 def self.newparam(name, options = {}, &block) options[:attributes] ||= {} param = genclass( name, :parent => options[:parent] || Puppet::Parameter, :attributes => options[:attributes], :block => block, :prefix => "Parameter", :array => @parameters, :hash => @paramhash ) handle_param_options(name, options) # Grr. param.required_features = options[:required_features] if options[:required_features] param.isnamevar if options[:namevar] param end
Creates a new property. @param name [Symbol] the name of the property @param options [Hash] a hash with options. @option options [Symbol] :array_matching (:first) specifies how the current state is matched against
the wanted state. Use `:first` if the property is single valued, and (`:all`) otherwise.
@option options [Class<inherits Puppet::Property>] :parent (Puppet::Property) the super class of this property @option options [Hash{String => Object}] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Boolean] :boolean (false) specifies if this is a boolean parameter @option options [Symbol] :retrieve the method to call on the provider (or `parent` if `provider` is not set)
to retrieve the current value of this property.
@option options [Symbol, Array<Symbol>] :required_features specifies required provider features by name @return [Class<inherits Puppet::Property>] the created property @yield [ ] a required block that is evaluated in the scope of the new property @api public @dsl type
# File lib/puppet/type.rb, line 478 def self.newproperty(name, options = {}, &block) name = name.intern # This is here for types that might still have the old method of defining # a parent class. unless options.is_a? Hash raise Puppet::DevError, "Options must be a hash, not #{options.inspect}" end raise Puppet::DevError, "Class #{self.name} already has a property named #{name}" if @validproperties.include?(name) if parent = options[:parent] options.delete(:parent) else parent = Puppet::Property end # We have to create our own, new block here because we want to define # an initial :retrieve method, if told to, and then eval the passed # block if available. prop = genclass(name, :parent => parent, :hash => @validproperties, :attributes => options) do # If they've passed a retrieve method, then override the retrieve # method on the class. if options[:retrieve] define_method(:retrieve) do provider.send(options[:retrieve]) end end class_eval(&block) if block end # If it's the 'ensure' property, always put it first. if name == :ensure @properties.unshift prop else @properties << prop end prop end
@return [Puppet::Parameter] Returns the parameter class associated with the given parameter name.
# File lib/puppet/type.rb, line 532 def self.paramclass(name) @paramhash[name] end
# File lib/puppet/type.rb, line 521 def self.paramdoc(param) @paramhash[param].doc end
@return [Array<String>] Returns the parameter names
# File lib/puppet/type.rb, line 526 def self.parameters return [] unless defined?(@parameters) @parameters.collect { |klass| klass.name } end
@return [Puppet::Property] Returns the property class ??? associated with the given property name
# File lib/puppet/type.rb, line 537 def self.propertybyname(name) @validproperties[name] end
Creates a new provider of a type. This method must be called directly on the type that it’s implementing. @todo Fix Confusing Explanations!
Is this a new provider of a Type (metatype), or a provider of an instance of Type (a resource), or a Provider (the implementation of a Type's behavior). CONFUSED. It calls magically named methods like "providify" ...
@param name [String, Symbol] the name of the WHAT? provider? type? @param options [Hash{Symbol => Object}] a hash of options, used by this method, and passed on to {genclass}, (see
it for additional options to pass).
@option options [Puppet::Provider] :parent the parent provider (what is this?) @option options [Puppet::Type] :resource_type the resource type, defaults to this type if unspecified @return [Puppet::Provider] a provider ??? @raise [Puppet::DevError] when the parent provider could not be found.
# File lib/puppet/type.rb, line 1731 def self.provide(name, options = {}, &block) name = name.intern if unprovide(name) Puppet.debug "Reloading #{name} #{self.name} provider" end parent = if pname = options[:parent] options.delete(:parent) if pname.is_a? Class pname else if provider = self.provider(pname) provider else raise Puppet::DevError, "Could not find parent provider #{pname} of #{name}" end end else Puppet::Provider end options[:resource_type] ||= self self.providify provider = genclass( name, :parent => parent, :hash => provider_hash, :prefix => "Provider", :block => block, :include => feature_module, :extend => feature_module, :attributes => options ) provider end
Returns the provider having the given name. This will load a provider if it is not already loaded. The returned provider is the first found provider having the given name, where “first found” semantics is defined by the {providerloader} in use.
@param name [String] the name of the provider to get @return [Puppet::Provider, nil] the found provider, or nil if no provider of the given name was found
# File lib/puppet/type.rb, line 1688 def self.provider(name) name = name.intern # If we don't have it yet, try loading it. @providerloader.load(name) unless provider_hash.has_key?(name) provider_hash[name] end
@return [Hash{ ??? => Puppet::Provider}] Returns a hash of WHAT EXACTLY for this type. @see provider_hash_by_type method to get the same for some other type
# File lib/puppet/type.rb, line 1677 def self.provider_hash Puppet::Type.provider_hash_by_type(self.name) end
@return [Hash{??? => Puppet::Provider}] Returns a hash of WHAT EXACTLY for the given type @todo what goes into this hash?
# File lib/puppet/type.rb, line 1670 def self.provider_hash_by_type(type) @provider_hashes ||= {} @provider_hashes[type] ||= {} end
Returns a list of loaded providers by name. This method will not load/search for available providers. @return [Array<String>] list of loaded provider names
# File lib/puppet/type.rb, line 1700 def self.providers provider_hash.keys end
Returns a list of one suitable provider per source, with the default provider first. @todo Needs better explanation; what does “source” mean in this context? @return [Array<Puppet::Provider>] list of providers
# File lib/puppet/type.rb, line 1127 def self.providers_by_source # Put the default provider first (can be nil), then the rest of the suitable providers. sources = [] [defaultprovider, suitableprovider].flatten.uniq.collect do |provider| next if provider.nil? next if sources.include?(provider.source) sources << provider.source provider end.compact end
Ensures there is a `:provider` parameter defined. Should only be called if there are providers. @return [void]
# File lib/puppet/type.rb, line 1775 def self.providify return if @paramhash.has_key? :provider newparam(:provider) do # We're using a hacky way to get the name of our type, since there doesn't # seem to be a correct way to introspect this at the time this code is run. # We expect that the class in which this code is executed will be something # like Puppet::Type::Ssh_authorized_key::ParameterProvider. desc The specific backend to use for this `#{self.to_s.split('::')[2].downcase}` resource. You will seldom need to specify this --- Puppet will usually discover the appropriate provider for your platform. # This is so we can refer back to the type to get a list of # providers for documentation. class << self # The reference to a parent type for the parameter `:provider` used to get a list of # providers for documentation purposes. # attr_accessor :parenttype end # Provides the ability to add documentation to a provider. # def self.doc # Since we're mixing @doc with text from other sources, we must normalize # its indentation with scrub. But we don't need to manually scrub the # provider's doc string, since markdown_definitionlist sanitizes its inputs. scrub(@doc) + "Available providers are:\n\n" + parenttype.providers.sort { |a,b| a.to_s <=> b.to_s }.collect { |i| markdown_definitionlist( i, scrub(parenttype().provider(i).doc) ) }.join end # @todo this does what? where and how? # @returns [String] the name of the provider defaultto { prov = @resource.class.defaultprovider prov.name if prov } validate do |provider_class| provider_class = provider_class[0] if provider_class.is_a? Array provider_class = provider_class.class.name if provider_class.is_a?(Puppet::Provider) unless provider = @resource.class.provider(provider_class) raise ArgumentError, "Invalid<EMAIL_ADDRESS>provider '#{provider_class}'" end end munge do |provider| provider = provider[0] if provider.is_a? Array provider = provider.intern if provider.is_a? String @resource.provider = provider if provider.is_a?(Puppet::Provider) provider.class.name else provider end end end.parenttype = self end
@todo document this, have no clue what this does… it retuns “RelationshipMetaparam.subclasses”
# File lib/puppet/type.rb, line 1469 def self.relationship_params RelationshipMetaparam.subclasses end
Returns a list of suitable providers for the given type. A call to this method will load all providers if not already loaded and ask each if it is suitable - those that are are included in the result. @note This method also does some special processing which rejects a provider named `:fake` (for testing purposes). @return [Array<Puppet::Provider>] Returns an array of all suitable providers.
# File lib/puppet/type.rb, line 1858 def self.suitableprovider providerloader.loadall if provider_hash.empty? provider_hash.find_all { |name, provider| provider.suitable? }.collect { |name, provider| provider }.reject { |p| p.name == :fake } # For testing end
Returns a mapping from the title string to setting of attribute value(s). This default implementation provides a mapping of title to the one and only namevar present in the type’s definition. @note Advanced: some logic requires this mapping to be done differently, using a different
validation/pattern, breaking up the title into several parts assigning each to an individual attribute, or even use a composite identity where all namevars are seen as part of the unique identity (such computation is done by the {#uniqueness} method. These advanced options are rarely used (only one of the built in puppet types use this, and then only a small part of the available functionality), and the support for these advanced mappings is not implemented in a straight forward way. For these reasons, this method has been marked as private).
@raise [Puppet::DevError] if there is no title pattern and there are two or more key attributes @return [Array<Array<Regexp, Array<Array <Symbol, Proc>>>>, nil] a structure with a regexp and the first key_attribute ??? @comment This wonderful piece of logic creates a structure used by Resource.parse_title which
has the capability to assign parts of the title to one or more attributes; It looks like an implementation of a composite identity key (all parts of the key_attributes array are in the key). This can also be seen in the method uniqueness_key. The implementation in this method simply assigns the title to the one and only namevar (which is name or a variable marked as namevar). If there are multiple namevars (any in addition to :name?) then this method MUST be implemented as it raises an exception if there is more than 1. Note that in puppet, it is only File that uses this to create a different pattern for assigning to the :path attribute This requires further digging. The entire construct is somewhat strange, since resource checks if the method "title_patterns" is implemented (it seems it always is) - why take this more expensive regexp mathching route for all other types?
@api private
# File lib/puppet/type.rb, line 404 def self.title_patterns case key_attributes.length when 0; [] when 1; [ [ /(.*)/, [ [key_attributes.first] ] ] ] else raise Puppet::DevError,"you must specify title patterns when there are two or more key attributes" end end
Returns the name of this type (if specified) or the parent type to_s. The returned name is on the form “Puppet::Type::<name>”, where the first letter of name is capitalized. @return [String] the fully qualified name Puppet::Type::<name> where the first letter of name is captialized
# File lib/puppet/type.rb, line 2088 def self.to_s if defined?(@name) <EMAIL_ADDRESS>else super end end
@todo this needs a better explanation Removes the implementation class of a given provider. @return [Object] returns what {Puppet::Util::ClassGen#rmclass} returns
# File lib/puppet/type.rb, line 1844 def self.unprovide(name) if @defaultprovider and @defaultprovider.name == name @defaultprovider = nil end rmclass(name, :hash => provider_hash, :prefix => "Provider") end
(see validattr?) @note see comment in code - how should this be documented? Are some of the other query methods deprecated?
(or should be).
@comment This is a forward-compatibility method - it’s the validity interface we’ll use in Puppet::Resource.
# File lib/puppet/type.rb, line 582 def self.valid_parameter?(name) validattr?(name) end
Creates a `validate` method that is used to validate a resource before it is operated on. The validation should raise exceptions if the validation finds errors. (It is not recommended to issue warnings as this typically just ends up in a logfile - you should fail if a validation fails). The easiest way to raise an appropriate exception is to call the method {Puppet::Util::Errors.fail} with the message as an argument.
@yield [ ] a required block called with self set to the instance of a Type class representing a resource. @return [void] @dsl type @api public
# File lib/puppet/type.rb, line 2107 def self.validate(&block) define_method(:validate, &block) #@validate = block end
Returns whether or not the given name is the name of a property, parameter or meta-parameter @return [Boolean] true if the given attribute name is the name of an existing property, parameter or meta-parameter
# File lib/puppet/type.rb, line 544 def self.validattr?(name) name = name.intern return true if name == :name @validattrs ||= {} unless @validattrs.include?(name) @validattrs[name] = !!(self.validproperty?(name) or self.validparameter?(name) or self.metaparam?(name)) end @validattrs[name] end
@return [Boolean] Returns true if the given name is the name of an existing parameter
# File lib/puppet/type.rb, line 573 def self.validparameter?(name) raise Puppet::DevError, "Class #{self} has not defined parameters" unless defined?(@parameters) !!(@paramhash.include?(name) or @@metaparamhash.include?(name)) end
@return [Array<Symbol>, {}] Returns a list of valid property names, or an empty hash if there are none. @todo An empty hash is returned if there are no defined parameters (not an empty array). This looks like
a bug.
# File lib/puppet/type.rb, line 566 def self.validproperties return {} unless defined?(@parameters) @validproperties.keys end
@return [Boolean] Returns true if the given name is the name of an existing property
# File lib/puppet/type.rb, line 557 def self.validproperty?(name) name = name.intern @validproperties.include?(name) && @validproperties[name] end
Returns true if the given name is a reference to a provider and if this is a suitable provider for this type. @todo How does the provider know if it is suitable for the type? Is it just suitable for the platform/
environment where this method is executing?
@param name [String] the name of the provider for which validity is checked @return [Boolean] true if the given name references a provider that is suitable
# File lib/puppet/type.rb, line 1711 def self.validprovider?(name) name = name.intern (provider_hash.has_key?(name) && provider_hash[name].suitable?) end
Compares this type against the given other (type) and returns -1, 0, or +1 depending on the order. @param other [Object] the object to compare against (produces nil, if not kind of Type} @return [-1, 0, +1, nil] produces -1 if this type is before the given other type, 0 if equals, and 1 if after.
Returns nil, if the given _other_ is not a kind of Type.
@see Comparable
# File lib/puppet/type.rb, line 93 def <=>(other) # We only order against other types, not arbitrary objects. return nil unless other.is_a? Puppet::Type # Our natural order is based on the reference name we use when comparing # against other type instances. self.ref <=> other.ref end
Gets the ‘should’ (wanted state) value of a parameter or property by name. To explicitly get the ‘is’ (current state) value use `o.is(:name)`, and to explicitly get the ‘should’ value use `o.should(:name)` @param name [String] the name of the attribute to obtain the ‘should’ value for. @return [Object] ‘should’/wanted value of the given attribute
# File lib/puppet/type.rb, line 619 def [](name) name = name.intern fail("Invalid parameter #{name}(#{name.inspect})") unless self.class.validattr?(name) if name == :name && nv = name_var name = nv end if obj = @parameters[name] # Note that if this is a property, then the value is the "should" value, # not the current value. obj.value else return nil end end
Sets the ‘should’ (wanted state) value of a property, or the value of a parameter. @return @raise [Puppet::Error] if the setting of the value fails, or if the given name is nil.
# File lib/puppet/type.rb, line 639 def []=(name,value) name = name.intern fail("Invalid parameter #{name}") unless self.class.validattr?(name) if name == :name && nv = name_var name = nv end raise Puppet::Error.new("Got nil value for #{name}") if value.nil? property = self.newattr(name) if property begin # make sure the parameter doesn't have any errors property.value = value rescue => detail error = Puppet::Error.new("Parameter #{name} failed on #{ref}: #{detail}") error.set_backtrace(detail.backtrace) raise error end end nil end
Creates a new property value holder for the resource if it is valid and does not already exist @return [Boolean] true if a new parameter was added, false otherwise
# File lib/puppet/type.rb, line 593 def add_property_parameter(prop_name) if self.class.validproperty?(prop_name) && !@parameters[prop_name] self.newattr(prop_name) return true end false end
# File lib/puppet/type.rb, line 1251 def all_properties resource.class.properties.find_all do |property| resource.provider.nil? or resource.provider.class.supports_parameter?(property) end.collect do |property| property.name end end
Returns the ancestors - WHAT? This implementation always returns an empty list. @todo WHAT IS THIS ? @return [Array<???>] returns a list of ancestors.
# File lib/puppet/type.rb, line 948 def ancestors [] end
@return [Boolean] Returns whether the resource is applicable to `:device` @todo Explain what this means @api private
# File lib/puppet/type.rb, line 2403 def appliable_to_device? self.class.can_apply_to(:device) end
@return [Boolean] Returns whether the resource is applicable to `:host` @todo Explain what this means @api private
# File lib/puppet/type.rb, line 2410 def appliable_to_host? self.class.can_apply_to(:host) end
Adds dependencies to the catalog from added autorequirements. See {autorequire} for how to add an auto-requirement. @todo needs details - see the param rel_catalog, and type of this param @param rel_catalog [Puppet::Catalog, nil] the catalog to add dependencies to. Defaults to the
catalog (TODO: what is the type of the catalog).
@raise [Puppet::DevError] if there is no catalog
# File lib/puppet/type.rb, line 1950 def autorequire(rel_catalog = nil) rel_catalog ||= catalog raise(Puppet::DevError, "You cannot add relationships without a catalog") unless rel_catalog reqs = [] self.class.eachautorequire { |type, block| # Ignore any types we can't find, although that would be a bit odd. next unless typeobj = Puppet::Type.type(type) # Retrieve the list of names from the block. next unless list = self.instance_eval(&block) list = [list] unless list.is_a?(Array) # Collect the current prereqs list.each { |dep| # Support them passing objects directly, to save some effort. unless dep.is_a? Puppet::Type # Skip autorequires that we aren't managing unless dep = rel_catalog.resource(type, dep) next end end reqs << Puppet::Relationship.new(dep, self) } } reqs end
Builds the dependencies associated with an individual object. @todo Which object is the “individual object”, as opposed to “object as a group?” or should it simply
be "this object" as in "this resource" ?
@todo Does this method “build dependencies” or “build what it depends on” … CONFUSING
@return [Array<???>] list of WHAT? resources? edges?
# File lib/puppet/type.rb, line 1986 def builddepends # Handle the requires self.class.relationship_params.collect do |klass| if param = @parameters[klass.name] param.to_edges end end.flatten.reject { |r| r.nil? } end
Returns a hash of the current properties and their values. If a resource is absent, it’s value is the symbol `:absent` @return [Hash{Puppet::Property => Object}] mapping of property instance to its value
# File lib/puppet/type.rb, line 1050 def currentpropvalues # It's important to use the 'properties' method here, as it follows the order # in which they're defined in the class. It also guarantees that 'ensure' # is the first property, which is important for skipping 'retrieve' on # all the properties if the resource is absent. ensure_state = false return properties.inject({}) do | prophash, property| if property.name == :ensure ensure_state = property.retrieve prophash[property] = ensure_state else if ensure_state == :absent prophash[property] = :absent else prophash[property] = property.retrieve end end prophash end end
Removes a property from the object; useful in testing or in cleanup when an error has been encountered @todo Incomprehensible - the comment says “Remove a property”, the code refers to @parameters, and
the method parameter is called "attr" - What is it, property, parameter, both (i.e an attribute) or what?
@todo Don’t know what the attr is (name or Property/Parameter?). Guessing it is a String name… @todo Is it possible to delete a meta-parameter? @todo What does delete mean? Is it deleted from the type or is its value state ‘is’/‘should’ deleted? @param attr [String] the attribute to delete from this object. WHAT IS THE TYPE? @raise [Puppet::DecError] when an attempt is made to delete an attribute that does not exists.
# File lib/puppet/type.rb, line 675 def delete(attr) attr = attr.intern if @parameters.has_key?(attr) @parameters.delete(attr) else raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}") end end
@return [Boolean] Returns true if the wanted state of the resoure is that it should be absent (i.e. to be deleted).
# File lib/puppet/type.rb, line 587 def deleting? obj = @parameters[:ensure] and obj.should == :absent end
Returns true if the search should be done in depth-first order. This implementation always returns false. @todo What is this used for?
@return [Boolean] true if the search should be done in depth first order.
# File lib/puppet/type.rb, line 911 def depthfirst? false end
Iterates over the existing properties. @todo what does this mean? As opposed to iterating over the “non existing properties” ??? Is it an
iteration over those properties that have state? CONFUSING.
@yieldparam property [Puppet::Property] each property @return [void]
# File lib/puppet/type.rb, line 689 def eachproperty # properties is a private method properties.each { |property| yield property } end
Creates a transaction event. Called by Transaction or by a property. Merges the given options with the options `:resource`, `:file`, `:line`, and `:tags`, initialized from values in this object. For possible options to pass (if any ????) see {Puppet::Transaction::Event}. @todo Needs a better explanation “Why should I care who is calling this method?”, What do I need to know
about events and how they work? Where can I read about them?
@param options [Hash] options merged with a fixed set of options defined by this method, passed on to {Puppet::Transaction::Event}. @return [Puppet::Transaction::Event] the created event
# File lib/puppet/type.rb, line 704 def event(options = {}) Puppet::Transaction::Event.new({:resource => self, :file => file, :line => line, :tags => tags}.merge(options)) end
@return [Boolean] Returns whether the resource is exported or not
# File lib/puppet/type.rb, line 2398 def exported?; !!@exported; end
Finishes any outstanding processing. This method should be called as a final step in setup, to allow the parameters that have associated auto-require needs to be processed.
@todo what is the expected sequence here - who is responsible for calling this? When?
Is the returned type correct?
@return [Array<Puppet::Parameter>] the validated list/set of attributes
# File lib/puppet/type.rb, line 2267 def finish # Make sure all of our relationships are valid. Again, must be done # when the entire catalog is instantiated. self.class.relationship_params.collect do |klass| if param = @parameters[klass.name] param.validate_relationship end end.flatten.reject { |r| r.nil? } end
Flushes the provider if supported by the provider, else no action. This is called by the transaction. @todo What does Flushing the provider mean? Why is it interesting to know that this is
called by the transaction?  GUESS IS VOID
# File lib/puppet/type.rb, line 958 def flush self.provider.flush if self.provider and self.provider.respond_to?(:flush) end
Returns true if all contained objects are in sync. @todo “contained in what?” in the given “in” parameter?
@todo deal with the comment _“FIXME I don’t think this is used on the type instances any more,
it's really only used for testing"_
@return [Boolean] true if in sync, false otherwise.
# File lib/puppet/type.rb, line 969 def insync?(is) insync = true if property = @parameters[:ensure] unless is.include? property raise Puppet::DevError, "The is value is not in the is array for '#{property.name}'" end ensureis = is[property] if property.safe_insync?(ensureis) and property.should == :absent return true end end properties.each { |property| unless is.include? property raise Puppet::DevError, "The is value is not in the is array for '#{property.name}'" end propis = is[property] unless property.safe_insync?(propis) property.debug("Not in sync: #{propis.inspect} vs #{property.should.inspect}") insync = false #else # property.debug("In sync") end } #self.debug("#{self} sync status is #{insync}") insync end
@todo check that this gets documentation (it is at the class level as well as instance). (see isomorphic?)
# File lib/puppet/type.rb, line 872 def isomorphic? self.class.isomorphic? end
Creates a log entry with the given message at the log level specified by the parameter `loglevel` @return [void]
# File lib/puppet/type.rb, line 2132 def log(msg) Puppet::Util::Log.create( :level => @parameters[:loglevel].value, :message => msg, :source => self ) end
Returns true if the instance is a managed instance. A ‘yes’ here means that the instance was created from the language, vs. being created in order resolve other questions, such as finding a package in a list. @note An object that is managed always stays managed, but an object that is not managed
may become managed later in its lifecycle.
@return [Boolean] true if the object is managed
# File lib/puppet/type.rb, line 882 def managed? # Once an object is managed, it always stays managed; but an object # that is listed as unmanaged might become managed later in the process, # so we have to check that every time if @managed return @managed else @managed = false properties.each { |property| s = property.should if s and ! property.class.unmanaged @managed = true break end } return @managed end end
@comment For now, leave the ‘name’ method functioning like it used to. Once ‘title’
works everywhere, I'll switch it.
Returns the resource’s name @todo There is a comment in source that this is not quite the same as ‘:title’ and that a switch should
be made...
@return [String] the name of a resource
# File lib/puppet/type.rb, line 2283 def name self[:name] end
@return [Symbol, Boolean] Returns the name of the namevar if there is only one or false otherwise. @comment This is really convoluted and part of the support for multiple namevars (?).
If there is only one namevar, the produced value is naturally this namevar, but if there are several? The logic caches the name of the namevar if it is a single name, but otherwise always calls key_attributes, and then caches the first if there was only one, otherwise it returns false and caches this (which is then subsequently returned as a cache hit).
# File lib/puppet/type.rb, line 608 def name_var return @name_var_cache unless @name_var_cache.nil? key_attributes = self.class.key_attributes @name_var_cache = (key_attributes.length == 1) && key_attributes.first end
Creates an instance to represent/manage the given attribute. Requires either the attribute name or class as the first argument, then an optional hash of attributes to set during initialization. @todo The original comment is just wrong - the method does not accept a hash of options @todo Detective work required; this method interacts with provider to ask if it supports a parameter of
the given class. it then returns the parameter if it exists, otherwise creates a parameter with its :resource => self.
@overload newattr(name)
@param name [String] Unclear what name is (probably a symbol) - Needs investigation.
@overload newattr(klass)
@param klass [Class] a class supported as an attribute class - Needs clarification what that means.
@return [???] Probably returns a new instance of the class - Needs investigation.
# File lib/puppet/type.rb, line 728 def newattr(name) if name.is_a?(Class) klass = name name = klass.name end unless klass = self.class.attrclass(name) raise Puppet::Error, "Resource type #{self.class.name} does not support parameter #{name}" end if provider and ! provider.class.supports_parameter?(klass) missing = klass.required_features.find_all { |f| ! provider.class.feature?(f) } debug "Provider %s does not support features %s; not managing attribute %s" % [provider.class.name, missing.join(", "), name] return nil end return @parameters[name] if @parameters.include?(name) @parameters[name] = klass.new(:resource => self) end
Returns the `noop` run mode status of this. @return [Boolean] true if running in noop mode.
# File lib/puppet/type.rb, line 1073 def noop? # If we're not a host_config, we're almost certainly part of # Settings, and we want to ignore 'noop' return false if catalog and ! catalog.host_config? if defined?(@noop) @noop else Puppet[:noop] end end
Returns the value of this object’s parameter given by name @param name [String] the name of the parameter @return [Object] the value
# File lib/puppet/type.rb, line 752 def parameter(name) @parameters[name.to_sym] end
Returns a shallow copy of this object’s hash of parameters. @todo Add that this is not only “parameters”, but also “properties” and “meta-parameters” ? Changes to the contained parameters will have an effect on the parameters of this type, but changes to the returned hash does not. @return [Hash{String => Puppet:???Parameter}] a new hash being a shallow copy of the parameters map name to parameter
# File lib/puppet/type.rb, line 761 def parameters @parameters.dup end
Returns the parent of this in the catalog. In case of an erroneous catalog where multiple parents have been produced, the first found (non deterministic) parent is returned. @return [???, nil] WHAT (which types can be the parent of a resource in a catalog?), or nil if there
is no catalog.
# File lib/puppet/type.rb, line 2293 def parent return nil unless catalog unless defined?(@parent) if parents = catalog.adjacent(self, :direction => :in) # We should never have more than one parent, so let's just ignore # it if we happen to. @parent = parents.shift else @parent = nil end end @parent end
Creates the path for logging and such. @todo “and such?”, what? @api private
# File lib/puppet/type.rb, line 1172 def pathbuilder if p = parent [p.pathbuilder, self.ref].flatten else [self.ref] end end
@return [Array<Puppet::Property>] Returns all of the property objects, in the order specified in the
class.
@todo “what does the ‘order specified in the class’ mean? The order the properties where added in the
ruby file adding a new type with new properties?
# File lib/puppet/type.rb, line 853 def properties self.class.properties.collect { |prop| @parameters[prop.name] }.compact end
# File lib/puppet/type.rb, line 1259 def properties_to_audit(list) if !list.kind_of?(Array) && list.to_sym == :all list = all_properties else list = Array(list).collect { |p| p.to_sym } end end
Returns a {Puppet::Property} instance by name. To return the value, use ‘resource’ @todo LAK:NOTE(20081028) Since the ‘parameter’ method is now a superset of this method,
this one should probably go away at some point. - Does this mean it should be deprecated ?
@return [Puppet::Property] the property with the given name, or nil if not a property or does not exist.
# File lib/puppet/type.rb, line 777 def property(name) (obj = @parameters[name.intern] and obj.is_a?(Puppet::Property)) ? obj : nil end
@return [Boolean] Returns whether the property given by name is defined or not. @todo what does it mean to be defined?
# File lib/puppet/type.rb, line 767 def propertydefined?(name) name = name.intern unless name.is_a? Symbol @parameters.include?(name) end
Sets the provider to the given provider/name. @overload provider=(name)
Sets the provider to the result of resolving the name to an instance of Provider. @param name [String] the name of the provider
@overload provider=(provider)
Sets the provider to the given instances of Provider. @param provider [Puppet::Provider] the provider to set
@return [Puppet::Provider] the provider set @raise [ArgumentError] if the provider could not be found/resolved.
# File lib/puppet/type.rb, line 1898 def provider=(name) if name.is_a?(Puppet::Provider) @provider = name @provider.resource = self elsif klass = self.class.provider(name) @provider = klass.new(self) else raise ArgumentError, "Could not find #{name} provider of #{self.class.name}" end end
Marks the object as “being purged”. This method is used by transactions to forbid deletion when there are dependencies. @todo what does this mean; “mark that we are purging” (purging what from where). How to use/when?
Is this internal API in transactions?
@see purging?
# File lib/puppet/type.rb, line 2330 def purging @purging = true end
Returns whether this resource is being purged or not. This method is used by transactions to forbid deletion when there are dependencies. @return [Boolean] the current “purging” state
# File lib/puppet/type.rb, line 2338 def purging? if defined?(@purging) @purging else false end end
Returns a reference to this as a string in “Type” format. @return [String] a reference to this object on the form ‘Type’
# File lib/puppet/type.rb, line 2311 def ref # memoizing this is worthwhile ~ 3 percent of calls are the "first time # around" in an average run of Puppet. --daniel 2012-07-17 @ref ||= "#{self.class.name.to_s.capitalize}[#{self.title}]" end
Removes this object (FROM WHERE?) @todo removes if from where? @overload remove(rmdeps)
@deprecated Use remove() @param rmdeps [Boolean] intended to indicate that all subscriptions should also be removed, ignored.
@overload remove() @return [void]
# File lib/puppet/type.rb, line 923 def remove(rmdeps = true) # This is hackish (mmm, cut and paste), but it works for now, and it's # better than warnings. @parameters.each do |name, obj| obj.remove end @parameters.clear @parent = nil # Remove the reference to the provider. if self.provider @provider.clear @provider = nil end end
Retrieves the current value of all contained properties. Parameters and meta-parameters are not included in the result. @todo As oposed to all non contained properties? How is this different than any of the other
methods that also "gets" properties/parameters/etc. ?
@return [Array<Object>] array of all property values (mix of types) @raise [fail???] if there is a provider and it is not suitable for the host this is evaluated for.
# File lib/puppet/type.rb, line 1008 def retrieve fail "Provider #{provider.class.name} is not functional on this host" if self.provider.is_a?(Puppet::Provider) and ! provider.class.suitable? result = Puppet::Resource.new(type, title) # Provide the name, so we know we'll always refer to a real thing result[:name] = self[:name] unless self[:name] == title if ensure_prop = property(:ensure) or (self.class.validattr?(:ensure) and ensure_prop = newattr(:ensure)) result[:ensure] = ensure_state = ensure_prop.retrieve else ensure_state = nil end properties.each do |property| next if property.name == :ensure if ensure_state == :absent result[property] = :absent else result[property] = property.retrieve end end result end
??? @todo what does this do? It seems to create a new Resource based on the result of calling retrieve
and if that is a Hash, else this method produces nil.
@return [Puppet::Resource, nil] a new Resource, or nil, if this object did not produce a Hash as the
result from #retrieve
# File lib/puppet/type.rb, line 1040 def retrieve_resource resource = retrieve resource = Resource.new(type, title, :parameters => resource) if resource.is_a? Hash resource end
(see self_refresh) @todo check that meaningful yardoc is produced - this method delegates to “self.class.self_refresh” @return [Boolean] - ??? returns true when … what?
# File lib/puppet/type.rb, line 2321 def self_refresh? self.class.self_refresh end
@todo comment says “For any parameters or properties that have defaults and have not yet been
set, set them now. This method can be handed a list of attributes, and if so it will only set defaults for those attributes."
@todo Needs a better explanation, and investigation about the claim an array can be passed (it is passed
to self.class.attrclass to produce a class on which a check is made if it has a method class :default (does not seem to support an array...
@return [void]
# File lib/puppet/type.rb, line 789 def set_default(attr) return unless klass = self.class.attrclass(attr) return unless klass.method_defined?(:default) return if @parameters.include?(klass.name) return unless parameter = newattr(klass.name) if value = parameter.default and ! value.nil? parameter.value = value else @parameters.delete(parameter.name) end end
@return [Object, nil] Returns the ‘should’ (wanted state) value for a specified property, or nil if the
given attribute name is not a property (i.e. if it is a parameter, meta-parameter, or does not exist).
# File lib/puppet/type.rb, line 710 def should(name) name = name.intern (prop = @parameters[name] and prop.is_a?(Puppet::Property)) ? prop.should : nil end
@return [Boolean] Returns true if this is something else than a `:provider`, or if it
is a provider and it is suitable, or if there is a default provider. Otherwise, false is returned.
# File lib/puppet/type.rb, line 1870 def suitable? # If we don't use providers, then we consider it suitable. return true unless self.class.paramclass(:provider) # We have a provider and it is suitable. return true if provider && provider.class.suitable? # We're using the default provider and there is one. if !provider and self.class.defaultprovider self.provider = self.class.defaultprovider.name return true end # We specified an unsuitable provider, or there isn't any suitable # provider. false end
Returns the title of this object, or it’s name if title was not explicetly set. If the title is not already set, it will be computed by looking up the {name_var} and using that value as the title. @todo it is somewhat confusing that if the name_var is a valid parameter, it is assumed to
be the name_var called :name, but if it is a property, it uses the name_var. It is further confusing as Type in some respects supports multiple namevars.
@return [String] Returns the title of this object, or it’s name if title was not explicetly set. @raise [??? devfail] if title is not set, and name_var can not be found.
# File lib/puppet/type.rb, line 2355 def title unless @title if self.class.validparameter?(name_var) @title = self[:name] elsif self.class.validproperty?(name_var) @title = self.should(name_var) else self.devfail "Could not find namevar #{name_var} for #{self.class.name}" end end @title end
@todo the comment says: “Convert our object to a hash. This just includes properties.” @todo this is confused, again it is the @parameters instance variable that is consulted, and
each value is copied - does it contain "properties" and "parameters" or both? Does it contain meta-parameters?
@return [Hash{ ??? => ??? }] a hash of WHAT?. The hash is a shallow copy, any changes to the
objects returned in this hash will be reflected in the original resource having these attributes.
# File lib/puppet/type.rb, line 811 def to_hash rethash = {} @parameters.each do |name, obj| rethash[name] = obj.value end rethash end
@todo What to resource? Which one of the resource forms is prroduced? returned here? @return [??? Resource] a resource that WHAT???
# File lib/puppet/type.rb, line 2379 def to_resource resource = self.retrieve_resource resource.tag(*self.tags) @parameters.each do |name, param| # Avoid adding each instance name twice next if param.class.isnamevar? and param.value == self.title # We've already got property values next if param.is_a?(Puppet::Property) resource[name] = param.value end resource end
Produces a reference to this in reference format. @see ref
# File lib/puppet/type.rb, line 2372 def to_s self.ref end
@return [String] the name of this object’s class @todo Would that be “file” for the “File” resource type? of “File” or something else?
# File lib/puppet/type.rb, line 824 def type self.class.name end
Produces a uniqueness_key @todo Explain what a uniqueness_key is @return [Object] an object that is a uniqueness_key for this object
# File lib/puppet/type.rb, line 418 def uniqueness_key self.class.key_attributes.sort_by { |attribute_name| attribute_name.to_s }.map{ |attribute_name| self[attribute_name] } end
@todo Comment says “Return a specific value for an attribute.”, as opposed to what “An upspecific value”??? @todo is this the ‘is’ or the ‘should’ value? @todo why is the return restricted to things that respond to :value? (Only non structural basic data types
supported?
@return [Object, nil] the value of the attribute having the given name, or nil if the given name is not
an attribute, or the referenced attribute does not respond to `:value`.
# File lib/puppet/type.rb, line 835 def value(name) name = name.intern (obj = @parameters[name] and obj.respond_to?(:value)) ? obj.value : nil end
Generated with the Darkfish Rdoc Generator 2.


{% extends "editFunnelLayout.html" %} {% block pagestyles %} {% endblock %} {% block content %}
Once you click agree the funnel will be removed from the entire system


Class: Concurrent::Promises::Event
- Inherits:
-
AbstractEventFuture
- Object
- Synchronization::Object
- AbstractEventFuture
- Concurrent::Promises::Event
- Defined in:
- lib/concurrent/edge/promises.rb
Overview
Represents an event which will happen in future (will be resolved). The event is either pending or resolved. It should be always resolved. Use Future to communicate rejections and cancellation.
Direct Known Subclasses
Constant Summary
Instance Method Summary (collapse)
-
- (Event) any(event_or_future)
(also: #|)
Creates a new event which will be resolved when the first of receiver,
event_or_future
resolves. -
- (Event) delay
Creates new event dependent on receiver which will not evaluate until touched, see AbstractEventFuture#touch.
-
- (Event) schedule(intended_time)
Creates new event dependent on receiver scheduled to execute on/in intended_time.
-
- (Event) to_event
Returns self, since this is event.
-
- (Future) to_future
Converts event to a future.
-
- (Event) with_default_executor(executor)
Crates new object with same class with the executor set as its new default executor.
-
- (Future, Event) zip(other)
(also: #&)
Creates a new event or a future which will be resolved when receiver and other are.
Instance Method Details
- (Event) any(event_or_future) Also known as: |
Creates a new event which will be resolved when the first of receiver, event_or_future
resolves.
847 848 849 |
# File 'lib/concurrent/edge/promises.rb', line 847 def any(event_or_future) AnyResolvedEventPromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).event end |
- (Event) delay
Creates new event dependent on receiver which will not evaluate until touched, see AbstractEventFuture#touch. In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated.
857 858 859 860 |
# File 'lib/concurrent/edge/promises.rb', line 857 def delay event = DelayPromise.new(@DefaultExecutor).event ZipEventEventPromise.new_blocked_by2(self, event, @DefaultExecutor).event end |
- (Event) schedule(intended_time)
Creates new event dependent on receiver scheduled to execute on/in intended_time. In time is interpreted from the moment the receiver is resolved, therefore it inserts delay into the chain.
869 870 871 872 873 874 |
# File 'lib/concurrent/edge/promises.rb', line 869 def schedule(intended_time) chain do event = ScheduledPromise.new(@DefaultExecutor, intended_time).event ZipEventEventPromise.new_blocked_by2(self, event, @DefaultExecutor).event end.flat_event end |
- (Event) to_event
Returns self, since this is event
887 888 889 |
# File 'lib/concurrent/edge/promises.rb', line 887 def to_event self end |
- (Future) to_future
Converts event to a future. The future is fulfilled when the event is resolved, the future may never fail.
879 880 881 882 883 |
# File 'lib/concurrent/edge/promises.rb', line 879 def to_future future = Promises.resolvable_future ensure chain_resolvable(future) end |
- (Event) with_default_executor(executor)
Crates new object with same class with the executor set as its new default executor. Any futures depending on it will use the new default executor.
893 894 895 |
# File 'lib/concurrent/edge/promises.rb', line 893 def with_default_executor(executor) EventWrapperPromise.new_blocked_by1(self, executor).event end |
- (Future, Event) zip(other) Also known as: &
Creates a new event or a future which will be resolved when receiver and other are. Returns an event if receiver and other are events, otherwise returns a future. If just one of the parties is Future then the result of the returned future is equal to the result of the supplied future. If both are futures then the result is as described in FactoryMethods#zip_futures_on.
833 834 835 836 837 838 839 |
# File 'lib/concurrent/edge/promises.rb', line 833 def zip(other) if other.is_a?(Future) ZipFutureEventPromise.new_blocked_by2(other, self, @DefaultExecutor).future else ZipEventEventPromise.new_blocked_by2(self, other, @DefaultExecutor).event end end |


5.2 Interface for Linked
Lists
void list_init(List *list, void (*destroy)(void *data));
Return Value
None.
Description
Initializes the linked list specified by
list. This operation must be called for a
linked list before the list can be used with any other
operation. The destroy argument provides a way
to free dynamically allocated data when list_destroy is called. For example,
if the list contains data dynamically allocated using malloc, destroy
should be set to free to free
the data as the linked list is destroyed. For structured data
containing several dynamically allocated members,
destroy should be set to a user-defined
function that calls free for
each dynamically allocated member as well as for the structure
itself. For a linked list containing data that should not be
freed, destroy should be set to NULL.
Complexity
O (1)
void list_destroy(List *list);
Return Value
None.
Description
Destroys the linked list specified by
list. No other operations are permitted after
calling list_destroy unless list_init is called again. The list_destroy operation removes all
elements from a linked list and calls the function passed as
destroy to list_init once for each element as it
is removed, provided destroy was not set to
NULL.
Complexity
O (n), where n is the number of elements in the
linked list.
int list_ins_next(List *list, ListElmt *element, const void *data);
Return Value
0 if inserting the element is successful, or
-1 otherwise.
Description
Inserts an element just after
element in the linked list specified by
list. If element is NULL, the
new element is inserted at the head of the list. The new
element contains a pointer to data, so the
memory referenced by data should remain valid
as long as the element remains in the list. It is the
responsibility of the caller to manage the storage associated
with data.
Complexity
O (1)
int list_rem_next(List *list, ListElmt *element, void **data);
Return Value
0 if removing the element is successful, or
-1 otherwise.
Description
Removes the element just after
element from the linked list specified by
list. If element is NULL, the
element at the head of the list is removed. Upon return,
data points to the data stored in the element
that was removed. It is the responsibility of the caller to
manage the storage associated with the data.
Complexity
O (1)
int list_size(const List *list);
Return Value
Number of elements in the list.
Description
Macro that evaluates to the number of
elements in the linked list specified by
list.
Complexity
O (1)
ListElmt *list_head(const List *list);
Return Value
Element at the head of the list.
Description
Macro that evaluates to the element at
the head of the linked list specified by
list.
Complexity
O (1)
ListElmt *list_tail(const List *list);
Return Value
Element at the tail of the list.
Description
Macro that evaluates
to the element at the tail of the linked list specified by
list.
Complexity
O (1)
int list_is_head(const ListElmt *element);
Return Value
1 if the element is
at the head of the list, or
otherwise.
Description
Macro that determines whether the element
specified as element is at the head of a
linked list.
Complexity
O (1)
int list_is_tail(const ListElmt *element);
Return Value
1 if the element is
at the tail of the list, or otherwise.
Description
Macro that determines whether the element
specified as element is at the tail of a
linked list.
Complexity
O (1)
void *list_data(const ListElmt *element);
Return Value
Data stored in the element.
Description
Macro that evaluates
to the data stored in the element of a linked list specified
by element.
Complexity
O (1)
ListElmt *list_next(const ListElmt *element);
Return Value
Element following the specified
element.
Description
Macro that evaluates to the element of a
linked list following the element specified by
element.
Complexity
O (1)
|


---
layout: page
header-img: "img/mcgill_univ_winter.gif"
---
Zhenyuan Ma
M.Eng.
Website
Zhenyuan Ma joined the smart transport group as a master student in January 2019 and she graduated in January 2021. She got her Bachelor degree in computer science at The Hong Kong Polytechnic University. She is interested in big data analysis, machine learning and algorithms, agent-based simulation and travel demand forecasting, and spatiotemporal analysis. Her master's thesis topic is multi-level population synthesis and missing value imputation on survey and census data.
Research Interests
- Big data analysis
- Agent-based simulation
- Travel demand forecasting
Selected Publications


Prism Ops brings smart automation to our customer’s daily IT operations. The typical operations workflow is a continuous cycle of monitoring, analyzing and taking action where necessary. Prism Ops mirrors traditional IT Admin’s workflows to improve operations efficiency. With Prism Ops, IT Admins are able to connect insights from machine data to automate this typical flow using the power of the machine learning engine X-FIT and the X-Play automation engine.
In this lab you will learn how Prism Ops can help IT Admins monitor, analyze and automatically act when a VM’s memory resource is constrained.
Open your Prism Central and navigate to the VMs page. Note down the IP Address of the GTSPrismOpsLabUtilityServer. You will need to access this IP Address throughout this lab.
Open a new tab in the browser, and navigate to http://<GTSPrismOpsLabUtilityServer_IP_ADDRESS>/alerts [example http://<IP_ADDRESS>/alerts]. It is possible you may need to log into the VM if you are the first one to use it. In that case, fill out the Prism Central IP (from the assignment spreadsheet, not the IP we just documented), Username and Password and click Login.
Once you have landed on the alerts page, leave this tab open. It will be used in a later portion of this lab.
In a new tab, navigate to http://<GTSPrismOpsLabUtilityServer_IP_ADDRESS>/ to complete the lab from [example http://<IP_ADDRESS>/]. Use this tab to complete the lab, unless specifically directed otherwise.
Prism Ops uses X-FIT machine learning to detect and monitor the behaviors of VMs running within the managed clusters.
Using machine learning Prism Ops analyzes the data, and applies a classification to VMs that are inefficient. The following are short descriptions of the different classifications:
- Overprovisioned: VMs identified as using minimal amounts of assigned resources.
- Inactive: VMs that have been powered off for a period of time or that are running VMs that do not consume any CPU, memory, or I/O resources.
- Constrained: VMs that could see improved performance with additional resources.
- Bully: VMs identified as using an abundance of resources and affecting other VMs.
Select > Dashboard (if not already there).
From the Dashboard, take a look at the VM Efficiency widget. This widget gives a summary of inefficient VMs that Prism Ops’s X-FIT machine learning has detected in your environment. Click on the View All Inefficient VMs link at the bottom of the widget to take a closer look.
You are now viewing the Efficiency focus. The Efficiency Detail column lists specifics on why Prism Ops flagged each VM as inefficient. You can hover the text in the Efficiency Detail column to view the full description.
Once an admin has examined the list of VM on the efficiency list, they can determine any VMs they wish to take action against. VMs that have too many or too few resources will require the individual VMs to be resized. This can be done using any of the various methods listed below:
Using this machine learning data, Prism Ops is also able to generate baselines, or expected ranges, for VM, Host and Cluster metric data. The X-FIT algorithms learn the normal behavior of these entities and represent that as a baseline range on the different charts. Whenever a metric value deviates from this expected range, Prism Ops will raise an anomaly.
Now let’s take a take a look at a VM by searching for and selecting ‘bootcamp_good_1’.
Click on Metrics > CPU Usage. Notice a dark blue line, and a lighter blue area around it. The dark blue line is the CPU Usage. The light blue area is the expected CPU Usage range for this VM. This particular VM is running an application that is upgraded at the same time each day, which explains the usage pattern. Notice that X-FIT detects this usage pattern, and has adjusted the expected range automatically. In this case, an anomaly has been raised for this VM, because the CPU Usage is far above the expected range. You can also reduce the time range to Last 24 hours to examine the chart more closely.
Click Alert Settings at the upper right to set an alert policy.
On the right hand side, you can change some of the configurations however you choose. In the below example, under Behavioral Anomaly, Every time there is an anomaly, alert was set to Warning, and Ignore all anomalies between was set to 10% and 70%. Under Static threshold, Alert Critical if was configured to > 95%.
Hit Cancel to exit the policy creation workflow.
Now let’s look at how we can take automated action to resolve some of these inefficiencies. For this lab we will assume that this VM is constrained for memory, and will show how we can automatically remediate the right sizing of this VM. We will also use a custom ticket system to give an idea of how this typical workflow could integrate with ticketing system such as ServiceNow.
Navigate to your _Initials_-LinuxToolsVM. The examples will use a VM called ABC - VM.
Note the current Memory Capacity of the VM, as we will later increase it with X-Play. The placement of widgets may differ for you compared to the below example. Also, you may need to scroll down within the Properties widget to find this value.
Navigate to the Action Gallery using the search bar.
Select the REST API action and choose the Clone operation from the actions menu.
We are creating an Action that we can later use in our playbook to generate a service ticket. Fill in the following values, and then click Copy.
``{"vm_name":"{{trigger[0].source_entity_info.name}}","vm_id":"{{trigger[0].source_entity_info.uuid}}","alert_name":"{{trigger[0].alert_entity_info.name}}","alert_id":"{{trigger[0].alert_entity_info.uuid}}"}``
Content-Type:application/json;charset=utf-8
Use the search bar to navigate to Playbooks.
Now we will create a Playbook to automate the generation of a service ticket. Click Create Playbook at the top of the table view.
Select Alert as a trigger
Search and select VM {vm_name} Memory Constrained as the alert policy.
Select the Specify VMs radio button and choose the _Initials_-LinuxToolsVM. This will make it so only alerts raised on your VM will trigger this Playbook.
First, we would like to generate a ticket for this alert. Click Add Action on the left side, and select the _Initials_ - Generate Service Ticket action. Note: For this lab, we set up our own ticketing system to illustrate the full workflow. You may noticed there is a ServiceNow action which can achieve the same workflow, but specifically for ServiceNow.
Notice the details from the Generate Service Ticket action are automatically filled in for you.
Next we would like to notify someone that the ticket was created by X-Play. Click Add Action and select the Email action. Fill in the field in the email action. Here are the examples.
Be sure to replace <GTSPrismOpsLabUtilityServer_IP_ADDRESS> in the message with its IP Address.
``Service Ticket Pending Approval: {{trigger[0].alert_entity_info.name}}``
``The alert {{trigger[0].alert_entity_info.name}} triggered Playbook {{playbook.playbook_name}} and has generated a Service ticket for the VM: {{trigger[0].source_entity_info.name}} which is now pending your approval. A ticket has been generated for you to take action on at http://<GTSPrismOpsLabUtilityServer_IP_ADDRESS>/ticketsystem``
Click Save & Close button and save it with a name _Initials_ - Generate Service Ticket for Constrained VM. Be sure to click _Enabled_ toggle.
Now we will create one more Playbook. This will be executed when we resolve the service ticket by adding memory to the affected VM, and sending an email once complete. Click Create Playbook at the top of the table view.
Select Manual as the trigger. Note: The ticket system we have constructed for this lab will call the trigger API provided by manual trigger, however this API is not public. In 5.17, we are introducing a Webhook Trigger which will expose a public API that allows achieving this same behavior. Tools like ServiceNow can use this Webhook to call Prism Central to trigger a playbook.
Select the VM entity type from the dropdown, as this playbook will be applied to VMs.
Click Add Action on the left side and select the VM Add Memory action.
Set the empty fields according to the screen below. Next, we would like to notify someone that an automated action was taken. Click Add Action to add the email action
Fill in the field in the email action. Here are the examples.
Playbook {{playbook.playbook_name}} was executed.
{{playbook.playbook_name}} has run and has added 1GiB of Memory to the VM {{trigger[0].source_entity_info.name}}.
Note
You are welcome to compose your own subject message. The above is just an example. You could click on Parameters to further customize the message.
Last, we would like to notify the ticket service to resolve the ticket. Click Add Action to add the REST API action. Fill in the following values replacing the <GTSPrismOpsLabUtilityServer_IP_ADDRESS> in the URL field.
{"vm_id":"{{trigger[0].source_entity_info.uuid}}"}
Click Save & Close button and save it with a name “Initials - Resolve Service Ticket”. Be sure to click _Enabled_ toggle.
Now let’s trigger the workflow. Navigate to the tab you opened at the beginning of the lab, with the /alerts URL [example <IP_ADDRESS>/alerts]. Select the Radio for VM Memory Constrained and select your VM. Click the Simulate Alert button. This will simulate a memory constrained alert on your VM.
You should receive an email to the email address you put down in the first playbook. It may take up to 5 minutes.
Inside the email click the link to visit the ticket system. Alternatively, you can directly access the ticket system by navigating to http://<GTSPrismOpsLabUtilityServer_IP_ADDRESS>/ticketsystem from a new tab in your browser.
Identify the ticket created for your VM, and click the vertical dots icon to show the Action menu. Click the Run Playbook option.
Choose the 2nd playbook you created _Initials_ - Resolve Service Ticket and click Submit.
Switch back to the previous tab with the Prism Central console open. Click on the _Initials_ - Resolve Service Ticket playbook, and then click the Plays tab towards the top of the view to take a look at the Plays that executed for this playbook. Click on the title of the Play in the table, to take a closer look.
The sections in this view can be expanded to show more details for each item. If there were any errors, they would also be surfaced in this view.
You can navigate back to your VM, and verify that the memory was indeed increased by 1 GiB.
You should also get an email telling you that the playbook ran.


These are not all my interests, but they are ones that don't really fit anywhere else…a hodgepodge, if you will.
Languages
Currently I am learning German. It feels as though I've been working my way through the Living Language German course forever, but I am going to be touring Germany in the Fall of 2022, and I fully intend to be able to understand what's going on when I'm there. One of my objectives in learning Python was to write scripts that would help with German practice.
Over the years I have taken at least a slight interest in learning other languages, including:
Books
I have an extensive collection of books, both fiction and non-fiction. Fortunately the LibraryThing website offers a convenient way to catalog books, otherwise I'd never be able to keep up with what I have.
Me at LibraryThing
DVDs
I have many more DVDs than I have books, and unfortunately I haven't found a database program that will catalog them the way I want. For the most part they are just in an Excel spreadsheet, which is hopelessly out-of-date. Oh, maybe that's another Python script I could write...


The Moment A Judge Recognised Her School Friend In Dock -VIDEO 21 Nov 2019 by Peace FM Online The Moment Judge Recognised Her School Friend In Dock -VIDEO Featured Video


User Feedback & Revised Design Goals
All users liked the customized dish recommendations and the function to directly look up ingredient information. This was reassuring for us, since these two functions are our primary focus, and what distinguishes us from existing apps.
Avoiding Embarrassment & Empowering our Users
Some users were confused about ordering directly in the app, since it is not a convention for them to order in an app within a restaurant, especially when others sitting on the same table are still ordering by talking to the waiters/waitresses. They were also afraid that by being the only one ordering in the app, they would stand out among their friends and feel embarrassed.
Since the goal of our app is to help them feel less embarrassed while ordering in these restaurants, we decided to get rid of the ordering function, and focus our attention on helping them better communicate with waiters.
After talking with more users, we came to realize that one of our most important goals is to empower our users, who are not confident about how to order dishes right now.
Refined Design Goals & Features
We refined our design goals and matched the features we hoped to implement to the goals we hope to achieve:
The rationale for the last point is that for the international student group we’re targeting, they usually know the English language well enough to live and study in the U.S.; they just have little exposure to the diverse cuisines in the U.S., and feel intimidated to get started. Therefore, instead of providing them with a tool that’s completely in their language, we hope to build something that’s primarily in English, with translations on demand. In this way, we hope that our users can gradually learn the terms they don’t understand, and rely on our tool less and less as they use it more.
High-Fidelity Design - Iteration 1
For the first iteration, my primary goal is to validate whether the design helps different types of users be more confident, make ordering decisions faster, feel comfortable visiting ethnic restaurants and ordering in front of people who know the cuisine well, as well as learn the basic terms of different cuisines over time. I also hoped to test the usability of the design, so that I can improve upon it.
I used Sketch and InVision to create a basic interactive prototype to illustrate enough functionalities for me to test my hypotheses.


Based on what has been done on the Assignments page for BF3, I'd suggest to do the same for the Unlocks, Assignments and Awards pages for BF4.
Quick links should allow you to go directly to the weapons/vehicles/whatever category you want to see without having to scroll down the entire page.
Minimizing should allow you to "hide" categories you don't want to see anymore.
As I've already said, both these "features" are in the Assignments page for BF3 so they should be possible (I guess).
Example image:
minimize.png


--- layout: default ---
Thapar University, Patiala. Computer Engineering, undergraduate. Graduating in June, 2018.
+91 -<PHONE_NUMBER>
Currently I'm working at MAQ Software, Hyderabad, as a Software intern. Here at MAQ Software, I'm a part of Text analytics (VoC analytics) team. My current project is to analyse customer feedbacks provided by client using Natural Language Processing and Machine Learning Algorithms. I have also helped my team to design and develop Machine learning courses for internal (company) learning portal. I mostly code in python-3 and have experience in python libraries: scikit-learn, Tensorlflow, Keras, gensim, nltk.
I have completed quite few online courses to enhance my technical capabalities. Recently I have completed deep learning specialization by Andrew NG, on Coursera and learned about Computer Vision, Natural Language Processing, mathematical details about ANN, CNN, RNN, LSTM and how they can be used in real world projects, check out some my projects.
I am actively looking for full time opportunities. If your company has openings in the field of Software Development, Machine Learning, send me an email at<EMAIL_ADDRESS>Also check out my projects and resume.


default
reference element
target element
in a container with margins
reference element
target element
in a container with margins and padding
reference element
target element
with padding on the reference element
reference element
target element
with padding on the target element
reference element
target element
with margin on the reference element
reference element
target element
with margin on the target element
reference element
target element
with a
<main>
with margins
reference element
reference element (nested)
this one is on click
demo enabled (1):
this one is on mousemove
demo enabled (2):
target element (in body)
target element
target element
target element


Material Desgin Snackbars with Callbacks and Actions. With the new Kabeers Snackbar JS. Dependancy Free. Small and easy to use
Snackbars inform users of a process that an app has performed or will perform. They appear temporarily, towards the bottom of the screen. They shouldn’t interrupt the user experience, and they don’t require user input to disappear.
More Information and Documentation about Snackbars at material.io/components/snackbar
SnackBar JS is available from JS Delivr, Kabeers CDNs, and Our AJAX Libraries Registery Snackbar Requires JS files plus its Custom CSS files (Snackbar CSS)
Kabeers Network CDN Page Here
AJAX Libs CDNs (Kabeers Network NPM Registery) Click Here
JS Deliever Here
K Avatar Js doesnot need extra JS code to instantiate. Just Call Snackbar Function CallbackFunction, Message are Important. Others are Optional Parameters
#Basic Syntax
Snackbar({message: "Snackbar message", actiontext: 'Button Text', time:500}, CallbackFunction, beforeShowFunction, afterShowFunction)
Snackbar Supports Both Vanilla Javascript Jquery or any other Selector Engine,
//Vanilla Javascript
document.querySelector(".one").addEventListener("click", () => {
Snackbar({ message: "Hello! I am a Simple & Plain Snackbar!"});
});
document.querySelector(".two").addEventListener("click", () => {
Snackbar({
message: "Hello! I am a Snackbar with All Features Possiable!",
actiontext: "Redo",
time:500
}, () => {
alert("Snackbar Action Button Clicked");
}, () => {
console.log('beforeShow')
}, () => {
console.log('AfterShow')
});
});
//JQuery
$(".one").on("click", () => {
Snackbar({ message: "Hello! I am a Simple & Plain Snackbar!"});
});
$(".two").on("click", () => {
Snackbar({
message: "Hello! I am a Snackbar with All Features Possiable!",
actiontext: "Redo",
time:500
}, () => {
alert("Snackbar Action Button Clicked");
}, () => {
console.log('beforeShow')
}, () => {
console.log('AfterShow')
});
});
</script>```
### Tips
```Snackbar({messange: "Snackbar message", actiontext: 'Button Text'}, async () => {
alert('CallBack Functions Can Be Called Async!')
}))```
### ES5 Support
```Snackbar({messange: "Snackbar message", actiontext: 'Button Text'}, async function () {
alert('CallBack Functions Can Be Called Async!')
}))
import {Snackbar} from './path/to/snackbar.umd.js';
--snackbar_action : red;
}```


bags (Multisets)¶
bag is a multiset implementation for Python. Currently, bags have constant time inclusion testing but can only contain hashable elements due to the implementation.
There are three classes provided:
Bag
An abstract base class for bags.
bag
A mutable (unhashable) bag.
frozenbag
An immutable (implements
collections.abc.Hashable
) version of a bag.
Both classes implement collections.abc.Sized
,
collections.abc.Iterable
and collections.abc.Container
.
Both classes implement collections.abc.Collection
starting in Python
3.6 and the polyfilled Collection
for Python < 3.6.
Set Operations¶
bag
and frozenbag
use python operators for multiset
operations:
__add__ (a + b): The sum of two multisets
__sub__ (a - b): The difference between a and b
__and__ (a & b): The intersection of a and b
__or__ (a | b): The union of a and b
__xor__ (a ^ b): The symmetric difference between a and b
bag
has the equivalent in-place operators defined.
Comparison Methods¶
Bags are comparable only to other bags. Ordering comparisons are done setwise.
>>> bag('ac') <= bag('ab')
False
>>> bag('ac') >= bag('ab')
False
>>> bag('a') <= bag('a') < bag('aa')
True
>>> bag('aa') <= bag('a')
False
Compared to existing similar implementations¶
collections.Counter¶
Counters don’t really behave like Collections - Sized, Iterable, Containers
Adding and Removing¶
>>> c = Counter()
>>> c['a'] += 1
>>> c['a'] -= 1
>>> 'a' in c
True
>>> b = bag()
>>> b.add('a')
>>> 'a' in b
True
>>> b.remove('a')
>>> 'a' in b
False
len
¶
>>> c = Counter()
>>> c['a'] += 1
>>> len(c)
1
>>> c['a'] -= 1
>>> len(c)
1
>>> c['a'] += 2
>>> len(c)
1
>>> len(Counter('aaabbc'))
3
>>> b = bag()
>>> b.add('a')
>>> len(b)
1
>>> b.remove('a')
>>> len(b)
0
>>> len(bag('aaabbc'))
6
Iterating¶
>>> for item in Counter('aaa'): print(item)
a
>>> for item in bag('aaa'): print(item)
a
a
a
Compared to Standard Types¶
bag vs. list¶
Inclusion testing is O(1)
Adding and removing elements is O(1)
Cannot add mutable elements
Elements aren’t ordered
bag vs. set¶
Can add multiple instances of equal elements
New Methods¶
These are bag methods that are not implementing an abstract method from a standard Python ABC.
num_unique_elements
Returns the number of unique elements in the bag. O(1)
unique_elements()
Returns a set of all the unique elements in the bag. O(1)
nlargest(n=None)
Returns the n most common elements and their counts from most common to least. If n is None then all elements are returned. O(n log n)
copy()
Returns a shallow copy of self. O(self.num_unique_elements())
isdisjoint(other: Iterable)
Tests if self is disjoint with any other Iterable. O(len(other))
issubset(other: Iterable)
Tests if self is a subset of another Iterable.
issuperset(other: Iterable)
Tests if self is a superset of another Iterable.
from_mapping(map: Mapping)
Classmethod to create a bag from a Mapping that maps elements to counts.
The following are only for mutable bags (not frozenbags).
pop()
add(elem)
discard(elem)
remove(elem)
clear()
API¶
Bag¶
-
class
collections_extended.
Bag
(iterable=None)[source]¶ Bases:
collections.abc.Collection
Base class for bag classes.
Base class for bag and frozenbag. Is not mutable and not hashable, so there’s no reason to use this instead of either bag or frozenbag.
-
__init__
(iterable=None)[source]¶ Create a new bag.
If iterable isn’t given, is None or is empty then the bag starts empty. Otherwise each element from iterable will be added to the bag however many times it appears.
This runs in O(len(iterable))
-
count
(value)[source]¶ Return the number of value present in this bag.
If value is not in the bag no Error is raised, instead 0 is returned.
This runs in O(1) time
- Parameters
value – The element of self to get the count of
- Returns
The count of value in self
- Return type
int
-
nlargest
(n=None)[source]¶ List the n most common elements and their counts. List is from the most common to the least. If n is None, the list all element counts. Run time should be O(m log m) where m is len(self) Args: n (int): The number of elements to return
Deprecated since version 1.0: Use heapq.nlargest(n, self.counts(), key=itemgetter(1)) instead or sorted(self.counts(), reverse=True, key=itemgetter(1)) for n=None
-
counts
()[source]¶ Return a view of the unique elements in self and their counts.
New in version 1.1.
-
classmethod
from_mapping
(mapping)[source]¶ Create a bag from a dict of elem->count.
Each key in the dict is added if the value is > 0.
- Raises
ValueError – If any count is < 0.
-
issubset
(other)[source]¶ Check that every element in self has a count <= in other.
- Parameters
other (Iterable) –
-
issuperset
(other)[source]¶ Check that every element in self has a count >= in other.
- Parameters
other (Iterable) –
-
__and__
(other)[source]¶ Intersection is the minimum of corresponding counts.
- This runs in O(l + n) where:
n is self.num_unique_elements()
l = 1 if other is a bag else l = len(other)
-
isdisjoint
(other)[source]¶ Return if this bag is disjoint with the passed collection.
This runs in O(len(other))
-
__or__
(other)[source]¶ Union is the maximum of all elements.
- This runs in O(m + n) where:
n = self.num_unique_elements()
m = other.num_unique_elements() if other is a bag else m = len(other)
-
__add__
(other)[source]¶ Return a new bag also containing all the elements of other.
self + other = self & other + self | other
- This runs in O(m + n) where:
n is self.num_unique_elements()
m is len(other)
- Parameters
other (Iterable) – elements to add to self
-
__sub__
(other)[source]¶ Difference between the sets.
For normal sets this is all x s.t. x in self and x not in other. For bags this is count(x) = max(0, self.count(x)-other.count(x))
- This runs in O(m + n) where:
n is self.num_unique_elements()
m is len(other)
- Parameters
other (Iterable) – elements to remove
-
product
(other, operator=None)[source]¶ Cartesian product of the two sets.
Optionally, pass an operator to combine elements instead of creating a tuple.
- This should run in O(m*n+l) where:
m is the number of unique elements in self
n is the number of unique elements in other
l is 0 if other is a bag, else l is the len(other)
- Parameters
other (Iterable) – The iterable to take the product with.
operator (Callable) – A function that accepts an element from self and other and returns a combined value to include in the return value.
-
bag¶
-
class
collections_extended.
bag
(iterable=None)[source]¶ Bases:
collections_extended.bags.Bag
bag is a mutable unhashable bag.
-
remove
(elem)[source]¶ Remove elem from this bag, raising a ValueError if it isn’t present.
- Parameters
elem – object to remove from self
- Raises
ValueError – if the elem isn’t present
-


March 1989
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).
Tim starts work on a hypertext GUI browser+editor using the NeXTStep development environment. He makes up "WorldWideWeb" as a name for the program. (See the first browser screenshot) "World
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).
Information Management: A Proposal" written by Tim BL and circulated for comments at CERN (TBL). Paper "HyperText and CERN" produced as background (text or WriteNow format).