quandl_operation 0.1.18 → 0.1.19

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.
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