quandl_operation 0.1.18 → 0.1.19

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87874fab0a0c7090d8a8d659e7492ff91fe7e98b
4
- data.tar.gz: 0ea2c0c04aa165ba162eeeea6473da15dc6565c6
3
+ metadata.gz: 21f4883192fd7504a13a091e6215b64d839359f8
4
+ data.tar.gz: 542095e6c669ebb97ac8c34543e40011a95847d2
5
5
  SHA512:
6
- metadata.gz: 597a729a3f03e538c4876bfa0ab3fdbb56fe309bae13f3348c8cd1312c3548ca77a051981aaca5858b9bcf566114768792195457aff332e251258fceb4baf9a4
7
- data.tar.gz: f7ccf8150ee7f1ee3ad1161f6f3c18b9cb40276d093bb4d117b9db059081d4052454611f4d049404266c449912bb913a4818f3b9ece52b663cfa29a2137ce572
6
+ metadata.gz: b3163d4f4952ddded01c8d8bbeab2c2680fadd9ef451728397ce90e0e49d71734a82153ca0b8e72e977ddf2536fe9969620ca9ba4092aae2ed46023220f8e331
7
+ data.tar.gz: 10e238077f7a8e08010ccc28561709451cd319b4cbd7e2a871c208b959350e0f92227de42d87d2dba5c2e6d11d469bd32a57f344c7adf04b014c5ef9f385d7bd
@@ -1,126 +1,24 @@
1
+ require 'csv'
2
+ require 'yaml'
3
+
4
+ require 'quandl/operation/qdformat/dump'
5
+ require 'quandl/operation/qdformat/load'
6
+ require 'quandl/operation/qdformat/node'
7
+
1
8
  class Quandl::Operation::QDFormat
2
-
3
- attr_accessor :source_code, :code, :name, :description, :data, :headers
4
-
5
9
  class << self
6
10
 
7
- def read(path)
8
- parse(File.read(path).strip)
9
- end
10
-
11
- def parse(output)
12
- datasets = []
13
- attributes = {}
14
- # for each line
15
- output.each_line do |line|
16
- # strip whitespace
17
- line = line.strip.rstrip
18
-
19
- # skip blank
20
- if line.blank?
21
- next
22
-
23
- # - denotes new dataset
24
- elsif line[0] == '-'
25
- # append current dataset
26
- datasets << attributes unless attributes.blank?
27
- # reset attributes for next dataset
28
- attributes = {}
29
-
30
- # without the data key we're still adding metadata
31
- elsif !attributes.has_key?(:data)
32
- # for each rule
33
- matched = false
34
- rules.each do |name, rule|
35
- # test line
36
- m = line.match(rule)
37
- # if the rule matches
38
- if !matched && m.present?
39
- matched = true
40
- case name
41
- when :full_code then attributes[:full_code] = line
42
- when :attribute then attributes[m[1].to_sym] = m[2]
43
- end
44
- end
45
- end
46
- # if no match was found for this line it must be data
47
- attributes[:data] = line if !matched
48
- # otherwise we're adding data
49
- else
50
- attributes[:data] += "\n" + line
51
- end
52
- end
53
- datasets << attributes unless attributes.blank?
54
- datasets.collect{|attrs| self.new(attrs) }
11
+ def load(input)
12
+ Quandl::Operation::QDFormat::Load.from_string(input)
55
13
  end
56
14
 
57
- def rules
58
- {
59
- full_code: /^([A-Z0-9_]+)\/([A-Z0-9_]+)$/,
60
- attribute: /^([a-z0-9_]+): (.+)/
61
- }
62
- end
63
-
64
- end
65
-
66
- def initialize(attrs)
67
- assign_attributes(attrs)
68
- end
69
-
70
- def assign_attributes(attrs)
71
- attrs.each do |key, value|
72
- self.send("#{key}=", value) if self.respond_to?(key)
15
+ def load_file(file_path)
16
+ Quandl::Operation::QDFormat::Load.from_file(input)
73
17
  end
