eod_data 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3ef51eae22119172e8e9e2b4559601bff4e3d2be
4
+ data.tar.gz: 20607e6d872aee0e4405c2977700a65c75ef57dc
5
+ SHA512:
6
+ metadata.gz: 34f9c4660ef83922bd85dfe0492985bdcfd0c50f39b4b9695da323c900d0a026e0251886ee0a6624ecb08195288cc483ba355e8307bd7df55e984393d4cce35b
7
+ data.tar.gz: f321b0f6b461c368128418108f7ecd73ae296b5dace6e8dd8898160a376d9be32402cd297afea2a5eb592a02f254309906fb0e1de10d1f2c58dec013faeecb06
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in eod_data.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Roy Ratcliffe
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # EodData
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'eod_data'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install eod_data
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/eod_data/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+ task default: :spec
data/eod_data.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'eod_data/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'eod_data'
8
+ spec.version = EodData::VERSION
9
+ spec.authors = ['Roy Ratcliffe']
10
+ spec.email = ['roy@pioneeringsoftware.co.uk']
11
+ spec.summary = %q{}
12
+ spec.description = %q{}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'nokogiri'
22
+ spec.add_runtime_dependency 'activesupport'
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'teamcity-ruby-client'
27
+ end
data/lib/eod_data.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'eod_data/version'
2
+ require 'eod_data/web_service'
3
+
4
+ module EodData
5
+ end
@@ -0,0 +1,3 @@
1
+ module EodData
2
+ VERSION = '0.2.0'
3
+ end
@@ -0,0 +1,3 @@
1
+ module EodData
2
+ class WebError < StandardError; end
3
+ end
@@ -0,0 +1,53 @@
1
+ require 'active_support/core_ext/string'
2
+
3
+ module EodData
4
+ # Represents an XML response from EODData, encapsulates the XML root element.
5
+ class WebResponse
6
+ attr_writer :root
7
+
8
+ # The XML root element should have the name RESPONSE or LOGINRESPONSE, or
9
+ # for that matter anything ending with RESPONSE. LOGINRESPONSE applies to
10
+ # token-access responses.
11
+ def initialize(root)
12
+ raise WebError, "Invalid response name #{root.name}" unless root.name.end_with?('RESPONSE')
13
+ @root = root
14
+ end
15
+
16
+ def name
17
+ @root.name
18
+ end
19
+
20
+ # Collects elements at +path+ whose element name matches +name+; where the
21
+ # name defaults to the path in singular, e.g. path at ITEMS, collecting
22
+ # elements by name ITEM. The answer is an array of hashes.
23
+ def elements_at(path, name=path.singularize)
24
+ @root.at(path).elements.select do |element|
25
+ element.name == name
26
+ end.map do |element|
27
+ hash = {}
28
+ element.attribute_nodes.each do |attr|
29
+ hash[attr.name.underscore.to_sym] = attr.content
30
+ end
31
+ hash
32
+ end
33
+ end
34
+
35
+ def respond_to?(symbol)
36
+ return true if symbol.to_s.end_with?('_string')
37
+ return true if symbol.to_s.end_with?('_text')
38
+ return true if symbol.to_s.end_with?('s')
39
+ super
40
+ end
41
+
42
+ private
43
+
44
+ # Sending method +something_string+ looks for attribute +something+ and
45
+ # answers its value.
46
+ def method_missing(symbol, *args)
47
+ return @root.attribute(symbol.to_s.sub(/_string$/, '').capitalize).to_s if symbol.to_s.end_with?('_string')
48
+ return @root.at(symbol.to_s.sub(/_text$/, '').upcase).text if symbol.to_s.end_with?('_text')
49
+ return elements_at(symbol.to_s.sub(/_/, '').upcase) if symbol.to_s.end_with?('s')
50
+ super
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,220 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'nokogiri'
4
+
5
+ require 'eod_data/web_response'
6
+ require 'eod_data/web_error'
7
+
8
+ class Hash
9
+ def convert_string_values!(type_and_keys = {})
10
+ type_and_keys.each do |type, keys|
11
+ keys.each do |key|
12
+ value = fetch(key)
13
+ case value
14
+ when String
15
+ store(key, case type
16
+ when :date_time
17
+ DateTime.parse(value)
18
+ when :integer
19
+ value.to_i
20
+ when :boolean
21
+ value.casecmp('true') == 0 || value.casecmp('yes') == 0
22
+ else
23
+ value
24
+ end)
25
+ end
26
+ end
27
+ end
28
+ self
29
+ end
30
+ end
31
+
32
+ module EodData
33
+ class WebService
34
+ URI_BASE = 'http://ws.eoddata.com/data.asmx/'
35
+
36
+ def membership
37
+ post_with_token('Membership', &raise_block_unless_success).membership_text
38
+ end
39
+
40
+ # Answers the number of months of history that EODData authorises for the
41
+ # user to download. Use the following block of Ruby code to collect the
42
+ # number of authorised months for all the available exchanges, where
43
+ # +service+ is an EodData::WebService instance.
44
+ #
45
+ # service.exchange_list.collect do |exchange|
46
+ # exchange[:code]
47
+ # end.collect do |code|
48
+ # service.exchange_months(code)
49
+ # end
50
+ #
51
+ def exchange_months(exchange)
52
+ post_with_token('ExchangeMonths',
53
+ {
54
+ 'Exchange' => exchange
55
+ },
56
+ &raise_block_unless_success).months_text.to_i
57
+ end
58
+
59
+ # Answers an array of exchanges represented as hashes. Each hash has the
60
+ # following symbol keys, with their values automatically converted to
61
+ # appropriate types: date-times, integers and booleans.
62
+ #
63
+ # :code
64
+ # :name
65
+ # :last_trade_date_time
66
+ # :country
67
+ # :currency
68
+ # :advances
69
+ # :declines
70
+ # :suffix
71
+ # :time_zone
72
+ # :is_intraday
73
+ # :intraday_start_date
74
+ # :has_intraday_product
75
+ #
76
+ def exchange_list
77
+ post_with_token('ExchangeList', &raise_block_unless_success).exchanges.map do |exchange|
78
+ exchange.convert_string_values!(
79
+ date_time: %w(last_trade_date_time intraday_start_date).map(&:to_sym),
80
+ integer: %w(advances declines).map(&:to_sym),
81
+ boolean: %w(is_intraday has_intraday_product).map(&:to_sym),
82
+ )
83
+ end
84
+ end
85
+
86
+ def symbol_list(exchange)
87
+ post_with_token('SymbolList',
88
+ {
89
+ 'Exchange' => exchange
90
+ },
91
+ &raise_block_unless_success).symbols.map do |symbol|
92
+ symbol.convert_string_values!(
93
+ date_time: %w(date_time).map(&:to_sym)
94
+ )
95
+ end
96
+ end
97
+
98
+ # Symbol changes have keys:
99
+ #
100
+ # :date_time
101
+ # :old_symbol
102
+ # :new_symbol
103
+ # :exchange_code
104
+ # :new_exchange_code
105
+ #
106
+ def symbol_changes_by_exchange(exchange)
107
+ post_with_token('SymbolChangesByExchange',
108
+ {
109
+ 'Exchange' => exchange
110
+ },
111
+ &raise_block_unless_success).symbol_changes
112
+ end
113
+
114
+ # Answers end-of-day quotes either for an entire exchange or for a given
115
+ # list of symbols at a given exchange. Answers an array of hashes, each
116
+ # representing an individual quote with keys as follows.
117
+ #
118
+ # :symbol
119
+ # :description
120
+ # :name
121
+ # :date_time
122
+ # :open
123
+ # :high
124
+ # :low
125
+ # :close
126
+ # :volume
127
+ # :open_interest
128
+ # :previous
129
+ # :change
130
+ # :bid
131
+ # :ask
132
+ # :previous_close
133
+ # :next_open
134
+ # :modified
135
+ #
136
+ def quote_list(exchange, symbols=nil)
137
+ uri_path = 'QuoteList'
138
+ params = {'Exchange' => exchange}
139
+ symbols = [] if symbols.nil?
140
+ unless symbols.empty?
141
+ uri_path << '2'
142
+ params['Symbols'] = symbols.join(',')
143
+ end
144
+ post_with_token(uri_path, params, &raise_block_unless_success).quotes
145
+ end
146
+
147
+ def quote_list_by_date(exchange, date)
148
+ post_with_token('QuoteListByDate',
149
+ {
150
+ 'Exchange' => exchange,
151
+ 'QuoteDate' => date.strftime('%Y%m%d')
152
+ },
153
+ &raise_block_unless_success).quotes
154
+ end
155
+
156
+ # Expects the environment to define a user name and password for use with
157
+ # the EODData API. However, when running within a Rails application, login
158
+ # first checks for an eod_data.yml configuration file in your Rails +config+
159
+ # folder; loading the user name and password from it if the file exists.
160
+ def login
161
+ if defined?(Rails)
162
+ path = File.join(Rails.configuration.paths['config'].expanded[0], 'eod_data.yml')
163
+ if File.exist?(path)
164
+ hash = YAML.load(File.open(path))
165
+ username = hash['username']
166
+ password = hash['password']
167
+ end
168
+ end
169
+ username ||= ENV['EODDATA_USERNAME']
170
+ password ||= ENV['EODDATA_PASSWORD']
171
+ post('Login',
172
+ 'Username' => username,
173
+ 'Password' => password) do |response|
174
+ raise WebError, "Invalid login response #{response.name}" unless response.name == 'LOGINRESPONSE'
175
+ end.token_string
176
+ end
177
+
178
+ # Answers the current EODData authentication token or obtains a new token.
179
+ def token
180
+ @token ||= login
181
+ end
182
+
183
+ # Sends an authenticated POST request to EODData web services. Answers an
184
+ # XML root element encapsulated by a WebResponse object if successful.
185
+ def post_with_token(uri_path, params={})
186
+ post(uri_path, params.merge({'Token' => token}))
187
+ end
188
+
189
+ # Sends a POST request to EODData. Answers a WebResponse object
190
+ # encapsulating the XML root element taken from the response body. This
191
+ # assumes that the body contains XML. Raises an exception if the HTML
192
+ # response code is not 200. After parsing the XML, sends the result to a
193
+ # block if given. Use this to validate the response and raise exceptions
194
+ # when invalid.
195
+ def post(uri_path, params={})
196
+ response = Net::HTTP.post_form(URI.join(URI_BASE, uri_path), params)
197
+ raise WebError, "Invalid response code #{response.code}" unless response.code.to_i == 200
198
+ response = WebResponse.new(Nokogiri::XML(response.body) do |config|
199
+ config.strict.nonet
200
+ end.root)
201
+ yield response if block_given?
202
+ response
203
+ end
204
+
205
+ private
206
+
207
+ # Answers a block which when it yields raises an exception if the block's
208
+ # WebResponse argument does not have a message attribute matching the given
209
+ # string.
210
+ def raise_block_unless_message(string)
211
+ Proc.new do |response|
212
+ raise WebError, "Invalid response message #{response.message_string}" unless response.message_string == string
213
+ end
214
+ end
215
+
216
+ def raise_block_unless_success
217
+ raise_block_unless_message 'Success'
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,74 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, make a
10
+ # separate helper file that requires this one and then use it only in the specs
11
+ # that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # These two settings work together to allow you to limit a spec run
19
+ # to individual examples or groups you care about by tagging them with
20
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
21
+ # get run.
22
+ config.filter_run :focus
23
+ config.run_all_when_everything_filtered = true
24
+
25
+ # Many RSpec users commonly either run the entire suite or an individual
26
+ # file, and it's useful to allow more verbose output when running an
27
+ # individual spec file.
28
+ if config.files_to_run.one?
29
+ # Use the documentation formatter for detailed output,
30
+ # unless a formatter has already been configured
31
+ # (e.g. via a command-line flag).
32
+ config.default_formatter = 'doc'
33
+ end
34
+
35
+ # Print the 10 slowest examples and example groups at the
36
+ # end of the spec run, to help surface which specs are running
37
+ # particularly slow.
38
+ config.profile_examples = 10
39
+
40
+ # Run specs in random order to surface order dependencies. If you find an
41
+ # order dependency and want to debug it, you can fix the order by providing
42
+ # the seed, which is printed after each run.
43
+ # --seed 1234
44
+ config.order = :random
45
+
46
+ # Seed global randomization in this process using the `--seed` CLI option.
47
+ # Setting this allows you to use `--seed` to deterministically reproduce
48
+ # test failures related to randomization by passing the same `--seed` value
49
+ # as the one that triggered the failure.
50
+ Kernel.srand config.seed
51
+
52
+ # rspec-expectations config goes here. You can use an alternate
53
+ # assertion/expectation library such as wrong or the stdlib/minitest
54
+ # assertions if you prefer.
55
+ config.expect_with :rspec do |expectations|
56
+ # Enable only the newer, non-monkey-patching expect syntax.
57
+ # For more details, see:
58
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
59
+ expectations.syntax = :expect
60
+ end
61
+
62
+ # rspec-mocks config goes here. You can use an alternate test double
63
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
64
+ config.mock_with :rspec do |mocks|
65
+ # Enable only the newer, non-monkey-patching expect syntax.
66
+ # For more details, see:
67
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
68
+ mocks.syntax = :expect
69
+
70
+ # Prevents you from mocking or stubbing a method that does not exist on
71
+ # a real object. This is generally recommended.
72
+ mocks.verify_partial_doubles = true
73
+ end
74
+ end
@@ -0,0 +1,62 @@
1
+ require 'rspec'
2
+ require 'eod_data'
3
+
4
+ describe EodData::WebService do
5
+ let(:web_service) { EodData::WebService.new }
6
+
7
+ it 'exists' do
8
+ expect(web_service).not_to be_nil
9
+ end
10
+
11
+ context 'without username or password' do
12
+ # Save and restore the environment's user name and password. Store as
13
+ # instance variables; save before, restore after.
14
+ before do
15
+ @username = ENV.delete('EODDATA_USERNAME')
16
+ @password = ENV.delete('EODDATA_PASSWORD')
17
+ end
18
+
19
+ it 'throws a web error, invalid response code 500' do
20
+ expect { web_service.exchange_list }.to raise_error(EodData::WebError)
21
+ end
22
+
23
+ after do
24
+ ENV['EODDATA_USERNAME'] = @username
25
+ ENV['EODDATA_PASSWORD'] = @password
26
+ end
27
+ end
28
+
29
+ context 'exchange list' do
30
+ let(:exchanges) { web_service.exchange_list }
31
+
32
+ it 'answers an array of exchange hashes' do
33
+ expect(exchanges).to be_an_instance_of(Array)
34
+ expect(exchanges.collect(&:class).uniq).to eq([Hash])
35
+ end
36
+
37
+ it 'values have appropriate types' do
38
+ exchanges.each do |exchange|
39
+ %w(last_trade_date_time intraday_start_date).map(&:to_sym).each do |key|
40
+ expect(exchange[key].class).to eq(DateTime) if exchange[key]
41
+ end
42
+ %w(advances declines).map(&:to_sym).each do |key|
43
+ expect(exchange[key].class).to eq(Fixnum) if exchange[key]
44
+ end
45
+ %w(is_intraday has_intraday_product).map(&:to_sym).each do |key|
46
+ expect([TrueClass, FalseClass]).to include(exchange[key].class) if exchange[key]
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ it 'answers an array of symbols for NYSE' do
53
+ symbols = web_service.symbol_list('NYSE')
54
+ expect(symbols).to be_an_instance_of(Array)
55
+ expect(symbols.collect(&:class).uniq).to eq([Hash])
56
+ symbols.each do |symbol|
57
+ %w(date_time).map(&:to_sym).each do |key|
58
+ expect(symbol[key].class).to eq(DateTime) if symbol[key]
59
+ end
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eod_data
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Roy Ratcliffe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: teamcity-ruby-client
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: ''
98
+ email:
99
+ - roy@pioneeringsoftware.co.uk
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - eod_data.gemspec
111
+ - lib/eod_data.rb
112
+ - lib/eod_data/version.rb
113
+ - lib/eod_data/web_error.rb
114
+ - lib/eod_data/web_response.rb
115
+ - lib/eod_data/web_service.rb
116
+ - spec/spec_helper.rb
117
+ - spec/web_service_spec.rb
118
+ homepage: ''
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.4.6
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: ''
142
+ test_files:
143
+ - spec/spec_helper.rb
144
+ - spec/web_service_spec.rb