dorian 2.0.1 → 2.1.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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/dorian/bin.rb +163 -36
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f442cb1d0f47b1eed61e28ae03731f5c6992e61bf074dbaa3f8b54d185dad8d7
4
- data.tar.gz: 877156a017e90bdc05a57b03f072467a9ab97d4ad4880d4be4fd6ef0e6ee5948
3
+ metadata.gz: 926123b36e9d821e68bec3a83818a70f7a39f6f52c1fa5d19ac777dc98b64da0
4
+ data.tar.gz: ae5fda1a6fb16ae0ae1d3fd61a329608586329fde537e4c4430513f0d2e1eb25
5
5
  SHA512:
6
- metadata.gz: b1676c471187b363b7ed432d331d7b3ce5b20992e7f57712088bc79a182db567a140fdc2edd5af8be674031e82862b1bedd514a19434f7d81630b1b2cbb771a6
7
- data.tar.gz: c2569fa773cc0fd88871ca875a6a1fa304c06e746cecd403e591b7dbcb3e19f2e3a6e3877cd19b8071c9b0966219b03306bdd6d5f4850b57f0acffc859b40fe2
6
+ metadata.gz: 5c9bbdc2e3951bd84159719b1292dce233c4092937cdb18054301e438517030bf4bf3b2352a89ec1cb705751130f8f374b1bc40b7496951be21b7744be36cf5c
7
+ data.tar.gz: 1e9210a0bf87c799539ac9ce4c39dd774c4483facdd326718c31bb3655a895a08b1aae273e80eb87a0f32ad6aa46491bbe73a4a2ec5645102ee4c59665019f50
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.1
1
+ 2.1.0
data/lib/dorian/bin.rb CHANGED
@@ -6,8 +6,8 @@ require "dorian/eval"
6
6
  require "dorian/progress"
7
7
  require "dorian/to_struct"
8
8
  require "json"
9
- require "yaml"
10
9
  require "parallel"
10
+ require "yaml"
11
11
 
12
12
  class Dorian
13
13
  class Bin
@@ -21,10 +21,12 @@ class Dorian
21
21
  "jsonl" => :jsonl,
22
22
  "raw" => :raw,
23
23
  "yaml" => :yaml,
24
- "yml" => :yaml
24
+ "yml" => :yaml,
25
+ "yamll" => :yamll,
26
+ "ymll" => :yamll
25
27
  }.freeze
26
28
 
27
- attr_reader :parsed, :command, :arguments
29
+ attr_reader :parsed, :command, :arguments, :ruby
28
30
 
29
31
  def initialize
30
32
  @parsed =
@@ -47,6 +49,15 @@ class Dorian
47
49
  parallel: {
48
50
  alias: :p
49
51
  },
52
+ parallel_type: {
53
+ alias: :pt,
54
+ type: :string,
55
+ default: :processes
56
+ },
57
+ n: {
58
+ type: :integer,
59
+ default: 100
60
+ },
50
61
  rails: {
51
62
  alias: :r
52
63
  },
@@ -73,7 +84,8 @@ class Dorian
73
84
  progress: :boolean,
74
85
  headers: :boolean,
75
86
  progress_format: {
76
- alias: :pf
87
+ alias: :pf,
88
+ type: :string
77
89
  },
78
90
  pretty: {
79
91
  default: true
@@ -87,7 +99,9 @@ class Dorian
87
99
  }
88
100
  )
89
101
 
90
- @command, *@arguments = parsed.arguments
102
+ @arguments = parsed.arguments
103
+ @command = arguments.first
104
+ @ruby = nil
91
105
  end
92
106
 
93
107
  def self.run(...)
@@ -99,12 +113,22 @@ class Dorian
99
113
  abort VERSION if version?
100
114
 
101
115
  case command&.to_sym
102
- when :read, nil
103
- command_read
104
116
  when :each
117
+ arguments.delete("each")
118
+ @command = :each
119
+ @ruby = arguments.join(" ")
120
+ @arguments = []
105
121
  command_each
122
+ when :all
123
+ arguments.delete("all")
124
+ @command = :all
125
+ @ruby = arguments.join(" ")
126
+ @arguments = []
127
+ command_all
106
128
  else
107
- abort "#{command} not supported"
129
+ arguments.delete("read")
130
+ @command = :read
131
+ command_read
108
132
  end
