worldbank_as_dataframe 0.2 → 0.2.2

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
  SHA256:
3
- metadata.gz: 7abdea5942d83b0664bd4d36a6857ca36e93c0c932d8ca903397d4875b87797b
4
- data.tar.gz: 733939bd09d746c4f545145758a4297c55b2bf5037ac263269621a6271c9034a
3
+ metadata.gz: dcb1ea76123deedc99ddce0e174ccd7930eba3a27ed76a617c7c8a7b28eb967a
4
+ data.tar.gz: daa92655da05f0df4014a67f4c3d35c14eff14c319c4da619747312c79a6b6d9
5
5
  SHA512:
6
- metadata.gz: 175ae1df0d00c482d2ff87b4df33090bd0f9fe53f1e486dba846e5fd64f3c353d067d49b22550113be03a268a337a59aaa71e14466fe5b2180b0777f8769f69f
7
- data.tar.gz: ea00816320862f337485937215c2cffd425bac0fec1194c92fe890e0924ae4db90f038b35930bc026f873222b2d54fc70a91da9bb727d846793e83ec9b0b57fc
6
+ metadata.gz: c08b5c1fda2faaef793185a0c8b3e1c56509d98ca38380faf892952476fb42a75da6b8c0d1be99cfeab4192c95f3803762cc048c4e5d040987672b9ce36e348c
7
+ data.tar.gz: f73a4ccd0590c351e8fde7e932b2744ec818034e7340eae868f3b79e8a89b1aae82bb746c9698c8ce542abfe6422607b3c9acd5f5755f8e4f16e267224a479a1
data/Changelog CHANGED
@@ -1,3 +1,7 @@
1
+ 0.2.2
2
+ Parse CMO commodity workbooks with Roo instead of SimpleXlsxReader
3
+ Match the Monthly Prices sheet after normalizing title whitespace and case
4
+ Skip chart-only sheets such as AFOSHEET
1
5
  0.0.1
2
6
  Initial release
3
7
  0.9.0
data/README.md CHANGED
@@ -96,6 +96,72 @@ include WorldbankAsDataframe
96
96
  # modifiers (like #dates above) called as class methods or chained in a query.
97
97
  #
98
98
 
