cosm-rb 0.2.00 → 0.2.01
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/lib/cosm-rb/datastream.rb +2 -2
- data/lib/cosm-rb/parsers/csv/datastream_defaults.rb +30 -6
- data/lib/cosm-rb/parsers/csv/feed_defaults.rb +58 -14
- data/lib/cosm-rb/parsers/xml/datapoint_defaults.rb +3 -1
- data/lib/cosm-rb/parsers/xml/datastream_defaults.rb +6 -0
- data/lib/cosm-rb/parsers/xml/helpers.rb +2 -3
- data/lib/cosm-rb/version.rb +1 -1
- data/spec/cosm-rb/datastream_spec.rb +7 -7
- data/spec/cosm-rb/parsers/csv/datastream_defaults_spec.rb +73 -2
- data/spec/cosm-rb/parsers/csv/feed_defaults_spec.rb +121 -0
- data/spec/cosm-rb/parsers/json/datastream_defaults_spec.rb +1 -1
- data/spec/cosm-rb/parsers/xml/datastream_defaults_spec.rb +71 -23
- data/spec/cosm-rb/parsers/xml/feed_defaults_spec.rb +34 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/fully_represent_datastream_matcher.rb +6 -2
- metadata +47 -47
data/lib/cosm-rb/datastream.rb
CHANGED
|
@@ -59,7 +59,7 @@ module Cosm
|
|
|
59
59
|
return pass
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
def initialize(input = {}, format = nil)
|
|
62
|
+
def initialize(input = {}, csv_version = nil, format = nil)
|
|
63
63
|
raise InvalidFormatError, "Unknown format specified, currently we can only parse JSON, XML or CSV." unless [nil,:json,:xml,:csv].include?(format)
|
|
64
64
|
if input.is_a? Hash
|
|
65
65
|
self.attributes = input
|
|
@@ -68,7 +68,7 @@ module Cosm
|
|
|
68
68
|
elsif format == :xml || (format.nil? && input.strip[0...1].to_s == "<")
|
|
69
69
|
self.attributes = from_xml(input)
|
|
70
70
|
else
|
|
71
|
-
self.attributes = from_csv(input)
|
|
71
|
+
self.attributes = from_csv(input, csv_version)
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -10,15 +10,39 @@ module Cosm
|
|
|
10
10
|
# we are running under 1.8.x or 1.9.x
|
|
11
11
|
raise InvalidCSVError, e.message
|
|
12
12
|
end
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
|
|
14
|
+
version = FeedDefaults.detect_version(rows, csv_version)
|
|
15
|
+
|
|
16
|
+
raise InvalidCSVError, "CSV is invalid. Submitted data appears to be empty" if rows.nil?
|
|
17
|
+
|
|
18
|
+
if version == :v1
|
|
19
|
+
raise InvalidCSVError, "CSV is invalid. Can only construct a Cosm::Datastream object from a single row of data" if rows.size > 1
|
|
20
|
+
row = rows.first
|
|
21
|
+
raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value" if row.size > 1
|
|
19
22
|
return { "current_value" => row[0].to_s.strip }
|
|
23
|
+
else
|
|
24
|
+
row_sizes = rows.collect { |row| row.size }.uniq
|
|
25
|
+
raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value, or a timestamp and a value" if row_sizes.max > 2
|
|
26
|
+
|
|
27
|
+
if rows.size == 1
|
|
28
|
+
# capture single lines (normal case)
|
|
29
|
+
row = rows.first
|
|
30
|
+
|
|
31
|
+
if row.size == 2
|
|
32
|
+
return { "updated" => row[0].to_s.strip, "current_value" => row[1].to_s.strip }
|
|
33
|
+
else
|
|
34
|
+
return { "current_value" => row[0].to_s.strip }
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
# capture multiple lines
|
|
38
|
+
raise InvalidCSVError, "CSV is invalid. If multiple values are included, then a timestamp and value must be submitted for every row" if row_sizes.min < 2
|
|
39
|
+
|
|
40
|
+
return { "datapoints" => rows.collect { |row| { "at" => row[0].to_s.strip, "value" => row[1].to_s.strip } } }
|
|
41
|
+
end
|
|
20
42
|
end
|
|
43
|
+
|
|
21
44
|
end
|
|
45
|
+
|
|
22
46
|
end
|
|
23
47
|
end
|
|
24
48
|
end
|
|
@@ -5,6 +5,16 @@ module Cosm
|
|
|
5
5
|
class InvalidCSVError < Cosm::ParserError ; end
|
|
6
6
|
|
|
7
7
|
module FeedDefaults
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def detect_version(rows, version = nil)
|
|
11
|
+
return version if version
|
|
12
|
+
return :v2 if rows.size >= 2
|
|
13
|
+
return :v1 if rows.size == 1 && rows.first.size != 2
|
|
14
|
+
raise UnknownVersionError, "CSV Version could not be detected"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
8
18
|
def from_csv(csv, csv_version = nil)
|
|
9
19
|
begin
|
|
10
20
|
rows = Cosm::CSV.parse(csv.strip)
|
|
@@ -13,17 +23,13 @@ module Cosm
|
|
|
13
23
|
# we are running under 1.8.x or 1.9.x
|
|
14
24
|
raise InvalidCSVError, e.message
|
|
15
25
|
end
|
|
16
|
-
|
|
26
|
+
|
|
27
|
+
version = FeedDefaults.detect_version(rows, csv_version)
|
|
28
|
+
|
|
17
29
|
hash = Hash.new
|
|
30
|
+
|
|
18
31
|
if version == :v2
|
|
19
|
-
|
|
20
|
-
hash["datastreams"] = rows.collect {|row|
|
|
21
|
-
timestamp = {}
|
|
22
|
-
if row.size == 3
|
|
23
|
-
timestamp["updated"] = row[1].strip
|
|
24
|
-
end
|
|
25
|
-
{ "id" => row.first.to_s.strip, "current_value" => row.last.to_s.strip }.merge(timestamp)
|
|
26
|
-
}
|
|
32
|
+
hash["datastreams"] = extract_datastreams(rows)
|
|
27
33
|
elsif version == :v1
|
|
28
34
|
raise InvalidCSVError, "CSV is invalid. Currently we can only accept CSV for your most recent set of values. You have submitted #{rows.size} rows of data." if rows.size > 1
|
|
29
35
|
hash["datastreams"] = []
|
|
@@ -37,11 +43,49 @@ module Cosm
|
|
|
37
43
|
|
|
38
44
|
private
|
|
39
45
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
raise
|
|
46
|
+
def extract_datastreams(rows)
|
|
47
|
+
row_sizes = rows.collect { |row| row.size }.uniq
|
|
48
|
+
row_ids = rows.collect { |row| row.first.to_s.strip }.uniq
|
|
49
|
+
|
|
50
|
+
raise InvalidCSVError, "CSV is invalid. Incorrect number of fields" if row_sizes.max > 3
|
|
51
|
+
|
|
52
|
+
datastream_buckets = {}
|
|
53
|
+
|
|
54
|
+
# iterate through each row bucketing by datastream id
|
|
55
|
+
rows.each do |row|
|
|
56
|
+
# this splits each row into the id first element, and an array containing the rest of the row
|
|
57
|
+
id, *rest = *row
|
|
58
|
+
|
|
59
|
+
# make empty array if it doesn't exist
|
|
60
|
+
datastream_buckets[id.to_s.strip] ||= []
|
|
61
|
+
# add this row to the correct bucketed array
|
|
62
|
+
datastream_buckets[id.to_s.strip] << rest
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
datastreams = []
|
|
66
|
+
|
|
67
|
+
row_ids.each do |datastream_id|
|
|
68
|
+
datastream_data = datastream_buckets[datastream_id]
|
|
69
|
+
|
|
70
|
+
if datastream_data.size == 1
|
|
71
|
+
# single value for this datastream - current normal
|
|
72
|
+
data = datastream_data[0]
|
|
73
|
+
if data.size == 2
|
|
74
|
+
datastreams << { "id" => datastream_id, "updated" => data[0].to_s.strip, "current_value" => data[1].to_s.strip }
|
|
75
|
+
else
|
|
76
|
+
datastreams << { "id" => datastream_id, "current_value" => data[0].to_s.strip }
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
# multiple values for this datastream
|
|
80
|
+
raise InvalidCSVError, "CSV is invalid. If multiple values given they must include a timestamp for all values" if datastream_data.collect { |d| d.size }.min < 2
|
|
81
|
+
|
|
82
|
+
datapoints = datastream_data.collect { |datapoint_data| { "at" => datapoint_data[0].to_s.strip, "value" => datapoint_data[1].to_s.strip } }
|
|
83
|
+
|
|
84
|
+
datastreams << { "id" => datastream_id, "datapoints" => datapoints }
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
return datastreams
|
|
45
89
|
end
|
|
46
90
|
end
|
|
47
91
|
end
|
|
@@ -11,8 +11,10 @@ module Cosm
|
|
|
11
11
|
raise InvalidXMLError, "Missing 'environment' node from base node" if parsed['eeml'].nil? || !parsed['eeml'].key?('environment')
|
|
12
12
|
return {} if parsed['eeml']['environment'].nil?
|
|
13
13
|
datastream = parsed['eeml']['environment']['data']
|
|
14
|
+
raise InvalidXMLError, "Multiple 'data' nodes are not permitted for Datapoint level XML" if datastream.is_a?(Array)
|
|
14
15
|
datapoint = datastream['datapoints']
|
|
15
|
-
|
|
16
|
+
raise InvalidXMLError, "Multiple 'value' nodes are not permitted for Datapoint level XML" if datapoint.is_a?(Array)
|
|
17
|
+
_extract_datapoints(datapoint).first
|
|
16
18
|
rescue MultiXml::ParseError => e
|
|
17
19
|
raise InvalidXMLError, e.message
|
|
18
20
|
end
|
|
@@ -23,6 +23,7 @@ module Cosm
|
|
|
23
23
|
|
|
24
24
|
# As produced by http://cosm.com/api/v2/FEED_ID/datastreams/DATASTREAM_ID.xml
|
|
25
25
|
def transform_v2(xml)
|
|
26
|
+
validate_xml(xml)
|
|
26
27
|
datastream = convert_to_hash(xml['data'])
|
|
27
28
|
_extract_datastream(datastream).merge({
|
|
28
29
|
:feed_id => strip(xml,'id'),
|
|
@@ -32,6 +33,7 @@ module Cosm
|
|
|
32
33
|
|
|
33
34
|
# As produced by http://cosm.com/api/v1/FEED_ID/datastreams/DATASTREAM_ID.xml
|
|
34
35
|
def transform_v1(xml)
|
|
36
|
+
validate_xml(xml)
|
|
35
37
|
datastream = convert_to_hash(xml['data'])
|
|
36
38
|
_extract_datastream_v1(datastream).merge({
|
|
37
39
|
:feed_id => strip(xml,'id'),
|
|
@@ -40,6 +42,10 @@ module Cosm
|
|
|
40
42
|
})
|
|
41
43
|
end
|
|
42
44
|
|
|
45
|
+
def validate_xml(xml)
|
|
46
|
+
raise InvalidXMLError, "Multiple 'data' nodes are not permitted for Datastream level XML" if xml['data'].is_a?(Array)
|
|
47
|
+
raise InvalidXMLError, "Missing 'data' node from source document" if xml['data'].nil?
|
|
48
|
+
end
|
|
43
49
|
end
|
|
44
50
|
end
|
|
45
51
|
end
|
data/lib/cosm-rb/version.rb
CHANGED
|
@@ -120,43 +120,43 @@ describe Cosm::Datastream do
|
|
|
120
120
|
|
|
121
121
|
it "should raise known exception if passed json but told xml" do
|
|
122
122
|
expect {
|
|
123
|
-
Cosm::Datastream.new(datastream_as_(:json), :xml)
|
|
123
|
+
Cosm::Datastream.new(datastream_as_(:json), :v2, :xml)
|
|
124
124
|
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
it "should raise known exception if passed csv but told xml" do
|
|
128
128
|
expect {
|
|
129
|
-
Cosm::Datastream.new(datastream_as_(:csv), :xml)
|
|
129
|
+
Cosm::Datastream.new(datastream_as_(:csv), :v2, :xml)
|
|
130
130
|
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
it "should raise known exception if passed xml but told json" do
|
|
134
134
|
expect {
|
|
135
|
-
Cosm::Datastream.new(datastream_as_(:xml), :json)
|
|
135
|
+
Cosm::Datastream.new(datastream_as_(:xml), :v2, :json)
|
|
136
136
|
}.to raise_error(Cosm::Parsers::JSON::InvalidJSONError)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
it "should raise known exception if passed csv but told json" do
|
|
140
140
|
expect {
|
|
141
|
-
Cosm::Datastream.new(datastream_as_(:csv), :json)
|
|
141
|
+
Cosm::Datastream.new(datastream_as_(:csv), :v2, :json)
|
|
142
142
|
}.to raise_error(Cosm::Parsers::JSON::InvalidJSONError)
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
it "should raise known exception if passed json but told csv" do
|
|
146
146
|
expect {
|
|
147
|
-
Cosm::Datastream.new(datastream_as_(:json), :csv)
|
|
147
|
+
Cosm::Datastream.new(datastream_as_(:json), :v2, :csv)
|
|
148
148
|
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
it "should raise known exception if passed xml but told csv" do
|
|
152
152
|
expect {
|
|
153
|
-
Cosm::Datastream.new(datastream_as_(:xml), :csv)
|
|
153
|
+
Cosm::Datastream.new(datastream_as_(:xml), :v2, :csv)
|
|
154
154
|
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
155
155
|
end
|
|
156
156
|
|
|
157
157
|
it "should raise known exception if told some format we don't accept" do
|
|
158
158
|
expect {
|
|
159
|
-
Cosm::Datastream.new(datastream_as_(:xml), :html)
|
|
159
|
+
Cosm::Datastream.new(datastream_as_(:xml), :v2, :html)
|
|
160
160
|
}.to raise_error(Cosm::InvalidFormatError)
|
|
161
161
|
end
|
|
162
162
|
|
|
@@ -4,13 +4,13 @@ describe "default datastream csv parser" do
|
|
|
4
4
|
describe "csv" do
|
|
5
5
|
it "should convert Pachube CSV into attributes hash" do
|
|
6
6
|
csv = datastream_as_(:csv)
|
|
7
|
-
datastream = Cosm::Datastream.new(csv)
|
|
7
|
+
datastream = Cosm::Datastream.new(csv, :v2)
|
|
8
8
|
datastream.should fully_represent_datastream(:csv, csv)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
it "should capture timestamp if present" do
|
|
12
12
|
csv = datastream_as_(:csv, :version => "timestamped")
|
|
13
|
-
datastream = Cosm::Datastream.new(csv)
|
|
13
|
+
datastream = Cosm::Datastream.new(csv, :v2, :csv)
|
|
14
14
|
datastream.updated.should == "2011-02-16T16:21:01.834174Z"
|
|
15
15
|
datastream.current_value.should == "14"
|
|
16
16
|
end
|
|
@@ -29,11 +29,82 @@ describe "default datastream csv parser" do
|
|
|
29
29
|
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
it "should raise error if passed more than a single value as v1" do
|
|
33
|
+
csv = "192,2"
|
|
34
|
+
expect {
|
|
35
|
+
Cosm::Datastream.new(csv, :v1)
|
|
36
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
37
|
+
end
|
|
38
|
+
|
|
32
39
|
it "should raise exception if passed garbage csv" do
|
|
33
40
|
expect {
|
|
34
41
|
Cosm::Datastream.new("badly, \"quoted", :csv)
|
|
35
42
|
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
36
43
|
end
|
|
44
|
+
|
|
45
|
+
it "should not raise exception if passed data with nil value" do
|
|
46
|
+
expect {
|
|
47
|
+
datastream = Cosm::Datastream.new("2012-08-12T00:00:00Z,", :v2)
|
|
48
|
+
datastream.current_value.should be_empty
|
|
49
|
+
}.to_not raise_error
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should parse multiline csv" do
|
|
53
|
+
csv = <<-CSV
|
|
54
|
+
2012-02-08T00:00:00Z,123
|
|
55
|
+
2012-02-08T00:00:10Z,124
|
|
56
|
+
2012-02-08T00:00:20Z,125
|
|
57
|
+
2012-02-08T00:00:30Z,126
|
|
58
|
+
CSV
|
|
59
|
+
datastream = Cosm::Datastream.new(csv, :v2)
|
|
60
|
+
datastream.updated.should be_nil
|
|
61
|
+
datastream.current_value.should be_nil
|
|
62
|
+
datastream.datapoints.size.should == 4
|
|
63
|
+
datastream.datapoints.collect { |d| [d.at, d.value].join(",") }.join("\n").should == csv.strip
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should not parse multiline csv passed to the v1 api" do
|
|
67
|
+
csv = <<-CSV
|
|
68
|
+
2012-02-08T00:00:00Z,123
|
|
69
|
+
2012-02-08T00:00:10Z,124
|
|
70
|
+
2012-02-08T00:00:20Z,125
|
|
71
|
+
2012-02-08T00:00:30Z,126
|
|
72
|
+
CSV
|
|
73
|
+
expect {
|
|
74
|
+
datastream = Cosm::Datastream.new(csv, :v1)
|
|
75
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should not accept multiline csv with just single values" do
|
|
79
|
+
csv = <<-CSV
|
|
80
|
+
123
|
|
81
|
+
124
|
|
82
|
+
125
|
|
83
|
+
126
|
|
84
|
+
CSV
|
|
85
|
+
|
|
86
|
+
expect {
|
|
87
|
+
datastream = Cosm::Datastream.new(csv, :v2)
|
|
88
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should strip whitespace from multiline values" do
|
|
92
|
+
csv = <<-CSV
|
|
93
|
+
2012-02-08T00:00:00Z , 123
|
|
94
|
+
2012-02-08T00:00:10Z , 124
|
|
95
|
+
2012-02-08T00:00:20Z , 125
|
|
96
|
+
2012-02-08T00:00:30Z , 126
|
|
97
|
+
CSV
|
|
98
|
+
|
|
99
|
+
datastream = Cosm::Datastream.new(csv, :v2)
|
|
100
|
+
datastream.updated.should be_nil
|
|
101
|
+
datastream.current_value.should be_nil
|
|
102
|
+
datastream.datapoints.size.should == 4
|
|
103
|
+
datastream.datapoints.sort { |a, b| a.at <=> b.at }.collect { |d| [d.at, d.value] }.should == [["2012-02-08T00:00:00Z","123"],
|
|
104
|
+
["2012-02-08T00:00:10Z","124"],
|
|
105
|
+
["2012-02-08T00:00:20Z","125"],
|
|
106
|
+
["2012-02-08T00:00:30Z","126"]]
|
|
107
|
+
end
|
|
37
108
|
end
|
|
38
109
|
end
|
|
39
110
|
|
|
@@ -61,6 +61,26 @@ CSV
|
|
|
61
61
|
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError, /3 rows/)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
context "nil attribute csv" do
|
|
65
|
+
before(:each) do
|
|
66
|
+
@csv = "0,,"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should not raise exception if csv has nil values as v1" do
|
|
70
|
+
expect {
|
|
71
|
+
feed = Cosm::Feed.new(@csv, :v1)
|
|
72
|
+
feed.datastreams.size.should == 3
|
|
73
|
+
}.to_not raise_error
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should not raise exception if csv has nil attributes as v2" do
|
|
77
|
+
expect {
|
|
78
|
+
feed = Cosm::Feed.new(@csv, :v2)
|
|
79
|
+
feed.datastreams.size.should == 1
|
|
80
|
+
}.to_not raise_error
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
64
84
|
context "unwanted whitespace" do
|
|
65
85
|
it "should strip whitespace from v2" do
|
|
66
86
|
dodgy_csv = <<-CSV
|
|
@@ -84,6 +104,107 @@ CSV
|
|
|
84
104
|
feed.should fully_represent_feed(:csv_v1, good_csv)
|
|
85
105
|
end
|
|
86
106
|
end
|
|
107
|
+
|
|
108
|
+
context "multivalue csv" do
|
|
109
|
+
def check_multiline_csv(csv)
|
|
110
|
+
feed = Cosm::Feed.new(csv)
|
|
111
|
+
|
|
112
|
+
feed.datastreams.size.should == 2
|
|
113
|
+
feed.datastreams.each do |datastream|
|
|
114
|
+
datastream.updated.should be_nil
|
|
115
|
+
datastream.current_value.should be_nil
|
|
116
|
+
datastream.datapoints.size.should == 3
|
|
117
|
+
datastream.datapoints.sort { |a,b| a.at <=> b.at }.collect { |d| [d.at, d.value] }.should == [["2012-08-12T00:00:00Z", "1"],
|
|
118
|
+
["2012-08-12T00:00:05Z", "2"],
|
|
119
|
+
["2012-08-12T00:00:10Z", "3"]]
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should capture multivalue csv with timestamps" do
|
|
124
|
+
csv = <<-CSV
|
|
125
|
+
stream0,2012-08-12T00:00:00Z,1
|
|
126
|
+
stream1,2012-08-12T00:00:00Z,1
|
|
127
|
+
stream0,2012-08-12T00:00:05Z,2
|
|
128
|
+
stream1,2012-08-12T00:00:05Z,2
|
|
129
|
+
stream0,2012-08-12T00:00:10Z,3
|
|
130
|
+
stream1,2012-08-12T00:00:10Z,3
|
|
131
|
+
CSV
|
|
132
|
+
|
|
133
|
+
check_multiline_csv(csv)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "should capture multivalue csv with timestamps no matter the grouping" do
|
|
137
|
+
csv = <<-CSV
|
|
138
|
+
stream0,2012-08-12T00:00:00Z,1
|
|
139
|
+
stream0,2012-08-12T00:00:05Z,2
|
|
140
|
+
stream0,2012-08-12T00:00:10Z,3
|
|
141
|
+
stream1,2012-08-12T00:00:00Z,1
|
|
142
|
+
stream1,2012-08-12T00:00:05Z,2
|
|
143
|
+
stream1,2012-08-12T00:00:10Z,3
|
|
144
|
+
CSV
|
|
145
|
+
|
|
146
|
+
check_multiline_csv(csv)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should strip whitespace from multiline csv" do
|
|
150
|
+
csv = <<-CSV
|
|
151
|
+
stream0, 2012-08-12T00:00:00Z, 1
|
|
152
|
+
stream0, 2012-08-12T00:00:05Z, 2
|
|
153
|
+
stream0, 2012-08-12T00:00:10Z, 3
|
|
154
|
+
stream1, 2012-08-12T00:00:00Z, 1
|
|
155
|
+
stream1, 2012-08-12T00:00:05Z, 2
|
|
156
|
+
stream1, 2012-08-12T00:00:10Z, 3
|
|
157
|
+
CSV
|
|
158
|
+
|
|
159
|
+
check_multiline_csv(csv)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "should reject multivalue csv without timestamps" do
|
|
163
|
+
csv = <<-CSV
|
|
164
|
+
stream0,1
|
|
165
|
+
stream1,1
|
|
166
|
+
stream0,2
|
|
167
|
+
stream1,2
|
|
168
|
+
stream0,3
|
|
169
|
+
stream1,3
|
|
170
|
+
CSV
|
|
171
|
+
expect {
|
|
172
|
+
Cosm::Feed.new(csv)
|
|
173
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "should reject multivalue csv if we tell it its v1" do
|
|
177
|
+
csv = <<-CSV
|
|
178
|
+
stream0,2012-08-12T00:00:00Z,1
|
|
179
|
+
stream1,2012-08-12T00:00:00Z,1
|
|
180
|
+
CSV
|
|
181
|
+
|
|
182
|
+
expect {
|
|
183
|
+
Cosm::Feed.new(csv, :v1)
|
|
184
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "should permit an individual value within a larger update to not have a timestamp" do
|
|
188
|
+
csv = <<-CSV
|
|
189
|
+
stream0,2012-08-12T00:00:00Z,1
|
|
190
|
+
stream1,2012-08-12T00:00:00Z,1
|
|
191
|
+
stream0,2012-08-12T00:00:05Z,2
|
|
192
|
+
stream1,2012-08-12T00:00:05Z,2
|
|
193
|
+
stream0,2012-08-12T00:00:10Z,3
|
|
194
|
+
stream1,2012-08-12T00:00:10Z,3
|
|
195
|
+
stream2,4
|
|
196
|
+
CSV
|
|
197
|
+
feed = Cosm::Feed.new(csv)
|
|
198
|
+
feed.datastreams.size.should == 3
|
|
199
|
+
sorted_datastreams = feed.datastreams.sort { |a, b| a.id <=> b.id }
|
|
200
|
+
[0,1].each do |i|
|
|
201
|
+
sorted_datastreams[i].current_value.should be_nil
|
|
202
|
+
sorted_datastreams[i].updated.should be_nil
|
|
203
|
+
sorted_datastreams[i].datapoints.size.should == 3
|
|
204
|
+
end
|
|
205
|
+
sorted_datastreams[2].current_value.should == "4"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
87
208
|
end
|
|
88
209
|
end
|
|
89
210
|
|
|
@@ -32,7 +32,7 @@ describe "default datastream json parser" do
|
|
|
32
32
|
|
|
33
33
|
it "should raise known exception if passed garbage as JSON" do
|
|
34
34
|
expect {
|
|
35
|
-
Cosm::Datastream.new("This is not json", :json)
|
|
35
|
+
Cosm::Datastream.new("This is not json", :v2, :json)
|
|
36
36
|
}.to raise_error(Cosm::Parsers::JSON::InvalidJSONError)
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -3,8 +3,8 @@ require 'spec_helper'
|
|
|
3
3
|
describe "default datastream xml parser" do
|
|
4
4
|
context "0.5.1 (used by API v2)" do
|
|
5
5
|
it "should convert into attributes hash" do
|
|
6
|
-
|
|
7
|
-
Cosm::Datastream.new(
|
|
6
|
+
xml = datastream_as_(:xml)
|
|
7
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
it "should convert into attributes hash when no version string but correct xmlns" do
|
|
@@ -13,30 +13,57 @@ describe "default datastream xml parser" do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
it "should handle blank tags" do
|
|
16
|
-
|
|
17
|
-
Cosm::Datastream.new(
|
|
16
|
+
xml = datastream_as_(:xml, :except_node => :tag)
|
|
17
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "should handle blank units" do
|
|
21
|
-
|
|
22
|
-
Cosm::Datastream.new(
|
|
21
|
+
xml = datastream_as_(:xml, :except_node => :unit)
|
|
22
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
it "should handle missing unit attributes" do
|
|
26
|
-
|
|
27
|
-
Cosm::Datastream.new(
|
|
26
|
+
xml = datastream_as_(:xml, :except_node => :unit_attributes)
|
|
27
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
it "should handle missing timestamps" do
|
|
31
|
-
|
|
32
|
-
Cosm::Datastream.new(
|
|
31
|
+
xml = datastream_as_(:xml, :except_node => :timestamps)
|
|
32
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should capture all datapoints" do
|
|
36
|
+
xml = datastream_as_(:xml)
|
|
37
|
+
datastream = Cosm::Datastream.new(xml)
|
|
38
|
+
datastream.datapoints.size.should == 3
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should raise exception if passed xml containing more than one datastream" do
|
|
42
|
+
xml = feed_as_(:xml)
|
|
43
|
+
expect {
|
|
44
|
+
Cosm::Datastream.new(xml)
|
|
45
|
+
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should raise exception if passed xml without any datastreams" do
|
|
49
|
+
xml = <<-XML
|
|
50
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
51
|
+
<eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
|
|
52
|
+
<environment id="504" creator="http://appdev.loc:3000/users/occaecati">
|
|
53
|
+
</environment>
|
|
54
|
+
</eeml>
|
|
55
|
+
XML
|
|
56
|
+
|
|
57
|
+
expect {
|
|
58
|
+
Cosm::Datastream.new(xml)
|
|
59
|
+
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
33
60
|
end
|
|
34
61
|
end
|
|
35
62
|
|
|
36
63
|
context "5 (used by API v1)" do
|
|
37
64
|
it "should convert into attributes hash" do
|
|
38
|
-
|
|
39
|
-
Cosm::Datastream.new(
|
|
65
|
+
xml = datastream_as_(:xml, :version => "5")
|
|
66
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
40
67
|
end
|
|
41
68
|
|
|
42
69
|
it "should convert into attributes hash even when no version attribute if correct xmlns" do
|
|
@@ -45,34 +72,55 @@ describe "default datastream xml parser" do
|
|
|
45
72
|
end
|
|
46
73
|
|
|
47
74
|
it "should handle blank tags" do
|
|
48
|
-
|
|
49
|
-
Cosm::Datastream.new(
|
|
75
|
+
xml = datastream_as_(:xml, :version => "5", :except_node => :tag)
|
|
76
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
50
77
|
end
|
|
51
78
|
|
|
52
79
|
it "should handle blank units" do
|
|
53
|
-
|
|
54
|
-
Cosm::Datastream.new(
|
|
80
|
+
xml = datastream_as_(:xml, :version => "5", :except_node => :unit)
|
|
81
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
55
82
|
end
|
|
56
83
|
|
|
57
84
|
it "should handle missing unit attributes" do
|
|
58
|
-
|
|
59
|
-
Cosm::Datastream.new(
|
|
85
|
+
xml = datastream_as_(:xml, :version => "5", :except_node => :unit_attributes)
|
|
86
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
60
87
|
end
|
|
61
88
|
|
|
62
89
|
it "should handle missing value attributes" do
|
|
63
|
-
|
|
64
|
-
Cosm::Datastream.new(
|
|
90
|
+
xml = datastream_as_(:xml, :version => "5", :except_node => :value_attributes)
|
|
91
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
65
92
|
end
|
|
66
93
|
|
|
67
94
|
it "should handle missing timestamps" do
|
|
68
|
-
|
|
69
|
-
Cosm::Datastream.new(
|
|
95
|
+
xml = datastream_as_(:xml, :version => "5", :except_node => :timestamps)
|
|
96
|
+
Cosm::Datastream.new(xml).should fully_represent_datastream(:xml, xml)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should raise exception if passed xml containing more than one datastream" do
|
|
100
|
+
xml = feed_as_(:xml, :version => "5")
|
|
101
|
+
expect {
|
|
102
|
+
Cosm::Datastream.new(xml)
|
|
103
|
+
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should raise exception if passed xml without any datastreams" do
|
|
107
|
+
xml = <<-XML
|
|
108
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
109
|
+
<eeml xmlns="http://www.eeml.org/xsd/005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
|
|
110
|
+
<environment updated="2011-02-16T16:21:01.834174Z" id="504" creator="http://appdev.loc:3000/users/occaecati">
|
|
111
|
+
</environment>
|
|
112
|
+
</eeml>
|
|
113
|
+
XML
|
|
114
|
+
|
|
115
|
+
expect {
|
|
116
|
+
Cosm::Datastream.new(xml)
|
|
117
|
+
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
70
118
|
end
|
|
71
119
|
end
|
|
72
120
|
|
|
73
121
|
it "should raise exception if passed garbage as XML" do
|
|
74
122
|
expect {
|
|
75
|
-
Cosm::Datastream.new("This is not xml", :xml)
|
|
123
|
+
Cosm::Datastream.new("This is not xml", :v2, :xml)
|
|
76
124
|
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
77
125
|
end
|
|
78
126
|
end
|
|
@@ -216,5 +216,39 @@ EOXML
|
|
|
216
216
|
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
|
217
217
|
end
|
|
218
218
|
end
|
|
219
|
+
|
|
220
|
+
context "feeds with datapoints" do
|
|
221
|
+
it "should grab all datapoints present in valid xml" do
|
|
222
|
+
xml = <<-XML
|
|
223
|
+
<eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
|
|
224
|
+
<environment>
|
|
225
|
+
<data id="0">
|
|
226
|
+
<datapoints>
|
|
227
|
+
<value at="2010-05-20T11:01:43Z">294</value>
|
|
228
|
+
<value at="2010-05-20T11:01:44Z">295</value>
|
|
229
|
+
<value at="2010-05-20T11:01:45Z">296</value>
|
|
230
|
+
<value at="2010-05-20T11:01:46Z">297</value>
|
|
231
|
+
</datapoints>
|
|
232
|
+
</data>
|
|
233
|
+
<data id="1">
|
|
234
|
+
<current_value at="2010-05-20T11:01:47Z">23</current_value>
|
|
235
|
+
<datapoints>
|
|
236
|
+
<value at="2010-05-20T11:01:43Z">24</value>
|
|
237
|
+
<value at="2010-05-20T11:01:44Z">25</value>
|
|
238
|
+
</datapoints>
|
|
239
|
+
</data>
|
|
240
|
+
</environment>
|
|
241
|
+
</eeml>
|
|
242
|
+
XML
|
|
243
|
+
feed = Cosm::Feed.new(xml)
|
|
244
|
+
feed.datastreams.size.should == 2
|
|
245
|
+
feed.datastreams[0].current_value.should == nil
|
|
246
|
+
feed.datastreams[0].datapoints.size.should == 4
|
|
247
|
+
feed.datastreams[0].datapoints.collect { |d| d.value }.should == ["294", "295", "296", "297"]
|
|
248
|
+
feed.datastreams[1].current_value.should == "23"
|
|
249
|
+
feed.datastreams[1].datapoints.size.should == 2
|
|
250
|
+
feed.datastreams[1].datapoints.collect { |d| d.value }.should == ["24", "25"]
|
|
251
|
+
end
|
|
252
|
+
end
|
|
219
253
|
end
|
|
220
254
|
|
data/spec/spec_helper.rb
CHANGED
|
@@ -77,10 +77,14 @@ RSpec::Matchers.define :fully_represent_datastream do |format, formatted_datastr
|
|
|
77
77
|
def match_json_datastream(datastream, formatted_datastream)
|
|
78
78
|
json = MultiJson.load(formatted_datastream)
|
|
79
79
|
case json['version']
|
|
80
|
-
when '
|
|
80
|
+
when '0.6-alpha'
|
|
81
81
|
raise "Not implemented"
|
|
82
82
|
else
|
|
83
|
-
|
|
83
|
+
datastream.current_value.should == json["current_value"]
|
|
84
|
+
datastream.id.should == json["id"]
|
|
85
|
+
datastream.updated.should == json["at"]
|
|
86
|
+
datastream.min_value.should == json["min_value"]
|
|
87
|
+
datastream.max_value.should == json["max_value"]
|
|
84
88
|
end
|
|
85
89
|
end
|
|
86
90
|
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cosm-rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 21
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 2
|
|
9
|
-
-
|
|
10
|
-
version: 0.2.
|
|
9
|
+
- 1
|
|
10
|
+
version: 0.2.01
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Paul Bellamy
|
|
@@ -21,9 +21,7 @@ date: 2012-09-11 00:00:00 +00:00
|
|
|
21
21
|
default_executable:
|
|
22
22
|
dependencies:
|
|
23
23
|
- !ruby/object:Gem::Dependency
|
|
24
|
-
|
|
25
|
-
prerelease: false
|
|
26
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
|
27
25
|
none: false
|
|
28
26
|
requirements:
|
|
29
27
|
- - ">="
|
|
@@ -34,12 +32,12 @@ dependencies:
|
|
|
34
32
|
- 3
|
|
35
33
|
- 6
|
|
36
34
|
version: 1.3.6
|
|
35
|
+
requirement: *id001
|
|
37
36
|
type: :runtime
|
|
38
|
-
|
|
39
|
-
- !ruby/object:Gem::Dependency
|
|
40
|
-
name: multi_xml
|
|
37
|
+
name: multi_json
|
|
41
38
|
prerelease: false
|
|
42
|
-
|
|
39
|
+
- !ruby/object:Gem::Dependency
|
|
40
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
|
43
41
|
none: false
|
|
44
42
|
requirements:
|
|
45
43
|
- - ">="
|
|
@@ -50,12 +48,12 @@ dependencies:
|
|
|
50
48
|
- 5
|
|
51
49
|
- 1
|
|
52
50
|
version: 0.5.1
|
|
51
|
+
requirement: *id002
|
|
53
52
|
type: :runtime
|
|
54
|
-
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: yajl-ruby
|
|
53
|
+
name: multi_xml
|
|
57
54
|
prerelease: false
|
|
58
|
-
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
|
59
57
|
none: false
|
|
60
58
|
requirements:
|
|
61
59
|
- - ">="
|
|
@@ -66,12 +64,12 @@ dependencies:
|
|
|
66
64
|
- 1
|
|
67
65
|
- 0
|
|
68
66
|
version: 1.1.0
|
|
67
|
+
requirement: *id003
|
|
69
68
|
type: :runtime
|
|
70
|
-
|
|
71
|
-
- !ruby/object:Gem::Dependency
|
|
72
|
-
name: nokogiri
|
|
69
|
+
name: yajl-ruby
|
|
73
70
|
prerelease: false
|
|
74
|
-
|
|
71
|
+
- !ruby/object:Gem::Dependency
|
|
72
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
|
75
73
|
none: false
|
|
76
74
|
requirements:
|
|
77
75
|
- - ">="
|
|
@@ -82,12 +80,12 @@ dependencies:
|
|
|
82
80
|
- 4
|
|
83
81
|
- 4
|
|
84
82
|
version: 1.4.4
|
|
83
|
+
requirement: *id004
|
|
85
84
|
type: :runtime
|
|
86
|
-
|
|
87
|
-
- !ruby/object:Gem::Dependency
|
|
88
|
-
name: httparty
|
|
85
|
+
name: nokogiri
|
|
89
86
|
prerelease: false
|
|
90
|
-
|
|
87
|
+
- !ruby/object:Gem::Dependency
|
|
88
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
|
91
89
|
none: false
|
|
92
90
|
requirements:
|
|
93
91
|
- - ">="
|
|
@@ -98,12 +96,12 @@ dependencies:
|
|
|
98
96
|
- 8
|
|
99
97
|
- 3
|
|
100
98
|
version: 0.8.3
|
|
99
|
+
requirement: *id005
|
|
101
100
|
type: :runtime
|
|
102
|
-
|
|
103
|
-
- !ruby/object:Gem::Dependency
|
|
104
|
-
name: fastercsv
|
|
101
|
+
name: httparty
|
|
105
102
|
prerelease: false
|
|
106
|
-
|
|
103
|
+
- !ruby/object:Gem::Dependency
|
|
104
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
|
107
105
|
none: false
|
|
108
106
|
requirements:
|
|
109
107
|
- - ">="
|
|
@@ -114,12 +112,12 @@ dependencies:
|
|
|
114
112
|
- 5
|
|
115
113
|
- x
|
|
116
114
|
version: 1.5.x
|
|
115
|
+
requirement: *id006
|
|
117
116
|
type: :runtime
|
|
118
|
-
|
|
119
|
-
- !ruby/object:Gem::Dependency
|
|
120
|
-
name: ox
|
|
117
|
+
name: fastercsv
|
|
121
118
|
prerelease: false
|
|
122
|
-
|
|
119
|
+
- !ruby/object:Gem::Dependency
|
|
120
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
|
123
121
|
none: false
|
|
124
122
|
requirements:
|
|
125
123
|
- - ">="
|
|
@@ -130,12 +128,12 @@ dependencies:
|
|
|
130
128
|
- 5
|
|
131
129
|
- 9
|
|
132
130
|
version: 1.5.9
|
|
131
|
+
requirement: *id007
|
|
133
132
|
type: :runtime
|
|
134
|
-
|
|
135
|
-
- !ruby/object:Gem::Dependency
|
|
136
|
-
name: ruby-debug
|
|
133
|
+
name: ox
|
|
137
134
|
prerelease: false
|
|
138
|
-
|
|
135
|
+
- !ruby/object:Gem::Dependency
|
|
136
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
|
139
137
|
none: false
|
|
140
138
|
requirements:
|
|
141
139
|
- - ">="
|
|
@@ -144,12 +142,12 @@ dependencies:
|
|
|
144
142
|
segments:
|
|
145
143
|
- 0
|
|
146
144
|
version: "0"
|
|
145
|
+
requirement: *id008
|
|
147
146
|
type: :development
|
|
148
|
-
|
|
149
|
-
- !ruby/object:Gem::Dependency
|
|
150
|
-
name: rcov
|
|
147
|
+
name: ruby-debug
|
|
151
148
|
prerelease: false
|
|
152
|
-
|
|
149
|
+
- !ruby/object:Gem::Dependency
|
|
150
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
|
153
151
|
none: false
|
|
154
152
|
requirements:
|
|
155
153
|
- - ">="
|
|
@@ -160,12 +158,12 @@ dependencies:
|
|
|
160
158
|
- 9
|
|
161
159
|
- 9
|
|
162
160
|
version: 0.9.9
|
|
161
|
+
requirement: *id009
|
|
163
162
|
type: :development
|
|
164
|
-
|
|
165
|
-
- !ruby/object:Gem::Dependency
|
|
166
|
-
name: rake
|
|
163
|
+
name: rcov
|
|
167
164
|
prerelease: false
|
|
168
|
-
|
|
165
|
+
- !ruby/object:Gem::Dependency
|
|
166
|
+
version_requirements: &id010 !ruby/object:Gem::Requirement
|
|
169
167
|
none: false
|
|
170
168
|
requirements:
|
|
171
169
|
- - "="
|
|
@@ -176,12 +174,12 @@ dependencies:
|
|
|
176
174
|
- 8
|
|
177
175
|
- 7
|
|
178
176
|
version: 0.8.7
|
|
177
|
+
requirement: *id010
|
|
179
178
|
type: :development
|
|
180
|
-
|
|
181
|
-
- !ruby/object:Gem::Dependency
|
|
182
|
-
name: rspec
|
|
179
|
+
name: rake
|
|
183
180
|
prerelease: false
|
|
184
|
-
|
|
181
|
+
- !ruby/object:Gem::Dependency
|
|
182
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
|
185
183
|
none: false
|
|
186
184
|
requirements:
|
|
187
185
|
- - "="
|
|
@@ -192,8 +190,10 @@ dependencies:
|
|
|
192
190
|
- 6
|
|
193
191
|
- 0
|
|
194
192
|
version: 2.6.0
|
|
193
|
+
requirement: *id011
|
|
195
194
|
type: :development
|
|
196
|
-
|
|
195
|
+
name: rspec
|
|
196
|
+
prerelease: false
|
|
197
197
|
description: A library for communicating with the Cosm REST API, parsing and rendering Cosm feed formats
|
|
198
198
|
email:
|
|
199
199
|
- paul.a.bellamy@gmail.com
|