gribr 0.2.0 → 0.3.0
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/Rakefile +2 -2
- data/VERSION +1 -1
- data/bin/probe-wukong +7 -0
- data/lib/gribr/degrib.rb +2 -1
- data/lib/gribr/degrib/file.rb +8 -2
- data/lib/gribr/degrib/inventory_record.rb +53 -17
- data/lib/gribr/degrib/message.rb +34 -0
- data/lib/gribr/inventory.rb +25 -14
- data/lib/gribr/wgrib/inventory_record.rb +18 -4
- data/spec/lib/gribr/degrib/file_spec.rb +12 -1
- data/spec/lib/gribr/degrib/inventory_record_spec.rb +4 -0
- data/spec/lib/gribr/degrib/inventory_spec.rb +9 -2
- data/spec/lib/gribr/degrib/message_spec.rb +31 -0
- data/spec/lib/gribr/inventory_spec.rb +8 -4
- data/spec/lib/gribr/wgrib/inventory_record_spec.rb +19 -3
- data/spec/lib/gribr/wgrib/inventory_spec.rb +6 -0
- metadata +10 -7
data/Rakefile
CHANGED
@@ -5,8 +5,8 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "gribr"
|
8
|
-
gem.summary = %Q{
|
9
|
-
gem.description = %Q{Ruby wrapper to read gridded binary (GRIB) files
|
8
|
+
gem.summary = %Q{Read gridded binary (GRIB) files with ruby.}
|
9
|
+
gem.description = %Q{Ruby wrapper to read gridded binary (GRIB) files using degrib.}
|
10
10
|
gem.email = "roman.scherer@burningswell.com"
|
11
11
|
gem.homepage = "http://github.com/r0man/gribr"
|
12
12
|
gem.authors = ["Roman Scherer"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/bin/probe-wukong
ADDED
data/lib/gribr/degrib.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'gribr/executeable'
|
2
1
|
require 'gribr/degrib/cube'
|
3
2
|
require 'gribr/degrib/file'
|
4
3
|
require 'gribr/degrib/index'
|
5
4
|
require 'gribr/degrib/inventory'
|
6
5
|
require 'gribr/degrib/inventory_record'
|
6
|
+
require 'gribr/degrib/message'
|
7
7
|
require 'gribr/degrib/probe_record'
|
8
|
+
require 'gribr/executeable'
|
8
9
|
|
9
10
|
module Gribr
|
10
11
|
|
data/lib/gribr/degrib/file.rb
CHANGED
@@ -35,7 +35,13 @@ module Gribr
|
|
35
35
|
@inventory ||= Inventory.file(self)
|
36
36
|
end
|
37
37
|
|
38
|
-
#
|
38
|
+
# Returns the messages in the grib file.
|
39
|
+
def messages
|
40
|
+
@messages || inventory.records.map { |record| Message.new(self, record) }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Probe the grib file at the given location and return/yield the
|
44
|
+
# records.
|
39
45
|
def probe(latitude, longitude, options = { }, &block)
|
40
46
|
probe_one(latitude, longitude, options, &block)
|
41
47
|
end
|
@@ -69,7 +75,7 @@ module Gribr
|
|
69
75
|
end
|
70
76
|
|
71
77
|
def validate!
|
72
|
-
raise "Sorry, not a grib file: #{path}" unless
|
78
|
+
raise "Sorry, not a grib file: #{path}" unless ::File.gribfile?(self); ensure; rewind
|
73
79
|
end
|
74
80
|
|
75
81
|
end
|
@@ -13,30 +13,66 @@ module Gribr
|
|
13
13
|
REGEXP_LEVEL = Regexp.new('([^,]+)').freeze
|
14
14
|
REGEXP_TIMESTAMP = Regexp.new('((\d{2})/(\d{2})/(\d{4})\s+(\d{2}):(\d{2}))').freeze
|
15
15
|
|
16
|
+
TIME_FORMAT = "%m/%d/%Y %H:%M".freeze
|
17
|
+
|
16
18
|
def end_position_of_previous
|
17
19
|
start_position - 1 if number > 1
|
18
20
|
end
|
19
21
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
record.unit = match_data[8]
|
30
|
-
record.level = match_data[9]
|
31
|
-
record.reference_time = Time.utc(match_data[13].to_i, match_data[11].to_i, match_data[12].to_i, match_data[14].to_i, match_data[15].to_i)
|
32
|
-
record.valid_time = Time.utc(match_data[19].to_i, match_data[17].to_i, match_data[18].to_i, match_data[20].to_i, match_data[21].to_i)
|
33
|
-
record
|
34
|
-
end
|
22
|
+
def to_s
|
23
|
+
[ formatted_number, start_position, version, formatted_element, level, formatted_reference_time, formatted_valid_time, formatted_projection ].join(", ")
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def formatted_element
|
29
|
+
"#{element}=\"#{description}\""
|
30
|
+
end
|
35
31
|
|
32
|
+
def formatted_number
|
33
|
+
sprintf("%.1f", number)
|
36
34
|
end
|
37
35
|
|
38
|
-
def
|
39
|
-
|
36
|
+
def formatted_time(time)
|
37
|
+
time.strftime(TIME_FORMAT)
|
38
|
+
end
|
39
|
+
|
40
|
+
def formatted_projection
|
41
|
+
sprintf("%.2f", (valid_time - reference_time) / 60 / 60)
|
42
|
+
end
|
43
|
+
|
44
|
+
def formatted_reference_time
|
45
|
+
formatted_time(reference_time)
|
46
|
+
end
|
47
|
+
|
48
|
+
def formatted_valid_time
|
49
|
+
formatted_time(valid_time)
|
50
|
+
end
|
51
|
+
|
52
|
+
class << self
|
53
|
+
|
54
|
+
def build(match_data)
|
55
|
+
|
56
|
+
if match_data
|
57
|
+
record = new
|
58
|
+
record.number = match_data[1].to_i
|
59
|
+
record.start_position = match_data[3].to_i
|
60
|
+
record.version = match_data[4].to_i
|
61
|
+
record.element = match_data[6]
|
62
|
+
record.description = match_data[7]
|
63
|
+
record.unit = match_data[8]
|
64
|
+
record.level = match_data[9]
|
65
|
+
record.reference_time = Time.utc(match_data[13].to_i, match_data[11].to_i, match_data[12].to_i, match_data[14].to_i, match_data[15].to_i)
|
66
|
+
record.valid_time = Time.utc(match_data[19].to_i, match_data[17].to_i, match_data[18].to_i, match_data[20].to_i, match_data[21].to_i)
|
67
|
+
record
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def regexp
|
73
|
+
@regexp ||= Regexp.new([REGEXP_FLOAT, REGEXP_INTEGER, REGEXP_INTEGER, REGEXP_ELEMENT, REGEXP_LEVEL, REGEXP_TIMESTAMP, REGEXP_TIMESTAMP].join('\s*,\s*')).freeze
|
74
|
+
end
|
75
|
+
|
40
76
|
end
|
41
77
|
|
42
78
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Gribr
|
2
|
+
module Degrib
|
3
|
+
|
4
|
+
class Message
|
5
|
+
|
6
|
+
attr_reader :file, :inventory_record
|
7
|
+
|
8
|
+
def initialize(file, inventory_record)
|
9
|
+
@file, @inventory_record = file, inventory_record
|
10
|
+
end
|
11
|
+
|
12
|
+
# Probe the grib message at the given location and return/yield
|
13
|
+
# the records.
|
14
|
+
def probe(latitude, longitude, options = { }, &block)
|
15
|
+
|
16
|
+
records = Array.new
|
17
|
+
|
18
|
+
file.probe(latitude, longitude, options) do |record|
|
19
|
+
|
20
|
+
# if record.element.downcase == inventory_record.element.downcase
|
21
|
+
yield(record) if block_given?
|
22
|
+
records << record
|
23
|
+
# end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
records
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/gribr/inventory.rb
CHANGED
@@ -1,31 +1,38 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
1
3
|
module Gribr
|
2
4
|
|
3
5
|
class Inventory
|
4
6
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
|
7
|
+
def initialize(records = Array.new)
|
8
|
+
@records = Hash.new
|
9
|
+
records.each { |record| add_record(record) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_record(record)
|
13
|
+
set_end_position_of_previous(record)
|
14
|
+
@records[record.number] = record
|
15
|
+
record
|
8
16
|
end
|
9
17
|
|
10
|
-
def
|
11
|
-
|
12
|
-
@messages[message.number] = message
|
18
|
+
def records
|
19
|
+
@records.values.sort_by(&:number)
|
13
20
|
end
|
14
21
|
|
15
|
-
def
|
16
|
-
|
22
|
+
def to_s
|
23
|
+
records.join("\n")
|
17
24
|
end
|
18
25
|
|
19
26
|
protected
|
20
27
|
|
21
|
-
def set_end_position_of_previous(
|
22
|
-
@
|
28
|
+
def set_end_position_of_previous(record)
|
29
|
+
@records[record.number - 1].end_position = record.end_position_of_previous if @records[record.number - 1]
|
23
30
|
end
|
24
31
|
|
25
32
|
class << self
|
26
33
|
|
27
34
|
def file(file)
|
28
|
-
|
35
|
+
::File.gribfile?(file) ? grib_file(file) : inventory_file(file)
|
29
36
|
end
|
30
37
|
|
31
38
|
def io(io)
|
@@ -35,9 +42,9 @@ module Gribr
|
|
35
42
|
io.each_with_index do |line, index|
|
36
43
|
|
37
44
|
if index > 0
|
38
|
-
|
39
|
-
inventory.
|
40
|
-
yield(
|
45
|
+
record = parse_record(line)
|
46
|
+
inventory.add_record(record)
|
47
|
+
yield(record) if block_given?
|
41
48
|
end
|
42
49
|
|
43
50
|
end
|
@@ -46,6 +53,10 @@ module Gribr
|
|
46
53
|
|
47
54
|
end
|
48
55
|
|
56
|
+
def url(url)
|
57
|
+
open(url) { |io| io(io) }
|
58
|
+
end
|
59
|
+
|
49
60
|
protected
|
50
61
|
|
51
62
|
def grib_file(file)
|
@@ -3,7 +3,7 @@ require 'gribr/utils'
|
|
3
3
|
module Gribr
|
4
4
|
module Wgrib
|
5
5
|
|
6
|
-
class InventoryRecord < Struct.new(:element, :end_position, :number, :start_position, :reference_time, :valid_time)
|
6
|
+
class InventoryRecord < Struct.new(:average, :element, :end_position, :level, :number, :start_position, :projection, :reference_time, :valid_time)
|
7
7
|
|
8
8
|
include Gribr::RegexpParser
|
9
9
|
|
@@ -16,6 +16,17 @@ module Gribr
|
|
16
16
|
class ShortInventoryRecord < InventoryRecord
|
17
17
|
|
18
18
|
REGEX_TIMESTAMP = Regexp.new("(d=(\\d{2,4})(\\d{2})(\\d{2})(\\d{2}))").freeze
|
19
|
+
TIME_FORMAT = "%Y%m%d%H".freeze
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
[number, start_position, formatted_reference_time, element, level, projection, average].join(":")
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def formatted_reference_time
|
28
|
+
"d=" + reference_time.strftime(TIME_FORMAT)
|
29
|
+
end
|
19
30
|
|
20
31
|
def self.build(match_data)
|
21
32
|
|
@@ -25,13 +36,16 @@ module Gribr
|
|
25
36
|
record.number = match_data[1].to_i
|
26
37
|
record.start_position = match_data[2].to_i
|
27
38
|
record.element = match_data[8]
|
39
|
+
record.level = match_data[9]
|
28
40
|
|
29
41
|
year = (match_data[4].size == 4 ? match_data[4] : Time.now.utc.year.to_s.gsub(/\d{2}$/, match_data[4])).to_i
|
30
|
-
record.
|
42
|
+
record.reference_time = Time.utc(year, match_data[5].to_i, match_data[6].to_i, match_data[7].to_i)
|
31
43
|
|
32
|
-
# Calculte reference time
|
33
44
|
offset = match_data[10].split.first.to_i * 60 * 60
|
34
|
-
record.
|
45
|
+
record.valid_time = record.reference_time + offset
|
46
|
+
|
47
|
+
record.projection = match_data[10]
|
48
|
+
record.average = match_data[11]
|
35
49
|
|
36
50
|
record
|
37
51
|
|
@@ -50,6 +50,14 @@ module Gribr::Degrib
|
|
50
50
|
@file.inventory.should be_kind_of(Inventory)
|
51
51
|
end
|
52
52
|
|
53
|
+
it "should return the messages as an array" do
|
54
|
+
@file.messages.should be_kind_of(Array)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return the messages as an array of Gribr::Degrib::Message objects" do
|
58
|
+
@file.messages.each { |message| message.should be_kind_of(Message) }
|
59
|
+
end
|
60
|
+
|
53
61
|
it "should probe at the given position and return the records in an array" do
|
54
62
|
@file.probe(@latitude, @longitude).should be_kind_of(Array)
|
55
63
|
end
|
@@ -61,9 +69,12 @@ module Gribr::Degrib
|
|
61
69
|
it "should probe at the given position and yield the records" do
|
62
70
|
@file.index!
|
63
71
|
@file.probe(@latitude, @longitude) { |record| record.should be_kind_of(ProbeRecord) }
|
64
|
-
# @file.probe(@latitude, @longitude) { |record| puts record }
|
65
72
|
end
|
66
73
|
|
74
|
+
# it "should probe at the given position and yield the records" do
|
75
|
+
# @file.probe(@latitude, @longitude) { |record| puts record }
|
76
|
+
# end
|
77
|
+
|
67
78
|
end
|
68
79
|
|
69
80
|
end
|
@@ -7,11 +7,18 @@ module Gribr::Degrib
|
|
7
7
|
describe "A degrib inventory" do
|
8
8
|
|
9
9
|
before(:each) do
|
10
|
-
@
|
10
|
+
@gribfilename = File.expand_path(File.dirname(__FILE__) + '/../../../fixtures/wind.grib')
|
11
|
+
@inventory = Inventory.file(@gribfilename)
|
11
12
|
end
|
12
13
|
|
13
14
|
it_should_behave_like "An inventory"
|
14
15
|
|
16
|
+
it "should return the string representation" do
|
17
|
+
expected = (`degrib #{@gribfilename} -I`).split("\n")
|
18
|
+
expected = expected[1..(expected.size - 1)].join("\n")
|
19
|
+
@inventory.to_s.should == expected
|
20
|
+
end
|
21
|
+
|
15
22
|
end
|
16
23
|
|
17
24
|
describe Inventory do
|
@@ -34,7 +41,7 @@ module Gribr::Degrib
|
|
34
41
|
Inventory.file(clazz.new(@gribfile)).should be_kind_of(Inventory)
|
35
42
|
end
|
36
43
|
|
37
|
-
it "should parse the inventory from the
|
44
|
+
it "should parse the inventory from the given inventory file" do
|
38
45
|
Tempfile.open("inventory") do |tempfile|
|
39
46
|
system("degrib #{@gribfile} -I > #{tempfile.path}")
|
40
47
|
Inventory.file(clazz.new(tempfile.path)).should be_kind_of(Inventory)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
2
|
+
|
3
|
+
module Gribr::Degrib
|
4
|
+
|
5
|
+
describe Message do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@latitude, @longitude = 0, 0
|
9
|
+
@filename = File.expand_path(File.dirname(__FILE__) + '/../../../fixtures/wind.grib')
|
10
|
+
@message = Gribr::Degrib::File.new(@filename).messages.first
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be kind of Gribr::Degrib::Message" do
|
14
|
+
@message.should be_kind_of(Message)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should probe the records at the given position and return them in an array" do
|
18
|
+
@message.probe(@latitude, @longitude).should be_kind_of(Array)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should probe the records at the given position and yield them to the given block" do
|
22
|
+
@message.probe(@latitude, @longitude) { |record| record.should be_kind_of(ProbeRecord) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# it "should probe at the given position and yield the records" do
|
26
|
+
# @message.probe(@latitude, @longitude) { |record| puts record }
|
27
|
+
# end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -8,12 +8,16 @@ module Gribr
|
|
8
8
|
@inventory.should be_kind_of(Inventory)
|
9
9
|
end
|
10
10
|
|
11
|
-
it "should return the
|
12
|
-
@inventory.
|
11
|
+
it "should return the records as an array" do
|
12
|
+
@inventory.records.should be_kind_of(Array)
|
13
13
|
end
|
14
14
|
|
15
|
-
it "should return the
|
16
|
-
@inventory.
|
15
|
+
it "should return the records sorted by number" do
|
16
|
+
@inventory.records.each_cons(2) { |cons| cons.first.number.should < cons.last.number }
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should calculate the end position for each record" do
|
20
|
+
@inventory.records.each_cons(2) { |cons| cons.first.end_position.should == cons.last.start_position - 1 }
|
17
21
|
end
|
18
22
|
|
19
23
|
end
|
@@ -26,12 +26,24 @@ module Gribr::Wgrib
|
|
26
26
|
@record.element.should == 'DIRSW'
|
27
27
|
end
|
28
28
|
|
29
|
-
it 'should assign the
|
30
|
-
@record.
|
29
|
+
it 'should assign the level' do
|
30
|
+
@record.level.should == 'sfc'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should assign the projection' do
|
34
|
+
@record.projection.should == '3hr fcst'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should assign the average value' do
|
38
|
+
@record.average.should == 'NAve=0'
|
31
39
|
end
|
32
40
|
|
33
41
|
it 'should assign the reference time' do
|
34
|
-
@record.reference_time.should ==
|
42
|
+
@record.reference_time.should == Time.utc(2009, 11, 4, 0)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should assign the valid time' do
|
46
|
+
@record.valid_time.should == @record.reference_time + (3 * 60 * 60)
|
35
47
|
end
|
36
48
|
|
37
49
|
end
|
@@ -54,6 +66,10 @@ module Gribr::Wgrib
|
|
54
66
|
|
55
67
|
it_should_behave_like "Parsing a short wgrib record"
|
56
68
|
|
69
|
+
it "should return the wgrib string representation" do
|
70
|
+
@record.to_s.should == "22:1057378:d=2009110400:DIRSW:sfc:3hr fcst:NAve=0"
|
71
|
+
end
|
72
|
+
|
57
73
|
end
|
58
74
|
|
59
75
|
end
|
@@ -12,6 +12,12 @@ module Gribr::Wgrib
|
|
12
12
|
|
13
13
|
it_should_behave_like "An inventory"
|
14
14
|
|
15
|
+
it "should create an inventory from an url" do
|
16
|
+
url = "http://nomad5.ncep.noaa.gov/pub/waves/nww3/nww320091104/nww3.t00z.grib.inv"
|
17
|
+
Inventory.should_receive(:open).with(url).and_yield(StringIO.new(""))
|
18
|
+
Inventory.url(url).should be_kind_of(Inventory)
|
19
|
+
end
|
20
|
+
|
15
21
|
end
|
16
22
|
|
17
23
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gribr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Scherer
|
@@ -9,8 +9,8 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
13
|
-
default_executable:
|
12
|
+
date: 2009-11-12 00:00:00 +01:00
|
13
|
+
default_executable: probe-wukong
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: "0"
|
34
34
|
version:
|
35
|
-
description: Ruby wrapper to read gridded binary (GRIB) files
|
35
|
+
description: Ruby wrapper to read gridded binary (GRIB) files using degrib.
|
36
36
|
email: roman.scherer@burningswell.com
|
37
|
-
executables:
|
38
|
-
|
37
|
+
executables:
|
38
|
+
- probe-wukong
|
39
39
|
extensions: []
|
40
40
|
|
41
41
|
extra_rdoc_files:
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- lib/gribr/degrib/index.rb
|
59
59
|
- lib/gribr/degrib/inventory.rb
|
60
60
|
- lib/gribr/degrib/inventory_record.rb
|
61
|
+
- lib/gribr/degrib/message.rb
|
61
62
|
- lib/gribr/degrib/probe_record.rb
|
62
63
|
- lib/gribr/executeable.rb
|
63
64
|
- lib/gribr/inventory.rb
|
@@ -73,6 +74,7 @@ files:
|
|
73
74
|
- spec/lib/gribr/degrib/index_spec.rb
|
74
75
|
- spec/lib/gribr/degrib/inventory_record_spec.rb
|
75
76
|
- spec/lib/gribr/degrib/inventory_spec.rb
|
77
|
+
- spec/lib/gribr/degrib/message_spec.rb
|
76
78
|
- spec/lib/gribr/degrib/probe_record_spec.rb
|
77
79
|
- spec/lib/gribr/degrib_spec.rb
|
78
80
|
- spec/lib/gribr/executeable_spec.rb
|
@@ -108,12 +110,13 @@ rubyforge_project:
|
|
108
110
|
rubygems_version: 1.3.5
|
109
111
|
signing_key:
|
110
112
|
specification_version: 3
|
111
|
-
summary:
|
113
|
+
summary: Read gridded binary (GRIB) files with ruby.
|
112
114
|
test_files:
|
113
115
|
- spec/gribr_spec.rb
|
114
116
|
- spec/lib/gribr/degrib/index_spec.rb
|
115
117
|
- spec/lib/gribr/degrib/cube_spec.rb
|
116
118
|
- spec/lib/gribr/degrib/probe_record_spec.rb
|
119
|
+
- spec/lib/gribr/degrib/message_spec.rb
|
117
120
|
- spec/lib/gribr/degrib/inventory_spec.rb
|
118
121
|
- spec/lib/gribr/degrib/inventory_record_spec.rb
|
119
122
|
- spec/lib/gribr/degrib/file_spec.rb
|