99
+ # Commodities#fetch downloads the Pink Sheet xlsx and parses the Monthly Prices
100
+ # sheet with Roo (chart-only sheets such as AFOSHEET are skipped).
101
+
102
+ WorldbankAsDataframe::Commodities.new.fetch
103
+ # =>
104
+ # shape: (777, 72)
105
+ # ┌────────────┬────────────────────────────┬──────────────────────────┬──────────────────────────┬───┬─────────────┬──────────────────┬──────────────────────┬────────────────────┐
106
+ # │ Timestamps ┆ Crude oil, average ($/bbl) ┆ Crude oil, Brent ($/bbl) ┆ Crude oil, Dubai ($/bbl) ┆ … ┆ Zinc ($/mt) ┆ Gold ($/troy oz) ┆ Platinum ($/troy oz) ┆ Silver ($/troy oz) │
107
+ # │ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
108
+ # │ date ┆ f64 ┆ f64 ┆ f64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
109
+ # ╞════════════╪════════════════════════════╪══════════════════════════╪══════════════════════════╪═══╪═════════════╪══════════════════╪══════════════════════╪════════════════════╡
110
+ # │ 1960-01-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ … ┆ 260.8 ┆ 35.27 ┆ 83.5 ┆ 0.9137 │
111
+ # │ 1960-02-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ … ┆ 244.9 ┆ 35.27 ┆ 83.5 ┆ 0.9137 │
112
+ # │ 1960-03-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ … ┆ 248.7 ┆ 35.27 ┆ 83.5 ┆ 0.9137 │
113
+ # │ 1960-04-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ … ┆ 254.6 ┆ 35.27 ┆ 83.5 ┆ 0.9137 │
114
+ # │ 1960-05-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ … ┆ 253.8 ┆ 35.27 ┆ 83.5 ┆ 0.9137 │
115
+ # │ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │
116
+ # │ 2024-05-01 ┆ 81.445 ┆ 81.995 ┆ 83.53 ┆ … ┆ 2959.13 ┆ 2351.13 ┆ 1014.68 ┆ 29.36 │
117
+ # │ 2024-06-01 ┆ 81.205 ┆ 82.555 ┆ 82.17 ┆ … ┆ 2809.19 ┆ 2326.44 ┆ 985.08 ┆ 29.577 │
118
+ # │ 2024-07-01 ┆ 83.258667 ┆ 85.296 ┆ 83.94 ┆ … ┆ 2777.27 ┆ 2398.2 ┆ 978.8 ┆ 29.773 │
119
+ # │ 2024-08-01 ┆ 78.121 ┆ 80.863 ┆ 77.95 ┆ … ┆ 2714.08 ┆ 2470.15 ┆ 945.36 ┆ 28.53 │
120
+ # │ 2024-09-01 ┆ 72.424333 ┆ 74.293 ┆ 73.43 ┆ … ┆ 2837.02 ┆ 2570.55 ┆ 966.7 ┆ 30.131 │
121
+ # └────────────┴────────────────────────────┴──────────────────────────┴──────────────────────────┴───┴─────────────┴──────────────────┴──────────────────────┴────────────────────┘
122
+
123
+ WorldbankAsDataframe::Commodities.new('crude').fetch
124
+ # =>
125
+ # shape: (777, 5)
126
+ # ┌────────────┬────────────────────────────┬──────────────────────────┬──────────────────────────┬────────────────────────┐
127
+ # │ Timestamps ┆ Crude oil, average ($/bbl) ┆ Crude oil, Brent ($/bbl) ┆ Crude oil, Dubai ($/bbl) ┆ Crude oil, WTI ($/bbl) │
128
+ # │ --- ┆ --- ┆ --- ┆ --- ┆ --- │
129
+ # │ date ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
130
+ # ╞════════════╪════════════════════════════╪══════════════════════════╪══════════════════════════╪════════════════════════╡
131
+ # │ 1960-01-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ null │
132
+ # │ 1960-02-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ null │
133
+ # │ 1960-03-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ null │
134
+ # │ 1960-04-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ null │
135
+ # │ 1960-05-01 ┆ 1.63 ┆ 1.63 ┆ 1.63 ┆ null │
136
+ # │ … ┆ … ┆ … ┆ … ┆ … │
137
+ # │ 2024-05-01 ┆ 81.445 ┆ 81.995 ┆ 83.53 ┆ 78.81 │
138
+ # │ 2024-06-01 ┆ 81.205 ┆ 82.555 ┆ 82.17 ┆ 78.89 │
139
+ # │ 2024-07-01 ┆ 83.258667 ┆ 85.296 ┆ 83.94 ┆ 80.54 │
140
+ # │ 2024-08-01 ┆ 78.121 ┆ 80.863 ┆ 77.95 ┆ 75.55 │
141
+ # │ 2024-09-01 ┆ 72.424333 ┆ 74.293 ┆ 73.43 ┆ 69.55 │
142
+ # └────────────┴────────────────────────────┴──────────────────────────┴──────────────────────────┴────────────────────────┘
143
+
144
+ WorldbankAsDataframe::Commodities.new('gold').fetch(start: '1980-01-01', fin: '2000-12-31')
145
+ # =>
146
+ # shape: (252, 2)
147
+ # ┌────────────┬──────────────────┐
148
+ # │ Timestamps ┆ Gold ($/troy oz) │
149
+ # │ --- ┆ --- │
150
+ # │ date ┆ f64 │
151
+ # ╞════════════╪══════════════════╡
152
+ # │ 1980-01-01 ┆ 675.31 │
153
+ # │ 1980-02-01 ┆ 665.32 │
154
+ # │ 1980-03-01 ┆ 553.58 │
155
+ # │ 1980-04-01 ┆ 517.41 │
156
+ # │ 1980-05-01 ┆ 513.8 │
157
+ # │ … ┆ … │
158
+ # │ 2000-08-01 ┆ 274.47 │
159
+ # │ 2000-09-01 ┆ 273.68 │
160
+ # │ 2000-10-01 ┆ 270.0 │
161
+ # │ 2000-11-01 ┆ 266.01 │
162
+ # │ 2000-12-01 ┆ 271.45 │
163
+ # └────────────┴──────────────────┘
164
+
99
165
  ```
100
166
 
101
167
 
@@ -1,15 +1,15 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '/source'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '/income_level'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '/lending_type'))
4
+ require File.expand_path(File.join(File.dirname(__FILE__), '/country'))
5
+ require File.expand_path(File.join(File.dirname(__FILE__), '/indicator'))
6
+ require File.expand_path(File.join(File.dirname(__FILE__), '/topic'))
7
+ require File.expand_path(File.join(File.dirname(__FILE__), '/region'))
8
+ require File.expand_path(File.join(File.dirname(__FILE__), '/query'))
9
+ require File.expand_path(File.join(File.dirname(__FILE__), '/data'))
10
+ require File.expand_path(File.join(File.dirname(__FILE__), '/param_query'))
11
+ require File.expand_path(File.join(File.dirname(__FILE__), '/data_query'))
1
12
  require 'httparty'
2
- require File.expand_path(File.join(File.dirname(__FILE__), 'source'))
3
- require File.expand_path(File.join(File.dirname(__FILE__), 'income_level'))
4
- require File.expand_path(File.join(File.dirname(__FILE__), 'lending_type'))
5
- require File.expand_path(File.join(File.dirname(__FILE__), 'country'))
6
- require File.expand_path(File.join(File.dirname(__FILE__), 'indicator'))
7
- require File.expand_path(File.join(File.dirname(__FILE__), 'topic'))
8
- require File.expand_path(File.join(File.dirname(__FILE__), 'region'))
9
- require File.expand_path(File.join(File.dirname(__FILE__), 'query'))
10
- require File.expand_path(File.join(File.dirname(__FILE__), 'data'))
11
- require File.expand_path(File.join(File.dirname(__FILE__), 'param_query'))
12
- require File.expand_path(File.join(File.dirname(__FILE__), 'data_query'))
13
13
 
14
14
  module WorldbankAsDataframe
15
15
  class Client
@@ -0,0 +1,108 @@
1
+ require 'open-uri'
2
+ require 'roo'
3
+ require 'polars-df'
4
+ require 'tempfile'
5
+ require 'date'
6
+
7
+ module WorldbankAsDataframe
8
+ class Commodities
9
+ CMO_URL = 'https://thedocs.worldbank.org/en/doc/5d903e848db1d1b83e0ec8f744e55570-0350012021/related/CMO-Historical-Data-Monthly.xlsx'
10
+ MONTHLY_PRICES_SHEET = 'Monthly Prices'
11
+ MISSING_MARKERS = ["…", "..."].freeze
12
+
13
+ attr_reader :tag
14
+
15
+ def initialize(series = nil, options={})
16
+ @tag = series
17
+ end
18
+
19
+ def fetch(start: nil, fin: nil, path: nil)
20
+ if path
21
+ _frame_from_path(path, start: start, fin: fin)
22
+ else
23
+ Tempfile.open(['cmo', '.xlsx'], binmode: true) do |f|
24
+ f.write(URI.open(CMO_URL, 'User-Agent' => 'worldbank_as_dataframe').read)
25
+ f.flush
26
+ _frame_from_path(f.path, start: start, fin: fin)
27
+ end
28
+ end
29
+ end
30
+
31
+ def _frame_from_path(path, start: nil, fin: nil)
32
+ xlsx = Roo::Excelx.new(path)
33
+ rows = _monthly_price_rows(xlsx)
34
+ _build_frame(rows, start: start, fin: fin)
35
+ end
36
+
37
+ def _monthly_price_rows(xlsx)
38
+ name = xlsx.sheets.find { |sheet_name| _normalize_key(sheet_name) == _normalize_key(MONTHLY_PRICES_SHEET) }
39
+ raise 'CMO workbook contained no Monthly Prices sheet' if name.nil?
40
+
41
+ sheet = xlsx.sheet(name)
42
+ last_row = sheet.last_row
43
+ raise 'CMO Monthly Prices sheet is empty' if last_row.nil?
44
+
45
+ (1..last_row).map { |idx| sheet.row(idx) }
46
+ end
47
+
48
+ def _build_frame(rows, start: nil, fin: nil)
49
+ ary = rows[4..].map { |row| row.dup }
50
+ raise 'CMO Monthly Prices sheet is missing header rows' if ary.nil? || ary.length < 3
51
+
52
+ ary[0][0] = 'Timestamps'
53
+ ary.map! { |a| a.reverse.drop_while(&:nil?).reverse }
54
+ ary[1].length.times { |i| ary[1][i] = [ary[0][i], ary[1][i]].compact.join(' ') }
55
+ ary = ary[1..]
56
+
57
+ cols = ary[0]
58
+ dat = ary[1..].map { |row| _coerce_row(row) }
59
+ dat.reject! { |row| row.compact.empty? }
60
+
61
+ frame_hsh = {}
62
+ cols.each_with_index { |col, i| frame_hsh[col] = dat.map { |row| row[i] } }
63
+ df = Polars::DataFrame.new(frame_hsh)
64
+
65
+ start_date = _to_date(start)
66
+ fin_date = _to_date(fin)
67
+ df = df.filter(Polars.col('Timestamps') >= start_date) unless start_date.nil?
68
+ df = df.filter(Polars.col('Timestamps') <= fin_date) unless fin_date.nil?
69
+
70
+ unless @tag.nil?
71
+ matched = cols.select { |c| c.to_s.downcase.include?(@tag.to_s.downcase) }
72
+ df = df.select(['Timestamps', *matched]) if matched.length > 0
73
+ end
74
+
75
+ df
76
+ end
77
+
78
+ def _normalize_label(text)
79
+ return '' if text.nil?
80
+
81
+ text.to_s
82
+ .gsub(/<[^>]+>/, '')
83
+ .gsub(/[[:space:]]+/, ' ')
84
+ .delete('*')
85
+ .strip
86
+ end
87
+
88
+ def _normalize_key(text)
89
+ _normalize_label(text).downcase
90
+ end
91
+
92
+ def _coerce_row(row)
93
+ row = row.dup
94
+ if row[0].to_s =~ /\A(\d{4})M(\d{2})\z/
95
+ row[0] = Date.new($1.to_i, $2.to_i, 1)
96
+ end
97
+ row.map { |cell| MISSING_MARKERS.include?(cell) ? nil : cell }
98
+ end
99
+
100
+ def _to_date(value)
101
+ return nil if value.nil?
102
+ return value if value.is_a?(Date)
103
+ return value.to_date if value.respond_to?(:to_date)
104
+
105
+ Date.parse(value.to_s)
106
+ end
107
+ end
108
+ end
@@ -1,3 +1,3 @@
1
1
  module WorldbankAsDataframe
2
- VERSION = "0.2"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -1,21 +1,20 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '/worldbank_as_dataframe/client'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '/worldbank_as_dataframe/commodities'))
2
3
 
3
4
  module WorldbankAsDataframe
4
-
5
5
  def self.client(query={}, raw=false)
6
- defaults = {:params => {:format => :json}, :dirs => []}
7
- defaults.merge!(query)
8
- WorldbankAsDataframe::Client.new(defaults, raw)
9
- end
10
-
11
- # Delegate to WorldbankAsDataframe::Client.new
12
- def self.method_missing(method, *args, &block)
13
- return super unless client.respond_to?(method)
14
- client.send(method, *args, &block)
15
- end
6
+ defaults = {:params => {:format => :json}, :dirs => []}
7
+ defaults.merge!(query)
8
+ WorldbankAsDataframe::Client.new(defaults, raw)
9
+ end
16
10
 
17
- def self.respond_to?(method, include_private=false)
18
- client.respond_to?(method, include_private) || super(method, include_private)
19
- end
11
+ # Delegate to WorldbankAsDataframe::Client.new
12
+ def self.method_missing(method, *args, &block)
13
+ return super unless client.respond_to?(method)
14
+ client.send(method, *args, &block)
15
+ end
20
16
 
17
+ def self.respond_to?(method, include_private=false)
18
+ client.respond_to?(method, include_private) || super(method, include_private)
19
+ end
21
20
  end
@@ -0,0 +1,3 @@
1
+ # Executed plans
2
+
3
+ No executed-plan notes have been recorded yet.
@@ -0,0 +1,5 @@
1
+ # Explicitly stated requirements
2
+
3
+ | ID | Title | File |
4
+ | --- | --- | --- |
5
+ | REQ-001 | Parse the current World Bank CMO workbook | [requirements/REQ-001.md](requirements/REQ-001.md) |
@@ -0,0 +1,13 @@
1
+ # REQ-001 — Parse the current World Bank CMO workbook
2
+
3
+ **Source:** user directive to fix the same SimpleXlsxReader failures found in `ny_frb_as_dataframe` (2026-09-09).
4
+
5
+ ## Statement
6
+
7
+ `WorldbankAsDataframe::Commodities#fetch` must load the current Pink Sheet `CMO-Historical-Data-Monthly.xlsx` and return a Polars frame.
8
+
9
+ ## Required behavior
10
+
11
+ - Do not use SimpleXlsxReader. The published workbook includes a chart sheet (`AFOSHEET`) and `simple_xlsx_reader` 1.0.5 fails on sheets without a dimension node. Parse data sheets with Roo.
12
+ - Do not set `SimpleXlsxReader.configuration.auto_slurp`.
13
+ - Match the `Monthly Prices` sheet after normalizing whitespace and case.
@@ -0,0 +1,29 @@
1
+ require 'helper'
2
+
3
+ describe WorldbankAsDataframe::Commodities do
4
+ let(:fixture) { File.expand_path('../../fixtures/cmo_monthly_prices.xlsx', __FILE__) }
5
+
6
+ it 'is instantiable' do
7
+ WorldbankAsDataframe::Commodities.new.should be_a WorldbankAsDataframe::Commodities
8
+ end
9
+
10
+ it 'parses Monthly Prices from a chart-heavy workbook via Roo' do
11
+ df = WorldbankAsDataframe::Commodities.new.fetch(path: fixture)
12
+ df.columns.should include('Timestamps')
13
+ df.columns.should include('Crude oil, average ($/bbl)')
14
+ df['Timestamps'].to_a.should include(Date.new(1960, 1, 1))
15
+ df['Crude oil, average ($/bbl)'].to_a.first.should == 1.63
16
+ end
17
+
18
+ it 'treats ellipsis cells as null and matches series tags case-insensitively' do
19
+ df = WorldbankAsDataframe::Commodities.new('crude oil').fetch(path: fixture)
20
+ df.columns.should == ['Timestamps', 'Crude oil, average ($/bbl)']
21
+ df.filter(Polars.col('Timestamps') == Date.new(1960, 2, 1))['Crude oil, average ($/bbl)'].to_a.first.should be_nil
22
+ end
23
+
24
+ it 'filters by start and fin' do
25
+ df = WorldbankAsDataframe::Commodities.new.fetch(path: fixture, start: '2020-01-01', fin: '2020-12-31')
26
+ df.height.should == 1
27
+ df['Timestamps'].to_a.should == [Date.new(2020, 1, 1)]
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'date'
5
+ require_relative '../lib/worldbank_as_dataframe'
6
+
7
+ FIXTURE = File.expand_path('../spec/fixtures/cmo_monthly_prices.xlsx', __dir__)
8
+ failures = []
9
+
10
+ failures << 'version' if WorldbankAsDataframe::VERSION.to_s.empty?
11
+
12
+ df = WorldbankAsDataframe::Commodities.new.fetch(path: FIXTURE)
13
+ failures << 'timestamps column' unless df.columns.include?('Timestamps')
14
+ failures << 'crude column' unless df.columns.include?('Crude oil, average ($/bbl)')
15
+ failures << '1960-01-01 row' unless df['Timestamps'].to_a.include?(Date.new(1960, 1, 1))
16
+ failures << 'crude value' unless df['Crude oil, average ($/bbl)'].to_a.first == 1.63
17
+
18
+ tagged = WorldbankAsDataframe::Commodities.new('CRUDE OIL').fetch(path: FIXTURE)
19
+ failures << 'tag columns' unless tagged.columns == ['Timestamps', 'Crude oil, average ($/bbl)']
20
+
21
+ windowed = WorldbankAsDataframe::Commodities.new.fetch(path: FIXTURE, start: '2020-01-01', fin: '2020-12-31')
22
+ failures << 'date window' unless windowed.height == 1 && windowed['Timestamps'].to_a == [Date.new(2020, 1, 1)]
23
+
24
+ c = WorldbankAsDataframe::Commodities.new
25
+ failures << 'normalize' unless c._normalize_key('<html>Monthly Prices*</html>') == 'monthly prices'
26
+
27
+ if failures.empty?
28
+ puts 'test_commodities: ok'
29
+ else
30
+ abort "test_commodities failed: #{failures.join(', ')}"
31
+ end
@@ -26,5 +26,6 @@ Gem::Specification.new do |gem|
26
26
  gem.add_runtime_dependency 'httparty'
