remote_table 1.2.2 → 1.2.3
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/.gitattributes +1 -0
- data/README.rdoc +12 -0
- data/lib/remote_table.rb +5 -0
- data/lib/remote_table/executor.rb +3 -0
- data/lib/remote_table/format.rb +16 -9
- data/lib/remote_table/format/delimited.rb +10 -8
- data/lib/remote_table/format/fixed_width.rb +12 -5
- data/lib/remote_table/format/mixins/processed_by_nokogiri.rb +4 -2
- data/lib/remote_table/format/mixins/processed_by_roo.rb +9 -12
- data/lib/remote_table/format/mixins/textual.rb +13 -2
- data/lib/remote_table/local_file.rb +12 -0
- data/lib/remote_table/properties.rb +48 -36
- data/lib/remote_table/version.rb +1 -1
- data/remote_table.gemspec +2 -4
- data/test/helper.rb +16 -1
- data/test/support/list-en1-semic-3.neooffice.binary.ods +0 -0
- data/test/support/list-en1-semic-3.neooffice.iso-8859-1.csv +0 -0
- data/test/support/list-en1-semic-3.neooffice.iso-8859-1.fixed_width-64 +0 -0
- data/test/support/list-en1-semic-3.neooffice.utf-8.csv +0 -0
- data/test/support/list-en1-semic-3.neooffice.utf-8.fixed_width-62 +0 -0
- data/test/support/list-en1-semic-3.neooffice.utf-8.html +0 -0
- data/test/support/list-en1-semic-3.neooffice.utf-8.xml +0 -0
- data/test/support/list-en1-semic-3.office-2011-for-mac-sp1-excel-95.binary.xls +0 -0
- data/test/support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xls +0 -0
- data/test/support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xlsx +0 -0
- data/test/support/list-en1-semic-3.office-2011-for-mac-sp1.iso-8859-1.html +0 -0
- data/test/support/list-en1-semic-3.office-2011-for-mac-sp1.mac.csv-comma +0 -0
- data/test/support/list-en1-semic-3.office-2011-for-mac-sp1.utf-8.html +0 -0
- data/test/support/list-en1-semic-3.original.iso-8859-1.csv +0 -0
- data/test/test_old_syntax.rb +1 -1
- data/test/test_old_transform.rb +26 -31
- data/test/test_remote_table.rb +34 -7
- metadata +37 -81
data/.gitattributes
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
list-en1-semic-3* -crlf -diff -merge
|
data/README.rdoc
CHANGED
@@ -6,6 +6,13 @@ Open local or remote XLSX, XLS, ODS, CSV and fixed-width files.
|
|
6
6
|
|
7
7
|
Used by http://data.brighterplanet.com and the data_miner gem (http://github.com/seamusabshere/data_miner)
|
8
8
|
|
9
|
+
==Requirements
|
10
|
+
|
11
|
+
* POSIX operating system (not windows)
|
12
|
+
* curl, iconv, perl, cat, cut, tail, etc. accessible from /usr/local/bin:/usr/bin:/bin
|
13
|
+
|
14
|
+
As this library matures, those should go away.
|
15
|
+
|
9
16
|
==Example
|
10
17
|
|
11
18
|
?> t = RemoteTable.new 'http://www.fueleconomy.gov/FEG/epadata/98guide6.zip', 'filename' => '98guide6.csv'
|
@@ -136,6 +143,11 @@ More examples:
|
|
136
143
|
[ 'spacer', 1 ],
|
137
144
|
[ 'header1', 10, { :type => :string } ]]
|
138
145
|
|
146
|
+
==Helpful hints
|
147
|
+
|
148
|
+
* ASCII-8BIT is the same as BINARY
|
149
|
+
* ISO-8859-1 is the same as Latin1
|
150
|
+
|
139
151
|
==Custom parsers
|
140
152
|
|
141
153
|
See the test file and also data_miner examples of custom parsers.
|
data/lib/remote_table.rb
CHANGED
@@ -16,6 +16,9 @@ class RemoteTable
|
|
16
16
|
|
17
17
|
def backtick_with_reporting(cmd, raise_on_error = false)
|
18
18
|
cmd = cmd.gsub /\n/m, ' '
|
19
|
+
if ::ENV['REMOTE_TABLE_DEBUG'] and ::ENV['REMOTE_TABLE_DEBUG'].include? 'backtick'
|
20
|
+
$stderr.puts "[remote_table] Executing #{cmd}"
|
21
|
+
end
|
19
22
|
pid = ::POSIX::Spawn.spawn({ 'PATH' => '/usr/local/bin:/usr/bin:/bin' }, cmd)
|
20
23
|
stat = ::Process::waitpid pid
|
21
24
|
if raise_on_error and not stat.success?
|
data/lib/remote_table/format.rb
CHANGED
@@ -24,17 +24,24 @@ class RemoteTable
|
|
24
24
|
@t = t
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def transliterate_to_utf8(str)
|
28
|
+
return if str.nil?
|
29
|
+
$stderr.puts "[remote_table translit] Before: #{str}" if ::ENV['REMOTE_TABLE_DEBUG'] and ::ENV['REMOTE_TABLE_DEBUG'].include?('translit')
|
30
|
+
transliterated_str = if ::RUBY_VERSION >= '1.9'
|
31
|
+
str.ensure_encoding t.properties.external_encoding, :external_encoding => t.properties.internal_encoding, :invalid_characters => :transcode
|
32
|
+
else
|
33
|
+
::Iconv.conv(t.properties.external_encoding_iconv, t.properties.internal_encoding, str.to_s + ' ')[0..-2]
|
34
|
+
end
|
35
|
+
$stderr.puts "[remote_table translit] After: #{transliterated_str}" if ::ENV['REMOTE_TABLE_DEBUG'] and ::ENV['REMOTE_TABLE_DEBUG'].include?('translit')
|
36
|
+
transliterated_str
|
37
|
+
end
|
38
|
+
|
39
|
+
def assume_utf8(str)
|
40
|
+
return if str.nil?
|
28
41
|
if ::RUBY_VERSION >= '1.9'
|
29
|
-
str.
|
42
|
+
str.encode! t.properties.external_encoding
|
30
43
|
else
|
31
|
-
|
32
|
-
begin
|
33
|
-
::Iconv.conv('UTF-8//TRANSLIT', t.properties.encoding[0], str.to_s + ' ')[0..-2]
|
34
|
-
rescue ::Iconv::IllegalSequence
|
35
|
-
$stderr.puts "[remote_table] Unable to transliterate #{str} into UTF-8 given #{t.properties.encoding[0]}"
|
36
|
-
str
|
37
|
-
end
|
44
|
+
str
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
@@ -17,19 +17,21 @@ class RemoteTable
|
|
17
17
|
include Textual
|
18
18
|
def each(&blk)
|
19
19
|
remove_useless_characters!
|
20
|
+
fix_newlines!
|
21
|
+
transliterate_whole_file_to_utf8!
|
20
22
|
skip_rows!
|
21
|
-
CSV.
|
23
|
+
CSV.new(t.local_file.encoded_io, fastercsv_options).each do |row|
|
22
24
|
if row.is_a?(CSV::Row)
|
23
|
-
|
24
|
-
if
|
25
|
-
|
26
|
-
memo[key] = utf8 value
|
25
|
+
hash = row.inject(::ActiveSupport::OrderedHash.new) do |memo, (k, v)|
|
26
|
+
if k.present?
|
27
|
+
memo[k] = v.to_s
|
27
28
|
end
|
28
29
|
memo
|
29
30
|
end
|
30
|
-
yield
|
31
|
-
|
32
|
-
|
31
|
+
yield hash if t.properties.keep_blank_rows or hash.any? { |k, v| v.present? }
|
32
|
+
elsif row.is_a?(::Array)
|
33
|
+
array = row.map { |v| v.to_s }
|
34
|
+
yield array if t.properties.keep_blank_rows or array.any? { |v| v.present? }
|
33
35
|
end
|
34
36
|
end
|
35
37
|
ensure
|
@@ -1,17 +1,20 @@
|
|
1
|
-
require '
|
1
|
+
require 'fixed_width'
|
2
|
+
|
2
3
|
class RemoteTable
|
3
4
|
class Format
|
4
5
|
class FixedWidth < Format
|
5
6
|
include Textual
|
6
7
|
def each(&blk)
|
7
8
|
remove_useless_characters!
|
9
|
+
fix_newlines!
|
10
|
+
transliterate_whole_file_to_utf8!
|
8
11
|
crop_rows!
|
9
12
|
skip_rows!
|
10
13
|
cut_columns!
|
11
14
|
parser.parse[:rows].each do |row|
|
12
15
|
row.reject! { |k, v| k.blank? }
|
13
16
|
row.each do |k, v|
|
14
|
-
row[k] =
|
17
|
+
row[k] = v.strip
|
15
18
|
end
|
16
19
|
yield row if t.properties.keep_blank_rows or row.any? { |k, v| v.present? }
|
17
20
|
end
|
@@ -22,16 +25,20 @@ class RemoteTable
|
|
22
25
|
private
|
23
26
|
|
24
27
|
def parser
|
25
|
-
@parser
|
28
|
+
return @parser if @parser.is_a?(::FixedWidth::Parser)
|
29
|
+
if ::FixedWidth::Section.private_instance_methods.map(&:to_sym).include?(:unpacker)
|
30
|
+
raise "[remote_table] You need a different (newer) version of the FixedWidth gem that supports multibyte encoding, sometime after https://github.com/timonk/fixed_width/pull/1 was incorporated"
|
31
|
+
end
|
32
|
+
@parser = ::FixedWidth::Parser.new definition, t.local_file.encoded_io
|
26
33
|
end
|
27
34
|
|
28
35
|
def definition
|
29
36
|
@definition ||= if t.properties.schema_name.is_a?(::String) or t.properties.schema_name.is_a?(::Symbol)
|
30
|
-
::
|
37
|
+
::FixedWidth.send :definition, t.properties.schema_name
|
31
38
|
elsif t.properties.schema.is_a?(::Array)
|
32
39
|
everything = lambda { |_| true }
|
33
40
|
srand # in case this was forked by resque
|
34
|
-
::
|
41
|
+
::FixedWidth.define(rand.to_s) do |d|
|
35
42
|
d.rows do |row|
|
36
43
|
row.trap(&everything)
|
37
44
|
t.properties.schema.each do |name, width, options|
|
@@ -4,7 +4,9 @@ class RemoteTable
|
|
4
4
|
class Format
|
5
5
|
module ProcessedByNokogiri
|
6
6
|
def each
|
7
|
+
raise "[remote_table] Need :row_css or :row_xpath in order to process XML or HTML" unless t.properties.row_css or t.properties.row_xpath
|
7
8
|
remove_useless_characters!
|
9
|
+
transliterate_whole_file_to_utf8!
|
8
10
|
first_row = true
|
9
11
|
keys = t.properties.headers if t.properties.headers.is_a?(::Array)
|
10
12
|
xml = nokogiri_class.parse(unescaped_xml_without_soft_hyphens, nil, 'UTF-8')
|
@@ -15,7 +17,7 @@ class RemoteTable
|
|
15
17
|
row.xpath(t.properties.column_xpath)
|
16
18
|
else
|
17
19
|
[row]
|
18
|
-
end.map { |cell| cell.content.gsub(/\s+/, ' ').strip }
|
20
|
+
end.map { |cell| assume_utf8 cell.content.gsub(/\s+/, ' ').strip }
|
19
21
|
if first_row and t.properties.use_first_row_as_header?
|
20
22
|
keys = values
|
21
23
|
first_row = false
|
@@ -57,7 +59,7 @@ class RemoteTable
|
|
57
59
|
|
58
60
|
# should we be doing this in ruby?
|
59
61
|
def unescaped_xml_without_soft_hyphens
|
60
|
-
str = ::CGI.unescapeHTML
|
62
|
+
str = ::CGI.unescapeHTML t.local_file.encoded_io.read
|
61
63
|
# get rid of MS Office baddies
|
62
64
|
str.gsub! '­', ''
|
63
65
|
str
|
@@ -6,9 +6,9 @@ class RemoteTable
|
|
6
6
|
spreadsheet = roo_class.new t.local_file.path, nil, :ignore
|
7
7
|
spreadsheet.default_sheet = t.properties.sheet.is_a?(::Numeric) ? spreadsheet.sheets[t.properties.sheet] : t.properties.sheet
|
8
8
|
if t.properties.output_class == ::Array
|
9
|
-
(
|
9
|
+
(first_row..spreadsheet.last_row).each do |y|
|
10
10
|
output = (1..spreadsheet.last_column).map do |x|
|
11
|
-
spreadsheet.cell(y, x).to_s.gsub(/<[^>]+>/, '').strip
|
11
|
+
assume_utf8 spreadsheet.cell(y, x).to_s.gsub(/<[^>]+>/, '').strip
|
12
12
|
end
|
13
13
|
yield output if t.properties.keep_blank_rows or output.any? { |v| v.present? }
|
14
14
|
end
|
@@ -16,18 +16,19 @@ class RemoteTable
|
|
16
16
|
keys = {}
|
17
17
|
if t.properties.use_first_row_as_header?
|
18
18
|
(1..spreadsheet.last_column).each do |x|
|
19
|
-
keys[x] = spreadsheet.cell(
|
20
|
-
keys[x] = spreadsheet.cell(
|
19
|
+
keys[x] = spreadsheet.cell(first_row, x)
|
20
|
+
keys[x] = spreadsheet.cell(first_row - 1, x) if keys[x].blank? # look up
|
21
|
+
keys[x] = assume_utf8 keys[x]
|
21
22
|
end
|
22
23
|
else
|
23
24
|
(1..spreadsheet.last_column).each do |x|
|
24
|
-
keys[x] = t.properties.headers[x - 1]
|
25
|
+
keys[x] = assume_utf8 t.properties.headers[x - 1]
|
25
26
|
end
|
26
27
|
end
|
27
|
-
(
|
28
|
+
(first_row+1..spreadsheet.last_row).each do |y|
|
28
29
|
output = (1..spreadsheet.last_column).inject(::ActiveSupport::OrderedHash.new) do |memo, x|
|
29
30
|
if keys[x].present?
|
30
|
-
memo[keys[x]] = spreadsheet.cell(y, x).to_s.gsub(/<[^>]+>/, '').strip
|
31
|
+
memo[keys[x]] = assume_utf8 spreadsheet.cell(y, x).to_s.gsub(/<[^>]+>/, '').strip
|
31
32
|
end
|
32
33
|
memo
|
33
34
|
end
|
@@ -40,13 +41,9 @@ class RemoteTable
|
|
40
41
|
|
41
42
|
private
|
42
43
|
|
43
|
-
def
|
44
|
+
def first_row
|
44
45
|
1 + t.properties.skip
|
45
46
|
end
|
46
|
-
|
47
|
-
def first_data_row
|
48
|
-
1 + header_row
|
49
|
-
end
|
50
47
|
end
|
51
48
|
end
|
52
49
|
end
|
@@ -6,11 +6,22 @@ class RemoteTable
|
|
6
6
|
USELESS_CHARACTERS = [
|
7
7
|
'\xef\xbb\xbf', # UTF-8 byte order mark
|
8
8
|
'\xc2\xad', # soft hyphen, often inserted by MS Office (html: ­)
|
9
|
-
'\xad',
|
10
|
-
# '\xa0'
|
11
9
|
]
|
12
10
|
def remove_useless_characters!
|
13
11
|
::RemoteTable.executor.bang t.local_file.path, "perl -pe 's/#{USELESS_CHARACTERS.join '//g; s/'}//g'"
|
12
|
+
if t.properties.internal_encoding =~ /windows.?1252/i
|
13
|
+
# soft hyphen again, as I have seen it appear in windows 1252
|
14
|
+
::RemoteTable.executor.bang t.local_file.path, %q{perl -pe 's/\xad//g'}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def transliterate_whole_file_to_utf8!
|
19
|
+
::RemoteTable.executor.bang t.local_file.path, "iconv -c -f #{::Escape.shell_single_word t.properties.internal_encoding} -t #{::Escape.shell_single_word t.properties.external_encoding_iconv}"
|
20
|
+
t.properties.update 'encoding' => t.properties.external_encoding
|
21
|
+
end
|
22
|
+
|
23
|
+
def fix_newlines!
|
24
|
+
::RemoteTable.executor.bang t.local_file.path, %q{perl -pe 's/\r\n|\n|\r/\n/g'}
|
14
25
|
end
|
15
26
|
|
16
27
|
def skip_rows!
|
@@ -15,8 +15,20 @@ class RemoteTable
|
|
15
15
|
@path
|
16
16
|
end
|
17
17
|
|
18
|
+
def encoded_io
|
19
|
+
@encoded_io ||= if ::RUBY_VERSION >= '1.9'
|
20
|
+
::File.open path, 'rb', :internal_encoding => t.properties.internal_encoding, :external_encoding => t.properties.external_encoding
|
21
|
+
else
|
22
|
+
::File.open path, 'rb'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
18
26
|
def delete
|
27
|
+
if @encoded_io.respond_to?(:closed?) and !@encoded_io.closed?
|
28
|
+
@encoded_io.close
|
29
|
+
end
|
19
30
|
::FileUtils.rm_rf staging_dir_path
|
31
|
+
@encoded_io = nil
|
20
32
|
@path = nil
|
21
33
|
@staging_dir_path = nil
|
22
34
|
end
|
@@ -3,8 +3,15 @@ class RemoteTable
|
|
3
3
|
# Represents the properties of a RemoteTable, whether they are explicitly set by the user or inferred automatically.
|
4
4
|
class Properties
|
5
5
|
attr_reader :t
|
6
|
+
attr_reader :current_options
|
7
|
+
|
6
8
|
def initialize(t)
|
7
9
|
@t = t
|
10
|
+
@current_options = t.options.dup
|
11
|
+
end
|
12
|
+
|
13
|
+
def update(options)
|
14
|
+
current_options.update options
|
8
15
|
end
|
9
16
|
|
10
17
|
# The parsed URI of the file to get.
|
@@ -22,19 +29,19 @@ class RemoteTable
|
|
22
29
|
# * call each
|
23
30
|
# Defaults to false.
|
24
31
|
def streaming
|
25
|
-
|
32
|
+
current_options['streaming'] || false
|
26
33
|
end
|
27
34
|
|
28
35
|
# Defaults to true.
|
29
36
|
def warn_on_multiple_downloads
|
30
|
-
|
37
|
+
current_options['warn_on_multiple_downloads'] != false
|
31
38
|
end
|
32
39
|
|
33
40
|
# The headers specified by the user
|
34
41
|
#
|
35
42
|
# Default: :first_row
|
36
43
|
def headers
|
37
|
-
|
44
|
+
current_options['headers'].nil? ? :first_row : current_options['headers']
|
38
45
|
end
|
39
46
|
|
40
47
|
def use_first_row_as_header?
|
@@ -49,60 +56,65 @@ class RemoteTable
|
|
49
56
|
#
|
50
57
|
# Default: 0
|
51
58
|
def sheet
|
52
|
-
|
59
|
+
current_options['sheet'] || 0
|
53
60
|
end
|
54
61
|
|
55
62
|
# Whether to keep blank rows
|
56
63
|
#
|
57
64
|
# Default: false
|
58
65
|
def keep_blank_rows
|
59
|
-
|
66
|
+
current_options['keep_blank_rows'] || false
|
60
67
|
end
|
61
68
|
|
62
69
|
# Form data to send in with the download request
|
63
70
|
def form_data
|
64
|
-
|
71
|
+
current_options['form_data']
|
65
72
|
end
|
66
73
|
|
67
74
|
# How many rows to skip
|
68
75
|
#
|
69
76
|
# Default: 0
|
70
77
|
def skip
|
71
|
-
|
78
|
+
current_options['skip'].to_i
|
72
79
|
end
|
73
80
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
81
|
+
def internal_encoding
|
82
|
+
(current_options['encoding'] || 'UTF-8').upcase
|
83
|
+
end
|
84
|
+
|
85
|
+
def external_encoding
|
86
|
+
'UTF-8'
|
87
|
+
end
|
88
|
+
|
89
|
+
def external_encoding_iconv
|
90
|
+
'UTF-8//TRANSLIT'
|
79
91
|
end
|
80
92
|
|
81
93
|
# The delimiter
|
82
94
|
#
|
83
95
|
# Default: ","
|
84
96
|
def delimiter
|
85
|
-
|
97
|
+
current_options['delimiter'] || ','
|
86
98
|
end
|
87
99
|
|
88
100
|
# The XPath used to find rows
|
89
101
|
def row_xpath
|
90
|
-
|
102
|
+
current_options['row_xpath']
|
91
103
|
end
|
92
104
|
|
93
105
|
# The XPath used to find columns
|
94
106
|
def column_xpath
|
95
|
-
|
107
|
+
current_options['column_xpath']
|
96
108
|
end
|
97
109
|
|
98
110
|
# The CSS selector used to find rows
|
99
111
|
def row_css
|
100
|
-
|
112
|
+
current_options['row_css']
|
101
113
|
end
|
102
114
|
|
103
115
|
# The CSS selector used to find columns
|
104
116
|
def column_css
|
105
|
-
|
117
|
+
current_options['column_css']
|
106
118
|
end
|
107
119
|
|
108
120
|
# The compression type.
|
@@ -111,8 +123,8 @@ class RemoteTable
|
|
111
123
|
#
|
112
124
|
# Can be specified as: "gz", "zip", "bz2", "exe" (treated as "zip")
|
113
125
|
def compression
|
114
|
-
clue = if
|
115
|
-
|
126
|
+
clue = if current_options['compression']
|
127
|
+
current_options['compression'].to_s
|
116
128
|
else
|
117
129
|
::File.extname uri.path
|
118
130
|
end
|
@@ -134,8 +146,8 @@ class RemoteTable
|
|
134
146
|
#
|
135
147
|
# Can be specified as: "tar"
|
136
148
|
def packing
|
137
|
-
clue = if
|
138
|
-
|
149
|
+
clue = if current_options['packing']
|
150
|
+
current_options['packing'].to_s
|
139
151
|
else
|
140
152
|
::File.extname(uri.path.sub(/\.#{compression}\z/, ''))
|
141
153
|
end
|
@@ -150,7 +162,7 @@ class RemoteTable
|
|
150
162
|
# Example:
|
151
163
|
# RemoteTable.new 'http://www.fueleconomy.gov/FEG/epadata/08data.zip', 'glob' => '/*.csv'
|
152
164
|
def glob
|
153
|
-
|
165
|
+
current_options['glob']
|
154
166
|
end
|
155
167
|
|
156
168
|
# The filename, which can be used to pick a file out of an archive.
|
@@ -158,17 +170,17 @@ class RemoteTable
|
|
158
170
|
# Example:
|
159
171
|
# RemoteTable.new 'http://www.fueleconomy.gov/FEG/epadata/08data.zip', 'filename' => '2008_FE_guide_ALL_rel_dates_-no sales-for DOE-5-1-08.csv'
|
160
172
|
def filename
|
161
|
-
|
173
|
+
current_options['filename']
|
162
174
|
end
|
163
175
|
|
164
176
|
# Cut columns up to this character
|
165
177
|
def cut
|
166
|
-
|
178
|
+
current_options['cut']
|
167
179
|
end
|
168
180
|
|
169
181
|
# Crop rows after this line
|
170
182
|
def crop
|
171
|
-
|
183
|
+
current_options['crop']
|
172
184
|
end
|
173
185
|
|
174
186
|
# The fixed-width schema, given as an array
|
@@ -183,31 +195,31 @@ class RemoteTable
|
|
183
195
|
# [ 'spacer', 12 ],
|
184
196
|
# [ 'header6', 10, { :type => :string } ]])
|
185
197
|
def schema
|
186
|
-
|
198
|
+
current_options['schema']
|
187
199
|
end
|
188
200
|
|
189
|
-
# The name of the fixed-width schema according to
|
201
|
+
# The name of the fixed-width schema according to FixedWidth
|
190
202
|
def schema_name
|
191
|
-
|
203
|
+
current_options['schema_name']
|
192
204
|
end
|
193
205
|
|
194
206
|
# A proc to call to decide whether to return a row.
|
195
207
|
def select
|
196
|
-
|
208
|
+
current_options['select']
|
197
209
|
end
|
198
210
|
|
199
211
|
# A proc to call to decide whether to return a row.
|
200
212
|
def reject
|
201
|
-
|
213
|
+
current_options['reject']
|
202
214
|
end
|
203
215
|
|
204
216
|
# A hash of options to create a new Errata instance (see the Errata gem at http://github.com/seamusabshere/errata) to be used on every row.
|
205
217
|
def errata
|
206
|
-
return unless
|
207
|
-
@errata ||= if
|
208
|
-
::Errata.new
|
218
|
+
return unless current_options.has_key? 'errata'
|
219
|
+
@errata ||= if current_options['errata'].is_a? ::Hash
|
220
|
+
::Errata.new current_options['errata']
|
209
221
|
else
|
210
|
-
|
222
|
+
current_options['errata']
|
211
223
|
end
|
212
224
|
end
|
213
225
|
|
@@ -220,8 +232,8 @@ class RemoteTable
|
|
220
232
|
# Can be specified as: "xlsx", "xls", "csv", "ods", "fixed_width", "html"
|
221
233
|
def format
|
222
234
|
return Format::Delimited if uri.host == 'spreadsheets.google.com'
|
223
|
-
clue = if
|
224
|
-
|
235
|
+
clue = if current_options['format']
|
236
|
+
current_options['format'].to_s
|
225
237
|
else
|
226
238
|
::File.extname t.local_file.path
|
227
239
|
end
|
data/lib/remote_table/version.rb
CHANGED
data/remote_table.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.add_dependency 'activesupport', '>=2.3.4'
|
23
23
|
s.add_dependency 'roo', '~>1.9'
|
24
|
-
s.add_dependency '
|
24
|
+
s.add_dependency 'fixed_width-multibyte' # TODO replace with fixed_width once timon gets off vacation
|
25
25
|
s.add_dependency 'i18n' # activesupport?
|
26
26
|
s.add_dependency 'builder' # roo?
|
27
27
|
s.add_dependency 'zip' # roo
|
@@ -31,9 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_dependency 'escape', '>=0.0.4'
|
32
32
|
s.add_dependency 'posix-spawn'
|
33
33
|
s.add_dependency 'ensure-encoding'
|
34
|
-
|
35
|
-
s.add_dependency 'fastercsv', '>=1.5.0'
|
36
|
-
end
|
34
|
+
s.add_dependency 'fastercsv', '>=1.5.0'
|
37
35
|
|
38
36
|
s.add_development_dependency 'errata', '>=0.2.0'
|
39
37
|
s.add_development_dependency 'test-unit'
|
data/test/helper.rb
CHANGED
@@ -4,11 +4,26 @@ Bundler.setup
|
|
4
4
|
require 'test/unit'
|
5
5
|
require 'shoulda'
|
6
6
|
require 'ruby-debug'
|
7
|
-
require 'tempfile'
|
8
7
|
|
9
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
10
9
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
11
10
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'remote_table'))
|
12
11
|
|
13
12
|
class Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
if RUBY_VERSION >= '1.9'
|
15
|
+
@old_default_internal = Encoding.default_internal
|
16
|
+
@old_default_external = Encoding.default_external
|
17
|
+
# totally random choices here
|
18
|
+
Encoding.default_internal = 'EUC-JP'
|
19
|
+
Encoding.default_external = 'Shift_JIS'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def teardown
|
24
|
+
if RUBY_VERSION >= '1.9'
|
25
|
+
Encoding.default_internal = @old_default_internal
|
26
|
+
Encoding.default_external = @old_default_external
|
27
|
+
end
|
28
|
+
end
|
14
29
|
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/test_old_syntax.rb
CHANGED
@@ -16,7 +16,7 @@ $test2_rows.freeze
|
|
16
16
|
class TestOldSyntax < Test::Unit::TestCase
|
17
17
|
should "open an XLSX like an array (numbered columns)" do
|
18
18
|
t = RemoteTable.new(:url => 'www.customerreferenceprogram.org/uploads/CRP_RFP_template.xlsx', :headers => false)
|
19
|
-
assert_equal "
|
19
|
+
assert_equal "Software-As-A-Service", t.rows[5][0]
|
20
20
|
end
|
21
21
|
|
22
22
|
should "open an XLSX with custom headers" do
|
data/test/test_old_transform.rb
CHANGED
@@ -1,36 +1,31 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class NaturalGasParser
|
4
4
|
def initialize(options = {})
|
5
5
|
# nothing
|
6
6
|
end
|
7
|
-
def add_hints!(bus)
|
8
|
-
bus[:sheet] = 'Data 1'
|
9
|
-
bus[:skip] = 2
|
10
|
-
bus[:select] = lambda { |row| row['year'] > 1989 }
|
11
|
-
end
|
12
7
|
def apply(row)
|
13
8
|
virtual_rows = []
|
14
|
-
row.keys.grep(
|
15
|
-
|
16
|
-
next if (
|
17
|
-
if
|
18
|
-
|
19
|
-
|
20
|
-
/\(PADD (.*)\)/.match(first_part)
|
21
|
-
padd_part = $1
|
22
|
-
next if padd_part == '1' # skip PADD 1 because we always prefer subdistricts
|
23
|
-
locatable = "#{padd_part} (PetroleumAdministrationForDefenseDistrict)"
|
9
|
+
row.keys.grep(/\A(.*) Natural Gas/) do |location_column_name|
|
10
|
+
match_1 = $1
|
11
|
+
next if (price = row[location_column_name]).blank? or (date = row['Date']).blank?
|
12
|
+
if match_1 == 'U.S.'
|
13
|
+
locatable_id = 'US'
|
14
|
+
locatable_type = 'Country'
|
24
15
|
else
|
25
|
-
|
16
|
+
locatable_id = match_1 # name
|
17
|
+
locatable_type = 'State'
|
26
18
|
end
|
27
19
|
date = Time.parse(date)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
20
|
+
new_row = ActiveSupport::OrderedHash.new
|
21
|
+
new_row['locatable_id'] = locatable_id
|
22
|
+
new_row['locatable_type'] = locatable_type
|
23
|
+
new_row['price'] = price
|
24
|
+
new_row['year'] = date.year
|
25
|
+
new_row['month'] = date.month
|
26
|
+
row_hash = RemoteTable::Transform.row_hash new_row
|
27
|
+
new_row['row_hash'] = row_hash
|
28
|
+
virtual_rows << new_row
|
34
29
|
end
|
35
30
|
virtual_rows
|
36
31
|
end
|
@@ -38,12 +33,12 @@ end
|
|
38
33
|
|
39
34
|
class TestOldTransform < Test::Unit::TestCase
|
40
35
|
should "open an XLS with a parser" do
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
36
|
+
t = RemoteTable.new(:url => 'http://tonto.eia.doe.gov/dnav/ng/xls/ng_pri_sum_a_EPG0_FWA_DMcf_a.xls',
|
37
|
+
:sheet => 'Data 1',
|
38
|
+
:skip => 2,
|
39
|
+
:select => lambda { |row| row['year'].to_i > 1989 },
|
40
|
+
:transform => { :class => NaturalGasParser })
|
41
|
+
assert_equal 'Country', t[0]['locatable_type']
|
42
|
+
assert_equal 'US', t[0]['locatable_id']
|
48
43
|
end
|
49
|
-
end
|
44
|
+
end
|
data/test/test_remote_table.rb
CHANGED
@@ -63,12 +63,12 @@ class TestRemoteTable < Test::Unit::TestCase
|
|
63
63
|
|
64
64
|
# fixes ArgumentError: invalid byte sequence in UTF-8
|
65
65
|
should %{safely strip soft hyphens and read windows-1252 html} do
|
66
|
-
t = RemoteTable.new :url => "http://www.faa.gov/air_traffic/publications/atpubs/CNT/5-2-A.htm", :row_xpath => '//table/tr[2]/td/table/tr', :column_xpath => 'td'
|
66
|
+
t = RemoteTable.new :url => "http://www.faa.gov/air_traffic/publications/atpubs/CNT/5-2-A.htm", :row_xpath => '//table/tr[2]/td/table/tr', :column_xpath => 'td', :encoding => 'windows-1252'
|
67
67
|
assert t.rows.detect { |row| row['Model'] == 'A300B4600' }
|
68
68
|
end
|
69
69
|
|
70
70
|
should %{transliterate characters from ISO-8859-1} do
|
71
|
-
t = RemoteTable.new :url => 'http://static.brighterplanet.com/science/data/consumables/pets/breed_genders.csv'
|
71
|
+
t = RemoteTable.new :url => 'http://static.brighterplanet.com/science/data/consumables/pets/breed_genders.csv', :encoding => 'ISO-8859-1'
|
72
72
|
assert t.rows.detect { |row| row['name'] == 'Briquet Griffon Vendéen' }
|
73
73
|
end
|
74
74
|
|
@@ -86,15 +86,42 @@ class TestRemoteTable < Test::Unit::TestCase
|
|
86
86
|
assert(time1 != time2)
|
87
87
|
end
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
89
|
+
{
|
90
|
+
# IMPOSSIBLE "../support/list-en1-semic-3.office-2011-for-mac-sp1-excel-95.binary.xls" => {:format=>"xls", :encoding=>"binary"},
|
91
|
+
"../support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xlsx" => {:format=>"xlsx"},
|
92
|
+
"../support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xls" => {:format=>"xls"},
|
93
|
+
"../support/list-en1-semic-3.neooffice.binary.ods" => {:format=>"ods"},
|
94
|
+
"../support/list-en1-semic-3.neooffice.iso-8859-1.fixed_width-64" => {:format=>"fixed_width", :encoding=>"iso-8859-1", :schema => [['name', 63, { :type => :string }], ['iso_3166', 2, { :type => :string }]]},
|
95
|
+
"../support/list-en1-semic-3.neooffice.utf-8.fixed_width-62" => {:format=>"fixed_width", :schema => [['name', 61, { :type => :string }], ['iso_3166', 2, { :type => :string }]]},
|
96
|
+
# TODO "../support/list-en1-semic-3.office-2011-for-mac-sp1.utf-8.html" => {:format=>"html" },
|
97
|
+
# TODO "../support/list-en1-semic-3.office-2011-for-mac-sp1.iso-8859-1.html" => {:format=>"html", :encoding=>"iso-8859-1"},
|
98
|
+
# TODO "../support/list-en1-semic-3.neooffice.utf-8.html" => {:format=>"html" },
|
99
|
+
"../support/list-en1-semic-3.neooffice.utf-8.xml" => {:format=>"xml", :row_css=>'Row', :column_css => 'Data', :select => lambda { |row| row[1].to_s =~ /[A-Z]{2}/ }},
|
100
|
+
"../support/list-en1-semic-3.neooffice.iso-8859-1.csv" => {:format=>"csv", :encoding=>"iso-8859-1", :delimiter => ';'},
|
101
|
+
"../support/list-en1-semic-3.original.iso-8859-1.csv" => {:format=>"csv", :encoding=>"iso-8859-1", :delimiter => ';'},
|
102
|
+
"../support/list-en1-semic-3.office-2011-for-mac-sp1.mac.csv-comma" => {:format=>"csv", :encoding=>"MACROMAN"}, # comma because no option in excel
|
103
|
+
"../support/list-en1-semic-3.neooffice.utf-8.csv" => {:format=>"csv", :delimiter => ';'}
|
104
|
+
}.each do |k, v|
|
105
|
+
should %{open #{k} with encoding #{v[:encoding] || 'default'}} do
|
106
|
+
options = v.merge(:headers => false, :skip => 2)
|
107
|
+
t = RemoteTable.new "file://#{File.expand_path(k, __FILE__)}", options
|
108
|
+
a = %{ÅLAND ISLANDS}
|
109
|
+
b = (t[1].is_a?(::Array) ? t[1][0] : t[1]['name'])
|
110
|
+
if RUBY_VERSION >= '1.9'
|
111
|
+
assert_equal 'UTF-8', a.encoding.to_s
|
112
|
+
assert_equal 'UTF-8', b.encoding.to_s
|
113
|
+
end
|
114
|
+
assert_equal a, b
|
93
115
|
end
|
94
116
|
end
|
95
117
|
|
118
|
+
should %{recode as UTF-8 even ISO-8859-1 (or any other encoding)} do
|
119
|
+
t = RemoteTable.new 'http://www.iso.org/iso/list-en1-semic-3.txt', :skip => 2, :headers => false, :delimiter => ';', :encoding => 'ISO-8859-1'
|
120
|
+
assert_equal %{ÅLAND ISLANDS}, t[1][0]
|
121
|
+
end
|
122
|
+
|
96
123
|
should %{parse a big CSV that is not UTF-8} do
|
97
|
-
t = RemoteTable.new 'https://openflights.svn.sourceforge.net/svnroot/openflights/openflights/data/airports.dat', :headers => false
|
124
|
+
t = RemoteTable.new 'https://openflights.svn.sourceforge.net/svnroot/openflights/openflights/data/airports.dat', :headers => false#, :encoding => 'UTF-8'
|
98
125
|
assert_equal 'Goroka', t[0][1]
|
99
126
|
end
|
100
127
|
end
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: remote_table
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 27
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 1
|
8
|
-
- 2
|
9
|
-
- 2
|
10
|
-
version: 1.2.2
|
5
|
+
version: 1.2.3
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Seamus Abshere
|
@@ -16,7 +11,8 @@ autorequire:
|
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
13
|
|
19
|
-
date: 2011-05-
|
14
|
+
date: 2011-05-21 00:00:00 -05:00
|
15
|
+
default_executable:
|
20
16
|
dependencies:
|
21
17
|
- !ruby/object:Gem::Dependency
|
22
18
|
name: activesupport
|
@@ -26,11 +22,6 @@ dependencies:
|
|
26
22
|
requirements:
|
27
23
|
- - ">="
|
28
24
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 11
|
30
|
-
segments:
|
31
|
-
- 2
|
32
|
-
- 3
|
33
|
-
- 4
|
34
25
|
version: 2.3.4
|
35
26
|
type: :runtime
|
36
27
|
version_requirements: *id001
|
@@ -42,27 +33,18 @@ dependencies:
|
|
42
33
|
requirements:
|
43
34
|
- - ~>
|
44
35
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 29
|
46
|
-
segments:
|
47
|
-
- 1
|
48
|
-
- 9
|
49
36
|
version: "1.9"
|
50
37
|
type: :runtime
|
51
38
|
version_requirements: *id002
|
52
39
|
- !ruby/object:Gem::Dependency
|
53
|
-
name:
|
40
|
+
name: fixed_width-multibyte
|
54
41
|
prerelease: false
|
55
42
|
requirement: &id003 !ruby/object:Gem::Requirement
|
56
43
|
none: false
|
57
44
|
requirements:
|
58
45
|
- - ">="
|
59
46
|
- !ruby/object:Gem::Version
|
60
|
-
|
61
|
-
segments:
|
62
|
-
- 0
|
63
|
-
- 99
|
64
|
-
- 4
|
65
|
-
version: 0.99.4
|
47
|
+
version: "0"
|
66
48
|
type: :runtime
|
67
49
|
version_requirements: *id003
|
68
50
|
- !ruby/object:Gem::Dependency
|
@@ -73,9 +55,6 @@ dependencies:
|
|
73
55
|
requirements:
|
74
56
|
- - ">="
|
75
57
|
- !ruby/object:Gem::Version
|
76
|
-
hash: 3
|
77
|
-
segments:
|
78
|
-
- 0
|
79
58
|
version: "0"
|
80
59
|
type: :runtime
|
81
60
|
version_requirements: *id004
|
@@ -87,9 +66,6 @@ dependencies:
|
|
87
66
|
requirements:
|
88
67
|
- - ">="
|
89
68
|
- !ruby/object:Gem::Version
|
90
|
-
hash: 3
|
91
|
-
segments:
|
92
|
-
- 0
|
93
69
|
version: "0"
|
94
70
|
type: :runtime
|
95
71
|
version_requirements: *id005
|
@@ -101,9 +77,6 @@ dependencies:
|
|
101
77
|
requirements:
|
102
78
|
- - ">="
|
103
79
|
- !ruby/object:Gem::Version
|
104
|
-
hash: 3
|
105
|
-
segments:
|
106
|
-
- 0
|
107
80
|
version: "0"
|
108
81
|
type: :runtime
|
109
82
|
version_requirements: *id006
|
@@ -115,11 +88,6 @@ dependencies:
|
|
115
88
|
requirements:
|
116
89
|
- - ">="
|
117
90
|
- !ruby/object:Gem::Version
|
118
|
-
hash: 5
|
119
|
-
segments:
|
120
|
-
- 1
|
121
|
-
- 4
|
122
|
-
- 1
|
123
91
|
version: 1.4.1
|
124
92
|
type: :runtime
|
125
93
|
version_requirements: *id007
|
@@ -131,9 +99,6 @@ dependencies:
|
|
131
99
|
requirements:
|
132
100
|
- - ">="
|
133
101
|
- !ruby/object:Gem::Version
|
134
|
-
hash: 3
|
135
|
-
segments:
|
136
|
-
- 0
|
137
102
|
version: "0"
|
138
103
|
type: :runtime
|
139
104
|
version_requirements: *id008
|
@@ -145,9 +110,6 @@ dependencies:
|
|
145
110
|
requirements:
|
146
111
|
- - ">="
|
147
112
|
- !ruby/object:Gem::Version
|
148
|
-
hash: 3
|
149
|
-
segments:
|
150
|
-
- 0
|
151
113
|
version: "0"
|
152
114
|
type: :runtime
|
153
115
|
version_requirements: *id009
|
@@ -159,11 +121,6 @@ dependencies:
|
|
159
121
|
requirements:
|
160
122
|
- - ">="
|
161
123
|
- !ruby/object:Gem::Version
|
162
|
-
hash: 23
|
163
|
-
segments:
|
164
|
-
- 0
|
165
|
-
- 0
|
166
|
-
- 4
|
167
124
|
version: 0.0.4
|
168
125
|
type: :runtime
|
169
126
|
version_requirements: *id010
|
@@ -175,9 +132,6 @@ dependencies:
|
|
175
132
|
requirements:
|
176
133
|
- - ">="
|
177
134
|
- !ruby/object:Gem::Version
|
178
|
-
hash: 3
|
179
|
-
segments:
|
180
|
-
- 0
|
181
135
|
version: "0"
|
182
136
|
type: :runtime
|
183
137
|
version_requirements: *id011
|
@@ -189,9 +143,6 @@ dependencies:
|
|
189
143
|
requirements:
|
190
144
|
- - ">="
|
191
145
|
- !ruby/object:Gem::Version
|
192
|
-
hash: 3
|
193
|
-
segments:
|
194
|
-
- 0
|
195
146
|
version: "0"
|
196
147
|
type: :runtime
|
197
148
|
version_requirements: *id012
|
@@ -203,11 +154,6 @@ dependencies:
|
|
203
154
|
requirements:
|
204
155
|
- - ">="
|
205
156
|
- !ruby/object:Gem::Version
|
206
|
-
hash: 3
|
207
|
-
segments:
|
208
|
-
- 1
|
209
|
-
- 5
|
210
|
-
- 0
|
211
157
|
version: 1.5.0
|
212
158
|
type: :runtime
|
213
159
|
version_requirements: *id013
|
@@ -219,11 +165,6 @@ dependencies:
|
|
219
165
|
requirements:
|
220
166
|
- - ">="
|
221
167
|
- !ruby/object:Gem::Version
|
222
|
-
hash: 23
|
223
|
-
segments:
|
224
|
-
- 0
|
225
|
-
- 2
|
226
|
-
- 0
|
227
168
|
version: 0.2.0
|
228
169
|
type: :development
|
229
170
|
version_requirements: *id014
|
@@ -235,9 +176,6 @@ dependencies:
|
|
235
176
|
requirements:
|
236
177
|
- - ">="
|
237
178
|
- !ruby/object:Gem::Version
|
238
|
-
hash: 3
|
239
|
-
segments:
|
240
|
-
- 0
|
241
179
|
version: "0"
|
242
180
|
type: :development
|
243
181
|
version_requirements: *id015
|
@@ -249,23 +187,17 @@ dependencies:
|
|
249
187
|
requirements:
|
250
188
|
- - ">="
|
251
189
|
- !ruby/object:Gem::Version
|
252
|
-
hash: 3
|
253
|
-
segments:
|
254
|
-
- 0
|
255
190
|
version: "0"
|
256
191
|
type: :development
|
257
192
|
version_requirements: *id016
|
258
193
|
- !ruby/object:Gem::Dependency
|
259
|
-
name: ruby-
|
194
|
+
name: ruby-debug19
|
260
195
|
prerelease: false
|
261
196
|
requirement: &id017 !ruby/object:Gem::Requirement
|
262
197
|
none: false
|
263
198
|
requirements:
|
264
199
|
- - ">="
|
265
200
|
- !ruby/object:Gem::Version
|
266
|
-
hash: 3
|
267
|
-
segments:
|
268
|
-
- 0
|
269
201
|
version: "0"
|
270
202
|
type: :development
|
271
203
|
version_requirements: *id017
|
@@ -280,6 +212,7 @@ extra_rdoc_files: []
|
|
280
212
|
|
281
213
|
files:
|
282
214
|
- .document
|
215
|
+
- .gitattributes
|
283
216
|
- .gitignore
|
284
217
|
- Gemfile
|
285
218
|
- LICENSE
|
@@ -305,11 +238,26 @@ files:
|
|
305
238
|
- lib/remote_table/version.rb
|
306
239
|
- remote_table.gemspec
|
307
240
|
- test/helper.rb
|
241
|
+
- test/support/list-en1-semic-3.neooffice.binary.ods
|
242
|
+
- test/support/list-en1-semic-3.neooffice.iso-8859-1.csv
|
243
|
+
- test/support/list-en1-semic-3.neooffice.iso-8859-1.fixed_width-64
|
244
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.csv
|
245
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.fixed_width-62
|
246
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.html
|
247
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.xml
|
248
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1-excel-95.binary.xls
|
249
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xls
|
250
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xlsx
|
251
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.iso-8859-1.html
|
252
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.mac.csv-comma
|
253
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.utf-8.html
|
254
|
+
- test/support/list-en1-semic-3.original.iso-8859-1.csv
|
308
255
|
- test/test_big.rb
|
309
256
|
- test/test_errata.rb
|
310
257
|
- test/test_old_syntax.rb
|
311
258
|
- test/test_old_transform.rb
|
312
259
|
- test/test_remote_table.rb
|
260
|
+
has_rdoc: true
|
313
261
|
homepage: https://github.com/seamusabshere/remote_table
|
314
262
|
licenses: []
|
315
263
|
|
@@ -323,28 +271,36 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
323
271
|
requirements:
|
324
272
|
- - ">="
|
325
273
|
- !ruby/object:Gem::Version
|
326
|
-
hash: 3
|
327
|
-
segments:
|
328
|
-
- 0
|
329
274
|
version: "0"
|
330
275
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
331
276
|
none: false
|
332
277
|
requirements:
|
333
278
|
- - ">="
|
334
279
|
- !ruby/object:Gem::Version
|
335
|
-
hash: 3
|
336
|
-
segments:
|
337
|
-
- 0
|
338
280
|
version: "0"
|
339
281
|
requirements: []
|
340
282
|
|
341
283
|
rubyforge_project: remotetable
|
342
|
-
rubygems_version: 1.
|
284
|
+
rubygems_version: 1.6.2
|
343
285
|
signing_key:
|
344
286
|
specification_version: 3
|
345
287
|
summary: Open local or remote XLSX, XLS, ODS, CSV and fixed-width files.
|
346
288
|
test_files:
|
347
289
|
- test/helper.rb
|
290
|
+
- test/support/list-en1-semic-3.neooffice.binary.ods
|
291
|
+
- test/support/list-en1-semic-3.neooffice.iso-8859-1.csv
|
292
|
+
- test/support/list-en1-semic-3.neooffice.iso-8859-1.fixed_width-64
|
293
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.csv
|
294
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.fixed_width-62
|
295
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.html
|
296
|
+
- test/support/list-en1-semic-3.neooffice.utf-8.xml
|
297
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1-excel-95.binary.xls
|
298
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xls
|
299
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.binary.xlsx
|
300
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.iso-8859-1.html
|
301
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.mac.csv-comma
|
302
|
+
- test/support/list-en1-semic-3.office-2011-for-mac-sp1.utf-8.html
|
303
|
+
- test/support/list-en1-semic-3.original.iso-8859-1.csv
|
348
304
|
- test/test_big.rb
|
349
305
|
- test/test_errata.rb
|
350
306
|
- test/test_old_syntax.rb
|