ryanwood-slither 0.99.1 → 0.99.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +8 -2
- data/README.rdoc +2 -0
- data/Rakefile +1 -1
- data/lib/slither/column.rb +32 -21
- data/lib/slither/section.rb +5 -2
- data/lib/slither/slither.rb +1 -0
- data/slither.gemspec +0 -0
- data/spec/column_spec.rb +97 -53
- data/spec/parser_spec.rb +1 -10
- data/spec/section_spec.rb +8 -0
- metadata +2 -3
- data/VERSION.yml +0 -4
data/History.txt
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
== 0.99.2 / 2009-04-28
|
|
2
3
|
|
|
3
|
-
*
|
|
4
|
+
* Added better support for float formatting
|
|
5
|
+
* Added the money_with_implied_decimal type
|
|
4
6
|
|
|
5
7
|
== 0.99.1 / 2009-04-22
|
|
6
8
|
|
|
@@ -8,3 +10,7 @@
|
|
|
8
10
|
* Prevent duplicate column names
|
|
9
11
|
* Better error messages
|
|
10
12
|
* Implement custom padding (spaces (default), zero)
|
|
13
|
+
|
|
14
|
+
== 0.99.0 / 2009-04-14
|
|
15
|
+
|
|
16
|
+
* Initial Release
|
data/README.rdoc
CHANGED
|
@@ -46,6 +46,8 @@ A simple, clean DSL for describing, writing, and parsing fixed-width text files.
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
Supported types are: string, integer, date, float, money, and money_with_implied_decimal.
|
|
50
|
+
|
|
49
51
|
Then either feed it a nested struct with data values to create the file in the defined format:
|
|
50
52
|
|
|
51
53
|
test_data = {
|
data/Rakefile
CHANGED
|
@@ -24,7 +24,7 @@ PROJ.name = 'slither'
|
|
|
24
24
|
PROJ.authors = 'Ryan Wood'
|
|
25
25
|
PROJ.email = 'ryan.wood@gmail.com'
|
|
26
26
|
PROJ.url = 'http://github.com/ryanwood/slither'
|
|
27
|
-
PROJ.version = '0.99.
|
|
27
|
+
PROJ.version = '0.99.2'
|
|
28
28
|
PROJ.exclude = %w(\.git .gitignore ^tasks \.eprj ^pkg)
|
|
29
29
|
PROJ.readme_file = 'README.rdoc'
|
|
30
30
|
|
data/lib/slither/column.rb
CHANGED
|
@@ -20,13 +20,15 @@ class Slither
|
|
|
20
20
|
"A#{@length}"
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def
|
|
23
|
+
def parse(value)
|
|
24
24
|
case @type
|
|
25
25
|
when :integer: value.to_i
|
|
26
|
-
when :float: value.to_f
|
|
26
|
+
when :float, :money: value.to_f
|
|
27
|
+
when :money_with_implied_decimal:
|
|
28
|
+
value.to_f / 100
|
|
27
29
|
when :date:
|
|
28
|
-
if @options[:
|
|
29
|
-
Date.strptime(value, @options[:
|
|
30
|
+
if @options[:format]
|
|
31
|
+
Date.strptime(value, @options[:format])
|
|
30
32
|
else
|
|
31
33
|
Date.strptime(value)
|
|
32
34
|
end
|
|
@@ -35,13 +37,15 @@ class Slither
|
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def format(value)
|
|
38
|
-
pad(formatter %
|
|
40
|
+
pad(formatter % to_s(value))
|
|
41
|
+
rescue
|
|
42
|
+
puts "Could not format column '#{@name}' as a '#{@type}' with formatter '#{formatter}' and value of '#{value}' (formatted: '#{to_s(value)}'). #{$!}"
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
private
|
|
42
46
|
|
|
43
47
|
def formatter
|
|
44
|
-
"%#{aligner}#{sizer}
|
|
48
|
+
"%#{aligner}#{sizer}s"
|
|
45
49
|
end
|
|
46
50
|
|
|
47
51
|
def aligner
|
|
@@ -52,14 +56,6 @@ class Slither
|
|
|
52
56
|
(@type == :float && @precision) ? @precision : @length
|
|
53
57
|
end
|
|
54
58
|
|
|
55
|
-
def typer
|
|
56
|
-
case @type
|
|
57
|
-
when :integer: 'd'
|
|
58
|
-
when :float: 's'
|
|
59
|
-
else 's'
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
59
|
# Manually apply padding. sprintf only allows padding on numeric fields.
|
|
64
60
|
def pad(value)
|
|
65
61
|
return value unless @padding == :zero
|
|
@@ -69,19 +65,34 @@ class Slither
|
|
|
69
65
|
value.gsub(space[0], '0' * space[0].size)
|
|
70
66
|
end
|
|
71
67
|
|
|
72
|
-
def
|
|
68
|
+
def to_s(value)
|
|
73
69
|
result = case @type
|
|
74
|
-
when :date:
|
|
75
|
-
if
|
|
76
|
-
|
|
70
|
+
when :date:
|
|
71
|
+
# If it's a DBI::Timestamp object, see if we can convert it to a Time object
|
|
72
|
+
unless value.respond_to?(:strftime)
|
|
73
|
+
value = value.to_time if value.respond_to?(:to_time)
|
|
74
|
+
end
|
|
75
|
+
if value.respond_to?(:strftime)
|
|
76
|
+
if @options[:format]
|
|
77
|
+
value.strftime(@options[:format])
|
|
78
|
+
else
|
|
79
|
+
value.strftime
|
|
80
|
+
end
|
|
77
81
|
else
|
|
78
|
-
value.
|
|
82
|
+
value.to_s
|
|
79
83
|
end
|
|
80
|
-
|
|
84
|
+
when :float:
|
|
85
|
+
@options[:format] ? @options[:format] % value.to_f : value.to_f.to_s
|
|
86
|
+
when :money:
|
|
87
|
+
"%.2f" % value.to_f
|
|
88
|
+
when :money_with_implied_decimal:
|
|
89
|
+
"%d" % (value.to_f * 100)
|
|
90
|
+
else
|
|
91
|
+
value.to_s
|
|
81
92
|
end
|
|
82
93
|
raise(
|
|
83
94
|
Slither::FormattedStringExceedsLengthError,
|
|
84
|
-
"The formatted value '#{result}'
|
|
95
|
+
"The formatted value '#{result}' in column '#{@name}' exceeds the allowed length of #{@length} chararacters."
|
|
85
96
|
) if result.length > @length
|
|
86
97
|
result
|
|
87
98
|
end
|
data/lib/slither/section.rb
CHANGED
|
@@ -39,7 +39,10 @@ class Slither
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def format(data)
|
|
42
|
-
|
|
42
|
+
# raise( ColumnMismatchError,
|
|
43
|
+
# "The '#{@name}' section has #{@columns.size} column(s) defined, but there are #{data.size} column(s) provided in the data."
|
|
44
|
+
# ) unless @columns.size == data.size
|
|
45
|
+
row = ''
|
|
43
46
|
@columns.each do |column|
|
|
44
47
|
row += column.format(data[column.name])
|
|
45
48
|
end
|
|
@@ -50,7 +53,7 @@ class Slither
|
|
|
50
53
|
line_data = line.unpack(unpacker)
|
|
51
54
|
row = {}
|
|
52
55
|
@columns.each_with_index do |c, i|
|
|
53
|
-
row[c.name] = c.
|
|
56
|
+
row[c.name] = c.parse(line_data[i]) unless RESERVED_NAMES.include?(c.name)
|
|
54
57
|
end
|
|
55
58
|
row
|
|
56
59
|
end
|
data/lib/slither/slither.rb
CHANGED
|
@@ -6,6 +6,7 @@ class Slither
|
|
|
6
6
|
class RequiredSectionNotFoundError < StandardError; end
|
|
7
7
|
class RequiredSectionEmptyError < StandardError; end
|
|
8
8
|
class FormattedStringExceedsLengthError < StandardError; end
|
|
9
|
+
class ColumnMismatchError < StandardError; end
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def self.define(name, options = {}, &block)
|
data/slither.gemspec
CHANGED
|
Binary file
|
data/spec/column_spec.rb
CHANGED
|
@@ -60,73 +60,55 @@ describe Slither::Column do
|
|
|
60
60
|
it "should return the proper unpack value for a string" do
|
|
61
61
|
@column.send(:unpacker).should == 'A5'
|
|
62
62
|
end
|
|
63
|
-
|
|
64
|
-
describe "when
|
|
63
|
+
|
|
64
|
+
describe "when parsing a value from a file" do
|
|
65
65
|
it "should default to a string" do
|
|
66
|
-
@column.
|
|
66
|
+
@column.parse(' name ').should == 'name'
|
|
67
|
+
@column.parse(' 234').should == '234'
|
|
68
|
+
@column.parse('000000234').should == '000000234'
|
|
69
|
+
@column.parse('12.34').should == '12.34'
|
|
67
70
|
end
|
|
68
|
-
|
|
69
|
-
it "should support the
|
|
70
|
-
@column = Slither::Column.new(
|
|
71
|
-
@column.
|
|
71
|
+
|
|
72
|
+
it "should support the integer type" do
|
|
73
|
+
@column = Slither::Column.new(:amount, 10, :type=> :integer)
|
|
74
|
+
@column.parse('234 ').should == 234
|
|
75
|
+
@column.parse(' 234').should == 234
|
|
76
|
+
@column.parse('00000234').should == 234
|
|
77
|
+
@column.parse('Ryan ').should == 0
|
|
78
|
+
@column.parse('00023.45').should == 23
|
|
72
79
|
end
|
|
73
80
|
|
|
74
|
-
it "should support the
|
|
75
|
-
@column = Slither::Column.new(
|
|
76
|
-
@column.
|
|
77
|
-
|
|
81
|
+
it "should support the float type" do
|
|
82
|
+
@column = Slither::Column.new(:amount, 10, :type=> :float)
|
|
83
|
+
@column.parse(' 234.45').should == 234.45
|
|
84
|
+
@column.parse('234.5600').should == 234.56
|
|
85
|
+
@column.parse(' 234').should == 234.0
|
|
86
|
+
@column.parse('00000234').should == 234.0
|
|
87
|
+
@column.parse('Ryan ').should == 0
|
|
88
|
+
@column.parse('00023.45').should == 23.45
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should support the money_with_implied_decimal type" do
|
|
92
|
+
@column = Slither::Column.new(:amount, 10, :type=> :money_with_implied_decimal)
|
|
93
|
+
@column.parse(' 23445').should == 234.45
|
|
94
|
+
end
|
|
78
95
|
|
|
79
|
-
it "should support the
|
|
80
|
-
@column = Slither::Column.new(
|
|
81
|
-
dt = @column.
|
|
96
|
+
it "should support the date type" do
|
|
97
|
+
@column = Slither::Column.new(:date, 10, :type => :date)
|
|
98
|
+
dt = @column.parse('2009-08-22')
|
|
82
99
|
dt.should be_a(Date)
|
|
83
100
|
dt.to_s.should == '2009-08-22'
|
|
84
101
|
end
|
|
85
102
|
|
|
86
|
-
it "should use the
|
|
87
|
-
@column = Slither::Column.new(
|
|
88
|
-
dt = @column.
|
|
103
|
+
it "should use the format option with date type if available" do
|
|
104
|
+
@column = Slither::Column.new(:date, 10, :type => :date, :format => "%m%d%Y")
|
|
105
|
+
dt = @column.parse('08222009')
|
|
89
106
|
dt.should be_a(Date)
|
|
90
107
|
dt.to_s.should == '2009-08-22'
|
|
91
108
|
end
|
|
92
109
|
end
|
|
93
110
|
|
|
94
|
-
describe "when
|
|
95
|
-
it "should default to a string" do
|
|
96
|
-
@column.send(:format_as_string, 'name').should == 'name'
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "should raise an error if the value is longer than the length" do
|
|
100
|
-
lambda { @column.send(:format_as_string, 'This string is too long') }.should raise_error(
|
|
101
|
-
Slither::FormattedStringExceedsLengthError,
|
|
102
|
-
"The formatted value 'This string is too long' exceeds #{@length} chararacters, the allowable length of the '#{@name}' column."
|
|
103
|
-
)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
it "should support the :integer type" do
|
|
107
|
-
@column = Slither::Column.new(@name, @length, :type => :integer)
|
|
108
|
-
@column.send(:format_as_string, 234).should == '234'
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
it "should support the :float type" do
|
|
112
|
-
@column = Slither::Column.new(:amount, 6, :type => :float)
|
|
113
|
-
@column.send(:format_as_string, 234.45).should == '234.45'
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it "should support the :date type" do
|
|
117
|
-
dt = Date.new(2009, 8, 22)
|
|
118
|
-
@column = Slither::Column.new(:date, 10, :type => :date)
|
|
119
|
-
@column.send(:format_as_string, dt).should == '2009-08-22'
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it "should use the :date_format option with :date type if available" do
|
|
123
|
-
dt = Date.new(2009, 8, 22)
|
|
124
|
-
@column = Slither::Column.new(:date, 8, :type => :date, :date_format => "%m%d%Y")
|
|
125
|
-
@column.send(:format_as_string, dt).should == '08222009'
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
describe "when formatting a column" do
|
|
111
|
+
describe "when applying formatting options" do
|
|
130
112
|
it "should return a proper formatter" do
|
|
131
113
|
@column = Slither::Column.new(@name, @length, :align => :left)
|
|
132
114
|
@column.send(:formatter).should == "%-5s"
|
|
@@ -162,6 +144,68 @@ describe Slither::Column do
|
|
|
162
144
|
@column = Slither::Column.new(@name, @length, :type => :float, :padding => :zero, :align => :left)
|
|
163
145
|
@column.format(4.45).should == '4.450'
|
|
164
146
|
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe "when formatting values for a file" do
|
|
151
|
+
it "should default to a string" do
|
|
152
|
+
@column = Slither::Column.new(:name, 10)
|
|
153
|
+
@column.format('Bill').should == ' Bill'
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "should raise an error if the value is longer than the length" do
|
|
157
|
+
@value = "XX" * @length
|
|
158
|
+
lambda { @column.format(@value) }.should raise_error(
|
|
159
|
+
Slither::FormattedStringExceedsLengthError,
|
|
160
|
+
"The formatted value '#{@value}' in column '#{@name}' exceeds the allowed length of #{@length} chararacters."
|
|
161
|
+
)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it "should support the integer type" do
|
|
165
|
+
@column = Slither::Column.new(:amount, 10, :type => :integer)
|
|
166
|
+
@column.format(234).should == ' 234'
|
|
167
|
+
@column.format('234').should == ' 234'
|
|
165
168
|
end
|
|
169
|
+
|
|
170
|
+
it "should support the float type" do
|
|
171
|
+
@column = Slither::Column.new(:amount, 10, :type => :float)
|
|
172
|
+
@column.format(234.45).should == ' 234.45'
|
|
173
|
+
@column.format('234.4500').should == ' 234.45'
|
|
174
|
+
@column.format('3').should == ' 3.0'
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "should support the float type with a format" do
|
|
178
|
+
@column = Slither::Column.new(:amount, 10, :type => :float, :format => "%.3f")
|
|
179
|
+
@column.format(234.45).should == ' 234.450'
|
|
180
|
+
@column.format('234.4500').should == ' 234.450'
|
|
181
|
+
@column.format('3').should == ' 3.000'
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should support the float type with a format, alignment and padding" do
|
|
185
|
+
@column = Slither::Column.new(:amount, 10, :type => :float, :format => "%.2f", :align => :left, :padding => :zero)
|
|
186
|
+
@column.format(234.45).should == '234.450000'
|
|
187
|
+
@column = Slither::Column.new(:amount, 10, :type => :float, :format => "%.2f", :align => :right, :padding => :zero)
|
|
188
|
+
@column.format('234.400').should == '0000234.40'
|
|
189
|
+
@column = Slither::Column.new(:amount, 10, :type => :float, :format => "%.4f", :align => :left, :padding => :space)
|
|
190
|
+
@column.format('3').should == '3.0000 '
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "should support the money_with_implied_decimal type" do
|
|
194
|
+
@column = Slither::Column.new(:amount, 10, :type=> :money_with_implied_decimal)
|
|
195
|
+
@column.format(234.450).should == " 23445"
|
|
196
|
+
@column.format(12.34).should == " 1234"
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "should support the date type" do
|
|
200
|
+
dt = Date.new(2009, 8, 22)
|
|
201
|
+
@column = Slither::Column.new(:date, 10, :type => :date)
|
|
202
|
+
@column.format(dt).should == '2009-08-22'
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "should support the date type with a :format" do
|
|
206
|
+
dt = Date.new(2009, 8, 22)
|
|
207
|
+
@column = Slither::Column.new(:date, 8, :type => :date, :format => "%m%d%Y")
|
|
208
|
+
@column.format(dt).should == '08222009'
|
|
209
|
+
end
|
|
166
210
|
end
|
|
167
211
|
end
|
data/spec/parser_spec.rb
CHANGED
|
@@ -69,15 +69,6 @@ describe Slither::Parser do
|
|
|
69
69
|
lambda { @parser.parse }.should raise_error(Slither::RequiredSectionNotFoundError, "Required section 'header' was not found.")
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
it "raise an error if a section limit is over run"
|
|
72
|
+
# it "raise an error if a section limit is over run"
|
|
73
73
|
end
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
describe "when in linear mode" do
|
|
78
|
-
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
74
|
end
|
data/spec/section_spec.rb
CHANGED
|
@@ -104,6 +104,14 @@ describe Slither::Section do
|
|
|
104
104
|
@section.column(:name, 10, :align => :left)
|
|
105
105
|
@section.format(@data).should == " 3Ryan "
|
|
106
106
|
end
|
|
107
|
+
|
|
108
|
+
# it "should raise an error if the data and column definitions aren't the same size" do
|
|
109
|
+
# @section.column(:id, 5)
|
|
110
|
+
# lambda { @section.format(@data) }.should raise_error(
|
|
111
|
+
# Slither::ColumnMismatchError,
|
|
112
|
+
# "The 'body' section has 1 column(s) defined, but there are 2 column(s) provided in the data."
|
|
113
|
+
# )
|
|
114
|
+
# end
|
|
107
115
|
end
|
|
108
116
|
|
|
109
117
|
describe "when parsing a file" do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ryanwood-slither
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.99.
|
|
4
|
+
version: 0.99.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Wood
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-04-
|
|
12
|
+
date: 2009-04-28 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -36,7 +36,6 @@ files:
|
|
|
36
36
|
- README.rdoc
|
|
37
37
|
- Rakefile
|
|
38
38
|
- TODO
|
|
39
|
-
- VERSION.yml
|
|
40
39
|
- lib/slither.rb
|
|
41
40
|
- lib/slither/column.rb
|
|
42
41
|
- lib/slither/definition.rb
|
data/VERSION.yml
DELETED