27
27
  gem.add_runtime_dependency 'polars-df'
28
28
  gem.add_runtime_dependency 'multi_json'
29
+ gem.add_runtime_dependency 'roo'
29
30
  # gem.add_runtime_dependency 'rash', '~> 0.3.0'
30
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: worldbank_as_dataframe
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bill McKinnon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-10 00:00:00.000000000 Z
11
+ date: 2026-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ZenTest
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: roo
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  description: A Ruby wrapper around the World Bank's Development Indicators API, with
154
168
  credit to Code for America and Justin Stoller
155
169
  email:
@@ -177,6 +191,7 @@ files:
177
191
  - bin/setup
178
192
  - lib/worldbank_as_dataframe.rb
179
193
  - lib/worldbank_as_dataframe/client.rb
194
+ - lib/worldbank_as_dataframe/commodities.rb
180
195
  - lib/worldbank_as_dataframe/country.rb
181
196
  - lib/worldbank_as_dataframe/data.rb
182
197
  - lib/worldbank_as_dataframe/data_query.rb
@@ -190,7 +205,11 @@ files:
190
205
  - lib/worldbank_as_dataframe/source.rb
191
206
  - lib/worldbank_as_dataframe/topic.rb
192
207
  - lib/worldbank_as_dataframe/version.rb