74
- end
75
-
76
- def attributes
77
- { name: name, source_code: source_code, code: code, description: description, column_names: headers, data: data }
78
- end
79
-
80
- def inspect
81
- "<##{self.class.name}" +
82
- [:full_code, :name, :description, :headers].inject({}){|m,k| m[k] = self.send(k); m }.to_s +
83
- " >"
84
- end
85
-
86
- def headers=(names)
87
- names = names.split(",").collect(&:strip) if names.is_a?(String)
88
- @headers = Array(names).flatten
89
- end
90
- def headers_as_qdf
91
- headers.join(', ') if headers.is_a?(Array)
92
- end
93
-
94
- def full_code=(value)
95
- value = value.split('/')
96
- self.source_code = value[0]
97
- self.code = value[1]
98
- end
99
-
100
- def full_code
101
- [source_code, code].join('/')
102
- end
103
-
104
- def data_as_qdf
105
- o = data
106
- o = o.to_a if o.respond_to?(:to_a)
107
- o = o.collect(&:to_csv).join if o.respond_to?(:to_csv) && o.first.is_a?(Array)
108
- o = o.to_csv if o.respond_to?(:to_csv)
109
- o
110
- end
111
-
112
- def data=(rows)
113
- @data = rows
114
- end
115
-
116
- def to_qdf
117
- output = [full_code]
118
- [:name, :description].each do |attr_name|
119
- output << "#{attr_name}: #{self.send(attr_name)}" if self.send(attr_name).present?
18
+
19
+ def dump(nodes)
20
+ Quandl::Operation::QDFormat::Dump.nodes(nodes)
120
21
  end
121
- output << "headers: #{headers_as_qdf}" if headers_as_qdf.present?
122
- output << data_as_qdf
123
- output.join("\n")
22
+
124
23
  end
125
-
126
24
  end
@@ -0,0 +1,49 @@
1
+ module Quandl
2
+ module Operation
3
+ class QDFormat
4
+
5
+ class Dump
6
+
7
+ class << self
8
+
9
+ def nodes(*args)
10
+ Array(args).flatten.collect{|r| node(r) }.join("\n")
11
+ end
12
+
13
+ def node(node)
14
+ self.new(node).to_qdf
15
+ end
16
+
17
+ end
18
+
19
+ attr_accessor :node
20
+
21
+ def initialize(r)
22
+ self.node = r
23
+ end
24
+
25
+ def to_qdf
26
+ [attributes, column_names, data].compact.join
27
+ end
28
+
29
+ def attributes
30
+ [:source_code, :code, :name, :description].
31
+ inject({}){|m,k| m[k.to_s] = node.send(k) unless node.send(k).blank?; m }.
32
+ to_yaml[4..-1]
33
+ end
34
+
35
+ def data
36
+ data = node.data.is_a?(Array) ? node.data.collect(&:to_csv).join : node.data
37
+ data = data.to_csv if data.respond_to?(:to_csv)
38
+ data
39
+ end
40
+
41
+ def column_names
42
+ node.column_names.to_csv if node.column_names.present?
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ class Quandl::Operation::QDFormat::Load
2
+
3
+ class << self
4
+
5
+ def from_file(path)
6
+ from_string(File.read(path).strip)
7
+ end
8
+
9
+ def from_string(input)
10
+ nodes = []
11
+ input.each_line do |line|
12
+ # strip whitespace
13
+ line = line.strip.rstrip
14
+ # ignore comments and blank lines
15
+ next if line[0] == '#' || line.blank?
16
+ # code_format denotes the start of a new node
17
+ nodes << { attributes: '', data: '' } if line =~ code_format
18
+ # attribute_format denotes an attribute
19
+ if line =~ attribute_format
20
+ # add the attribute to attributes
21
+ nodes[-1][:attributes] += "#{line}\n"
22
+ # otherwise it must be data
23
+ else
24
+ nodes[-1][:data] += "#{line}\n"
25
+ end
26
+ end
27
+ # append the current node
28
+ nodes = parse_nodes(nodes)
29
+ nodes
30
+ end
31
+
32
+
33
+ protected
34
+
35
+ def parse_nodes(nodes)
36
+ nodes.collect do |node|
37
+ node[:attributes] = YAML.load( node[:attributes] )
38
+ node[:attributes][:data] = CSV.parse(node[:data])
39
+ Quandl::Operation::QDFormat::Node.new(node[:attributes])
40
+ end
41
+ end
42
+
43
+ def code_format
44
+ /^code: (.+)/
45
+ end
46
+
47
+ def attribute_format
48
+ /^([a-z0-9_]+): (.+)/
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,49 @@
1
+ class Quandl::Operation::QDFormat::Node
2
+
3
+ ATTRIBUTES = :source_code, :code, :name, :description, :column_names
4
+ attr_accessor *ATTRIBUTES
5
+
6
+ attr_accessor :data
7
+
8
+ def initialize(attrs)
9
+ assign_attributes(attrs)
10
+ end
11
+
12
+ def assign_attributes(attrs)
13
+ attrs.each do |key, value|
14
+ self.send("#{key}=", value) if self.respond_to?(key)
15
+ end
16
+ end
17
+
18
+ def attributes
19
+ ATTRIBUTES.inject({}){|m,k| m[k] = self.send(k); m }
20
+ end
21
+
22
+ def inspect
23
+ "<##{self.class.name} #{attributes.to_s} >"
24
+ end
25
+
26
+ def full_code=(value)
27
+ value = value.split('/')
28
+ self.source_code = value[0]
29
+ self.code = value[1]
30
+ end
31
+
32
+ def full_code
33
+ [source_code, code].join('/')
34
+ end
35
+
36
+ def data=(rows)
37
+ self.column_names = rows.shift unless rows.first.collect{|r| r.to_s.numeric? }.include?(true)
38
+ @data = rows
39
+ end
40
+
41
+ def column_names=(names)
42
+ @column_names = Array(names).flatten.collect{|n| n.strip.rstrip }
43
+ end
44
+
45
+ def to_qdf
46
+ Quandl::Operation::QDFormat::Dump.node(self)
47
+ end
48
+
49
+ end
@@ -1,5 +1,5 @@
1
1
  module Quandl
