cosm-rb 0.0.3 → 0.0.5
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/.travis.yml +1 -5
- data/Rakefile +6 -4
- data/cosm-rb.gemspec +11 -3
- data/lib/cosm-rb.rb +9 -1
- data/lib/cosm-rb/datastream.rb +0 -10
- data/lib/cosm-rb/parsers/csv/datastream_defaults.rb +10 -2
- data/lib/cosm-rb/parsers/csv/feed_defaults.rb +15 -10
- data/lib/cosm-rb/parsers/json/feed_defaults.rb +29 -24
- data/lib/cosm-rb/parsers/xml/datapoint_defaults.rb +1 -0
- data/lib/cosm-rb/parsers/xml/datastream_defaults.rb +7 -5
- data/lib/cosm-rb/parsers/xml/feed_defaults.rb +63 -39
- data/lib/cosm-rb/templates/csv/datapoint_defaults.rb +4 -4
- data/lib/cosm-rb/templates/csv/datastream_defaults.rb +2 -2
- data/lib/cosm-rb/templates/csv/feed_defaults.rb +5 -5
- data/lib/cosm-rb/version.rb +1 -1
- data/spec/cosm-rb/datastream_spec.rb +1 -0
- data/spec/cosm-rb/parsers/csv/datastream_defaults_spec.rb +22 -0
- data/spec/cosm-rb/parsers/csv/feed_defaults_spec.rb +18 -0
- data/spec/cosm-rb/parsers/json/feed_defaults_spec.rb +22 -0
- data/spec/cosm-rb/parsers/xml/feed_defaults_spec.rb +70 -0
- data/spec/cosm-rb/templates/csv/datapoint_defaults_spec.rb +2 -2
- data/spec/cosm-rb/templates/csv/datastream_defaults_spec.rb +5 -5
- data/spec/cosm-rb/templates/csv/feed_defaults_spec.rb +7 -7
- data/spec/spec_helper.rb +14 -0
- data/spec/support/feed_helper.rb +11 -1
- data/spec/support/fully_represent_feed_matcher.rb +15 -6
- metadata +44 -87
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
@@ -20,10 +20,12 @@ desc "Run all specs in spec directory"
|
|
20
20
|
RSpec::Core::RakeTask.new do |t|
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
if RUBY_VERSION.to_f < 1.9
|
24
|
+
desc "Run all specs with rcov"
|
25
|
+
RSpec::Core::RakeTask.new(:rcov => :clean) do |t|
|
26
|
+
t.rcov = true
|
27
|
+
t.rcov_opts = '--exclude .gem/*,spec/*,.bundle/*,config/*,.rvm/*,lib/cosm-rb.rb'
|
28
|
+
end
|
27
29
|
end
|
28
30
|
|
29
31
|
namespace :spec do
|
data/cosm-rb.gemspec
CHANGED
@@ -25,10 +25,18 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency("nokogiri", ">=1.4.4")
|
26
26
|
s.add_dependency("httparty", ">=0.8.3")
|
27
27
|
|
28
|
+
if RUBY_VERSION.to_f < 1.9
|
29
|
+
s.add_dependency("fastercsv", ">=1.5.x")
|
30
|
+
end
|
31
|
+
|
28
32
|
begin
|
29
|
-
if
|
30
|
-
|
31
|
-
|
33
|
+
if !defined?(JRUBY_VERSION)
|
34
|
+
if RUBY_VERSION.to_f < 1.9
|
35
|
+
s.add_development_dependency("ruby-debug")
|
36
|
+
s.add_development_dependency("rcov", ">=0.9.9")
|
37
|
+
else
|
38
|
+
s.add_development_dependency("simplecov")
|
39
|
+
end
|
32
40
|
end
|
33
41
|
rescue
|
34
42
|
p "Could not detect ruby version"
|
data/lib/cosm-rb.rb
CHANGED
@@ -4,7 +4,6 @@ if defined?(JRUBY_VERSION)
|
|
4
4
|
else
|
5
5
|
require 'yajl/json_gem'
|
6
6
|
end
|
7
|
-
require 'csv'
|
8
7
|
|
9
8
|
$:.unshift(File.dirname(File.expand_path(__FILE__)))
|
10
9
|
|
@@ -31,3 +30,12 @@ require 'cosm-rb/permission'
|
|
31
30
|
require 'cosm-rb/resource'
|
32
31
|
|
33
32
|
require 'cosm-rb/client'
|
33
|
+
|
34
|
+
if RUBY_VERSION.to_f < 1.9
|
35
|
+
require 'fastercsv'
|
36
|
+
Cosm::CSV = FasterCSV
|
37
|
+
else
|
38
|
+
require 'csv'
|
39
|
+
Cosm::CSV = CSV
|
40
|
+
end
|
41
|
+
|
data/lib/cosm-rb/datastream.rb
CHANGED
@@ -13,16 +13,6 @@ module Cosm
|
|
13
13
|
include Cosm::Parsers::CSV::DatastreamDefaults
|
14
14
|
|
15
15
|
include Validations
|
16
|
-
# validate :before, :join_tags
|
17
|
-
|
18
|
-
# validates_presence_of :id
|
19
|
-
# validates_length_of :current_value, :maximum => 255
|
20
|
-
# validates_length_of :tags, :maximum => 255
|
21
|
-
# validates_inclusion_of :unit_type, :in => VALID_UNIT_TYPES,
|
22
|
-
# :allow_nil => true,
|
23
|
-
# :message => "is not a valid unit_type (pick one from #{VALID_UNIT_TYPES} or leave blank)"
|
24
|
-
# validates_format_of :id, :with => /\A[\w\-\+\.]+\Z/
|
25
|
-
#
|
26
16
|
|
27
17
|
def valid?
|
28
18
|
pass = true
|
@@ -2,8 +2,16 @@ module Cosm
|
|
2
2
|
module Parsers
|
3
3
|
module CSV
|
4
4
|
module DatastreamDefaults
|
5
|
-
def from_csv(csv)
|
6
|
-
|
5
|
+
def from_csv(csv, csv_version = nil)
|
6
|
+
rows = Cosm::CSV.parse(csv.strip)
|
7
|
+
raise InvalidCSVError, "CSV is invalid. Can only construct a Cosm::Datastream object from a single row of data" if rows.size > 1
|
8
|
+
row = rows.first
|
9
|
+
raise InvalidCSVError, "CSV is invalid. Too many fields; must only be a single value, or a timestamp and a value" if row.size > 2
|
10
|
+
if row.size == 2
|
11
|
+
return { "updated" => row[0], "current_value" => row[1].to_s }
|
12
|
+
else
|
13
|
+
return { "current_value" => row[0].to_s }
|
14
|
+
end
|
7
15
|
end
|
8
16
|
end
|
9
17
|
end
|
@@ -2,20 +2,25 @@ module Cosm
|
|
2
2
|
module Parsers
|
3
3
|
module CSV
|
4
4
|
class UnknownVersionError < StandardError ; end
|
5
|
+
class InvalidCSVError < StandardError ; end
|
6
|
+
|
5
7
|
module FeedDefaults
|
6
8
|
def from_csv(csv, csv_version = nil)
|
7
|
-
|
8
|
-
version = detect_version(
|
9
|
+
rows = Cosm::CSV.parse(csv.strip)
|
10
|
+
version = detect_version(rows, csv_version)
|
9
11
|
hash = Hash.new
|
10
12
|
if version == :v2
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
raise InvalidCSVError, "CSV is invalid. Incorrect number of fields" if rows.sort { |a,b| a.length <=> b.length }.reverse.first.length > 3
|
14
|
+
hash["datastreams"] = rows.collect {|row|
|
15
|
+
timestamp = {}
|
16
|
+
if row.size == 3
|
17
|
+
timestamp["updated"] = row[1]
|
18
|
+
end
|
19
|
+
{ "id" => row.first.to_s, "current_value" => row.last.to_s }.merge(timestamp)
|
15
20
|
}
|
16
21
|
elsif version == :v1
|
17
22
|
hash["datastreams"] = []
|
18
|
-
|
23
|
+
rows.first.each_with_index do |current_value, stream_id|
|
19
24
|
hash["datastreams"] << { "id" => stream_id.to_s, "current_value" => current_value }
|
20
25
|
end
|
21
26
|
end
|
@@ -25,10 +30,10 @@ module Cosm
|
|
25
30
|
|
26
31
|
private
|
27
32
|
|
28
|
-
def detect_version(
|
33
|
+
def detect_version(rows, version = nil)
|
29
34
|
return version if version
|
30
|
-
return :v2 if
|
31
|
-
return :v1 if
|
35
|
+
return :v2 if rows.size >= 2
|
36
|
+
return :v1 if rows.size == 1 && rows.first.size != 2
|
32
37
|
raise UnknownVersionError, "CSV Version could not be detected"
|
33
38
|
end
|
34
39
|
end
|
@@ -10,7 +10,7 @@ module Cosm
|
|
10
10
|
case hash['version']
|
11
11
|
when '1.0.0'
|
12
12
|
transform_1_0_0(hash)
|
13
|
-
when '0.6-alpha'
|
13
|
+
when '0.6-alpha', '0.6'
|
14
14
|
transform_0_6_alpha(hash)
|
15
15
|
end
|
16
16
|
end
|
@@ -59,30 +59,35 @@ module Cosm
|
|
59
59
|
def transform_0_6_alpha(hash)
|
60
60
|
hash["retrieved_at"] = hash["updated"]
|
61
61
|
hash["state"] = hash["status"]
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
if hash["datastreams"]
|
63
|
+
hash["datastreams"] = hash["datastreams"].collect do |datastream|
|
64
|
+
unit_hash = {}
|
65
|
+
if unit = datastream.delete('unit')
|
66
|
+
unit_hash['unit_type'] = unit['type']
|
67
|
+
unit_hash['unit_symbol'] = unit['symbol']
|
68
|
+
unit_hash['unit_label'] = unit['label']
|
69
|
+
end
|
70
|
+
value_hash = {}
|
71
|
+
if datastream["values"].size >= 1
|
72
|
+
value_hash["current_value"] = datastream["values"].first["value"]
|
73
|
+
value_hash["min_value"] = datastream["values"].first["min_value"]
|
74
|
+
value_hash["max_value"] = datastream["values"].first["max_value"]
|
75
|
+
value_hash["updated"] = datastream["values"].first["recorded_at"]
|
76
|
+
end
|
77
|
+
{
|
78
|
+
"id" => datastream["id"],
|
79
|
+
"tags" => join_tags(datastream["tags"]),
|
80
|
+
}.merge(value_hash).merge(unit_hash)
|
81
|
+
end
|
82
|
+
if location = hash.delete("location")
|
83
|
+
hash["location_disposition"] = location["disposition"]
|
84
|
+
hash["location_domain"] = location["domain"]
|
85
|
+
hash["location_ele"] = location["ele"]
|
86
|
+
hash["location_exposure"] = location["exposure"]
|
87
|
+
hash["location_lat"] = location["lat"]
|
88
|
+
hash["location_lon"] = location["lon"]
|
89
|
+
hash["location_name"] = location["name"]
|
68
90
|
end
|
69
|
-
{
|
70
|
-
"id" => datastream["id"],
|
71
|
-
"current_value" => datastream["values"].first["value"],
|
72
|
-
"min_value" => datastream["values"].first["min_value"],
|
73
|
-
"max_value" => datastream["values"].first["max_value"],
|
74
|
-
"updated" => datastream["values"].first["recorded_at"],
|
75
|
-
"tags" => join_tags(datastream["tags"]),
|
76
|
-
}.merge(unit_hash)
|
77
|
-
end
|
78
|
-
if location = hash.delete("location")
|
79
|
-
hash["location_disposition"] = location["disposition"]
|
80
|
-
hash["location_domain"] = location["domain"]
|
81
|
-
hash["location_ele"] = location["ele"]
|
82
|
-
hash["location_exposure"] = location["exposure"]
|
83
|
-
hash["location_lat"] = location["lat"]
|
84
|
-
hash["location_lon"] = location["lon"]
|
85
|
-
hash["location_name"] = location["name"]
|
86
91
|
end
|
87
92
|
hash
|
88
93
|
end
|
@@ -6,6 +6,7 @@ module Cosm
|
|
6
6
|
xml = Nokogiri.parse(xml)
|
7
7
|
hash = {}
|
8
8
|
environment = xml.at_xpath("//xmlns:environment")
|
9
|
+
raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
|
9
10
|
data = environment.at_xpath("xmlns:data")
|
10
11
|
datapoint = data.at_xpath("xmlns:datapoints")
|
11
12
|
value = datapoint.at_xpath("xmlns:value")
|
@@ -18,12 +18,13 @@ module Cosm
|
|
18
18
|
def transform_0_5_1(xml)
|
19
19
|
hash = {}
|
20
20
|
environment = xml.at_xpath("//xmlns:environment")
|
21
|
+
raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
|
21
22
|
data = environment.at_xpath("xmlns:data")
|
22
23
|
hash["feed_id"] = environment.attributes["id"].value
|
23
24
|
hash["feed_creator"] = environment.attributes["creator"].value
|
24
25
|
hash["id"] = data.attributes["id"].value
|
25
|
-
if (tags = data.xpath("xmlns:tag").collect
|
26
|
-
hash["tags"] = tags.sort{|a,b| a.downcase <=> b.downcase}.
|
26
|
+
if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
27
|
+
hash["tags"] = Cosm::CSV.generate_line(tags.sort{|a,b| a.downcase <=> b.downcase}).strip
|
27
28
|
end
|
28
29
|
current_value = data.at_xpath("xmlns:current_value")
|
29
30
|
hash["current_value"] = current_value.content
|
@@ -40,7 +41,7 @@ module Cosm
|
|
40
41
|
value = datapoint.at_xpath("xmlns:value")
|
41
42
|
{
|
42
43
|
"value" => value.content,
|
43
|
-
"at" => value.attributes["at"].
|
44
|
+
"at" => value.attributes["at"].value
|
44
45
|
}
|
45
46
|
end
|
46
47
|
hash
|
@@ -50,13 +51,14 @@ module Cosm
|
|
50
51
|
def transform_5(xml)
|
51
52
|
hash = {}
|
52
53
|
environment = xml.at_xpath("//xmlns:environment")
|
54
|
+
raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
|
53
55
|
data = environment.at_xpath("xmlns:data")
|
54
56
|
hash["feed_id"] = environment.attributes["id"].value
|
55
57
|
hash["feed_creator"] = "http://www.haque.co.uk"
|
56
58
|
hash["updated"] = environment.attributes["updated"].value
|
57
59
|
hash["id"] = data.attributes["id"].value
|
58
|
-
if (tags = data.xpath("xmlns:tag").collect
|
59
|
-
hash["tags"] = tags.sort{|a,b| a.downcase <=> b.downcase}.
|
60
|
+
if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
61
|
+
hash["tags"] = Cosm::CSV.generate_line(tags.sort{ |a,b| a.downcase <=> b.downcase }).strip
|
60
62
|
end
|
61
63
|
current_value = data.at_xpath("xmlns:value")
|
62
64
|
hash["current_value"] = current_value.content
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module Cosm
|
2
2
|
module Parsers
|
3
3
|
module XML
|
4
|
+
class InvalidXMLError < StandardError; end
|
4
5
|
module FeedDefaults
|
5
6
|
def from_xml(xml)
|
6
7
|
xml = Nokogiri.parse(xml)
|
7
8
|
case xml.root.attributes["version"].value
|
8
9
|
when "0.5.1"
|
9
10
|
transform_0_5_1(xml)
|
10
|
-
else
|
11
|
+
else
|
11
12
|
transform_5(xml)
|
12
13
|
end
|
13
14
|
end
|
@@ -16,60 +17,73 @@ module Cosm
|
|
16
17
|
def transform_0_5_1(xml)
|
17
18
|
hash = {}
|
18
19
|
environment = xml.at_xpath("//xmlns:environment")
|
20
|
+
raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
|
19
21
|
hash["updated"] = environment.attributes["updated"].value
|
20
22
|
hash["created"] = environment.attributes["created"].value
|
21
23
|
hash["creator"] = environment.attributes["creator"].value
|
22
|
-
hash["title"] = environment.at_xpath("xmlns:title").content
|
23
|
-
hash["feed"] = environment.at_xpath("xmlns:feed").content
|
24
|
-
hash["auto_feed_url"] = environment.at_xpath("xmlns:auto_feed_url").content
|
25
|
-
hash["status"] = environment.at_xpath("xmlns:status").content
|
26
|
-
hash["description"] = environment.at_xpath("xmlns:description").content
|
27
|
-
hash["icon"] = environment.at_xpath("xmlns:icon").content
|
28
|
-
hash["website"] = environment.at_xpath("xmlns:website").content
|
29
|
-
hash["email"] = environment.at_xpath("xmlns:email").content
|
30
|
-
hash["private"] = environment.at_xpath("xmlns:private").content
|
31
|
-
|
24
|
+
hash["title"] = strip(environment.at_xpath("xmlns:title").content)
|
25
|
+
hash["feed"] = strip(environment.at_xpath("xmlns:feed").content)
|
26
|
+
hash["auto_feed_url"] = strip(environment.at_xpath("xmlns:auto_feed_url").content)
|
27
|
+
hash["status"] = strip(environment.at_xpath("xmlns:status").content)
|
28
|
+
hash["description"] = strip(environment.at_xpath("xmlns:description").content)
|
29
|
+
hash["icon"] = strip(environment.at_xpath("xmlns:icon").content)
|
30
|
+
hash["website"] = strip(environment.at_xpath("xmlns:website").content)
|
31
|
+
hash["email"] = strip(environment.at_xpath("xmlns:email").content)
|
32
|
+
hash["private"] = strip(environment.at_xpath("xmlns:private").content)
|
33
|
+
if (tags = environment.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
34
|
+
hash["tags"] = Cosm::CSV.generate_line(tags.sort{|a,b| a.downcase <=> b.downcase}).strip
|
35
|
+
end
|
32
36
|
location = environment.at_xpath("xmlns:location")
|
33
37
|
if location
|
34
|
-
hash["location_name"] = location.at_xpath("xmlns:name").content
|
35
|
-
hash["location_lat"] = location.at_xpath("xmlns:lat").content
|
36
|
-
hash["location_lon"] = location.at_xpath("xmlns:lon").content
|
37
|
-
hash["location_ele"] = location.at_xpath("xmlns:ele").content
|
38
|
+
hash["location_name"] = strip(location.at_xpath("xmlns:name").content)
|
39
|
+
hash["location_lat"] = strip(location.at_xpath("xmlns:lat").content)
|
40
|
+
hash["location_lon"] = strip(location.at_xpath("xmlns:lon").content)
|
41
|
+
hash["location_ele"] = strip(location.at_xpath("xmlns:ele").content)
|
38
42
|
hash["location_domain"] = location.attributes["domain"].value
|
39
43
|
hash["location_exposure"] = location.attributes["exposure"].value
|
40
44
|
hash["location_disposition"] = location.attributes["disposition"].value
|
41
45
|
end
|
42
46
|
owner = environment.at_xpath("xmlns:user")
|
43
47
|
if owner
|
44
|
-
hash["owner_login"] = owner.at_xpath("xmlns:login").content
|
48
|
+
hash["owner_login"] = strip(owner.at_xpath("xmlns:login").content)
|
45
49
|
end
|
46
50
|
hash["datastreams"] = environment.xpath("xmlns:data").collect do |datastream|
|
47
51
|
current_value = datastream.at_xpath("xmlns:current_value")
|
52
|
+
if current_value
|
53
|
+
value_hash = {
|
54
|
+
"current_value" => strip(current_value.content),
|
55
|
+
"updated" => current_value.attributes["at"].value,
|
56
|
+
}
|
57
|
+
else
|
58
|
+
value_hash = {}
|
59
|
+
end
|
48
60
|
unit = datastream.at_xpath("xmlns:unit")
|
49
61
|
if unit
|
50
62
|
unit_hash = {
|
51
|
-
"unit_label" => unit.content,
|
63
|
+
"unit_label" => strip(unit.content),
|
52
64
|
"unit_type" => unit.attributes["type"].value,
|
53
65
|
"unit_symbol" => unit.attributes["symbol"].value,
|
54
66
|
}
|
55
67
|
else
|
56
68
|
unit_hash = {}
|
57
69
|
end
|
70
|
+
if (tags = datastream.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
71
|
+
tags_hash = { "tags" => Cosm::CSV.generate_line(tags.sort { |a, b| a.downcase <=> b.downcase }).strip }
|
72
|
+
else
|
73
|
+
tags_hash = {}
|
74
|
+
end
|
58
75
|
{
|
59
76
|
"id" => datastream.attributes["id"].value,
|
60
|
-
"
|
61
|
-
"
|
62
|
-
"updated" => current_value.attributes["at"].value,
|
63
|
-
"min_value" => datastream.at_xpath("xmlns:min_value").content,
|
64
|
-
"max_value" => datastream.at_xpath("xmlns:max_value").content,
|
77
|
+
"min_value" => strip(datastream.at_xpath("xmlns:min_value").content),
|
78
|
+
"max_value" => strip(datastream.at_xpath("xmlns:max_value").content),
|
65
79
|
"datapoints" => datastream.xpath("xmlns:datapoints").collect do |datapoint|
|
66
80
|
value = datapoint.at_xpath("xmlns:value")
|
67
81
|
{
|
68
82
|
"at" => value.attributes["at"].value,
|
69
|
-
"value" => value.content,
|
83
|
+
"value" => strip(value.content),
|
70
84
|
}
|
71
85
|
end
|
72
|
-
}.merge(unit_hash)
|
86
|
+
}.merge(value_hash).merge(unit_hash).merge(tags_hash)
|
73
87
|
end
|
74
88
|
hash
|
75
89
|
end
|
@@ -78,21 +92,22 @@ module Cosm
|
|
78
92
|
def transform_5(xml)
|
79
93
|
hash = {}
|
80
94
|
environment = xml.at_xpath("//xmlns:environment")
|
95
|
+
raise InvalidXMLError, "Missing 'environment' node from base node" if environment.nil?
|
81
96
|
hash["updated"] = environment.attributes["updated"].value
|
82
97
|
hash["creator"] = "http://www.haque.co.uk"
|
83
|
-
hash["title"] = environment.at_xpath("xmlns:title").content
|
84
|
-
hash["feed"] = environment.at_xpath("xmlns:feed").content
|
85
|
-
hash["status"] = environment.at_xpath("xmlns:status").content
|
86
|
-
hash["description"] = environment.at_xpath("xmlns:description").content
|
87
|
-
hash["icon"] = environment.at_xpath("xmlns:icon").content
|
88
|
-
hash["website"] = environment.at_xpath("xmlns:website").content
|
89
|
-
hash["email"] = environment.at_xpath("xmlns:email").content
|
98
|
+
hash["title"] = strip(environment.at_xpath("xmlns:title").content)
|
99
|
+
hash["feed"] = strip(environment.at_xpath("xmlns:feed").content)
|
100
|
+
hash["status"] = strip(environment.at_xpath("xmlns:status").content)
|
101
|
+
hash["description"] = strip(environment.at_xpath("xmlns:description").content)
|
102
|
+
hash["icon"] = strip(environment.at_xpath("xmlns:icon").content)
|
103
|
+
hash["website"] = strip(environment.at_xpath("xmlns:website").content)
|
104
|
+
hash["email"] = strip(environment.at_xpath("xmlns:email").content)
|
90
105
|
location = environment.at_xpath("xmlns:location")
|
91
106
|
if location
|
92
|
-
hash["location_name"] = location.at_xpath("xmlns:name").content
|
93
|
-
hash["location_lat"] = location.at_xpath("xmlns:lat").content
|
94
|
-
hash["location_lon"] = location.at_xpath("xmlns:lon").content
|
95
|
-
hash["location_ele"] = location.at_xpath("xmlns:ele").content
|
107
|
+
hash["location_name"] = strip(location.at_xpath("xmlns:name").content)
|
108
|
+
hash["location_lat"] = strip(location.at_xpath("xmlns:lat").content)
|
109
|
+
hash["location_lon"] = strip(location.at_xpath("xmlns:lon").content)
|
110
|
+
hash["location_ele"] = strip(location.at_xpath("xmlns:ele").content)
|
96
111
|
hash["location_domain"] = location.attributes["domain"].value
|
97
112
|
hash["location_exposure"] = location.attributes["exposure"].value
|
98
113
|
hash["location_disposition"] = location.attributes["disposition"].value
|
@@ -102,24 +117,33 @@ module Cosm
|
|
102
117
|
unit = datastream.at_xpath("xmlns:unit")
|
103
118
|
if unit
|
104
119
|
unit_hash = {
|
105
|
-
"unit_label" => unit.content,
|
120
|
+
"unit_label" => strip(unit.content),
|
106
121
|
"unit_type" => unit.attributes["type"].value,
|
107
122
|
"unit_symbol" => unit.attributes["symbol"].value,
|
108
123
|
}
|
109
124
|
else
|
110
125
|
unit_hash = {}
|
111
126
|
end
|
127
|
+
if (tags = datastream.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
128
|
+
tags_hash = { "tags" => Cosm::CSV.generate_line(tags.sort { |a, b| a.downcase <=> b.downcase }).strip }
|
129
|
+
else
|
130
|
+
tags_hash = {}
|
131
|
+
end
|
112
132
|
{
|
113
133
|
"id" => datastream.attributes["id"].value,
|
114
|
-
"
|
115
|
-
"current_value" => current_value.content,
|
134
|
+
"current_value" => strip(current_value.content),
|
116
135
|
"updated" => environment.attributes["updated"].value,
|
117
136
|
"min_value" => current_value.attributes["minValue"].value,
|
118
137
|
"max_value" => current_value.attributes["maxValue"].value,
|
119
|
-
}.merge(unit_hash)
|
138
|
+
}.merge(unit_hash).merge(tags_hash)
|
120
139
|
end
|
121
140
|
hash
|
122
141
|
end
|
142
|
+
|
143
|
+
def strip(value)
|
144
|
+
return value.nil? ? nil : value.strip
|
145
|
+
end
|
146
|
+
private :strip
|
123
147
|
end
|
124
148
|
end
|
125
149
|
end
|
@@ -6,13 +6,13 @@ module Cosm
|
|
6
6
|
options[:depth] = 4 if options[:full]
|
7
7
|
case options[:depth].to_i
|
8
8
|
when 4
|
9
|
-
::CSV.generate_line([feed_id, datastream_id, at.iso8601(6), value]).strip
|
9
|
+
Cosm::CSV.generate_line([feed_id, datastream_id, at.iso8601(6), value]).strip
|
10
10
|
when 3
|
11
|
-
::CSV.generate_line([datastream_id, at.iso8601(6), value]).strip
|
11
|
+
Cosm::CSV.generate_line([datastream_id, at.iso8601(6), value]).strip
|
12
12
|
when 2
|
13
|
-
::CSV.generate_line([at.iso8601(6), value]).strip
|
13
|
+
Cosm::CSV.generate_line([at.iso8601(6), value]).strip
|
14
14
|
else
|
15
|
-
::CSV.generate_line([value]).strip
|
15
|
+
Cosm::CSV.generate_line([value]).strip
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -30,11 +30,11 @@ module Cosm
|
|
30
30
|
datapoints.collect {|datapoint| csv << [datapoint.at.iso8601(6), datapoint.value] }
|
31
31
|
csv << [updated.iso8601(6), current_value] if csv.empty?
|
32
32
|
end
|
33
|
-
csv.collect {|row| ::CSV.generate_line(row).strip }.join("\n")
|
33
|
+
csv.collect {|row| Cosm::CSV.generate_line(row).strip }.join("\n")
|
34
34
|
end
|
35
35
|
|
36
36
|
def csv_1
|
37
|
-
::CSV.generate_line([current_value]).strip
|
37
|
+
Cosm::CSV.generate_line([current_value]).strip
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -18,9 +18,9 @@ module Cosm
|
|
18
18
|
if options[:full]
|
19
19
|
datastreams.collect do |datastream|
|
20
20
|
if datastream.datapoints.any?
|
21
|
-
datastream.datapoints.collect { |datapoint| csv << ::CSV.generate_line([id, datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
|
21
|
+
datastream.datapoints.collect { |datapoint| csv << Cosm::CSV.generate_line([id, datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
|
22
22
|
else
|
23
|
-
csv << ::CSV.generate_line([id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
23
|
+
csv << Cosm::CSV.generate_line([id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
24
24
|
end
|
25
25
|
|
26
26
|
|
@@ -28,9 +28,9 @@ module Cosm
|
|
28
28
|
else
|
29
29
|
datastreams.collect do |datastream|
|
30
30
|
if datastream.datapoints.any?
|
31
|
-
datastream.datapoints.collect { |datapoint| csv << ::CSV.generate_line([datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
|
31
|
+
datastream.datapoints.collect { |datapoint| csv << Cosm::CSV.generate_line([datastream.id, datapoint.at.iso8601(6), datapoint.value]).strip }
|
32
32
|
else
|
33
|
-
csv << ::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
33
|
+
csv << Cosm::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -38,7 +38,7 @@ module Cosm
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def csv_1
|
41
|
-
::CSV.generate_line(datastreams.collect {|ds| ds.current_value }).strip
|
41
|
+
Cosm::CSV.generate_line(datastreams.collect {|ds| ds.current_value }).strip
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/cosm-rb/version.rb
CHANGED
@@ -7,6 +7,28 @@ describe "default datastream csv parser" do
|
|
7
7
|
datastream = Cosm::Datastream.new(csv)
|
8
8
|
datastream.should fully_represent_datastream(:csv, csv)
|
9
9
|
end
|
10
|
+
|
11
|
+
it "should capture timestamp if present" do
|
12
|
+
timestamp = Time.now.iso8601(6)
|
13
|
+
csv = "#{timestamp},123"
|
14
|
+
datastream = Cosm::Datastream.new(csv)
|
15
|
+
datastream.updated.should == timestamp
|
16
|
+
datastream.current_value.should == "123"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise error if passed more than a single row" do
|
20
|
+
csv = "12\n13"
|
21
|
+
expect {
|
22
|
+
Cosm::Datastream.new(csv)
|
23
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise error passed more than three values in a row" do
|
27
|
+
csv = "#{Time.now.iso8601(6)},123,456"
|
28
|
+
expect {
|
29
|
+
Cosm::Datastream.new(csv)
|
30
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
31
|
+
end
|
10
32
|
end
|
11
33
|
end
|
12
34
|
|
@@ -8,6 +8,12 @@ describe "default feed csv parser" do
|
|
8
8
|
feed.should fully_represent_feed(:csv_v2, csv)
|
9
9
|
end
|
10
10
|
|
11
|
+
it "should convert no timestamp v2 CSV into attributes hash" do
|
12
|
+
csv = feed_as_(:csv, :version => 'v2_notimestamp')
|
13
|
+
feed = Cosm::Feed.new(csv)
|
14
|
+
feed.should fully_represent_feed(:csv_v2, csv)
|
15
|
+
end
|
16
|
+
|
11
17
|
it "should convert Pachube CSV v1 into attributes hash" do
|
12
18
|
csv = feed_as_(:csv, :version => 'v1')
|
13
19
|
feed = Cosm::Feed.new(csv)
|
@@ -30,6 +36,18 @@ describe "default feed csv parser" do
|
|
30
36
|
feed = Cosm::Feed.new(csv, :v1)
|
31
37
|
feed.should fully_represent_feed(:csv_v1, csv)
|
32
38
|
end
|
39
|
+
|
40
|
+
it "should raise an error if passed some wild csv with more than max permitted three columns" do
|
41
|
+
csv =<<-CSV
|
42
|
+
Date-Time, System HOA,Jockey Pump HOA,VFD Pump HOA,Lag Pump HOA,Lag Pump 2 HOA,Power Monitor,Water Level Relay,High Discharge Pressure,Reset Function,Jockey Running,VFD Run,Lag Pump Run,VFD Fault,Filter In Auto,Filter In Hand,Differential Press 1,Filter 1 Running,High Limit Switch,Low Limit Switch,Lag Pump Running,VFD Run Output Auto,VFD Pump On,Lag Pump,Lag Pump 1 On,System Auto Mode,Fault,Lag Pump 2 Run,Jockey On,Jockey Pump Run,Lag Pump 2,Filter Forward,Filter Reverse,Filter Solenoid,Pressure,Flow,Unknown?,VFD Input,VFD Output,
|
43
|
+
2009;Apr;19;12;44;15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
|
44
|
+
2009;Apr;19;12;44;30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
|
45
|
+
2009;Apr;19;12;48;52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
|
46
|
+
CSV
|
47
|
+
expect {
|
48
|
+
Cosm::Feed.new(csv)
|
49
|
+
}.to raise_error(Cosm::Parsers::CSV::InvalidCSVError)
|
50
|
+
end
|
33
51
|
end
|
34
52
|
end
|
35
53
|
|
@@ -13,6 +13,28 @@ describe "default feed json parser" do
|
|
13
13
|
feed = Cosm::Feed.new(json)
|
14
14
|
feed.should fully_represent_feed(:json, json)
|
15
15
|
end
|
16
|
+
|
17
|
+
it "should convert Pachube JSON 0.6-alpha (used by API v1) into attributes hash" do
|
18
|
+
json = feed_as_(:json, :version => "0.6")
|
19
|
+
feed = Cosm::Feed.new(json)
|
20
|
+
feed.should fully_represent_feed(:json, json)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should handle json if no value present" do
|
24
|
+
json = "{\"version\":\"0.6-alpha\",\"datastreams\":[{\"unit\":{\"label\":\"Tmax\",\"symbol\":\"C\"},\"values\":{},\"id\":\"1\"}]}"
|
25
|
+
expect {
|
26
|
+
feed = Cosm::Feed.new(json)
|
27
|
+
feed.datastreams.size.should == 1
|
28
|
+
}.to_not raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should capture empty fields if present" do
|
32
|
+
json = "{\"version\":\"1.0.0\",\"description\":\"\",\"feed\":\"\",\"location\":{\"name\":\"\"}}"
|
33
|
+
feed = Cosm::Feed.new(json)
|
34
|
+
feed.description.should == ""
|
35
|
+
feed.feed.should == ""
|
36
|
+
feed.location_name.should == ""
|
37
|
+
end
|
16
38
|
end
|
17
39
|
end
|
18
40
|
|
@@ -27,6 +27,38 @@ describe "default feed xml parser" do
|
|
27
27
|
Cosm::Feed.new(@xml).should fully_represent_feed(:xml, @xml)
|
28
28
|
end
|
29
29
|
|
30
|
+
it "should gracefully handle 0.5.1 xml missing the base environment node" do
|
31
|
+
xml = <<-EOXML
|
32
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
33
|
+
<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/005 http://www.eeml.org/xsd/005/005.xsd">
|
34
|
+
<title>ohai</title>
|
35
|
+
</eeml>
|
36
|
+
EOXML
|
37
|
+
expect {
|
38
|
+
Cosm::Feed.new(xml)
|
39
|
+
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should handle datastream with no current_value" do
|
43
|
+
xml = <<-EOXML
|
44
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
45
|
+
<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">
|
46
|
+
<environment updated="2011-02-16T16:21:01.834174Z" id="504" creator="http://test.host/users/fred">
|
47
|
+
<title>Cosm Office environment</title>
|
48
|
+
<data id="0">
|
49
|
+
<tag>freakin lasers</tag>
|
50
|
+
<tag>humidity</tag>
|
51
|
+
<tag>Temperature</tag>
|
52
|
+
</data>
|
53
|
+
</environment>
|
54
|
+
</eeml>
|
55
|
+
EOXML
|
56
|
+
|
57
|
+
feed = Cosm::Feed.new(xml)
|
58
|
+
feed.datastreams.size.should == 1
|
59
|
+
feed.datastreams.first.tags.should == "freakin lasers,humidity,Temperature"
|
60
|
+
end
|
61
|
+
|
30
62
|
end
|
31
63
|
|
32
64
|
context "5 (used by API v1)" do
|
@@ -57,9 +89,47 @@ describe "default feed xml parser" do
|
|
57
89
|
|
58
90
|
it "should handle missing value attributes" do
|
59
91
|
@xml = feed_as_(:xml, :version => "5", :except_node => :value_attributes)
|
92
|
+
feed = Cosm::Feed.new(@xml)
|
60
93
|
Cosm::Feed.new(@xml).should fully_represent_feed(:xml, @xml)
|
61
94
|
end
|
62
95
|
|
96
|
+
it "should gracefully handle 0.5.1 xml missing the base environment node" do
|
97
|
+
xml = <<-EOXML
|
98
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
99
|
+
<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">
|
100
|
+
<title>ohai</title>
|
101
|
+
</eeml>
|
102
|
+
EOXML
|
103
|
+
expect {
|
104
|
+
Cosm::Feed.new(xml)
|
105
|
+
}.to raise_error(Cosm::Parsers::XML::InvalidXMLError)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should gracefully handle our oddly whitespaced real example" do
|
109
|
+
xml = <<-EOXML
|
110
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
111
|
+
<eeml version="5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.eeml.org/xsd/005" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
|
112
|
+
<environment>
|
113
|
+
<data id="4773635294300160">
|
114
|
+
<tag>
|
115
|
+
10.F59894010800</tag>
|
116
|
+
<tag>
|
117
|
+
Living Room, S wall</tag>
|
118
|
+
<value>
|
119
|
+
24.1875</value>
|
120
|
+
<unit type="derivedSI">
|
121
|
+
celsius</unit>
|
122
|
+
</data>
|
123
|
+
</environment>
|
124
|
+
</eeml>
|
125
|
+
EOXML
|
126
|
+
feed = Cosm::Feed.new(xml)
|
127
|
+
|
128
|
+
datastream = feed.datastreams.first
|
129
|
+
datastream.tags.should == "10.F59894010800,\"Living Room, S wall\""
|
130
|
+
datastream.current_value.should == "24.1875"
|
131
|
+
datastream.unit_label.should == "celsius"
|
132
|
+
end
|
63
133
|
end
|
64
134
|
end
|
65
135
|
|
@@ -29,13 +29,13 @@ describe "default datapoint json templates" do
|
|
29
29
|
it "should escape stuff that could upset csv parsers" do
|
30
30
|
@datapoint.value = "I \n , am not a csv"
|
31
31
|
csv = @datapoint.generate_csv("2")
|
32
|
-
csv.should == CSV.generate_line([@datapoint.value]).strip
|
32
|
+
csv.should == Cosm::CSV.generate_line([@datapoint.value]).strip
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should escape characters that could upset csv parsers via full" do
|
36
36
|
@datapoint.value = "I \n , am not a csv"
|
37
37
|
csv = @datapoint.generate_csv("2", :full => true)
|
38
|
-
csv.should == CSV.generate_line([@datapoint.feed_id, @datapoint.datastream_id, @datapoint.at.iso8601(6), @datapoint.value]).strip
|
38
|
+
csv.should == Cosm::CSV.generate_line([@datapoint.feed_id, @datapoint.datastream_id, @datapoint.at.iso8601(6), @datapoint.value]).strip
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -85,7 +85,7 @@ describe "default datastream json templates" do
|
|
85
85
|
@datastream.current_value = "one,field"
|
86
86
|
@datastream.datapoints = []
|
87
87
|
csv = @datastream.generate_csv("2")
|
88
|
-
csv.should == CSV.generate_line([@datastream.updated.iso8601(6),@datastream.current_value]).strip
|
88
|
+
csv.should == Cosm::CSV.generate_line([@datastream.updated.iso8601(6),@datastream.current_value]).strip
|
89
89
|
end
|
90
90
|
|
91
91
|
it "should escape characters that could upset csv parsers with datapoints" do
|
@@ -94,14 +94,14 @@ describe "default datastream json templates" do
|
|
94
94
|
dp.value = "1,field"
|
95
95
|
end
|
96
96
|
csv = @datastream.generate_csv("2")
|
97
|
-
csv.should == @datastream.datapoints.collect {|dp| CSV.generate_line([dp.at.iso8601(6),dp.value]).strip }.join("\n")
|
97
|
+
csv.should == @datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([dp.at.iso8601(6),dp.value]).strip }.join("\n")
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should escape characters that could upset csv parsers without datapoints via full" do
|
101
101
|
@datastream.current_value = "one,field"
|
102
102
|
@datastream.datapoints = []
|
103
103
|
csv = @datastream.generate_csv("2", :full => true)
|
104
|
-
csv.should == CSV.generate_line([@datastream.feed_id,@datastream.id,@datastream.updated.iso8601(6),@datastream.current_value]).strip
|
104
|
+
csv.should == Cosm::CSV.generate_line([@datastream.feed_id,@datastream.id,@datastream.updated.iso8601(6),@datastream.current_value]).strip
|
105
105
|
end
|
106
106
|
|
107
107
|
it "should escape characters that could upset csv parsers with datapoints via full" do
|
@@ -110,7 +110,7 @@ describe "default datastream json templates" do
|
|
110
110
|
dp.value = "1,field"
|
111
111
|
end
|
112
112
|
csv = @datastream.generate_csv("2", :full => true)
|
113
|
-
csv.should == @datastream.datapoints.collect {|dp| CSV.generate_line([@datastream.feed_id,@datastream.id,dp.at.iso8601(6),dp.value]).strip }.join("\n")
|
113
|
+
csv.should == @datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([@datastream.feed_id,@datastream.id,dp.at.iso8601(6),dp.value]).strip }.join("\n")
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
@@ -124,7 +124,7 @@ describe "default datastream json templates" do
|
|
124
124
|
it "should escape characters that could upset csv parsers" do
|
125
125
|
@datastream.current_value = "I \n am full of c,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, evil"
|
126
126
|
csv = @datastream.generate_csv("1")
|
127
|
-
csv.should == CSV.generate_line([@datastream.current_value]).strip
|
127
|
+
csv.should == Cosm::CSV.generate_line([@datastream.current_value]).strip
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
@@ -22,7 +22,7 @@ describe "default feed json templates" do
|
|
22
22
|
end
|
23
23
|
csv = @feed.generate_csv("2")
|
24
24
|
expected_csv = @feed.datastreams.collect do |datastream|
|
25
|
-
CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
25
|
+
Cosm::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
26
26
|
end.join("\n")
|
27
27
|
csv.should == expected_csv
|
28
28
|
end
|
@@ -33,7 +33,7 @@ describe "default feed json templates" do
|
|
33
33
|
end
|
34
34
|
csv = @feed.generate_csv("2", :full => true)
|
35
35
|
expected_csv = @feed.datastreams.collect do |datastream|
|
36
|
-
CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
36
|
+
Cosm::CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
37
37
|
end.join("\n")
|
38
38
|
csv.should == expected_csv
|
39
39
|
end
|
@@ -42,9 +42,9 @@ describe "default feed json templates" do
|
|
42
42
|
csv = @feed.generate_csv("2")
|
43
43
|
expected_csv = @feed.datastreams.collect do |datastream|
|
44
44
|
if datastream.datapoints.any?
|
45
|
-
datastream.datapoints.collect {|dp| CSV.generate_line([datastream.id, dp.at.iso8601(6), dp.value]).strip }
|
45
|
+
datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([datastream.id, dp.at.iso8601(6), dp.value]).strip }
|
46
46
|
else
|
47
|
-
CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
47
|
+
Cosm::CSV.generate_line([datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
48
48
|
end
|
49
49
|
end.join("\n")
|
50
50
|
csv.should == expected_csv
|
@@ -54,9 +54,9 @@ describe "default feed json templates" do
|
|
54
54
|
csv = @feed.generate_csv("2", :full => true)
|
55
55
|
expected_csv = @feed.datastreams.collect do |datastream|
|
56
56
|
if datastream.datapoints.any?
|
57
|
-
datastream.datapoints.collect {|dp| CSV.generate_line([@feed.id, datastream.id, dp.at.iso8601(6), dp.value]).strip }
|
57
|
+
datastream.datapoints.collect {|dp| Cosm::CSV.generate_line([@feed.id, datastream.id, dp.at.iso8601(6), dp.value]).strip }
|
58
58
|
else
|
59
|
-
CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
59
|
+
Cosm::CSV.generate_line([@feed.id, datastream.id, datastream.updated.iso8601(6), datastream.current_value]).strip
|
60
60
|
end
|
61
61
|
end.join("\n")
|
62
62
|
csv.should == expected_csv
|
@@ -68,7 +68,7 @@ describe "default feed json templates" do
|
|
68
68
|
it "should represent Pachube JSON" do
|
69
69
|
csv = @feed.generate_csv("1")
|
70
70
|
expected_csv = @feed.datastreams.collect do |datastream|
|
71
|
-
CSV.generate_line([datastream.current_value]).strip
|
71
|
+
Cosm::CSV.generate_line([datastream.current_value]).strip
|
72
72
|
end.join(",")
|
73
73
|
csv.should == expected_csv
|
74
74
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,20 @@ require 'rspec'
|
|
5
5
|
|
6
6
|
require 'time'
|
7
7
|
|
8
|
+
if !defined?(JRUBY_VERSION)
|
9
|
+
if RUBY_VERSION < "1.9"
|
10
|
+
require 'ruby-debug'
|
11
|
+
else
|
12
|
+
if ENV["COVERAGE"] == "on"
|
13
|
+
require 'simplecov'
|
14
|
+
SimpleCov.start do
|
15
|
+
add_filter "/spec/"
|
16
|
+
add_filter "/lib/cosm-rb.rb"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
8
22
|
Dir['./spec/support/**/*.rb'].map {|f| require f}
|
9
23
|
|
10
24
|
$:.push File.expand_path("../lib", __FILE__)
|
data/spec/support/feed_helper.rb
CHANGED
@@ -159,6 +159,16 @@ def feed_as_csv(version)
|
|
159
159
|
4,2011-06-13T12:30:04.714629Z,0
|
160
160
|
5,2011-06-13T12:30:04.714629Z,0
|
161
161
|
6,2011-06-13T12:30:04.714629Z,-30362
|
162
|
+
}
|
163
|
+
when 'v2_notimestamp'
|
164
|
+
%Q{
|
165
|
+
0,15
|
166
|
+
1,905
|
167
|
+
2,326
|
168
|
+
3,0
|
169
|
+
4,0
|
170
|
+
5,0
|
171
|
+
6,-30362
|
162
172
|
}
|
163
173
|
when 'unknown'
|
164
174
|
'34,98'
|
@@ -265,7 +275,7 @@ def feed_as_json(version)
|
|
265
275
|
}
|
266
276
|
]
|
267
277
|
}
|
268
|
-
when "0.6-alpha"
|
278
|
+
when "0.6-alpha", "0.6"
|
269
279
|
{
|
270
280
|
"datastreams" => [{
|
271
281
|
"tags" => ["humidity"],
|
@@ -14,7 +14,7 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
|
|
14
14
|
end
|
15
15
|
|
16
16
|
failure_message_for_should do |feed|
|
17
|
-
"expected #{feed} to fully represent #{formatted_feed}"
|
17
|
+
"expected #{feed.attributes.inspect} to fully represent #{formatted_feed}"
|
18
18
|
end
|
19
19
|
|
20
20
|
description do
|
@@ -22,7 +22,7 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def match_csv_v1_feed(feed, formatted_feed)
|
25
|
-
csv = CSV.parse(formatted_feed.strip)
|
25
|
+
csv = Cosm::CSV.parse(formatted_feed.strip)
|
26
26
|
csv.length.should == 1
|
27
27
|
csv = csv.first
|
28
28
|
feed.datastreams.length.should == csv.length
|
@@ -33,11 +33,14 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def match_csv_v2_feed(feed, formatted_feed)
|
36
|
-
csv = CSV.parse(formatted_feed.strip)
|
36
|
+
csv = Cosm::CSV.parse(formatted_feed.strip)
|
37
37
|
feed.datastreams.length.should == csv.length
|
38
38
|
feed.datastreams.each do |datastream|
|
39
39
|
row = csv.detect {|d| d.first == datastream.id}
|
40
40
|
datastream.current_value.should == row.last
|
41
|
+
if row.size == 3
|
42
|
+
datastream.updated.iso8601.should == row[1]
|
43
|
+
end
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
@@ -60,7 +63,9 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
|
|
60
63
|
feed.website.should == environment.at_xpath("xmlns:website").content
|
61
64
|
feed.email.should == environment.at_xpath("xmlns:email").content
|
62
65
|
feed.private.should == environment.at_xpath("xmlns:private").content
|
63
|
-
feed.tags
|
66
|
+
if feed.tags
|
67
|
+
feed.tags.should == environment.xpath("xmlns:tag").map(&:content).sort{|a,b| a.downcase<=>b.downcase}.join(',')
|
68
|
+
end
|
64
69
|
owner = environment.at_xpath("xmlns:user")
|
65
70
|
if owner
|
66
71
|
feed.owner_login.should == owner.at_xpath("xmlns:login").content
|
@@ -78,7 +83,9 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
|
|
78
83
|
feed.datastreams.each do |ds|
|
79
84
|
data = environment.at_xpath("xmlns:data[@id=\"#{ds.id}\"]")
|
80
85
|
ds.id.should == data.attributes["id"].value
|
81
|
-
|
86
|
+
if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
87
|
+
ds.tags.should == tags.sort{|a,b| a.downcase<=>b.downcase}.join(',')
|
88
|
+
end
|
82
89
|
current_value = data.at_xpath("xmlns:current_value")
|
83
90
|
ds.current_value.should == current_value.content
|
84
91
|
ds.updated.should == current_value.attributes["at"].value
|
@@ -120,7 +127,9 @@ RSpec::Matchers.define :fully_represent_feed do |format, formatted_feed|
|
|
120
127
|
feed.datastreams.each do |ds|
|
121
128
|
data = environment.at_xpath("xmlns:data[@id=\"#{ds.id}\"]")
|
122
129
|
ds.id.should == data.attributes["id"].value
|
123
|
-
|
130
|
+
if (tags = data.xpath("xmlns:tag").collect { |t| t.content.strip }).any?
|
131
|
+
ds.tags.should == tags.sort{ |a,b| a.downcase <=> b.downcase }.join(',')
|
132
|
+
end
|
124
133
|
current_value = data.at_xpath("xmlns:value")
|
125
134
|
ds.current_value.should == current_value.content
|
126
135
|
ds.updated.should == environment.attributes["updated"].value
|
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
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Paul Bellamy
|
@@ -17,12 +17,9 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2012-
|
21
|
-
default_executable:
|
20
|
+
date: 2012-07-10 00:00:00 Z
|
22
21
|
dependencies:
|
23
22
|
- !ruby/object:Gem::Dependency
|
24
|
-
prerelease: false
|
25
|
-
type: :runtime
|
26
23
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
27
24
|
none: false
|
28
25
|
requirements:
|
@@ -34,11 +31,11 @@ dependencies:
|
|
34
31
|
- 8
|
35
32
|
- 1
|
36
33
|
version: 0.8.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
37
36
|
requirement: *id001
|
38
37
|
name: yajl-ruby
|
39
38
|
- !ruby/object:Gem::Dependency
|
40
|
-
prerelease: false
|
41
|
-
type: :runtime
|
42
39
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
43
40
|
none: false
|
44
41
|
requirements:
|
@@ -50,11 +47,11 @@ dependencies:
|
|
50
47
|
- 4
|
51
48
|
- 4
|
52
49
|
version: 1.4.4
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
53
52
|
requirement: *id002
|
54
53
|
name: nokogiri
|
55
54
|
- !ruby/object:Gem::Dependency
|
56
|
-
prerelease: false
|
57
|
-
type: :runtime
|
58
55
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
59
56
|
none: false
|
60
57
|
requirements:
|
@@ -66,12 +63,28 @@ dependencies:
|
|
66
63
|
- 8
|
67
64
|
- 3
|
68
65
|
version: 0.8.3
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
69
68
|
requirement: *id003
|
70
69
|
name: httparty
|
71
70
|
- !ruby/object:Gem::Dependency
|
72
|
-
prerelease: false
|
73
|
-
type: :development
|
74
71
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 121
|
77
|
+
segments:
|
78
|
+
- 1
|
79
|
+
- 5
|
80
|
+
- x
|
81
|
+
version: 1.5.x
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
requirement: *id004
|
85
|
+
name: fastercsv
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
75
88
|
none: false
|
76
89
|
requirements:
|
77
90
|
- - ">="
|
@@ -80,12 +93,12 @@ dependencies:
|
|
80
93
|
segments:
|
81
94
|
- 0
|
82
95
|
version: "0"
|
83
|
-
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
requirement: *id005
|
84
99
|
name: ruby-debug
|
85
100
|
- !ruby/object:Gem::Dependency
|
86
|
-
|
87
|
-
type: :development
|
88
|
-
version_requirements: &id005 !ruby/object:Gem::Requirement
|
101
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
89
102
|
none: false
|
90
103
|
requirements:
|
91
104
|
- - ">="
|
@@ -96,12 +109,12 @@ dependencies:
|
|
96
109
|
- 9
|
97
110
|
- 9
|
98
111
|
version: 0.9.9
|
99
|
-
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
requirement: *id006
|
100
115
|
name: rcov
|
101
116
|
- !ruby/object:Gem::Dependency
|
102
|
-
|
103
|
-
type: :development
|
104
|
-
version_requirements: &id006 !ruby/object:Gem::Requirement
|
117
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
105
118
|
none: false
|
106
119
|
requirements:
|
107
120
|
- - "="
|
@@ -112,12 +125,12 @@ dependencies:
|
|
112
125
|
- 8
|
113
126
|
- 7
|
114
127
|
version: 0.8.7
|
115
|
-
|
128
|
+
type: :development
|
129
|
+
prerelease: false
|
130
|
+
requirement: *id007
|
116
131
|
name: rake
|
117
132
|
- !ruby/object:Gem::Dependency
|
118
|
-
|
119
|
-
type: :development
|
120
|
-
version_requirements: &id007 !ruby/object:Gem::Requirement
|
133
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
121
134
|
none: false
|
122
135
|
requirements:
|
123
136
|
- - "="
|
@@ -128,7 +141,9 @@ dependencies:
|
|
128
141
|
- 6
|
129
142
|
- 0
|
130
143
|
version: 2.6.0
|
131
|
-
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
requirement: *id008
|
132
147
|
name: rspec
|
133
148
|
description: A library for communicating with the Cosm REST API, parsing and rendering Cosm feed formats
|
134
149
|
email:
|
@@ -265,7 +280,6 @@ files:
|
|
265
280
|
- spec/support/key_helper.rb
|
266
281
|
- spec/support/search_result_helper.rb
|
267
282
|
- spec/support/trigger_helper.rb
|
268
|
-
has_rdoc: true
|
269
283
|
homepage: http://github.com/cosm/cosm-rb
|
270
284
|
licenses: []
|
271
285
|
|
@@ -296,66 +310,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
296
310
|
requirements: []
|
297
311
|
|
298
312
|
rubyforge_project:
|
299
|
-
rubygems_version: 1.
|
313
|
+
rubygems_version: 1.8.22
|
300
314
|
signing_key:
|
301
315
|
specification_version: 3
|
302
316
|
summary: A library for communicating with the Cosm REST API, parsing and rendering Cosm feed formats
|
303
|
-
test_files:
|
304
|
-
|
305
|
-
- spec/cosm-rb/base/instance_methods_spec.rb
|
306
|
-
- spec/cosm-rb/base_spec.rb
|
307
|
-
- spec/cosm-rb/client_spec.rb
|
308
|
-
- spec/cosm-rb/datapoint_spec.rb
|
309
|
-
- spec/cosm-rb/datastream_spec.rb
|
310
|
-
- spec/cosm-rb/feed_spec.rb
|
311
|
-
- spec/cosm-rb/hash_extensions_spec.rb
|
312
|
-
- spec/cosm-rb/helpers_spec.rb
|
313
|
-
- spec/cosm-rb/key_spec.rb
|
314
|
-
- spec/cosm-rb/parsers/csv/datastream_defaults_spec.rb
|
315
|
-
- spec/cosm-rb/parsers/csv/feed_defaults_spec.rb
|
316
|
-
- spec/cosm-rb/parsers/json/datapoint_defaults_spec.rb
|
317
|
-
- spec/cosm-rb/parsers/json/datastream_defaults_spec.rb
|
318
|
-
- spec/cosm-rb/parsers/json/feed_defaults_spec.rb
|
319
|
-
- spec/cosm-rb/parsers/json/key_defaults_spec.rb
|
320
|
-
- spec/cosm-rb/parsers/json/search_result_defaults_spec.rb
|
321
|
-
- spec/cosm-rb/parsers/json/trigger_defaults_spec.rb
|
322
|
-
- spec/cosm-rb/parsers/xml/datapoint_defaults_spec.rb
|
323
|
-
- spec/cosm-rb/parsers/xml/datastream_defaults_spec.rb
|
324
|
-
- spec/cosm-rb/parsers/xml/feed_defaults_spec.rb
|
325
|
-
- spec/cosm-rb/parsers/xml/key_defaults_spec.rb
|
326
|
-
- spec/cosm-rb/parsers/xml/trigger_defaults_spec.rb
|
327
|
-
- spec/cosm-rb/search_result_spec.rb
|
328
|
-
- spec/cosm-rb/string_extensions_spec.rb
|
329
|
-
- spec/cosm-rb/template_spec.rb
|
330
|
-
- spec/cosm-rb/templates/csv/datapoint_defaults_spec.rb
|
331
|
-
- spec/cosm-rb/templates/csv/datastream_defaults_spec.rb
|
332
|
-
- spec/cosm-rb/templates/csv/feed_defaults_spec.rb
|
333
|
-
- spec/cosm-rb/templates/json/datapoint_defaults_spec.rb
|
334
|
-
- spec/cosm-rb/templates/json/datastream_defaults_spec.rb
|
335
|
-
- spec/cosm-rb/templates/json/feed_defaults_spec.rb
|
336
|
-
- spec/cosm-rb/templates/json/key_defaults_spec.rb
|
337
|
-
- spec/cosm-rb/templates/json/search_result_defaults_spec.rb
|
338
|
-
- spec/cosm-rb/templates/json/trigger_defaults_spec.rb
|
339
|
-
- spec/cosm-rb/templates/xml/datapoint_defaults_spec.rb
|
340
|
-
- spec/cosm-rb/templates/xml/datastream_defaults_spec.rb
|
341
|
-
- spec/cosm-rb/templates/xml/feed_defaults_spec.rb
|
342
|
-
- spec/cosm-rb/templates/xml/search_result_defaults_spec.rb
|
343
|
-
- spec/cosm-rb/trigger_spec.rb
|
344
|
-
- spec/fixtures/models.rb
|
345
|
-
- spec/spec_helper.rb
|
346
|
-
- spec/support/contain_datapoint_eeml_matcher.rb
|
347
|
-
- spec/support/contain_datastream_eeml_matcher.rb
|
348
|
-
- spec/support/contain_feed_eeml_matcher.rb
|
349
|
-
- spec/support/datapoint_helper.rb
|
350
|
-
- spec/support/datastream_helper.rb
|
351
|
-
- spec/support/describe_eeml_matcher.rb
|
352
|
-
- spec/support/feed_helper.rb
|
353
|
-
- spec/support/fully_represent_datapoint_matcher.rb
|
354
|
-
- spec/support/fully_represent_datastream_matcher.rb
|
355
|
-
- spec/support/fully_represent_feed_matcher.rb
|
356
|
-
- spec/support/fully_represent_key_matcher.rb
|
357
|
-
- spec/support/fully_represent_search_result_matcher.rb
|
358
|
-
- spec/support/fully_represent_trigger_matcher.rb
|
359
|
-
- spec/support/key_helper.rb
|
360
|
-
- spec/support/search_result_helper.rb
|
361
|
-
- spec/support/trigger_helper.rb
|
317
|
+
test_files: []
|
318
|
+
|