109
133
  end
110
134
 
@@ -117,17 +141,27 @@ class Dorian
117
141
  outputs(reads(File.read(input)), file: input)
118
142
  end
119
143
 
120
- each(stdin_arguments) { |input| outputs(reads(input)) }
144
+ each(stdin_arguments + arguments) { |input| outputs(reads(input)) }
145
+ end
146
+
147
+ def everything
148
+ read_stdin_files + read_files + stdin_arguments + arguments
121
149
  end
122
150
 
123
151
  def command_each
124
- each(read_stdin_files + read_files + stdin_arguments) do |input|
125
- each(lines(reads(input))) do |line|
126
- evaluates(arguments.join(" "), it: line)
152
+ each(everything) do |input|
153
+ each(lines(reads(input)), progress: true) do |line|
154
+ evaluates(ruby, it: line)
127
155
  end
128
156
  end
129
157
  end
130
158
 
159
+ def command_all
160
+ each(everything, progress: true) do |input|
161
+ evaluates(ruby, it: reads(input))
162
+ end
163
+ end
164
+
131
165
  def outputs(content, file: nil)
132
166
  if write? && file
133
167
  File.write(file, to_output(content))
@@ -141,25 +175,22 @@ class Dorian
141
175
 
142
176
  case output
143
177
  when :csv
144
- CSV.generate(headers: headers_of(content)) do |csv|
145
- csv << headers_of(content) if headers_of(content)
146
-
147
- each(content) { |row| csv << row }
148
- end
178
+ (headers_of(content) ? headers_of(content).to_csv : "") +
179
+ map(content) do |element|
180
+ CSV.generate(headers: headers_of(content)) do |csv|
181
+ csv << wrap(element)
182
+ end
183
+ end.join
149
184
  when :json
150
185
  pretty? ? JSON.pretty_generate(content) : content.to_json
151
- when :jsonl
186
+ when :jsonl, :yamll
152
187
  map(content, &:to_json).join("\n")
153
188
  when :raw
154
189
  content
155
- when :ruby
156
- content.inspect
157
- when :rubyl
158
- map(content, &:inspect).join("\n")
159
190
  when :yaml
160
191
  content.to_yaml
161
192
  else
162
- abort "#{output} not supported"
193
+ abort "#{output.inspect} not supported"
163
194
  end
164
195
  end
165
196
 
@@ -173,15 +204,19 @@ class Dorian
173
204
  end
174
205
  when :json
175
206
  JSON.parse(content).to_deep_struct
176
- when :jsonl
207
+ when :jsonl, :yamll
177
208
  map(content.lines) { |line| JSON.parse(line) }.to_deep_struct
178
209
  when :raw
179
210
  content
180
211
  when :yaml
181
- YAML.safe_load(content)
212
+ YAML.safe_load(content).to_deep_struct
182
213
  else
183
- abort "#{input} not supported"
214
+ abort "#{input.inspect} not supported"
184
215
  end
216
+ rescue JSON::ParserError => e
217
+ abort "invalid json: #{e.message}"
218
+ rescue Psych::SyntaxError => e
219
+ abort "invalid yaml: #{e.message}"
185
220
  end
186
221
 
187
222
  def pretty?
@@ -190,13 +225,15 @@ class Dorian
190
225
 
191
226
  def read_stdin
192
227
  @read_stdin ||= $stdin.each_line.to_a
228
+ rescue Interrupt
229
+ abort "interupt in read_stdin"
193
230
  end
194
231
 
195
232
  def stdin_files
196
- return [] if files.any?
197
- return [] unless stdin == :files
233
+ return [] if files.any? || arguments.any?
234
+ return [] if stdin != :files
198
235
 
199
- read_stdin.map(&:rstrip)
236
+ map(read_stdin, &:rstrip)
200
237
  end
201
238
 
202
239
  def read_stdin_files
@@ -208,7 +245,7 @@ class Dorian
208
245
  end
209
246
 
210
247
  def stdin_arguments
211
- return [] if files.any?
248
+ return [] if files.any? || arguments.any?
212
249
  return [] if stdin == :files
213
250
 
214
251
  [read_stdin.join]
@@ -218,6 +255,10 @@ class Dorian
218
255
  options.stdin.to_sym
219
256
  end
220
257
 