208
+ - reqs/executed_plans.md
209
+ - reqs/explicitly_stated_requirements.md
210
+ - reqs/requirements/REQ-001.md
193
211
  - spec/fixtures/brazil.json
212
+ - spec/fixtures/cmo_monthly_prices.xlsx
194
213
  - spec/fixtures/countries.json
195
214
  - spec/fixtures/countries_india.json
196
215
  - spec/fixtures/income_level_lmc.json
@@ -207,6 +226,7 @@ files:
207
226
  - spec/fixtures/topics.json
208
227
  - spec/helper.rb
209
228
  - spec/worldbank_as_dataframe/client_spec.rb
229
+ - spec/worldbank_as_dataframe/commodities_spec.rb
210
230
  - spec/worldbank_as_dataframe/country_spec.rb
211
231
  - spec/worldbank_as_dataframe/data_query_spec.rb
212
232
  - spec/worldbank_as_dataframe/data_spec.rb
@@ -219,6 +239,7 @@ files:
219
239
  - spec/worldbank_as_dataframe/source_spec.rb
220
240
  - spec/worldbank_as_dataframe/topic_spec.rb
221
241
  - spec/worldbank_as_dataframe_spec.rb
242
+ - test/test_commodities.rb
222
243
  - worldbank_as_dataframe.gemspec
