The Specification class contains the metadata for a Gem. Typically defined in a .gemspec file or a Rakefile, and looks like this:
spec = Gem::Specification.new do |s| s.name = 'example' s.version = '1.0' s.summary = 'Example gem specification' ... end
For a great way to package gems, use Hoe.
The the version number of a specification that does not specify one (i.e. RubyGems 0.7 or earlier).
The specification version applied to any new Specification instances created. This should be bumped whenever something in the spec format changes.
An informal list of changes to the specification. The highest-valued key should be equal to the CURRENT_SPECIFICATION_VERSION.
true when this gemspec has been loaded from a specifications directory. This attribute is not persisted.
The version of RubyGems used to create this gem.
Do not set this, it is set automatically when the gem is packaged.
The Gem::Specification version of this gemspec.
Do not set this, it is set automatically when the gem is packaged.
The date this gem was created
Do not set this, it is set automatically when the gem is packaged.
A short summary of this gem’s description. Displayed in `gem list -d`.
The description should be more detailed than the summary. For example, you might wish to copy the entire README into the description.
As of RubyGems 1.3.2 newlines are no longer stripped.
Paths in the gem to add to $LOAD_PATH when this gem is activated.
The default ‘lib’ is typically sufficient.
A contact email for this gem
If you are providing multiple authors and multiple emails they should be in the same order such that:
Hash[*spec.authors.zip(spec.emails).flatten]
Gives a hash of author name to email address.
The rubyforge project this gem lives under. i.e. RubyGems’ rubyforge_project is “rubygems”.
Autorequire was used by old RubyGems to automatically require a file. It no longer is supported.
Deprecated and ignored, defaults to true.
Formerly used to indicate this gem was RDoc-capable.
The platform this gem runs on. See Gem::Platform for details.
Setting this to any value other than Gem::Platform::RUBY or Gem::Platform::CURRENT is probably wrong.
The license(s) for the library. Each license must be a short name, no more than 64 characters.
Files included in this gem. You cannot append to this accessor, you must assign to it.
Only add files you can require to this list, not directories, etc.
Directories are automatically stripped from this list when building a gem, other non-files cause an error.
Test files included in this gem. You cannot append to this accessor, you must assign to it.
Extensions to build when installing the gem. See Gem::Installer#build_extensions for valid values.
Load custom marshal format, re-initializing defaults as needed
# File lib/rubygems/specification.rb, line 288 288: def self._load(str) 289: array = Marshal.load str 290: 291: spec = Gem::Specification.new 292: spec.instance_variable_set :@specification_version, array[1] 293: 294: current_version = CURRENT_SPECIFICATION_VERSION 295: 296: field_count = if spec.specification_version > current_version then 297: spec.instance_variable_set :@specification_version, 298: current_version 299: MARSHAL_FIELDS[current_version] 300: else 301: MARSHAL_FIELDS[spec.specification_version] 302: end 303: 304: if array.size < field_count then 305: raise TypeError, "invalid Gem::Specification format #{array.inspect}" 306: end 307: 308: spec.instance_variable_set :@rubygems_version, array[0] 309: # spec version 310: spec.instance_variable_set :@name, array[2] 311: spec.instance_variable_set :@version, array[3] 312: spec.instance_variable_set :@date, array[4] 313: spec.instance_variable_set :@summary, array[5] 314: spec.instance_variable_set :@required_ruby_version, array[6] 315: spec.instance_variable_set :@required_rubygems_version, array[7] 316: spec.instance_variable_set :@original_platform, array[8] 317: spec.instance_variable_set :@dependencies, array[9] 318: spec.instance_variable_set :@rubyforge_project, array[10] 319: spec.instance_variable_set :@email, array[11] 320: spec.instance_variable_set :@authors, array[12] 321: spec.instance_variable_set :@description, array[13] 322: spec.instance_variable_set :@homepage, array[14] 323: spec.instance_variable_set :@has_rdoc, array[15] 324: spec.instance_variable_set :@new_platform, array[16] 325: spec.instance_variable_set :@platform, array[16].to_s 326: spec.instance_variable_set :@license, array[17] 327: spec.instance_variable_set :@loaded, false 328: 329: spec 330: end
Same as :attribute, but ensures that values assigned to the attribute are array values by applying :to_a to the value.
# File lib/rubygems/specification.rb, line 175 175: def self.array_attribute(name) 176: @@non_nil_attributes << ["@#{name}".intern, []] 177: 178: @@array_attributes << name 179: @@attributes << [name, []] 180: @@default_value[name] = [] 181: code = %{ 182: def #{name} 183: @#{name} ||= [] 184: end 185: def #{name}=(value) 186: @#{name} = Array(value) 187: end 188: } 189: 190: module_eval code, __FILE__, __LINE__ - 9 191: end
Specification attributes that are arrays (appendable and so-forth)
# File lib/rubygems/specification.rb, line 148 148: def self.array_attributes 149: @@array_attributes.dup 150: end
Specifies the name and default for a specification attribute, and creates a reader and writer method like Module#attr_accessor.
The reader method returns the default if the value hasn’t been set.
# File lib/rubygems/specification.rb, line 158 158: def self.attribute(name, default=nil) 159: ivar_name = "@#{name}".intern 160: if default.nil? then 161: @@nil_attributes << ivar_name 162: else 163: @@non_nil_attributes << [ivar_name, default] 164: end 165: 166: @@attributes << [name, default] 167: @@default_value[name] = default 168: attr_accessor(name) 169: end
Defines a singular version of an existing plural attribute (i.e. one whose value is expected to be an array). This means just creating a helper method that takes a single value and appends it to the array. These are created for convenience, so that in a spec, one can write
s.require_path = 'mylib'
instead of:
s.require_paths = ['mylib']
That above convenience is available courtesy of:
attribute_alias_singular :require_path, :require_paths
# File lib/rubygems/specification.rb, line 247 247: def self.attribute_alias_singular(singular, plural) 248: define_method("#{singular}=") { |val| 249: send("#{plural}=", [val]) 250: } 251: define_method("#{singular}") { 252: val = send("#{plural}") 253: val.nil? ? nil : val.first 254: } 255: end
Default values for specification attributes
# File lib/rubygems/specification.rb, line 120 120: def self.attribute_defaults 121: @@attributes.dup 122: end
Names of all specification attributes
# File lib/rubygems/specification.rb, line 113 113: def self.attribute_names 114: @@attributes.map { |name, default| name } 115: end
Shortcut for creating several attributes at once (each with a default value of nil).
# File lib/rubygems/specification.rb, line 216 216: def self.attributes(*args) 217: args.each do |arg| 218: attribute(arg, nil) 219: end 220: end
The default value for specification attribute name
# File lib/rubygems/specification.rb, line 127 127: def self.default_value(name) 128: @@default_value[name] 129: end
Special loader for YAML files. When a Specification object is loaded from a YAML file, it bypasses the normal Ruby object initialization routine (#). This method makes up for that and deals with gems of different ages.
‘input’ can be anything that YAML.load() accepts: String or IO.
# File lib/rubygems/specification.rb, line 478 478: def self.from_yaml(input) 479: input = normalize_yaml_input input 480: spec = YAML.load input 481: 482: if spec && spec.class == FalseClass then 483: raise Gem::EndOfYAMLException 484: end 485: 486: unless Gem::Specification === spec then 487: raise Gem::Exception, "YAML data doesn't evaluate to gem specification" 488: end 489: 490: unless (spec.instance_variables.include? '@specification_version' or 491: spec.instance_variables.include? :@specification_version) and 492: spec.instance_variable_get :@specification_version 493: spec.instance_variable_set :@specification_version, 494: NONEXISTENT_SPECIFICATION_VERSION 495: end 496: 497: spec 498: end
Loads ruby format gemspec from filename
# File lib/rubygems/specification.rb, line 503 503: def self.load(filename) 504: gemspec = nil 505: raise "NESTED Specification.load calls not allowed!" if @@gather 506: @@gather = proc { |gs| gemspec = gs } 507: data = File.read filename 508: eval data, nil, filename 509: gemspec 510: ensure 511: @@gather = nil 512: end
Specification constructor. Assigns the default values to the attributes and yields itself for further initialization. Optionally takes name and version.
# File lib/rubygems/specification.rb, line 416 416: def initialize name = nil, version = nil 417: @new_platform = nil 418: assign_defaults 419: @loaded = false 420: @loaded_from = nil 421: 422: self.name = name if name 423: self.version = version if version 424: 425: yield self if block_given? 426: 427: @@gather.call(self) if @@gather 428: end
Make sure the YAML specification is properly formatted with dashes
# File lib/rubygems/specification.rb, line 517 517: def self.normalize_yaml_input(input) 518: result = input.respond_to?(:read) ? input.read : input 519: result = "--- " + result unless result =~ /^--- / 520: result 521: end
Some attributes require special behaviour when they are accessed. This allows for that.
# File lib/rubygems/specification.rb, line 226 226: def self.overwrite_accessor(name, &block) 227: remove_method name 228: define_method(name, &block) 229: end
Sometimes we don’t want the world to use a setter method for a particular attribute.
read_only makes it private so we can still use it internally.
# File lib/rubygems/specification.rb, line 207 207: def self.read_only(*names) 208: names.each do |name| 209: private "#{name}=" 210: end 211: end
Same as attribute above, but also records this attribute as mandatory.
# File lib/rubygems/specification.rb, line 196 196: def self.required_attribute(*args) 197: @@required_attributes << args.first 198: attribute(*args) 199: end
Dump only crucial instance variables.
# File lib/rubygems/specification.rb, line 262 262: def _dump(limit) 263: Marshal.dump [ 264: @rubygems_version, 265: @specification_version, 266: @name, 267: @version, 268: (Time === @date ? @date : (require 'time'; Time.parse(@date.to_s))), 269: @summary, 270: @required_ruby_version, 271: @required_rubygems_version, 272: @original_platform, 273: @dependencies, 274: @rubyforge_project, 275: @email, 276: @authors, 277: @description, 278: @homepage, 279: @has_rdoc, 280: @new_platform, 281: @licenses 282: ] 283: end
Returns an array with bindir attached to each executable in the executables list
# File lib/rubygems/specification.rb, line 372 372: def add_bindir(executables) 373: return nil if executables.nil? 374: 375: if @bindir then 376: Array(executables).map { |e| File.join(@bindir, e) } 377: else 378: executables 379: end 380: rescue 381: return nil 382: end
Adds a runtime dependency
Adds a development dependency named gem with requirements to this Gem. For example:
spec.add_development_dependency 'jabber4r', '> 0.1', '<= 0.5'
Development dependencies aren’t installed by default and aren’t activated when a gem is required.
# File lib/rubygems/specification.rb, line 551 551: def add_development_dependency(gem, *requirements) 552: add_dependency_with_type(gem, :development, *requirements) 553: end
Adds a runtime dependency named gem with requirements to this Gem. For example:
spec.add_runtime_dependency 'jabber4r', '> 0.1', '<= 0.5'
# File lib/rubygems/specification.rb, line 561 561: def add_runtime_dependency(gem, *requirements) 562: add_dependency_with_type(gem, :runtime, *requirements) 563: end
Each attribute has a default value (possibly nil). Here, we initialize all attributes to their default value. This is done through the accessor methods, so special behaviours will be honored. Furthermore, we take a copy of the default so each specification instance has its own empty arrays, etc.
# File lib/rubygems/specification.rb, line 452 452: def assign_defaults 453: @@nil_attributes.each do |name| 454: instance_variable_set name, nil 455: end 456: 457: @@non_nil_attributes.each do |name, default| 458: value = case default 459: when Time, Numeric, Symbol, true, false, nil then default 460: else default.dup 461: end 462: 463: instance_variable_set name, value 464: end 465: 466: # HACK 467: instance_variable_set :@new_platform, Gem::Platform::RUBY 468: end
Return a list of all gems that have a dependency on this gemspec. The list is structured with entries that conform to:
[depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
# File lib/rubygems/specification.rb, line 954 954: def dependent_gems 955: out = [] 956: Gem.source_index.each do |name,gem| 957: gem.dependencies.each do |dep| 958: if self.satisfies_requirement?(dep) then 959: sats = [] 960: find_all_satisfiers(dep) do |sat| 961: sats << sat 962: end 963: out << [gem, dep, sats] 964: end 965: end 966: end 967: out 968: end
List of dependencies that are used for development
# File lib/rubygems/specification.rb, line 342 342: def development_dependencies 343: dependencies.select { |d| d.type == :development } 344: end
Singular accessor for #
# File lib/rubygems/specification.rb, line 1339 1339: attribute_alias_singular :executable, :executables
The default (generated) file name of the gem. See also #.
spec.file_name # => "example-1.0.gem"
# File lib/rubygems/specification.rb, line 609 609: def file_name 610: full_name + '.gem' 611: end
The full path to the gem (install path + full name).
# File lib/rubygems/specification.rb, line 598 598: def full_gem_path 599: path = File.join installation_path, 'gems', full_name 600: return path if File.directory? path 601: File.join installation_path, 'gems', original_name 602: end
Returns the full name (name-version) of this Gem. Platform information is included (name-version-platform) if it is specified and not the default Ruby platform.
# File lib/rubygems/specification.rb, line 575 575: def full_name 576: if platform == Gem::Platform::RUBY or platform.nil? then 577: "#{@name}-#{@version}" 578: else 579: "#{@name}-#{@version}-#{platform}" 580: end 581: end
has_rdoc is now ignored
# File lib/rubygems/specification.rb, line 1364 1364: overwrite_accessor :has_rdoc do
True if this gem has files in test_files
# File lib/rubygems/specification.rb, line 403 403: def has_unit_tests? 404: not test_files.empty? 405: end
Duplicates array_attributes from other_spec so state isn’t shared.
# File lib/rubygems/specification.rb, line 433 433: def initialize_copy(other_spec) 434: other_ivars = other_spec.instance_variables 435: other_ivars = other_ivars.map { |ivar| ivar.intern } if # for 1.9 436: other_ivars.any? { |ivar| String === ivar } 437: 438: self.class.array_attributes.each do |name| 439: name = :"@#{name}" 440: next unless other_ivars.include? name 441: instance_variable_set name, other_spec.instance_variable_get(name).dup 442: end 443: end
The directory that this gem was installed into.
# File lib/rubygems/specification.rb, line 616 616: def installation_path 617: unless @loaded_from then 618: raise Gem::Exception, "spec #{full_name} is not from an installed gem" 619: end 620: 621: File.expand_path File.dirname(File.dirname(@loaded_from)) 622: end
Files in the Gem under one of the require_paths
# File lib/rubygems/specification.rb, line 387 387: def lib_files 388: @files.select do |file| 389: require_paths.any? do |path| 390: file.index(path) == 0 391: end 392: end 393: end
Singular accessor for #
# File lib/rubygems/specification.rb, line 1349 1349: attribute_alias_singular :license, :licenses
Sets the rubygems_version to the current RubyGems version
# File lib/rubygems/specification.rb, line 526 526: def mark_version 527: @rubygems_version = Gem::VERSION 528: end
Normalize the list of files so that:
All file lists have redundancies removed.
Files referenced in the extra_rdoc_files are included in the package file list.
# File lib/rubygems/specification.rb, line 939 939: def normalize 940: if defined?(@extra_rdoc_files) and @extra_rdoc_files then 941: @extra_rdoc_files.uniq! 942: @files ||= [] 943: @files.concat(@extra_rdoc_files) 944: end 945: @files.uniq! if @files 946: end
Singular accessor for #
# File lib/rubygems/specification.rb, line 1354 1354: attribute_alias_singular :require_path, :require_paths
List of depedencies that will automatically be activated at runtime.
# File lib/rubygems/specification.rb, line 335 335: def runtime_dependencies 336: dependencies.select { |d| d.type == :runtime || d.type == nil } 337: end
Checks if this specification meets the requirement of dependency.
# File lib/rubygems/specification.rb, line 627 627: def satisfies_requirement?(dependency) 628: return @name == dependency.name && 629: dependency.requirement.satisfied_by?(@version) 630: end
Returns an object you can use to sort specifications in #.
# File lib/rubygems/specification.rb, line 635 635: def sort_obj 636: [@name, @version, @new_platform == Gem::Platform::RUBY ? 1 : 1] 637: end
The default name of the gemspec. See also #
spec.spec_name # => "example-1.0.gemspec"
# File lib/rubygems/specification.rb, line 644 644: def spec_name 645: full_name + '.gemspec' 646: end
Singular accessor for #
# File lib/rubygems/specification.rb, line 1359 1359: attribute_alias_singular :test_file, :test_files
Returns a Ruby code representation of this specification, such that it can be eval’ed and reconstruct the same specification later. Attributes that still have their default values are omitted.
# File lib/rubygems/specification.rb, line 731 731: def to_ruby 732: mark_version 733: result = [] 734: result << "# -*- encoding: utf-8 -*-" 735: result << nil 736: result << "Gem::Specification.new do |s|" 737: 738: result << " s.name = #{ruby_code name}" 739: result << " s.version = #{ruby_code version}" 740: unless platform.nil? or platform == Gem::Platform::RUBY then 741: result << " s.platform = #{ruby_code original_platform}" 742: end 743: result << "" 744: result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version=" 745: 746: handled = [ 747: :dependencies, 748: :name, 749: :platform, 750: :required_rubygems_version, 751: :specification_version, 752: :version, 753: ] 754: 755: attributes = @@attributes.sort_by { |attr_name,| attr_name.to_s } 756: 757: attributes.each do |attr_name, default| 758: next if handled.include? attr_name 759: current_value = self.send(attr_name) 760: if current_value != default or 761: self.class.required_attribute? attr_name then 762: result << " s.#{attr_name} = #{ruby_code current_value}" 763: end 764: end 765: 766: result << nil 767: result << " if s.respond_to? :specification_version then" 768: result << " current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION" 769: result << " s.specification_version = #{specification_version}" 770: result << nil 771: 772: result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then" 773: 774: unless dependencies.empty? then 775: dependencies.each do |dep| 776: version_reqs_param = dep.requirements_list.inspect 777: dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK 778: result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{version_reqs_param})" 779: end 780: end 781: 782: result << " else" 783: 784: unless dependencies.empty? then 785: dependencies.each do |dep| 786: version_reqs_param = dep.requirements_list.inspect 787: result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" 788: end 789: end 790: 791: result << ' end' 792: 793: result << " else" 794: dependencies.each do |dep| 795: version_reqs_param = dep.requirements_list.inspect 796: result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" 797: end 798: result << " end" 799: 800: result << "end" 801: result << nil 802: 803: result.join "\n" 804: end
Checks that the specification contains all required fields, and does a very basic sanity check.
Raises InvalidSpecificationException if the spec does not pass the checks..
# File lib/rubygems/specification.rb, line 813 813: def validate 814: extend Gem::UserInteraction 815: normalize 816: 817: if rubygems_version != Gem::VERSION then 818: raise Gem::InvalidSpecificationException, 819: "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" 820: end 821: 822: @@required_attributes.each do |symbol| 823: unless self.send symbol then 824: raise Gem::InvalidSpecificationException, 825: "missing value for attribute #{symbol}" 826: end 827: end 828: 829: unless String === name then 830: raise Gem::InvalidSpecificationException, 831: "invalid value for attribute name: \"#{name.inspect}\"" 832: end 833: 834: if require_paths.empty? then 835: raise Gem::InvalidSpecificationException, 836: 'specification must have at least one require_path' 837: end 838: 839: @files.delete_if do |file| File.directory? file end 840: @test_files.delete_if do |file| File.directory? file end 841: @executables.delete_if do |file| 842: File.directory? File.join(bindir, file) 843: end 844: @extra_rdoc_files.delete_if do |file| File.directory? file end 845: @extensions.delete_if do |file| File.directory? file end 846: 847: non_files = files.select do |file| 848: !File.file? file 849: end 850: 851: unless non_files.empty? then 852: non_files = non_files.map { |file| file.inspect } 853: raise Gem::InvalidSpecificationException, 854: "[#{non_files.join ", "}] are not files" 855: end 856: 857: unless specification_version.is_a?(Fixnum) 858: raise Gem::InvalidSpecificationException, 859: 'specification_version must be a Fixnum (did you mean version?)' 860: end 861: 862: case platform 863: when Gem::Platform, Gem::Platform::RUBY then # ok 864: else 865: raise Gem::InvalidSpecificationException, 866: "invalid platform #{platform.inspect}, see Gem::Platform" 867: end 868: 869: unless Array === authors and 870: authors.all? { |author| String === author } then 871: raise Gem::InvalidSpecificationException, 872: 'authors must be Array of Strings' 873: end 874: 875: licenses.each { |license| 876: if license.length > 64 877: raise Gem::InvalidSpecificationException, 878: "each license must be 64 characters or less" 879: end 880: } 881: 882: # reject FIXME and TODO 883: 884: unless authors.grep(/FIXME|TODO/).empty? then 885: raise Gem::InvalidSpecificationException, 886: '"FIXME" or "TODO" is not an author' 887: end 888: 889: unless Array(email).grep(/FIXME|TODO/).empty? then 890: raise Gem::InvalidSpecificationException, 891: '"FIXME" or "TODO" is not an email address' 892: end 893: 894: if description =~ /FIXME|TODO/ then 895: raise Gem::InvalidSpecificationException, 896: '"FIXME" or "TODO" is not a description' 897: end 898: 899: if summary =~ /FIXME|TODO/ then 900: raise Gem::InvalidSpecificationException, 901: '"FIXME" or "TODO" is not a summary' 902: end 903: 904: if homepage and not homepage.empty? and 905: homepage !~ /\A[a-z][a-z\d+.-]*:/ then 906: raise Gem::InvalidSpecificationException, 907: "\"#{homepage}\" is not a URI" 908: end 909: 910: # Warnings 911: 912: ]author description email homepage rubyforge_project summary].each do |attribute| 913: value = self.send attribute 914: alert_warning "no #{attribute} specified" if value.nil? or value.empty? 915: end 916: 917: if summary and not summary.empty? and description == summary then 918: alert_warning 'description and summary are identical' 919: end 920: 921: alert_warning "deprecated autorequire specified" if autorequire 922: 923: executables.each do |executable| 924: executable_path = File.join bindir, executable 925: shebang = File.read(executable_path, 2) == '#!' 926: 927: alert_warning "#{executable_path} is missing #! line" unless shebang 928: end 929: 930: true 931: end
Adds a dependency on gem dependency with type type that requires requirements. Valid types are currently :runtime and :development.
# File lib/rubygems/specification.rb, line 1006 1006: def add_dependency_with_type(dependency, type, *requirements) 1007: requirements = if requirements.empty? then 1008: Gem::Requirement.default 1009: else 1010: requirements.flatten 1011: end 1012: 1013: unless dependency.respond_to?(:name) && 1014: dependency.respond_to?(:version_requirements) 1015: 1016: dependency = Gem::Dependency.new(dependency, requirements, type) 1017: end 1018: 1019: dependencies << dependency 1020: end
Finds all gems that satisfy dep
# File lib/rubygems/specification.rb, line 1027 1027: def find_all_satisfiers(dep) 1028: Gem.source_index.each do |_, gem| 1029: yield gem if gem.satisfies_requirement? dep 1030: end 1031: end
Return a string containing a Ruby code representation of the given object.
# File lib/rubygems/specification.rb, line 1039 1039: def ruby_code(obj) 1040: case obj 1041: when String then '%q{' + obj + '}' 1042: when Array then obj.inspect 1043: when Gem::Version then obj.to_s.inspect 1044: when Date then '%q{' + obj.strftime('%Y-%m-%d') + '}' 1045: when Time then '%q{' + obj.strftime('%Y-%m-%d') + '}' 1046: when Numeric then obj.inspect 1047: when true, false, nil then obj.inspect 1048: when Gem::Platform then "Gem::Platform.new(#{obj.to_a.inspect})" 1049: when Gem::Requirement then "Gem::Requirement.new(#{obj.to_s.inspect})" 1050: else raise Gem::Exception, "ruby_code case not handled: #{obj.class}" 1051: end 1052: end
True if this gem has the same attributes as other.
# File lib/rubygems/specification.rb, line 664 664: def same_attributes?(other) 665: @@attributes.each do |name, default| 666: return false unless self.send(name) == other.send(name) 667: end 668: true 669: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.