kiba-common 0.7.0 → 1.5.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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/ci.yml +41 -0
- data/Changes.md +52 -2
- data/Gemfile +1 -1
- data/README.md +101 -9
- data/Rakefile +2 -2
- data/kiba-common.gemspec +21 -17
- data/lib/kiba-common/destinations/csv.rb +10 -7
- data/lib/kiba-common/destinations/lambda.rb +23 -0
- data/lib/kiba-common/dsl_extensions/logger.rb +2 -2
- data/lib/kiba-common/dsl_extensions/show_me.rb +3 -5
- data/lib/kiba-common/sources/csv.rb +22 -0
- data/lib/kiba-common/sources/enumerable.rb +1 -1
- data/lib/kiba-common/transforms/enumerable_exploder.rb +1 -1
- data/lib/kiba-common/version.rb +1 -1
- data/test/helper.rb +5 -5
- data/test/support/assert_called.rb +1 -1
- data/test/support/test_array_destination.rb +2 -2
- data/test/support/test_hash_configured_object.rb +9 -0
- data/test/support/test_keyword_proxy_source.rb +13 -0
- data/test/test_csv_destination.rb +10 -10
- data/test/test_csv_source.rb +51 -0
- data/test/test_enumerable_exploder_transform.rb +8 -8
- data/test/test_enumerable_source.rb +6 -6
- data/test/test_integration.rb +57 -0
- data/test/test_lambda_destination.rb +22 -0
- data/test/test_logger.rb +5 -5
- data/test/test_show_me.rb +13 -8
- data/test/test_source_transform_adapter.rb +70 -6
- metadata +42 -15
- data/.travis.yml +0 -11
- data/lib/kiba-common/transforms/source_transform_adapter.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c572e8d0d2cea374d8ee86d54ada3d323dd1087d91c002ef30b565c8dd98199
|
4
|
+
data.tar.gz: 1153c67d2bff98455663f4b2859d8af8f723ddab135411e720bc4abdbca3da3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cfccbc1d90c83bd202d5bbd996fe02a5599ca0b210921d1d3d7ff1d205ecb2484ebe1a686d3345773dc7298cd86616e8a89ceaa607312cfb495b4b5c41df010
|
7
|
+
data.tar.gz: 76fc871cc277824452e94db9545092a8333bf26404151c5a5d5367be6a0d7df0690c834b3a576eedcca79e6299a3947b393f5c502c6ad9041de9f88259ebc12f
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: thbar
|
@@ -0,0 +1,41 @@
|
|
1
|
+
name: CI build
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
build:
|
5
|
+
strategy:
|
6
|
+
fail-fast: false
|
7
|
+
matrix:
|
8
|
+
os: [ubuntu-latest]
|
9
|
+
ruby:
|
10
|
+
- '2.5'
|
11
|
+
- '2.6'
|
12
|
+
- '2.7'
|
13
|
+
- '3.0'
|
14
|
+
- head
|
15
|
+
- jruby
|
16
|
+
- jruby-head
|
17
|
+
- truffleruby
|
18
|
+
- truffleruby-head
|
19
|
+
runs-on: ${{ matrix.os }}
|
20
|
+
steps:
|
21
|
+
- uses: actions/checkout@v2
|
22
|
+
- uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
25
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
26
|
+
- run: bundle exec rake
|
27
|
+
# NOTE: calling "bundle install" because the cache apparently did not update due to the gemspec injection
|
28
|
+
- run: bundle install && bundle exec standardrb
|
29
|
+
if: matrix.ruby == '3.0' # not using "head" because rubocop won't work there yet
|
30
|
+
# What's below helps having a single "status check" for mergeability, without
|
31
|
+
# having to add each new version to the list of expected status checks in GitHub.
|
32
|
+
# See https://github.community/t/status-check-for-a-matrix-jobs/127354/7
|
33
|
+
global:
|
34
|
+
if: ${{ always() }}
|
35
|
+
runs-on: ubuntu-latest
|
36
|
+
name: build (matrix)
|
37
|
+
needs: build
|
38
|
+
steps:
|
39
|
+
- name: Check build matrix status
|
40
|
+
if: ${{ needs.build.result != 'success' }}
|
41
|
+
run: exit 1
|
data/Changes.md
CHANGED
@@ -1,5 +1,55 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
1.5.0
|
2
|
+
-----
|
3
|
+
|
4
|
+
- Support for Kiba 4
|
5
|
+
- Breaking: Drop support for Ruby < 2.5
|
6
|
+
- Breaking: Require Kiba 3+
|
7
|
+
- [StandardRB](https://github.com/testdouble/standard) has been added for formatting & linting the codebase.
|
8
|
+
|
9
|
+
|
10
|
+
1.1.0
|
11
|
+
-----
|
12
|
+
|
13
|
+
- Support for Ruby 2.7+ (affects CSV source and destination)
|
14
|
+
- Breaking: `show_me!` is now compatible with both `awesome_print` and its modern replacement `amazing_print`. You will have to `require` the one you want to use in your code from now on.
|
15
|
+
- Breaking: `SourceTransformAdapter` has been removed due to complexities with Ruby 2.7+ keyword arguments. The suggested replacement is to use `Enumerator` and `EnumerableExploder` like this:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
# before
|
19
|
+
transform SourceTransformAdapter
|
20
|
+
|
21
|
+
# after
|
22
|
+
transform do |klass, args|
|
23
|
+
Enumerator.new do |y|
|
24
|
+
# NOTE: you may have to use double-splat (**) here instead
|
25
|
+
# if you provide keyword arguments, or other variants
|
26
|
+
klass.new(*args).each do |r|
|
27
|
+
y << r
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
transform Kiba::Common::Transforms::EnumerableExploder
|
33
|
+
```
|
34
|
+
|
35
|
+
1.0.0
|
36
|
+
-----
|
37
|
+
|
38
|
+
- Kiba ETL v3 compatibility
|
39
|
+
- New: Kiba::Common::Destinations::Lambda lets you write block-form destinations (handy for one-off scripts).
|
40
|
+
|
41
|
+
0.9.0
|
42
|
+
-----
|
43
|
+
|
44
|
+
- New: Kiba::Common::Sources::CSV provides a basic CSV source for simple needs.
|
45
|
+
|
46
|
+
0.8.0
|
47
|
+
-----
|
48
|
+
|
49
|
+
- Bugfix: `show_me!` used with a block should not modify the processed row.
|
50
|
+
|
51
|
+
0.7.0
|
52
|
+
-----
|
3
53
|
|
4
54
|
- New: Kiba::Common::Transforms::SourceTransformAdapter let you transform rows into parameters for source instantiation.
|
5
55
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
Kiba Common is a companion gem to [Kiba](https://github.com/thbar/kiba) and [Kiba Pro](https://github.com/thbar/kiba/blob/master/Pro-Changes.md) in which I'll share commonly used helpers.
|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/kiba-common)
|
4
|
+
[](https://github.com/thbar/kiba-common/actions)
|
4
5
|
|
5
6
|
## Usage
|
6
7
|
|
@@ -14,7 +15,8 @@ Then see below for each module usage & require clause.
|
|
14
15
|
|
15
16
|
## Supported Ruby versions
|
16
17
|
|
17
|
-
`kiba-common` currently supports Ruby 2.
|
18
|
+
`kiba-common` currently supports Ruby 2.5+, JRuby 9.2+ and TruffleRuby. See [test matrix](https://github.com/thbar/kiba-common/actions).
|
19
|
+
|
18
20
|
|
19
21
|
## Available components
|
20
22
|
|
@@ -48,7 +50,7 @@ But since Kiba v2 introduction of `StreamingRunner`, it is possible for transfor
|
|
48
50
|
|
49
51
|
Leveraging that possibility, you can use a `SourceTransformAdapter` to dynamically instantiate the source for each of your input rows.
|
50
52
|
|
51
|
-
This allows to mix-and-match components in a much more versatile & powerful way.
|
53
|
+
This allows you to mix-and-match components in a much more versatile & powerful way.
|
52
54
|
|
53
55
|
Requirements: Kiba v2 with `StreamingRunner` enabled.
|
54
56
|
|
@@ -85,7 +87,7 @@ require 'kiba-common/transforms/enumerable_exploder'
|
|
85
87
|
transform Kiba::Common::Transforms::EnumerableExploder
|
86
88
|
```
|
87
89
|
|
88
|
-
|
90
|
+
This can help if you are reading XML/JSON documents from a source and each input document contains multiple rows that you want to extract.
|
89
91
|
|
90
92
|
```ruby
|
91
93
|
source Kiba::Common::Sources::Enumerable, -> { Dir["input/*.xml"] }
|
@@ -104,7 +106,7 @@ Similarly, if you have a CSV document as your input:
|
|
104
106
|
| ------------- | ------------- |
|
105
107
|
| 00001 | John:Mary:Sally |
|
106
108
|
|
107
|
-
and you want to reformat it to
|
109
|
+
and you want to reformat it to the following:
|
108
110
|
|
109
111
|
| po_number | buyer |
|
110
112
|
|-------------|---------|
|
@@ -129,17 +131,81 @@ end
|
|
129
131
|
transform Kiba::Common::Transforms::EnumerableExploder
|
130
132
|
```
|
131
133
|
|
134
|
+
### Kiba::Common::Sources::CSV
|
135
|
+
|
136
|
+
A CSV source for basic needs (in particular, it doesn't yield row metadata, which are useful in more advanced scenarios).
|
137
|
+
|
138
|
+
Use the `csv_options` keyword to control the input format like when using [Ruby CSV class](http://ruby-doc.org/stdlib-2.4.0/libdoc/csv/rdoc/CSV.html#method-c-new).
|
139
|
+
|
140
|
+
Usage:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
require 'kiba-common/sources/csv'
|
144
|
+
|
145
|
+
# by defaults, csv_options are empty
|
146
|
+
source Kiba::Common::Sources::CSV, filename: 'input.csv'
|
147
|
+
|
148
|
+
# you can provide your own csv_options
|
149
|
+
source Kiba::Common::Sources::CSV, filename: 'input.csv',
|
150
|
+
csv_options: { headers: true, header_converters: :symbol }
|
151
|
+
```
|
152
|
+
|
153
|
+
Note that the emitted rows are instances of [`CSV::Row`](http://ruby-doc.org/stdlib-2.5.3/libdoc/csv/rdoc/CSV/Row.html), part `Array` and part `Hash`, which retain order of fields and allow duplicates (unlike a regular `Hash`).
|
154
|
+
|
155
|
+
If the rest of your pipeline expects `Hash` rows (like for instance `Kiba::Common::Destinations::CSV`), you'll want to transform the rows to `Hash` instances yourself using [`to_hash`](http://ruby-doc.org/stdlib-2.5.3/libdoc/csv/rdoc/CSV/Row.html#method-i-to_hash). This will "collapse the row into a simple Hash. Be warned that this discards field order and clobbers duplicate fields."
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
transform { |r| r.to_hash }
|
159
|
+
```
|
160
|
+
|
161
|
+
#### Handling multiple input CSV files
|
162
|
+
|
163
|
+
You can process multiple files by chaining the various components available in Kiba Common (see `test/test_integration#test_multiple_csv_inputs` for an actual demo):
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
# create one row per input filename
|
167
|
+
source Kiba::Common::Sources::Enumerable, -> { Dir[File.join(dir, '*.csv')] }
|
168
|
+
|
169
|
+
# out of that row, create configuration for a CSV source
|
170
|
+
transform do |r|
|
171
|
+
[
|
172
|
+
Kiba::Common::Sources::CSV,
|
173
|
+
filename: r,
|
174
|
+
csv_options: { headers: true, header_converters: :symbol }
|
175
|
+
]
|
176
|
+
end
|
177
|
+
|
178
|
+
# instantiate & yield CSV rows for each configuration
|
179
|
+
transform Kiba::Common::Transforms::SourceTransformAdapter
|
180
|
+
```
|
181
|
+
|
182
|
+
Alternatively, you can wrap this source in your own source like this:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
class MultipleCSVSource
|
186
|
+
def initialize(file_pattern:, csv_options:)
|
187
|
+
|
188
|
+
def each
|
189
|
+
Dir[file_pattern].each do |filename|
|
190
|
+
Kiba::Common::Sources::CSV.new(filename, csv_options).each do |row|
|
191
|
+
yield row
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
132
198
|
### Kiba::Common::Destinations::CSV
|
133
199
|
|
134
200
|
A way to dump `Hash` rows as CSV.
|
135
201
|
|
136
202
|
All rows are expected to have the exact same set of keys as the first row.
|
137
203
|
|
138
|
-
The headers will be the first row keys
|
204
|
+
The headers will be the first row keys unless you pass an array of keys via `headers`.
|
139
205
|
|
140
|
-
All keys are mandatory (although they can have a nil value).
|
206
|
+
All keys are mandatory (although they can have a `nil` value).
|
141
207
|
|
142
|
-
Use the `csv_options` keyword to control the output format like
|
208
|
+
Use the `csv_options` keyword to control the output format like when using [Ruby CSV class](http://ruby-doc.org/stdlib-2.4.0/libdoc/csv/rdoc/CSV.html#method-c-new).
|
143
209
|
|
144
210
|
Usage:
|
145
211
|
|
@@ -161,6 +227,30 @@ destination Kiba::Common::Destinations::CSV,
|
|
161
227
|
headers: [:field, :other_field]
|
162
228
|
```
|
163
229
|
|
230
|
+
### Kiba::Common::Destinations::Lambda
|
231
|
+
|
232
|
+
At times, it can be convenient to use a block form for a destination (pretty much like Kiba's built-in "block transform"), especially for one-off scripts.
|
233
|
+
|
234
|
+
The Lambda destination is there for that purpose.
|
235
|
+
|
236
|
+
Example use:
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
require 'kiba-common/destinations/lambda'
|
240
|
+
|
241
|
+
destination Kiba::Common::Destinations::Lambda,
|
242
|
+
# called at destination instantiation time (once)
|
243
|
+
on_init: -> { ... },
|
244
|
+
# called for each row
|
245
|
+
on_write: -> (row) { ... },
|
246
|
+
# called after all the rows have been written
|
247
|
+
on_close: -> { ... }
|
248
|
+
```
|
249
|
+
|
250
|
+
Each "callback" (e.g. `on_init`) is optional.
|
251
|
+
|
252
|
+
The callback code can refer to scope variables or instance variables you may have declared above.
|
253
|
+
|
164
254
|
### Kiba::Common::DSLExtensions::Logger
|
165
255
|
|
166
256
|
A simple logging facility.
|
@@ -189,7 +279,7 @@ logger = Logger.new(xxx)
|
|
189
279
|
|
190
280
|
### Kiba::Common::DSLExtensions::ShowMe
|
191
281
|
|
192
|
-
A way to color-dump rows on the screen, useful
|
282
|
+
A way to color-dump rows on the screen, useful during development when you are inspecting the data (requires either the `amazing_print` or the `awesome_print` gem).
|
193
283
|
|
194
284
|
Usage:
|
195
285
|
|
@@ -212,6 +302,8 @@ show_me! { |r| r.except(:some_noisy_field) }
|
|
212
302
|
|
213
303
|
## Contributing & Legal
|
214
304
|
|
305
|
+
See [LICENSE](LICENSE) for license.
|
306
|
+
|
215
307
|
(agreement below borrowed from Sidekiq Legal)
|
216
308
|
|
217
309
|
By submitting a Pull Request, you disavow any rights or claims to any changes submitted to the Kiba Common project and assign the copyright of those changes to LoGeek SARL.
|
data/Rakefile
CHANGED
data/kiba-common.gemspec
CHANGED
@@ -1,21 +1,25 @@
|
|
1
|
-
|
2
|
-
require File.expand_path('../lib/kiba-common/version', __FILE__)
|
1
|
+
require File.expand_path("../lib/kiba-common/version", __FILE__)
|
3
2
|
|
4
3
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors
|
6
|
-
gem.email
|
7
|
-
gem.description
|
8
|
-
gem.homepage
|
9
|
-
gem.license
|
10
|
-
gem.files
|
11
|
-
gem.test_files
|
12
|
-
gem.name
|
13
|
-
gem.require_paths = [
|
14
|
-
gem.version
|
4
|
+
gem.authors = ["Thibaut Barrère"]
|
5
|
+
gem.email = ["thibaut.barrere@gmail.com"]
|
6
|
+
gem.description = gem.summary = "Commonly used helpers for Kiba ETL"
|
7
|
+
gem.homepage = "https://github.com/thbar/kiba-common"
|
8
|
+
gem.license = "LGPL-3.0"
|
9
|
+
gem.files = `git ls-files | grep -Ev '^(examples)'`.split("\n")
|
10
|
+
gem.test_files = `git ls-files -- test/*`.split("\n")
|
11
|
+
gem.name = "kiba-common"
|
12
|
+
gem.require_paths = ["lib"]
|
13
|
+
gem.version = Kiba::Common::VERSION
|
14
|
+
gem.metadata = {
|
15
|
+
"source_code_uri" => "https://github.com/thbar/kiba-common",
|
16
|
+
"documentation_uri" => "https://github.com/thbar/kiba-common/blob/master/README.md"
|
17
|
+
}
|
15
18
|
|
16
|
-
gem.add_dependency
|
17
|
-
gem.add_development_dependency
|
18
|
-
gem.add_development_dependency
|
19
|
-
gem.add_development_dependency
|
20
|
-
gem.add_development_dependency
|
19
|
+
gem.add_dependency "kiba", ">= 3.0.0", "< 5"
|
20
|
+
gem.add_development_dependency "rake"
|
21
|
+
gem.add_development_dependency "minitest"
|
22
|
+
gem.add_development_dependency "amazing_print"
|
23
|
+
gem.add_development_dependency "minitest-focus"
|
24
|
+
gem.add_development_dependency "standard"
|
21
25
|
end
|
@@ -1,28 +1,31 @@
|
|
1
|
-
require
|
1
|
+
require "csv"
|
2
2
|
|
3
3
|
module Kiba
|
4
4
|
module Common
|
5
5
|
module Destinations
|
6
6
|
class CSV
|
7
7
|
attr_reader :filename, :csv_options, :csv, :headers
|
8
|
-
|
8
|
+
|
9
9
|
def initialize(filename:, csv_options: nil, headers: nil)
|
10
10
|
@filename = filename
|
11
11
|
@csv_options = csv_options || {}
|
12
12
|
@headers = headers
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def write(row)
|
16
|
-
@csv ||= ::CSV.open(filename,
|
16
|
+
@csv ||= ::CSV.open(filename, "wb", **csv_options)
|
17
17
|
@headers ||= row.keys
|
18
|
-
@headers_written ||=
|
18
|
+
@headers_written ||= begin
|
19
|
+
csv << headers
|
20
|
+
true
|
21
|
+
end
|
19
22
|
csv << row.fetch_values(*@headers)
|
20
23
|
end
|
21
|
-
|
24
|
+
|
22
25
|
def close
|
23
26
|
csv&.close
|
24
27
|
end
|
25
28
|
end
|
26
29
|
end
|
27
30
|
end
|
28
|
-
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Kiba
|
2
|
+
module Common
|
3
|
+
module Destinations
|
4
|
+
class Lambda
|
5
|
+
attr_reader :on_write, :on_close
|
6
|
+
|
7
|
+
def initialize(on_init: nil, on_write: nil, on_close: nil)
|
8
|
+
@on_write = on_write
|
9
|
+
@on_close = on_close
|
10
|
+
on_init&.call
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(row)
|
14
|
+
on_write&.call(row)
|
15
|
+
end
|
16
|
+
|
17
|
+
def close
|
18
|
+
on_close&.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,17 +1,15 @@
|
|
1
|
-
require 'awesome_print'
|
2
|
-
|
3
1
|
module Kiba
|
4
2
|
module Common
|
5
3
|
module DSLExtensions
|
6
4
|
# Color print your row.
|
7
5
|
module ShowMe
|
8
6
|
def show_me!(&pre_process)
|
9
|
-
transform do |
|
10
|
-
row = pre_process ? pre_process.call(
|
7
|
+
transform do |original_row|
|
8
|
+
row = pre_process ? pre_process.call(original_row) : original_row
|
11
9
|
# NOTE: invoking Kernel.ap for testing since
|
12
10
|
# ap itself is harder to mock (Kiba Context)
|
13
11
|
Kernel.ap(row)
|
14
|
-
|
12
|
+
original_row
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "csv"
|
2
|
+
|
3
|
+
module Kiba
|
4
|
+
module Common
|
5
|
+
module Sources
|
6
|
+
class CSV
|
7
|
+
attr_reader :filename, :csv_options
|
8
|
+
|
9
|
+
def initialize(filename:, csv_options: {})
|
10
|
+
@filename = filename
|
11
|
+
@csv_options = csv_options
|
12
|
+
end
|
13
|
+
|
14
|
+
def each
|
15
|
+
::CSV.foreach(filename, **csv_options) do |row|
|
16
|
+
yield row
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/kiba-common/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "minitest/autorun"
|
2
|
+
require "minitest/pride"
|
3
|
+
require "minitest/focus"
|
4
4
|
|
5
|
-
require
|
6
|
-
require_relative
|
5
|
+
require "kiba-common/sources/enumerable"
|
6
|
+
require_relative "support/assert_called"
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require_relative
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require "kiba-common/destinations/csv"
|
4
4
|
|
5
5
|
class TestCSVDestination < Minitest::Test
|
6
|
-
TEST_FILENAME =
|
7
|
-
|
6
|
+
TEST_FILENAME = "output.csv"
|
7
|
+
|
8
8
|
def teardown
|
9
9
|
File.delete(TEST_FILENAME) if File.exist?(TEST_FILENAME)
|
10
10
|
end
|
@@ -21,24 +21,24 @@ class TestCSVDestination < Minitest::Test
|
|
21
21
|
end
|
22
22
|
|
23
23
|
Kiba.run(job)
|
24
|
-
|
24
|
+
|
25
25
|
IO.read(TEST_FILENAME)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def test_classic
|
29
29
|
assert_equal <<~CSV, run_etl
|
30
30
|
name,age
|
31
31
|
world,999
|
32
32
|
CSV
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def test_csv_options
|
36
|
-
assert_equal <<~CSV, run_etl(csv_options: {col_sep:
|
36
|
+
assert_equal <<~CSV, run_etl(csv_options: {col_sep: ";"})
|
37
37
|
name;age
|
38
38
|
world;999
|
39
39
|
CSV
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def test_headers_provided
|
43
43
|
assert_equal <<~CSV, run_etl(headers: [:age])
|
44
44
|
age
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require "kiba-common/sources/csv"
|
4
|
+
require_relative "support/test_array_destination"
|
5
|
+
|
6
|
+
class TestCSVSource < MiniTest::Test
|
7
|
+
TEST_FILENAME = "input.csv"
|
8
|
+
|
9
|
+
def setup
|
10
|
+
CSV.open(TEST_FILENAME, "wb") do |csv|
|
11
|
+
csv << %w[first_name last_name]
|
12
|
+
csv << %w[John Barry]
|
13
|
+
csv << %w[Kate Bush]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
FileUtils.rm(TEST_FILENAME) if File.exist?(TEST_FILENAME)
|
19
|
+
end
|
20
|
+
|
21
|
+
def run_job(args)
|
22
|
+
rows = []
|
23
|
+
job = Kiba.parse do
|
24
|
+
source Kiba::Common::Sources::CSV, **args
|
25
|
+
destination TestArrayDestination, rows
|
26
|
+
end
|
27
|
+
Kiba.run(job)
|
28
|
+
rows
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_with_csv_options
|
32
|
+
rows = run_job filename: TEST_FILENAME,
|
33
|
+
csv_options: {headers: true, header_converters: :symbol}
|
34
|
+
|
35
|
+
assert_equal [CSV::Row], rows.map(&:class).uniq
|
36
|
+
assert_equal([
|
37
|
+
{first_name: "John", last_name: "Barry"},
|
38
|
+
{first_name: "Kate", last_name: "Bush"}
|
39
|
+
], rows.map(&:to_h))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_without_csv_options
|
43
|
+
rows = run_job(filename: TEST_FILENAME)
|
44
|
+
|
45
|
+
assert_equal [
|
46
|
+
%w[first_name last_name],
|
47
|
+
%w[John Barry],
|
48
|
+
%w[Kate Bush]
|
49
|
+
], rows
|
50
|
+
end
|
51
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require_relative
|
2
|
-
require
|
3
|
-
require_relative
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require_relative "support/test_array_destination"
|
4
|
+
require "kiba-common/transforms/enumerable_exploder"
|
5
|
+
require "kiba/dsl_extensions/config"
|
6
6
|
|
7
7
|
class TestEnumerableExploderTransform < Minitest::Test
|
8
8
|
def test_exploder
|
9
9
|
output = []
|
10
|
-
input = [[1,2],[3,4,5]]
|
10
|
+
input = [[1, 2], [3, 4, 5]]
|
11
11
|
|
12
12
|
job = Kiba.parse do
|
13
13
|
extend Kiba::DSLExtensions::Config
|
@@ -18,7 +18,7 @@ class TestEnumerableExploderTransform < Minitest::Test
|
|
18
18
|
destination TestArrayDestination, output
|
19
19
|
end
|
20
20
|
Kiba.run(job)
|
21
|
-
|
21
|
+
|
22
22
|
assert_equal input.flatten, output
|
23
23
|
end
|
24
|
-
end
|
24
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require_relative
|
2
|
-
require
|
3
|
-
require_relative
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require_relative "support/test_array_destination"
|
4
4
|
|
5
5
|
class TestEnumerableSource < Minitest::Test
|
6
6
|
def assert_enumerable_source(input:, expected_output:)
|
@@ -16,12 +16,12 @@ class TestEnumerableSource < Minitest::Test
|
|
16
16
|
end
|
17
17
|
Kiba.run(job)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def test_source_as_enumerable
|
21
21
|
assert_enumerable_source(input: (1..10), expected_output: (2..20).step(2).to_a)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def test_source_as_callable
|
25
25
|
assert_enumerable_source(input: -> { (1..10) }, expected_output: (2..20).step(2).to_a)
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require_relative "support/test_array_destination"
|
4
|
+
require "kiba-common/sources/csv"
|
5
|
+
require "kiba-common/destinations/csv"
|
6
|
+
|
7
|
+
# a testbed to verify & showcase how you can chain multiple components
|
8
|
+
class TestIntegration < Minitest::Test
|
9
|
+
def write_csv(filename, data)
|
10
|
+
d = Kiba::Common::Destinations::CSV.new(filename: filename)
|
11
|
+
data.each { |r| d.write(r) }
|
12
|
+
d.close
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_multiple_csv_inputs
|
16
|
+
Dir.mktmpdir do |dir|
|
17
|
+
write_csv File.join(dir, "001.csv"), [first_name: "John"]
|
18
|
+
write_csv File.join(dir, "002.csv"), [first_name: "Kate"]
|
19
|
+
|
20
|
+
rows = []
|
21
|
+
job = Kiba.parse do
|
22
|
+
# enable the new streaming-runner (for SourceTransformAdapter support)
|
23
|
+
extend Kiba::DSLExtensions::Config
|
24
|
+
config :kiba, runner: Kiba::StreamingRunner
|
25
|
+
|
26
|
+
# create one row per input file
|
27
|
+
source Kiba::Common::Sources::Enumerable, -> { Dir[File.join(dir, "*.csv")].sort }
|
28
|
+
|
29
|
+
# out of that row, create configuration for a CSV source
|
30
|
+
transform do |r|
|
31
|
+
[
|
32
|
+
Kiba::Common::Sources::CSV,
|
33
|
+
filename: r,
|
34
|
+
csv_options: {headers: true, header_converters: :symbol}
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
transform do |klass, args|
|
39
|
+
Enumerator.new do |y|
|
40
|
+
klass.new(**args).each do |r|
|
41
|
+
y << r
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
transform Kiba::Common::Transforms::EnumerableExploder
|
46
|
+
|
47
|
+
destination TestArrayDestination, rows
|
48
|
+
end
|
49
|
+
Kiba.run(job)
|
50
|
+
|
51
|
+
assert_equal([
|
52
|
+
{first_name: "John"},
|
53
|
+
{first_name: "Kate"}
|
54
|
+
], rows.map(&:to_h))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require "kiba-common/destinations/lambda"
|
4
|
+
|
5
|
+
class TestLambdaDestination < MiniTest::Test
|
6
|
+
def test_lambda
|
7
|
+
accumulator = []
|
8
|
+
on_init_called = false
|
9
|
+
on_close_called = false
|
10
|
+
job = Kiba.parse do
|
11
|
+
source Kiba::Common::Sources::Enumerable, ["one", "two"]
|
12
|
+
destination Kiba::Common::Destinations::Lambda,
|
13
|
+
on_init: -> { on_init_called = true },
|
14
|
+
on_write: ->(r) { accumulator << r },
|
15
|
+
on_close: -> { on_close_called = true }
|
16
|
+
end
|
17
|
+
Kiba.run(job)
|
18
|
+
assert_equal ["one", "two"], accumulator
|
19
|
+
assert_equal true, on_init_called
|
20
|
+
assert_equal true, on_close_called
|
21
|
+
end
|
22
|
+
end
|
data/test/test_logger.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require_relative
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require "kiba-common/dsl_extensions/logger"
|
4
4
|
|
5
5
|
class TestLogger < Minitest::Test
|
6
6
|
def test_default_logger
|
@@ -20,11 +20,11 @@ class TestLogger < Minitest::Test
|
|
20
20
|
logger = Logger.new(buffer)
|
21
21
|
|
22
22
|
pre_process do
|
23
|
-
logger.info
|
23
|
+
logger.info "Logging from pre_process"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
Kiba.run(job)
|
27
27
|
|
28
|
-
assert_includes buffer.string,
|
28
|
+
assert_includes buffer.string, "Logging from pre_process"
|
29
29
|
end
|
30
30
|
end
|
data/test/test_show_me.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require_relative
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require_relative "helper"
|
2
|
+
require "kiba"
|
3
|
+
require "amazing_print"
|
4
|
+
require "kiba-common/dsl_extensions/show_me"
|
4
5
|
|
5
6
|
class TestShowMe < Minitest::Test
|
6
7
|
include AssertCalled
|
@@ -8,24 +9,28 @@ class TestShowMe < Minitest::Test
|
|
8
9
|
def test_show_me
|
9
10
|
job = Kiba.parse do
|
10
11
|
extend Kiba::Common::DSLExtensions::ShowMe
|
11
|
-
source Kiba::Common::Sources::Enumerable, [
|
12
|
+
source Kiba::Common::Sources::Enumerable, ["row"]
|
12
13
|
show_me!
|
13
14
|
end
|
14
|
-
|
15
|
-
assert_called(Kernel, :ap, [
|
15
|
+
|
16
|
+
assert_called(Kernel, :ap, ["row"]) do
|
16
17
|
Kiba.run(job)
|
17
18
|
end
|
18
19
|
end
|
19
|
-
|
20
|
+
|
20
21
|
def test_show_me_pre_process
|
22
|
+
output = []
|
21
23
|
job = Kiba.parse do
|
22
24
|
extend Kiba::Common::DSLExtensions::ShowMe
|
23
25
|
source Kiba::Common::Sources::Enumerable, [{this: "OK", not_this: "KO"}]
|
24
26
|
show_me! { |r| r.fetch(:this) }
|
27
|
+
destination TestArrayDestination, output
|
25
28
|
end
|
26
29
|
|
27
|
-
assert_called(Kernel, :ap, [
|
30
|
+
assert_called(Kernel, :ap, ["OK"]) do
|
28
31
|
Kiba.run(job)
|
29
32
|
end
|
33
|
+
|
34
|
+
assert_equal [{this: "OK", not_this: "KO"}], output
|
30
35
|
end
|
31
36
|
end
|
@@ -1,6 +1,11 @@
|
|
1
|
-
require_relative
|
2
|
-
|
1
|
+
require_relative "helper"
|
2
|
+
require_relative "support/test_keyword_proxy_source"
|
3
|
+
require_relative "support/test_hash_configured_object"
|
3
4
|
|
5
|
+
# NOTE: the SourceTransformAdapter has been removed,
|
6
|
+
# but I'm keeping these tests, patched to instead use
|
7
|
+
# Enumerator, as a way to verify that the alternative
|
8
|
+
# I provided in the change log still works.
|
4
9
|
class TestSourceTransformAdapter < Minitest::Test
|
5
10
|
include Kiba::Common::Sources
|
6
11
|
include Kiba::DSLExtensions
|
@@ -12,13 +17,72 @@ class TestSourceTransformAdapter < Minitest::Test
|
|
12
17
|
config :kiba, runner: Kiba::StreamingRunner
|
13
18
|
|
14
19
|
source Enumerable, [
|
15
|
-
[
|
16
|
-
[
|
20
|
+
[Enumerable, (1..10)],
|
21
|
+
[Enumerable, (11..20)]
|
17
22
|
]
|
18
|
-
|
23
|
+
|
24
|
+
transform do |klass, args|
|
25
|
+
Enumerator.new do |y|
|
26
|
+
klass.new(args).each do |r|
|
27
|
+
y << r
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
transform Kiba::Common::Transforms::EnumerableExploder
|
32
|
+
|
19
33
|
destination TestArrayDestination, rows
|
20
34
|
end
|
21
35
|
Kiba.run(job)
|
22
36
|
assert_equal (1..20).to_a, rows
|
23
37
|
end
|
24
|
-
|
38
|
+
|
39
|
+
def test_instantiation_keyword_arguments
|
40
|
+
rows = []
|
41
|
+
job = Kiba.parse do
|
42
|
+
source Enumerable, [
|
43
|
+
# Test against a class that expects explicit keyword arguments
|
44
|
+
[TestKeywordProxySource, {mandatory: "some value"}]
|
45
|
+
]
|
46
|
+
|
47
|
+
transform do |klass, args|
|
48
|
+
Enumerator.new do |y|
|
49
|
+
klass.new(**args).each do |r|
|
50
|
+
y << r
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
transform Kiba::Common::Transforms::EnumerableExploder
|
55
|
+
|
56
|
+
destination TestArrayDestination, rows
|
57
|
+
end
|
58
|
+
Kiba.run(job)
|
59
|
+
assert_equal([
|
60
|
+
{mandatory: "some value", optional: nil}
|
61
|
+
], rows)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_hash_configured_object
|
65
|
+
rows = []
|
66
|
+
job = Kiba.parse do
|
67
|
+
source Enumerable, [
|
68
|
+
# Test against a class that takes a single Hash argument
|
69
|
+
[TestHashConfiguredObject, {mandatory: "some value"}]
|
70
|
+
]
|
71
|
+
|
72
|
+
transform do |klass, args|
|
73
|
+
Enumerator.new do |y|
|
74
|
+
klass.new(**args).each do |r|
|
75
|
+
y << r
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
transform Kiba::Common::Transforms::EnumerableExploder
|
80
|
+
|
81
|
+
destination TestArrayDestination, rows
|
82
|
+
end
|
83
|
+
Kiba.run(job)
|
84
|
+
assert_equal([
|
85
|
+
{mandatory: "some value"}
|
86
|
+
], rows)
|
87
|
+
end
|
88
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kiba-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibaut Barrère
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kiba
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.0.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '5'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 3.0.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '5'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: rake
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: amazing_print
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
@@ -86,6 +86,20 @@ dependencies:
|
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: standard
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
89
103
|
description: Commonly used helpers for Kiba ETL
|
90
104
|
email:
|
91
105
|
- thibaut.barrere@gmail.com
|
@@ -93,8 +107,9 @@ executables: []
|
|
93
107
|
extensions: []
|
94
108
|
extra_rdoc_files: []
|
95
109
|
files:
|
110
|
+
- ".github/FUNDING.yml"
|
111
|
+
- ".github/workflows/ci.yml"
|
96
112
|
- ".gitignore"
|
97
|
-
- ".travis.yml"
|
98
113
|
- Changes.md
|
99
114
|
- Gemfile
|
100
115
|
- LICENSE
|
@@ -102,26 +117,34 @@ files:
|
|
102
117
|
- Rakefile
|
103
118
|
- kiba-common.gemspec
|
104
119
|
- lib/kiba-common/destinations/csv.rb
|
120
|
+
- lib/kiba-common/destinations/lambda.rb
|
105
121
|
- lib/kiba-common/dsl_extensions/logger.rb
|
106
122
|
- lib/kiba-common/dsl_extensions/show_me.rb
|
123
|
+
- lib/kiba-common/sources/csv.rb
|
107
124
|
- lib/kiba-common/sources/enumerable.rb
|
108
125
|
- lib/kiba-common/transforms/enumerable_exploder.rb
|
109
|
-
- lib/kiba-common/transforms/source_transform_adapter.rb
|
110
126
|
- lib/kiba-common/version.rb
|
111
127
|
- test/helper.rb
|
112
128
|
- test/support/assert_called.rb
|
113
129
|
- test/support/test_array_destination.rb
|
130
|
+
- test/support/test_hash_configured_object.rb
|
131
|
+
- test/support/test_keyword_proxy_source.rb
|
114
132
|
- test/test_csv_destination.rb
|
133
|
+
- test/test_csv_source.rb
|
115
134
|
- test/test_enumerable_exploder_transform.rb
|
116
135
|
- test/test_enumerable_source.rb
|
136
|
+
- test/test_integration.rb
|
137
|
+
- test/test_lambda_destination.rb
|
117
138
|
- test/test_logger.rb
|
118
139
|
- test/test_show_me.rb
|
119
140
|
- test/test_source_transform_adapter.rb
|
120
141
|
homepage: https://github.com/thbar/kiba-common
|
121
142
|
licenses:
|
122
143
|
- LGPL-3.0
|
123
|
-
metadata:
|
124
|
-
|
144
|
+
metadata:
|
145
|
+
source_code_uri: https://github.com/thbar/kiba-common
|
146
|
+
documentation_uri: https://github.com/thbar/kiba-common/blob/master/README.md
|
147
|
+
post_install_message:
|
125
148
|
rdoc_options: []
|
126
149
|
require_paths:
|
127
150
|
- lib
|
@@ -136,18 +159,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
159
|
- !ruby/object:Gem::Version
|
137
160
|
version: '0'
|
138
161
|
requirements: []
|
139
|
-
|
140
|
-
|
141
|
-
signing_key:
|
162
|
+
rubygems_version: 3.2.3
|
163
|
+
signing_key:
|
142
164
|
specification_version: 4
|
143
165
|
summary: Commonly used helpers for Kiba ETL
|
144
166
|
test_files:
|
145
167
|
- test/helper.rb
|
146
168
|
- test/support/assert_called.rb
|
147
169
|
- test/support/test_array_destination.rb
|
170
|
+
- test/support/test_hash_configured_object.rb
|
171
|
+
- test/support/test_keyword_proxy_source.rb
|
148
172
|
- test/test_csv_destination.rb
|
173
|
+
- test/test_csv_source.rb
|
149
174
|
- test/test_enumerable_exploder_transform.rb
|
150
175
|
- test/test_enumerable_source.rb
|
176
|
+
- test/test_integration.rb
|
177
|
+
- test/test_lambda_destination.rb
|
151
178
|
- test/test_logger.rb
|
152
179
|
- test/test_show_me.rb
|
153
180
|
- test/test_source_transform_adapter.rb
|
data/.travis.yml
DELETED