223
244
  homepage: https://github.com/bmck/worldbank_as_dataframe
224
245
  licenses: []
@@ -238,12 +259,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
259
  - !ruby/object:Gem::Version
239
260
  version: '0'
240
261
  requirements: []
241
- rubygems_version: 3.5.18
262
+ rubygems_version: 3.3.7
242
263
  signing_key:
243
264
  specification_version: 4
244
265
  summary: A Ruby wrapper around the World Bank's Development Indicators API
245
266
  test_files:
246
267
  - spec/fixtures/brazil.json
268
+ - spec/fixtures/cmo_monthly_prices.xlsx
247
269
  - spec/fixtures/countries.json
248
270
  - spec/fixtures/countries_india.json
249
271
  - spec/fixtures/income_level_lmc.json
@@ -260,6 +282,7 @@ test_files:
260
282
  - spec/fixtures/topics.json
261
283
  - spec/helper.rb
262
284
  - spec/worldbank_as_dataframe/client_spec.rb
285
+ - spec/worldbank_as_dataframe/commodities_spec.rb
263
286
  - spec/worldbank_as_dataframe/country_spec.rb
264
287
  - spec/worldbank_as_dataframe/data_query_spec.rb
265
288
  - spec/worldbank_as_dataframe/data_spec.rb
@@ -272,3 +295,4 @@ test_files:
272
295
  - spec/worldbank_as_dataframe/source_spec.rb
273
296
  - spec/worldbank_as_dataframe/topic_spec.rb
274
297
  - spec/worldbank_as_dataframe_spec.rb
298
+ - test/test_commodities.rb