258
+ def deep?
259
+ !!options.deep
260
+ end
261
+
221
262
  def options
222
263
  parsed.options
223
264
  end
@@ -294,26 +335,110 @@ class Dorian
294
335
  parsed.help
295
336
  end
296
337
 
338
+ def n
339
+ options.n
340
+ end
341
+
342
+ def parallel_type
343
+ options.parallel_type&.to_sym
344
+ end
345
+
297
346
  def headers_of(content)
298
- return unless headers?
299
347
  return unless content.respond_to?(:first)
300
348
  return unless content.first
301
349
  return unless content.first.respond_to?(:to_h)
302
350
  return unless content.first.to_h.keys.any?
303
351
 
304
352
  content.first.to_h.keys
353
+ rescue TypeError
354
+ nil
355
+ end
356
+
357
+ def parallel_options
358
+ if parallel_type == :processes
359
+ { in_processes: n }
360
+ elsif parallel_type == :threads
361
+ { in_threads: n }
362
+ else
363
+ abort "#{parallel_type.inspect} not supported"
364
+ end
305
365
  end
306
366
 
307
- def each(collection, &)
308
- parallel? ? Parallel.each(collection, &) : collection.each(&)
367
+ def each(collection, options: parallel_options, progress: false, &)
368
+ collection = wrap(collection)
369
+ progress_bar = progress ? create_progress_bar(collection.size) : nil
370
+
371
+ if parallel?
372
+ Parallel.each(
373
+ collection,
374
+ **options,
375
+ finish: ->(*) { progress_bar&.increment },
376
+ &
377
+ )
378
+ else
379
+ collection.each do |element|
380
+ yield(element).tap { progress_bar&.increment }
381
+ end
382
+ end
309
383
  end
310
384
 
311
- def map(collection, &)
312
- parallel? ? Parallel.map(collection, &) : collection.map(&)
385
+ def map(collection, options: parallel_options, progress: false, &)
386
+ collection = wrap(collection)
387
+ progress_bar = progress ? create_progress_bar(collection.size) : nil
388
+
389
+ if parallel?
390
+ Parallel.map(
391
+ collection,
392
+ **options,
393
+ finish: ->(*) { progress_bar&.increment },
394
+ &
395
+ )
396
+ else
397
+ collection.map do |element|
398
+ yield(element).tap { progress_bar&.increment }
399
+ end
400
+ end
313
401
  end
314
402
 
315
403
  def lines(input)
316
- input.is_a?(String) ? input.lines.map(&:rstrip) : Array(input)
404
+ if input.is_a?(String)
405
+ input.lines.map(&:rstrip)
406
+ elsif deep?
407
+ deep_lines(input)
408
+ else
409
+ Array(input)
410
+ end
411
+ end
412
+
413
+ def deep_lines(input)
414
+ case input
415
+ when Array
416
+ [input.to_deep_struct] +
417
+ input.flat_map { |element| deep_lines(element) }
418
+ when Hash
419
+ [input.to_deep_struct] +
420
+ input.flat_map { |key, value| deep_lines([key, value]) }
421
+ when Struct
422
+ deep_lines(input.from_deep_struct).to_deep_struct
423
+ else
424
+ [input.to_deep_struct]
425
+ end
426
+ end
427
+
428
+ def wrap(ruby)
429
+ if ruby.is_a?(Hash)
430
+ ruby
431
+ elsif ruby.respond_to?(:to_a)
432
+ ruby.to_a
433
+ else
434
+ Array(ruby)
435
+ end
436
+ end
437
+
438
+ def create_progress_bar(total)
439
+ return unless progress?
440
+
441
+ Dorian::Progress.create(total:, format: progress_format)
317
442
  end
318
443
 
319
444
  def evaluates(
@@ -324,6 +449,7 @@ class Dorian
324
449
  stderr: stderr?,
325
450
  colorize: colorize?,
326
451
  rails: rails?,
452
+ fast: fast?,
327
453
  returns: false
328
454
  )
329
455
  Dorian::Eval.eval(
@@ -334,6 +460,7 @@ class Dorian
334
460
  stderr:,
335
461
  colorize:,
336
462
  rails:,
463
+ fast:,
337
464
  returns:
338
465
  )
339
466
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dorian
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-31 00:00:00.000000000 Z
11
+ date: 2024-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: csv