iniparse-1.4.2/ 0000755 0001750 0001750 00000000000 12725022733 013545 5 ustar terceiro terceiro iniparse-1.4.2/iniparse.gemspec 0000644 0001750 0001750 00000003236 12725022733 016730 0 ustar terceiro terceiro # Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.specification_version = 2 if s.respond_to? :specification_version=
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.rubygems_version = '1.3.5'
## Leave these as is they will be modified for you by the rake gemspec task.
## If your rubyforge_project name is different, then edit it and comment out
## the sub! line in the Rakefile
s.name = 'iniparse'
s.version = '1.4.2'
s.date = '2015-12-03'
s.rubyforge_project = 'iniparse'
s.summary = 'A pure Ruby library for parsing INI documents.'
s.authors = ['Anthony Williams']
s.email = 'hi@antw.me'
s.homepage = 'http://github.com/antw/iniparse'
s.licenses = ['MIT']
s.description = 'A pure Ruby library for parsing INI documents. ' \
'Preserves the structure of the original document, ' \
'including whitespace and comments'
s.require_paths = %w(lib)
s.rdoc_options = ['--charset=UTF-8']
s.extra_rdoc_files = %w(LICENSE README.rdoc)
# Dependencies.
s.add_development_dependency('rspec', '~> 2.14')
# = MANIFEST =
s.files = %w[
Gemfile
LICENSE
README.rdoc
Rakefile
TODO
iniparse.gemspec
lib/iniparse.rb
lib/iniparse/document.rb
lib/iniparse/generator.rb
lib/iniparse/line_collection.rb
lib/iniparse/lines.rb
lib/iniparse/parser.rb
]
# = MANIFEST =
end
iniparse-1.4.2/LICENSE 0000644 0001750 0001750 00000002050 12725022733 014547 0 ustar terceiro terceiro Copyright (c) 2008-2010 Anthony Williams
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. iniparse-1.4.2/.travis.yml 0000644 0001750 0001750 00000000174 12725022733 015660 0 ustar terceiro terceiro language: ruby
script: "bundle exec rspec"
bundler_args: "--without extras"
rvm:
- "2.1.0"
- "1.9.3"
- "jruby-19mode"
iniparse-1.4.2/.rspec 0000644 0001750 0001750 00000000010 12725022733 014651 0 ustar terceiro terceiro --color
iniparse-1.4.2/README.rdoc 0000644 0001750 0001750 00000005341 12725022733 015356 0 ustar terceiro terceiro = IniParse {
}[http://travis-ci.org/antw/iniparse]
IniParse is a pure Ruby library for parsing
INI[http://en.wikipedia.org/wiki/INI_file] configuration and data
files.
=== Main features
* Support for duplicate options. While not common, some INI files
contain an option more than once. IniParse does not overwrite previous
options, but allows you to access all of the duplicate values.
* Preservation of white space and blank lines. When writing back to
your INI file, line indents, white space and comments (and their indents)
are preserved. Only trailing white space (which has no significance in INI
files) will be removed.
* Preservation of section and option ordering. Sections and options
are kept in the same order they are in the original document ensuring that
nothing gets mangled when writing back to the file.
If you don't need the above mentioned features, you may find the simpler
IniFile gem does all you need.
=== Opening an INI file
Parsing an INI file is fairly simple:
IniParse.parse( File.read('path/to/my/file.ini') ) # => IniParse::Document
IniParse.parse returns an IniParse::Document instance which represents the
passed "INI string". Assuming you know the structure of the document, you can
access the sections in the INI document with IniParse::Document#[]. For
example:
document = IniParse.parse( File.read('path/to/my/file.ini') )
document['a_section']
# => IniParse::Lines::Section
document['a_section']['an_option']
# => "a value"
document['a_section']['another_option']
# => "another value"
In the event that duplicate options were found, an array of the values will
be supplied to you.
document = IniParse.parse <<-EOS
[my_section]
key = value
key = another value
key = a third value
EOS
document['my_section']['key']
# => ['value', 'another value', 'third value']
Options which appear before the first section will be added to a section called
"__anonymous__".
document = IniParse.parse <<-EOS
driver = true
[driver]
key = value
EOS
document['__anonymous__']['driver']
# => true
document['driver']['key']
# => 'value'
=== Updating an INI file
document['a_section']['an_option']
# => "a value"
document['a_section']['an_option'] = 'a new value'
document['a_section']['an_option']
# => "a new value"
Delete entire sections by calling `#delete` with the section name...
document.delete('a_section')
... or a single option with `#delete` on the section object:
document['a_section'].delete('an_option')
=== Creating a new INI file
See IniParse::Generator.
iniparse-1.4.2/lib/ 0000755 0001750 0001750 00000000000 12725022733 014313 5 ustar terceiro terceiro iniparse-1.4.2/lib/iniparse/ 0000755 0001750 0001750 00000000000 12725022733 016125 5 ustar terceiro terceiro iniparse-1.4.2/lib/iniparse/parser.rb 0000644 0001750 0001750 00000005565 12725022733 017761 0 ustar terceiro terceiro module IniParse
class Parser
# Returns the line types.
#
# ==== Returns
# Array
#
def self.parse_types
@@parse_types ||= []
end
# Sets the line types. Handy if you want to add your own custom Line
# classes.
#
# ==== Parameters
# types:: An array containing Line classes.
#
def self.parse_types=(types)
parse_types.replace(types)
end
self.parse_types = [ IniParse::Lines::Section,
IniParse::Lines::Option, IniParse::Lines::Blank ]
# Creates a new Parser instance for parsing string +source+.
#
# ==== Parameters
# source:: The source string.
#
def initialize(source)
@source = source.dup
end
# Parses the source string and returns the resulting data structure.
#
# ==== Returns
# IniParse::Document
#
def parse
IniParse::Generator.gen do |generator|
@source.split("\n", -1).each do |line|
generator.send(*Parser.parse_line(line))
end
end
end
class << self
# Takes a raw line from an INI document, striping out any inline
# comment, and indent, then returns the appropriate tuple so that the
# Generator instance can add the line to the Document.
#
# ==== Raises
# IniParse::ParseError: If the line could not be parsed.
#
def parse_line(line)
sanitized, opts = strip_indent(*strip_comment(line, {}))
parsed = nil
@@parse_types.each do |type|
break if (parsed = type.parse(sanitized, opts))
end
if parsed.nil?
raise IniParse::ParseError,
"A line of your INI document could not be parsed to a " \
"LineType: '#{line}'."
end
parsed
end
#######
private
#######
# Strips in inline comment from a line (or value), removes trailing
# whitespace and sets the comment options as applicable.
def strip_comment(line, opts)
if m = /^(^)(?:(;|\#)(\s*)(.*))$$/.match(line) ||
m = /^(.*?)(?:\s+(;|\#)(\s*)(.*))$/.match(line) # Comment lines.
opts[:comment] = m[4].rstrip
opts[:comment_prefix] = m[3]
opts[:comment_sep] = m[2]
# Remove the line content (since an option value may contain a
# semi-colon) _then_ get the index of the comment separator.
opts[:comment_offset] =
line[(m[1].length..-1)].index(m[2]) + m[1].length
line = m[1]
else
line.rstrip!
end
[line, opts]
end
# Removes any leading whitespace from a line, and adds it to the options
# hash.
def strip_indent(line, opts)
if m = /^(\s+).*$/.match(line)
line.lstrip!
opts[:indent] = m[1]
end
[line, opts]
end
end
end # Parser
end # IniParse
iniparse-1.4.2/lib/iniparse/lines.rb 0000644 0001750 0001750 00000022457 12725022733 017576 0 ustar terceiro terceiro module IniParse
module Lines
# A base class from which other line types should inherit.
module Line
# ==== Parameters
# opts:: Extra options for the line.
#
def initialize(opts = {})
@comment = opts.fetch(:comment, nil)
@comment_sep = opts.fetch(:comment_sep, ';')
@comment_prefix = opts.fetch(:comment_prefix, ' ')
@comment_offset = opts.fetch(:comment_offset, 0)
@indent = opts.fetch(:indent, '')
end
# Returns if this line has an inline comment.
def has_comment?
not @comment.nil?
end
# Returns this line as a string as it would be represented in an INI
# document.
def to_ini
[*line_contents].map { |ini|
if has_comment?
ini += ' ' if ini =~ /\S/ # not blank
ini = ini.ljust(@comment_offset)
ini += comment
end
@indent + ini
}.join "\n"
end
# Returns the contents for this line.
def line_contents
''
end
# Returns the inline comment for this line. Includes the comment
# separator at the beginning of the string.
def comment
"#{ @comment_sep }#{ @comment_prefix }#{ @comment }"
end
# Returns whether this is a line which has no data.
def blank?
false
end
# Returns the options used to create the line
def options
{
comment: @comment,
comment_sep: @comment_sep,
comment_prefix: @comment_prefix,
comment_offset: @comment_offset,
indent: @indent
}
end
end
# Represents a section header in an INI document. Section headers consist
# of a string of characters wrapped in square brackets.
#
# [section]
# key=value
# etc
# ...
#
class Section
include Line
@regex = /^\[ # Opening bracket
([^\]]+) # Section name
\]$ # Closing bracket
/x
attr_accessor :key
attr_reader :lines
include Enumerable
# ==== Parameters
# key:: The section name.
# opts:: Extra options for the line.
#
def initialize(key, opts = {})
super(opts)
@key = key.to_s
@lines = IniParse::OptionCollection.new
end
def self.parse(line, opts)
if m = @regex.match(line)
[:section, m[1], opts]
end
end
# Returns this line as a string as it would be represented in an INI
# document. Includes options, comments and blanks.
def to_ini
coll = lines.to_a
if coll.any?
[*super,coll.to_a.map do |line|
if line.kind_of?(Array)
line.map { |dup_line| dup_line.to_ini }.join($/)
else
line.to_ini
end
end].join($/)
else
super
end
end
# Enumerates through each Option in this section.
#
# Does not yield blank and comment lines by default; if you want _all_
# lines to be yielded, pass true.
#
# ==== Parameters
# include_blank:: Include blank/comment lines?
#
def each(*args, &blk)
@lines.each(*args, &blk)
end
# Adds a new option to this section, or updates an existing one.
#
# Note that +[]=+ has no knowledge of duplicate options and will happily
# overwrite duplicate options with your new value.
#
# section['an_option']
# # => ['duplicate one', 'duplicate two', ...]
# section['an_option'] = 'new value'
# section['an_option]
# # => 'new value'
#
# If you do not wish to overwrite duplicates, but wish instead for your
# new option to be considered a duplicate, use +add_option+ instead.
#
def []=(key, value)
line = @lines[key.to_s]
opts = {}
if line.kind_of?(Array)
opts = line.first.options
elsif line.respond_to? :options
opts = line.options
end
@lines[key.to_s] = IniParse::Lines::Option.new(key.to_s, value, opts)
end
# Returns the value of an option identified by +key+.
#
# Returns nil if there is no corresponding option. If the key provided
# matches a set of duplicate options, an array will be returned containing
# the value of each option.
#
def [](key)
key = key.to_s
if @lines.has_key?(key)
if (match = @lines[key]).kind_of?(Array)
match.map { |line| line.value }
else
match.value
end
end
end
# Deletes the option identified by +key+.
#
# Returns the section.
#
def delete(*args)
@lines.delete(*args)
self
end
# Like [], except instead of returning just the option value, it returns
# the matching line instance.
#
# Will return an array of lines if the key matches a set of duplicates.
#
def option(key)
@lines[key.to_s]
end
# Returns true if an option with the given +key+ exists in this section.
def has_option?(key)
@lines.has_key?(key.to_s)
end
# Merges section +other+ into this one. If the section being merged into
# this one contains options with the same key, they will be handled as
# duplicates.
#
# ==== Parameters
# other:: The section to merge into this one.
#
def merge!(other)
other.lines.each(true) do |line|
if line.kind_of?(Array)
line.each { |duplicate| @lines << duplicate }
else
@lines << line
end
end
end
#######
private
#######
def line_contents
'[%s]' % key
end
end
# Stores options which appear at the beginning of a file, without a
# preceding section.
class AnonymousSection < Section
def initialize
super('__anonymous__')
end
def to_ini
# Remove the leading space which is added by joining the blank line
# content with the options.
super.gsub(/\A\n/, '')
end
#######
private
#######
def line_contents
''
end
end
# Represents probably the most common type of line in an INI document:
# an option. Consists of a key and value, usually separated with an =.
#
# key = value
#
class Option
include Line
@regex = /^\s*([^=]+) # Option
=
(.*?)$ # Value
/x
attr_accessor :key, :value
# ==== Parameters
# key:: The option key.
# value:: The value for this option.
# opts:: Extra options for the line.
#
def initialize(key, value, opts = {})
super(opts)
@key, @value = key.to_s, value
end
def self.parse(line, opts)
if m = @regex.match(line)
[:option, m[1].strip, typecast(m[2].strip), opts]
end
end
# Attempts to typecast values.
def self.typecast(value)
case value
when /^\s*$/ then nil
when /^-?(?:\d|[1-9]\d+)$/ then Integer(value)
when /^-?(?:\d|[1-9]\d+)(?:\.\d+)?(?:e[+-]?\d+)?$/i then Float(value)
when /^true$/i then true
when /^false$/i then false
else value
end
end
#######
private
#######
# returns an array to support multiple lines or a single one at once
# because of options key duplication
def line_contents
if value.kind_of?(Array)
value.map { |v, i| "#{key} = #{v}" }
else
"#{key} = #{value}"
end
end
end
# Represents a blank line. Used so that we can preserve blank lines when
# writing back to the file.
class Blank
include Line
def blank?
true
end
def self.parse(line, opts)
if line !~ /\S/ # blank
if opts[:comment].nil?
[:blank]
else
[:comment, opts[:comment], opts]
end
end
end
end
# Represents a comment. Comment lines begin with a semi-colon or hash.
#
# ; this is a comment
# # also a comment
#
class Comment < Blank
# Returns if this line has an inline comment.
#
# Being a Comment this will always return true, even if the comment
# is nil. This would be the case if the line starts with a comment
# seperator, but has no comment text. See spec/fixtures/smb.ini for a
# real-world example.
#
def has_comment?
true
end
# Returns the inline comment for this line. Includes the comment
# separator at the beginning of the string.
#
# In rare cases where a comment seperator appeared in the original file,
# but without a comment, just the seperator will be returned.
#
def comment
@comment !~ /\S/ ? @comment_sep : super
end
end
end # Lines
end # IniParse
iniparse-1.4.2/lib/iniparse/line_collection.rb 0000644 0001750 0001750 00000011425 12725022733 021617 0 ustar terceiro terceiro module IniParse
# Represents a collection of lines in an INI document.
#
# LineCollection acts a bit like an Array/Hash hybrid, allowing arbitrary
# lines to be added to the collection, but also indexes the keys of Section
# and Option lines to enable O(1) lookup via LineCollection#[].
#
# The lines instances are stored in an array, +@lines+, while the index of
# each Section/Option is held in a Hash, +@indicies+, keyed with the
# Section/Option#key value (see LineCollection#[]=).
#
module LineCollection
include Enumerable
def initialize
@lines = []
@indicies = {}
end
# Retrive a value identified by +key+.
def [](key)
has_key?(key) ? @lines[ @indicies[key] ] : nil
end
# Set a +value+ identified by +key+.
#
# If a value with the given key already exists, the value will be replaced
# with the new one, with the new value taking the position of the old.
#
def []=(key, value)
key = key.to_s
if has_key?(key)
@lines[ @indicies[key] ] = value
else
@lines << value
@indicies[key] = @lines.length - 1
end
end
# Appends a line to the collection.
#
# Note that if you pass a line with a key already represented in the
# collection, the old item will be replaced.
#
def <<(line)
line.blank? ? (@lines << line) : (self[line.key] = line) ; self
end
alias_method :push, :<<
# Enumerates through the collection.
#
# By default #each does not yield blank and comment lines.
#
# ==== Parameters
# include_blank:: Include blank/comment lines?
#
def each(include_blank = false)
@lines.each do |line|
if include_blank || ! (line.is_a?(Array) ? line.empty? : line.blank?)
yield(line)
end
end
end
# Removes the value identified by +key+.
def delete(key)
key = key.key if key.respond_to?(:key)
unless (idx = @indicies[key]).nil?
@indicies.delete(key)
@indicies.each { |k,v| @indicies[k] = v -= 1 if v > idx }
@lines.delete_at(idx)
end
end
# Returns whether +key+ is in the collection.
def has_key?(*args)
@indicies.has_key?(*args)
end
# Return an array containing the keys for the lines added to this
# collection.
def keys
map { |line| line.key }
end
# Returns this collection as an array. Includes blank and comment lines.
def to_a
@lines.dup
end
# Returns this collection as a hash. Does not contain blank and comment
# lines.
def to_hash
Hash[ *(map { |line| [line.key, line] }).flatten ]
end
alias_method :to_h, :to_hash
end
# A implementation of LineCollection used for storing (mostly) Option
# instances contained within a Section.
#
# Since it is assumed that an INI document will only represent a section
# once, if SectionCollection encounters a Section key already held in the
# collection, the existing section is merged with the new one (see
# IniParse::Lines::Section#merge!).
class SectionCollection
include LineCollection
def <<(line)
if line.kind_of?(IniParse::Lines::Option)
option = line
line = IniParse::Lines::AnonymousSection.new
line.lines << option if option
end
if line.blank? || (! has_key?(line.key))
super # Adding a new section, comment or blank line.
else
self[line.key].merge!(line)
end
self
end
end
# A implementation of LineCollection used for storing (mostly) Option
# instances contained within a Section.
#
# Whenever OptionCollection encounters an Option key already held in the
# collection, it treats it as a duplicate. This means that instead of
# overwriting the existing value, the value is changed to an array
# containing the previous _and_ the new Option instances.
class OptionCollection
include LineCollection
# Appends a line to the collection.
#
# If you push an Option with a key already represented in the collection,
# the previous Option will not be overwritten, but treated as a duplicate.
#
# ==== Parameters
# line:: The line to be added to this section.
#
def <<(line)
if line.kind_of?(IniParse::Lines::Section)
raise IniParse::LineNotAllowed,
"You can't add a Section to an OptionCollection."
end
if line.blank? || (! has_key?(line.key))
super # Adding a new option, comment or blank line.
else
self[line.key] = [self[line.key], line].flatten
end
self
end
# Return an array containing the keys for the lines added to this
# collection.
def keys
map { |line| line.kind_of?(Array) ? line.first.key : line.key }
end
end
end
iniparse-1.4.2/lib/iniparse/generator.rb 0000644 0001750 0001750 00000013425 12725022733 020445 0 ustar terceiro terceiro module IniParse
# Generator provides a means for easily creating new INI documents.
#
# Rather than trying to hack together new INI documents by manually creating
# Document, Section and Option instances, it is preferable to use Generator
# which will handle it all for you.
#
# The Generator is exposed through IniParse.gen.
#
# IniParse.gen do |doc|
# doc.section("vehicle") do |vehicle|
# vehicle.option("road_side", "left")
# vehicle.option("realistic_acceleration", true)
# vehicle.option("max_trains", 500)
# end
#
# doc.section("construction") do |construction|
# construction.option("build_on_slopes", true)
# construction.option("autoslope", true)
# end
# end
#
# # => IniParse::Document
#
# This can be simplified further if you don't mind the small overhead
# which comes with +method_missing+:
#
# IniParse.gen do |doc|
# doc.vehicle do |vehicle|
# vehicle.road_side = "left"
# vehicle.realistic_acceleration = true
# vehicle.max_trains = 500
# end
#
# doc.construction do |construction|
# construction.build_on_slopes = true
# construction.autoslope = true
# end
# end
#
# # => IniParse::Document
#
# If you want to add slightly more complicated formatting to your document,
# each line type (except blanks) takes a number of optional parameters:
#
# :comment::
# Adds an inline comment at the end of the line.
# :comment_offset::
# Indent the comment. Measured in characters from _beginning_ of the line.
# See String#ljust.
# :indent::
# Adds the supplied text to the beginning of the line.
#
# If you supply +:indent+, +:comment_sep+, or +:comment_offset+ options when
# adding a section, the same options will be inherited by all of the options
# which belong to it.
#
# IniParse.gen do |doc|
# doc.section("vehicle",
# :comment => "Options for vehicles", :indent => " "
# ) do |vehicle|
# vehicle.option("road_side", "left")
# vehicle.option("realistic_acceleration", true)
# vehicle.option("max_trains", 500, :comment => "More = slower")
# end
# end.to_ini
#
# [vehicle] ; Options for vehicles
# road_side = left
# realistic_acceleration = true
# max_trains = 500 ; More = slower
#
class Generator
attr_reader :context
attr_reader :document
def initialize(opts = {}) # :nodoc:
@document = IniParse::Document.new
@context = @document
@in_section = false
@opt_stack = [opts]
end
def gen # :nodoc:
yield self
@document
end
# Creates a new IniParse::Document with the given sections and options.
#
# ==== Returns
# IniParse::Document
#
def self.gen(opts = {}, &blk)
new(opts).gen(&blk)
end
# Creates a new section with the given name and adds it to the document.
#
# You can optionally supply a block (as detailed in the documentation for
# Generator#gen) in order to add options to the section.
#
# ==== Parameters
# name:: A name for the given section.
#
def section(name, opts = {})
if @in_section
# Nesting sections is bad, mmmkay?
raise LineNotAllowed, "You can't nest sections in INI files."
end
# Add to a section if it already exists
if @document.has_section?(name.to_s())
@context = @document[name.to_s()]
else
@context = Lines::Section.new(name, line_options(opts))
@document.lines << @context
end
if block_given?
begin
@in_section = true
with_options(opts) { yield self }
@context = @document
blank()
ensure
@in_section = false
end
end
end
# Adds a new option to the current section.
#
# Can only be called as part of a section block, or after at least one
# section has been added to the document.
#
# ==== Parameters
# key:: The key (name) for this option.
# value:: The option's value.
# opts:: Extra options for the line (formatting, etc).
#
# ==== Raises
# IniParse::NoSectionError::
# If no section has been added to the document yet.
#
def option(key, value, opts = {})
@context.lines << Lines::Option.new(
key, value, line_options(opts)
)
rescue LineNotAllowed
# Tried to add an Option to a Document.
raise NoSectionError,
'Your INI document contains an option before the first section is ' \
'declared which is not allowed.'
end
# Adds a new comment line to the document.
#
# ==== Parameters
# comment:: The text for the comment line.
#
def comment(comment, opts = {})
@context.lines << Lines::Comment.new(
line_options(opts.merge(:comment => comment))
)
end
# Adds a new blank line to the document.
def blank
@context.lines << Lines::Blank.new
end
# Wraps lines, setting default options for each.
def with_options(opts = {}) # :nodoc:
opts = opts.dup
opts.delete(:comment)
@opt_stack.push( @opt_stack.last.merge(opts))
yield self
@opt_stack.pop
end
def method_missing(name, *args, &blk) # :nodoc:
if m = name.to_s.match(/(.*)=$/)
option(m[1], *args)
else
section(name.to_s, *args, &blk)
end
end
#######
private
#######
# Returns options for a line.
#
# If the context is a section, we use the section options as a base,
# rather than the global defaults.
#
def line_options(given_opts) # :nodoc:
@opt_stack.last.empty? ? given_opts : @opt_stack.last.merge(given_opts)
end
end
end
iniparse-1.4.2/lib/iniparse/document.rb 0000644 0001750 0001750 00000005706 12725022733 020300 0 ustar terceiro terceiro module IniParse
# Represents an INI document.
class Document
include Enumerable
attr_reader :lines
attr_accessor :path
# Creates a new Document instance.
def initialize(path = nil)
@path = path
@lines = IniParse::SectionCollection.new
end
# Enumerates through each Section in this document.
#
# Does not yield blank and comment lines by default; if you want _all_
# lines to be yielded, pass true.
#
# ==== Parameters
# include_blank:: Include blank/comment lines?
#
def each(*args, &blk)
@lines.each(*args, &blk)
end
# Returns the section identified by +key+.
#
# Returns nil if there is no Section with the given key.
#
def [](key)
@lines[key.to_s]
end
# Returns the section identified by +key+.
#
# If there is no Section with the given key it will be created.
#
def section(key)
@lines[key.to_s] ||= Lines::Section.new(key.to_s)
end
# Deletes the section whose name matches the given +key+.
#
# Returns the document.
#
def delete(*args)
@lines.delete(*args)
self
end
# Returns this document as a string suitable for saving to a file.
def to_ini
string = @lines.to_a.map { |line| line.to_ini }.join($/)
string = "#{ string }\n" unless string[-1] == "\n"
string
end
alias_method :to_s, :to_ini
# Returns a has representation of the INI with multi-line options
# as an array
def to_hash
result = {}
@lines.entries.each do |section|
result[section.key] ||= {}
section.entries.each do |option|
opts = Array(option)
val = opts.map { |o| o.respond_to?(:value) ? o.value : o }
val = val.size > 1 ? val : val.first
result[section.key][opts.first.key] = val
end
end
result
end
alias_method :to_h, :to_hash
# A human-readable version of the document, for debugging.
def inspect
sections = @lines.select { |l| l.is_a?(IniParse::Lines::Section) }
"#"
end
# Returns true if a section with the given +key+ exists in this document.
def has_section?(key)
@lines.has_key?(key.to_s)
end
# Saves a copy of this Document to disk.
#
# If a path was supplied when the Document was initialized then nothing
# needs to be given to Document#save. If Document was not given a file
# path, or you wish to save the document elsewhere, supply a path when
# calling Document#save.
#
# ==== Parameters
# path:: A path to which this document will be saved.
#
# ==== Raises
# IniParseError:: If your document couldn't be saved.
#
def save(path = nil)
@path = path if path
raise IniParseError, 'No path given to Document#save' if @path !~ /\S/
File.open(@path, 'w') { |f| f.write(self.to_ini) }
end
end
end
iniparse-1.4.2/lib/iniparse.rb 0000644 0001750 0001750 00000003052 12725022733 016452 0 ustar terceiro terceiro dir = File.expand_path('iniparse', File.dirname(__FILE__))
require File.join(dir, 'document')
require File.join(dir, 'generator')
require File.join(dir, 'line_collection')
require File.join(dir, 'lines')
require File.join(dir, 'parser')
module IniParse
VERSION = '1.4.2'
# A base class for IniParse errors.
class IniParseError < StandardError; end
# Raised if an error occurs parsing an INI document.
class ParseError < IniParseError; end
# Raised when an option line is found during parsing before the first
# section.
class NoSectionError < ParseError; end
# Raised when a line is added to a collection which isn't allowed (e.g.
# adding a Section line into an OptionCollection).
class LineNotAllowed < IniParseError; end
module_function
# Parse given given INI document source +source+.
#
# See IniParse::Parser.parse
#
# ==== Parameters
# source:: The source from the INI document.
#
# ==== Returns
# IniParse::Document
#
def parse(source)
IniParse::Parser.new(source.gsub(/(?:: The path to the INI document.
#
# ==== Returns
# IniParse::Document
#
def open(path)
document = parse(File.read(path))
document.path = path
document
end
# Creates a new IniParse::Document using the specification you provide.
#
# See IniParse::Generator.
#
# ==== Returns
# IniParse::Document
#
def gen(&blk)
IniParse::Generator.new.gen(&blk)
end
end
iniparse-1.4.2/Rakefile 0000644 0001750 0001750 00000006520 12725022733 015215 0 ustar terceiro terceiro require 'rubygems'
require 'rake'
require 'date'
require 'rake/clean'
require 'rdoc/task'
require 'rspec/core/rake_task'
##############################################################################
# Helpers
##############################################################################
def name
@name ||= Dir['*.gemspec'].first.split('.').first
end
def version
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
end
def date
Date.today.to_s
end
def rubyforge_project
name
end
def gemspec_file
"#{name}.gemspec"
end
def gem_file
"#{name}-#{version}.gem"
end
def replace_header(head, header_name)
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
end
##############################################################################
# Packaging & Installation.
##############################################################################
CLEAN.include ['pkg', '*.gem', 'doc', 'coverage']
desc 'Build the gem, and push to Github'
task :release => :build do
unless `git branch` =~ /^\* master$/
puts "You must be on the master branch to release!"
exit!
end
sh "git commit --allow-empty -a -m 'Release #{version}'"
sh "git tag v#{version}"
sh "git push origin master"
sh "git push origin v#{version}"
puts "Push to Rubygems.org with"
puts " gem push pkg/#{name}-#{version}.gem"
end
desc 'Builds the IniParse gem'
task :build => :gemspec do
sh "mkdir -p pkg"
sh "gem build #{gemspec_file}"
sh "mv #{gem_file} pkg"
end
desc 'Creates a fresh gemspec'
task :gemspec => :validate do
# read spec file and split out manifest section
spec = File.read(gemspec_file)
head, manifest, tail = spec.split(" # = MANIFEST =\n")
# replace name version and date
replace_header(head, :name)
replace_header(head, :version)
replace_header(head, :date)
#comment this out if your rubyforge_project has a different name
replace_header(head, :rubyforge_project)
# determine file list from git ls-files
files = `git ls-files`.
split("\n").
sort.
reject { |file| file =~ /^\./ }.
reject { |file| file =~ /^(rdoc|pkg|spec)/ }.
map { |file| " #{file}" }.
join("\n")
# piece file back together and write
manifest = " s.files = %w[\n#{files}\n ]\n"
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
File.open(gemspec_file, 'w') { |io| io.write(spec) }
puts "Updated #{gemspec_file}"
end
task :validate do
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
unless libfiles.empty?
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
exit!
end
unless Dir['VERSION*'].empty?
puts "A `VERSION` file at root level violates Gem best practices."
exit!
end
end
##############################################################################
# Documentation
##############################################################################
Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = "iniparse #{version}"
rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb')
end
##############################################################################
# Tests & Metrics.
##############################################################################
RSpec::Core::RakeTask.new('spec') do |spec|
spec.pattern = 'spec/**/*_spec.rb'
end
iniparse-1.4.2/TODO 0000644 0001750 0001750 00000000124 12725022733 014232 0 ustar terceiro terceiro * Support multi-line options with backslashes (presumably with
OptionCollection).
iniparse-1.4.2/spec/ 0000755 0001750 0001750 00000000000 12725022733 014477 5 ustar terceiro terceiro iniparse-1.4.2/spec/generator/ 0000755 0001750 0001750 00000000000 12725022733 016465 5 ustar terceiro terceiro iniparse-1.4.2/spec/generator/without_section_blocks_spec.rb 0000644 0001750 0001750 00000010365 12725022733 024615 0 ustar terceiro terceiro require 'spec_helper'
# Tests use of the Generator when used like so:
#
# @gen = IniParse::Generator.new
# @gen.comment('My very own comment')
# @gen.section('my_section')
# @gen.option('my_option', 'my value')
# ...
#
# Or
#
# IniParse::Generator.gen do |doc|
# doc.comment('My very own comment')
# doc.section('my_section')
# doc.option('my_option', 'my value')
# end
#
describe 'When generating a document using Generator without section blocks,' do
before(:each) { @gen = IniParse::Generator.new }
# --
# ==========================================================================
# SECTION LINES
# ==========================================================================
# ++
describe 'adding a section' do
it 'should add a Section to the document' do
@gen.section("a section")
@gen.document.should have_section("a section")
end
it 'should change the Generator context to the section' do
@gen.section("a section")
@gen.context.should == @gen.document['a section']
end
it 'should pass extra options to the Section instance' do
@gen.section("a section", :indent => ' ')
@gen.document["a section"].to_ini.should match(/\A /)
end
end
# --
# ==========================================================================
# OPTION LINES
# ==========================================================================
# ++
describe 'adding a option' do
it 'should pass extra options to the Option instance' do
@gen.section("a section")
@gen.option("my option", "a value", :indent => ' ')
@gen.document["a section"].option("my option").to_ini.should match(/^ /)
end
describe 'when the context is a Document' do
it "should add the option to an __anonymous__ section" do
@gen.option("key", "value")
@gen.document['__anonymous__']['key'].should eql('value')
end
end
describe 'when the context is a Section' do
it 'should add the option to the section' do
@gen.section("a section")
@gen.option("my option", "a value")
@gen.document["a section"].should have_option("my option")
@gen.document["a section"]["my option"].should == "a value"
end
end
end
# --
# ==========================================================================
# COMMENT LINES
# ==========================================================================
# ++
describe 'adding a comment' do
it 'should pass extra options to the Option instance' do
@gen.comment("My comment", :indent => ' ')
@gen.document.lines.to_a.first.to_ini.should match(/^ /)
end
it 'should ignore any extra :comment option' do
@gen.comment("My comment", :comment => 'Ignored')
comment_ini = @gen.document.lines.to_a.first.to_ini
comment_ini.should match(/My comment/)
comment_ini.should_not match(/Ignored/)
end
describe 'when the context is a Document' do
it 'should add a comment to the document' do
@gen.comment('My comment')
comment = @gen.document.lines.to_a.first
comment.should be_kind_of(IniParse::Lines::Comment)
comment.to_ini.should match(/; My comment/)
end
end
describe 'when the context is a Section' do
it 'should add a comment to the section' do
@gen.section('a section')
@gen.comment('My comment')
comment = @gen.document['a section'].lines.to_a.first
comment.should be_kind_of(IniParse::Lines::Comment)
comment.to_ini.should match(/My comment/)
end
end
end
# --
# ==========================================================================
# BLANK LINES
# ==========================================================================
# ++
describe 'adding a blank line' do
it 'should add a blank line to the document when it is the context' do
@gen.blank
comment = @gen.document.lines.to_a.first
comment.should be_kind_of(IniParse::Lines::Blank)
end
it 'should add a blank line to the section when it is the context' do
@gen.section('a section')
@gen.blank
comment = @gen.document['a section'].lines.to_a.first
comment.should be_kind_of(IniParse::Lines::Blank)
end
end
end
iniparse-1.4.2/spec/generator/method_missing_spec.rb 0000644 0001750 0001750 00000006112 12725022733 023035 0 ustar terceiro terceiro require 'spec_helper'
# Tests use of the Generator when used like so:
#
# IniParse::Generator.gen do |doc|
# doc.comment 'My very own comment'
# doc.my_section do |section|
# section.my_option = 'my value'
# end
# end
#
describe 'When generating a document using Generator with section blocks using method_missing,' do
# --
# ==========================================================================
# SECTION LINES
# ==========================================================================
# ++
describe 'adding a section' do
it 'should yield an object with generator methods' do
IniParse::Generator.gen do |doc|
doc.a_section do |section|
%w( option comment blank ).each do |meth|
section.should respond_to(meth)
end
end
end
end
it 'should add a Section to the document' do
IniParse::Generator.gen do |doc|
doc.a_section { |section| }
end.should have_section("a_section")
end
it 'should change the Generator context to the section during the section block' do
IniParse::Generator.gen do |doc|
doc.a_section do |section|
section.context.should be_kind_of(IniParse::Lines::Section)
section.context.key.should == "a_section"
end
end
end
it 'should reset the Generator context to the document after the section block' do
IniParse::Generator.gen do |doc|
doc.a_section { |section| }
doc.context.should be_kind_of(IniParse::Document)
end
end
it 'should append a blank line to the document, after the section' do
IniParse::Generator.gen do |doc|
doc.a_section { |section| }
end.lines.to_a.last.should be_kind_of(IniParse::Lines::Blank)
end
it 'should raise a LineNotAllowed if you attempt to nest a section' do
lambda do
IniParse::Generator.gen do |doc|
doc.a_section do |section_one|
section_one.another_section { |section_two| }
end
end
end.should raise_error(IniParse::LineNotAllowed)
end
end
# --
# ==========================================================================
# OPTION LINES
# ==========================================================================
# ++
describe 'adding a option' do
describe 'when the context is a Document' do
it "adds the option to an __anonymous__ section" do
doc = IniParse::Generator.gen { |doc| doc.my_option = "a value" }
doc['__anonymous__']['my_option'].should eql('a value')
end
end
describe 'when the context is a Section' do
it 'should add the option to the section' do
document = IniParse::Generator.gen do |doc|
doc.a_section do |section|
section.my_option = "a value"
end
end
section = document["a_section"]
section.should have_option("my_option")
section["my_option"].should == "a value"
end
end
end
# Comments and blanks are added in the same way as in the
# 'with_section_block_spec.rb' specification.
end
iniparse-1.4.2/spec/generator/with_section_blocks_spec.rb 0000644 0001750 0001750 00000024276 12725022733 024073 0 ustar terceiro terceiro require 'spec_helper'
# Tests use of the Generator when used like so:
#
# IniParse::Generator.gen do |doc|
# doc.comment('My very own comment')
# doc.section('my_section') do |section|
# section.option('my_option', 'my value')
# end
# end
#
describe 'When generating a document using Generator with section blocks,' do
it 'should be able to compile an empty document' do
lambda { IniParse::Generator.gen { |doc| } }.should_not raise_error
end
it 'should raise LocalJumpError if no block is given' do
lambda { IniParse::Generator.gen }.should raise_error(LocalJumpError)
end
it "should yield an object with generator methods" do
IniParse::Generator.gen do |doc|
%w( section option comment blank ).each do |meth|
doc.should respond_to(meth)
end
end
end
# --
# ==========================================================================
# SECTION LINES
# ==========================================================================
# ++
describe 'adding a section' do
it 'should yield an object with generator methods' do
IniParse::Generator.gen do |doc|
doc.section("a section") do |section|
%w( option comment blank ).each do |meth|
section.should respond_to(meth)
end
end
end
end
it 'should add a Section to the document' do
IniParse::Generator.gen do |doc|
doc.section("a section") { |section| }
end.should have_section("a section")
end
it 'should change the Generator context to the section during the section block' do
IniParse::Generator.gen do |doc|
doc.section("a section") do |section|
section.context.should be_kind_of(IniParse::Lines::Section)
section.context.key.should == "a section"
end
end
end
it 'should reset the Generator context to the document after the section block' do
IniParse::Generator.gen do |doc|
doc.section("a section") { |section| }
doc.context.should be_kind_of(IniParse::Document)
end
end
it "should use the parent document's options as a base" do
document = IniParse::Generator.gen(:indent => ' ') do |doc|
doc.section("a section") { |section| }
end
document["a section"].to_ini.should match(/\A /)
end
it 'should pass extra options to the Section instance' do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :indent => ' ') { |section| }
end
document["a section"].to_ini.should match(/\A /)
end
it 'should append a blank line to the document, after the section' do
IniParse::Generator.gen do |doc|
doc.section("a section") { |section| }
end.lines.to_a.last.should be_kind_of(IniParse::Lines::Blank)
end
it 'should raise a LineNotAllowed if you attempt to nest a section' do
lambda do
IniParse::Generator.gen do |doc|
doc.section("a section") do |section_one|
section_one.section("another_section") { |section_two| }
end
end
end.should raise_error(IniParse::LineNotAllowed)
end
end
# --
# ==========================================================================
# OPTION LINES
# ==========================================================================
# ++
describe 'adding a option' do
describe 'when the context is a Document' do
it "should add the option to an __anonymous__ section" do
document = IniParse::Generator.gen do |doc|
doc.option("my option", "a value")
end
document['__anonymous__']['my option'].should eql('a value')
end
end
describe 'when the context is a Section' do
it 'should add the option to the section' do
document = IniParse::Generator.gen do |doc|
doc.section("a section") do |section|
section.option("my option", "a value")
end
end
section = document["a section"]
section.should have_option("my option")
section["my option"].should == "a value"
end
it 'should pass extra options to the Option instance' do
document = IniParse::Generator.gen do |doc|
doc.section("a section") do |section|
section.option("my option", "a value", :indent => " ")
end
end
document["a section"].option("my option").to_ini.should match(/^ /)
end
it "should use the parent document's options as a base" do
document = IniParse::Generator.gen(:indent => " ") do |doc|
doc.section("a section") do |section|
section.option("my option", "a value")
end
end
document["a section"].option("my option").to_ini.should match(/^ /)
end
it "should use the parent section's options as a base" do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :indent => " ") do |section|
section.option("my option", "a value")
end
end
document["a section"].option("my option").to_ini.should match(/^ /)
end
it "should allow customisation of the parent's options" do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :indent => " ") do |section|
section.option("my option", "a value", {
:comment_sep => "#", :comment => 'a comment'
})
end
end
option_ini = document["a section"].option("my option").to_ini
option_ini.should match(/^ /)
option_ini.should match(/ # a comment/)
end
it "should not use the parent section's comment when setting line options" do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :comment => "My section") do |section|
section.option("my option", "a value")
end
end
document["a section"].option("my option").to_ini.should_not match(/My section$/)
end
end
end
# --
# ==========================================================================
# COMMENT LINES
# ==========================================================================
# ++
describe 'adding a comment' do
it 'should pass extra options to the Option instance' do
document = IniParse::Generator.gen do |doc|
doc.comment("My comment", :indent => ' ')
end
document.lines.to_a.first.to_ini.should match(/\A /)
end
it 'should ignore any extra :comment option' do
document = IniParse::Generator.gen do |doc|
doc.comment("My comment", :comment => 'Ignored')
end
document.lines.to_a.first.to_ini.should match(/My comment/)
document.lines.to_a.first.to_ini.should_not match(/Ignored/)
end
describe 'when the context is a Document' do
it 'should add a comment to the document' do
document = IniParse::Generator.gen do |doc|
doc.comment("My comment")
end
comment = document.lines.to_a.first
comment.should be_kind_of(IniParse::Lines::Comment)
comment.to_ini.should match(/My comment/)
end
it 'should use the default line options as a base' do
document = IniParse::Generator.gen do |doc|
doc.comment("My comment")
end
comment_ini = document.lines.to_a.first.to_ini
# Match separator (;) and offset (0).
comment_ini.should == '; My comment'
end
end
describe 'when the context is a Section' do
it 'should add a comment to the section' do
document = IniParse::Generator.gen do |doc|
doc.section("a section") do |section|
section.comment("My comment")
end
end
comment = document['a section'].lines.to_a.first
comment.should be_kind_of(IniParse::Lines::Comment)
comment.to_ini.should match(/My comment/)
end
it "should use the parent document's line options as a base" do
document = IniParse::Generator.gen(:comment_offset => 5) do |doc|
doc.section("a section") do |section|
section.comment("My comment")
end
end
document['a section'].lines.to_a.first.to_ini.should match(/^ ;/)
end
it "should use the parent section's line options as a base" do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :comment_offset => 5) do |section|
section.comment("My comment")
end
end
document['a section'].lines.to_a.first.to_ini.should match(/^ ;/)
end
it "should allow customisation of the parent's options" do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :comment_offset => 5) do |section|
section.comment("My comment", :comment_sep => "#")
end
end
# Match separator (#) and offset (5)
document['a section'].lines.to_a.first.to_ini.should \
== ' # My comment'
end
it "should not use the parent section's comment when setting line options" do
document = IniParse::Generator.gen do |doc|
doc.section("a section", :comment => "My section") do |section|
section.comment("My comment")
end
end
comment_ini = document['a section'].lines.to_a.first.to_ini
comment_ini.should match(/My comment/)
comment_ini.should_not match(/My section/)
end
end
end
# --
# ==========================================================================
# BLANK LINES
# ==========================================================================
# ++
describe 'adding a blank line' do
it 'should add a blank line to the document when it is the context' do
document = IniParse::Generator.gen do |doc|
doc.blank
end
document.lines.to_a.first.should be_kind_of(IniParse::Lines::Blank)
end
it 'should add a blank line to the section when it is the context' do
document = IniParse::Generator.gen do |doc|
doc.section("a section") do |section|
section.blank
end
end
document['a section'].lines.to_a.first.should be_kind_of(IniParse::Lines::Blank)
end
end
end
iniparse-1.4.2/spec/iniparse_spec.rb 0000644 0001750 0001750 00000002663 12725022733 017657 0 ustar terceiro terceiro require 'spec_helper'
describe "IniParse" do
describe '.parse' do
context 'with a line ending in a backslash' do
let(:ini) do
<<-'INI'.gsub(/^\s*/, '')
[a]
opt = 1 \
other = 2
INI
end
let(:doc) { IniParse.parse(ini) }
it 'recognises the line continuation' do
expect(doc.to_s).to eq("[a]\nopt = 1 other = 2\n")
end
it 'has one option' do
expect(doc['a'].to_a.length).to eq(1)
end
end
context 'with a line ending in a double-backslash' do
let(:ini) do
<<-'INI'.gsub(/^\s*/, '')
[a]
opt = 1 \\
other = 2
INI
end
let(:doc) { IniParse.parse(ini) }
it 'does not see a line continuation' do
expect(doc.to_s).to eq(ini)
end
it 'has one option' do
expect(doc['a'].to_a.length).to eq(2)
end
end
end
describe '.open' do
before(:each) { File.stub(:read).and_return('[section]') }
it 'should return an IniParse::Document' do
IniParse.open('/my/path.ini').should be_kind_of(IniParse::Document)
end
it 'should set the path on the returned Document' do
IniParse.open('/my/path.ini').path.should == '/my/path.ini'
end
it 'should read the file at the given path' do
File.should_receive(:read).with('/my/path.ini').and_return('[section]')
IniParse.open('/my/path.ini')
end
end
end
iniparse-1.4.2/spec/spec_helper_spec.rb 0000644 0001750 0001750 00000012425 12725022733 020333 0 ustar terceiro terceiro require 'spec_helper'
# --
# ============================================================================
# Empty array.
# ============================================================================
# ++
describe 'An empty array' do
it 'should not pass be_section_tuple' do
[].should_not be_section_tuple
end
it 'should not pass be_option_tuple' do
[].should_not be_option_tuple
end
it 'should not pass be_blank_tuple' do
[].should_not be_blank_tuple
end
it 'should not pass be_comment_tuple' do
[].should_not be_comment_tuple
end
end
# --
# ============================================================================
# Section tuple.
# ============================================================================
# ++
describe 'Line tuple [:section, "key", {:opt => "val"}]' do
before(:all) { @tuple = [:section, "key", {:opt => "val"}] }
it 'should pass be_section_tuple' do
@tuple.should be_section_tuple
end
it 'should pass be_section_tuple("key")' do
@tuple.should be_section_tuple("key")
end
it 'should fail be_section_tuple("invalid")' do
@tuple.should_not be_section_tuple("invalid")
end
it 'should pass be_section_tuple("key", {:opt => "val"})' do
@tuple.should be_section_tuple("key", {:opt => "val"})
end
it 'should not pass be_section_tuple("key", {:invalid => "val"})' do
@tuple.should_not be_section_tuple("key", {:invalid => "val"})
end
it 'should not pass be_section_tuple("key", {:opt => "invalid"})' do
@tuple.should_not be_section_tuple("key", {:opt => "invalid"})
end
it 'should fail be_option_tuple' do
@tuple.should_not be_option_tuple
end
it 'should fail be_blank_tuple' do
@tuple.should_not be_blank_tuple
end
it 'should fail be_comment_tuple' do
@tuple.should_not be_comment_tuple
end
end
# --
# ============================================================================
# Option tuple.
# ============================================================================
# ++
describe 'Line tuple [:option, "key", "val", {:opt => "val"}]' do
before(:all) { @tuple = [:option, "key", "val", {:opt => "val"}] }
it 'should fail be_section_tuple' do
@tuple.should_not be_section_tuple
end
it 'should pass be_option_tuple' do
@tuple.should be_option_tuple
end
it 'should pass be_option_tuple("key")' do
@tuple.should be_option_tuple("key")
end
it 'should fail be_option_tuple("invalid")' do
@tuple.should_not be_option_tuple("invalid")
end
it 'should pass be_option_tuple("key", "val")' do
@tuple.should be_option_tuple("key", "val")
end
it 'should pass be_option_tuple(:any, "val")' do
@tuple.should be_option_tuple(:any, "val")
end
it 'should fail be_option_tuple("key", "invalid")' do
@tuple.should_not be_option_tuple("key", "invalid")
end
it 'should pass be_option_tuple("key", "val", { :opt => "val" })' do
@tuple.should be_option_tuple("key", "val", { :opt => "val" })
end
it 'should fail be_option_tuple("key", "val", { :invalid => "val" })' do
@tuple.should_not be_option_tuple("key", "val", { :invalid => "val" })
end
it 'should fail be_option_tuple("key", "val", { :opt => "invalid" })' do
@tuple.should_not be_option_tuple("key", "val", { :opt => "invalid" })
end
it 'should fail be_blank_tuple' do
@tuple.should_not be_blank_tuple
end
it 'should fail be_comment_tuple' do
@tuple.should_not be_comment_tuple
end
end
# --
# ============================================================================
# Blank tuple.
# ============================================================================
# ++
describe 'Line tuple [:blank]' do
before(:all) { @tuple = [:blank] }
it 'should fail be_section_tuple' do
@tuple.should_not be_section_tuple
end
it 'should fail be_option_tuple' do
@tuple.should_not be_option_tuple
end
it 'should pass be_blank_tuple' do
@tuple.should be_blank_tuple
end
it 'should fail be_comment_tuple' do
@tuple.should_not be_comment_tuple
end
end
# --
# ============================================================================
# Coment tuple.
# ============================================================================
# ++
describe 'Line tuple [:comment, "A comment", {:opt => "val"}]' do
before(:all) { @tuple = [:comment, "A comment", {:opt => "val"}] }
it 'should fail be_section_tuple' do
@tuple.should_not be_section_tuple
end
it 'should fail be_option_tuple' do
@tuple.should_not be_option_tuple
end
it 'should fail be_blank_tuple' do
@tuple.should_not be_blank_tuple
end
it 'should pass be_comment_tuple' do
@tuple.should be_comment_tuple
end
it 'should pass be_comment_tuple("A comment")' do
@tuple.should be_comment_tuple("A comment")
end
it 'should fail be_comment_tuple("Invalid")' do
@tuple.should_not be_comment_tuple("Invalid")
end
it 'should pass be_comment_tuple("A comment", {:opt => "val"})' do
@tuple.should be_comment_tuple("A comment", {:opt => "val"})
end
it 'should fail be_comment_tuple("A comment", {:invalid => "val"})' do
@tuple.should_not be_comment_tuple("A comment", {:invalid => "val"})
end
it 'should fail be_comment_tuple("A comment", {:opt => "invalid"})' do
@tuple.should_not be_comment_tuple("A comment", {:opt => "invalid"})
end
end
iniparse-1.4.2/spec/lines_spec.rb 0000644 0001750 0001750 00000033331 12725022733 017153 0 ustar terceiro terceiro require 'spec_helper'
module IniParse::Test
class FakeLine
include IniParse::Lines::Line
def line_contents
'fake line'
end
end
end
describe "IniParse::Lines::Line module" do
describe '#to_ini' do
it 'should return +line_contents+' do
IniParse::Test::FakeLine.new.to_ini.should == 'fake line'
end
it 'should preserve line indents' do
IniParse::Test::FakeLine.new(
:indent => ' '
).to_ini.should == ' fake line'
end
describe 'when a comment is set' do
it 'should correctly include the comment' do
IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 10
).to_ini.should == 'fake line ; comment'
end
it 'should correctly indent the comment' do
IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 15
).to_ini.should == 'fake line ; comment'
end
it 'should use ";" as a default comment seperator' do
IniParse::Test::FakeLine.new(
:comment => 'comment'
).to_ini.should == 'fake line ; comment'
end
it 'should use the correct seperator' do
IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => '#'
).to_ini.should == 'fake line # comment'
end
it 'should use the ensure a space is added before the comment seperator' do
IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 0
).to_ini.should == 'fake line ; comment'
end
it 'should not add an extra space if the line is blank' do
line = IniParse::Test::FakeLine.new(
:comment => 'comment', :comment_sep => ';', :comment_offset => 0
)
line.stub(:line_contents).and_return('')
line.to_ini.should == '; comment'
end
end
describe 'when no comment is set' do
it 'should not add trailing space if :comment_offset has a value' do
IniParse::Test::FakeLine.new(:comment_offset => 10).to_ini.should == 'fake line'
end
it 'should not add a comment seperator :comment_sep has a value' do
IniParse::Test::FakeLine.new(:comment_sep => ';').to_ini.should == 'fake line'
end
end
end
describe '#has_comment?' do
it 'should return true if :comment has a non-blank value' do
IniParse::Test::FakeLine.new(:comment => 'comment').should have_comment
end
it 'should return true if :comment has a blank value' do
IniParse::Test::FakeLine.new(:comment => '').should have_comment
end
it 'should return false if :comment has a nil value' do
IniParse::Test::FakeLine.new.should_not have_comment
IniParse::Test::FakeLine.new(:comment => nil).should_not have_comment
end
end
end
#
# Section
#
describe 'IniParse::Lines::Section' do
before(:each) { @section = IniParse::Lines::Section.new('a section') }
it 'should respond_to +lines+' do
@section.should respond_to(:lines)
end
it 'should not respond_to +lines=+' do
@section.should_not respond_to(:lines=)
end
it 'should include Enumerable' do
IniParse::Lines::Section.included_modules.should include(Enumerable)
end
describe '#initialize' do
it 'should typecast the given key to a string' do
IniParse::Lines::Section.new(:symbol).key.should == 'symbol'
end
end
describe '#option' do
it 'should retrieve the line identified by the given key' do
option = IniParse::Lines::Option.new('k', 'value one')
@section.lines << option
@section.option('k').should == option
end
it 'should return nil if the given key does not exist' do
@section.option('does_not_exist').should be_nil
end
end
describe '#each' do
it 'should call #each on +lines+' do
@section.lines.should_receive(:each)
@section.each { |l| }
end
end
describe '#[]' do
it 'should return nil if the given key does not exist' do
@section['k'].should be_nil
end
it 'should return a value if the given key exists' do
@section.lines << IniParse::Lines::Option.new('k', 'v')
@section['k'].should == 'v'
end
it 'should return an array of values if the key is a duplicate' do
@section.lines << IniParse::Lines::Option.new('k', 'v1')
@section.lines << IniParse::Lines::Option.new('k', 'v2')
@section.lines << IniParse::Lines::Option.new('k', 'v3')
@section['k'].should == ['v1', 'v2', 'v3']
end
it 'should typecast the key to a string' do
@section.lines << IniParse::Lines::Option.new('k', 'v')
@section[:k].should == 'v'
end
end
describe '#[]=' do
it 'should add a new Option with the given key and value' do
@section['k'] = 'a value'
@section.option('k').should be_kind_of(IniParse::Lines::Option)
@section['k'].should == 'a value'
end
it 'should update the Option if one already exists' do
@section.lines << IniParse::Lines::Option.new('k', 'orig value')
@section['k'] = 'new value'
@section['k'].should == 'new value'
end
it 'should replace the existing Option if it is an array' do
@section.lines << IniParse::Lines::Option.new('k', 'v1')
@section.lines << IniParse::Lines::Option.new('k', 'v2')
@section['k'] = 'new value'
@section.option('k').should be_kind_of(IniParse::Lines::Option)
@section['k'].should == 'new value'
end
it 'should typecast the key to a string' do
@section[:k] = 'a value'
@section['k'].should == 'a value'
end
end
describe '#merge!' do
before(:each) do
@section.lines << IniParse::Lines::Option.new('a', 'val1')
@section.lines << IniParse::Lines::Blank.new
@section.lines << IniParse::Lines::Comment.new
@section.lines << IniParse::Lines::Option.new('b', 'val2')
@new_section = IniParse::Lines::Section.new('new section')
end
it 'should merge options from the given Section into the receiver' do
@new_section.lines << IniParse::Lines::Option.new('c', 'val3')
@new_section.lines << IniParse::Lines::Option.new('d', 'val4')
@section.merge!(@new_section)
@section['a'].should == 'val1'
@section['b'].should == 'val2'
@section['c'].should == 'val3'
@section['d'].should == 'val4'
end
it 'should handle duplicates' do
@new_section.lines << IniParse::Lines::Option.new('a', 'val2')
@section.merge!(@new_section)
@section['a'].should == ['val1', 'val2']
end
it 'should handle duplicates on both sides' do
@section.lines << IniParse::Lines::Option.new('a', 'val2')
@new_section.lines << IniParse::Lines::Option.new('a', 'val3')
@new_section.lines << IniParse::Lines::Option.new('a', 'val4')
@section.merge!(@new_section)
@section['a'].should == ['val1', 'val2', 'val3', 'val4']
end
it 'should copy blank lines' do
@new_section.lines << IniParse::Lines::Blank.new
@section.merge!(@new_section)
line = nil
@section.each(true) { |l| line = l }
line.should be_kind_of(IniParse::Lines::Blank)
end
it 'should copy comments' do
@new_section.lines << IniParse::Lines::Comment.new
@section.merge!(@new_section)
line = nil
@section.each(true) { |l| line = l }
line.should be_kind_of(IniParse::Lines::Comment)
end
end
describe '#delete' do
let(:opt_one) { IniParse::Lines::Option.new('a', 'b') }
let(:opt_two) { IniParse::Lines::Option.new('c', 'd') }
before(:each) do
@section.lines << opt_one
@section.lines << opt_two
end
it 'removes the option given a key' do
lambda { @section.delete('a') }.
should change { @section['a'] }.to(nil)
end
it 'removes the option given an Option' do
lambda { @section.delete(opt_one) }.
should change { @section['a'] }.to(nil)
end
it 'should not remove non-matching lines' do
lambda { @section.delete('a') }.should_not change { @section['c'] }
end
it 'returns the section' do
@section.delete('a').should eql(@section)
end
end
describe '#to_ini' do
it 'should include the section key' do
IniParse::Lines::Section.new('a section').to_ini.should == '[a section]'
end
it 'should include lines belonging to the section' do
@section.lines << IniParse::Lines::Option.new('a', 'val1')
@section.lines << IniParse::Lines::Blank.new
@section.lines << IniParse::Lines::Comment.new(
:comment => 'my comment', :comment_sep => ';', :comment_offset => 0
)
@section.lines << IniParse::Lines::Option.new('b', 'val2')
@section.to_ini.should ==
"[a section]\n" \
"a = val1\n" \
"\n" \
"; my comment\n" \
"b = val2"
end
it 'should include duplicate lines' do
@section.lines << IniParse::Lines::Option.new('a', 'val1')
@section.lines << IniParse::Lines::Option.new('a', 'val2')
@section.to_ini.should ==
"[a section]\n" \
"a = val1\n" \
"a = val2"
end
end
describe '#has_option?' do
before do
@section['first'] = 'value'
end
it 'should return true if an option with the given key exists' do
@section.should have_option('first')
end
it 'should return true if no option with the given key exists' do
@section.should_not have_option('second')
end
end
end
#
# Option
#
describe 'Iniparse::Lines::Option' do
describe '#initialize' do
it 'should typecast the given key to a string' do
IniParse::Lines::Option.new(:symbol, '').key.should == 'symbol'
end
end
describe '#to_ini' do
it 'should include the key and value' do
IniParse::Lines::Option.new('key', 'value').to_ini.should == 'key = value'
end
end
describe '.parse' do
def parse(line, opts = {})
IniParse::Lines::Option.parse(line, opts)
end
it 'should typecast empty values to nil' do
parse('key =').should be_option_tuple('key', nil)
parse('key = ').should be_option_tuple('key', nil)
parse('key = ').should be_option_tuple('key', nil)
end
it 'should not typecast "true" if true is part of a word' do
parse('key = TestTrueTest').should be_option_tuple('key', 'TestTrueTest')
parse('key = TrueTest').should be_option_tuple('key', 'TrueTest')
parse('key = TestTrue').should be_option_tuple('key', 'TestTrue')
end
it 'should not typecast "false" if false is part of a word' do
parse('key = TestFalseTest').should be_option_tuple('key', 'TestFalseTest')
parse('key = FalseTest').should be_option_tuple('key', 'FalseTest')
parse('key = TestFalse').should be_option_tuple('key', 'TestFalse')
end
it 'should typecast "true" to TrueClass' do
parse('key = true').should be_option_tuple('key', true)
parse('key = TRUE').should be_option_tuple('key', true)
end
it 'should typecast "false" to FalseClass' do
parse('key = false').should be_option_tuple('key', false)
parse('key = FALSE').should be_option_tuple('key', false)
end
it 'should typecast integer values to Integer' do
parse('key = 1').should be_option_tuple('key', 1)
parse('key = 10').should be_option_tuple('key', 10)
end
it 'should not typecast integers with a leading 0 to Integer' do
parse('key = 0700').should be_option_tuple('key', '0700')
end
it 'should typecast negative integer values to Integer' do
parse('key = -1').should be_option_tuple('key', -1)
end
it 'should typecast float values to Float' do
parse('key = 3.14159265').should be_option_tuple('key', 3.14159265)
end
it 'should typecast negative float values to Float' do
parse('key = -3.14159265').should be_option_tuple('key', -3.14159265)
end
it 'should typecast scientific notation numbers to Float' do
parse('key = 10e5').should be_option_tuple('key', 10e5)
parse('key = 10e+5').should be_option_tuple('key', 10e5)
parse('key = 10e-5').should be_option_tuple('key', 10e-5)
parse('key = -10e5').should be_option_tuple('key', -10e5)
parse('key = -10e+5').should be_option_tuple('key', -10e5)
parse('key = -10e-5').should be_option_tuple('key', -10e-5)
parse('key = 3.14159265e5').should be_option_tuple('key', 3.14159265e5)
parse('key = 3.14159265e+5').should be_option_tuple('key', 3.14159265e5)
parse('key = 3.14159265e-5').should be_option_tuple('key', 3.14159265e-5)
parse('key = -3.14159265e5').should be_option_tuple('key', -3.14159265e5)
parse('key = -3.14159265e+5').should be_option_tuple('key', -3.14159265e5)
parse('key = -3.14159265e-5').should be_option_tuple('key', -3.14159265e-5)
end
end
end
#
# Blank
#
#
# Comment
#
describe 'IniParse::Lines::Comment' do
describe '#has_comment?' do
it 'should return true if :comment has a non-blank value' do
IniParse::Lines::Comment.new(:comment => 'comment').should have_comment
end
it 'should return true if :comment has a blank value' do
IniParse::Lines::Comment.new(:comment => '').should have_comment
end
it 'should return true if :comment has a nil value' do
IniParse::Lines::Comment.new.should have_comment
IniParse::Lines::Comment.new(:comment => nil).should have_comment
end
end
describe '#to_ini' do
it 'should return the comment' do
IniParse::Lines::Comment.new(
:comment => 'a comment'
).to_ini.should == '; a comment'
end
it 'should preserve comment offset' do
IniParse::Lines::Comment.new(
:comment => 'a comment', :comment_offset => 10
).to_ini.should == ' ; a comment'
end
it 'should return just the comment_sep if the comment is blank' do
IniParse::Lines::Comment.new.to_ini.should == ';'
end
end
end
iniparse-1.4.2/spec/spec_helper.rb 0000644 0001750 0001750 00000010043 12725022733 017313 0 ustar terceiro terceiro $:.push File.join(File.dirname(__FILE__), '..', 'lib')
require 'rubygems'
require 'rspec'
require 'iniparse'
require File.join(File.dirname(__FILE__), 'spec_fixtures')
module IniParse
module Test
module Helpers
# Taken from Merb Core's spec helper.
# Merb is licenced using the MIT License and is copyright
# Engine Yard Inc.
class BeKindOf
def initialize(expected) # + args
@expected = expected
end
def matches?(target)
@target = target
@target.kind_of?(@expected)
end
def failure_message
"expected #{@expected} but got #{@target.class}"
end
def negative_failure_message
"expected #{@expected} to not be #{@target.class}"
end
def description
"be_kind_of #{@target}"
end
end
# Used to match line tuples returned by Parser.parse_line.
class BeLineTuple
def initialize(type, value_keys = [], *expected)
@expected_type = type
@value_keys = value_keys
if expected.nil?
@expected_opts = {}
@expected_values = []
else
@expected_opts = expected.pop
@expected_values = expected
end
end
def matches?(tuple)
@tuple = tuple
@failure_message = catch(:fail) do
tuple?
correct_type?
correct_values?
correct_opts?
true
end
@failure_message == true
end
def failure_message
"expected #{@expected_type} tuple #{@failure_message}"
end
def negative_failure_message
"expected #{@tuple.inspect} to not be #{@expected_type} tuple"
end
def description
"be_#{@expected_type}_tuple #{@tuple}"
end
#######
private
#######
# Matchers.
def tuple?
throw :fail, "but was #{@tuple.class}" unless @tuple.kind_of?(Array)
end
def correct_type?
throw :fail, "but was #{type} tuple" unless type == @expected_type
end
def correct_values?
# Make sure the values match.
@value_keys.each_with_index do |key, i|
if @expected_values[i] != :any && values[i] != @expected_values[i]
throw :fail, 'with %s value of "%s" but was "%s"' % [
key, values[i], @expected_values[i]
]
end
end
end
def correct_opts?
if(! @expected_opts.nil?)
if (! @expected_opts.empty?) && opts.empty?
throw :fail, 'with options but there were none'
end
@expected_opts.each do |key, value|
unless opts.has_key?(key)
throw :fail, 'with option "%s", but key was not present' % key
end
unless opts[key] == value
throw :fail, 'with option "%s" => "%s" but was "%s"' % [
key, value, opts[key]
]
end
end
end
end
# Tuple values, etc.
def type
@type ||= @tuple.first
end
def values
@values ||= @tuple.length < 3 ? [] : @tuple[1..-2]
end
def opts
@opts ||= @tuple.last
end
end
def be_kind_of(expected) # + args
BeKindOf.new(expected)
end
def be_section_tuple(key = :any, opts = {})
BeLineTuple.new(:section, [:key], key, opts)
end
def be_option_tuple(key = :any, value = :any, opts = {})
BeLineTuple.new(:option, [:key, :value], key, value, opts)
end
def be_blank_tuple
BeLineTuple.new(:blank)
end
def be_comment_tuple(comment = :any, opts = {})
BeLineTuple.new(:comment, [:comment], comment, opts)
end
def fixture(fix)
IniParse::Test::Fixtures[fix]
end
end
end
end
RSpec.configure do |config|
config.include(IniParse::Test::Helpers)
end
iniparse-1.4.2/spec/fixtures/ 0000755 0001750 0001750 00000000000 12725022733 016350 5 ustar terceiro terceiro iniparse-1.4.2/spec/fixtures/authconfig.ini 0000644 0001750 0001750 00000000601 12725022733 021175 0 ustar terceiro terceiro [global]
#--authconfig--start-line--
# Generated by authconfig on 2014/04/08 15:14:28
# DO NOT EDIT THIS SECTION (delimited by --start-line--/--end-line--)
# Any modification may be deleted or altered by authconfig in future
template homedir = /home/%U
template shell = /bin/bash
winbind use default domain = true
winbind offline logon = false
#--authconfig--end-line--
iniparse-1.4.2/spec/fixtures/race07.ini 0000644 0001750 0001750 00000005442 12725022733 020137 0 ustar terceiro terceiro ; All names and Steam IDs changed to fake values.
[Header]
Game=RACE 07
Version=1.1.1.14
TimeString=2008/09/13 23:26:32
Aids=0,0,0,0,0,1,1,0,0
[Race]
RaceMode=5
Scene=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.TRK
AIDB=GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW
Race Length=0.100
Track Length=4018.8376
[Slot010]
Driver=Mark Voss
SteamUser=mvoss
SteamId=1865369
Vehicle=Chevrolet Lacetti 2007
Team=TEMPLATE_TEAM
QualTime=1:37.839
Laps=13
Lap=(0, -1.000, 1:48.697)
Lap=(1, 89.397, 1:39.455)
Lap=(2, 198.095, 1:38.060)
Lap=(3, 297.550, 1:38.632)
Lap=(4, 395.610, 1:38.031)
Lap=(5, 494.242, 1:39.562)
Lap=(6, 592.273, 1:39.950)
Lap=(7, 691.835, 1:38.366)
Lap=(8, 791.785, 1:39.889)
Lap=(9, 890.151, 1:39.420)
Lap=(10, 990.040, 1:39.401)
Lap=(11, 1089.460, 1:39.506)
Lap=(12, 1188.862, 1:40.017)
LapDistanceTravelled=3857.750244
BestLap=1:38.031
RaceTime=0:21:38.988
[Slot016]
Driver=Corey Ball
SteamUser=cball
SteamId=889853
Vehicle=SEAT Leon 2007
Team=TEMPLATE_TEAM
QualTime=1:37.904
Laps=9
Lap=(0, -1.000, 1:51.434)
Lap=(1, 89.397, 1:39.427)
Lap=(2, 200.831, 1:38.394)
Lap=(3, 300.258, 1:40.239)
Lap=(4, 398.653, 1:38.172)
Lap=(5, 498.891, 1:38.427)
Lap=(6, 597.063, 1:39.271)
Lap=(7, 695.490, 1:39.922)
Lap=(8, 794.761, 1:40.305)
LapDistanceTravelled=532.898193
BestLap=1:38.172
RaceTime=DNF
Reason=0
[Slot013]
Driver=Gabriel Lloyd
SteamUser=glloyd
SteamId=635
Vehicle=Chevrolet Lacetti 2007
Team=TEMPLATE_TEAM
QualTime=1:36.607
Laps=13
Lap=(0, -1.000, 1:50.816)
Lap=(1, 89.397, 1:38.835)
Lap=(2, 200.213, 1:38.082)
Lap=(3, 299.048, 1:38.367)
Lap=(4, 397.131, 1:37.825)
Lap=(5, 495.497, 1:38.757)
Lap=(6, 593.322, 1:38.718)
Lap=(7, 692.080, 1:38.478)
Lap=(8, 790.797, 1:39.347)
Lap=(9, 889.275, 1:38.713)
Lap=(10, 988.622, 1:38.952)
Lap=(11, 1087.336, 1:39.285)
Lap=(12, 1186.288, 1:40.555)
LapDistanceTravelled=3898.517578
BestLap=1:37.825
RaceTime=0:21:36.730
[Slot018]
Driver=Reino Lintula
SteamUser=rlintula
SteamId=1816
Vehicle=SEAT Leon 2007
Team=TEMPLATE_TEAM
QualTime=1:39.602
Laps=7
Lap=(0, -1.000, 1:52.788)
Lap=(1, 112.593, 1:39.346)
Lap=(2, 225.381, 1:40.680)
Lap=(3, 324.727, 1:38.775)
Lap=(4, 425.407, 1:40.149)
Lap=(5, 524.182, 1:41.551)
Lap=(6, 624.331, 1:46.908)
LapDistanceTravelled=1333.551270
BestLap=1:38.775
RaceTime=DNF
Reason=0
[Slot002]
Driver=Jerry Lalich
SteamUser=jlalich
SteamId=236892
Vehicle=Chevrolet Lacetti 2007
Team=TEMPLATE_TEAM
QualTime=1:38.081
Laps=13
Lap=(0, -1.000, 1:48.530)
Lap=(1, 89.397, 1:39.213)
Lap=(2, 197.927, 1:37.933)
Lap=(3, 297.140, 1:37.717)
Lap=(4, 395.073, 1:38.500)
Lap=(5, 492.790, 1:38.641)
Lap=(6, 591.290, 1:39.810)
Lap=(7, 689.931, 1:39.177)
Lap=(8, 789.742, 1:40.122)
Lap=(9, 888.918, 1:38.928)
Lap=(10, 989.040, 1:39.238)
Lap=(11, 1087.968, 1:39.223)
Lap=(12, 1187.206, 1:39.888)
LapDistanceTravelled=3892.720215
BestLap=1:37.717
RaceTime=0:21:36.920
[END]
iniparse-1.4.2/spec/fixtures/smb.ini 0000644 0001750 0001750 00000006046 12725022733 017640 0 ustar terceiro terceiro ; Configuration file for the Samba software suite.
; ============================================================================
;
; For the format of this file and comprehensive descriptions of all the
; configuration option, please refer to the man page for smb.conf(5).
;
; The following configuration should suit most systems for basic usage and
; initial testing. It gives all clients access to their home directories and
; allows access to all printers specified in /etc/printcap.
; BEGIN required configuration
; Parameters inside the required configuration block should not be altered.
; They may be changed at any time by upgrades or other automated processes.
;
; Site-specific customizations will only be preserved if they are done
; outside this block. If you choose to make customizations, it is your
; own responsibility to verify that they work correctly with the supported
; configuration tools.
[global]
debug pid = yes
log level = 1
server string = Mac OS X
printcap name = cups
printing = cups
encrypt passwords = yes
use spnego = yes
passdb backend = odsam
idmap domains = default
idmap config default: default = yes
idmap config default: backend = odsam
idmap alloc backend = odsam
idmap negative cache time = 5
map to guest = Bad User
guest account = nobody
unix charset = UTF-8-MAC
display charset = UTF-8-MAC
dos charset = 437
vfs objects = darwinacl,darwin_streams
; Don't become a master browser unless absolutely necessary.
os level = 2
domain master = no
; For performance reasons, set the transmit buffer size
; to the maximum and enable sendfile support.
max xmit = 131072
use sendfile = yes
; The darwin_streams module gives us named streams support.
stream support = yes
ea support = yes
; Enable locking coherency with AFP.
darwin_streams:brlm = yes
; Core files are invariably disabled system-wide, but attempting to
; dump core will trigger a crash report, so we still want to try.
enable core files = yes
; Configure usershares for use by the synchronize-shares tool.
usershare max shares = 1000
usershare path = /var/samba/shares
usershare owner only = no
usershare allow guests = yes
usershare allow full config = yes
; Filter inaccessible shares from the browse list.
com.apple:filter shares by access = yes
; Check in with PAM to enforce SACL access policy.
obey pam restrictions = yes
; Don't be trying to enforce ACLs in userspace.
acl check permissions = no
; Make sure that we resolve unqualified names as NetBIOS before DNS.
name resolve order = lmhosts wins bcast host
; Pull in system-wide preference settings. These are managed by
; synchronize-preferences tool.
include = /var/db/smb.conf
[printers]
comment = All Printers
path = /tmp
printable = yes
guest ok = no
create mode = 0700
writeable = no
browseable = no
; Site-specific parameters can be added below this comment.
; END required configuration.
iniparse-1.4.2/spec/fixtures/openttd.ini 0000644 0001750 0001750 00000024767 12725022733 020546 0 ustar terceiro terceiro
[misc]
display_opt = SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS
news_ticker_sound = false
fullscreen = false
language = english_US.lng
resolution = 1680,936
screenshot_format =
savegame_format =
rightclick_emulate = false
small_font =
medium_font =
large_font =
small_size = 6
medium_size = 10
large_size = 16
small_aa = false
medium_aa = false
large_aa = false
sprite_cache_size = 4
player_face = 0
transparency_options = 3
transparency_locks = 0
invisibility_options = 30
keyboard =
keyboard_caps =
[music]
playlist = 0
music_vol = 0
effect_vol = 0
custom_1 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
custom_2 = 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
playing = false
shuffle = false
extmidi = timidity
[difficulty]
max_no_competitors = 0
competitor_start_time = 2
number_towns = 1
number_industries = 2
max_loan = 500000
initial_interest = 2
vehicle_costs = 0
competitor_speed = 2
competitor_intelligence = 0
vehicle_breakdowns = 1
subsidy_multiplier = 2
construction_cost = 0
terrain_type = 0
quantity_sea_lakes = 0
economy = 0
line_reverse_mode = 0
disasters = 0
town_council_tolerance = 0
diff_level = 3
[game_creation]
town_name = english
landscape = temperate
snow_line = 56
snow_line_height = 7
starting_year = 1960
land_generator = 1
oil_refinery_limit = 32
tgen_smoothness = 0
generation_seed = 83252223
tree_placer = 2
heightmap_rotation = 0
se_flat_world_height = 0
map_x = 9
map_y = 9
[vehicle]
road_side = left
realistic_acceleration = true
mammoth_trains = true
never_expire_vehicles = true
max_trains = 500
max_roadveh = 500
max_aircraft = 200
max_ships = 300
servint_ispercent = false
servint_trains = 150
servint_roadveh = 150
servint_ships = 360
servint_aircraft = 100
wagon_speed_limits = true
disable_elrails = false
freight_trains = 1
plane_speed = 4
dynamic_engines = false
extend_vehicle_life = 0
[construction]
build_on_slopes = true
autoslope = true
extra_dynamite = false
longbridges = true
signal_side = true
road_stop_on_town_road = true
raw_industry_construction = 1
[station]
always_small_airport = true
join_stations = true
nonuniform_stations = true
station_spread = 12
modified_catchment = true
adjacent_stations = true
[economy]
town_layout = 2
station_noise_level = false
inflation = true
multiple_industry_per_town = true
same_industry_close = true
bribe = true
exclusive_rights = true
give_money = true
smooth_economy = true
allow_shares = false
town_growth_rate = 1
larger_towns = 6
initial_city_size = 2
mod_road_rebuild = true
dist_local_authority = 20
town_noise_population = 800,2000,4000
[pf]
forbid_90_deg = false
roadveh_queue = true
pathfinder_for_trains = 2
pathfinder_for_roadvehs = 2
pathfinder_for_ships = 0
wait_oneway_signal = 15
wait_twoway_signal = 41
wait_for_pbs_path = 30
reserve_paths = false
path_backoff_interval = 20
opf.pf_maxlength = 4096
opf.pf_maxdepth = 48
npf.npf_max_search_nodes = 10000
npf.npf_rail_firstred_penalty = 1000
npf.npf_rail_firstred_exit_penalty = 10000
npf.npf_rail_lastred_penalty = 1000
npf.npf_rail_station_penalty = 100
npf.npf_rail_slope_penalty = 100
npf.npf_rail_curve_penalty = 1
npf.npf_rail_depot_reverse_penalty = 5000
npf.npf_rail_pbs_cross_penalty = 300
npf.npf_rail_pbs_signal_back_penalty = 1500
npf.npf_buoy_penalty = 200
npf.npf_water_curve_penalty = 25
npf.npf_road_curve_penalty = 1
npf.npf_crossing_penalty = 300
npf.npf_road_drive_through_penalty = 800
yapf.disable_node_optimization = false
yapf.max_search_nodes = 10000
yapf.rail_firstred_twoway_eol = true
yapf.rail_firstred_penalty = 1000
yapf.rail_firstred_exit_penalty = 10000
yapf.rail_lastred_penalty = 1000
yapf.rail_lastred_exit_penalty = 10000
yapf.rail_station_penalty = 1000
yapf.rail_slope_penalty = 200
yapf.rail_curve45_penalty = 300
yapf.rail_curve90_penalty = 600
yapf.rail_depot_reverse_penalty = 5000
yapf.rail_crossing_penalty = 300
yapf.rail_look_ahead_max_signals = 10
yapf.rail_look_ahead_signal_p0 = 500
yapf.rail_look_ahead_signal_p1 = -100
yapf.rail_look_ahead_signal_p2 = 5
yapf.rail_pbs_cross_penalty = 300
yapf.rail_pbs_station_penalty = 800
yapf.rail_pbs_signal_back_penalty = 1500
yapf.rail_doubleslip_penalty = 100
yapf.rail_longer_platform_penalty = 800
yapf.rail_longer_platform_per_tile_penalty = 0
yapf.rail_shorter_platform_penalty = 4000
yapf.rail_shorter_platform_per_tile_penalty = 0
yapf.road_slope_penalty = 200
yapf.road_curve_penalty = 100
yapf.road_crossing_penalty = 300
yapf.road_stop_penalty = 800
[order]
gotodepot = true
no_servicing_if_no_breakdowns = true
timetabling = true
improved_load = true
selectgoods = true
serviceathelipad = true
gradual_loading = true
[gui]
colored_news_year = 1901
ending_year = 2051
autosave = yearly
vehicle_speed = true
status_long_date = true
show_finances = true
autoscroll = false
reverse_scroll = true
smooth_scroll = false
measure_tooltip = true
errmsg_duration = 5
toolbar_pos = 1
window_snap_radius = 10
population_in_label = true
link_terraform_toolbar = true
liveries = 2
prefer_teamchat = false
scrollwheel_scrolling = 0
scrollwheel_multiplier = 5
pause_on_newgame = false
advanced_vehicle_list = 2
timetable_in_ticks = false
loading_indicators = 1
default_rail_type = 6
enable_signal_gui = true
drag_signals_density = 4
semaphore_build_before = 1975
train_income_warn = true
order_review_system = 2
lost_train_warn = true
autorenew = true
autorenew_months = 12
autorenew_money = 80000
always_build_infrastructure = false
new_nonstop = false
keep_all_autosave = false
autosave_on_exit = false
max_num_autosaves = 16
bridge_pillars = true
auto_euro = true
news_message_timeout = 2
show_track_reservation = false
default_signal_type = 0
cycle_signal_types = 0
console_backlog_timeout = 100
console_backlog_length = 100
network_chat_box_width = 700
network_chat_box_height = 25
right_mouse_btn_emulation = 0
[ai]
ainew_active = false
ai_in_multiplayer = false
ai_disable_veh_train = false
ai_disable_veh_roadveh = false
ai_disable_veh_aircraft = false
ai_disable_veh_ship = false
[locale]
currency = GBP
units = imperial
[network]
max_join_time = 500
pause_on_join = true
server_bind_ip = 0.0.0.0
server_port = 3979
server_advertise = false
lan_internet = 1
client_name = Ant
server_password =
rcon_password =
default_company_pass =
server_name =
connect_to_ip =
network_id =
autoclean_companies = false
autoclean_unprotected = 12
autoclean_protected = 36
max_companies = 8
max_clients = 10
max_spectators = 10
restart_game_year = 0
min_active_clients = 0
server_lang = ANY
reload_cfg = false
last_host =
last_port =
[currency]
rate = 1
separator = .
to_euro = 0
prefix = ""
suffix = " credits"
[servers]
[bans]
[news_display]
arrival_player = summarized
arrival_other = summarized
accident = full
company_info = full
open = summarized
close = summarized
economy = summarized
production_player = full
production_other = full
production_nobody = summarized
advice = full
new_vehicles = full
acceptance = summarized
subsidies = summarized
general = summarized
[version]
version_string = r14768
version_number = 070039B0
[preset-J]
gcf/1_other/BlackCC/mauvetoblackw.grf =
gcf/1_other/OpenGFX/newbuildings.grf =
gcf/1_other/OpenGFX/OpenGFX_NewShips_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_NewWaterFeatures.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newEyeCandy_v0.2.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newFaces_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newFonts_-_Newspaper_Fonts_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newFonts_-_Small_Fonts_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newIndustries_v0.8.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_-_Airports_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_-_newBridges_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_v0.6.grf =
gcf/1_other/OpenGFX/OpenGFX_NewLandscape_v0.3.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newTerrain_v0.4.grf =
gcf/4_infrastructure/transrapidtrackset/z/signals.grf =
gcf/8_vehicles/trains_wagons/pb_ukrs/pb_ukrs.grf =
gcf/8_vehicles/trains_wagons/pb_ukrs/ukrsap1w.grf =
gcf/6_town_buildings/ttrs3/ttrs3w.GRF =
gcf/7_stations/basic_platforms/basic_platformsw.grf =
gcf/1_other/townnames/british/brit_names.grf =
gcf/7_stations/indstatr/indstatrw.grf =
gcf/5_industries_cargos/pikkind/pikkindw.grf =
gcf/4_infrastructure/ukroadset/UKRoadsetw.grf =
gcf/7_stations/newstats/newstatsw.grf =
gcf/4_infrastructure/nhfoundations/nhfoundationsw.grf =
gcf/4_infrastructure/bktun/BKTunw.grf =
gcf/7_stations/buffers/buffers.grf =
gcf/8_vehicles/planes/pb_av8/pb_av8w.grf =
gcf/8_vehicles/road_vehicles/egrvts/egrvts.grf =
gcf/4_infrastructure/b_newbridges/newbridgesW.GRF =
gcf/8_vehicles/ships/newships/newshipsw.grf =
gcf/8_vehicles/ships/newships/nshp_ecs.grf =
gcf/4_infrastructure/nhdep/nhdepw.grf =
gcf/4_infrastructure/fence/fencew.grf =
gcf/2_landscape/stolentrees/stolentreesw_162_108.grf =
gcf/5_industries_cargos/pikkind/z/pikbrikw.grf =
[newgrf]
gcf/2_landscape/rivers/riversw.grf =
gcf/1_other/townnames/british/brit_names.grf =
gcf/8_vehicles/planes/pb_av8/pb_av8w.grf =
gcf/8_vehicles/trains_wagons/empty/empty.grf =
gcf/8_vehicles/road_vehicles/grvts/egrvts.grf =
gcf/7_stations/buffers/buffers.grf =
gcf/8_vehicles/road_vehicles/heqsdt/heqsdt.grf =
gcf/7_stations/indstatr/indstatrw.grf =
gcf/1_other/BlackCC/mauvetoblackw.grf =
gcf/4_infrastructure/b_newtramtracks/NewTramTracksW_v0.4.1.grf =
gcf/4_infrastructure/nhfoundations/nhfoundationsw.grf =
gcf/8_vehicles/ships/newships/newshipsw.grf =
gcf/8_vehicles/ships/newships/nshp_ecs.grf =
gcf/7_stations/newstats/newstatsw.grf =
gcf/4_infrastructure/nhdep/nhdepw.grf =
gcf/1_other/OpenGFX/morebuildings.grf =
gcf/1_other/OpenGFX/newbuildings022.grf =
gcf/1_other/OpenGFX/hq.grf =
gcf/1_other/OpenGFX/OpenGFX_NewWaterFeatures.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newEyeCandy_v0.2.grf =
gcf/1_other/OpenGFX/OpenGFX_NewIndustries_v0.10.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newInfrastructure_-_Airports_v0.1.grf =
gcf/1_other/OpenGFX/OpenGFX_newInfrastructure_v0.7.grf =
gcf/1_other/OpenGFX/OpenGFX_NewLandscape_v0.3.1.grf =
gcf/1_other/OpenGFX/OpenGFX_-_newTerrain_v0.4.grf =
gcf/5_industries_cargos/pikkind/pikkindw.grf =
gcf/2_landscape/stolentrees/stolentreesw_162_108.grf =
gcf/4_infrastructure/totalbridges/total_bridges.grf =
gcf/7_stations/ukwaypoints/ukwaypointsw.grf =
gcf/8_vehicles/trains_wagons/pb_ukrs/pb_ukrs.grf = 0 3 0
gcf/8_vehicles/trains_wagons/pb_ukrs/ukrsap1w.grf =
gcf/4_infrastructure/yarrs/yarrs.grf =
gcf/6_town_buildings/w2w/w2w.grf =
gcf/1_other/townnames/welsh/welshnames.grf =
gcf/2_landscape/smoothsnow/smoothsnoww.grf =
gcf/6_town_buildings/pb_ukrh/pb_ukrhw.grf =
gcf/9_last/shiptool/shiptoolv4.grf =
[newgrf-static]
iniparse-1.4.2/spec/spec_fixtures.rb 0000644 0001750 0001750 00000002727 12725022733 017717 0 ustar terceiro terceiro module IniParse
module Test
class Fixtures
@@fixtures = {}
def self.[](fix)
if @@fixtures.has_key?(fix)
@@fixtures[fix]
else
@@fixtures[fix] = File.read(
File.join(File.expand_path('fixtures', File.dirname(__FILE__)), fix)
)
end
end
def self.[]=(fix, val)
@@fixtures[fix] = val
end
end
end
end
IniParse::Test::Fixtures[:comment_before_section] = <<-FIX.gsub(/^ /, '')
; This is a comment
[first_section]
key = value
FIX
IniParse::Test::Fixtures[:blank_before_section] = <<-FIX.gsub(/^ /, '')
[first_section]
key = value
FIX
IniParse::Test::Fixtures[:blank_in_section] = <<-FIX.gsub(/^ /, '')
[first_section]
key = value
FIX
IniParse::Test::Fixtures[:option_before_section] = <<-FIX.gsub(/^ /, '')
foo = bar
[foo]
another = thing
FIX
IniParse::Test::Fixtures[:invalid_line] = <<-FIX.gsub(/^ /, '')
this line is not valid
FIX
IniParse::Test::Fixtures[:section_with_equals] = <<-FIX.gsub(/^ /, '')
[first_section = name]
key = value
[another_section = a name]
another = thing
FIX
IniParse::Test::Fixtures[:comment_line] = <<-FIX.gsub(/^ /, '')
[first_section]
; block comment ;
; with more lines ;
key = value
FIX
IniParse::Test::Fixtures[:duplicate_section] = <<-FIX.gsub(/^ /, '')
[first_section]
key = value
another = thing
[second_section]
okay = yes
[first_section]
third = fourth
another = again
FIX
iniparse-1.4.2/spec/document_spec.rb 0000644 0001750 0001750 00000010614 12725022733 017656 0 ustar terceiro terceiro require 'spec_helper'
describe "IniParse::Document" do
it 'should have a +lines+ reader' do
methods = IniParse::Document.instance_methods.map { |m| m.to_sym }
methods.should include(:lines)
end
it 'should not have a +lines+ writer' do
methods = IniParse::Document.instance_methods.map { |m| m.to_sym }
methods.should_not include(:lines=)
end
it 'should delegate #[] to +lines+' do
doc = IniParse::Document.new
doc.lines.should_receive(:[]).with('key')
doc['key']
end
it 'should call #each to +lines+' do
doc = IniParse::Document.new
doc.lines.should_receive(:each)
doc.each { |l| }
end
it 'should be enumerable' do
IniParse::Document.included_modules.should include(Enumerable)
sections = [
IniParse::Lines::Section.new('first section'),
IniParse::Lines::Section.new('second section')
]
doc = IniParse::Document.new
doc.lines << sections[0] << sections[1]
doc.map { |line| line }.should == sections
end
describe '#has_section?' do
before(:all) do
@doc = IniParse::Document.new
@doc.lines << IniParse::Lines::Section.new('first section')
@doc.section('another section')
end
it 'should return true if a section with the given key exists' do
@doc.should have_section('first section')
@doc.should have_section('another section')
end
it 'should return true if no section with the given key exists' do
@doc.should_not have_section('second section')
end
end
describe '#delete' do
let(:document) do
IniParse::Generator.gen do |doc|
doc.section('first') do |section|
section.alpha = 'bravo'
section.charlie = 'delta'
end
doc.section('second') do |section|
section.echo = 'foxtrot'
section.golf = 'hotel'
end
end
end
it 'removes the section given a key' do
lambda { document.delete('first') }.
should change { document['first'] }.to(nil)
end
it 'removes the section given a Section' do
lambda { document.delete(document['first']) }.
should change { document['first'] }.to(nil)
end
it 'removes the lines' do
lambda { document.delete('first') }.
should change { document.to_ini.match(/alpha/) }.to(nil)
end
it 'returns the document' do
document.delete('first').should eql(document)
end
end
describe '#to_ini' do
let(:document) do
IniParse.parse(<<-EOF.gsub(/^\s+/, ''))
[one]
alpha = bravo
[two]
chalie = delta
EOF
end
context 'when the document has a trailing Blank line' do
it 'outputs the newline to the output string' do
expect(document.to_ini).to match(/\n\Z/)
end
it 'does not add a second newline to the output string' do
expect(document.to_ini).to_not match(/\n\n\Z/)
end
end # when the document has a trailing Blank line
context 'when the document has no trailing Blank line' do
before { document.delete('two') }
it 'adds a newline to the output string' do
expect(document.to_ini).to match(/\n\Z/)
end
end # when the document has no trailing Blank line
end # to_ini
describe '#save' do
describe 'when no path is given to save' do
it 'should save the INI document if a path was given when initialized' do
doc = IniParse::Document.new('/a/path/to/a/file.ini')
File.should_receive(:open).with('/a/path/to/a/file.ini', 'w')
doc.save
end
it 'should raise IniParseError if no path was given when initialized' do
lambda { IniParse::Document.new.save }.should \
raise_error(IniParse::IniParseError)
end
end
describe 'when a path is given to save' do
it "should update the document's +path+" do
File.stub(:open).and_return(true)
doc = IniParse::Document.new('/a/path/to/a/file.ini')
doc.save('/a/new/path.ini')
doc.path.should == '/a/new/path.ini'
end
it 'should save the INI document to the given path' do
File.should_receive(:open).with('/a/new/path.ini', 'w')
IniParse::Document.new('/a/path/to/a/file.ini').save('/a/new/path.ini')
end
it 'should raise IniParseError if no path was given when initialized' do
lambda { IniParse::Document.new.save }.should \
raise_error(IniParse::IniParseError)
end
end
end
end
iniparse-1.4.2/spec/line_collection_spec.rb 0000644 0001750 0001750 00000014051 12725022733 021201 0 ustar terceiro terceiro require 'spec_helper'
# ----------------------------------------------------------------------------
# Shared specs for all Collection types...
# ----------------------------------------------------------------------------
share_examples_for "LineCollection" do
before(:each) do
@collection << (@c1 = IniParse::Lines::Comment.new)
@collection << @i1
@collection << @i2
@collection << (@b1 = IniParse::Lines::Blank.new)
@collection << @i3
@collection << (@b2 = IniParse::Lines::Blank.new)
end
describe '#each' do
it 'should remove blanks and comments by default' do
@collection.each { |l| l.should be_kind_of(@i1.class) }
end
it 'should not remove blanks and comments if true is given' do
arr = []
# map(true)->each(true) not possible with Enumerable
@collection.each(true) do |line|
arr << line
end
arr.should == [@c1, @i1, @i2, @b1, @i3, @b2]
end
end
describe '#[]' do
it 'should fetch the correct value' do
@collection['first'].should == @i1
@collection['second'].should == @i2
@collection['third'].should == @i3
end
it 'should return nil if the given key does not exist' do
@collection['does not exist'].should be_nil
end
end
describe '#[]=' do
it 'should successfully add a new key' do
@collection['fourth'] = @new
@collection['fourth'].should == @new
end
it 'should successfully update an existing key' do
@collection['second'] = @new
@collection['second'].should == @new
# Make sure the old data is gone.
@collection.detect { |s| s.key == 'second' }.should be_nil
end
it 'should typecast given keys to a string' do
@collection[:a_symbol] = @new
@collection['a_symbol'].should == @new
end
end
describe '#<<' do
it 'should set the key correctly if given a new item' do
@collection.should_not have_key(@new.key)
@collection << @new
@collection.should have_key(@new.key)
end
it 'should append Blank lines' do
@collection << IniParse::Lines::Blank.new
@collection.instance_variable_get(:@lines).last.should \
be_kind_of(IniParse::Lines::Blank)
end
it 'should append Comment lines' do
@collection << IniParse::Lines::Comment.new
@collection.instance_variable_get(:@lines).last.should \
be_kind_of(IniParse::Lines::Comment)
end
it 'should return self' do
(@collection << @new).should == @collection
end
end
describe '#delete' do
it 'should remove the given value and adjust the indicies' do
@collection['second'].should_not be_nil
@collection.delete('second')
@collection['second'].should be_nil
@collection['first'].should == @i1
@collection['third'].should == @i3
end
it "should do nothing if the supplied key does not exist" do
@collection.delete('does not exist')
@collection['first'].should == @i1
@collection['third'].should == @i3
end
end
describe '#to_a' do
it 'should return an array' do
@collection.to_a.should be_kind_of(Array)
end
it 'should include all lines' do
@collection.to_a.should == [@c1, @i1, @i2, @b1, @i3, @b2]
end
it 'should include references to the same line objects as the collection' do
@collection << @new
@collection.to_a.last.object_id.should == @new.object_id
end
end
describe '#to_hash' do
it 'should return a hash' do
@collection.to_hash.should be_kind_of(Hash)
end
it 'should have the correct keys' do
hash = @collection.to_hash
hash.keys.length.should == 3
hash.should have_key('first')
hash.should have_key('second')
hash.should have_key('third')
end
it 'should have the correct values' do
hash = @collection.to_hash
hash['first'].should == @i1
hash['second'].should == @i2
hash['third'].should == @i3
end
end
describe '#keys' do
it 'should return an array of strings' do
@collection.keys.should == ['first', 'second', 'third']
end
end
end
# ----------------------------------------------------------------------------
# On with the collection specs...
# ----------------------------------------------------------------------------
describe 'IniParse::OptionCollection' do
before(:each) do
@collection = IniParse::OptionCollection.new
@i1 = IniParse::Lines::Option.new('first', 'v1')
@i2 = IniParse::Lines::Option.new('second', 'v2')
@i3 = IniParse::Lines::Option.new('third', 'v3')
@new = IniParse::Lines::Option.new('fourth', 'v4')
end
it_should_behave_like 'LineCollection'
describe '#<<' do
it 'should raise a LineNotAllowed exception if a Section is pushed' do
lambda { @collection << IniParse::Lines::Section.new('s') }.should \
raise_error(IniParse::LineNotAllowed)
end
it 'should add the Option as a duplicate if an option with the same key exists' do
option_one = IniParse::Lines::Option.new('k', 'value one')
option_two = IniParse::Lines::Option.new('k', 'value two')
@collection << option_one
@collection << option_two
@collection['k'].should == [option_one, option_two]
end
end
describe '#keys' do
it 'should handle duplicates' do
@collection << @i1 << @i2 << @i3
@collection << IniParse::Lines::Option.new('first', 'v5')
@collection.keys.should == ['first', 'second', 'third']
end
end
end
describe 'IniParse::SectionCollection' do
before(:each) do
@collection = IniParse::SectionCollection.new
@i1 = IniParse::Lines::Section.new('first')
@i2 = IniParse::Lines::Section.new('second')
@i3 = IniParse::Lines::Section.new('third')
@new = IniParse::Lines::Section.new('fourth')
end
it_should_behave_like 'LineCollection'
describe '#<<' do
it 'should add merge Section with the other, if it is a duplicate' do
new_section = IniParse::Lines::Section.new('first')
@collection << @i1
@i1.should_receive(:merge!).with(new_section).once
@collection << new_section
end
end
end
iniparse-1.4.2/spec/fixture_spec.rb 0000644 0001750 0001750 00000015154 12725022733 017532 0 ustar terceiro terceiro require 'spec_helper'
describe "IniParse" do
describe 'openttd.ini fixture' do
before(:all) do
@fixture = fixture('openttd.ini')
end
it 'should parse without any errors' do
lambda { IniParse.parse(@fixture) }.should_not raise_error
end
it 'should have the correct sections' do
IniParse.parse(fixture('openttd.ini')).lines.keys.should == [
'misc', 'music', 'difficulty', 'game_creation', 'vehicle',
'construction', 'station', 'economy', 'pf', 'order', 'gui', 'ai',
'locale', 'network', 'currency', 'servers', 'bans', 'news_display',
'version', 'preset-J', 'newgrf', 'newgrf-static'
]
end
it 'should have the correct options' do
# Test the keys from one section.
doc = IniParse.parse(@fixture)
section = doc['misc']
section.lines.keys.should == [
'display_opt', 'news_ticker_sound', 'fullscreen', 'language',
'resolution', 'screenshot_format', 'savegame_format',
'rightclick_emulate', 'small_font', 'medium_font', 'large_font',
'small_size', 'medium_size', 'large_size', 'small_aa', 'medium_aa',
'large_aa', 'sprite_cache_size', 'player_face',
'transparency_options', 'transparency_locks', 'invisibility_options',
'keyboard', 'keyboard_caps'
]
# Test some of the options.
section['display_opt'].should == 'SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION|FULL_DETAIL|WAYPOINTS'
section['news_ticker_sound'].should be_false
section['language'].should == 'english_US.lng'
section['resolution'].should == '1680,936'
section['large_size'].should == 16
# Test some other options.
doc['currency']['suffix'].should == '" credits"'
doc['news_display']['production_nobody'].should == 'summarized'
doc['version']['version_number'].should == '070039B0'
doc['preset-J']['gcf/1_other/BlackCC/mauvetoblackw.grf'].should be_nil
doc['preset-J']['gcf/1_other/OpenGFX/OpenGFX_-_newFaces_v0.1.grf'].should be_nil
end
it 'should be identical to the original when calling #to_ini' do
IniParse.parse(@fixture).to_ini.should == @fixture
end
end
describe 'race07.ini fixture' do
before(:all) do
@fixture = fixture('race07.ini')
end
it 'should parse without any errors' do
lambda { IniParse.parse(@fixture) }.should_not raise_error
end
it 'should have the correct sections' do
IniParse.parse(fixture('race07.ini')).lines.keys.should == [
'Header', 'Race', 'Slot010', 'Slot016', 'Slot013', 'Slot018',
'Slot002', 'END'
]
end
it 'should have the correct options' do
# Test the keys from one section.
doc = IniParse.parse(@fixture)
section = doc['Slot010']
section.lines.keys.should == [
'Driver', 'SteamUser', 'SteamId', 'Vehicle', 'Team', 'QualTime',
'Laps', 'Lap', 'LapDistanceTravelled', 'BestLap', 'RaceTime'
]
# Test some of the options.
section['Driver'].should == 'Mark Voss'
section['SteamUser'].should == 'mvoss'
section['SteamId'].should == 1865369
section['Vehicle'].should == 'Chevrolet Lacetti 2007'
section['Team'].should == 'TEMPLATE_TEAM'
section['QualTime'].should == '1:37.839'
section['Laps'].should == 13
section['LapDistanceTravelled'].should == 3857.750244
section['BestLap'].should == '1:38.031'
section['RaceTime'].should == '0:21:38.988'
section['Lap'].should == [
'(0, -1.000, 1:48.697)', '(1, 89.397, 1:39.455)',
'(2, 198.095, 1:38.060)', '(3, 297.550, 1:38.632)',
'(4, 395.610, 1:38.031)', '(5, 494.242, 1:39.562)',
'(6, 592.273, 1:39.950)', '(7, 691.835, 1:38.366)',
'(8, 791.785, 1:39.889)', '(9, 890.151, 1:39.420)',
'(10, 990.040, 1:39.401)', '(11, 1089.460, 1:39.506)',
'(12, 1188.862, 1:40.017)'
]
doc['Header']['Version'].should == '1.1.1.14'
doc['Header']['TimeString'].should == '2008/09/13 23:26:32'
doc['Header']['Aids'].should == '0,0,0,0,0,1,1,0,0'
doc['Race']['AIDB'].should == 'GameData\Locations\Anderstorp_2007\2007_ANDERSTORP.AIW'
doc['Race']['Race Length'].should == 0.1
end
it 'should be identical to the original when calling #to_ini' do
pending('awaiting presevation (or lack) of whitespace around =') do
IniParse.parse(@fixture).to_ini.should == @fixture
end
end
end
describe 'smb.ini fixture' do
before(:all) do
@fixture = fixture('smb.ini')
end
it 'should parse without any errors' do
lambda { IniParse.parse(@fixture) }.should_not raise_error
end
it 'should have the correct sections' do
IniParse.parse(@fixture).lines.keys.should == [
'global', 'printers'
]
end
it 'should have the correct options' do
# Test the keys from one section.
doc = IniParse.parse(@fixture)
section = doc['global']
section.lines.keys.should == [
'debug pid', 'log level', 'server string', 'printcap name',
'printing', 'encrypt passwords', 'use spnego', 'passdb backend',
'idmap domains', 'idmap config default: default',
'idmap config default: backend', 'idmap alloc backend',
'idmap negative cache time', 'map to guest', 'guest account',
'unix charset', 'display charset', 'dos charset', 'vfs objects',
'os level', 'domain master', 'max xmit', 'use sendfile',
'stream support', 'ea support', 'darwin_streams:brlm',
'enable core files', 'usershare max shares', 'usershare path',
'usershare owner only', 'usershare allow guests',
'usershare allow full config', 'com.apple:filter shares by access',
'obey pam restrictions', 'acl check permissions',
'name resolve order', 'include'
]
section['display charset'].should == 'UTF-8-MAC'
section['vfs objects'].should == 'darwinacl,darwin_streams'
section['usershare path'].should == '/var/samba/shares'
end
it 'should be identical to the original when calling #to_ini' do
IniParse.parse(@fixture).to_ini.should == @fixture
end
end
describe 'authconfig.ini fixture' do
before(:all) do
@fixture = fixture('authconfig.ini')
end
it 'should be identical to the original when calling #to_ini' do
IniParse.parse(@fixture).to_ini.should == @fixture
end
end
describe 'option before section fixture' do
before(:all) do
@fixture = fixture(:option_before_section)
end
it 'should be identical to the original when calling #to_ini' do
IniParse.parse(@fixture).to_ini.should == @fixture
end
end
end
iniparse-1.4.2/spec/parser/ 0000755 0001750 0001750 00000000000 12725022733 015773 5 ustar terceiro terceiro iniparse-1.4.2/spec/parser/line_parsing_spec.rb 0000644 0001750 0001750 00000026444 12725022733 022016 0 ustar terceiro terceiro require 'spec_helper'
# Tests parsing of individual, out of context, line types using #parse_line.
describe 'Parsing a line' do
it 'should strip leading whitespace and set the :indent option' do
IniParse::Parser.parse_line(' [section]').should \
be_section_tuple(:any, {:indent => ' '})
end
it 'should raise an error if the line could not be matched' do
lambda { IniParse::Parser.parse_line('invalid line') }.should \
raise_error(IniParse::ParseError)
end
it 'should parse using the types set in IniParse::Parser.parse_types' do
begin
# Remove last type.
type = IniParse::Parser.parse_types.pop
type.should_not_receive(:parse)
IniParse::Parser.parse_line('[section]')
ensure
IniParse::Parser.parse_types << type
end
end
# --
# ==========================================================================
# Option lines.
# ==========================================================================
# ++
describe 'with "k = v"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('k = v')
end
it 'should return an option tuple' do
@tuple.should be_option_tuple('k', 'v')
end
it 'should set no indent, comment, offset or separator' do
@tuple.last[:indent].should be_nil
@tuple.last[:comment].should be_nil
@tuple.last[:comment_offset].should be_nil
@tuple.last[:comment_sep].should be_nil
end
end
describe 'with "k = a value with spaces"' do
it 'should return an option tuple' do
IniParse::Parser.parse_line('k = a value with spaces').should \
be_option_tuple('k', 'a value with spaces')
end
end
describe 'with "k = v ; a comment "' do
before(:all) do
@tuple = IniParse::Parser.parse_line('k = v ; a comment')
end
it 'should return an option tuple' do
@tuple.should be_option_tuple('k', 'v')
end
it 'should set the comment to "a comment"' do
@tuple.should be_option_tuple(:any, :any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
@tuple.should be_option_tuple(:any, :any, :comment_sep => ';')
end
it 'should set the comment offset to 6' do
@tuple.should be_option_tuple(:any, :any, :comment_offset => 6)
end
end
describe 'with "k = v;w;x y;z"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('k = v;w;x y;z')
end
it 'should return an option tuple with the correct value' do
@tuple.should be_option_tuple(:any, 'v;w;x y;z')
end
it 'should not set a comment' do
@tuple.last[:comment].should be_nil
@tuple.last[:comment_offset].should be_nil
@tuple.last[:comment_sep].should be_nil
end
end
describe 'with "k = v;w ; a comment"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('k = v;w ; a comment')
end
it 'should return an option tuple with the correct value' do
@tuple.should be_option_tuple(:any, 'v;w')
end
it 'should set the comment to "a comment"' do
@tuple.should be_option_tuple(:any, :any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
@tuple.should be_option_tuple(:any, :any, :comment_sep => ';')
end
it 'should set the comment offset to 8' do
@tuple.should be_option_tuple(:any, :any, :comment_offset => 8)
end
end
describe 'with "key=value"' do
it 'should return an option tuple with the correct key and value' do
IniParse::Parser.parse_line('key=value').should \
be_option_tuple('key', 'value')
end
end
describe 'with "key= value"' do
it 'should return an option tuple with the correct key and value' do
IniParse::Parser.parse_line('key= value').should \
be_option_tuple('key', 'value')
end
end
describe 'with "key =value"' do
it 'should return an option tuple with the correct key and value' do
IniParse::Parser.parse_line('key =value').should \
be_option_tuple('key', 'value')
end
end
describe 'with "key = value"' do
it 'should return an option tuple with the correct key and value' do
IniParse::Parser.parse_line('key = value').should \
be_option_tuple('key', 'value')
end
end
describe 'with "key ="' do
it 'should return an option tuple with the correct key' do
IniParse::Parser.parse_line('key =').should \
be_option_tuple('key')
end
it 'should set the option value to nil' do
IniParse::Parser.parse_line('key =').should \
be_option_tuple(:any, nil)
end
end
describe 'with "key = EEjDDJJjDJDJD233232=="' do
it 'should include the "equals" in the option value' do
IniParse::Parser.parse_line('key = EEjDDJJjDJDJD233232==').should \
be_option_tuple('key', 'EEjDDJJjDJDJD233232==')
end
end
describe 'with "key = ==EEjDDJJjDJDJD233232"' do
it 'should include the "equals" in the option value' do
IniParse::Parser.parse_line('key = ==EEjDDJJjDJDJD233232').should \
be_option_tuple('key', '==EEjDDJJjDJDJD233232')
end
end
describe 'with "key.two = value"' do
it 'should return an option tuple with the correct key' do
IniParse::Parser.parse_line('key.two = value').should \
be_option_tuple('key.two')
end
end
describe 'with "key/with/slashes = value"' do
it 'should return an option tuple with the correct key' do
IniParse::Parser.parse_line('key/with/slashes = value').should \
be_option_tuple('key/with/slashes', 'value')
end
end
describe 'with "key_with_underscores = value"' do
it 'should return an option tuple with the correct key' do
IniParse::Parser.parse_line('key_with_underscores = value').should \
be_option_tuple('key_with_underscores', 'value')
end
end
describe 'with "key-with-dashes = value"' do
it 'should return an option tuple with the correct key' do
IniParse::Parser.parse_line('key-with-dashes = value').should \
be_option_tuple('key-with-dashes', 'value')
end
end
describe 'with "key with spaces = value"' do
it 'should return an option tuple with the correct key' do
IniParse::Parser.parse_line('key with spaces = value').should \
be_option_tuple('key with spaces', 'value')
end
end
# --
# ==========================================================================
# Section lines.
# ==========================================================================
# ++
describe 'with "[section]"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('[section]')
end
it 'should return a section tuple' do
@tuple.should be_section_tuple('section')
end
it 'should set no indent, comment, offset or separator' do
@tuple.last[:indent].should be_nil
@tuple.last[:comment].should be_nil
@tuple.last[:comment_offset].should be_nil
@tuple.last[:comment_sep].should be_nil
end
end
describe 'with "[section with whitespace]"' do
it 'should return a section tuple with the correct key' do
IniParse::Parser.parse_line('[section with whitespace]').should \
be_section_tuple('section with whitespace')
end
end
describe 'with "[ section with surounding whitespace ]"' do
it 'should return a section tuple with the correct key' do
IniParse::Parser.parse_line('[ section with surounding whitespace ]').should \
be_section_tuple(' section with surounding whitespace ')
end
end
describe 'with "[section] ; a comment"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('[section] ; a comment')
end
it 'should return a section tuple' do
@tuple.should be_section_tuple('section')
end
it 'should set the comment to "a comment"' do
@tuple.should be_section_tuple(:any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
@tuple.should be_section_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 10' do
@tuple.should be_section_tuple(:any, :comment_offset => 10)
end
end
describe 'with "[section;with#comment;chars]"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('[section;with#comment;chars]')
end
it 'should return a section tuple with the correct key' do
@tuple.should be_section_tuple('section;with#comment;chars')
end
it 'should not set a comment' do
@tuple.last[:indent].should be_nil
@tuple.last[:comment].should be_nil
@tuple.last[:comment_offset].should be_nil
@tuple.last[:comment_sep].should be_nil
end
end
describe 'with "[section;with#comment;chars] ; a comment"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('[section;with#comment;chars] ; a comment')
end
it 'should return a section tuple with the correct key' do
@tuple.should be_section_tuple('section;with#comment;chars')
end
it 'should set the comment to "a comment"' do
@tuple.should be_section_tuple(:any, :comment => 'a comment')
end
it 'should set the comment separator to ";"' do
@tuple.should be_section_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 29' do
@tuple.should be_section_tuple(:any, :comment_offset => 29)
end
end
# --
# ==========================================================================
# Comment lines.
# ==========================================================================
# ++
describe 'with "; a comment"' do
before(:all) do
@tuple = IniParse::Parser.parse_line('; a comment')
end
it 'should return a comment tuple with the correct comment' do
@tuple.should be_comment_tuple('a comment')
end
it 'should set the comment separator to ";"' do
@tuple.should be_comment_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 0' do
@tuple.should be_comment_tuple(:any, :comment_offset => 0)
end
end
describe 'with " ; a comment"' do
before(:all) do
@tuple = IniParse::Parser.parse_line(' ; a comment')
end
it 'should return a comment tuple with the correct comment' do
@tuple.should be_comment_tuple('a comment')
end
it 'should set the comment separator to ";"' do
@tuple.should be_comment_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 1' do
@tuple.should be_comment_tuple(:any, :comment_offset => 1)
end
end
describe 'with ";"' do
before(:all) do
@tuple = IniParse::Parser.parse_line(';')
end
it 'should return a comment tuple with an empty value' do
@tuple.should be_comment_tuple('')
end
it 'should set the comment separator to ";"' do
@tuple.should be_comment_tuple(:any, :comment_sep => ';')
end
it 'should set the comment offset to 0' do
@tuple.should be_comment_tuple(:any, :comment_offset => 0)
end
end
# --
# ==========================================================================
# Blank lines.
# ==========================================================================
# ++
describe 'with ""' do
it 'should return a blank tuple' do
IniParse::Parser.parse_line('').should be_blank_tuple
end
end
describe 'with " "' do
it 'should return a blank tuple' do
IniParse::Parser.parse_line(' ').should be_blank_tuple
end
end
end
iniparse-1.4.2/spec/parser/document_parsing_spec.rb 0000644 0001750 0001750 00000006243 12725022733 022700 0 ustar terceiro terceiro require 'spec_helper'
# Tests parsing of multiple lines, in context, using #parse.
describe 'Parsing a document' do
describe 'when a comment preceeds a single section and option' do
before(:all) do
@doc = IniParse::Parser.new(fixture(:comment_before_section)).parse
end
it 'should have a comment as the first line' do
@doc.lines.to_a.first.should be_kind_of(IniParse::Lines::Comment)
end
it 'should have one section' do
@doc.lines.keys.should == ['first_section']
end
it 'should have one option belonging to `first_section`' do
@doc['first_section']['key'].should == 'value'
end
end
it 'should allow blank lines to preceed the first section' do
lambda {
@doc = IniParse::Parser.new(fixture(:blank_before_section)).parse
}.should_not raise_error
@doc.lines.to_a.first.should be_kind_of(IniParse::Lines::Blank)
end
it 'should allow a blank line to belong to a section' do
lambda {
@doc = IniParse::Parser.new(fixture(:blank_in_section)).parse
}.should_not raise_error
@doc['first_section'].lines.to_a.first.should be_kind_of(IniParse::Lines::Blank)
end
it 'should permit comments on their own line' do
lambda {
@doc = IniParse::Parser.new(fixture(:comment_line)).parse
}.should_not raise_error
line = @doc['first_section'].lines.to_a.first
line.comment.should eql('; block comment ;')
end
it 'should permit options before the first section' do
doc = IniParse::Parser.new(fixture(:option_before_section)).parse
doc.lines.should have_key('__anonymous__')
doc['__anonymous__']['foo'].should eql('bar')
doc['foo']['another'].should eql('thing')
end
it 'should raise ParseError if a line could not be parsed' do
lambda { IniParse::Parser.new(fixture(:invalid_line)).parse }.should \
raise_error(IniParse::ParseError)
end
describe 'when a section name contains "="' do
before(:all) do
@doc = IniParse::Parser.new(fixture(:section_with_equals)).parse
end
it 'should have two sections' do
@doc.lines.to_a.length.should == 2
end
it 'should have one section' do
@doc.lines.keys.should == ['first_section = name',
'another_section = a name']
end
it 'should have one option belonging to `first_section = name`' do
@doc['first_section = name']['key'].should == 'value'
end
it 'should have one option belonging to `another_section = a name`' do
@doc['another_section = a name']['another'].should == 'thing'
end
end
describe 'when a document contains a section multiple times' do
before(:all) do
@doc = IniParse::Parser.new(fixture(:duplicate_section)).parse
end
it 'should only add the section once' do
# "first_section" and "second_section".
@doc.lines.to_a.length.should == 2
end
it 'should retain values from the first time' do
@doc['first_section']['key'].should == 'value'
end
it 'should add new keys' do
@doc['first_section']['third'].should == 'fourth'
end
it 'should merge in duplicate keys' do
@doc['first_section']['another'].should == %w( thing again )
end
end
end
iniparse-1.4.2/.gitignore 0000644 0001750 0001750 00000000105 12725022733 015531 0 ustar terceiro terceiro .DS_Store
coverage/*
doc/*
pkg/*
*.rbc
*.swp
*.gem
rdoc
Gemfile.lock
iniparse-1.4.2/Gemfile 0000644 0001750 0001750 00000000046 12725022733 015040 0 ustar terceiro terceiro source 'https://rubygems.org'
gemspec