2
2
  module Operation
3
- VERSION = "0.1.18"
3
+ VERSION = "0.1.19"
4
4
  end
5
5
  end
@@ -4,61 +4,71 @@ require 'spec_helper'
4
4
 
5
5
  describe Quandl::Operation::QDFormat do
6
6
 
7
- let(:full_code){ "SOURCE_CODE/DATASET_CODE" }
8
- let(:name){ 'name: Test dataset name' }
9
- let(:description){ 'description: Dataset description' }
10
- let(:headers){ 'headers: Date, value, high, low' }
11
- let(:data){ "2013-11-20,9.99470588235294,11.003235294117646,14.00164705882353\n2013-11-19,10.039388096885814,,14.09718770934256\n2013-11-18,10.03702588792184,11.040801329322205,14.148600982164867\n2013-11-16,10.019903902583621,10.99988541851354,14.186053161235304\n2013-11-15,9.98453953586862,10.922239168500502,\n2013-11-14,10.004508614940358,10.894612328250766,\n2013-11-13,,10.877309120435308,14.187437960548612\n2013-11-12,,10.838918617657301,14.22499294338536\n2013-11-11,9.965116185761039,10.827442115591547,14.178970907392053\n2013-11-09,9.881291973139637,10.924889094631869" }
12
-
13
- let(:output){
7
+ let(:qdf_dataset){
14
8
  %Q{
15
- ---
16
- #{full_code}
17
- #{name}
18
- #{description}
19
- #{headers}
20
- #{data}
21
- -
22
- - I am a comment.
23
- -
24
- #{full_code}
25
- #{name}
26
- #{description}
27
- #{headers}
28
- #{data}
29
- -----
9
+ # YAML metadata
10
+ code: DATASET_CODE
11
+ source_code: SOURCE_CODE
12
+ name: Test Dataset Name 1
13
+ description: Here is a description with multiple lines.\\n This is the second line.
14
+ # CSV data
15
+ Date, Value, High, Low
16
+ 2013-11-20,9.99470588235294,11.003235294117646,14.00164705882353
17
+ 2013-11-19,10.039388096885814,,14.09718770934256
18
+
19
+ # Second dataset
20
+ code: DATASET_CODE_2
21
+ source_code: SOURCE_CODE_2
22
+ name: Test Dataset Name 2
23
+ description: Here is a description with multiple lines.
24
+ # CSV data
25
+ Date, Value, High, Low
26
+ 2013-11-20,9.99470588235294,11.003235294117646,14.00164705882353
27
+ 2013-11-19,10.039388096885814,,14.09718770934256
28
+ 2013-11-18,11.039388096885814,,15.09718770934256
30
29
  }
31
30
  }
32
- let(:collection){ Quandl::Operation::QDFormat.parse(output) }
33
31
 
34
- describe ".parse" do
32
+ let(:collection){ Quandl::Operation::QDFormat.load(qdf_dataset) }
33
+
34
+ describe ".load" do
35
35
 
36
36
  subject{ collection }
37
-
37
+
38
38
  its(:count){ should eq 2 }
39
39
 
40
40
  describe "#first" do
41
41
  subject{ collection.first }
42
42
 
43
- it{ should be_a Quandl::Operation::QDFormat }
43
+ it{ should be_a Quandl::Operation::QDFormat::Node }
44
44
  its(:source_code){ should eq 'SOURCE_CODE' }
45
45
  its(:code){ should eq 'DATASET_CODE' }
46
- its(:name){ should eq 'Test dataset name' }
47
- its(:description){ should eq 'Dataset description' }
48
- its(:headers){ should eq ['Date', 'value', 'high', 'low'] }
49
- its(:data){ should eq data }
46
+ its(:name){ should eq 'Test Dataset Name 1' }
47
+ its(:description){ should eq 'Here is a description with multiple lines.\n This is the second line.' }
48
+ its(:column_names){ should eq ['Date', 'Value', 'High', 'Low'] }
49
+ its(:data){ should eq [
50
+ ["2013-11-20", "9.99470588235294", "11.003235294117646", "14.00164705882353"],
51
+ ["2013-11-19", "10.039388096885814", nil, "14.09718770934256"]] }
50
52
  end
51
53
  end
52
54
 
53
55
  describe "#to_qdf" do
54
56
  subject{ collection.first }
55
- its(:to_qdf){ should eq [full_code, name, description, headers, data].join("\n")}
57
+
58
+ its(:to_qdf){ should eq %Q{source_code: SOURCE_CODE
59
+ code: DATASET_CODE
60
+ name: Test Dataset Name 1
61
+ description: Here is a description with multiple lines.\\n This is the second line.
62
+ Date,Value,High,Low
63
+ 2013-11-20,9.99470588235294,11.003235294117646,14.00164705882353
64
+ 2013-11-19,10.039388096885814,,14.09718770934256
65
+ }}
56
66
 
57
67
  context "data Array" do
58
68
  let(:data){ [['2013-11-20',9.94,11.2],['2013-11-19',9.94,11.2],['2013-11-18',9.94,11.2]] }
59
- subject{ Quandl::Operation::QDFormat.new( full_code: "TEST/OIL", data: data ) }
69
+ subject{ Quandl::Operation::QDFormat::Node.new( full_code: "TEST/OIL", data: data ) }
60
70
 
61
- its(:to_qdf){ should eq ["TEST/OIL", data.collect(&:to_csv).join].join("\n") }
71
+ its(:to_qdf){ should eq "source_code: TEST\ncode: OIL\n2013-11-20,9.94,11.2\n2013-11-19,9.94,11.2\n2013-11-18,9.94,11.2\n" }
62
72
 
63
73
  end
64
74
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quandl_operation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.18
4
+ version: 0.1.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Hilscher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-21 00:00:00.000000000 Z
11
+ date: 2013-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -149,6 +149,9 @@ files:
149
149
  - lib/quandl/operation/core_ext/time.rb
150
150
  - lib/quandl/operation/parse.rb
151
151
  - lib/quandl/operation/qdformat.rb
152
+ - lib/quandl/operation/qdformat/dump.rb
153
+ - lib/quandl/operation/qdformat/load.rb
154
+ - lib/quandl/operation/qdformat/node.rb
152
155
  - lib/quandl/operation/transform.rb
153
156
  - lib/quandl/operation/version.rb
154
157
  - quandl_operation.gemspec